Source-Changes-HG archive

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

[src/cherry-xenmp]: src/sys/arch Various interrupt fixes, mainly:



details:   https://anonhg.NetBSD.org/src/rev/8ed7f8bc237a
branches:  cherry-xenmp
changeset: 765646:8ed7f8bc237a
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sat Oct 22 19:21:57 2011 +0000

description:
Various interrupt fixes, mainly:
keep a per-cpu mask of enabled events, and use it to get pending events.
A cpu-specific event (all of them at this time) should not be ever masked
by another CPU, because it may prevent the target CPU from seeing it
(the clock events all fires at once for example).

diffstat:

 sys/arch/x86/include/cpu.h            |   3 +-
 sys/arch/xen/x86/hypervisor_machdep.c |  12 +++++++-
 sys/arch/xen/xen/evtchn.c             |  46 +++++++++++++++++++++++++++-------
 3 files changed, 48 insertions(+), 13 deletions(-)

diffs (194 lines):

diff -r 88ce4a19a991 -r 8ed7f8bc237a sys/arch/x86/include/cpu.h
--- a/sys/arch/x86/include/cpu.h        Fri Oct 21 18:08:44 2011 +0000
+++ b/sys/arch/x86/include/cpu.h        Sat Oct 22 19:21:57 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpu.h,v 1.34.2.6 2011/09/01 08:04:46 cherry Exp $      */
+/*     $NetBSD: cpu.h,v 1.34.2.7 2011/10/22 19:21:57 bouyer Exp $      */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -126,6 +126,7 @@
 
 #ifdef XEN
        struct iplsource  *ci_isources[NIPL];
+       u_long ci_evtmask[NR_EVENT_CHANNELS]; /* events allowed on this CPU */
 #else
        struct intrsource *ci_isources[MAX_INTR_SOURCES];
 #endif
diff -r 88ce4a19a991 -r 8ed7f8bc237a sys/arch/xen/x86/hypervisor_machdep.c
--- a/sys/arch/xen/x86/hypervisor_machdep.c     Fri Oct 21 18:08:44 2011 +0000
+++ b/sys/arch/xen/x86/hypervisor_machdep.c     Sat Oct 22 19:21:57 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hypervisor_machdep.c,v 1.14.2.5 2011/09/18 18:46:40 cherry Exp $       */
+/*     $NetBSD: hypervisor_machdep.c,v 1.14.2.6 2011/10/22 19:21:57 bouyer Exp $       */
 
 /*
  *
@@ -54,7 +54,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.14.2.5 2011/09/18 18:46:40 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.14.2.6 2011/10/22 19:21:57 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -109,6 +109,7 @@
                l1 &= ~(1UL << l1i);
 
                l2 = pendingl2[l1i] & (mask != NULL ? ~mask[l1i] : -1UL);
+               l2 &= ci->ci_evtmask[l1i];
 
                if (mask != NULL) xen_atomic_setbits_l(&mask[l1i], l2);
                xen_atomic_clearbits_l(&pendingl2[l1i], l2);
@@ -405,6 +406,13 @@
        KASSERT(ci->ci_isources[ipl] != NULL);
        ci->ci_isources[ipl]->ipl_evt_mask1 |= 1UL << l1;
        ci->ci_isources[ipl]->ipl_evt_mask2[l1] |= 1UL << l2;
+       if (__predict_false(ci != curcpu())) {
+               if (xen_send_ipi(ci, XEN_IPI_HVCB)) {
+                       panic("hypervisor_set_ipending: "
+                           "xen_send_ipi(cpu%d, XEN_IPI_HVCB) failed\n",
+                           (int) ci->ci_cpuid);
+               }
+       }
 }
 
 void
diff -r 88ce4a19a991 -r 8ed7f8bc237a sys/arch/xen/xen/evtchn.c
--- a/sys/arch/xen/xen/evtchn.c Fri Oct 21 18:08:44 2011 +0000
+++ b/sys/arch/xen/xen/evtchn.c Sat Oct 22 19:21:57 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: evtchn.c,v 1.47.6.5 2011/09/18 18:46:40 cherry Exp $   */
+/*     $NetBSD: evtchn.c,v 1.47.6.6 2011/10/22 19:21:57 bouyer Exp $   */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -54,7 +54,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.47.6.5 2011/09/18 18:46:40 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.47.6.6 2011/10/22 19:21:57 bouyer Exp $");
 
 #include "opt_xen.h"
 #include "isa.h"
@@ -190,6 +190,7 @@
         * be called.
         */
        evtsource[debug_port] = (void *)-1;
+       xen_atomic_set_bit(&curcpu()->ci_evtmask[0], debug_port);
        hypervisor_enable_event(debug_port);
 
        x86_enable_intr();              /* at long last... */
@@ -263,8 +264,16 @@
        mutex_spin_enter(&evtlock[evtch]);
        ih = evtsource[evtch]->ev_handlers;
        while (ih != NULL) {
-               if (ih->ih_level <= ilevel ||
-                  ih->ih_cpu != ci) {
+               if (ih->ih_cpu != ci) {
+                       hypervisor_set_ipending(ih->ih_cpu, 1 << ih->ih_level,
+                           evtch >> LONG_SHIFT, evtch & LONG_MASK);
+                       iplmask &= ~IUNMASK(ci, ih->ih_level);
+                       ih = ih->ih_evt_next;
+                       continue;
+               }
+               if (ih->ih_level <= ilevel) {
+                       hypervisor_set_ipending(ih->ih_cpu, iplmask,
+                           evtch >> LONG_SHIFT, evtch & LONG_MASK);
 #ifdef IRQ_DEBUG
                if (evtch == IRQ_DEBUG)
                    printf("ih->ih_level %d <= ilevel %d\n", ih->ih_level, ilevel);
@@ -390,7 +399,11 @@
                        panic("Failed to bind virtual IRQ %d\n", virq);
                evtchn = op.u.bind_virq.port;
 
-               virq_to_evtch[virq] = evtchn;
+               if (virq == VIRQ_TIMER) {
+                       virq_timer_to_evtch[ci->ci_cpuid] = evtchn;
+               } else {
+                       virq_to_evtch[virq] = evtchn;
+               }
        }
 
        evtch_bindcount[evtchn]++;
@@ -428,7 +441,11 @@
                if (HYPERVISOR_event_channel_op(&op) != 0)
                        panic("Failed to unbind virtual IRQ %d\n", virq);
 
-               virq_to_evtch[virq] = -1;
+               if (virq == VIRQ_TIMER) {
+                       virq_timer_to_evtch[ci->ci_cpuid] = -1;
+               } else {
+                       virq_to_evtch[virq] = -1;
+               }
        }
 
        mutex_spin_exit(&evtchn_lock);
@@ -552,9 +569,10 @@
  * Recalculate the interrupt from scratch for an event source.
  */
 static void
-intr_calculatemasks(struct evtsource *evts, int evtch)
+intr_calculatemasks(struct evtsource *evts, int evtch, struct cpu_info *ci)
 {
        struct intrhand *ih;
+       int cpu_receive = 0;
 
 #ifdef MULTIPROCESSOR
        KASSERT(!mutex_owned(&evtlock[evtch]));
@@ -566,7 +584,13 @@
                if (ih->ih_level > evts->ev_maxlevel)
                        evts->ev_maxlevel = ih->ih_level;
                evts->ev_imask |= (1 << ih->ih_level);
+               if (ih->ih_cpu == ci)
+                       cpu_receive = 1;
        }
+       if (cpu_receive)
+               xen_atomic_set_bit(&curcpu()->ci_evtmask[0], evtch);
+       else
+               xen_atomic_clear_bit(&curcpu()->ci_evtmask[0], evtch);
        mutex_spin_exit(&evtlock[evtch]);
 }
 
@@ -665,7 +689,7 @@
                mutex_spin_exit(&evtlock[evtch]);
        }
 
-       intr_calculatemasks(evts, evtch);
+       intr_calculatemasks(evts, evtch, ci);
        splx(s);
 
        return 0;
@@ -702,7 +726,7 @@
        struct evtsource *evts;
        struct intrhand *ih;
        struct intrhand **ihp;
-       struct cpu_info *ci = curcpu();
+       struct cpu_info *ci;
 
        evts = evtsource[evtch];
        if (evts == NULL)
@@ -719,6 +743,7 @@
                mutex_spin_exit(&evtlock[evtch]);
                return ENOENT;
        }
+       ci = ih->ih_cpu;
        *ihp = ih->ih_evt_next;
        mutex_spin_exit(&evtlock[evtch]);
 
@@ -734,11 +759,12 @@
        *ihp = ih->ih_ipl_next;
        free(ih, M_DEVBUF);
        if (evts->ev_handlers == NULL) {
+               xen_atomic_clear_bit(&ci->ci_evtmask[0], evtch);
                evcnt_detach(&evts->ev_evcnt);
                free(evts, M_DEVBUF);
                evtsource[evtch] = NULL;
        } else {
-               intr_calculatemasks(evts, evtch);
+               intr_calculatemasks(evts, evtch, ci);
        }
        return 0;
 }



Home | Main Index | Thread Index | Old Index