Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/arch/xen/xen/evtchn.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/arch/xen/xen/evtchn.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.66 retrieving revision 1.67 diff -u -p -r1.66 -r1.67 --- src/sys/arch/xen/xen/evtchn.c 2012/12/28 06:29:56 1.66 +++ src/sys/arch/xen/xen/evtchn.c 2013/01/12 17:39:46 1.67 @@ -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 -__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; }