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;
}