Thu Mar 13 22:04:57 2008 UTC ()
Implement a C version of splx() in evtchn_do_event(). using plain splx()
here will reenable interrupts as a side effect, and we don't want it here.

It could cause some event handlers to run twice (which should be harmless),
and trap() to be called on the wrong LWP in doreti_checkast (which can
probably cause some damage).


(bouyer)
diff -r1.32 -r1.33 src/sys/arch/xen/xen/evtchn.c

cvs diff -r1.32 -r1.33 src/sys/arch/xen/xen/evtchn.c (expand / switch to unified diff)

--- src/sys/arch/xen/xen/evtchn.c 2008/02/19 19:50:53 1.32
+++ src/sys/arch/xen/xen/evtchn.c 2008/03/13 22:04:57 1.33
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: evtchn.c,v 1.32 2008/02/19 19:50:53 bouyer Exp $ */ 1/* $NetBSD: evtchn.c,v 1.33 2008/03/13 22:04:57 bouyer Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Manuel Bouyer. 4 * Copyright (c) 2006 Manuel Bouyer.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software 14 * 3. All advertising materials mentioning features or use of this software
@@ -54,27 +54,27 @@ @@ -54,27 +54,27 @@
54 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 54 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 55 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 56 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
57 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 57 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
58 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 61 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
62 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63 */ 63 */
64 64
65 65
66#include <sys/cdefs.h> 66#include <sys/cdefs.h>
67__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.32 2008/02/19 19:50:53 bouyer Exp $"); 67__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.33 2008/03/13 22:04:57 bouyer Exp $");
68 68
69#include "opt_xen.h" 69#include "opt_xen.h"
70#include "isa.h" 70#include "isa.h"
71#include "pci.h" 71#include "pci.h"
72 72
73#include <sys/param.h> 73#include <sys/param.h>
74#include <sys/kernel.h> 74#include <sys/kernel.h>
75#include <sys/systm.h> 75#include <sys/systm.h>
76#include <sys/proc.h> 76#include <sys/proc.h>
77#include <sys/malloc.h> 77#include <sys/malloc.h>
78#include <sys/reboot.h> 78#include <sys/reboot.h>
79#include <sys/simplelock.h> 79#include <sys/simplelock.h>
80 80
@@ -180,26 +180,28 @@ init_events() @@ -180,26 +180,28 @@ init_events()
180 180
181 x86_enable_intr(); /* at long last... */ 181 x86_enable_intr(); /* at long last... */
182} 182}
183 183
184unsigned int 184unsigned int
185evtchn_do_event(int evtch, struct intrframe *regs) 185evtchn_do_event(int evtch, struct intrframe *regs)
186{ 186{
187 struct cpu_info *ci; 187 struct cpu_info *ci;
188 int ilevel; 188 int ilevel;
189 struct intrhand *ih; 189 struct intrhand *ih;
190 int (*ih_fun)(void *, void *); 190 int (*ih_fun)(void *, void *);
191 extern struct uvmexp uvmexp; 191 extern struct uvmexp uvmexp;
192 u_int32_t iplmask; 192 u_int32_t iplmask;
 193 int i;
 194 u_int32_t iplbit;
193 195
194#ifdef DIAGNOSTIC 196#ifdef DIAGNOSTIC
195 if (evtch >= NR_EVENT_CHANNELS) { 197 if (evtch >= NR_EVENT_CHANNELS) {
196 printf("event number %d > NR_IRQS\n", evtch); 198 printf("event number %d > NR_IRQS\n", evtch);
197 panic("evtchn_do_event"); 199 panic("evtchn_do_event");
198 } 200 }
199#endif 201#endif
200 202
201#ifdef IRQ_DEBUG 203#ifdef IRQ_DEBUG
202 if (evtch == IRQ_DEBUG) 204 if (evtch == IRQ_DEBUG)
203 printf("evtchn_do_event: evtch %d\n", evtch); 205 printf("evtchn_do_event: evtch %d\n", evtch);
204#endif 206#endif
205 ci = &cpu_info_primary; 207 ci = &cpu_info_primary;
@@ -243,42 +245,69 @@ evtchn_do_event(int evtch, struct intrfr @@ -243,42 +245,69 @@ evtchn_do_event(int evtch, struct intrfr
243 while (ih != NULL) { 245 while (ih != NULL) {
244 if (ih->ih_level <= ilevel) { 246 if (ih->ih_level <= ilevel) {
245#ifdef IRQ_DEBUG 247#ifdef IRQ_DEBUG
246 if (evtch == IRQ_DEBUG) 248 if (evtch == IRQ_DEBUG)
247 printf("ih->ih_level %d <= ilevel %d\n", ih->ih_level, ilevel); 249 printf("ih->ih_level %d <= ilevel %d\n", ih->ih_level, ilevel);
248#endif 250#endif
249#ifdef MULTIPROCESSOR 251#ifdef MULTIPROCESSOR
250 x86_intunlock(regs); 252 x86_intunlock(regs);
251#endif 253#endif
252 cli(); 254 cli();
253 hypervisor_set_ipending(iplmask, 255 hypervisor_set_ipending(iplmask,
254 evtch >> LONG_SHIFT, evtch & LONG_MASK); 256 evtch >> LONG_SHIFT, evtch & LONG_MASK);
255 /* leave masked */ 257 /* leave masked */
256 splx(ilevel); 258 goto splx;
257 return 0; 
258 } 259 }
259 iplmask &= ~IUNMASK(ci, ih->ih_level); 260 iplmask &= ~IUNMASK(ci, ih->ih_level);
260 ci->ci_ilevel = ih->ih_level; 261 ci->ci_ilevel = ih->ih_level;
261 ih_fun = (void *)ih->ih_fun; 262 ih_fun = (void *)ih->ih_fun;
262 ih_fun(ih->ih_arg, regs); 263 ih_fun(ih->ih_arg, regs);
263 ih = ih->ih_evt_next; 264 ih = ih->ih_evt_next;
264 } 265 }
265 cli(); 266 cli();
266#ifdef MULTIPROCESSOR 267#ifdef MULTIPROCESSOR
267 x86_intunlock(regs); 268 x86_intunlock(regs);
268#endif 269#endif
269 hypervisor_enable_event(evtch); 270 hypervisor_enable_event(evtch);
270 splx(ilevel); 271splx:
271 272 /*
 273 * C version of spllower(). ASTs will be checked when
 274 * hypevisor_callback() exits, so no need to check here.
 275 */
 276 iplbit = 1 << (NIPL - 1);
 277 i = (NIPL - 1);
 278 while ((iplmask = (IUNMASK(ci, ilevel) & ci->ci_ipending)) != 0) {
 279 if (iplbit == 0) {
 280 /* another pending ipl went in while running a handler*/
 281 iplbit = 1 << (NIPL - 1);
 282 i = (NIPL - 1);
 283 }
 284 if (iplmask & iplbit) {
 285 ci->ci_ipending &= ~iplbit;
 286 KASSERT(i > ilevel);
 287 ci->ci_ilevel = i;
 288 for (ih = ci->ci_isources[i]->ipl_handlers; ih != NULL;
 289 ih = ih->ih_ipl_next) {
 290 sti();
 291 ih_fun = (void *)ih->ih_fun;
 292 ih_fun(ih->ih_arg, regs);
 293 cli();
 294 }
 295 hypervisor_enable_ipl(i);
 296 }
 297 i--;
 298 iplbit >>= 1;
 299 }
 300 ci->ci_ilevel = ilevel;
272 return 0; 301 return 0;
273} 302}
274 303
275int 304int
276bind_virq_to_evtch(int virq) 305bind_virq_to_evtch(int virq)
277{ 306{
278 evtchn_op_t op; 307 evtchn_op_t op;
279 int evtchn, s; 308 int evtchn, s;
280 309
281 s = splhigh(); 310 s = splhigh();
282 simple_lock(&irq_mapping_update_lock); 311 simple_lock(&irq_mapping_update_lock);
283 312
284 evtchn = virq_to_evtch[virq]; 313 evtchn = virq_to_evtch[virq];