Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/xen Change event_set_handler() to take the target C...



details:   https://anonhg.NetBSD.org/src/rev/4065db5f982a
branches:  trunk
changeset: 932458:4065db5f982a
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Thu May 07 19:48:57 2020 +0000

description:
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).

diffstat:

 sys/arch/xen/include/evtchn.h |    5 +-
 sys/arch/xen/x86/xen_intr.c   |   10 +-
 sys/arch/xen/x86/xen_ipi.c    |    6 +-
 sys/arch/xen/xen/evtchn.c     |  208 ++++++++++++++++++++++++-----------------
 sys/arch/xen/xen/xen_clock.c  |    6 +-
 5 files changed, 137 insertions(+), 98 deletions(-)

diffs (truncated from 401 to 300 lines):

diff -r 6d41440e1e2f -r 4065db5f982a sys/arch/xen/include/evtchn.h
--- a/sys/arch/xen/include/evtchn.h     Thu May 07 19:25:57 2020 +0000
+++ b/sys/arch/xen/include/evtchn.h     Thu May 07 19:48:57 2020 +0000
@@ -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 @@
 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 *);
diff -r 6d41440e1e2f -r 4065db5f982a sys/arch/xen/x86/xen_intr.c
--- a/sys/arch/xen/x86/xen_intr.c       Thu May 07 19:25:57 2020 +0000
+++ b/sys/arch/xen/x86/xen_intr.c       Thu May 07 19:48:57 2020 +0000
@@ -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 @@
                    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 @@
        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 @@
        }
 
        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 */
diff -r 6d41440e1e2f -r 4065db5f982a sys/arch/xen/x86/xen_ipi.c
--- a/sys/arch/xen/x86/xen_ipi.c        Thu May 07 19:25:57 2020 +0000
+++ b/sys/arch/xen/x86/xen_ipi.c        Thu May 07 19:48:57 2020 +0000
@@ -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 @@
            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 */
        }
diff -r 6d41440e1e2f -r 4065db5f982a sys/arch/xen/xen/evtchn.c
--- a/sys/arch/xen/xen/evtchn.c Thu May 07 19:25:57 2020 +0000
+++ b/sys/arch/xen/xen/evtchn.c Thu May 07 19:48:57 2020 +0000
@@ -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 @@
        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 @@
                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 @@
        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 @@
                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 @@
 #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;
-                       }



Home | Main Index | Thread Index | Old Index