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:
bouyer 2005-04-20 22:01:24 +00:00
parent af8e900914
commit 4fe12d1c70
4 changed files with 92 additions and 59 deletions

View File

@ -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__ */

View File

@ -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
@ -25,35 +25,35 @@
#define IPL_NONE 0x0 /* nothing */
#define IPL_SOFTCLOCK 0x1 /* timeouts */
#define IPL_SOFTNET 0x2 /* protocol stacks */
#define IPL_SOFTXENEVT 0x3 /* /dev/xenevt */
#define IPL_SOFTXENEVT 0x3 /* /dev/xenevt */
#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_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_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 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. */
#define SIR_CLOCK IPL_SOFTCLOCK
#define SIR_NET IPL_SOFTNET
#define SIR_SERIAL IPL_SOFTSERIAL
#define SIR_XENEVT IPL_SOFTXENEVT
#define SIR_CLOCK IPL_SOFTCLOCK
#define SIR_NET IPL_SOFTNET
#define SIR_SERIAL IPL_SOFTSERIAL
#define SIR_XENEVT IPL_SOFTXENEVT
#define IREENT_MAGIC 0x18041969
/* Interrupt sharing types (for ISA) */
#define IST_NONE 0 /* none */
#define IST_PULSE 1 /* pulsed */
#define IST_EDGE 2 /* edge-triggered */
#define IST_LEVEL 3 /* level-triggered */
#define IST_NONE 0 /* none */
#define IST_PULSE 1 /* pulsed */
#define IST_EDGE 2 /* edge-triggered */
#define IST_LEVEL 3 /* level-triggered */
#endif /* _XEN_INTRDEFS_H */

View File

@ -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,15 +237,20 @@ 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);
return EAGAIN;
splx(s);
save_and_cli(flags);
simple_lock(&ctrl_if_lock);
} else {
splx(s);
return EAGAIN;
}
}
msg->id = 0xFF;
@ -449,16 +464,7 @@ 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);
wakeup(&ctrl_if_rxmsg_deferred_cons);
}
#ifdef notyet
@ -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);
}

View File

@ -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();
}
}
}