Module Name:    src
Committed By:   bouyer
Date:           Thu May  7 19:48:58 UTC 2020

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

Log Message:
Change event_set_handler() to take the target CPU parameter. If ci is NULL,
  event_set_handler() will choose the CPU and bind the event.
  If ci is not NULL the caller is responsible for binding the event.
Use a IPI xcall to register the handlers if needed.
pull in a hack from x86 to force pirq handlers to be mpsafe if registered at
a level != IPL_VM. This is for the com at isa interrupt handler, which
registers at IPL_HIGH and has to way to tell it's mpsafe (taking
KERNEL_LOCK at IPL_HIGH causes deadlocks on MP systems).


To generate a diff of this commit:
cvs rdiff -u -r1.31 -r1.32 src/sys/arch/xen/include/evtchn.h
cvs rdiff -u -r1.26 -r1.27 src/sys/arch/xen/x86/xen_intr.c
cvs rdiff -u -r1.38 -r1.39 src/sys/arch/xen/x86/xen_ipi.c
cvs rdiff -u -r1.93 -r1.94 src/sys/arch/xen/xen/evtchn.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/xen/xen/xen_clock.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/xen/include/evtchn.h
diff -u src/sys/arch/xen/include/evtchn.h:1.31 src/sys/arch/xen/include/evtchn.h:1.32
--- src/sys/arch/xen/include/evtchn.h:1.31	Mon May  4 15:55:56 2020
+++ src/sys/arch/xen/include/evtchn.h	Thu May  7 19:48:58 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: evtchn.h,v 1.31 2020/05/04 15:55:56 jdolecek Exp $	*/
+/*	$NetBSD: evtchn.h,v 1.32 2020/05/07 19:48:58 bouyer Exp $	*/
 
 /*
  *
@@ -40,12 +40,11 @@ unsigned int evtchn_do_event(int, struct
 void call_evtchn_do_event(int, struct intrframe *);
 void call_xenevt_event(int);
 struct intrhand *event_set_handler(int, int (*func)(void *), void *,
-    int, const char *, const char *, bool, bool);
+    int, const char *, const char *, bool, struct cpu_info *);
 int event_remove_handler(int, int (*func)(void *), void *);
 
 struct cpu_info;
 struct intrhand;
-void event_set_iplhandler(struct cpu_info *, struct intrhand *, int);
 
 extern int debug_port;
 extern int xen_debug_handler(void *);

Index: src/sys/arch/xen/x86/xen_intr.c
diff -u src/sys/arch/xen/x86/xen_intr.c:1.26 src/sys/arch/xen/x86/xen_intr.c:1.27
--- src/sys/arch/xen/x86/xen_intr.c:1.26	Tue May  5 17:02:01 2020
+++ src/sys/arch/xen/x86/xen_intr.c	Thu May  7 19:48:58 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: xen_intr.c,v 1.26 2020/05/05 17:02:01 bouyer Exp $	*/
+/*	$NetBSD: xen_intr.c,v 1.27 2020/05/07 19:48:58 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.26 2020/05/05 17:02:01 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_intr.c,v 1.27 2020/05/07 19:48:58 bouyer Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -143,7 +143,7 @@ xen_intr_establish_xname(int legacy_irq,
 		    sizeof(intrstr_buf));
 
 		rih = event_set_handler(pin, handler, arg, level,
-		    intrstr, xname, known_mpsafe, true);
+		    intrstr, xname, known_mpsafe, NULL);
 
 		if (rih == NULL) {
 			printf("%s: can't establish interrupt\n", __func__);
@@ -157,6 +157,8 @@ xen_intr_establish_xname(int legacy_irq,
 	struct pintrhand *pih;
 	int gsi;
 	int evtchn;
+	/* the hack below is from x86's intr_establish_xname() */
+	bool mpsafe = (known_mpsafe || level != IPL_VM);
 
 	KASSERTMSG(legacy_irq == -1 || (0 <= legacy_irq && legacy_irq < NUM_XEN_IRQS),
 	    "bad legacy IRQ value: %d", legacy_irq);
@@ -190,7 +192,7 @@ xen_intr_establish_xname(int legacy_irq,
 	}
 
 	pih = pirq_establish(gsi, evtchn, handler, arg, level,
-			     intrstr, xname, known_mpsafe);
+			     intrstr, xname, mpsafe);
 	pih->pic = pic;
 	return pih;
 #endif /* NPCI > 0 || NISA > 0 */

Index: src/sys/arch/xen/x86/xen_ipi.c
diff -u src/sys/arch/xen/x86/xen_ipi.c:1.38 src/sys/arch/xen/x86/xen_ipi.c:1.39
--- src/sys/arch/xen/x86/xen_ipi.c:1.38	Sat Apr 25 15:26:17 2020
+++ src/sys/arch/xen/x86/xen_ipi.c	Thu May  7 19:48:58 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: xen_ipi.c,v 1.38 2020/04/25 15:26:17 bouyer Exp $ */
+/* $NetBSD: xen_ipi.c,v 1.39 2020/05/07 19:48:58 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2011, 2019 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  * Based on: x86/ipi.c
  */
 
-__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.38 2020/04/25 15:26:17 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.39 2020/05/07 19:48:58 bouyer Exp $");
 
 #include "opt_ddb.h"
 
@@ -143,7 +143,7 @@ xen_ipi_init(void)
 	    device_xname(ci->ci_dev));
 
 	if (event_set_handler(evtchn, xen_ipi_handler, ci, IPL_HIGH, NULL,
-	    intr_xname, true, false) == NULL) {
+	    intr_xname, true, ci) == NULL) {
 		panic("%s: unable to register ipi handler\n", __func__);
 		/* NOTREACHED */
 	}

Index: src/sys/arch/xen/xen/evtchn.c
diff -u src/sys/arch/xen/xen/evtchn.c:1.93 src/sys/arch/xen/xen/evtchn.c:1.94
--- src/sys/arch/xen/xen/evtchn.c:1.93	Wed May  6 13:43:48 2020
+++ src/sys/arch/xen/xen/evtchn.c	Thu May  7 19:48:57 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: evtchn.c,v 1.93 2020/05/06 13:43:48 bouyer Exp $	*/
+/*	$NetBSD: evtchn.c,v 1.94 2020/05/07 19:48:57 bouyer Exp $	*/
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -54,7 +54,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.93 2020/05/06 13:43:48 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.94 2020/05/07 19:48:57 bouyer Exp $");
 
 #include "opt_xen.h"
 #include "isa.h"
@@ -722,7 +722,7 @@ pirq_establish(int pirq, int evtch, int 
 	ih->arg = arg;
 
 	if (event_set_handler(evtch, pirq_interrupt, ih, level, intrname,
-	    xname, known_mpsafe, true) == NULL) {
+	    xname, known_mpsafe, NULL) == NULL) {
 		kmem_free(ih, sizeof(struct pintrhand));
 		return NULL;
 	}
@@ -784,14 +784,81 @@ intr_calculatemasks(struct evtsource *ev
 		xen_atomic_clear_bit(&curcpu()->ci_evtmask[0], evtch);
 }
 
+
+struct event_set_handler_args {
+	struct intrhand *ih;
+	struct intrsource *ipls;
+	struct evtsource *evts;
+	int evtch;
+};
+
+/*
+ * Called on bound CPU to handle event_set_handler()
+ * caller (on initiating CPU) holds cpu_lock on our behalf
+ * arg1: struct event_set_handler_args *
+ * arg2: NULL
+ */
+
+static void
+event_set_handler_xcall(void *arg1, void *arg2)
+{
+	struct event_set_handler_args *esh_args = arg1;
+	struct intrhand **ihp, *ih = esh_args->ih;
+	struct evtsource *evts = esh_args->evts;
+
+	const u_long psl = x86_read_psl();
+	x86_disable_intr();
+	/* sort by IPL order, higher first */
+	for (ihp = &evts->ev_handlers; *ihp != NULL;
+	    ihp = &((*ihp)->ih_evt_next)) {
+		if ((*ihp)->ih_level < ih->ih_level)
+			break;
+	}
+	/* insert before *ihp */
+	ih->ih_evt_next = *ihp;
+	*ihp = ih;
+#ifndef XENPV
+	evts->ev_isl->is_handlers = evts->ev_handlers;
+#endif
+	/* register per-cpu handler for spllower() */
+	struct cpu_info *ci = ih->ih_cpu;
+	int sir = XEN_IPL2SIR(ih->ih_level);
+	KASSERT(sir >= SIR_XENIPL_VM && sir <= SIR_XENIPL_HIGH);
+
+	KASSERT(ci == curcpu());
+	if (ci->ci_isources[sir] == NULL) {
+		KASSERT(esh_args->ipls != NULL);
+		ci->ci_isources[sir] = esh_args->ipls;
+	}
+	struct intrsource *ipls = ci->ci_isources[sir];
+	ih->ih_next = ipls->is_handlers;
+	ipls->is_handlers = ih;
+	x86_intr_calculatemasks(ci);
+
+	intr_calculatemasks(evts, esh_args->evtch, ci);
+	x86_write_psl(psl);
+}
+
 struct intrhand *
 event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
-    const char *intrname, const char *xname, bool mpsafe, bool bind)
+    const char *intrname, const char *xname, bool mpsafe, struct cpu_info *ci)
 {
-	struct cpu_info *ci = curcpu(); /* XXX: pass in ci ? */
-	struct evtsource *evts;
-	struct intrhand *ih, **ihp;
+	struct event_set_handler_args esh_args;
 	char intrstr_buf[INTRIDBUF];
+	bool bind = false;
+
+	memset(&esh_args, 0, sizeof(esh_args));
+
+	/*
+	 * if ci is not specified, we bind to the current cpu.
+	 * if ci has been proviced by the called, we assume 
+	 * he will do the EVTCHNOP_bind_vcpu if needed.
+	 */
+	if (ci == NULL) {
+		ci = curcpu();
+		bind = true;
+	}
+		
 
 #ifdef IRQ_DEBUG
 	printf("event_set_handler IRQ %d handler %p\n", evtch, func);
@@ -806,29 +873,47 @@ event_set_handler(int evtch, int (*func)
 	printf("event_set_handler evtch %d handler %p level %d\n", evtch,
 	       handler, level);
 #endif
-	ih = kmem_zalloc(sizeof (struct intrhand), KM_NOSLEEP);
-	if (ih == NULL)
+	esh_args.ih = kmem_zalloc(sizeof (struct intrhand), KM_NOSLEEP);
+	if (esh_args.ih == NULL)
 		panic("can't allocate fixed interrupt source");
 
 
-	ih->ih_pic = &xen_pic;
-	ih->ih_level = level;
-	ih->ih_fun = ih->ih_realfun = func;
-	ih->ih_arg = ih->ih_realarg = arg;
-	ih->ih_evt_next = NULL;
-	ih->ih_next = NULL;
-	ih->ih_cpu = ci;
-	ih->ih_pin = evtch;
+	esh_args.ih->ih_pic = &xen_pic;
+	esh_args.ih->ih_level = level;
+	esh_args.ih->ih_fun = esh_args.ih->ih_realfun = func;
+	esh_args.ih->ih_arg = esh_args.ih->ih_realarg = arg;
+	esh_args.ih->ih_evt_next = NULL;
+	esh_args.ih->ih_next = NULL;
+	esh_args.ih->ih_cpu = ci;
+	esh_args.ih->ih_pin = evtch;
 #ifdef MULTIPROCESSOR
 	if (!mpsafe) {
-		ih->ih_fun = xen_intr_biglock_wrapper;
-		ih->ih_arg = ih;
+		esh_args.ih->ih_fun = xen_intr_biglock_wrapper;
+		esh_args.ih->ih_arg = esh_args.ih;
 	}
 #endif /* MULTIPROCESSOR */
+	KASSERT(mpsafe || level < IPL_HIGH);
 
 	mutex_enter(&cpu_lock);
+	/* allocate IPL source if needed */
+	int sir = XEN_IPL2SIR(level);
+	if (ci->ci_isources[sir] == NULL) {
+		struct intrsource *ipls;
+		ipls = kmem_zalloc(sizeof (struct intrsource), KM_NOSLEEP);
+		if (ipls == NULL)
+			panic("can't allocate fixed interrupt source");
+		ipls->is_recurse = xenev_stubs[level - IPL_VM].ist_recurse;
+		ipls->is_resume = xenev_stubs[level - IPL_VM].ist_resume;
+		ipls->is_pic = &xen_pic;
+		esh_args.ipls = ipls;
+		/*
+		 * note that we can't set ci_isources here, as
+		 * the assembly can't handle is_handlers being NULL
+		 */
+	}
 	/* register handler for event channel */
 	if (evtsource[evtch] == NULL) {
+		struct evtsource *evts;
 		evtchn_op_t op;
 		if (intrname == NULL)
 			intrname = intr_create_intrid(-1, &xen_pic, evtch,
@@ -838,15 +923,7 @@ event_set_handler(int evtch, int (*func)
 		if (evts == NULL)
 			panic("can't allocate fixed interrupt source");
 
-		evts->ev_handlers = ih;
-		/*
-		 * XXX: We're assuming here that ci is the same cpu as
-		 * the one on which this event/port is bound on. The
-		 * api needs to be reshuffled so that this assumption
-		 * is more explicitly implemented.
-		 */
 		evts->ev_cpu = ci;
-		evtsource[evtch] = evts;
 		strlcpy(evts->ev_intrname, intrname, sizeof(evts->ev_intrname));
 
 		evcnt_attach_dynamic(&evts->ev_evcnt, EVCNT_TYPE_INTR, NULL,
@@ -864,70 +941,31 @@ event_set_handler(int evtch, int (*func)
 #ifndef XENPV
 		evts->ev_isl = intr_allocate_io_intrsource(intrname);
 		evts->ev_isl->is_pic = &xen_pic;
-		evts->ev_isl->is_handlers = evts->ev_handlers;
-#endif
-	} else {
-		evts = evtsource[evtch];
-		/* sort by IPL order, higher first */
-		for (ihp = &evts->ev_handlers; ; ihp = &((*ihp)->ih_evt_next)) {
-			if ((*ihp)->ih_level < ih->ih_level) {
-				/* insert before *ihp */
-				ih->ih_evt_next = *ihp;
-				*ihp = ih;
-				break;
-			}
-			if ((*ihp)->ih_evt_next == NULL) {
-				(*ihp)->ih_evt_next = ih;
-				break;
-			}
-		}
-#ifndef XENPV
-		evts->ev_isl->is_handlers = evts->ev_handlers;
 #endif
+		evtsource[evtch] = evts;
 	}
-	const u_long psl = x86_read_psl();
-	x86_disable_intr();
-	/* register per-cpu handler for spllower() */
-	event_set_iplhandler(ci, ih, level);
-	intr_calculatemasks(evts, evtch, ci);
-	x86_write_psl(psl);
+	esh_args.evts = evtsource[evtch];
 
 	// append device name
-	if (evts->ev_xname[0] != '\0')
-		strlcat(evts->ev_xname, ", ", sizeof(evts->ev_xname));
-	strlcat(evts->ev_xname, xname, sizeof(evts->ev_xname));
-
-	mutex_exit(&cpu_lock);
-	return ih;
-}
+	if (esh_args.evts->ev_xname[0] != '\0') {
+		strlcat(esh_args.evts->ev_xname, ", ",
+		    sizeof(esh_args.evts->ev_xname));
+	}
+	strlcat(esh_args.evts->ev_xname, xname,
+	    sizeof(esh_args.evts->ev_xname));
 
-void
-event_set_iplhandler(struct cpu_info *ci,
-		     struct intrhand *ih,
-		     int level)
-{
-	struct intrsource *ipls;
-	int sir = XEN_IPL2SIR(level);
-	KASSERT(sir >= SIR_XENIPL_VM && sir <= SIR_XENIPL_HIGH);
+	esh_args.evtch = evtch;
 
-	KASSERT(ci == ih->ih_cpu);
-	KASSERT(ci == curcpu());
-	if (ci->ci_isources[sir] == NULL) {
-		ipls = kmem_zalloc(sizeof (struct intrsource),
-		    KM_NOSLEEP);
-		if (ipls == NULL)
-			panic("can't allocate fixed interrupt source");
-		ipls->is_recurse = xenev_stubs[level - IPL_VM].ist_recurse;
-		ipls->is_resume = xenev_stubs[level - IPL_VM].ist_resume;
-		ipls->is_handlers = ih;
-		ipls->is_pic = &xen_pic;
-		ci->ci_isources[sir] = ipls;
+	if (ci == curcpu() || !mp_online) {
+		event_set_handler_xcall(&esh_args, NULL);
 	} else {
-		ipls = ci->ci_isources[sir];
-		ih->ih_next = ipls->is_handlers;
-		ipls->is_handlers = ih;
+		uint64_t where = xc_unicast(0, event_set_handler_xcall,
+		    &esh_args, NULL, ci);
+		xc_wait(where);
 	}
-	x86_intr_calculatemasks(ci);
+
+	mutex_exit(&cpu_lock);
+	return esh_args.ih;
 }
 
 /*

Index: src/sys/arch/xen/xen/xen_clock.c
diff -u src/sys/arch/xen/xen/xen_clock.c:1.4 src/sys/arch/xen/xen/xen_clock.c:1.5
--- src/sys/arch/xen/xen/xen_clock.c:1.4	Sat May  2 16:44:36 2020
+++ src/sys/arch/xen/xen/xen_clock.c	Thu May  7 19:48:57 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: xen_clock.c,v 1.4 2020/05/02 16:44:36 bouyer Exp $	*/
+/*	$NetBSD: xen_clock.c,v 1.5 2020/05/07 19:48:57 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2017, 2018 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xen_clock.c,v 1.4 2020/05/02 16:44:36 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_clock.c,v 1.5 2020/05/07 19:48:57 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -636,7 +636,7 @@ xen_resumeclocks(struct cpu_info *ci)
 	/* XXX sketchy function pointer cast -- fix the API, please */
 	if (event_set_handler(evtch,
 	    __FPTRCAST(int (*)(void *), xen_timer_handler),
-	    ci, IPL_CLOCK, NULL, intr_xname, true, false) == NULL)
+	    ci, IPL_CLOCK, NULL, intr_xname, true, ci) == NULL)
 		panic("failed to establish timer interrupt handler");
 
 	hypervisor_unmask_event(evtch);

Reply via email to