Module Name: src Committed By: bouyer Date: Sat Jan 12 17:39:46 UTC 2013
Modified Files: src/sys/arch/xen/include: evtchn.h hypervisor.h src/sys/arch/xen/x86: hypervisor_machdep.c src/sys/arch/xen/xen: evtchn.c Log Message: Back out this commit: http://mail-index.netbsd.org/source-changes/2012/12/28/msg039950.html which cause a panic when running tests on amd64, as shown on: http://www-soc.lip6.fr/~bouyer/NetBSD-tests/xen/HEAD/ (i386 hangs for unrelated reasons). To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/sys/arch/xen/include/evtchn.h cvs rdiff -u -r1.40 -r1.41 src/sys/arch/xen/include/hypervisor.h cvs rdiff -u -r1.24 -r1.25 src/sys/arch/xen/x86/hypervisor_machdep.c cvs rdiff -u -r1.66 -r1.67 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/xen/include/evtchn.h diff -u src/sys/arch/xen/include/evtchn.h:1.21 src/sys/arch/xen/include/evtchn.h:1.22 --- src/sys/arch/xen/include/evtchn.h:1.21 Fri Dec 28 06:29:56 2012 +++ src/sys/arch/xen/include/evtchn.h Sat Jan 12 17:39:46 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: evtchn.h,v 1.21 2012/12/28 06:29:56 cherry Exp $ */ +/* $NetBSD: evtchn.h,v 1.22 2013/01/12 17:39:46 bouyer Exp $ */ /* * @@ -33,9 +33,6 @@ extern struct evtsource *evtsource[]; -#include <sys/mutex.h> -extern kmutex_t evtlock[]; - void events_default_setup(void); void events_init(void); bool events_suspend(void); Index: src/sys/arch/xen/include/hypervisor.h diff -u src/sys/arch/xen/include/hypervisor.h:1.40 src/sys/arch/xen/include/hypervisor.h:1.41 --- src/sys/arch/xen/include/hypervisor.h:1.40 Fri Dec 28 06:29:56 2012 +++ src/sys/arch/xen/include/hypervisor.h Sat Jan 12 17:39:46 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: hypervisor.h,v 1.40 2012/12/28 06:29:56 cherry Exp $ */ +/* $NetBSD: hypervisor.h,v 1.41 2013/01/12 17:39:46 bouyer Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -142,7 +142,6 @@ void hypervisor_unmask_event(unsigned in void hypervisor_mask_event(unsigned int); void hypervisor_clear_event(unsigned int); void hypervisor_enable_ipl(unsigned int); -void hypervisor_do_iplpending(unsigned int, void *); void hypervisor_set_ipending(uint32_t, int, int); void hypervisor_machdep_attach(void); void hypervisor_machdep_resume(void); Index: src/sys/arch/xen/x86/hypervisor_machdep.c diff -u src/sys/arch/xen/x86/hypervisor_machdep.c:1.24 src/sys/arch/xen/x86/hypervisor_machdep.c:1.25 --- src/sys/arch/xen/x86/hypervisor_machdep.c:1.24 Fri Dec 28 06:29:56 2012 +++ src/sys/arch/xen/x86/hypervisor_machdep.c Sat Jan 12 17:39:46 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: hypervisor_machdep.c,v 1.24 2012/12/28 06:29:56 cherry Exp $ */ +/* $NetBSD: hypervisor_machdep.c,v 1.25 2013/01/12 17:39:46 bouyer Exp $ */ /* * @@ -54,7 +54,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.24 2012/12/28 06:29:56 cherry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.25 2013/01/12 17:39:46 bouyer Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -187,7 +187,7 @@ stipending(void) */ while (vci->evtchn_upcall_pending) { - x86_disable_intr(); + cli(); vci->evtchn_upcall_pending = 0; @@ -195,7 +195,7 @@ stipending(void) s->evtchn_pending, s->evtchn_mask, evt_set_pending, &ret); - x86_enable_intr(); + sti(); } #if 0 @@ -284,82 +284,6 @@ do_hypervisor_callback(struct intrframe #endif } -/* Iterate through pending events and call the event handler */ -struct splargs { - int ipl; - struct intrframe *regs; -}; - -static inline void -evt_do_iplcallback(unsigned int evtch, unsigned int l1i, - unsigned int l2i, void *args) -{ - KASSERT(args != NULL); - struct splargs *sargs = args; - - struct intrhand *ih; - int (*ih_fun)(void *, void *); - - int ipl = sargs->ipl; - struct cpu_info *ci = curcpu(); - struct intrframe *regs = sargs->regs; - - KASSERT(evtsource[evtch] != 0); - - KASSERT(ci->ci_ilevel == ipl); - - KASSERT(x86_read_psl() != 0); - x86_enable_intr(); - mutex_spin_enter(&evtlock[evtch]); - ih = evtsource[evtch]->ev_handlers; - while (ih != NULL) { - if (ih->ih_cpu != ci) { /* Skip non-local handlers */ - ih = ih->ih_evt_next; - continue; - } - if (ih->ih_level == ipl) { - KASSERT(x86_read_psl() == 0); - x86_disable_intr(); - ci->ci_ilevel = ih->ih_level; - x86_enable_intr(); - ih_fun = (void *)ih->ih_fun; - ih_fun(ih->ih_arg, regs); - if (ci->ci_ilevel != ipl) { - printf("evtchn_do_event: " - "handler %p didn't lower " - "ipl %d %d\n", - ih_fun, ci->ci_ilevel, ipl); - } - } - ih = ih->ih_evt_next; - } - mutex_spin_exit(&evtlock[evtch]); - hypervisor_enable_event(evtch); - x86_disable_intr(); - - KASSERT(ci->ci_ilevel == ipl); -} - -/* - * Iterate through all pending interrupt handlers at 'ipl', on current - * cpu. - */ -void -hypervisor_do_iplpending(unsigned int ipl, void *regs) -{ - struct cpu_info *ci; - struct splargs splargs = { - .ipl = ipl, - .regs = regs}; - - ci = curcpu(); - - evt_iterate_bits(&ci->ci_isources[ipl]->ipl_evt_mask1, - ci->ci_isources[ipl]->ipl_evt_mask2, NULL, - evt_do_iplcallback, &splargs); -} - - void hypervisor_send_event(struct cpu_info *ci, unsigned int ev) { @@ -513,6 +437,13 @@ hypervisor_set_ipending(uint32_t iplmask 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 Index: src/sys/arch/xen/xen/evtchn.c diff -u src/sys/arch/xen/xen/evtchn.c:1.66 src/sys/arch/xen/xen/evtchn.c:1.67 --- src/sys/arch/xen/xen/evtchn.c:1.66 Fri Dec 28 06:29:56 2012 +++ src/sys/arch/xen/xen/evtchn.c Sat Jan 12 17:39:46 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: evtchn.c,v 1.66 2012/12/28 06:29:56 cherry Exp $ */ +/* $NetBSD: evtchn.c,v 1.67 2013/01/12 17:39:46 bouyer Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -54,7 +54,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.66 2012/12/28 06:29:56 cherry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.67 2013/01/12 17:39:46 bouyer Exp $"); #include "opt_xen.h" #include "isa.h" @@ -89,7 +89,7 @@ static kmutex_t evtchn_lock; struct evtsource *evtsource[NR_EVENT_CHANNELS]; /* channel locks */ -kmutex_t evtlock[NR_EVENT_CHANNELS]; +static kmutex_t evtlock[NR_EVENT_CHANNELS]; /* Reference counts for bindings to event channels XXX: redo for SMP */ static uint8_t evtch_bindcount[NR_EVENT_CHANNELS]; @@ -228,50 +228,6 @@ events_resume (void) } -static int -xspllower(int ilevel, void *regs) -{ - int i; - uint32_t iplbit; - uint32_t iplpending; - - struct cpu_info *ci; - - KASSERT(kpreempt_disabled()); - KASSERT(x86_read_psl() != 0); /* Interrupts must be disabled */ - - ci = curcpu(); - ci->ci_idepth++; - - KASSERT(ilevel < ci->ci_ilevel); - /* - * C version of spllower(). ASTs will be checked when - * hypevisor_callback() exits, so no need to check here. - */ - iplpending = (IUNMASK(ci, ilevel) & ci->ci_ipending); - while (iplpending != 0) { - iplbit = 1 << (NIPL - 1); - i = (NIPL - 1); - while (iplpending != 0 && i > ilevel) { - while (iplpending & iplbit) { - ci->ci_ipending &= ~iplbit; - ci->ci_ilevel = i; - hypervisor_do_iplpending(i, regs); - KASSERT(x86_read_psl() != 0); - /* more pending IPLs may have been registered */ - iplpending = - (IUNMASK(ci, ilevel) & ci->ci_ipending); - } - i--; - iplbit >>= 1; - } - } - KASSERT(x86_read_psl() != 0); - ci->ci_ilevel = ilevel; - ci->ci_idepth--; - return 0; -} - unsigned int evtchn_do_event(int evtch, struct intrframe *regs) { @@ -280,6 +236,8 @@ evtchn_do_event(int evtch, struct intrfr struct intrhand *ih; int (*ih_fun)(void *, void *); uint32_t iplmask; + int i; + uint32_t iplbit; #ifdef DIAGNOSTIC if (evtch >= NR_EVENT_CHANNELS) { @@ -334,12 +292,9 @@ evtchn_do_event(int evtch, struct intrfr } ci->ci_ilevel = evtsource[evtch]->ev_maxlevel; iplmask = evtsource[evtch]->ev_imask; - - KASSERT(x86_read_psl() != 0); - x86_enable_intr(); + sti(); mutex_spin_enter(&evtlock[evtch]); ih = evtsource[evtch]->ev_handlers; - while (ih != NULL) { if (ih->ih_cpu != ci) { hypervisor_send_event(ih->ih_cpu, evtch); @@ -352,44 +307,60 @@ evtchn_do_event(int evtch, struct intrfr if (evtch == IRQ_DEBUG) printf("ih->ih_level %d <= ilevel %d\n", ih->ih_level, ilevel); #endif - mutex_spin_exit(&evtlock[evtch]); - x86_disable_intr(); - hypervisor_set_ipending(iplmask, - evtch >> LONG_SHIFT, evtch & LONG_MASK); - + cli(); + hypervisor_set_ipending(iplmask, + evtch >> LONG_SHIFT, evtch & LONG_MASK); /* leave masked */ + mutex_spin_exit(&evtlock[evtch]); goto splx; } iplmask &= ~IUNMASK(ci, ih->ih_level); - - KASSERT(x86_read_psl() == 0); - KASSERT(ih->ih_level > ilevel); - - { /* Lower current spl to current handler */ - x86_disable_intr(); - - /* assert for handlers being sorted by spl */ - KASSERT(ci->ci_ilevel >= ih->ih_level); - - /* Lower it */ - ci->ci_ilevel = ih->ih_level; - - x86_enable_intr(); - } - - /* Assert handler doesn't break spl rules */ - KASSERT(ih->ih_level > ilevel); - + ci->ci_ilevel = ih->ih_level; ih_fun = (void *)ih->ih_fun; ih_fun(ih->ih_arg, regs); ih = ih->ih_evt_next; } mutex_spin_exit(&evtlock[evtch]); - x86_disable_intr(); + cli(); hypervisor_enable_event(evtch); splx: - KASSERT(ci->ci_ilevel > ilevel); - xspllower(ilevel, regs); + /* + * C version of spllower(). ASTs will be checked when + * hypevisor_callback() exits, so no need to check here. + */ + iplmask = (IUNMASK(ci, ilevel) & ci->ci_ipending); + while (iplmask != 0) { + iplbit = 1 << (NIPL - 1); + i = (NIPL - 1); + while (iplmask != 0 && i > ilevel) { + while (iplmask & iplbit) { + ci->ci_ipending &= ~iplbit; + ci->ci_ilevel = i; + for (ih = ci->ci_isources[i]->ipl_handlers; + ih != NULL; ih = ih->ih_ipl_next) { + KASSERT(ih->ih_cpu == ci); + sti(); + ih_fun = (void *)ih->ih_fun; + ih_fun(ih->ih_arg, regs); + cli(); + if (ci->ci_ilevel != i) { + printf("evtchn_do_event: " + "handler %p didn't lower " + "ipl %d %d\n", + ih_fun, ci->ci_ilevel, i); + ci->ci_ilevel = i; + } + } + hypervisor_enable_ipl(i); + /* more pending IPLs may have been registered */ + iplmask = + (IUNMASK(ci, ilevel) & ci->ci_ipending); + } + i--; + iplbit >>= 1; + } + } + ci->ci_ilevel = ilevel; return 0; }