Add polling support to the domain controller. Use this in xencons instead
of relying on the fact that the domain controller is still getting interrupts when xenconscn_getc()/xenconscn_putc() is called. Now that polling is fixed, move IPL_CTRL down between IPL_SOFTSERIAL and IPL_TTY, fixing port-xen/29999 by YAMAMOTO Takashi. Now that IPL_CTRL is low enouth, remove the softintr stuff from the domain controller, and call wakeup() directly. Thanks to YAMAMOTO Takashi and Christian Limpach for feedback and suggestions.
This commit is contained in:
parent
af8e900914
commit
4fe12d1c70
|
@ -136,4 +136,10 @@ int ctrl_if_transmitter_empty(void); /* !! DANGEROUS FUNCTION !! */
|
|||
*/
|
||||
void ctrl_if_discard_responses(void); /* !! DANGEROUS FUNCTION !! */
|
||||
|
||||
/*
|
||||
* message polling for use by xencons. Warning: this will reenable
|
||||
* interrupts at splhigh.
|
||||
*/
|
||||
void ctrl_if_console_poll(void);
|
||||
|
||||
#endif /* __ASM_XEN__CONTROL_IF_H__ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: intrdefs.h,v 1.1 2005/04/16 22:49:37 bouyer Exp $ */
|
||||
/* $NetBSD: intrdefs.h,v 1.2 2005/04/20 22:01:24 bouyer Exp $ */
|
||||
/* NetBSD intrdefs.h,v 1.3 2003/06/16 20:01:06 thorpej Exp */
|
||||
|
||||
#ifndef _XEN_INTRDEFS_H
|
||||
|
@ -29,17 +29,17 @@
|
|||
#define IPL_BIO 0x4 /* block I/O */
|
||||
#define IPL_NET 0x5 /* network */
|
||||
#define IPL_SOFTSERIAL 0x6 /* serial */
|
||||
#define IPL_TTY 0x7 /* terminal */
|
||||
#define IPL_VM 0x8 /* memory allocation */
|
||||
#define IPL_AUDIO 0x9 /* audio */
|
||||
#define IPL_CLOCK 0xa /* clock */
|
||||
#define IPL_CTRL 0x7 /* control events */
|
||||
#define IPL_TTY 0x8 /* terminal */
|
||||
#define IPL_VM 0x9 /* memory allocation */
|
||||
#define IPL_AUDIO 0xa /* audio */
|
||||
#define IPL_CLOCK 0xb /* clock */
|
||||
#define IPL_SCHED IPL_CLOCK
|
||||
#define IPL_HIGH 0xb /* everything */
|
||||
#define IPL_SERIAL 0xb /* serial */
|
||||
#define IPL_IPI 0xc /* inter-processor interrupts */
|
||||
#define IPL_DEBUG 0xd /* debug events */
|
||||
#define IPL_DIE 0xe /* die events */
|
||||
#define IPL_CTRL 0xf /* control events */
|
||||
#define IPL_HIGH 0xc /* everything */
|
||||
#define IPL_SERIAL 0xc /* serial */
|
||||
#define IPL_IPI 0xd /* inter-processor interrupts */
|
||||
#define IPL_DEBUG 0xe /* debug events */
|
||||
#define IPL_DIE 0xf /* die events */
|
||||
#define NIPL 16
|
||||
|
||||
/* Soft interrupt masks. */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ctrl_if.c,v 1.7 2005/04/17 21:11:30 bouyer Exp $ */
|
||||
/* $NetBSD: ctrl_if.c,v 1.8 2005/04/20 22:01:24 bouyer Exp $ */
|
||||
|
||||
/******************************************************************************
|
||||
* ctrl_if.c
|
||||
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ctrl_if.c,v 1.7 2005/04/17 21:11:30 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ctrl_if.c,v 1.8 2005/04/20 22:01:24 bouyer Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -63,8 +63,6 @@ static struct {
|
|||
static void __ctrl_if_rxmsg_deferred(void *unused);
|
||||
static void ctrl_if_kthread_create(void *);
|
||||
|
||||
static void *ctrl_if_softintr = NULL;
|
||||
|
||||
static int ctrl_if_tx_wait;
|
||||
static void __ctrl_if_tx_tasklet(unsigned long data);
|
||||
|
||||
|
@ -85,7 +83,8 @@ static void ctrl_if_rxmsg_default_handler(ctrl_msg_t *msg, unsigned long id)
|
|||
ctrl_if_send_response(msg);
|
||||
}
|
||||
|
||||
static void __ctrl_if_tx_tasklet(unsigned long data)
|
||||
static void
|
||||
__ctrl_if_tx_tasklet(unsigned long data)
|
||||
{
|
||||
control_if_t *ctrl_if = get_ctrl_if();
|
||||
ctrl_msg_t *msg;
|
||||
|
@ -157,7 +156,8 @@ __ctrl_if_rxmsg_deferred(void *unused)
|
|||
}
|
||||
}
|
||||
|
||||
static void __ctrl_if_rx_tasklet(unsigned long data)
|
||||
static void
|
||||
__ctrl_if_rx_tasklet(unsigned long data)
|
||||
{
|
||||
control_if_t *ctrl_if = get_ctrl_if();
|
||||
ctrl_msg_t msg, *pmsg;
|
||||
|
@ -179,7 +179,12 @@ static void __ctrl_if_rx_tasklet(unsigned long data)
|
|||
|
||||
if ( msg.length != 0 )
|
||||
memcpy(msg.msg, pmsg->msg, msg.length);
|
||||
|
||||
/*
|
||||
* increase ctrl_if_rx_req_cons now,
|
||||
* as the handler may end up calling __ctrl_if_rx_tasklet() again
|
||||
* though the console polling code.
|
||||
*/
|
||||
ctrl_if_rx_req_cons++;
|
||||
if ( x86_atomic_test_bit(
|
||||
(unsigned long *)&ctrl_if_rxmsg_blocking_context,
|
||||
msg.type) )
|
||||
|
@ -187,30 +192,35 @@ static void __ctrl_if_rx_tasklet(unsigned long data)
|
|||
&msg, offsetof(ctrl_msg_t, msg) + msg.length);
|
||||
else
|
||||
(*ctrl_if_rxmsg_handler[msg.type])(&msg, 0);
|
||||
|
||||
ctrl_if_rx_req_cons++;
|
||||
/* update rp, in case the console polling code was used */
|
||||
rp = ctrl_if->rx_req_prod;
|
||||
x86_lfence(); /* Ensure we see all requests up to 'rp'. */
|
||||
}
|
||||
|
||||
if ( dp != ctrl_if_rxmsg_deferred_prod )
|
||||
{
|
||||
__insn_barrier();
|
||||
ctrl_if_rxmsg_deferred_prod = dp;
|
||||
if (ctrl_if_softintr)
|
||||
softintr_schedule(ctrl_if_softintr);
|
||||
wakeup(&ctrl_if_rxmsg_deferred_cons);
|
||||
}
|
||||
}
|
||||
|
||||
static int ctrl_if_interrupt(void *arg)
|
||||
{
|
||||
control_if_t *ctrl_if = get_ctrl_if();
|
||||
int ret = 0;
|
||||
|
||||
if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod )
|
||||
if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod ) {
|
||||
ret = 1;
|
||||
__ctrl_if_tx_tasklet(0);
|
||||
}
|
||||
|
||||
if ( ctrl_if_rx_req_cons != ctrl_if->rx_req_prod )
|
||||
if ( ctrl_if_rx_req_cons != ctrl_if->rx_req_prod ) {
|
||||
ret = 1;
|
||||
__ctrl_if_rx_tasklet(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -227,16 +237,21 @@ ctrl_if_send_message_noblock(
|
|||
save_and_cli(flags);
|
||||
simple_lock(&ctrl_if_lock);
|
||||
|
||||
if ( TX_FULL(ctrl_if) )
|
||||
while ( TX_FULL(ctrl_if) )
|
||||
{
|
||||
simple_unlock(&ctrl_if_lock);
|
||||
restore_flags(flags);
|
||||
s = splhigh();
|
||||
if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod )
|
||||
if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod ) {
|
||||
__ctrl_if_tx_tasklet(0);
|
||||
splx(s);
|
||||
save_and_cli(flags);
|
||||
simple_lock(&ctrl_if_lock);
|
||||
} else {
|
||||
splx(s);
|
||||
return EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
msg->id = 0xFF;
|
||||
if ( hnd != NULL )
|
||||
|
@ -449,15 +464,6 @@ ctrl_if_unregister_receiver(
|
|||
restore_flags(flags);
|
||||
|
||||
/* Ensure that @hnd will not be executed after this function returns. */
|
||||
if (ctrl_if_softintr)
|
||||
softintr_schedule(ctrl_if_softintr);
|
||||
}
|
||||
|
||||
static void
|
||||
ctrl_if_softintr_handler(void *arg)
|
||||
{
|
||||
|
||||
if ( ctrl_if_rxmsg_deferred_cons != ctrl_if_rxmsg_deferred_prod )
|
||||
wakeup(&ctrl_if_rxmsg_deferred_cons);
|
||||
}
|
||||
|
||||
|
@ -500,7 +506,7 @@ void ctrl_if_resume(void)
|
|||
aprint_verbose("Domain controller: using event channel %d\n",
|
||||
ctrl_if_evtchn);
|
||||
|
||||
event_set_handler(ctrl_if_evtchn, &ctrl_if_interrupt, NULL, IPL_CTRL,
|
||||
event_set_handler(ctrl_if_evtchn, &ctrl_if_interrupt, NULL, IPL_SCHED,
|
||||
"ctrlev");
|
||||
hypervisor_enable_event(ctrl_if_evtchn);
|
||||
}
|
||||
|
@ -523,9 +529,6 @@ void ctrl_if_init(void)
|
|||
if (ctrl_if_evtchn == -1)
|
||||
ctrl_if_early_init();
|
||||
|
||||
ctrl_if_softintr = softintr_establish(IPL_SOFTNET,
|
||||
ctrl_if_softintr_handler, NULL);
|
||||
|
||||
kthread_create(ctrl_if_kthread_create, NULL);
|
||||
|
||||
ctrl_if_resume();
|
||||
|
@ -559,3 +562,29 @@ void ctrl_if_discard_responses(void)
|
|||
ctrl_if_tx_resp_cons = get_ctrl_if()->tx_resp_prod;
|
||||
}
|
||||
|
||||
/*
|
||||
* polling functions, for xencons's benefit
|
||||
* We need to enable events before calling HYPERVISOR_block().
|
||||
* Do this at a high enouth IPL so that no other interrupt will interfere
|
||||
* with our polling.
|
||||
*/
|
||||
|
||||
void
|
||||
ctrl_if_console_poll(void)
|
||||
{
|
||||
int s = splhigh();
|
||||
|
||||
/*
|
||||
* Unmask the ctrl event, and block waiting for an interrupt.
|
||||
* Note that the event we get may not be for the console.
|
||||
* In this case, the console code will call us again.
|
||||
*/
|
||||
|
||||
while (ctrl_if_interrupt(NULL) == 0) {
|
||||
/* enable interrupts. */
|
||||
hypervisor_clear_event(ctrl_if_evtchn);
|
||||
hypervisor_unmask_event(ctrl_if_evtchn);
|
||||
HYPERVISOR_block();
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: xencons.c,v 1.7 2005/04/17 14:50:11 bouyer Exp $ */
|
||||
/* $NetBSD: xencons.c,v 1.8 2005/04/20 22:01:24 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: xencons.c,v 1.7 2005/04/17 14:50:11 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: xencons.c,v 1.8 2005/04/20 22:01:24 bouyer Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
@ -461,7 +461,7 @@ xenconscn_getc(dev_t dev)
|
|||
|
||||
while (xencons_console_device->buf_write ==
|
||||
xencons_console_device->buf_read) {
|
||||
HYPERVISOR_yield();
|
||||
ctrl_if_console_poll();
|
||||
}
|
||||
|
||||
ret = xencons_console_device->buf[xencons_console_device->buf_read];
|
||||
|
@ -490,9 +490,7 @@ xenconscn_putc(dev_t dev, int c)
|
|||
msg.length = 1;
|
||||
msg.msg[0] = c;
|
||||
while (ctrl_if_send_message_noblock(&msg, NULL, 0) == EAGAIN) {
|
||||
HYPERVISOR_yield();
|
||||
/* XXX check return value and queue wait for space
|
||||
* thread/softint */
|
||||
ctrl_if_console_poll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue