ia64/xen-unstable

changeset 6492:8fe8a99b1c2a

New console transport and update xenconsoled.
Add a new console interface using a seperate shared page and event channel
instead of passing the console input/output over control messages.
Update xenconsoled to use the new console interface.
Make xenconsoled garbage collect dying domains by subscribing to
the domain exception virq.
Signed-off-by: Robert Read <robert@xensource.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Aug 30 16:14:53 2005 +0000 (2005-08-30)
parents e69cbfee4011
children b043928b0873
files linux-2.6-xen-sparse/drivers/xen/console/Makefile linux-2.6-xen-sparse/drivers/xen/console/console.c linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h tools/console/daemon/io.c tools/console/daemon/utils.c tools/libxc/xc_linux_build.c tools/libxc/xenguest.h tools/python/xen/lowlevel/xc/xc.c tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/image.py xen/include/public/xen.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/console/Makefile	Tue Aug 30 08:47:51 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/console/Makefile	Tue Aug 30 16:14:53 2005 +0000
     1.3 @@ -1,2 +1,2 @@
     1.4  
     1.5 -obj-y	:= console.o
     1.6 +obj-y	:= console.o xencons_ring.o
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c	Tue Aug 30 08:47:51 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c	Tue Aug 30 16:14:53 2005 +0000
     2.3 @@ -51,8 +51,8 @@
     2.4  #include <asm-xen/xen-public/event_channel.h>
     2.5  #include <asm-xen/hypervisor.h>
     2.6  #include <asm-xen/evtchn.h>
     2.7 -#include <asm-xen/ctrl_if.h>
     2.8  
     2.9 +#include "xencons_ring.h"
    2.10  /*
    2.11   * Modes:
    2.12   *  'xencons=off'  [XC_OFF]:     Console is disabled.
    2.13 @@ -118,13 +118,6 @@ static spinlock_t xencons_lock = SPIN_LO
    2.14  /* Common transmit-kick routine. */
    2.15  static void __xencons_tx_flush(void);
    2.16  
    2.17 -/* This task is used to defer sending console data until there is space. */
    2.18 -static void xencons_tx_flush_task_routine(void *data);
    2.19 -
    2.20 -static DECLARE_TQUEUE(xencons_tx_flush_task, 
    2.21 -                      xencons_tx_flush_task_routine,
    2.22 -                      NULL);
    2.23 -
    2.24  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
    2.25  static struct tty_driver *xencons_driver;
    2.26  #else
    2.27 @@ -264,39 +257,22 @@ asmlinkage int xprintk(const char *fmt, 
    2.28  /*** Forcibly flush console data before dying. ***/
    2.29  void xencons_force_flush(void)
    2.30  {
    2.31 -    ctrl_msg_t msg;
    2.32      int        sz;
    2.33  
    2.34      /* Emergency console is synchronous, so there's nothing to flush. */
    2.35      if ( xen_start_info.flags & SIF_INITDOMAIN )
    2.36          return;
    2.37  
    2.38 -    /*
    2.39 -     * We use dangerous control-interface functions that require a quiescent
    2.40 -     * system and no interrupts. Try to ensure this with a global cli().
    2.41 -     */
    2.42 -    local_irq_disable(); /* XXXsmp */
    2.43  
    2.44      /* Spin until console data is flushed through to the domain controller. */
    2.45 -    while ( (wc != wp) && !ctrl_if_transmitter_empty() )
    2.46 +    while ( (wc != wp) )
    2.47      {
    2.48 -        /* Interrupts are disabled -- we must manually reap responses. */
    2.49 -        ctrl_if_discard_responses();
    2.50 -
    2.51 +	int sent = 0;
    2.52          if ( (sz = wp - wc) == 0 )
    2.53              continue;
    2.54 -        if ( sz > sizeof(msg.msg) )
    2.55 -            sz = sizeof(msg.msg);
    2.56 -        if ( sz > (wbuf_size - WBUF_MASK(wc)) )
    2.57 -            sz = wbuf_size - WBUF_MASK(wc);
    2.58 -
    2.59 -        msg.type    = CMSG_CONSOLE;
    2.60 -        msg.subtype = CMSG_CONSOLE_DATA;
    2.61 -        msg.length  = sz;
    2.62 -        memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
    2.63 -            
    2.64 -        if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
    2.65 -            wc += sz;
    2.66 +	sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
    2.67 +	if (sent > 0)
    2.68 +	    wc += sent;
    2.69      }
    2.70  }
    2.71  
    2.72 @@ -320,7 +296,7 @@ static int xencons_priv_irq;
    2.73  static char x_char;
    2.74  
    2.75  /* Non-privileged receive callback. */
    2.76 -static void xencons_rx(ctrl_msg_t *msg, unsigned long id)
    2.77 +static void xencons_rx(char *buf, unsigned len)
    2.78  {
    2.79      int           i;
    2.80      unsigned long flags;
    2.81 @@ -328,21 +304,18 @@ static void xencons_rx(ctrl_msg_t *msg, 
    2.82      spin_lock_irqsave(&xencons_lock, flags);
    2.83      if ( xencons_tty != NULL )
    2.84      {
    2.85 -        for ( i = 0; i < msg->length; i++ )
    2.86 -            tty_insert_flip_char(xencons_tty, msg->msg[i], 0);
    2.87 +        for ( i = 0; i < len; i++ )
    2.88 +            tty_insert_flip_char(xencons_tty, buf[i], 0);
    2.89          tty_flip_buffer_push(xencons_tty);
    2.90      }
    2.91      spin_unlock_irqrestore(&xencons_lock, flags);
    2.92  
    2.93 -    msg->length = 0;
    2.94 -    ctrl_if_send_response(msg);
    2.95  }
    2.96  
    2.97  /* Privileged and non-privileged transmit worker. */
    2.98  static void __xencons_tx_flush(void)
    2.99  {
   2.100      int        sz, work_done = 0;
   2.101 -    ctrl_msg_t msg;
   2.102  
   2.103      if ( xen_start_info.flags & SIF_INITDOMAIN )
   2.104      {
   2.105 @@ -367,38 +340,23 @@ static void __xencons_tx_flush(void)
   2.106      {
   2.107          while ( x_char )
   2.108          {
   2.109 -            msg.type    = CMSG_CONSOLE;
   2.110 -            msg.subtype = CMSG_CONSOLE_DATA;
   2.111 -            msg.length  = 1;
   2.112 -            msg.msg[0]  = x_char;
   2.113 -
   2.114 -            if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
   2.115 -                x_char = 0;
   2.116 -            else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
   2.117 -                break;
   2.118 -
   2.119 -            work_done = 1;
   2.120 +	    if (xencons_ring_send(&x_char, 1) == 1) {
   2.121 +		x_char = 0;
   2.122 +		work_done = 1;
   2.123 +	    }
   2.124          }
   2.125  
   2.126          while ( wc != wp )
   2.127          {
   2.128 +	    int sent;
   2.129              sz = wp - wc;
   2.130 -            if ( sz > sizeof(msg.msg) )
   2.131 -                sz = sizeof(msg.msg);
   2.132 -            if ( sz > (wbuf_size - WBUF_MASK(wc)) )
   2.133 -                sz = wbuf_size - WBUF_MASK(wc);
   2.134 -
   2.135 -            msg.type    = CMSG_CONSOLE;
   2.136 -            msg.subtype = CMSG_CONSOLE_DATA;
   2.137 -            msg.length  = sz;
   2.138 -            memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
   2.139 -            
   2.140 -            if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
   2.141 -                wc += sz;
   2.142 -            else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
   2.143 -                break;
   2.144 -
   2.145 -            work_done = 1;
   2.146 +	    if ( sz > (wbuf_size - WBUF_MASK(wc)) )
   2.147 +		sz = wbuf_size - WBUF_MASK(wc);
   2.148 +	    sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
   2.149 +	    if ( sent > 0 ) {
   2.150 +		wc += sent;
   2.151 +		work_done = 1;
   2.152 +	    }
   2.153          }
   2.154      }
   2.155  
   2.156 @@ -411,15 +369,6 @@ static void __xencons_tx_flush(void)
   2.157      }
   2.158  }
   2.159  
   2.160 -/* Non-privileged transmit kicker. */
   2.161 -static void xencons_tx_flush_task_routine(void *data)
   2.162 -{
   2.163 -    unsigned long flags;
   2.164 -    spin_lock_irqsave(&xencons_lock, flags);
   2.165 -    __xencons_tx_flush();
   2.166 -    spin_unlock_irqrestore(&xencons_lock, flags);
   2.167 -}
   2.168 -
   2.169  /* Privileged receive callback and transmit kicker. */
   2.170  static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id,
   2.171                                            struct pt_regs *regs)
   2.172 @@ -726,6 +675,8 @@ static int __init xencons_init(void)
   2.173      if ( xc_mode == XC_OFF )
   2.174          return 0;
   2.175  
   2.176 +    xencons_ring_init();
   2.177 +
   2.178  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   2.179      xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ? 
   2.180                                        1 : MAX_NR_CONSOLES);
   2.181 @@ -802,7 +753,8 @@ static int __init xencons_init(void)
   2.182      }
   2.183      else
   2.184      {
   2.185 -        (void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0);
   2.186 +	
   2.187 +	xencons_ring_register_receiver(xencons_rx);
   2.188      }
   2.189  
   2.190      printk("Xen virtual console successfully installed as %s%d\n",
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c	Tue Aug 30 16:14:53 2005 +0000
     3.3 @@ -0,0 +1,124 @@
     3.4 +#include <linux/version.h>
     3.5 +#include <linux/module.h>
     3.6 +#include <linux/errno.h>
     3.7 +#include <linux/signal.h>
     3.8 +#include <linux/sched.h>
     3.9 +#include <linux/interrupt.h>
    3.10 +#include <linux/tty.h>
    3.11 +#include <linux/tty_flip.h>
    3.12 +#include <linux/serial.h>
    3.13 +#include <linux/major.h>
    3.14 +#include <linux/ptrace.h>
    3.15 +#include <linux/ioport.h>
    3.16 +#include <linux/mm.h>
    3.17 +#include <linux/slab.h>
    3.18 +
    3.19 +#include <asm-xen/hypervisor.h>
    3.20 +#include <asm-xen/evtchn.h>
    3.21 +#include <linux/wait.h>
    3.22 +#include <linux/interrupt.h>
    3.23 +#include <linux/sched.h>
    3.24 +#include <linux/err.h>
    3.25 +#include "xencons_ring.h"
    3.26 +
    3.27 +
    3.28 +struct ring_head
    3.29 +{
    3.30 +	u32 cons;
    3.31 +	u32 prod;
    3.32 +	char buf[0];
    3.33 +} __attribute__((packed));
    3.34 +
    3.35 +
    3.36 +#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
    3.37 +#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
    3.38 +#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
    3.39 +
    3.40 +static inline struct ring_head *outring(void)
    3.41 +{
    3.42 +	return machine_to_virt(xen_start_info.console_mfn << PAGE_SHIFT);
    3.43 +}
    3.44 +
    3.45 +static inline struct ring_head *inring(void)
    3.46 +{
    3.47 +	return machine_to_virt(xen_start_info.console_mfn << PAGE_SHIFT)
    3.48 +		+ PAGE_SIZE/2;
    3.49 +}
    3.50 +
    3.51 +
    3.52 +/* don't block -  write as much as possible and return */
    3.53 +static int __xencons_ring_send(struct ring_head *ring, const char *data, unsigned len)
    3.54 +{
    3.55 +	int copied = 0;
    3.56 +
    3.57 +	mb();
    3.58 +	while (copied < len && !XENCONS_FULL(ring)) {
    3.59 +		ring->buf[XENCONS_IDX(ring->prod)] = data[copied];
    3.60 +		ring->prod++;
    3.61 +		copied++;
    3.62 +	}
    3.63 +	mb();
    3.64 +
    3.65 +	return copied;
    3.66 +}
    3.67 +
    3.68 +int xencons_ring_send(const char *data, unsigned len)
    3.69 +{
    3.70 +	struct ring_head *out = outring();
    3.71 +	int sent = 0;
    3.72 +	
    3.73 +	sent = __xencons_ring_send(out, data, len);
    3.74 +	notify_via_evtchn(xen_start_info.console_evtchn);
    3.75 +	return sent;
    3.76 +
    3.77 +}	
    3.78 +
    3.79 +
    3.80 +static xencons_receiver_func *xencons_receiver;
    3.81 +
    3.82 +static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
    3.83 +{
    3.84 +	struct ring_head *ring = inring();
    3.85 +	while (ring->cons < ring->prod) {
    3.86 +		if (xencons_receiver != NULL) {
    3.87 +			xencons_receiver(ring->buf + XENCONS_IDX(ring->cons),
    3.88 +					 1);
    3.89 +		}
    3.90 +		ring->cons++;
    3.91 +	}
    3.92 +	return IRQ_HANDLED;
    3.93 +}
    3.94 +
    3.95 +void xencons_ring_register_receiver(xencons_receiver_func *f)
    3.96 +{
    3.97 +	xencons_receiver = f;
    3.98 +}
    3.99 +
   3.100 +int xencons_ring_init(void)
   3.101 +{
   3.102 +	int err;
   3.103 +
   3.104 +	if (!xen_start_info.console_evtchn)
   3.105 +		return 0;
   3.106 +
   3.107 +	err = bind_evtchn_to_irqhandler(
   3.108 +		xen_start_info.console_evtchn, handle_input,
   3.109 +		0, "xencons", inring());
   3.110 +	if (err) {
   3.111 +		xprintk(KERN_ERR "XEN console request irq failed %i\n", err);
   3.112 +		unbind_evtchn_from_irq(xen_start_info.console_evtchn);
   3.113 +		return err;
   3.114 +	}
   3.115 +
   3.116 +	return 0;
   3.117 +}
   3.118 +
   3.119 +void xencons_suspend_comms(void)
   3.120 +{
   3.121 +
   3.122 +	if (!xen_start_info.console_evtchn)
   3.123 +		return;
   3.124 +
   3.125 +	unbind_evtchn_from_irqhandler(xen_start_info.console_evtchn, inring());
   3.126 +}
   3.127 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h	Tue Aug 30 16:14:53 2005 +0000
     4.3 @@ -0,0 +1,13 @@
     4.4 +#ifndef _XENCONS_RING_H
     4.5 +#define _XENCONS_RING_H
     4.6 +
     4.7 +asmlinkage int xprintk(const char *fmt, ...);
     4.8 +
     4.9 +
    4.10 +int xencons_ring_init(void);
    4.11 +int xencons_ring_send(const char *data, unsigned len);
    4.12 +
    4.13 +typedef void (xencons_receiver_func)(char *buf, unsigned len);
    4.14 +void xencons_ring_register_receiver(xencons_receiver_func *f);
    4.15 +
    4.16 +#endif /* _XENCONS_RING_H */
     5.1 --- a/tools/console/daemon/io.c	Tue Aug 30 08:47:51 2005 +0000
     5.2 +++ b/tools/console/daemon/io.c	Tue Aug 30 16:14:53 2005 +0000
     5.3 @@ -36,6 +36,9 @@
     5.4  #include <fcntl.h>
     5.5  #include <unistd.h>
     5.6  #include <termios.h>
     5.7 +#include <stdarg.h>
     5.8 +#include <sys/ioctl.h>
     5.9 +#include <sys/mman.h>
    5.10  
    5.11  #define MAX(a, b) (((a) > (b)) ? (a) : (b))
    5.12  #define MIN(a, b) (((a) < (b)) ? (a) : (b))
    5.13 @@ -48,26 +51,67 @@ struct buffer
    5.14  	size_t max_capacity;
    5.15  };
    5.16  
    5.17 -static void buffer_append(struct buffer *buffer, const void *data, size_t size)
    5.18 +struct domain
    5.19 +{
    5.20 +	int domid;
    5.21 +	int tty_fd;
    5.22 +	bool is_dead;
    5.23 +	struct buffer buffer;
    5.24 +	struct domain *next;
    5.25 +	unsigned long mfn;
    5.26 +	int local_port;
    5.27 +	int remote_port;
    5.28 +	char *page;
    5.29 +	int evtchn_fd;
    5.30 +};
    5.31 +
    5.32 +static struct domain *dom_head;
    5.33 +
    5.34 +struct ring_head
    5.35  {
    5.36 -	if ((buffer->capacity - buffer->size) < size) {
    5.37 -		buffer->capacity += (size + 1024);
    5.38 -		buffer->data = realloc(buffer->data, buffer->capacity);
    5.39 -		if (buffer->data == NULL) {
    5.40 -			dolog(LOG_ERR, "Memory allocation failed");
    5.41 -			exit(ENOMEM);
    5.42 +	u32 cons;
    5.43 +	u32 prod;
    5.44 +	char buf[0];
    5.45 +} __attribute__((packed));
    5.46 +
    5.47 +#define PAGE_SIZE (getpagesize())
    5.48 +#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
    5.49 +#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
    5.50 +#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
    5.51 +#define XENCONS_SPACE(ring) (XENCONS_RING_SIZE - ((ring)->prod - (ring)->cons))
    5.52 +
    5.53 +static void buffer_append(struct domain *dom)
    5.54 +{
    5.55 +	struct buffer *buffer = &dom->buffer;
    5.56 +	struct ring_head *ring = (struct ring_head *)dom->page;
    5.57 +	size_t size;
    5.58 +
    5.59 +	while ((size = ring->prod - ring->cons) != 0) {
    5.60 +		if ((buffer->capacity - buffer->size) < size) {
    5.61 +			buffer->capacity += (size + 1024);
    5.62 +			buffer->data = realloc(buffer->data, buffer->capacity);
    5.63 +			if (buffer->data == NULL) {
    5.64 +				dolog(LOG_ERR, "Memory allocation failed");
    5.65 +				exit(ENOMEM);
    5.66 +			}
    5.67  		}
    5.68 -	}
    5.69  
    5.70 -	memcpy(buffer->data + buffer->size, data, size);
    5.71 -	buffer->size += size;
    5.72 +		while (ring->cons < ring->prod) {
    5.73 +			buffer->data[buffer->size] =
    5.74 +				ring->buf[XENCONS_IDX(ring->cons)];
    5.75 +			buffer->size++;
    5.76 +			ring->cons++;
    5.77 +		}
    5.78  
    5.79 -	if (buffer->max_capacity &&
    5.80 -	    buffer->size > buffer->max_capacity) {
    5.81 -		memmove(buffer->data + (buffer->size - buffer->max_capacity),
    5.82 -			buffer->data, buffer->max_capacity);
    5.83 -		buffer->data = realloc(buffer->data, buffer->max_capacity);
    5.84 -		buffer->capacity = buffer->max_capacity;
    5.85 +		if (buffer->max_capacity &&
    5.86 +		    buffer->size > buffer->max_capacity) {
    5.87 +			memmove(buffer->data + (buffer->size -
    5.88 +						buffer->max_capacity),
    5.89 +				buffer->data, buffer->max_capacity);
    5.90 +			buffer->data = realloc(buffer->data,
    5.91 +					       buffer->max_capacity);
    5.92 +			buffer->capacity = buffer->max_capacity;
    5.93 +		}
    5.94  	}
    5.95  }
    5.96  
    5.97 @@ -83,17 +127,6 @@ static void buffer_advance(struct buffer
    5.98  	buffer->size -= size;
    5.99  }
   5.100  
   5.101 -struct domain
   5.102 -{
   5.103 -	int domid;
   5.104 -	int tty_fd;
   5.105 -	bool is_dead;
   5.106 -	struct buffer buffer;
   5.107 -	struct domain *next;
   5.108 -};
   5.109 -
   5.110 -static struct domain *dom_head;
   5.111 -
   5.112  static bool domain_is_valid(int domid)
   5.113  {
   5.114  	bool ret;
   5.115 @@ -107,7 +140,7 @@ static bool domain_is_valid(int domid)
   5.116  
   5.117  static int domain_create_tty(struct domain *dom)
   5.118  {
   5.119 -	char path[1024];
   5.120 +	char *path;
   5.121  	int master;
   5.122  
   5.123  	if ((master = getpt()) == -1 ||
   5.124 @@ -126,24 +159,108 @@ static int domain_create_tty(struct doma
   5.125  			tcsetattr(master, TCSAFLUSH, &term);
   5.126  		}
   5.127  
   5.128 -		xs_mkdir(xs, "/console");
   5.129 -		snprintf(path, sizeof(path), "/console/%d", dom->domid);
   5.130 -		xs_mkdir(xs, path);
   5.131 -		strcat(path, "/tty");
   5.132 +		asprintf(&path, "/console/%d/tty", dom->domid);
   5.133 +		xs_write(xs, path, slave, strlen(slave), O_CREAT);
   5.134 +		free(path);
   5.135  
   5.136 -		xs_write(xs, path, slave, strlen(slave), O_CREAT);
   5.137 -
   5.138 -		snprintf(path, sizeof(path), "/console/%d/limit", dom->domid);
   5.139 +		asprintf(&path, "/console/%d/limit", dom->domid);
   5.140  		data = xs_read(xs, path, &len);
   5.141  		if (data) {
   5.142  			dom->buffer.max_capacity = strtoul(data, 0, 0);
   5.143  			free(data);
   5.144  		}
   5.145 +		free(path);
   5.146  	}
   5.147  
   5.148  	return master;
   5.149  }
   5.150  
   5.151 +/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
   5.152 +int xs_gather(struct xs_handle *xs, const char *dir, ...)
   5.153 +{
   5.154 +	va_list ap;
   5.155 +	const char *name;
   5.156 +	char *path;
   5.157 +	int ret = 0;
   5.158 +
   5.159 +	va_start(ap, dir);
   5.160 +	while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
   5.161 +		const char *fmt = va_arg(ap, char *);
   5.162 +		void *result = va_arg(ap, void *);
   5.163 +		char *p;
   5.164 +
   5.165 +		asprintf(&path, "%s/%s", dir, name);
   5.166 +		p = xs_read(xs, path, NULL);
   5.167 +		free(path);
   5.168 +		if (p == NULL) {
   5.169 +			ret = ENOENT;
   5.170 +			break;
   5.171 +		}
   5.172 +		if (fmt) {
   5.173 +			if (sscanf(p, fmt, result) == 0)
   5.174 +				ret = EINVAL;
   5.175 +			free(p);
   5.176 +		} else
   5.177 +			*(char **)result = p;
   5.178 +	}
   5.179 +	va_end(ap);
   5.180 +	return ret;
   5.181 +}
   5.182 +
   5.183 +#define EVENTCHN_BIND		_IO('E', 2)
   5.184 +#define EVENTCHN_UNBIND 	_IO('E', 3)
   5.185 +
   5.186 +static int domain_create_ring(struct domain *dom)
   5.187 +{
   5.188 +	char *dompath, *path;
   5.189 +	int err;
   5.190 +
   5.191 +	dom->page = NULL;
   5.192 +	dom->evtchn_fd = -1;
   5.193 +
   5.194 +	asprintf(&path, "/console/%d/domain", dom->domid);
   5.195 +	dompath = xs_read(xs, path, NULL);
   5.196 +	free(path);
   5.197 +	if (!dompath)
   5.198 +		return ENOENT;
   5.199 +
   5.200 +	err = xs_gather(xs, dompath,
   5.201 +			"console_mfn", "%li", &dom->mfn,
   5.202 +			"console_channel/port1", "%i", &dom->local_port,
   5.203 +			"console_channel/port2", "%i", &dom->remote_port,
   5.204 +			NULL);
   5.205 +	if (err)
   5.206 +		goto out;
   5.207 +
   5.208 +	dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
   5.209 +					 PROT_READ|PROT_WRITE, dom->mfn);
   5.210 +	if (dom->page == NULL) {
   5.211 +		err = EINVAL;
   5.212 +		goto out;
   5.213 +	}
   5.214 +
   5.215 +	/* Opening evtchn independently for each console is a bit
   5.216 +	 * wastefule, but that's how the code is structured... */
   5.217 +	err = open("/dev/xen/evtchn", O_RDWR);
   5.218 +	if (err == -1) {
   5.219 +		err = errno;
   5.220 +		goto out;
   5.221 +	}
   5.222 +	dom->evtchn_fd = err;
   5.223 +
   5.224 +	if (ioctl(dom->evtchn_fd, EVENTCHN_BIND, dom->local_port) == -1) {
   5.225 +		err = errno;
   5.226 +		munmap(dom->page, getpagesize());
   5.227 +		close(dom->evtchn_fd);
   5.228 +		dom->evtchn_fd = -1;
   5.229 +		goto out;
   5.230 +	}
   5.231 +
   5.232 + out:
   5.233 +	free(dompath);
   5.234 +	return err;
   5.235 +}
   5.236 +
   5.237  static struct domain *create_domain(int domid)
   5.238  {
   5.239  	struct domain *dom;
   5.240 @@ -162,7 +279,9 @@ static struct domain *create_domain(int 
   5.241  	dom->buffer.size = 0;
   5.242  	dom->buffer.capacity = 0;
   5.243  	dom->buffer.max_capacity = 0;
   5.244 -	dom->next = 0;
   5.245 +	dom->next = NULL;
   5.246 +
   5.247 +	domain_create_ring(dom);
   5.248  
   5.249  	dolog(LOG_DEBUG, "New domain %d", domid);
   5.250  
   5.251 @@ -200,9 +319,14 @@ static void remove_domain(struct domain 
   5.252  
   5.253  		if (dom->domid == d->domid) {
   5.254  			*pp = d->next;
   5.255 -			if (d->buffer.data) {
   5.256 +			if (d->buffer.data)
   5.257  				free(d->buffer.data);
   5.258 -			}
   5.259 +			if (d->page)
   5.260 +				munmap(d->page, getpagesize());
   5.261 +			if (d->evtchn_fd != -1)
   5.262 +				close(d->evtchn_fd);
   5.263 +			if (d->tty_fd != -1)
   5.264 +				close(d->tty_fd);
   5.265  			free(d);
   5.266  			break;
   5.267  		}
   5.268 @@ -211,28 +335,28 @@ static void remove_domain(struct domain 
   5.269  
   5.270  static void remove_dead_domains(struct domain *dom)
   5.271  {
   5.272 -	if (dom == NULL) return;
   5.273 -	remove_dead_domains(dom->next);
   5.274 +	struct domain *n;
   5.275  
   5.276 -	if (dom->is_dead) {
   5.277 -		remove_domain(dom);
   5.278 +	while (dom != NULL) {
   5.279 +		n = dom->next;
   5.280 +		if (dom->is_dead)
   5.281 +			remove_domain(dom);
   5.282 +		dom = n;
   5.283  	}
   5.284  }
   5.285  
   5.286  static void handle_tty_read(struct domain *dom)
   5.287  {
   5.288  	ssize_t len;
   5.289 -	xcs_msg_t msg;
   5.290 +	char msg[80];
   5.291 +	struct ring_head *inring =
   5.292 +		(struct ring_head *)(dom->page + PAGE_SIZE/2);
   5.293 +	int i;
   5.294  
   5.295 -	msg.type = XCS_REQUEST;
   5.296 -	msg.u.control.remote_dom = dom->domid;
   5.297 -	msg.u.control.msg.type = CMSG_CONSOLE;
   5.298 -	msg.u.control.msg.subtype = CMSG_CONSOLE_DATA;
   5.299 -	msg.u.control.msg.id = 1;
   5.300 -
   5.301 -	len = read(dom->tty_fd, msg.u.control.msg.msg, 60);
   5.302 +	len = read(dom->tty_fd, msg, MAX(XENCONS_SPACE(inring), sizeof(msg)));
   5.303  	if (len < 1) {
   5.304  		close(dom->tty_fd);
   5.305 +		dom->tty_fd = -1;
   5.306  
   5.307  		if (domain_is_valid(dom->domid)) {
   5.308  			dom->tty_fd = domain_create_tty(dom);
   5.309 @@ -240,14 +364,14 @@ static void handle_tty_read(struct domai
   5.310  			dom->is_dead = true;
   5.311  		}
   5.312  	} else if (domain_is_valid(dom->domid)) {
   5.313 -		msg.u.control.msg.length = len;
   5.314 -
   5.315 -		if (!write_sync(xcs_data_fd, &msg, sizeof(msg))) {
   5.316 -			dolog(LOG_ERR, "Write to xcs failed: %m");
   5.317 -			exit(1);
   5.318 +		for (i = 0; i < len; i++) {
   5.319 +			inring->buf[XENCONS_IDX(inring->prod)] = msg[i];
   5.320 +			inring->prod++;
   5.321  		}
   5.322 +		xc_evtchn_send(xc, dom->local_port);
   5.323  	} else {
   5.324  		close(dom->tty_fd);
   5.325 +		dom->tty_fd = -1;
   5.326  		dom->is_dead = true;
   5.327  	}
   5.328  }
   5.329 @@ -259,6 +383,7 @@ static void handle_tty_write(struct doma
   5.330  	len = write(dom->tty_fd, dom->buffer.data, dom->buffer.size);
   5.331  	if (len < 1) {
   5.332  		close(dom->tty_fd);
   5.333 +		dom->tty_fd = -1;
   5.334  
   5.335  		if (domain_is_valid(dom->domid)) {
   5.336  			dom->tty_fd = domain_create_tty(dom);
   5.337 @@ -270,6 +395,18 @@ static void handle_tty_write(struct doma
   5.338  	}
   5.339  }
   5.340  
   5.341 +static void handle_ring_read(struct domain *dom)
   5.342 +{
   5.343 +	u16 v;
   5.344 +
   5.345 +	if (!read_sync(dom->evtchn_fd, &v, sizeof(v)))
   5.346 +		return;
   5.347 +
   5.348 +	buffer_append(dom);
   5.349 +
   5.350 +	(void)write_sync(dom->evtchn_fd, &v, sizeof(v));
   5.351 +}
   5.352 +
   5.353  static void handle_xcs_msg(int fd)
   5.354  {
   5.355  	xcs_msg_t msg;
   5.356 @@ -277,13 +414,6 @@ static void handle_xcs_msg(int fd)
   5.357  	if (!read_sync(fd, &msg, sizeof(msg))) {
   5.358  		dolog(LOG_ERR, "read from xcs failed! %m");
   5.359  		exit(1);
   5.360 -	} else if (msg.type == XCS_REQUEST) {
   5.361 -		struct domain *dom;
   5.362 -
   5.363 -		dom = lookup_domain(msg.u.control.remote_dom);
   5.364 -		buffer_append(&dom->buffer,
   5.365 -			      msg.u.control.msg.msg,
   5.366 -			      msg.u.control.msg.length);
   5.367  	}
   5.368  }
   5.369  
   5.370 @@ -291,9 +421,12 @@ static void enum_domains(void)
   5.371  {
   5.372  	int domid = 0;
   5.373  	xc_dominfo_t dominfo;
   5.374 +	struct domain *dom;
   5.375  
   5.376  	while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
   5.377 -		lookup_domain(dominfo.domid);
   5.378 +		dom = lookup_domain(dominfo.domid);
   5.379 +		if (dominfo.dying || dominfo.crashed || dominfo.shutdown)
   5.380 +			dom->is_dead = true;
   5.381  		domid = dominfo.domid + 1;
   5.382  	}
   5.383  }
   5.384 @@ -302,12 +435,11 @@ void handle_io(void)
   5.385  {
   5.386  	fd_set readfds, writefds;
   5.387  	int ret;
   5.388 -	int max_fd = -1;
   5.389 -	int num_of_writes = 0;
   5.390  
   5.391  	do {
   5.392  		struct domain *d;
   5.393  		struct timeval tv = { 1, 0 };
   5.394 +		int max_fd = -1;
   5.395  
   5.396  		FD_ZERO(&readfds);
   5.397  		FD_ZERO(&writefds);
   5.398 @@ -319,42 +451,36 @@ void handle_io(void)
   5.399  			if (d->tty_fd != -1) {
   5.400  				FD_SET(d->tty_fd, &readfds);
   5.401  			}
   5.402 +			if (d->evtchn_fd != -1)
   5.403 +				FD_SET(d->evtchn_fd, &readfds);
   5.404  
   5.405  			if (d->tty_fd != -1 && !buffer_empty(&d->buffer)) {
   5.406  				FD_SET(d->tty_fd, &writefds);
   5.407  			}
   5.408  
   5.409  			max_fd = MAX(d->tty_fd, max_fd);
   5.410 +			max_fd = MAX(d->evtchn_fd, max_fd);
   5.411  		}
   5.412  
   5.413  		ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
   5.414 -		if (tv.tv_sec == 1 && (++num_of_writes % 100) == 0) {
   5.415 -#if 0
   5.416 -			/* FIXME */
   5.417 -			/* This is a nasty hack.  xcs does not handle the
   5.418 -			   control channels filling up well at all.  We'll
   5.419 -			   throttle ourselves here since we do proper
   5.420 -			   queueing to give the domains a shot at pulling out
   5.421 -			   the data.  Fixing xcs is not worth it as it's
   5.422 -			   going away */
   5.423 -			tv.tv_usec = 1000;
   5.424 -			select(0, 0, 0, 0, &tv);
   5.425 -#endif
   5.426 -		}
   5.427  		enum_domains();
   5.428  
   5.429 -		if (FD_ISSET(xcs_data_fd, &readfds)) {
   5.430 +		if (FD_ISSET(xcs_data_fd, &readfds))
   5.431  			handle_xcs_msg(xcs_data_fd);
   5.432 -		}
   5.433  
   5.434  		for (d = dom_head; d; d = d->next) {
   5.435 -			if (!d->is_dead && FD_ISSET(d->tty_fd, &readfds)) {
   5.436 -				handle_tty_read(d);
   5.437 -			}
   5.438 +			if (d->is_dead || d->tty_fd == -1 ||
   5.439 +			    d->evtchn_fd == -1)
   5.440 +				continue;
   5.441  
   5.442 -			if (!d->is_dead && FD_ISSET(d->tty_fd, &writefds)) {
   5.443 +			if (FD_ISSET(d->tty_fd, &readfds))
   5.444 +				handle_tty_read(d);
   5.445 +
   5.446 +			if (FD_ISSET(d->evtchn_fd, &readfds))
   5.447 +				handle_ring_read(d);
   5.448 +
   5.449 +			if (FD_ISSET(d->tty_fd, &writefds))
   5.450  				handle_tty_write(d);
   5.451 -			}
   5.452  		}
   5.453  
   5.454  		remove_dead_domains(dom_head);
     6.1 --- a/tools/console/daemon/utils.c	Tue Aug 30 08:47:51 2005 +0000
     6.2 +++ b/tools/console/daemon/utils.c	Tue Aug 30 16:14:53 2005 +0000
     6.3 @@ -226,14 +226,10 @@ bool xen_setup(void)
     6.4  		goto out_close_data;
     6.5  	}
     6.6  
     6.7 -	/* Since the vast majority of control messages are console messages
     6.8 -	   it's just easier to ignore other messages that try to bind to 
     6.9 -	   a specific type. */
    6.10 -	msg.type = XCS_MSG_BIND;
    6.11 -	msg.u.bind.port = PORT_WILDCARD;
    6.12 -	msg.u.bind.type = TYPE_WILDCARD;
    6.13 +	msg.type = XCS_VIRQ_BIND;
    6.14 +	msg.u.virq.virq = VIRQ_DOM_EXC;
    6.15  	if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
    6.16 -		dolog(LOG_ERR, "xcs vind failed.  Possible bug.");
    6.17 +		dolog(LOG_ERR, "xcs virq bind failed.  Possible bug.");
    6.18  		goto out_close_data;
    6.19  	}
    6.20  	
     7.1 --- a/tools/libxc/xc_linux_build.c	Tue Aug 30 08:47:51 2005 +0000
     7.2 +++ b/tools/libxc/xc_linux_build.c	Tue Aug 30 16:14:53 2005 +0000
     7.3 @@ -335,7 +335,8 @@ static int setup_guest(int xc_handle,
     7.4                         unsigned int control_evtchn,
     7.5                         unsigned long flags,
     7.6                         unsigned int vcpus,
     7.7 -		       unsigned int store_evtchn, unsigned long *store_mfn)
     7.8 +		       unsigned int store_evtchn, unsigned long *store_mfn,
     7.9 +		       unsigned int console_evtchn, unsigned long *console_mfn)
    7.10  {
    7.11      unsigned long *page_array = NULL;
    7.12      unsigned long count, i;
    7.13 @@ -358,6 +359,8 @@ static int setup_guest(int xc_handle,
    7.14      unsigned long vstartinfo_end;
    7.15      unsigned long vstoreinfo_start;
    7.16      unsigned long vstoreinfo_end;
    7.17 +    unsigned long vconsole_start;
    7.18 +    unsigned long vconsole_end;
    7.19      unsigned long vstack_start;
    7.20      unsigned long vstack_end;
    7.21      unsigned long vpt_start;
    7.22 @@ -393,7 +396,9 @@ static int setup_guest(int xc_handle,
    7.23      vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
    7.24      vstoreinfo_start = round_pgup(vphysmap_end);
    7.25      vstoreinfo_end   = vstoreinfo_start + PAGE_SIZE;
    7.26 -    vpt_start        = vstoreinfo_end; 
    7.27 +    vconsole_start   = vstoreinfo_end;
    7.28 +    vconsole_end     = vstoreinfo_end + PAGE_SIZE;
    7.29 +    vpt_start        = vconsole_end; 
    7.30  
    7.31      for ( nr_pt_pages = 2; ; nr_pt_pages++ )
    7.32      {
    7.33 @@ -437,6 +442,7 @@ static int setup_guest(int xc_handle,
    7.34             " Init. ramdisk: %p->%p\n"
    7.35             " Phys-Mach map: %p->%p\n"
    7.36             " Store page:    %p->%p\n"
    7.37 +           " Console page:  %p->%p\n"
    7.38             " Page tables:   %p->%p\n"
    7.39             " Start info:    %p->%p\n"
    7.40             " Boot stack:    %p->%p\n"
    7.41 @@ -445,6 +451,7 @@ static int setup_guest(int xc_handle,
    7.42             _p(vinitrd_start), _p(vinitrd_end),
    7.43             _p(vphysmap_start), _p(vphysmap_end),
    7.44             _p(vstoreinfo_start), _p(vstoreinfo_end),
    7.45 +           _p(vconsole_start), _p(vconsole_end),
    7.46             _p(vpt_start), _p(vpt_end),
    7.47             _p(vstartinfo_start), _p(vstartinfo_end),
    7.48             _p(vstack_start), _p(vstack_end),
    7.49 @@ -566,6 +573,8 @@ static int setup_guest(int xc_handle,
    7.50  #endif
    7.51  
    7.52      *store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT];
    7.53 +    *console_mfn = page_array[(vconsole_start-dsi.v_start) >> PAGE_SHIFT];
    7.54 +
    7.55  
    7.56      start_info = xc_map_foreign_range(
    7.57          xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
    7.58 @@ -580,6 +589,8 @@ static int setup_guest(int xc_handle,
    7.59      start_info->domain_controller_evtchn = control_evtchn;
    7.60      start_info->store_mfn    = *store_mfn;
    7.61      start_info->store_evtchn = store_evtchn;
    7.62 +    start_info->console_mfn   = *console_mfn;
    7.63 +    start_info->console_evtchn = console_evtchn;
    7.64      if ( initrd_len != 0 )
    7.65      {
    7.66          start_info->mod_start    = vinitrd_start;
    7.67 @@ -631,7 +642,9 @@ int xc_linux_build(int xc_handle,
    7.68                     unsigned long flags,
    7.69                     unsigned int vcpus,
    7.70                     unsigned int store_evtchn,
    7.71 -                   unsigned long *store_mfn)
    7.72 +                   unsigned long *store_mfn,
    7.73 +                   unsigned int console_evtchn,
    7.74 +                   unsigned long *console_mfn)
    7.75  {
    7.76      dom0_op_t launch_op, op;
    7.77      int initrd_fd = -1;
    7.78 @@ -707,7 +720,8 @@ int xc_linux_build(int xc_handle,
    7.79                       &vstack_start, ctxt, cmdline,
    7.80                       op.u.getdomaininfo.shared_info_frame,
    7.81                       control_evtchn, flags, vcpus,
    7.82 -                     store_evtchn, store_mfn) < 0 )
    7.83 +                     store_evtchn, store_mfn,
    7.84 +		     console_evtchn, console_mfn) < 0 )
    7.85      {
    7.86          ERROR("Error constructing guest OS");
    7.87          goto error_out;
     8.1 --- a/tools/libxc/xenguest.h	Tue Aug 30 08:47:51 2005 +0000
     8.2 +++ b/tools/libxc/xenguest.h	Tue Aug 30 16:14:53 2005 +0000
     8.3 @@ -47,7 +47,9 @@ int xc_linux_build(int xc_handle,
     8.4                     unsigned long flags,
     8.5                     unsigned int vcpus,
     8.6                     unsigned int store_evtchn,
     8.7 -                   unsigned long *store_mfn);
     8.8 +                   unsigned long *store_mfn,
     8.9 +                   unsigned int console_evtchn,
    8.10 +                   unsigned long *console_mfn);
    8.11  
    8.12  struct mem_map;
    8.13  int xc_vmx_build(int xc_handle,
     9.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Tue Aug 30 08:47:51 2005 +0000
     9.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Tue Aug 30 16:14:53 2005 +0000
     9.3 @@ -268,25 +268,33 @@ static PyObject *pyxc_linux_build(PyObje
     9.4      u32 dom;
     9.5      char *image, *ramdisk = NULL, *cmdline = "";
     9.6      int flags = 0, vcpus = 1;
     9.7 -    int control_evtchn, store_evtchn;
     9.8 +    int control_evtchn, store_evtchn, console_evtchn;
     9.9      unsigned long store_mfn = 0;
    9.10 +    unsigned long console_mfn = 0;
    9.11  
    9.12      static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn", 
    9.13 -                                "image", "ramdisk", "cmdline", "flags",
    9.14 +                                "console_evtchn", "image", 
    9.15 +				/* optional */
    9.16 +				"ramdisk", "cmdline", "flags",
    9.17  				"vcpus", NULL };
    9.18  
    9.19 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssii", kwd_list,
    9.20 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiis|ssii", kwd_list,
    9.21                                        &dom, &control_evtchn, &store_evtchn,
    9.22 -                                      &image, &ramdisk, &cmdline, &flags,
    9.23 +				      &console_evtchn, &image, 
    9.24 +				      /* optional */
    9.25 +				      &ramdisk, &cmdline, &flags,
    9.26                                        &vcpus) )
    9.27          return NULL;
    9.28  
    9.29      if ( xc_linux_build(xc->xc_handle, dom, image,
    9.30                          ramdisk, cmdline, control_evtchn, flags, vcpus,
    9.31 -                        store_evtchn, &store_mfn) != 0 )
    9.32 +                        store_evtchn, &store_mfn, 
    9.33 +			console_evtchn, &console_mfn) != 0 )
    9.34          return PyErr_SetFromErrno(xc_error);
    9.35      
    9.36 -    return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
    9.37 +    return Py_BuildValue("{s:i,s:i}", 
    9.38 +			 "store_mfn", store_mfn,
    9.39 +			 "console_mfn", console_mfn);
    9.40  }
    9.41  
    9.42  static PyObject *pyxc_vmx_build(PyObject *self,
    10.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Tue Aug 30 08:47:51 2005 +0000
    10.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Tue Aug 30 16:14:53 2005 +0000
    10.3 @@ -47,7 +47,7 @@ from xen.xend.XendError import XendError
    10.4  from xen.xend.XendRoot import get_component
    10.5  
    10.6  from xen.xend.uuid import getUuid
    10.7 -from xen.xend.xenstore import DBVar
    10.8 +from xen.xend.xenstore import DBVar, XenNode, DBMap
    10.9  
   10.10  """Shutdown code for poweroff."""
   10.11  DOMAIN_POWEROFF = 0
   10.12 @@ -231,6 +231,7 @@ class XendDomainInfo:
   10.13          DBVar('start_time',    ty='float'),
   10.14          DBVar('state',         ty='str'),
   10.15          DBVar('store_mfn',     ty='long'),
   10.16 +        DBVar('console_mfn',     ty='long'),
   10.17          DBVar('restart_mode',  ty='str'),
   10.18          DBVar('restart_state', ty='str'),
   10.19          DBVar('restart_time',  ty='float'),
   10.20 @@ -260,6 +261,8 @@ class XendDomainInfo:
   10.21          self.channel = None
   10.22          self.store_channel = None
   10.23          self.store_mfn = None
   10.24 +        self.console_channel = None
   10.25 +        self.console_mfn = None
   10.26          self.controllers = {}
   10.27          
   10.28          self.info = None
   10.29 @@ -297,6 +300,9 @@ class XendDomainInfo:
   10.30          if self.store_channel:
   10.31              self.store_channel.saveToDB(self.db.addChild("store_channel"),
   10.32                                          save=save)
   10.33 +        if self.console_channel:
   10.34 +            self.console_channel.saveToDB(self.db.addChild("console_channel"),
   10.35 +                                        save=save)
   10.36          if self.image:
   10.37              self.image.exportToDB(save=save, sync=sync)
   10.38          self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
   10.39 @@ -329,6 +335,9 @@ class XendDomainInfo:
   10.40      def getStoreChannel(self):
   10.41          return self.store_channel
   10.42  
   10.43 +    def getConsoleChannel(self):
   10.44 +        return self.console_channel
   10.45 +
   10.46      def update(self, info):
   10.47          """Update with  info from xc.domain_getinfo().
   10.48          """
   10.49 @@ -518,6 +527,14 @@ class XendDomainInfo:
   10.50              sxpr.append(self.store_channel.sxpr())
   10.51          if self.store_mfn:
   10.52              sxpr.append(['store_mfn', self.store_mfn])
   10.53 +        if self.console_channel:
   10.54 +            sxpr.append(['console_channel', self.console_channel.sxpr()])
   10.55 +        if self.console_mfn:
   10.56 +            sxpr.append(['console_mfn', self.console_mfn])
   10.57 +# already in (devices)
   10.58 +#        console = self.getConsole()
   10.59 +#        if console:
   10.60 +#            sxpr.append(console.sxpr())
   10.61  
   10.62          if self.restart_count:
   10.63              sxpr.append(['restart_count', self.restart_count])
   10.64 @@ -712,6 +729,13 @@ class XendDomainInfo:
   10.65              except Exception, ex:
   10.66                  log.warning("error in domain release on xenstore: %s", ex)
   10.67                  pass
   10.68 +        if self.console_channel:
   10.69 +            # notify processes using this cosole?
   10.70 +            try:
   10.71 +                self.console_channel.close()
   10.72 +                self.console_channel = None
   10.73 +            except:
   10.74 +                pass
   10.75          if self.image:
   10.76              try:
   10.77                  self.device_model_pid = 0
   10.78 @@ -808,6 +832,7 @@ class XendDomainInfo:
   10.79          """
   10.80          self.channel = self.openChannel("channel", 0, 1)
   10.81          self.store_channel = self.eventChannel("store_channel")
   10.82 +        self.console_channel = self.eventChannel("console_channel")
   10.83  
   10.84      def create_configured_devices(self):
   10.85          devices = sxp.children(self.config, 'device')
   10.86 @@ -1003,6 +1028,7 @@ class XendDomainInfo:
   10.87          self.configure_fields()
   10.88          self.create_devices()
   10.89          self.create_blkif()
   10.90 +        self.publish_console()
   10.91  
   10.92      def create_blkif(self):
   10.93          """Create the block device interface (blkif) for the vm.
   10.94 @@ -1017,6 +1043,12 @@ class XendDomainInfo:
   10.95              backend = blkif.getBackend(0)
   10.96              backend.connect(recreate=self.recreate)
   10.97  
   10.98 +    def publish_console(self):
   10.99 +        db = DBMap(db=XenNode("/console/%d" % self.id))
  10.100 +        db.clear()
  10.101 +        db['domain'] = self.db.getPath()
  10.102 +        db.saveDB(save=True)
  10.103 +        
  10.104      def configure_fields(self):
  10.105          """Process the vm configuration fields using the registered handlers.
  10.106          """
    11.1 --- a/tools/python/xen/xend/image.py	Tue Aug 30 08:47:51 2005 +0000
    11.2 +++ b/tools/python/xen/xend/image.py	Tue Aug 30 16:14:53 2005 +0000
    11.3 @@ -238,16 +238,33 @@ class LinuxImageHandler(ImageHandler):
    11.4              store_evtchn = self.vm.store_channel.port2
    11.5          else:
    11.6              store_evtchn = 0
    11.7 +        if self.vm.console_channel:
    11.8 +            console_evtchn = self.vm.console_channel.port2
    11.9 +        else:
   11.10 +            console_evtchn = 0
   11.11 +
   11.12 +        log.debug("dom            = %d", self.vm.getDomain())
   11.13 +        log.debug("image          = %s", self.kernel)
   11.14 +        log.debug("control_evtchn = %s", self.vm.channel.getRemotePort())
   11.15 +        log.debug("store_evtchn   = %d", store_evtchn)
   11.16 +        log.debug("console_evtchn = %d", console_evtchn)
   11.17 +        log.debug("cmdline        = %s", self.cmdline)
   11.18 +        log.debug("ramdisk        = %s", self.ramdisk)
   11.19 +        log.debug("flags          = %d", self.flags)
   11.20 +        log.debug("vcpus          = %d", self.vm.vcpus)
   11.21 +
   11.22          ret = xc.linux_build(dom            = self.vm.getDomain(),
   11.23                               image          = self.kernel,
   11.24                               control_evtchn = self.vm.channel.getRemotePort(),
   11.25                               store_evtchn   = store_evtchn,
   11.26 +                             console_evtchn = console_evtchn,
   11.27                               cmdline        = self.cmdline,
   11.28                               ramdisk        = self.ramdisk,
   11.29                               flags          = self.flags,
   11.30                               vcpus          = self.vm.vcpus)
   11.31          if isinstance(ret, dict):
   11.32              self.vm.store_mfn = ret.get('store_mfn')
   11.33 +            self.vm.console_mfn = ret.get('console_mfn')
   11.34              return 0
   11.35          return ret
   11.36  
    12.1 --- a/xen/include/public/xen.h	Tue Aug 30 08:47:51 2005 +0000
    12.2 +++ b/xen/include/public/xen.h	Tue Aug 30 16:14:53 2005 +0000
    12.3 @@ -438,19 +438,21 @@ typedef struct shared_info {
    12.4  #define MAX_GUEST_CMDLINE 1024
    12.5  typedef struct start_info {
    12.6      /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME.    */
    12.7 -    unsigned long nr_pages;   /* Total pages allocated to this domain.    */
    12.8 -    unsigned long shared_info;/* MACHINE address of shared info struct.   */
    12.9 -    u32      flags;           /* SIF_xxx flags.                           */
   12.10 +    unsigned long nr_pages;     /* Total pages allocated to this domain.  */
   12.11 +    unsigned long shared_info;  /* MACHINE address of shared info struct. */
   12.12 +    u32      flags;             /* SIF_xxx flags.                         */
   12.13      u16      domain_controller_evtchn;
   12.14      /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME).     */
   12.15 -    unsigned long pt_base;    /* VIRTUAL address of page directory.       */
   12.16 -    unsigned long nr_pt_frames;/* Number of bootstrap p.t. frames.        */
   12.17 -    unsigned long mfn_list;   /* VIRTUAL address of page-frame list.      */
   12.18 -    unsigned long mod_start;  /* VIRTUAL address of pre-loaded module.    */
   12.19 -    unsigned long mod_len;    /* Size (bytes) of pre-loaded module.       */
   12.20 +    unsigned long pt_base;      /* VIRTUAL address of page directory.     */
   12.21 +    unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames.       */
   12.22 +    unsigned long mfn_list;     /* VIRTUAL address of page-frame list.    */
   12.23 +    unsigned long mod_start;    /* VIRTUAL address of pre-loaded module.  */
   12.24 +    unsigned long mod_len;      /* Size (bytes) of pre-loaded module.     */
   12.25      s8 cmd_line[MAX_GUEST_CMDLINE];
   12.26 -    unsigned long store_mfn;  /* MACHINE page number of shared page.      */
   12.27 -    u16      store_evtchn;    /* Event channel for store communication.   */
   12.28 +    unsigned long store_mfn;    /* MACHINE page number of shared page.    */
   12.29 +    u16      store_evtchn;      /* Event channel for store communication. */
   12.30 +    unsigned long console_mfn;  /* MACHINE address of console page.       */
   12.31 +    u16      console_evtchn;    /* Event channel for console messages.    */
   12.32  } start_info_t;
   12.33  
   12.34  /* These flags are passed in the 'flags' field of start_info_t. */