Fix xenevt to not call softint_schedule() above IPL_HIGH:
Register a ipl callback for IPL_HIGH. if the current ipl level is too high, just record the event in a bitmap, and record IPL_HIGH as pending. The callback will process the pending events.
This commit is contained in:
parent
b1eaff3725
commit
e3e720d87d
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: evtchn.h,v 1.14 2007/12/12 22:16:32 bouyer Exp $ */
|
||||
/* $NetBSD: evtchn.h,v 1.15 2008/02/19 13:25:53 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
@ -45,6 +45,9 @@ void call_evtchn_do_event(int, struct intrframe *);
|
||||
int event_set_handler(int, int (*func)(void *), void *, int, const char *);
|
||||
int event_remove_handler(int, int (*func)(void *), void *);
|
||||
|
||||
struct intrhand;
|
||||
void event_set_iplhandler(struct intrhand *, int);
|
||||
|
||||
extern int debug_port;
|
||||
extern int xen_debug_handler(void *);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: xen.h,v 1.26 2008/01/11 20:00:41 bouyer Exp $ */
|
||||
/* $NetBSD: xen.h,v 1.27 2008/02/19 13:25:53 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
@ -62,6 +62,7 @@ void xennetback_init(void);
|
||||
void xen_shm_init(void);
|
||||
|
||||
void xenevt_event(int);
|
||||
void xenevt_setipending(int, int);
|
||||
void xenevt_notify(void);
|
||||
|
||||
void idle_block(void);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: hypervisor_machdep.c,v 1.4 2007/12/20 23:46:11 ad Exp $ */
|
||||
/* $NetBSD: hypervisor_machdep.c,v 1.5 2008/02/19 13:25:53 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
@ -59,7 +59,7 @@
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.4 2007/12/20 23:46:11 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.5 2008/02/19 13:25:53 bouyer Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -141,8 +141,10 @@ stipending()
|
||||
ret = 1;
|
||||
}
|
||||
#ifdef DOM0OPS
|
||||
else
|
||||
xenevt_event(port);
|
||||
else {
|
||||
/* set pending event */
|
||||
xenevt_setipending(l1i, l2i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -218,8 +220,18 @@ do_hypervisor_callback(struct intrframe *regs)
|
||||
if (evtsource[port])
|
||||
call_evtchn_do_event(port, regs);
|
||||
#ifdef DOM0OPS
|
||||
else
|
||||
xenevt_event(port);
|
||||
else {
|
||||
if (ci->ci_ilevel < IPL_HIGH) {
|
||||
/* fast path */
|
||||
int oipl = ci->ci_ilevel;
|
||||
ci->ci_ilevel = IPL_HIGH;
|
||||
xenevt_event(port);
|
||||
ci->ci_ilevel = oipl;
|
||||
} else {
|
||||
/* set pending event */
|
||||
xenevt_setipending(l1i, l2i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: evtchn.c,v 1.30 2008/01/11 20:00:53 bouyer Exp $ */
|
||||
/* $NetBSD: evtchn.c,v 1.31 2008/02/19 13:25:53 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Manuel Bouyer.
|
||||
@ -64,7 +64,7 @@
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.30 2008/01/11 20:00:53 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.31 2008/02/19 13:25:53 bouyer Exp $");
|
||||
|
||||
#include "opt_xen.h"
|
||||
#include "isa.h"
|
||||
@ -449,10 +449,9 @@ int
|
||||
event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
|
||||
const char *evname)
|
||||
{
|
||||
struct iplsource *ipls;
|
||||
struct cpu_info *ci = &cpu_info_primary;
|
||||
struct evtsource *evts;
|
||||
struct intrhand *ih, **ihp;
|
||||
struct cpu_info *ci;
|
||||
int s;
|
||||
|
||||
#ifdef IRQ_DEBUG
|
||||
@ -482,22 +481,12 @@ event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
|
||||
ih->ih_evt_next = NULL;
|
||||
ih->ih_ipl_next = NULL;
|
||||
|
||||
ci = &cpu_info_primary;
|
||||
s = splhigh();
|
||||
if (ci->ci_isources[level] == NULL) {
|
||||
MALLOC(ipls, struct iplsource *, sizeof (struct iplsource),
|
||||
M_DEVBUF, M_WAITOK|M_ZERO);
|
||||
if (ipls == NULL)
|
||||
panic("can't allocate fixed interrupt source");
|
||||
ipls->ipl_recurse = xenev_stubs[level].ist_recurse;
|
||||
ipls->ipl_resume = xenev_stubs[level].ist_resume;
|
||||
ipls->ipl_handlers = ih;
|
||||
ci->ci_isources[level] = ipls;
|
||||
} else {
|
||||
ipls = ci->ci_isources[level];
|
||||
ih->ih_ipl_next = ipls->ipl_handlers;
|
||||
ipls->ipl_handlers = ih;
|
||||
}
|
||||
|
||||
/* register handler for spllower() */
|
||||
event_set_iplhandler(ih, level);
|
||||
|
||||
/* register handler for event channel */
|
||||
if (evtsource[evtch] == NULL) {
|
||||
MALLOC(evts, struct evtsource *, sizeof (struct evtsource),
|
||||
M_DEVBUF, M_WAITOK|M_ZERO);
|
||||
@ -536,6 +525,28 @@ event_set_handler(int evtch, int (*func)(void *), void *arg, int level,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
event_set_iplhandler(struct intrhand *ih, int level)
|
||||
{
|
||||
struct cpu_info *ci = &cpu_info_primary;
|
||||
struct iplsource *ipls;
|
||||
|
||||
if (ci->ci_isources[level] == NULL) {
|
||||
MALLOC(ipls, struct iplsource *, sizeof (struct iplsource),
|
||||
M_DEVBUF, M_WAITOK|M_ZERO);
|
||||
if (ipls == NULL)
|
||||
panic("can't allocate fixed interrupt source");
|
||||
ipls->ipl_recurse = xenev_stubs[level].ist_recurse;
|
||||
ipls->ipl_resume = xenev_stubs[level].ist_resume;
|
||||
ipls->ipl_handlers = ih;
|
||||
ci->ci_isources[level] = ipls;
|
||||
} else {
|
||||
ipls = ci->ci_isources[level];
|
||||
ih->ih_ipl_next = ipls->ipl_handlers;
|
||||
ipls->ipl_handlers = ih;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
event_remove_handler(int evtch, int (*func)(void *), void *arg)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: xenevt.c,v 1.20 2008/02/17 14:03:16 bouyer Exp $ */
|
||||
/* $NetBSD: xenevt.c,v 1.21 2008/02/19 13:25:53 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Manuel Bouyer.
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: xenevt.c,v 1.20 2008/02/17 14:03:16 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: xenevt.c,v 1.21 2008/02/19 13:25:53 bouyer Exp $");
|
||||
|
||||
#include "opt_xen.h"
|
||||
#include <sys/param.h>
|
||||
@ -136,22 +136,76 @@ STAILQ_HEAD(, xenevt_d) devevent_pending =
|
||||
static void xenevt_donotify(struct xenevt_d *);
|
||||
static void xenevt_record(struct xenevt_d *, evtchn_port_t);
|
||||
|
||||
/* pending events */
|
||||
long xenevt_ev1;
|
||||
long xenevt_ev2[NR_EVENT_CHANNELS];
|
||||
static int xenevt_processevt(void *);
|
||||
|
||||
/* called at boot time */
|
||||
void
|
||||
xenevtattach(int n)
|
||||
{
|
||||
struct intrhand *ih;
|
||||
int s;
|
||||
|
||||
devevent_sih = softint_establish(SOFTINT_SERIAL,
|
||||
(void (*)(void *))xenevt_notify, NULL);
|
||||
memset(devevent, 0, sizeof(devevent));
|
||||
xenevt_ev1 = 0;
|
||||
memset(xenevt_ev2, 0, sizeof(xenevt_ev2));
|
||||
|
||||
/* register a hanlder at splhigh, so that spllower() will call us */
|
||||
MALLOC(ih, struct intrhand *, sizeof (struct intrhand), M_DEVBUF,
|
||||
M_WAITOK|M_ZERO);
|
||||
if (ih == NULL)
|
||||
panic("can't allocate xenevt interrupt source");
|
||||
ih->ih_fun = xenevt_processevt;
|
||||
ih->ih_arg = NULL;
|
||||
ih->ih_ipl_next = NULL;
|
||||
s = splhigh();
|
||||
event_set_iplhandler(ih, IPL_HIGH);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/* event callback */
|
||||
/* register pending event - always called with interrupt disabled */
|
||||
void
|
||||
xenevt_setipending(int l1, int l2)
|
||||
{
|
||||
xen_atomic_setbits_l(&xenevt_ev1, l1);
|
||||
xen_atomic_setbits_l(&xenevt_ev2[l1], l2);
|
||||
curcpu()->ci_ipending |= 1 << IPL_HIGH;
|
||||
}
|
||||
|
||||
/* process pending events */
|
||||
static int
|
||||
xenevt_processevt(void *v)
|
||||
{
|
||||
long l1, l2;
|
||||
int l1i, l2i;
|
||||
int port;
|
||||
|
||||
l1 = xen_atomic_xchg(&xenevt_ev1, 0);
|
||||
while ((l1i = ffs(l1)) != 0) {
|
||||
l1i--;
|
||||
l1 &= ~(1 << l1i);
|
||||
l2 = xen_atomic_xchg(&xenevt_ev2[l1i], 0);
|
||||
while ((l2i = ffs(l2)) != 0) {
|
||||
l2i--;
|
||||
l2 &= ~(1 << l2i);
|
||||
port = (l1i << 5) + l2i;
|
||||
xenevt_event(port);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* event callback, called at splhigh() */
|
||||
void
|
||||
xenevt_event(int port)
|
||||
{
|
||||
struct xenevt_d *d;
|
||||
struct cpu_info *ci;
|
||||
|
||||
d = devevent[port];
|
||||
if (d != NULL) {
|
||||
@ -161,18 +215,11 @@ xenevt_event(int port)
|
||||
return;
|
||||
}
|
||||
|
||||
ci = curcpu();
|
||||
|
||||
if (ci->ci_ilevel < IPL_SOFTSERIAL) {
|
||||
/* fast and common path */
|
||||
xenevt_donotify(d);
|
||||
} else {
|
||||
simple_lock(&devevent_pending_lock);
|
||||
STAILQ_INSERT_TAIL(&devevent_pending, d, pendingq);
|
||||
simple_unlock(&devevent_pending_lock);
|
||||
d->pending = true;
|
||||
softint_schedule(devevent_sih);
|
||||
}
|
||||
simple_lock(&devevent_pending_lock);
|
||||
STAILQ_INSERT_TAIL(&devevent_pending, d, pendingq);
|
||||
simple_unlock(&devevent_pending_lock);
|
||||
d->pending = true;
|
||||
softint_schedule(devevent_sih);
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,7 +227,7 @@ void
|
||||
xenevt_notify()
|
||||
{
|
||||
|
||||
cli();
|
||||
int s = splhigh();
|
||||
simple_lock(&devevent_pending_lock);
|
||||
while (/* CONSTCOND */ 1) {
|
||||
struct xenevt_d *d;
|
||||
@ -191,16 +238,16 @@ xenevt_notify()
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&devevent_pending, pendingq);
|
||||
simple_unlock(&devevent_pending_lock);
|
||||
sti();
|
||||
splx(s);
|
||||
|
||||
d->pending = false;
|
||||
xenevt_donotify(d);
|
||||
|
||||
cli();
|
||||
s = splhigh();
|
||||
simple_lock(&devevent_pending_lock);
|
||||
}
|
||||
simple_unlock(&devevent_pending_lock);
|
||||
sti();
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user