Module Name:    src
Committed By:   bouyer
Date:           Mon Apr 13 22:54:12 UTC 2020

Modified Files:
        src/sys/arch/x86/include: cpu.h
        src/sys/arch/xen/include: evtchn.h
        src/sys/arch/xen/x86: xen_intr.c xen_ipi.c
        src/sys/arch/xen/xen: clock.c evtchn.c

Log Message:
By default, events are bound to CPU 0 (exept for IPIs and VTIMERs which
are bound to a different CPU at creation time).
Recent MI changes caused the scheduler to choose a different CPU when
probing and attaching xennet devices (I guess it's the xenbus thread which
runs on a different CPU). This cause the callback to be called on a different
CPU than the one expected by the kernel, and the event is ignored.
It is handled when the clock causes the callback to be called on the right
CPU, which is why xennet still run, but slowly.

Change event_set_handler() to do a EVTCHNOP_bind_vcpu if requested to,
and make sure we don't do it for IPIs and VIRQs (for theses, the op fails).


To generate a diff of this commit:
cvs rdiff -u -r1.119 -r1.120 src/sys/arch/x86/include/cpu.h
cvs rdiff -u -r1.28 -r1.29 src/sys/arch/xen/include/evtchn.h
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/xen/x86/xen_intr.c
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/xen/x86/xen_ipi.c
cvs rdiff -u -r1.80 -r1.81 src/sys/arch/xen/xen/clock.c
cvs rdiff -u -r1.88 -r1.89 src/sys/arch/xen/xen/evtchn.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/include/cpu.h
diff -u src/sys/arch/x86/include/cpu.h:1.119 src/sys/arch/x86/include/cpu.h:1.120
--- src/sys/arch/x86/include/cpu.h:1.119	Fri Apr 10 14:35:26 2020
+++ src/sys/arch/x86/include/cpu.h	Mon Apr 13 22:54:11 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.119 2020/04/10 14:35:26 bouyer Exp $	*/
+/*	$NetBSD: cpu.h,v 1.120 2020/04/13 22:54:11 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1990 The Regents of the University of California.
@@ -307,9 +307,6 @@ struct cpu_info {
 	 */
 	uint64_t	ci_xen_systime_ns_skew;
 
-	/* Xen periodic timer interrupt handle.  */
-	struct intrhand	*ci_xen_timer_intrhand;
-
 	/*
 	 * Clockframe for timer interrupt handler.
 	 * Saved at entry via event callback.

Index: src/sys/arch/xen/include/evtchn.h
diff -u src/sys/arch/xen/include/evtchn.h:1.28 src/sys/arch/xen/include/evtchn.h:1.29
--- src/sys/arch/xen/include/evtchn.h:1.28	Mon Apr  6 19:26:00 2020
+++ src/sys/arch/xen/include/evtchn.h	Mon Apr 13 22:54:12 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: evtchn.h,v 1.28 2020/04/06 19:26:00 jdolecek Exp $	*/
+/*	$NetBSD: evtchn.h,v 1.29 2020/04/13 22:54:12 bouyer Exp $	*/
 
 /*
  *
@@ -42,7 +42,7 @@ unsigned int evtchn_do_event(int, struct
 void call_evtchn_do_event(int, struct intrframe *);
 void call_xenevt_event(int);
 int event_set_handler(int, int (*func)(void *), void *, int, const char *,
-    const char *, bool);
+    const char *, bool, bool);
 int event_remove_handler(int, int (*func)(void *), void *);
 
 struct cpu_info;

Index: src/sys/arch/xen/x86/xen_intr.c
diff -u src/sys/arch/xen/x86/xen_intr.c:1.21 src/sys/arch/xen/x86/xen_intr.c:1.22
--- src/sys/arch/xen/x86/xen_intr.c:1.21	Mon Apr  6 19:26:00 2020
+++ src/sys/arch/xen/x86/xen_intr.c	Mon Apr 13 22:54:12 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: xen_intr.c,v 1.21 2020/04/06 19:26:00 jdolecek Exp $	*/
+/*	$NetBSD: xen_intr.c,v 1.22 2020/04/13 22:54:12 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xen_intr.c,v 1.21 2020/04/06 19:26:00 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_intr.c,v 1.22 2020/04/13 22:54:12 bouyer Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -170,7 +170,7 @@ xen_intr_establish_xname(int legacy_irq,
 		    sizeof(intrstr_buf));
 
 		event_set_handler(pin, handler, arg, level, intrstr, xname,
-		    known_mpsafe);
+		    known_mpsafe, true);
 
 		rih = kmem_zalloc(sizeof(*rih), cold ? KM_NOSLEEP : KM_SLEEP);
 		if (rih == NULL) {

Index: src/sys/arch/xen/x86/xen_ipi.c
diff -u src/sys/arch/xen/x86/xen_ipi.c:1.35 src/sys/arch/xen/x86/xen_ipi.c:1.36
--- src/sys/arch/xen/x86/xen_ipi.c:1.35	Sun Dec  1 15:34:46 2019
+++ src/sys/arch/xen/x86/xen_ipi.c	Mon Apr 13 22:54:12 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: xen_ipi.c,v 1.35 2019/12/01 15:34:46 ad Exp $ */
+/* $NetBSD: xen_ipi.c,v 1.36 2020/04/13 22:54:12 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2011, 2019 The NetBSD Foundation, Inc.
@@ -33,10 +33,10 @@
 
 /* 
  * Based on: x86/ipi.c
- * __KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.35 2019/12/01 15:34:46 ad Exp $");
+ * __KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.36 2020/04/13 22:54:12 bouyer Exp $");
  */
 
-__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.35 2019/12/01 15:34:46 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.36 2020/04/13 22:54:12 bouyer Exp $");
 
 #include "opt_ddb.h"
 
@@ -98,6 +98,8 @@ xen_ipi_handler(void *arg)
 
 	ci = curcpu();
 	regs = arg;
+
+	KASSERT(ci == arg);
 	
 	pending = atomic_swap_32(&ci->ci_ipis, 0);
 
@@ -139,8 +141,8 @@ xen_ipi_init(void)
 	snprintf(intr_xname, sizeof(intr_xname), "%s ipi",
 	    device_xname(ci->ci_dev));
 
-	if (xen_intr_establish_xname(-1, &xen_pic, evtchn, IST_LEVEL, IPL_HIGH,
-		xen_ipi_handler, ci, true, intr_xname) == NULL) {
+	if (event_set_handler(evtchn, xen_ipi_handler, ci, IPL_HIGH, NULL,
+	    intr_xname, true, false) != 0) {
 		panic("%s: unable to register ipi handler\n", __func__);
 		/* NOTREACHED */
 	}
@@ -314,7 +316,6 @@ xen_ipi_generic(struct cpu_info *ci, str
 {
 	KASSERT(ci != NULL);
 	KASSERT(intrf != NULL);
-
 	ipi_cpu_handler();
 }
 

Index: src/sys/arch/xen/xen/clock.c
diff -u src/sys/arch/xen/xen/clock.c:1.80 src/sys/arch/xen/xen/clock.c:1.81
--- src/sys/arch/xen/xen/clock.c:1.80	Wed Oct 16 18:29:49 2019
+++ src/sys/arch/xen/xen/clock.c	Mon Apr 13 22:54:12 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: clock.c,v 1.80 2019/10/16 18:29:49 christos Exp $	*/
+/*	$NetBSD: clock.c,v 1.81 2020/04/13 22:54:12 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2017, 2018 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.80 2019/10/16 18:29:49 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.81 2020/04/13 22:54:12 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -722,14 +722,13 @@ xen_suspendclocks(struct cpu_info *ci)
 
 	KASSERT(ci == curcpu());
 	KASSERT(kpreempt_disabled());
-	KASSERT(ci->ci_xen_timer_intrhand != NULL);
 
 	evtch = unbind_virq_from_evtch(VIRQ_TIMER);
 	KASSERT(evtch != -1);
 
 	hypervisor_mask_event(evtch);
-	xen_intr_disestablish(ci->ci_xen_timer_intrhand);
-	ci->ci_xen_timer_intrhand = NULL;
+	event_remove_handler(evtch, 
+	    __FPTRCAST(int (*)(void *), xen_timer_handler), ci);
 
 	aprint_verbose("Xen clock: removed event channel %d\n", evtch);
 
@@ -755,7 +754,6 @@ xen_resumeclocks(struct cpu_info *ci)
 
 	KASSERT(ci == curcpu());
 	KASSERT(kpreempt_disabled());
-	KASSERT(ci->ci_xen_timer_intrhand == NULL);
 
 	evtch = bind_virq_to_evtch(VIRQ_TIMER);
 	KASSERT(evtch != -1);
@@ -763,11 +761,9 @@ xen_resumeclocks(struct cpu_info *ci)
 	snprintf(intr_xname, sizeof(intr_xname), "%s clock",
 	    device_xname(ci->ci_dev));
 	/* XXX sketchy function pointer cast -- fix the API, please */
-	ci->ci_xen_timer_intrhand = xen_intr_establish_xname(-1, &xen_pic,
-	    evtch, IST_LEVEL, IPL_CLOCK,
+	if (event_set_handler(evtch,
 	    __FPTRCAST(int (*)(void *), xen_timer_handler),
-	    ci, true, intr_xname);
-	if (ci->ci_xen_timer_intrhand == NULL)
+	    ci, IPL_CLOCK, NULL, intr_xname, true, false) != 0)
 		panic("failed to establish timer interrupt handler");
 
 	hypervisor_unmask_event(evtch);

Index: src/sys/arch/xen/xen/evtchn.c
diff -u src/sys/arch/xen/xen/evtchn.c:1.88 src/sys/arch/xen/xen/evtchn.c:1.89
--- src/sys/arch/xen/xen/evtchn.c:1.88	Mon Apr  6 19:26:00 2020
+++ src/sys/arch/xen/xen/evtchn.c	Mon Apr 13 22:54:12 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: evtchn.c,v 1.88 2020/04/06 19:26:00 jdolecek Exp $	*/
+/*	$NetBSD: evtchn.c,v 1.89 2020/04/13 22:54:12 bouyer Exp $	*/
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -54,7 +54,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.88 2020/04/06 19:26:00 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.89 2020/04/13 22:54:12 bouyer Exp $");
 
 #include "opt_xen.h"
 #include "isa.h"
@@ -764,7 +764,7 @@ pirq_establish(int pirq, int evtch, int 
 	ih->arg = arg;
 
 	if (event_set_handler(evtch, pirq_interrupt, ih, level, intrname,
-	    xname, known_mpsafe) != 0) {
+	    xname, known_mpsafe, true) != 0) {
 		kmem_free(ih, sizeof(struct pintrhand));
 		return NULL;
 	}
@@ -834,12 +834,13 @@ intr_calculatemasks(struct evtsource *ev
 
 int
 event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
-    const char *intrname, const char *xname, bool mpsafe)
+    const char *intrname, const char *xname, bool mpsafe, bool bind)
 {
 	struct cpu_info *ci = curcpu(); /* XXX: pass in ci ? */
 	struct evtsource *evts;
 	struct intrhand *ih, **ihp;
 	int s;
+	char intrstr_buf[INTRIDBUF];
 
 #ifdef IRQ_DEBUG
 	printf("event_set_handler IRQ %d handler %p\n", evtch, func);
@@ -848,7 +849,7 @@ event_set_handler(int evtch, int (*func)
 	KASSERTMSG(evtch >= 0, "negative evtch: %d", evtch);
 	KASSERTMSG(evtch < NR_EVENT_CHANNELS,
 	    "evtch number %d > NR_EVENT_CHANNELS", evtch);
-	KASSERT(intrname != NULL && xname != NULL);
+	KASSERT(xname != NULL);
 
 #if 0
 	printf("event_set_handler evtch %d handler %p level %d\n", evtch,
@@ -879,6 +880,10 @@ event_set_handler(int evtch, int (*func)
 
 	/* register handler for event channel */
 	if (evtsource[evtch] == NULL) {
+		evtchn_op_t op;
+		if (intrname == NULL)
+			intrname = intr_create_intrid(-1, &xen_pic, evtch,
+			    intrstr_buf, sizeof(intrstr_buf));
 		evts = kmem_zalloc(sizeof (struct evtsource),
 		    KM_NOSLEEP);
 		if (evts == NULL)
@@ -898,6 +903,15 @@ event_set_handler(int evtch, int (*func)
 
 		evcnt_attach_dynamic(&evts->ev_evcnt, EVCNT_TYPE_INTR, NULL,
 		    device_xname(ci->ci_dev), evts->ev_intrname);
+		if (bind) {
+			op.cmd = EVTCHNOP_bind_vcpu;
+			op.u.bind_vcpu.port = evtch;
+			op.u.bind_vcpu.vcpu = ci->ci_cpuid;
+			if (HYPERVISOR_event_channel_op(&op) != 0) {
+				panic("Failed to bind event %d to "
+				    "VCPU %"PRIuCPUID, evtch, ci->ci_cpuid);
+			}
+		}
 	} else {
 		evts = evtsource[evtch];
 		/* sort by IPL order, higher first */

Reply via email to