Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/xen refactor the bitstring/mask operations to be be...



details:   https://anonhg.NetBSD.org/src/rev/2b443977a9da
branches:  trunk
changeset: 768182:2b443977a9da
user:      cherry <cherry%NetBSD.org@localhost>
date:      Wed Aug 10 21:46:02 2011 +0000

description:
refactor the bitstring/mask operations to be behind an API. Make pending interrupt marking cpu aware.

diffstat:

 sys/arch/xen/include/hypervisor.h     |    6 +-
 sys/arch/xen/x86/hypervisor_machdep.c |  235 ++++++++++++++++++---------------
 sys/arch/xen/xen/evtchn.c             |    8 +-
 3 files changed, 136 insertions(+), 113 deletions(-)

diffs (truncated from 382 to 300 lines):

diff -r 0bb7e1ddff50 -r 2b443977a9da sys/arch/xen/include/hypervisor.h
--- a/sys/arch/xen/include/hypervisor.h Wed Aug 10 20:38:45 2011 +0000
+++ b/sys/arch/xen/include/hypervisor.h Wed Aug 10 21:46:02 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hypervisor.h,v 1.31 2009/10/19 18:41:10 bouyer Exp $   */
+/*     $NetBSD: hypervisor.h,v 1.32 2011/08/10 21:46:02 cherry Exp $   */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -91,6 +91,7 @@
 #include <xen/xen3-public/io/netif.h>
 #include <xen/xen3-public/io/blkif.h>
 
+#include <machine/cpu.h>
 #include <machine/hypercalls.h>
 
 #undef u8
@@ -136,7 +137,8 @@
 void hypervisor_mask_event(unsigned int);
 void hypervisor_clear_event(unsigned int);
 void hypervisor_enable_ipl(unsigned int);
-void hypervisor_set_ipending(uint32_t, int, int);
+void hypervisor_set_ipending(struct cpu_info *, 
+                            uint32_t, int, int);
 void hypervisor_machdep_attach(void);
 
 /* 
diff -r 0bb7e1ddff50 -r 2b443977a9da sys/arch/xen/x86/hypervisor_machdep.c
--- a/sys/arch/xen/x86/hypervisor_machdep.c     Wed Aug 10 20:38:45 2011 +0000
+++ b/sys/arch/xen/x86/hypervisor_machdep.c     Wed Aug 10 21:46:02 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hypervisor_machdep.c,v 1.14 2011/03/30 21:53:58 jym Exp $      */
+/*     $NetBSD: hypervisor_machdep.c,v 1.15 2011/08/10 21:46:02 cherry Exp $   */
 
 /*
  *
@@ -54,7 +54,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.14 2011/03/30 21:53:58 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.15 2011/08/10 21:46:02 cherry Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -86,13 +86,79 @@
 // #define PORT_DEBUG 4
 // #define EARLY_DEBUG_EVENT
 
+/* callback function type */
+typedef void (*iterate_func_t)(struct cpu_info *, unsigned int,
+                              unsigned int, unsigned int, void *);
+
+static inline void
+evt_iterate_bits(struct cpu_info *ci, volatile unsigned long *pendingl1,
+                volatile unsigned long *pendingl2, 
+                volatile unsigned long *mask,
+                iterate_func_t iterate_pending, void *iterate_args)
+{
+
+       KASSERT(pendingl1 != NULL);
+       KASSERT(pendingl2 != NULL);
+       
+       unsigned long l1, l2;
+       unsigned int l1i, l2i, port;
+
+       l1 = xen_atomic_xchg(pendingl1, 0);
+       while ((l1i = xen_ffs(l1)) != 0) {
+               l1i--;
+               l1 &= ~(1UL << l1i);
+
+               l2 = pendingl2[l1i] & (mask != NULL ? ~mask[l1i] : -1UL);
+
+               if (mask != NULL) xen_atomic_setbits_l(&mask[l1i], l2);
+               xen_atomic_clearbits_l(&pendingl2[l1i], l2);
+
+               while ((l2i = xen_ffs(l2)) != 0) {
+                       l2i--;
+                       l2 &= ~(1UL << l2i);
+
+                       port = (l1i << LONG_SHIFT) + l2i;
+
+                       iterate_pending(ci, port, l1i, l2i, iterate_args);
+               }
+       }
+}
+
+/*
+ * Set per-cpu "pending" information for outstanding events that
+ * cannot be processed now.
+ */
+   
+static inline void
+evt_set_pending(struct cpu_info *ci, unsigned int port, unsigned int l1i,
+               unsigned int l2i, void *args)
+{
+
+       KASSERT(args != NULL);
+       KASSERT(ci != NULL);
+
+       int *ret = args;
+
+       if (evtsource[port]) {
+               hypervisor_set_ipending(ci, evtsource[port]->ev_imask,
+                   l1i, l2i);
+               evtsource[port]->ev_evcnt.ev_count++;
+               if (*ret == 0 && ci->ci_ilevel <
+                   evtsource[port]->ev_maxlevel)
+                       *ret = 1;
+       }
+#ifdef DOM0OPS
+       else  {
+               /* set pending event */
+               xenevt_setipending(l1i, l2i);
+       }
+#endif
+}
+
 int stipending(void);
 int
 stipending(void)
 {
-       unsigned long l1;
-       unsigned long l2;
-       unsigned int l1i, l2i, port;
        volatile shared_info_t *s = HYPERVISOR_shared_info;
        struct cpu_info *ci;
        volatile struct vcpu_info *vci;
@@ -120,45 +186,16 @@
         * we're only called after STIC, so we know that we'll have to
         * STI at the end
         */
+
        while (vci->evtchn_upcall_pending) {
                cli();
+
                vci->evtchn_upcall_pending = 0;
-               /* NB. No need for a barrier here -- XCHG is a barrier
-                * on x86. */
-               l1 = xen_atomic_xchg(&vci->evtchn_pending_sel, 0);
-               while ((l1i = xen_ffs(l1)) != 0) {
-                       l1i--;
-                       l1 &= ~(1UL << l1i);
-
-                       l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
-                       /*
-                        * mask and clear event. More efficient than calling
-                        * hypervisor_mask/clear_event for each event.
-                        */
-                       xen_atomic_setbits_l(&s->evtchn_mask[l1i], l2);
-                       xen_atomic_clearbits_l(&s->evtchn_pending[l1i], l2);
-                       while ((l2i = xen_ffs(l2)) != 0) {
-                               l2i--;
-                               l2 &= ~(1UL << l2i);
 
-                               port = (l1i << LONG_SHIFT) + l2i;
-                               if (evtsource[port]) {
-                                       hypervisor_set_ipending(
-                                           evtsource[port]->ev_imask,
-                                           l1i, l2i);
-                                       evtsource[port]->ev_evcnt.ev_count++;
-                                       if (ret == 0 && ci->ci_ilevel <
-                                           evtsource[port]->ev_maxlevel)
-                                               ret = 1;
-                               }
-#ifdef DOM0OPS
-                               else  {
-                                       /* set pending event */
-                                       xenevt_setipending(l1i, l2i);
-                               }
-#endif
-                       }
-               }
+               evt_iterate_bits(ci, &vci->evtchn_pending_sel,
+                   s->evtchn_pending, s->evtchn_mask,
+                   evt_set_pending, &ret);
+
                sti();
        }
 
@@ -173,12 +210,42 @@
        return (ret);
 }
 
+/* Iterate through pending events and call the event handler */
+
+static inline void
+evt_do_hypervisor_callback(struct cpu_info *ci, unsigned int port,
+                          unsigned int l1i, unsigned int l2i, void *args)
+{
+       KASSERT(args != NULL);
+       KASSERT(ci == curcpu());
+
+       struct intrframe *regs = args;
+
+#ifdef PORT_DEBUG
+       if (port == PORT_DEBUG)
+               printf("do_hypervisor_callback event %d\n", port);
+#endif
+       if (evtsource[port])
+               call_evtchn_do_event(port, regs);
+#ifdef DOM0OPS
+       else  {
+               if (ci->ci_ilevel < IPL_HIGH) {
+                       /* fast path */
+                       int oipl = ci->ci_ilevel;
+                       ci->ci_ilevel = IPL_HIGH;
+                       call_xenevt_event(port);
+                       ci->ci_ilevel = oipl;
+               } else {
+                       /* set pending event */
+                       xenevt_setipending(l1i, l2i);
+               }
+       }
+#endif
+}
+
 void
 do_hypervisor_callback(struct intrframe *regs)
 {
-       unsigned long l1;
-       unsigned long l2;
-       unsigned int l1i, l2i, port;
        volatile shared_info_t *s = HYPERVISOR_shared_info;
        struct cpu_info *ci;
        volatile struct vcpu_info *vci;
@@ -199,51 +266,10 @@
 
        while (vci->evtchn_upcall_pending) {
                vci->evtchn_upcall_pending = 0;
-               /* NB. No need for a barrier here -- XCHG is a barrier
-                * on x86. */
-               l1 = xen_atomic_xchg(&vci->evtchn_pending_sel, 0);
-               while ((l1i = xen_ffs(l1)) != 0) {
-                       l1i--;
-                       l1 &= ~(1UL << l1i);
 
-                       l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
-                       /*
-                        * mask and clear the pending events.
-                        * Doing it here for all event that will be processed
-                        * avoids a race with stipending (which can be called
-                        * though evtchn_do_event->splx) that could cause an
-                        * event to be both processed and marked pending.
-                        */
-                       xen_atomic_setbits_l(&s->evtchn_mask[l1i], l2);
-                       xen_atomic_clearbits_l(&s->evtchn_pending[l1i], l2);
-
-                       while ((l2i = xen_ffs(l2)) != 0) {
-                               l2i--;
-                               l2 &= ~(1UL << l2i);
-
-                               port = (l1i << LONG_SHIFT) + l2i;
-#ifdef PORT_DEBUG
-                               if (port == PORT_DEBUG)
-                                       printf("do_hypervisor_callback event %d\n", port);
-#endif
-                               if (evtsource[port])
-                                       call_evtchn_do_event(port, regs);
-#ifdef DOM0OPS
-                               else  {
-                                       if (ci->ci_ilevel < IPL_HIGH) {
-                                               /* fast path */
-                                               int oipl = ci->ci_ilevel;
-                                               ci->ci_ilevel = IPL_HIGH;
-                                               call_xenevt_event(port);
-                                               ci->ci_ilevel = oipl;
-                                       } else {
-                                               /* set pending event */
-                                               xenevt_setipending(l1i, l2i);
-                                       }
-                               }
-#endif
-                       }
-               }
+               evt_iterate_bits(ci, &vci->evtchn_pending_sel,
+                   s->evtchn_pending, s->evtchn_mask,
+                   evt_do_hypervisor_callback, regs);
        }
 
 #ifdef DIAGNOSTIC
@@ -303,11 +329,18 @@
        xen_atomic_clear_bit(&s->evtchn_pending[0], ev);
 }
 
+static inline void
+evt_enable_event(struct cpu_info *ci, unsigned int port,  
+                unsigned int l1i, unsigned int l2i, void *args)
+{
+       KASSERT(ci != NULL);
+       KASSERT(args == NULL);
+       hypervisor_enable_event(port);
+}
+
 void
 hypervisor_enable_ipl(unsigned int ipl)
 {
-       u_long l1, l2;
-       int l1i, l2i;
        struct cpu_info *ci = curcpu();



Home | Main Index | Thread Index | Old Index