Module Name: src Committed By: cherry Date: Sun Nov 25 07:48:47 UTC 2012
Modified Files: src/sys/arch/xen/xen: evtchn.c Log Message: hypervisor_set_ipending() should not set the pending flag across cpus. The reason for this is that the pending flag update is not atomic, or protected by a lock. Since its current (mis)use in evtchn_do_event() across cpus is to notify the remote cpu of an interrupt, we use hypervisor_send_event() instead, to trigger an event on the remote cpu, which in turn invokes evtchn_do_event() on that cpu and DTRT on it. On the local cpu, we protect hypervisor_set_ipending() from re-entry via cli(). Remove a redundant and unprotected call to hypervisor_set_ipending(). Thanks to jym@ for spotting this discrepancy while reviewing a related patch. See: http://mail-index.netbsd.org/tech-kern/2012/11/12/msg014374.html To generate a diff of this commit: cvs rdiff -u -r1.62 -r1.63 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/xen/evtchn.c diff -u src/sys/arch/xen/xen/evtchn.c:1.62 src/sys/arch/xen/xen/evtchn.c:1.63 --- src/sys/arch/xen/xen/evtchn.c:1.62 Sun Feb 12 14:24:08 2012 +++ src/sys/arch/xen/xen/evtchn.c Sun Nov 25 07:48:46 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: evtchn.c,v 1.62 2012/02/12 14:24:08 jym Exp $ */ +/* $NetBSD: evtchn.c,v 1.63 2012/11/25 07:48:46 cherry Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -54,7 +54,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.62 2012/02/12 14:24:08 jym Exp $"); +__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.63 2012/11/25 07:48:46 cherry Exp $"); #include "opt_xen.h" #include "isa.h" @@ -298,15 +298,12 @@ evtchn_do_event(int evtch, struct intrfr ih = evtsource[evtch]->ev_handlers; while (ih != NULL) { if (ih->ih_cpu != ci) { - hypervisor_set_ipending(ih->ih_cpu, 1 << ih->ih_level, - evtch >> LONG_SHIFT, evtch & LONG_MASK); + hypervisor_send_event(ih->ih_cpu, evtch); 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);