ia64/xen-unstable

changeset 2964:2b25e0010db8

bitkeeper revision 1.1159.1.415 (4195dc7etTtvj4twOJH5_vELAFyETw)

Merge freefall.cl.cam.ac.uk:/auto/groups/xeno/BK/xen-unstable.bk
into freefall.cl.cam.ac.uk:/auto/groups/xeno/users/cl349/BK/xen.bk-smp
author cl349@freefall.cl.cam.ac.uk
date Sat Nov 13 10:05:50 2004 +0000 (2004-11-13)
parents 186962673207 36472cdf9921
children e2675067dd05
files .rootkeys BitKeeper/etc/ignore linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h tools/x2d2/Makefile tools/x2d2/cntrl_con.c tools/x2d2/domain_controller.h tools/x2d2/main.c tools/x2d2/minixend.h tools/x2d2/util.c xen/arch/x86/traps.c xen/common/keyhandler.c xen/common/vsprintf.c xen/drivers/char/console.c xen/drivers/char/serial.c xen/include/asm-x86/hardirq.h xen/include/xen/console.h xen/include/xen/debugger_hooks.h xen/include/xen/keyhandler.h xen/include/xen/serial.h
line diff
     1.1 --- a/.rootkeys	Fri Nov 12 12:43:41 2004 +0000
     1.2 +++ b/.rootkeys	Sat Nov 13 10:05:50 2004 +0000
     1.3 @@ -531,6 +531,12 @@ 4104ffca-jPHLVOrW0n0VghEXXtKxg tools/sv/
     1.4  40fcefb3yMSrZvApO9ToIi-iQwnchA tools/sv/images/xen.png
     1.5  41013a83z27rKvWIxAfUBMVZ1eDCDg tools/sv/inc/script.js
     1.6  40fcefb3zGC9XNBkSwTEobCoq8YClA tools/sv/inc/style.css
     1.7 +4194e861IgTabTt8HOuh143QIJFD1Q tools/x2d2/Makefile
     1.8 +4194e861M2gcBz4i94cQYpqzi8n6UA tools/x2d2/cntrl_con.c
     1.9 +4194e861xToz-o2KH6VT_CPJqVGMCg tools/x2d2/domain_controller.h
    1.10 +4194e8612TrrMvC8ZlA4h2ZYCPWz4g tools/x2d2/main.c
    1.11 +4194e861x2eqNCD61RYPCUEBVdMYuw tools/x2d2/minixend.h
    1.12 +4194e861A4V9VbD_FYmgXpYEj5YwVg tools/x2d2/util.c
    1.13  403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
    1.14  40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
    1.15  4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xentrace/xentrace.8
    1.16 @@ -766,6 +772,7 @@ 3f840f12CkbYSlwMrY2S11Mpyxg7Nw xen/inclu
    1.17  3ddb79c259jh8hE7vre_8NuE7nwNSA xen/include/xen/config.h
    1.18  3eb165e0eawr3R-p2ZQtSdLWtLRN_A xen/include/xen/console.h
    1.19  3ddb79c1V44RD26YqCUm-kqIupM37A xen/include/xen/ctype.h
    1.20 +4194efbdvxUXjCLobbopgLOojisO4Q xen/include/xen/debugger_hooks.h
    1.21  3ddb79c05DdHQ0UxX_jKsXdR4QlMCA xen/include/xen/delay.h
    1.22  3ddb79c2O729EttZTYu1c8LcsUO_GQ xen/include/xen/elf.h
    1.23  3ddb79c0HIghfBF8zFUdmXhOU8i6hA xen/include/xen/errno.h
     2.1 --- a/BitKeeper/etc/ignore	Fri Nov 12 12:43:41 2004 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Sat Nov 13 10:05:50 2004 +0000
     2.3 @@ -79,3 +79,4 @@ install/*
     2.4  
     2.5  patches/ebtables-brnf-5_vs_2.4.25.diff
     2.6  patches/ebtables.diff
     2.7 +tools/x2d2/minixend
     3.1 --- a/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c	Fri Nov 12 12:43:41 2004 +0000
     3.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c	Sat Nov 13 10:05:50 2004 +0000
     3.3 @@ -87,7 +87,7 @@ void force_evtchn_callback(void)
     3.4      (void)HYPERVISOR_xen_version(0);
     3.5  }
     3.6  
     3.7 -void evtchn_do_upcall(struct pt_regs *regs)
     3.8 +asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
     3.9  {
    3.10      unsigned long  l1, l2;
    3.11      unsigned int   l1i, l2i, port;
     4.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c	Fri Nov 12 12:43:41 2004 +0000
     4.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c	Sat Nov 13 10:05:50 2004 +0000
     4.3 @@ -137,6 +137,7 @@ static inline void ADD_ID_TO_FREELIST( u
     4.4  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
     4.5  #define DISABLE_SCATTERGATHER() 
     4.6  #else
     4.7 +static int sg_operation = -1;
     4.8  #define DISABLE_SCATTERGATHER() (sg_operation = -1)
     4.9  #endif
    4.10  
    4.11 @@ -498,7 +499,6 @@ static irqreturn_t blkif_int(int irq, vo
    4.12  /**************************  KERNEL VERSION 2.4  **************************/
    4.13  
    4.14  static kdev_t        sg_dev;
    4.15 -static int           sg_operation = -1;
    4.16  static unsigned long sg_next_sect;
    4.17  
    4.18  /*
     5.1 --- a/linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h	Fri Nov 12 12:43:41 2004 +0000
     5.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h	Sat Nov 13 10:05:50 2004 +0000
     5.3 @@ -46,7 +46,7 @@
     5.4  void evtchn_do_upcall(struct pt_regs *regs);
     5.5  
     5.6  /* Entry point for notifications into the userland character device. */
     5.7 -void evtchn_device_upcall(int port);
     5.8 +asmlinkage void evtchn_device_upcall(int port);
     5.9  
    5.10  #ifdef XEN_EVTCHN_MASK_OPS
    5.11  
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/x2d2/Makefile	Sat Nov 13 10:05:50 2004 +0000
     6.3 @@ -0,0 +1,10 @@
     6.4 +CFLAGS+=-Wall -g -Werror
     6.5 +
     6.6 +SRCS=main.c cntrl_con.c util.c
     6.7 +
     6.8 +all: minixend
     6.9 +
    6.10 +#$(SRCS): minixend.h
    6.11 +
    6.12 +minixend: $(subst .c,.o,$(SRCS))
    6.13 +	gcc $^ -o $@ $(LDFLAGS) -lxc -lpthread
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/x2d2/cntrl_con.c	Sat Nov 13 10:05:50 2004 +0000
     7.3 @@ -0,0 +1,458 @@
     7.4 +#define _GNU_SOURCE
     7.5 +
     7.6 +#include <sys/types.h>
     7.7 +#include <sys/ioctl.h>
     7.8 +#include <sys/socket.h>
     7.9 +#include <assert.h>
    7.10 +#include <ctype.h>
    7.11 +#include <err.h>
    7.12 +#include <errno.h>
    7.13 +#include <pthread.h>
    7.14 +#include <netinet/in.h>
    7.15 +#include <stdarg.h>
    7.16 +#include <stddef.h>
    7.17 +#include <stdio.h>
    7.18 +#include <stdlib.h>
    7.19 +#include <string.h>
    7.20 +#include <unistd.h>
    7.21 +
    7.22 +#include "minixend.h"
    7.23 +
    7.24 +struct command {
    7.25 +	const char *name;
    7.26 +	void (*func)(struct open_connection *oc, const struct command *c,
    7.27 +		     const char *, const char *);
    7.28 +};
    7.29 +
    7.30 +static void
    7.31 +domain_created(const char *name, int mem_kb, int domid)
    7.32 +{
    7.33 +	struct domain *d;
    7.34 +	d = xmalloc(sizeof(*d));
    7.35 +	d->domid = domid;
    7.36 +	d->name = xstrdup(name);
    7.37 +	d->mem_kb = mem_kb;
    7.38 +	d->state = DOM_STATE_CREATED;
    7.39 +	d->control_evtchn = -1; /* Not connected yet. */
    7.40 +
    7.41 +	memcpy(d->netif_mac, "\xaa\x00\x00\x02\x00\x00", 6);
    7.42 +	d->netif_mac[5] = d->domid;
    7.43 +
    7.44 +	pthread_mutex_init(&d->mux, NULL);
    7.45 +	pthread_cond_init(&d->cond, NULL);
    7.46 +
    7.47 +	pthread_create(&d->thread, NULL, domain_thread_func, d);
    7.48 +
    7.49 +	list_insert_after(&d->domain_list, &head_domain);
    7.50 +}
    7.51 +
    7.52 +static struct domain *
    7.53 +find_domain(int domain_id)
    7.54 +{
    7.55 +	struct domain *d;
    7.56 +
    7.57 +	foreach_domain(d) {
    7.58 +		if (d->domid == domain_id)
    7.59 +			return d;
    7.60 +	}
    7.61 +	return NULL;
    7.62 +}
    7.63 +
    7.64 +static int
    7.65 +free_event_port(struct domain *d, int port)
    7.66 +{
    7.67 +	if (d == NULL)
    7.68 +		return xc_evtchn_close(xc_handle, DOMID_SELF, port);
    7.69 +	else
    7.70 +		return xc_evtchn_close(xc_handle, d->domid, port);
    7.71 +}
    7.72 +
    7.73 +static char *
    7.74 +readline(struct open_connection *oc)
    7.75 +{
    7.76 +	char *end;
    7.77 +	char *res;
    7.78 +	int line_length;
    7.79 +
    7.80 +	if (oc->state == OC_STATE_ERROR)
    7.81 +		return NULL;
    7.82 +
    7.83 +	end = memchr(oc->buf, '\r', oc->buf_used);
    7.84 +	assert(end != NULL);
    7.85 +	line_length = end - oc->buf;
    7.86 +
    7.87 +	res = xmalloc(line_length + 1);
    7.88 +	memcpy(res, oc->buf, line_length);
    7.89 +	res[line_length] = 0;
    7.90 +	memmove(oc->buf, oc->buf + line_length + 2,
    7.91 +		oc->buf_used - line_length - 2);
    7.92 +
    7.93 +	oc->buf_used -= line_length + 2;
    7.94 +
    7.95 +	if (memchr(oc->buf, '\n', oc->buf_used))
    7.96 +		oc->state = OC_STATE_COMMAND_PENDING;
    7.97 +	else
    7.98 +		oc->state = OC_STATE_CONNECTED;
    7.99 +
   7.100 +	return res;
   7.101 +}
   7.102 +
   7.103 +static unsigned long
   7.104 +find_domain_shared_info_mfn(struct domain *d)
   7.105 +{
   7.106 +	xc_dominfo_t info;
   7.107 +
   7.108 +	xc_domain_getinfo(xc_handle, d->domid, 1, &info);
   7.109 +	return info.shared_info_frame;
   7.110 +}
   7.111 +
   7.112 +static void
   7.113 +send_message(struct open_connection *oc, const char *fmt, ...)
   7.114 +{
   7.115 +	char *buf;
   7.116 +	va_list ap;
   7.117 +	int size;
   7.118 +	int off;
   7.119 +	ssize_t r;
   7.120 +
   7.121 +	if (oc->state == OC_STATE_ERROR)
   7.122 +		return;
   7.123 +
   7.124 +	va_start(ap, fmt);
   7.125 +	size = vasprintf(&buf, fmt, ap);
   7.126 +	va_end(ap);
   7.127 +	if (size < 0)
   7.128 +		err(1, "preparing response to a query");
   7.129 +	assert(buf[0] == 'E' || buf[0] == 'N');
   7.130 +	assert(isdigit(buf[1]));
   7.131 +	assert(isdigit(buf[2]));
   7.132 +	assert(buf[3] == ' ' || buf[3] == '\n');
   7.133 +
   7.134 +	off = 0;
   7.135 +	while (off < size) {
   7.136 +		r = write(oc->fd, buf + off, size - off);
   7.137 +		if (r < 0) {
   7.138 +			warn("sending response to remote");
   7.139 +			oc->state = OC_STATE_ERROR;
   7.140 +			free(buf);
   7.141 +			return;
   7.142 +		}
   7.143 +		off += r;
   7.144 +	}
   7.145 +	free(buf);
   7.146 +}
   7.147 +
   7.148 +static void
   7.149 +default_command_handler(struct open_connection *oc, const struct command *ign,
   7.150 +			const char *buf, const char *args)
   7.151 +{
   7.152 +	warnx("bad command %s", buf);
   7.153 +	send_message(oc, "E00 unknown command %s\n", buf);
   7.154 +}
   7.155 +
   7.156 +static void
   7.157 +create_command_handler(struct open_connection *oc, const struct command *ign,
   7.158 +		       const char *buf, const char *args)
   7.159 +{
   7.160 +	char *name;
   7.161 +	unsigned mem_kb;
   7.162 +	int r;
   7.163 +	u32 domid = -1;
   7.164 +
   7.165 +	r = sscanf(args, "%d %a[^\n]", &mem_kb, &name);
   7.166 +	if (r != 2) {
   7.167 +		send_message(oc, "E01 failed to parse %s\n", args);
   7.168 +		return;
   7.169 +	}
   7.170 +	r = xc_domain_create(xc_handle, mem_kb, name, -1, 0, &domid);
   7.171 +	if (r < 0) {
   7.172 +		send_message(oc, "E02 creating domain (%s)\n",
   7.173 +			     strerror(errno));
   7.174 +		free(name);
   7.175 +		return;
   7.176 +	}
   7.177 +
   7.178 +	domain_created(name, mem_kb, domid);
   7.179 +
   7.180 +	send_message(oc, "N00 %d\n", domid);
   7.181 +	free(name);
   7.182 +}
   7.183 +
   7.184 +static void
   7.185 +build_command_handler(struct open_connection *oc, const struct command *ign,
   7.186 +		      const char *buf, const char *args)
   7.187 +{
   7.188 +	struct domain *d;
   7.189 +	int domain_id;
   7.190 +	char *image, *cmdline;
   7.191 +	int event_ports[2];
   7.192 +	int r;
   7.193 +
   7.194 +	r = sscanf(args, "%d %a[^\t] %a[^\n]", &domain_id,
   7.195 +		   &image, &cmdline);
   7.196 +	if (r != 3) {
   7.197 +		send_message(oc, "E03 failed to parse %s\n", args);
   7.198 +		return;
   7.199 +	}
   7.200 +	d = find_domain(domain_id);
   7.201 +	if (d == NULL) {
   7.202 +		send_message(oc, "E04 unknown domain %d\n", domain_id);
   7.203 +		goto out;
   7.204 +	}
   7.205 +	if (d->state != DOM_STATE_CREATED) {
   7.206 +		send_message(oc, "E05 domain %d in bad state\n", domain_id);
   7.207 +		goto out;
   7.208 +	}
   7.209 +
   7.210 +	r = allocate_event_channel(d, event_ports);
   7.211 +	if (r < 0) {
   7.212 +		send_message(oc, "E06 allocating control event channel: %s\n",
   7.213 +			     strerror(errno));
   7.214 +		goto out;
   7.215 +	}
   7.216 +
   7.217 +	r = xc_linux_build(xc_handle, domain_id, image, NULL, cmdline,
   7.218 +			   event_ports[1], 0);
   7.219 +	if (r < 0) {
   7.220 +		send_message(oc, "E07 building domain: %s\n",
   7.221 +			     strerror(errno));
   7.222 +		free_event_port(NULL, event_ports[0]);
   7.223 +		free_event_port(d, event_ports[1]);
   7.224 +		goto out;
   7.225 +	}
   7.226 +
   7.227 +	if (ioctl(evtchn_fd, EVTCHN_BIND, event_ports[0]) < 0)
   7.228 +		err(1, "binding to event control event channel");
   7.229 +
   7.230 +	d->shared_info_mfn = find_domain_shared_info_mfn(d);
   7.231 +	d->shared_info = map_domain_mem(d, d->shared_info_mfn);
   7.232 +	if (d->shared_info == NULL)
   7.233 +		err(1, "maping domain shared info page at %lx.\n",
   7.234 +		    d->shared_info_mfn);
   7.235 +	d->ctrl_if = (control_if_t *)((unsigned)d->shared_info + 2048);
   7.236 +
   7.237 +	d->control_evtchn = event_ports[0];
   7.238 +	d->state = DOM_STATE_PAUSED;
   7.239 +
   7.240 +	send_message(oc, "N00\n");
   7.241 +
   7.242 + out:
   7.243 +	free(image);
   7.244 +	free(cmdline);
   7.245 +	return;
   7.246 +}
   7.247 +
   7.248 +static void
   7.249 +unpause_command_handler(struct open_connection *oc,
   7.250 +			const struct command *ign,
   7.251 +			const char *buf,
   7.252 +			const char *args)
   7.253 +{
   7.254 +	int domain_id;
   7.255 +	int r;
   7.256 +	struct domain *d;
   7.257 +
   7.258 +	r = sscanf(args, "%d", &domain_id);
   7.259 +	if (r != 1) {
   7.260 +		send_message(oc, "E08 cannot parse %s\n", args);
   7.261 +		return;
   7.262 +	}
   7.263 +	d = find_domain(domain_id);
   7.264 +	if (d == NULL) {
   7.265 +		send_message(oc, "E09 cannot find domain %d\n", domain_id);
   7.266 +		return;
   7.267 +	}
   7.268 +	if (d->state != DOM_STATE_PAUSED) {
   7.269 +		send_message(oc, "E10 domain not paused\n");
   7.270 +		return;
   7.271 +	}
   7.272 +
   7.273 +	r = xc_domain_unpause(xc_handle, d->domid);
   7.274 +	if (r < 0) {
   7.275 +		send_message(oc, "E11 unpausing domain: %s\n",
   7.276 +			     strerror(errno));
   7.277 +		return;
   7.278 +	}
   7.279 +
   7.280 +	d->state = DOM_STATE_RUNNING;
   7.281 +	send_message(oc, "N00\n");
   7.282 +}
   7.283 +
   7.284 +static void
   7.285 +console_command_handler(struct open_connection *oc,
   7.286 +			const struct command *ign,
   7.287 +			const char *buf,
   7.288 +			const char *args)
   7.289 +{
   7.290 +	int domain_id;
   7.291 +	struct domain *d;
   7.292 +	int r;
   7.293 +	struct sockaddr_in name;
   7.294 +	socklen_t namelen;
   7.295 +
   7.296 +	r = sscanf(args, "%d", &domain_id);
   7.297 +	if (r != 1) {
   7.298 +		send_message(oc, "E12 cannot parse %s\n", args);
   7.299 +		return;
   7.300 +	}
   7.301 +	d = find_domain(domain_id);
   7.302 +	if (d == NULL) {
   7.303 +		send_message(oc, "E13 cannot find domain %d\n", domain_id);
   7.304 +		return;
   7.305 +	}
   7.306 +	if (d->cc != NULL) {
   7.307 +		send_message(oc, "E14 console already exists\n");
   7.308 +		return;
   7.309 +	}
   7.310 +
   7.311 +	d->cc = xmalloc(sizeof(*d->cc));
   7.312 +	d->cc->fd = socket(PF_INET, SOCK_STREAM, 0);
   7.313 +	if (d->cc->fd < 0)
   7.314 +		err(1, "creating console socket");
   7.315 +	d->cc->dom = d;
   7.316 +	d->cc->state = CC_STATE_PENDING;
   7.317 +	d->cc->buf_used = 0;
   7.318 +	d->cc->buf_allocated = 0;
   7.319 +	d->cc->buf = NULL;
   7.320 +
   7.321 +	r = listen(d->cc->fd, 1);
   7.322 +	if (r < 0)
   7.323 +		err(1, "listening on console socket");
   7.324 +	namelen = sizeof(name);
   7.325 +	r = getsockname(d->cc->fd, (struct sockaddr *)&name, &namelen);
   7.326 +	if (r < 0)
   7.327 +		err(1, "getting name of console socket");
   7.328 +	assert(name.sin_family == AF_INET);
   7.329 +	assert(namelen == sizeof(name));
   7.330 +	list_insert_after(&d->cc->list, &head_console);
   7.331 +	send_message(oc, "N00 %d\n", ntohs(name.sin_port));
   7.332 +}
   7.333 +
   7.334 +static void
   7.335 +plug_command_handler(struct open_connection *oc,
   7.336 +		     const struct command *ign,
   7.337 +		     const char *buf,
   7.338 +		     const char *args)
   7.339 +{
   7.340 +	unsigned domid;
   7.341 +	int r;
   7.342 +	struct domain *d;
   7.343 +
   7.344 +	r = sscanf(args, "%d", &domid);
   7.345 +	if (r != 1) {
   7.346 +		send_message(oc, "E15 cannot parse %s\n", args);
   7.347 +		return;
   7.348 +	}
   7.349 +	d = find_domain(domid);
   7.350 +	if (d == NULL) {
   7.351 +		send_message(oc, "E16 cannot find domain %d\n", domid);
   7.352 +		return;
   7.353 +	}
   7.354 +
   7.355 +	d->plugged = 1;
   7.356 +	send_message(oc, "N00\n");
   7.357 +	PRINTF(1, "set domain %d plug state to %d\n", d->domid, d->plugged);
   7.358 +}
   7.359 +
   7.360 +static void
   7.361 +destroy_command_handler(struct open_connection *oc,
   7.362 +			const struct command *ign,
   7.363 +			const char *buf,
   7.364 +			const char *args)
   7.365 +{
   7.366 +	unsigned domid;
   7.367 +	int r;
   7.368 +	struct domain *d;
   7.369 +
   7.370 +	r = sscanf(args, "%d", &domid);
   7.371 +	if (r != 1) {
   7.372 +		send_message(oc, "E17 cannot parse %s\n", args);
   7.373 +		return;
   7.374 +	}
   7.375 +	d = find_domain(domid);
   7.376 +	if (d == NULL) {
   7.377 +		send_message(oc, "E18 cannot find domain %d\n", domid);
   7.378 +		return;
   7.379 +	}
   7.380 +
   7.381 +	r = xc_domain_destroy(xc_handle, domid);
   7.382 +	if (r < 0) {
   7.383 +		send_message(oc, "E19 error destroying domain %d: %s\n",
   7.384 +			     domid, sys_errlist[errno]);
   7.385 +		return;
   7.386 +	}
   7.387 +	d->state = DOM_STATE_DEAD;
   7.388 +
   7.389 +	send_message(oc, "N00\n");
   7.390 +}
   7.391 +
   7.392 +static void
   7.393 +list_command_handler(struct open_connection *oc,
   7.394 +		     const struct command *ign,
   7.395 +		     const char *buf,
   7.396 +		     const char *args)
   7.397 +{
   7.398 +	struct domain *d;
   7.399 +	static const char *const state_strings[] = {
   7.400 +		[DOM_STATE_CREATED] = "created",
   7.401 +		[DOM_STATE_PAUSED] = "paused",
   7.402 +		[DOM_STATE_RUNNING] = "running",
   7.403 +		[DOM_STATE_DEAD] = "dead"
   7.404 +	};
   7.405 +
   7.406 +	foreach_domain(d) {
   7.407 +		send_message(oc, "N01 %d %s %d %s\n",
   7.408 +			     d->domid,
   7.409 +			     d->name,
   7.410 +			     d->mem_kb,
   7.411 +			     state_strings[d->state]);
   7.412 +	}
   7.413 +	send_message(oc, "N00\n");
   7.414 +}
   7.415 +
   7.416 +static struct command
   7.417 +default_command = { NULL, default_command_handler };
   7.418 +
   7.419 +static struct command
   7.420 +commands[] = {
   7.421 +	{ "build", build_command_handler },
   7.422 +	{ "console", console_command_handler },
   7.423 +	{ "create", create_command_handler },
   7.424 +	{ "destroy", destroy_command_handler },
   7.425 +	{ "plug", plug_command_handler },
   7.426 +	{ "list", list_command_handler },
   7.427 +	{ "unpause", unpause_command_handler }
   7.428 +};
   7.429 +
   7.430 +void
   7.431 +process_command(struct open_connection *oc)
   7.432 +{
   7.433 +	char *buf, *b;
   7.434 +	int command_len;
   7.435 +	int x;
   7.436 +	struct command *cmd;
   7.437 +
   7.438 +	buf = readline(oc);
   7.439 +	if (buf == NULL)
   7.440 +		return;
   7.441 +	b = strchr(buf, ' ');
   7.442 +	if (b == NULL)
   7.443 +		command_len = strlen(buf);
   7.444 +	else
   7.445 +		command_len = b - buf;
   7.446 +	b = buf + command_len;
   7.447 +	while (b[0] && b[0] == ' ')
   7.448 +		b++;
   7.449 +
   7.450 +	cmd = &default_command;
   7.451 +	for (x = 0; x < sizeof(commands) / sizeof(commands[0]); x++) {
   7.452 +		if (strlen(commands[x].name) == command_len &&
   7.453 +		    memcmp(commands[x].name, buf, command_len) == 0) {
   7.454 +			cmd = &commands[x];
   7.455 +			break;
   7.456 +		}
   7.457 +	}
   7.458 +	cmd->func(oc, cmd, buf, b);
   7.459 +	free(buf);
   7.460 +	return;
   7.461 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/x2d2/domain_controller.h	Sat Nov 13 10:05:50 2004 +0000
     8.3 @@ -0,0 +1,562 @@
     8.4 +/******************************************************************************
     8.5 + * domain_controller.h
     8.6 + * 
     8.7 + * Interface to server controller (e.g., 'xend'). This header file defines the 
     8.8 + * interface that is shared with guest OSes.
     8.9 + * 
    8.10 + * Copyright (c) 2004, K A Fraser
    8.11 + */
    8.12 +
    8.13 +/* I've copied this from the xen source pool as getting Xen and
    8.14 +   userspace headers to play nicely together is beyond me -- sos22 */
    8.15 +#define PACKED __attribute__ ((packed))
    8.16 +typedef unsigned long memory_t;   /* Full-sized pointer/address/memory-size. */
    8.17 +#define __MEMORY_PADDING(_X) u32 __pad_ ## _X
    8.18 +#define _MEMORY_PADDING(_X)  __MEMORY_PADDING(_X)
    8.19 +#define MEMORY_PADDING       _MEMORY_PADDING(__LINE__)
    8.20 +typedef u16 domid_t;
    8.21 +
    8.22 +/*
    8.23 + * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
    8.24 + * interpreted by control software to determine the appropriate action. These 
    8.25 + * are only really advisories: the controller can actually do as it likes.
    8.26 + */
    8.27 +#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
    8.28 +#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
    8.29 +#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
    8.30 +
    8.31 +
    8.32 +/*
    8.33 + * CONTROLLER MESSAGING INTERFACE.
    8.34 + */
    8.35 +
    8.36 +typedef struct {
    8.37 +    u8 type;     /*  0: echoed in response */
    8.38 +    u8 subtype;  /*  1: echoed in response */
    8.39 +    u8 id;       /*  2: echoed in response */
    8.40 +    u8 length;   /*  3: number of bytes in 'msg' */
    8.41 +    u8 msg[60];  /*  4: type-specific message data */
    8.42 +} PACKED control_msg_t; /* 64 bytes */
    8.43 +
    8.44 +#define CONTROL_RING_SIZE 8
    8.45 +typedef u32 CONTROL_RING_IDX;
    8.46 +#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
    8.47 +
    8.48 +typedef struct {
    8.49 +    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
    8.50 +    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
    8.51 +    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
    8.52 +    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
    8.53 +} PACKED control_if_t; /* 1040 bytes */
    8.54 +
    8.55 +/*
    8.56 + * Top-level command types.
    8.57 + */
    8.58 +#define CMSG_CONSOLE        0  /* Console                 */
    8.59 +#define CMSG_BLKIF_BE       1  /* Block-device backend    */
    8.60 +#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
    8.61 +#define CMSG_NETIF_BE       3  /* Network-device backend  */
    8.62 +#define CMSG_NETIF_FE       4  /* Network-device frontend */
    8.63 +#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
    8.64 +#define CMSG_PDB_BE         7  /* PDB backend.            */
    8.65 +#define CMSG_PDB_FE         8  /* PDB frontend.           */
    8.66 +
    8.67 +/******************************************************************************
    8.68 + * CONSOLE DEFINITIONS
    8.69 + */
    8.70 +
    8.71 +/*
    8.72 + * Subtypes for console messages.
    8.73 + */
    8.74 +#define CMSG_CONSOLE_DATA       0
    8.75 +
    8.76 +
    8.77 +/******************************************************************************
    8.78 + * BLOCK-INTERFACE FRONTEND DEFINITIONS
    8.79 + */
    8.80 +
    8.81 +/* Messages from domain controller to guest. */
    8.82 +#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
    8.83 +
    8.84 +/* Messages from guest to domain controller. */
    8.85 +#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
    8.86 +#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
    8.87 +#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
    8.88 +
    8.89 +/* These are used by both front-end and back-end drivers. */
    8.90 +#define blkif_vdev_t   u16
    8.91 +#define blkif_pdev_t   u16
    8.92 +#define blkif_sector_t u64
    8.93 +
    8.94 +/*
    8.95 + * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
    8.96 + *  Notify a guest about a status change on one of its block interfaces.
    8.97 + *  If the interface is DESTROYED or DOWN then the interface is disconnected:
    8.98 + *   1. The shared-memory frame is available for reuse.
    8.99 + *   2. Any unacknowledged messgaes pending on the interface were dropped.
   8.100 + */
   8.101 +#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
   8.102 +#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
   8.103 +#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
   8.104 +typedef struct {
   8.105 +    u32 handle; /*  0 */
   8.106 +    u32 status; /*  4 */
   8.107 +    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
   8.108 +} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
   8.109 +
   8.110 +/*
   8.111 + * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
   8.112 + *  Notify the domain controller that the front-end driver is DOWN or UP.
   8.113 + *  When the driver goes DOWN then the controller will send no more
   8.114 + *  status-change notifications. When the driver comes UP then the controller
   8.115 + *  will send a notification for each interface that currently exists.
   8.116 + *  If the driver goes DOWN while interfaces are still UP, the domain
   8.117 + *  will automatically take the interfaces DOWN.
   8.118 + */
   8.119 +#define BLKIF_DRIVER_STATUS_DOWN   0
   8.120 +#define BLKIF_DRIVER_STATUS_UP     1
   8.121 +typedef struct {
   8.122 +    /* IN */
   8.123 +    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
   8.124 +    /* OUT */
   8.125 +    /*
   8.126 +     * Tells driver how many interfaces it should expect to immediately
   8.127 +     * receive notifications about.
   8.128 +     */
   8.129 +    u32 nr_interfaces; /*  4 */
   8.130 +} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
   8.131 +
   8.132 +/*
   8.133 + * CMSG_BLKIF_FE_INTERFACE_CONNECT:
   8.134 + *  If successful, the domain controller will acknowledge with a
   8.135 + *  STATUS_CONNECTED message.
   8.136 + */
   8.137 +typedef struct {
   8.138 +    u32      handle;      /*  0 */
   8.139 +    u32      __pad;
   8.140 +    memory_t shmem_frame; /*  8 */
   8.141 +    MEMORY_PADDING;
   8.142 +} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
   8.143 +
   8.144 +/*
   8.145 + * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
   8.146 + *  If successful, the domain controller will acknowledge with a
   8.147 + *  STATUS_DISCONNECTED message.
   8.148 + */
   8.149 +typedef struct {
   8.150 +    u32 handle; /*  0 */
   8.151 +} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
   8.152 +
   8.153 +
   8.154 +/******************************************************************************
   8.155 + * BLOCK-INTERFACE BACKEND DEFINITIONS
   8.156 + */
   8.157 +
   8.158 +/* Messages from domain controller. */
   8.159 +#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
   8.160 +#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
   8.161 +#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
   8.162 +#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
   8.163 +#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
   8.164 +#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
   8.165 +#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
   8.166 +#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
   8.167 +
   8.168 +/* Messages to domain controller. */
   8.169 +#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
   8.170 +
   8.171 +/*
   8.172 + * Message request/response definitions for block-device messages.
   8.173 + */
   8.174 +
   8.175 +typedef struct {
   8.176 +    blkif_sector_t sector_start;   /*  0 */
   8.177 +    blkif_sector_t sector_length;  /*  8 */
   8.178 +    blkif_pdev_t   device;         /* 16 */
   8.179 +    u16            __pad;          /* 18 */
   8.180 +} PACKED blkif_extent_t; /* 20 bytes */
   8.181 +
   8.182 +/* Non-specific 'okay' return. */
   8.183 +#define BLKIF_BE_STATUS_OKAY                0
   8.184 +/* Non-specific 'error' return. */
   8.185 +#define BLKIF_BE_STATUS_ERROR               1
   8.186 +/* The following are specific error returns. */
   8.187 +#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
   8.188 +#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
   8.189 +#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
   8.190 +#define BLKIF_BE_STATUS_VBD_EXISTS          5
   8.191 +#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
   8.192 +#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
   8.193 +#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
   8.194 +#define BLKIF_BE_STATUS_MAPPING_ERROR       9
   8.195 +
   8.196 +/* This macro can be used to create an array of descriptive error strings. */
   8.197 +#define BLKIF_BE_STATUS_ERRORS {    \
   8.198 +    "Okay",                         \
   8.199 +    "Non-specific error",           \
   8.200 +    "Interface already exists",     \
   8.201 +    "Interface not found",          \
   8.202 +    "Interface is still connected", \
   8.203 +    "VBD already exists",           \
   8.204 +    "VBD not found",                \
   8.205 +    "Out of memory",                \
   8.206 +    "Extent not found for VBD",     \
   8.207 +    "Could not map domain memory" }
   8.208 +
   8.209 +/*
   8.210 + * CMSG_BLKIF_BE_CREATE:
   8.211 + *  When the driver sends a successful response then the interface is fully
   8.212 + *  created. The controller will send a DOWN notification to the front-end
   8.213 + *  driver.
   8.214 + */
   8.215 +typedef struct { 
   8.216 +    /* IN */
   8.217 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   8.218 +    u16        __pad;
   8.219 +    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
   8.220 +    /* OUT */
   8.221 +    u32        status;        /*  8 */
   8.222 +} PACKED blkif_be_create_t; /* 12 bytes */
   8.223 +
   8.224 +/*
   8.225 + * CMSG_BLKIF_BE_DESTROY:
   8.226 + *  When the driver sends a successful response then the interface is fully
   8.227 + *  torn down. The controller will send a DESTROYED notification to the
   8.228 + *  front-end driver.
   8.229 + */
   8.230 +typedef struct { 
   8.231 +    /* IN */
   8.232 +    domid_t    domid;         /*  0: Identify interface to be destroyed. */
   8.233 +    u16        __pad;
   8.234 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   8.235 +    /* OUT */
   8.236 +    u32        status;        /*  8 */
   8.237 +} PACKED blkif_be_destroy_t; /* 12 bytes */
   8.238 +
   8.239 +/*
   8.240 + * CMSG_BLKIF_BE_CONNECT:
   8.241 + *  When the driver sends a successful response then the interface is fully
   8.242 + *  connected. The controller will send a CONNECTED notification to the
   8.243 + *  front-end driver.
   8.244 + */
   8.245 +typedef struct { 
   8.246 +    /* IN */
   8.247 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   8.248 +    u16        __pad;
   8.249 +    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
   8.250 +    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
   8.251 +    MEMORY_PADDING;
   8.252 +    u32        evtchn;        /* 16: Event channel for notifications.    */
   8.253 +    /* OUT */
   8.254 +    u32        status;        /* 20 */
   8.255 +} PACKED blkif_be_connect_t;  /* 24 bytes */
   8.256 +
   8.257 +/*
   8.258 + * CMSG_BLKIF_BE_DISCONNECT:
   8.259 + *  When the driver sends a successful response then the interface is fully
   8.260 + *  disconnected. The controller will send a DOWN notification to the front-end
   8.261 + *  driver.
   8.262 + */
   8.263 +typedef struct { 
   8.264 +    /* IN */
   8.265 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   8.266 +    u16        __pad;
   8.267 +    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
   8.268 +    /* OUT */
   8.269 +    u32        status;        /*  8 */
   8.270 +} PACKED blkif_be_disconnect_t; /* 12 bytes */
   8.271 +
   8.272 +/* CMSG_BLKIF_BE_VBD_CREATE */
   8.273 +typedef struct { 
   8.274 +    /* IN */
   8.275 +    domid_t    domid;         /*  0: Identify blkdev interface.          */
   8.276 +    u16        __pad;
   8.277 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   8.278 +    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
   8.279 +    u16        readonly;      /* 10: Non-zero -> VBD isn't writable.     */
   8.280 +    /* OUT */
   8.281 +    u32        status;        /* 12 */
   8.282 +} PACKED blkif_be_vbd_create_t; /* 16 bytes */
   8.283 +
   8.284 +/* CMSG_BLKIF_BE_VBD_DESTROY */
   8.285 +typedef struct {
   8.286 +    /* IN */
   8.287 +    domid_t    domid;         /*  0: Identify blkdev interface.          */
   8.288 +    u16        __pad0;        /*  2 */
   8.289 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   8.290 +    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
   8.291 +    u16        __pad1;        /* 10 */
   8.292 +    /* OUT */
   8.293 +    u32        status;        /* 12 */
   8.294 +} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
   8.295 +
   8.296 +/* CMSG_BLKIF_BE_VBD_GROW */
   8.297 +typedef struct { 
   8.298 +    /* IN */
   8.299 +    domid_t    domid;         /*  0: Identify blkdev interface.          */
   8.300 +    u16        __pad0;        /*  2 */
   8.301 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   8.302 +    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
   8.303 +    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
   8.304 +    u16        __pad1;        /* 30 */
   8.305 +    /* OUT */
   8.306 +    u32        status;        /* 32 */
   8.307 +} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
   8.308 +
   8.309 +/* CMSG_BLKIF_BE_VBD_SHRINK */
   8.310 +typedef struct { 
   8.311 +    /* IN */
   8.312 +    domid_t    domid;         /*  0: Identify blkdev interface.          */
   8.313 +    u16        __pad0;        /*  2 */
   8.314 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   8.315 +    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
   8.316 +    u16        __pad1;        /* 10 */
   8.317 +    /* OUT */
   8.318 +    u32        status;        /* 12 */
   8.319 +} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
   8.320 +
   8.321 +/*
   8.322 + * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
   8.323 + *  Notify the domain controller that the back-end driver is DOWN or UP.
   8.324 + *  If the driver goes DOWN while interfaces are still UP, the controller
   8.325 + *  will automatically send DOWN notifications.
   8.326 + */
   8.327 +typedef struct {
   8.328 +    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
   8.329 +} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
   8.330 +
   8.331 +
   8.332 +/******************************************************************************
   8.333 + * NETWORK-INTERFACE FRONTEND DEFINITIONS
   8.334 + */
   8.335 +
   8.336 +/* Messages from domain controller to guest. */
   8.337 +#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
   8.338 +
   8.339 +/* Messages from guest to domain controller. */
   8.340 +#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
   8.341 +#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
   8.342 +#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
   8.343 +
   8.344 +/*
   8.345 + * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
   8.346 + *  Notify a guest about a status change on one of its network interfaces.
   8.347 + *  If the interface is DESTROYED or DOWN then the interface is disconnected:
   8.348 + *   1. The shared-memory frame is available for reuse.
   8.349 + *   2. Any unacknowledged messgaes pending on the interface were dropped.
   8.350 + */
   8.351 +#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
   8.352 +#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
   8.353 +#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
   8.354 +typedef struct {
   8.355 +    u32        handle; /*  0 */
   8.356 +    u32        status; /*  4 */
   8.357 +    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
   8.358 +    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
   8.359 +} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
   8.360 +
   8.361 +/*
   8.362 + * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
   8.363 + *  Notify the domain controller that the front-end driver is DOWN or UP.
   8.364 + *  When the driver goes DOWN then the controller will send no more
   8.365 + *  status-change notifications. When the driver comes UP then the controller
   8.366 + *  will send a notification for each interface that currently exists.
   8.367 + *  If the driver goes DOWN while interfaces are still UP, the domain
   8.368 + *  will automatically take the interfaces DOWN.
   8.369 + */
   8.370 +#define NETIF_DRIVER_STATUS_DOWN   0
   8.371 +#define NETIF_DRIVER_STATUS_UP     1
   8.372 +typedef struct {
   8.373 +    /* IN */
   8.374 +    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
   8.375 +    /* OUT */
   8.376 +    /*
   8.377 +     * Tells driver how many interfaces it should expect to immediately
   8.378 +     * receive notifications about.
   8.379 +     */
   8.380 +    u32        nr_interfaces; /*  4 */
   8.381 +} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
   8.382 +
   8.383 +/*
   8.384 + * CMSG_NETIF_FE_INTERFACE_CONNECT:
   8.385 + *  If successful, the domain controller will acknowledge with a
   8.386 + *  STATUS_CONNECTED message.
   8.387 + */
   8.388 +typedef struct {
   8.389 +    u32        handle;         /*  0 */
   8.390 +    u32        __pad;          /*  4 */
   8.391 +    memory_t   tx_shmem_frame; /*  8 */
   8.392 +    MEMORY_PADDING;
   8.393 +    memory_t   rx_shmem_frame; /* 16 */
   8.394 +    MEMORY_PADDING;
   8.395 +} PACKED netif_fe_interface_connect_t; /* 24 bytes */
   8.396 +
   8.397 +/*
   8.398 + * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
   8.399 + *  If successful, the domain controller will acknowledge with a
   8.400 + *  STATUS_DISCONNECTED message.
   8.401 + */
   8.402 +typedef struct {
   8.403 +    u32        handle;        /*  0 */
   8.404 +} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
   8.405 +
   8.406 +
   8.407 +/******************************************************************************
   8.408 + * NETWORK-INTERFACE BACKEND DEFINITIONS
   8.409 + */
   8.410 +
   8.411 +/* Messages from domain controller. */
   8.412 +#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
   8.413 +#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
   8.414 +#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
   8.415 +#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
   8.416 +
   8.417 +/* Messages to domain controller. */
   8.418 +#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
   8.419 +
   8.420 +/*
   8.421 + * Message request/response definitions for net-device messages.
   8.422 + */
   8.423 +
   8.424 +/* Non-specific 'okay' return. */
   8.425 +#define NETIF_BE_STATUS_OKAY                0
   8.426 +/* Non-specific 'error' return. */
   8.427 +#define NETIF_BE_STATUS_ERROR               1
   8.428 +/* The following are specific error returns. */
   8.429 +#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
   8.430 +#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
   8.431 +#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
   8.432 +#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
   8.433 +#define NETIF_BE_STATUS_MAPPING_ERROR       6
   8.434 +
   8.435 +/* This macro can be used to create an array of descriptive error strings. */
   8.436 +#define NETIF_BE_STATUS_ERRORS {    \
   8.437 +    "Okay",                         \
   8.438 +    "Non-specific error",           \
   8.439 +    "Interface already exists",     \
   8.440 +    "Interface not found",          \
   8.441 +    "Interface is still connected", \
   8.442 +    "Out of memory",                \
   8.443 +    "Could not map domain memory" }
   8.444 +
   8.445 +/*
   8.446 + * CMSG_NETIF_BE_CREATE:
   8.447 + *  When the driver sends a successful response then the interface is fully
   8.448 + *  created. The controller will send a DOWN notification to the front-end
   8.449 + *  driver.
   8.450 + */
   8.451 +typedef struct { 
   8.452 +    /* IN */
   8.453 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   8.454 +    u16        __pad0;        /*  2 */
   8.455 +    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
   8.456 +    u8         mac[6];        /*  8 */
   8.457 +    u16        __pad1;        /* 14 */
   8.458 +    /* OUT */
   8.459 +    u32        status;        /* 16 */
   8.460 +} PACKED netif_be_create_t; /* 20 bytes */
   8.461 +
   8.462 +/*
   8.463 + * CMSG_NETIF_BE_DESTROY:
   8.464 + *  When the driver sends a successful response then the interface is fully
   8.465 + *  torn down. The controller will send a DESTROYED notification to the
   8.466 + *  front-end driver.
   8.467 + */
   8.468 +typedef struct { 
   8.469 +    /* IN */
   8.470 +    domid_t    domid;         /*  0: Identify interface to be destroyed. */
   8.471 +    u16        __pad;
   8.472 +    u32        netif_handle;  /*  4: ...ditto...                         */
   8.473 +    /* OUT */
   8.474 +    u32   status;             /*  8 */
   8.475 +} PACKED netif_be_destroy_t; /* 12 bytes */
   8.476 +
   8.477 +/*
   8.478 + * CMSG_NETIF_BE_CONNECT:
   8.479 + *  When the driver sends a successful response then the interface is fully
   8.480 + *  connected. The controller will send a CONNECTED notification to the
   8.481 + *  front-end driver.
   8.482 + */
   8.483 +typedef struct { 
   8.484 +    /* IN */
   8.485 +    domid_t    domid;          /*  0: Domain attached to new interface.   */
   8.486 +    u16        __pad0;         /*  2 */
   8.487 +    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
   8.488 +    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
   8.489 +    MEMORY_PADDING;
   8.490 +    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
   8.491 +    MEMORY_PADDING;
   8.492 +    u16        evtchn;         /* 24: Event channel for notifications.    */
   8.493 +    u16        __pad1;         /* 26 */
   8.494 +    /* OUT */
   8.495 +    u32        status;         /* 28 */
   8.496 +} PACKED netif_be_connect_t; /* 32 bytes */
   8.497 +
   8.498 +/*
   8.499 + * CMSG_NETIF_BE_DISCONNECT:
   8.500 + *  When the driver sends a successful response then the interface is fully
   8.501 + *  disconnected. The controller will send a DOWN notification to the front-end
   8.502 + *  driver.
   8.503 + */
   8.504 +typedef struct { 
   8.505 +    /* IN */
   8.506 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   8.507 +    u16        __pad;
   8.508 +    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
   8.509 +    /* OUT */
   8.510 +    u32        status;        /*  8 */
   8.511 +} PACKED netif_be_disconnect_t; /* 12 bytes */
   8.512 +
   8.513 +/*
   8.514 + * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
   8.515 + *  Notify the domain controller that the back-end driver is DOWN or UP.
   8.516 + *  If the driver goes DOWN while interfaces are still UP, the domain
   8.517 + *  will automatically send DOWN notifications.
   8.518 + */
   8.519 +typedef struct {
   8.520 +    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
   8.521 +} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
   8.522 +
   8.523 +
   8.524 +/******************************************************************************
   8.525 + * SHUTDOWN DEFINITIONS
   8.526 + */
   8.527 +
   8.528 +/*
   8.529 + * Subtypes for shutdown messages.
   8.530 + */
   8.531 +#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
   8.532 +#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
   8.533 +#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
   8.534 +                                    /* SHUTDOWN_suspend.                     */
   8.535 +
   8.536 +/******************************************************************************
   8.537 + * PDB DEFINITIONS
   8.538 + */
   8.539 +
   8.540 +/* Notify the backend that a new frontend has connected. */
   8.541 +#define CMSG_PDB_BE_INTERFACE_CONNECTED 0
   8.542 +typedef struct {
   8.543 +    int assist_port;
   8.544 +    int event_port;
   8.545 +} pdb_be_connected_t;
   8.546 +
   8.547 +/* Notify the domain controller that the status of the backend has
   8.548 +   changed. */
   8.549 +#define CMSG_PDB_BE_DRIVER_STATUS_CHANGED 1
   8.550 +typedef struct {
   8.551 +    unsigned status;
   8.552 +#define PDB_DRIVER_STATUS_UP 1
   8.553 +    unsigned long event_page;
   8.554 +    unsigned long assist_page;
   8.555 +} pdb_be_driver_status_changed_t;
   8.556 +
   8.557 +/* Notify a front end that a back end just popped up. */
   8.558 +#define CMSG_PDB_FE_NEW_BE 0
   8.559 +typedef struct {
   8.560 +    int domain;
   8.561 +    int assist_evtchn;
   8.562 +    int event_evtchn;
   8.563 +    unsigned long assist_frame;
   8.564 +    unsigned long event_frame;
   8.565 +} pdb_fe_new_be_t;
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/x2d2/main.c	Sat Nov 13 10:05:50 2004 +0000
     9.3 @@ -0,0 +1,1015 @@
     9.4 +#define _GNU_SOURCE
     9.5 +
     9.6 +#include <sys/types.h>
     9.7 +#include <sys/fcntl.h>
     9.8 +#include <sys/ioctl.h>
     9.9 +#include <sys/mman.h>
    9.10 +#include <sys/select.h>
    9.11 +#include <sys/socket.h>
    9.12 +#include <sys/wait.h>
    9.13 +#include <asm/page.h>
    9.14 +#include <assert.h>
    9.15 +#include <ctype.h>
    9.16 +#include <err.h>
    9.17 +#include <errno.h>
    9.18 +#include <netinet/in.h>
    9.19 +#include <printf.h>
    9.20 +#include <pthread.h>
    9.21 +#include <stdarg.h>
    9.22 +#include <stddef.h>
    9.23 +#include <stdio.h>
    9.24 +#include <stdlib.h>
    9.25 +#include <string.h>
    9.26 +#include <unistd.h>
    9.27 +
    9.28 +#include "minixend.h"
    9.29 +
    9.30 +#define NETWORK_SCRIPT "/etc/xen/scripts/network"
    9.31 +#define VIFBRIDGE_SCRIPT "/etc/xen/scripts/vif-bridge"
    9.32 +
    9.33 +#define MINIXEND_PORT 5123
    9.34 +
    9.35 +#define mb() asm volatile ("" ::: "memory")
    9.36 +
    9.37 +static void send_control_message(int type, int subtype, int id,
    9.38 +				 int size, void *payload,
    9.39 +				 struct domain *target);
    9.40 +
    9.41 +struct list_head
    9.42 +head_domain = LIST_HEAD(&head_domain);
    9.43 +
    9.44 +static struct list_head
    9.45 +head_connection = LIST_HEAD(&head_connection);
    9.46 +
    9.47 +struct list_head
    9.48 +head_console = LIST_HEAD(&head_console);
    9.49 +
    9.50 +#define foreach_open_connection(d)                                          \
    9.51 +foreach_item(d, &head_connection, struct open_connection, connection_list)
    9.52 +
    9.53 +/* Not modified after initial start up */
    9.54 +static struct domain *
    9.55 +dom0;
    9.56 +unsigned
    9.57 +xc_handle;
    9.58 +static int
    9.59 +listen_fd;
    9.60 +int
    9.61 +evtchn_fd;
    9.62 +
    9.63 +static struct list_head
    9.64 +head_event_receiver = LIST_HEAD(&head_event_receiver);
    9.65 +
    9.66 +struct event_receiver {
    9.67 +	struct list_head list;
    9.68 +	int id;
    9.69 +	pthread_cond_t cond;
    9.70 +};
    9.71 +
    9.72 +/* We're protected by the dom0 mutex in here */
    9.73 +static struct event_receiver *
    9.74 +allocate_event_receiver(struct domain *d)
    9.75 +{
    9.76 +	static int next_message_id;
    9.77 +	struct event_receiver *work;
    9.78 +
    9.79 +	assert(d == dom0);
    9.80 +	work = xmalloc(sizeof(*work));
    9.81 +	work->id = next_message_id++;
    9.82 +	pthread_cond_init(&work->cond, NULL);
    9.83 +
    9.84 +	list_insert_after(&work->list, &head_event_receiver);
    9.85 +
    9.86 +	return work;
    9.87 +}
    9.88 +
    9.89 +static struct event_receiver *
    9.90 +find_event_receiver(int id)
    9.91 +{
    9.92 +	struct event_receiver *work;
    9.93 +	foreach_item(work, &head_event_receiver, struct event_receiver, list)
    9.94 +		if (work->id == id)
    9.95 +			return work;
    9.96 +	return NULL;
    9.97 +}
    9.98 +
    9.99 +static void
   9.100 +release_event_receiver(struct event_receiver *w)
   9.101 +{
   9.102 +	list_remove(&w->list);
   9.103 +	pthread_cond_destroy(&w->cond);
   9.104 +	free(w);
   9.105 +}
   9.106 +
   9.107 +/* Send a message to dom0, and then block awaiting a reply. */
   9.108 +/* Make sure we don't hold any domain mutexs */
   9.109 +static void
   9.110 +send_dom0_message_block(control_msg_t *msg)
   9.111 +{
   9.112 +	CONTROL_RING_IDX c;
   9.113 +	struct event_receiver *er;
   9.114 +	control_msg_t buf;
   9.115 +
   9.116 +	PRINTF(0, "sending message to dom0 and blocking for reply.\n");
   9.117 +	pthread_mutex_lock(&dom0->mux);
   9.118 +	PRINTF(0, "got dom0 lock.\n");
   9.119 +	er = allocate_event_receiver(dom0);
   9.120 +	PRINTF(0, "allocated evetn receiver.\n");
   9.121 +	msg->id = er->id;
   9.122 +	PRINTF(1, "sending message with id %d\n", msg->id);
   9.123 +	send_control_message(msg->type, msg->subtype,
   9.124 +			     msg->id, msg->length, msg->msg, dom0);
   9.125 +	xc_evtchn_send(xc_handle, dom0->control_evtchn);
   9.126 +
   9.127 +	PRINTF(0, "waiting for reply\n");
   9.128 +	pthread_cond_wait(&er->cond, &dom0->mux);
   9.129 +	PRINTF(0, "got reply\n");
   9.130 +
   9.131 +	c = dom0->rx_resp_cons % CONTROL_RING_SIZE;
   9.132 +	memcpy(&buf, &dom0->ctrl_if->rx_ring[c], sizeof(buf));
   9.133 +	assert(msg->id == buf.id);
   9.134 +	assert(msg->type == buf.type);
   9.135 +	assert(msg->subtype == buf.subtype);
   9.136 +	memcpy(msg, &buf, sizeof(*msg));
   9.137 +	dom0->rx_resp_cons++;
   9.138 +
   9.139 +	release_event_receiver(er);
   9.140 +
   9.141 +	pthread_mutex_unlock(&dom0->mux);
   9.142 +
   9.143 +	PRINTF(1, "got reply to message with id %d\n", msg->id);
   9.144 +}
   9.145 +
   9.146 +/* Allocate an interdomain event channel.  event_ports[0] is the
   9.147 +   local event port number, event_ports[1] the remote */
   9.148 +int
   9.149 +allocate_event_channel(struct domain *d, int event_ports[2])
   9.150 +{
   9.151 +	return xc_evtchn_bind_interdomain(xc_handle, DOMID_SELF,
   9.152 +					  d->domid, event_ports,
   9.153 +					  event_ports+1);
   9.154 +}
   9.155 +
   9.156 +static void
   9.157 +accept_new_connection(void)
   9.158 +{
   9.159 +	int fd;
   9.160 +	struct open_connection *oc;
   9.161 +
   9.162 +	fd = accept(listen_fd, NULL, NULL);
   9.163 +	if (fd < 0)
   9.164 +		return;
   9.165 +	oc = xmalloc(sizeof(*oc));
   9.166 +	oc->fd = fd;
   9.167 +	oc->state = OC_STATE_CONNECTED;
   9.168 +	oc->buf_used = 0;
   9.169 +	oc->buf_allocated = 16;
   9.170 +	oc->buf = xmalloc(oc->buf_allocated);
   9.171 +	list_insert_after(&oc->connection_list, &head_connection);
   9.172 +}
   9.173 +
   9.174 +static void
   9.175 +closedown_connection(struct open_connection *oc)
   9.176 +{
   9.177 +	close(oc->fd);
   9.178 +	assert(oc->buf);
   9.179 +	free(oc->buf);
   9.180 +	free(oc);
   9.181 +}
   9.182 +
   9.183 +#if 0
   9.184 +/* Hackl for the benefit of domain replay */
   9.185 +static unsigned
   9.186 +report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
   9.187 +{
   9.188 +	if (!do_direct) {
   9.189 +		int rc;
   9.190 +		asm("int $0x80" : "=a" (rc)
   9.191 +		    : "0" (264), "b" (ptr), "c" (val), "d" (dom));
   9.192 +		if (rc < 0) {
   9.193 +			errno = -rc;
   9.194 +			rc = -1;
   9.195 +		}
   9.196 +		return rc;
   9.197 +	} else {
   9.198 +		*ptr = val;
   9.199 +		return 0;
   9.200 +	}
   9.201 +}
   9.202 +#else
   9.203 +static unsigned
   9.204 +report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
   9.205 +{
   9.206 +	*ptr = val;
   9.207 +	return 0;
   9.208 +}
   9.209 +#endif
   9.210 +
   9.211 +static void
   9.212 +send_control_reply(const control_msg_t *msg, struct domain *d)
   9.213 +{
   9.214 +	CONTROL_RING_IDX c;
   9.215 +
   9.216 +	PRINTF(3,"Control reply, type %d:%d, length %d.\n",
   9.217 +	       msg->type, msg->subtype, msg->length);
   9.218 +	c = d->ctrl_if->tx_resp_prod % CONTROL_RING_SIZE;
   9.219 +	memcpy(&d->ctrl_if->tx_ring[c], msg, sizeof(*msg));
   9.220 +	report_work(&d->ctrl_if->tx_resp_prod,
   9.221 +		    d->ctrl_if->tx_resp_prod + 1,
   9.222 +		    d->domid,
   9.223 +		    0);
   9.224 +	PRINTF(4,"tx_resp_prod %ld.\n", d->ctrl_if->tx_resp_prod);
   9.225 +	assert(!d->plugged);
   9.226 +}
   9.227 +
   9.228 +static void
   9.229 +send_trivial_control_reply(const control_msg_t *msg, struct domain *d)
   9.230 +{
   9.231 +	control_msg_t rep;
   9.232 +
   9.233 +	memset(&rep, 0, sizeof(rep));
   9.234 +	rep.type = msg->type;
   9.235 +	rep.subtype = msg->subtype;
   9.236 +	rep.id = msg->id;
   9.237 +	send_control_reply(&rep, d);
   9.238 +}
   9.239 +
   9.240 +static void
   9.241 +process_console_control_message(control_msg_t *m, struct domain *d)
   9.242 +{
   9.243 +	int off;
   9.244 +	int r;
   9.245 +
   9.246 +	if (m->subtype != CMSG_CONSOLE_DATA) {
   9.247 +		warnx("unknown console message subtype %d",
   9.248 +		      m->subtype);
   9.249 +		return;
   9.250 +	}
   9.251 +
   9.252 +	if (m->length > 60) {
   9.253 +		warnx("truncating message from domain %d (was length %d)",
   9.254 +		      d->domid, m->length);
   9.255 +		m->length = 60;
   9.256 +	}
   9.257 +	PRINTF(1, "DOM%d: %.*s\n", d->domid, m->length, m->msg);
   9.258 +	send_trivial_control_reply(m, d);
   9.259 +
   9.260 +	if (d->cc) {
   9.261 +		PRINTF(5, "Have a console connection.\n");
   9.262 +		if (d->cc->state == CC_STATE_CONNECTED) {
   9.263 +			PRINTF(5, "Console is connected, sending directly.\n");
   9.264 +			for (off = 0; off < m->length; off += r) {
   9.265 +				r = write(d->cc->fd, m->msg + off,
   9.266 +					  m->length - off);
   9.267 +				if (r <= 0) {
   9.268 +					d->cc->state = CC_STATE_ERROR;
   9.269 +					break;
   9.270 +				}
   9.271 +			}
   9.272 +		} else {
   9.273 +			PRINTF(5, "Console not connected, buffering.\n");
   9.274 +			if (d->cc->buf_allocated == 0) {
   9.275 +				d->cc->buf_allocated = 60;
   9.276 +				d->cc->buf = xmalloc(d->cc->buf_allocated);
   9.277 +				d->cc->buf_used = 0;
   9.278 +			} else if (d->cc->buf_allocated <
   9.279 +				   d->cc->buf_used + m->length) {
   9.280 +				d->cc->buf_allocated += 60;
   9.281 +				d->cc->buf = xrealloc(d->cc->buf,
   9.282 +						      d->cc->buf_allocated);
   9.283 +			}
   9.284 +			assert(d->cc->buf_allocated >=
   9.285 +			       d->cc->buf_used + m->length);
   9.286 +			memcpy(d->cc->buf + d->cc->buf_used,
   9.287 +			       m->msg,
   9.288 +			       m->length);
   9.289 +			d->cc->buf_used += m->length;
   9.290 +		}
   9.291 +	}
   9.292 +}
   9.293 +
   9.294 +static void
   9.295 +process_blkif_fe_message(control_msg_t *m, struct domain *d)
   9.296 +{
   9.297 +	switch (m->subtype) {
   9.298 +	default:
   9.299 +		warnx("unknown blkif front end message subtype %d",
   9.300 +		      m->subtype);
   9.301 +	}
   9.302 +}
   9.303 +
   9.304 +static void
   9.305 +send_control_message(int type, int subtype, int id,
   9.306 +		     int size, void *payload, struct domain *target)
   9.307 +{
   9.308 +	control_msg_t msg;
   9.309 +	CONTROL_RING_IDX c;
   9.310 +
   9.311 +	msg.type = type;
   9.312 +	msg.subtype = subtype;
   9.313 +	msg.id = id;
   9.314 +	msg.length = size;
   9.315 +	memcpy(msg.msg, payload, size);
   9.316 +
   9.317 +	c = target->ctrl_if->rx_req_prod % CONTROL_RING_SIZE;
   9.318 +	memcpy(&target->ctrl_if->rx_ring[c], &msg, sizeof(msg));
   9.319 +	report_work(&target->ctrl_if->rx_req_prod,
   9.320 +		    target->ctrl_if->rx_req_prod + 1,
   9.321 +		    target->domid,
   9.322 +		    0);
   9.323 +	assert(!target->plugged);
   9.324 +}
   9.325 +
   9.326 +/* Procedure for bringing a new netif front end up:
   9.327 +
   9.328 +   -- Front end sends us NETIF_FE_DRIVER_STATUS_CHANGED
   9.329 +   -- We send back end NETIF_BE_CREATE, wait for a reply
   9.330 +   -- Back end creates a new netif for us, replies
   9.331 +   -- We send front end a NETIF_FE_DRIVER_STATUS_CHANGED message saying
   9.332 +      how many interfaces we've created for it
   9.333 +   -- We send front end a NETIF_FE_INTERFACE_STATUS_CHANGED for each
   9.334 +      netif created
   9.335 +   -- Front end sends us a NETIF_FE_INTERFACE_CONNECT for each netif
   9.336 +*/
   9.337 +static void
   9.338 +handle_netif_fe_driver_status_changed(control_msg_t *m,
   9.339 +				      netif_fe_driver_status_changed_t *sh,
   9.340 +				      struct domain *d)
   9.341 +{
   9.342 +	netif_fe_interface_status_changed_t if_s;
   9.343 +	control_msg_t be_msg;
   9.344 +	netif_be_create_t *be = (void *)be_msg.msg;
   9.345 +	int r;
   9.346 +
   9.347 +	switch (sh->status) {
   9.348 +	case NETIF_DRIVER_STATUS_UP:
   9.349 +		/* Tell the back end about the new interface coming
   9.350 +		 * up. */
   9.351 +		if (d->created_netif_backend) {
   9.352 +			PRINTF(10, "Front end came up twice in dom %d -> reporting no interfaces this time around.\n", d->domid);
   9.353 +			sh->nr_interfaces = 0;
   9.354 +			send_control_reply(m, d);
   9.355 +			send_control_message(CMSG_NETIF_FE,
   9.356 +					     CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
   9.357 +					     1,
   9.358 +					     sizeof(*sh),
   9.359 +					     sh,
   9.360 +					     d);
   9.361 +			return;
   9.362 +		}
   9.363 +		be_msg.type = CMSG_NETIF_BE;
   9.364 +		be_msg.subtype = CMSG_NETIF_BE_CREATE;
   9.365 +		be_msg.id = d->domid;
   9.366 +		be_msg.length = sizeof(*be);
   9.367 +		be->domid = d->domid;
   9.368 +		be->netif_handle = 0;
   9.369 +		memcpy(be->mac, d->netif_mac, 6);
   9.370 +
   9.371 +		PRINTF(2,"Telling back end about new front end.\n");
   9.372 +		pthread_mutex_unlock(&d->mux);
   9.373 +		send_dom0_message_block(&be_msg);
   9.374 +		pthread_mutex_lock(&d->mux);
   9.375 +		PRINTF(3,"Done.\n");
   9.376 +
   9.377 +		if (be->status != NETIF_BE_STATUS_OKAY) {
   9.378 +			/* Uh oh... can't bring back end
   9.379 +			 * up. */
   9.380 +			sh->nr_interfaces = 0;
   9.381 +			send_control_reply(m, d);
   9.382 +			send_control_message(CMSG_NETIF_FE,
   9.383 +					     CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
   9.384 +					     1,
   9.385 +					     sizeof(*sh),
   9.386 +					     sh,
   9.387 +					     d);
   9.388 +			return;
   9.389 +		}
   9.390 +		d->created_netif_backend = 1;
   9.391 +
   9.392 +		r = our_system(VIFBRIDGE_SCRIPT " up domain=%s mac=%.02x:%.02x:%.02x:%.02x:%.02x:%.02x vif=vif%d.0 bridge=xen-br0",
   9.393 +			       d->name,
   9.394 +			       d->netif_mac[0],
   9.395 +			       d->netif_mac[1],
   9.396 +			       d->netif_mac[2],
   9.397 +			       d->netif_mac[3],
   9.398 +			       d->netif_mac[4],
   9.399 +			       d->netif_mac[5],
   9.400 +			       d->domid);
   9.401 +		if (r != 0)
   9.402 +			warn("error %d running " VIFBRIDGE_SCRIPT, r);
   9.403 +
   9.404 +		/* Tell domain how many interfaces it has to deal
   9.405 +		 * with. */
   9.406 +		sh->nr_interfaces = 1;
   9.407 +		send_control_reply(m, d);
   9.408 +		send_control_message(CMSG_NETIF_FE,
   9.409 +				     CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
   9.410 +				     1,
   9.411 +				     sizeof(*sh),
   9.412 +				     sh,
   9.413 +				     d);
   9.414 +
   9.415 +		PRINTF(2,"Telling front end about its interfaces.\n");
   9.416 +		if_s.handle = 0;
   9.417 +		if_s.status = NETIF_INTERFACE_STATUS_DISCONNECTED;
   9.418 +		send_control_message(CMSG_NETIF_FE,
   9.419 +				     CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED,
   9.420 +				     1,
   9.421 +				     sizeof(if_s),
   9.422 +				     &if_s,
   9.423 +				     d);
   9.424 +		PRINTF(3,"Done.\n");
   9.425 +
   9.426 +		break;
   9.427 +	default:
   9.428 +		warnx("unknown netif status %ld", sh->status);
   9.429 +		break;
   9.430 +	}
   9.431 +}
   9.432 +
   9.433 +static void
   9.434 +handle_netif_fe_interface_connect(control_msg_t *m,
   9.435 +				  netif_fe_interface_connect_t *ic,
   9.436 +				  struct domain *d)
   9.437 +{
   9.438 +	control_msg_t be_msg;
   9.439 +	netif_be_connect_t *bmsg = (void *)be_msg.msg;
   9.440 +	netif_fe_interface_status_changed_t fmsg = {0};
   9.441 +	int evtchn_ports[2];
   9.442 +	int r;
   9.443 +
   9.444 +	PRINTF(4, "front end sent us an interface connect message.\n");
   9.445 +	send_trivial_control_reply(m, d);
   9.446 +
   9.447 +	r = xc_evtchn_bind_interdomain(xc_handle,
   9.448 +				       dom0->domid,
   9.449 +				       d->domid,
   9.450 +				       &evtchn_ports[0],
   9.451 +				       &evtchn_ports[1]);
   9.452 +	if (r < 0)
   9.453 +		err(1, "allocating network event channel");
   9.454 +
   9.455 +	be_msg.type = CMSG_NETIF_BE;
   9.456 +	be_msg.subtype = CMSG_NETIF_BE_CONNECT;
   9.457 +	be_msg.id = 0;
   9.458 +	be_msg.length = sizeof(*bmsg);
   9.459 +	bmsg->domid = d->domid;
   9.460 +	bmsg->netif_handle = ic->handle;
   9.461 +	bmsg->tx_shmem_frame = ic->tx_shmem_frame;
   9.462 +	bmsg->rx_shmem_frame = ic->rx_shmem_frame;
   9.463 +	bmsg->evtchn = evtchn_ports[0];
   9.464 +
   9.465 +	pthread_mutex_unlock(&d->mux);
   9.466 +	send_dom0_message_block(&be_msg);
   9.467 +	pthread_mutex_lock(&d->mux);
   9.468 +
   9.469 +	if (bmsg->status != NETIF_BE_STATUS_OKAY) {
   9.470 +		PRINTF(2, "error connected backend netif: %ld\n",
   9.471 +		       bmsg->status);
   9.472 +		abort(); /* Need to handle this */
   9.473 +	} else {
   9.474 +		PRINTF(3, "connect backend netif\n");
   9.475 +
   9.476 +		/* Tell the domain that we've connected it up. */
   9.477 +		fmsg.handle = ic->handle;
   9.478 +		fmsg.status = NETIF_INTERFACE_STATUS_CONNECTED;
   9.479 +		fmsg.evtchn = evtchn_ports[1];
   9.480 +		memcpy(fmsg.mac, d->netif_mac, 6);
   9.481 +
   9.482 +		send_control_message(CMSG_NETIF_FE,
   9.483 +				     CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED,
   9.484 +				     0,
   9.485 +				     sizeof(fmsg),
   9.486 +				     &fmsg,
   9.487 +				     d);
   9.488 +	}
   9.489 +}
   9.490 +
   9.491 +static void
   9.492 +process_netif_fe_message(control_msg_t *m, struct domain *d)
   9.493 +{
   9.494 +	switch (m->subtype) {
   9.495 +	case CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
   9.496 +	{
   9.497 +		netif_fe_driver_status_changed_t *sh =
   9.498 +			(netif_fe_driver_status_changed_t *)m->msg;
   9.499 +		handle_netif_fe_driver_status_changed(m, sh, d);
   9.500 +		break;
   9.501 +	}
   9.502 +	case CMSG_NETIF_FE_INTERFACE_CONNECT:
   9.503 +	{
   9.504 +		netif_fe_interface_connect_t *ic =
   9.505 +			(netif_fe_interface_connect_t *)m->msg;
   9.506 +		handle_netif_fe_interface_connect(m, ic, d);
   9.507 +		break;
   9.508 +	}
   9.509 +	default:
   9.510 +		warnx("unknown netif front end message subtype %d",
   9.511 +		      m->subtype);
   9.512 +	}
   9.513 +}
   9.514 +
   9.515 +static void
   9.516 +process_pdb_be_driver_status_changed_message(control_msg_t *msg,
   9.517 +					     pdb_be_driver_status_changed_t*pe,
   9.518 +					     struct domain *d)
   9.519 +{
   9.520 +	pdb_be_connected_t conn;
   9.521 +	pdb_fe_new_be_t new_be;
   9.522 +	int assist_channel[2];
   9.523 +	int event_channel[2];
   9.524 +	int r;
   9.525 +
   9.526 +	switch (pe->status) {
   9.527 +	case PDB_DRIVER_STATUS_UP:
   9.528 +		PRINTF(4, "creating event channel for PDB device\n");
   9.529 +		r = allocate_event_channel(d, assist_channel);
   9.530 +		r |= allocate_event_channel(d, event_channel);
   9.531 +		if (r < 0)
   9.532 +			abort(); /* XXX need to handle this */
   9.533 +
   9.534 +		send_trivial_control_reply(msg, d);
   9.535 +
   9.536 +		PRINTF(4, "informing front end of event channel\n");
   9.537 +		conn.assist_port = assist_channel[1];
   9.538 +		conn.event_port = event_channel[1];
   9.539 +		send_control_message(CMSG_PDB_BE,
   9.540 +				     CMSG_PDB_BE_INTERFACE_CONNECTED,
   9.541 +				     0,
   9.542 +				     sizeof(conn),
   9.543 +				     &conn,
   9.544 +				     d);
   9.545 +
   9.546 +		PRINTF(4, "informing back end of front end\n");
   9.547 +		new_be.domain = d->domid;
   9.548 +		new_be.assist_evtchn = assist_channel[0];
   9.549 +		new_be.event_evtchn = event_channel[0];
   9.550 +		new_be.assist_frame = pe->assist_page;
   9.551 +		new_be.event_frame = pe->event_page;
   9.552 +		send_control_message(CMSG_PDB_FE,
   9.553 +				     CMSG_PDB_FE_NEW_BE,
   9.554 +				     0,
   9.555 +				     sizeof(new_be),
   9.556 +				     &new_be,
   9.557 +				     dom0);
   9.558 +		break;
   9.559 +	default:
   9.560 +		warnx("unknown pdb status %d", pe->status);
   9.561 +	}
   9.562 +}
   9.563 +
   9.564 +static void
   9.565 +process_pdb_be_message(control_msg_t *msg, struct domain *d)
   9.566 +{
   9.567 +	switch (msg->subtype) {
   9.568 +	case CMSG_PDB_BE_DRIVER_STATUS_CHANGED:
   9.569 +	{
   9.570 +		pdb_be_driver_status_changed_t *pe =
   9.571 +			(pdb_be_driver_status_changed_t *)msg->msg;
   9.572 +		process_pdb_be_driver_status_changed_message(msg, pe, d);
   9.573 +		break;
   9.574 +	}
   9.575 +	default:
   9.576 +		warnx("unknown pdb back end message subtype %d",
   9.577 +		      msg->subtype);
   9.578 +	}
   9.579 +}
   9.580 +
   9.581 +static void
   9.582 +process_control_message(control_msg_t *msg, struct domain *d)
   9.583 +{
   9.584 +	control_msg_t m;
   9.585 +
   9.586 +	/* Don't want a malicous domain messing us about, so copy the
   9.587 +	   control mesasge into a local buffer. */
   9.588 +	memcpy(&m, msg, sizeof(m));
   9.589 +	switch (m.type) {
   9.590 +	case CMSG_CONSOLE:
   9.591 +		process_console_control_message(&m, d);
   9.592 +		break;
   9.593 +	case CMSG_BLKIF_FE:
   9.594 +		process_blkif_fe_message(&m, d);
   9.595 +		break;
   9.596 +	case CMSG_NETIF_FE:
   9.597 +		process_netif_fe_message(&m, d);
   9.598 +		break;
   9.599 +	case CMSG_PDB_BE:
   9.600 +		process_pdb_be_message(&m, d);
   9.601 +		break;
   9.602 +	default:
   9.603 +		warnx("unknown control message type %d", m.type);
   9.604 +	}
   9.605 +}
   9.606 +
   9.607 +static void
   9.608 +domain_did_control_event(struct domain *d)
   9.609 +{
   9.610 +	CONTROL_RING_IDX c;
   9.611 +
   9.612 +	/* Pick up and process control ring messages. */
   9.613 +	while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
   9.614 +		c = d->tx_req_cons % CONTROL_RING_SIZE;
   9.615 +		process_control_message(&d->ctrl_if->tx_ring[c], d);
   9.616 +		d->tx_req_cons++;
   9.617 +		assert(d->tx_req_cons <= d->ctrl_if->tx_req_prod);
   9.618 +		PRINTF(5, "req_cons %ld, req_prod %ld.\n",
   9.619 +		       d->tx_req_cons, d->ctrl_if->tx_req_prod);
   9.620 +	}
   9.621 +
   9.622 +	/* Take any replies off, and discard them. */
   9.623 +	if (d->rx_resp_cons != d->ctrl_if->rx_resp_prod)
   9.624 +		PRINTF(1, "discard %ld events\n",
   9.625 +		       d->ctrl_if->rx_resp_prod -
   9.626 +		       d->rx_resp_cons);
   9.627 +	d->rx_resp_cons = d->ctrl_if->rx_resp_prod;
   9.628 +}
   9.629 +
   9.630 +/* This is the main function for domain control threads */
   9.631 +void *
   9.632 +domain_thread_func(void *D)
   9.633 +{
   9.634 +	struct domain *d = D;
   9.635 +	int r;
   9.636 +	CONTROL_RING_IDX old_resp_prod, old_req_prod;
   9.637 +
   9.638 +	pthread_mutex_lock(&d->mux);
   9.639 +	for (;;) {
   9.640 +		pthread_cond_wait(&d->cond, &d->mux);
   9.641 +
   9.642 +		old_resp_prod = d->ctrl_if->tx_resp_prod;
   9.643 +		old_req_prod = d->ctrl_if->rx_req_prod;
   9.644 +
   9.645 +		domain_did_control_event(d);
   9.646 +		if (d->cc && d->cc->in_buf_used != 0 && d->plugged == 0) {
   9.647 +			r = d->cc->in_buf_used;
   9.648 +			if (r > 60)
   9.649 +				r = 60;
   9.650 +			PRINTF(1, "Sending to domain: %.*s\n",
   9.651 +			       r, d->cc->in_buf);
   9.652 +			send_control_message(CMSG_CONSOLE,
   9.653 +					     CMSG_CONSOLE_DATA,
   9.654 +					     0,
   9.655 +					     r,
   9.656 +					     d->cc->in_buf,
   9.657 +					     d);
   9.658 +			memmove(d->cc->in_buf, d->cc->in_buf + r,
   9.659 +				d->cc->in_buf_used - r);
   9.660 +			d->cc->in_buf_used -= r;
   9.661 +		}
   9.662 +
   9.663 +		if (d->ctrl_if->tx_resp_prod != old_resp_prod ||
   9.664 +		    d->ctrl_if->rx_req_prod != old_req_prod)
   9.665 +			xc_evtchn_send(xc_handle, d->control_evtchn);
   9.666 +	}
   9.667 +}
   9.668 +
   9.669 +/* This is the only thing you can do with a domain structure if you're
   9.670 +   not in the thread which controls that domain.  Domain 0 is
   9.671 +   special. */
   9.672 +void
   9.673 +signal_domain(struct domain *d)
   9.674 +{
   9.675 +	CONTROL_RING_IDX c;
   9.676 +	int id;
   9.677 +	struct event_receiver *evt;
   9.678 +
   9.679 +	pthread_mutex_lock(&d->mux);
   9.680 +	if (d == dom0) {
   9.681 +		/* Take events off of dom0's control ring, and send
   9.682 +		   them to the event receivers. */
   9.683 +		while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
   9.684 +			c = d->tx_req_cons % CONTROL_RING_SIZE;
   9.685 +			id = d->ctrl_if->tx_ring[c].id;
   9.686 +			evt = find_event_receiver(id);
   9.687 +			if (evt != NULL) {
   9.688 +				PRINTF(1, "delivering event id %d\n", evt->id);
   9.689 +				pthread_cond_broadcast(&evt->cond);
   9.690 +				pthread_mutex_unlock(&d->mux);
   9.691 +				pthread_yield();
   9.692 +				pthread_mutex_lock(&d->mux);
   9.693 +			} else {
   9.694 +				warnx("unexpected message id %d discarded",
   9.695 +				      id);
   9.696 +				d->tx_req_cons++;
   9.697 +			}
   9.698 +		}
   9.699 +		while (d->rx_resp_cons != d->ctrl_if->rx_resp_prod) {
   9.700 +			c = d->rx_resp_cons % CONTROL_RING_SIZE;
   9.701 +			id = d->ctrl_if->rx_ring[c].id;
   9.702 +			evt = find_event_receiver(id);
   9.703 +			if (evt != NULL) {
   9.704 +				PRINTF(1, "delivering event rep id %d\n", evt->id);
   9.705 +				pthread_cond_broadcast(&evt->cond);
   9.706 +				pthread_mutex_unlock(&d->mux);
   9.707 +				pthread_yield();
   9.708 +				pthread_mutex_lock(&d->mux);
   9.709 +			} else {
   9.710 +				warnx("unexpected message reply id %d discarded",
   9.711 +				      id);
   9.712 +				d->rx_resp_cons++;
   9.713 +			}
   9.714 +		}
   9.715 +	} else {
   9.716 +		if (d->plugged) {
   9.717 +			d->event_pending = 1;
   9.718 +		} else {
   9.719 +			pthread_cond_broadcast(&d->cond);
   9.720 +		}
   9.721 +	}
   9.722 +	pthread_mutex_unlock(&d->mux);
   9.723 +}
   9.724 +
   9.725 +static void
   9.726 +handle_evtchn_event(void)
   9.727 +{
   9.728 +	short port;
   9.729 +	struct domain *d;
   9.730 +
   9.731 +	read(evtchn_fd, &port, sizeof(short));
   9.732 +	write(evtchn_fd, &port, sizeof(short));
   9.733 +	foreach_domain (d) {
   9.734 +		if (d->control_evtchn == port) {
   9.735 +			signal_domain(d);
   9.736 +			return;
   9.737 +		}
   9.738 +	}
   9.739 +	warnx("got an event on an unknown port %d", port);
   9.740 +}
   9.741 +
   9.742 +void *
   9.743 +map_domain_mem(struct domain *d, unsigned long mfn)
   9.744 +{
   9.745 +	return xc_map_foreign_range(xc_handle, d->domid,
   9.746 +				    PAGE_SIZE, PROT_READ | PROT_WRITE,
   9.747 +				    mfn);
   9.748 +}
   9.749 +
   9.750 +static void
   9.751 +handle_console_event(struct console_connection *cc)
   9.752 +{
   9.753 +	int r;
   9.754 +	int fd;
   9.755 +
   9.756 +	switch (cc->state) {
   9.757 +	case CC_STATE_ERROR:
   9.758 +		/* Errors shouldn't get here. */
   9.759 +		abort();
   9.760 +	case CC_STATE_PENDING:
   9.761 +		fd = accept(cc->fd, NULL, NULL);
   9.762 +		if (fd >= 0) {
   9.763 +			PRINTF(3, "Accepted console connection for domain %d",
   9.764 +			       cc->dom->domid);
   9.765 +			close(cc->fd);
   9.766 +			cc->fd = fd;
   9.767 +			cc->state = CC_STATE_CONNECTED;
   9.768 +			while (cc->buf_used != 0) {
   9.769 +				r = write(cc->fd,
   9.770 +					  cc->buf,
   9.771 +					  cc->buf_used);
   9.772 +				if (r <= 0) {
   9.773 +					cc->state = CC_STATE_ERROR;
   9.774 +					break;
   9.775 +				}
   9.776 +				memmove(cc->buf,
   9.777 +					cc->buf + r,
   9.778 +					cc->buf_used - r);
   9.779 +				cc->buf_used -= r;
   9.780 +			}
   9.781 +			free(cc->buf);
   9.782 +			cc->buf = NULL;
   9.783 +			cc->buf_allocated = 0;
   9.784 +		} else {
   9.785 +			PRINTF(1, "error %s accepting console", strerror(errno));
   9.786 +		}
   9.787 +		pthread_mutex_unlock(&cc->dom->mux);
   9.788 +		break;
   9.789 +	case CC_STATE_CONNECTED:
   9.790 +		if (cc->in_buf_allocated == 0) {
   9.791 +			assert(cc->in_buf_used == 0);
   9.792 +			cc->in_buf_allocated = 128;
   9.793 +			cc->in_buf = xmalloc(cc->in_buf_allocated);
   9.794 +		}
   9.795 +		if (cc->in_buf_used == cc->in_buf_allocated) {
   9.796 +			cc->in_buf_allocated *= 2;
   9.797 +			cc->in_buf = xrealloc(cc->in_buf, cc->in_buf_allocated);
   9.798 +		}
   9.799 +		r = read(cc->fd, cc->in_buf + cc->in_buf_used,
   9.800 +			 cc->in_buf_allocated - cc->in_buf_used);
   9.801 +		if (r <= 0) {
   9.802 +			cc->state = CC_STATE_ERROR;
   9.803 +		} else {
   9.804 +			cc->in_buf_used += r;
   9.805 +		}
   9.806 +		pthread_mutex_unlock(&cc->dom->mux);
   9.807 +		signal_domain(cc->dom);
   9.808 +		break;
   9.809 +	}
   9.810 +}
   9.811 +
   9.812 +static void
   9.813 +handle_connection_event(struct open_connection *oc)
   9.814 +{
   9.815 +	int r;
   9.816 +
   9.817 +	/* We know that some amount of data is ready and waiting for
   9.818 +	   us.  Slurp it in. */
   9.819 +	if (oc->buf_used == oc->buf_allocated) {
   9.820 +		oc->buf_allocated *= 2;
   9.821 +		oc->buf = xrealloc(oc->buf, oc->buf_allocated);
   9.822 +	}
   9.823 +	r = read(oc->fd, oc->buf + oc->buf_used,
   9.824 +		 oc->buf_allocated - oc->buf_used);
   9.825 +	if (r < 0) {
   9.826 +		warn("reading command from remote");
   9.827 +		oc->state = OC_STATE_ERROR;
   9.828 +	} else if (r == 0) {
   9.829 +		warnx("reading command from remote");
   9.830 +		oc->state = OC_STATE_ERROR;
   9.831 +	} else {
   9.832 +		oc->buf_used += r;
   9.833 +		if (strchr(oc->buf, '\n'))
   9.834 +			oc->state = OC_STATE_COMMAND_PENDING;
   9.835 +	}
   9.836 +}
   9.837 +
   9.838 +static void
   9.839 +get_and_process_event(void)
   9.840 +{
   9.841 +	fd_set read_fds, except_fds;
   9.842 +	struct open_connection *oc;
   9.843 +	struct console_connection *cc;
   9.844 +	int max_fd = listen_fd;
   9.845 +	int r;
   9.846 +	struct list_head *li, *temp_li;
   9.847 +
   9.848 +	FD_ZERO(&read_fds);
   9.849 +	FD_ZERO(&except_fds);
   9.850 +	FD_SET(listen_fd, &read_fds);
   9.851 +	FD_SET(evtchn_fd, &read_fds);
   9.852 +	if (evtchn_fd > max_fd)
   9.853 +		max_fd = evtchn_fd;
   9.854 +	foreach_open_connection(oc) {
   9.855 +		FD_SET(oc->fd, &read_fds);
   9.856 +		FD_SET(oc->fd, &except_fds);
   9.857 +		if (oc->fd > max_fd)
   9.858 +			max_fd = oc->fd;
   9.859 +	}
   9.860 +	foreach_console_connection(cc) {
   9.861 +		FD_SET(cc->fd, &read_fds);
   9.862 +		FD_SET(cc->fd, &except_fds);
   9.863 +		if (cc->fd > max_fd)
   9.864 +			max_fd = cc->fd;
   9.865 +	}
   9.866 +
   9.867 +	r = select(max_fd + 1, &read_fds, NULL, &except_fds, NULL);
   9.868 +	if (r < 0)
   9.869 +		err(1, "select");
   9.870 +	if (FD_ISSET(listen_fd, &read_fds)) {
   9.871 +		accept_new_connection();
   9.872 +	} else if (FD_ISSET(evtchn_fd, &read_fds))
   9.873 +		handle_evtchn_event();
   9.874 +
   9.875 +
   9.876 +	foreach_open_connection(oc) {
   9.877 +		if (FD_ISSET(oc->fd, &read_fds))
   9.878 +			handle_connection_event(oc);
   9.879 +		if (FD_ISSET(oc->fd, &except_fds))
   9.880 +			oc->state = OC_STATE_ERROR;
   9.881 +	}
   9.882 +	list_foreach_safe(&head_console, li, temp_li) {
   9.883 +		cc = list_item(li, struct console_connection, list);
   9.884 +		if (FD_ISSET(cc->fd, &read_fds))
   9.885 +			handle_console_event(cc);
   9.886 +		if (FD_ISSET(cc->fd, &except_fds) ||
   9.887 +		    cc->state == CC_STATE_ERROR) {
   9.888 +			PRINTF(1, "Cleaning up console connection");
   9.889 +			cc->dom->cc = NULL;
   9.890 +			list_remove(&cc->list);
   9.891 +			close(cc->fd);
   9.892 +			if (cc->buf_allocated != 0)
   9.893 +				free(cc->buf);
   9.894 +			if (cc->in_buf_allocated != 0)
   9.895 +				free(cc->in_buf);
   9.896 +			free(cc);
   9.897 +		}
   9.898 +	}
   9.899 +
   9.900 +	/* Run pending stuff on the open connections. */
   9.901 +	list_foreach_safe(&head_connection, li, temp_li) {
   9.902 +		oc = list_item(li, struct open_connection, connection_list);
   9.903 +		switch (oc->state) {
   9.904 +		case OC_STATE_ERROR:
   9.905 +			list_remove(&oc->connection_list);
   9.906 +			closedown_connection(oc);
   9.907 +			break;
   9.908 +		case OC_STATE_COMMAND_PENDING:
   9.909 +			process_command(oc);
   9.910 +			break;
   9.911 +		case OC_STATE_CONNECTED:
   9.912 +			/* Don't need to do anything */
   9.913 +			break;
   9.914 +		}
   9.915 +	}
   9.916 +}
   9.917 +
   9.918 +static int
   9.919 +start_listening(void)
   9.920 +{
   9.921 +	int sock;
   9.922 +	struct sockaddr_in inaddr;
   9.923 +
   9.924 +	sock = socket(PF_INET, SOCK_STREAM, 0);
   9.925 +	if (sock < 0)
   9.926 +		err(1, "creating socket");
   9.927 +	memset(&inaddr, 0, sizeof(inaddr));
   9.928 +	inaddr.sin_family = AF_INET;
   9.929 +	inaddr.sin_port = htons(MINIXEND_PORT);
   9.930 +
   9.931 +	if (bind(sock, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
   9.932 +		err(1, "binding to port %d", MINIXEND_PORT);
   9.933 +	if (listen(sock, 5) < 0)
   9.934 +		err(1, "listening for connections");
   9.935 +
   9.936 +	return sock;
   9.937 +}
   9.938 +
   9.939 +static struct domain *
   9.940 +find_dom0(void)
   9.941 +{
   9.942 +	int r;
   9.943 +	xc_dominfo_t info;
   9.944 +	struct domain *work;
   9.945 +
   9.946 +	r = xc_domain_getinfo(xc_handle, 0, 1, &info);
   9.947 +	if (r < 0)
   9.948 +		err(1, "getting domain 0 information");
   9.949 +	work = xmalloc(sizeof(*work));
   9.950 +	work->control_evtchn = 2;
   9.951 +	if (ioctl(evtchn_fd, EVTCHN_BIND, 2) < 0)
   9.952 +		err(1, "binding to domain 0 control event channel");
   9.953 +
   9.954 +	work->domid = 0;
   9.955 +	work->name = xstrdup("dom0");
   9.956 +	work->mem_kb = info.max_memkb;
   9.957 +	work->state = DOM_STATE_RUNNING;
   9.958 +	work->shared_info_mfn = info.shared_info_frame;
   9.959 +
   9.960 +	work->shared_info = map_domain_mem(work, info.shared_info_frame);
   9.961 +	work->ctrl_if = (control_if_t *)((unsigned)work->shared_info + 2048);
   9.962 +	work->tx_req_cons = work->ctrl_if->tx_req_prod;
   9.963 +	work->rx_resp_cons = work->ctrl_if->rx_resp_prod;
   9.964 +
   9.965 +	pthread_mutex_init(&work->mux, NULL);
   9.966 +	pthread_cond_init(&work->cond, NULL);
   9.967 +
   9.968 +	list_insert_after(&work->domain_list, &head_domain);
   9.969 +
   9.970 +	return work;
   9.971 +}
   9.972 +
   9.973 +int
   9.974 +main(int argc, char *argv[])
   9.975 +{
   9.976 +	int r;
   9.977 +
   9.978 +	r = our_system(NETWORK_SCRIPT " start antispoof=no");
   9.979 +	if (r < 0)
   9.980 +		err(1, "running " NETWORK_SCRIPT);
   9.981 +	if (!WIFEXITED(r)) {
   9.982 +		if (WIFSIGNALED(r)) {
   9.983 +			errx(1, NETWORK_SCRIPT " killed by signal %d",
   9.984 +			     WTERMSIG(r));
   9.985 +		}
   9.986 +		errx(1, NETWORK_SCRIPT " terminated abnormally");
   9.987 +	}
   9.988 +	if (WEXITSTATUS(r) != 0)
   9.989 +		errx(1, NETWORK_SCRIPT " returned error status %d",
   9.990 +		     WEXITSTATUS(r));
   9.991 +
   9.992 +	xc_handle = xc_interface_open();
   9.993 +
   9.994 +	listen_fd = start_listening();
   9.995 +
   9.996 +	evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
   9.997 +	if (evtchn_fd < 0)
   9.998 +		err(1, "openning /dev/xen/evtchn");
   9.999 +
  9.1000 +	dom0 = find_dom0();
  9.1001 +
  9.1002 +	while (1) {
  9.1003 +		get_and_process_event();
  9.1004 +
  9.1005 +		PRINTF(5, "Dom0 ring state:\n");
  9.1006 +		PRINTF(5, "RX: req_prod %ld, resp_prod %ld, resp_cons %ld\n",
  9.1007 +		       dom0->ctrl_if->rx_req_prod,
  9.1008 +		       dom0->ctrl_if->rx_resp_prod,
  9.1009 +		       dom0->rx_resp_cons);
  9.1010 +		PRINTF(5, "TX: req_prod %ld, resp_prod %ld, req_cons %ld\n",
  9.1011 +		       dom0->ctrl_if->tx_req_prod,
  9.1012 +		       dom0->ctrl_if->tx_resp_prod,
  9.1013 +		       dom0->tx_req_cons);
  9.1014 +	}
  9.1015 +
  9.1016 +	return 0;
  9.1017 +}
  9.1018 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/x2d2/minixend.h	Sat Nov 13 10:05:50 2004 +0000
    10.3 @@ -0,0 +1,218 @@
    10.4 +#ifndef MINIXEND_H__
    10.5 +#define MINIXEND_H__
    10.6 +
    10.7 +#include <sys/types.h>
    10.8 +#include <xc.h>
    10.9 +#include "domain_controller.h"
   10.10 +
   10.11 +/* Yet again, persuading Xen headers to include successfully in a
   10.12 +   userspace process proves to be beyond me.  Sigh. */
   10.13 +#define MAX_VIRT_CPUS 1
   10.14 +
   10.15 +typedef struct {
   10.16 +    u32  tsc_bits;      /* 0: 32 bits read from the CPU's TSC. */
   10.17 +    u32  tsc_bitshift;  /* 4: 'tsc_bits' uses N:N+31 of TSC.   */
   10.18 +} PACKED tsc_timestamp_t; /* 8 bytes */
   10.19 +
   10.20 +typedef struct {
   10.21 +    u64 mfn_to_pfn_start;      /* MFN of start of m2p table */
   10.22 +    u64 pfn_to_mfn_frame_list; /* MFN of a table of MFNs that 
   10.23 +				  make up p2m table */
   10.24 +} PACKED arch_shared_info_t;
   10.25 +
   10.26 +typedef struct
   10.27 +{
   10.28 +    unsigned long ebx;
   10.29 +    unsigned long ecx;
   10.30 +    unsigned long edx;
   10.31 +    unsigned long esi;
   10.32 +    unsigned long edi;
   10.33 +    unsigned long ebp;
   10.34 +    unsigned long eax;
   10.35 +    unsigned long ds;
   10.36 +    unsigned long es;
   10.37 +    unsigned long fs;
   10.38 +    unsigned long gs;
   10.39 +    unsigned long _unused;
   10.40 +    unsigned long eip;
   10.41 +    unsigned long cs;
   10.42 +    unsigned long eflags;
   10.43 +    unsigned long esp;
   10.44 +    unsigned long ss;
   10.45 +} PACKED execution_context_t;
   10.46 +
   10.47 +typedef struct shared_info_st
   10.48 +{
   10.49 +    struct {
   10.50 +        u8 evtchn_upcall_pending;
   10.51 +        u8 evtchn_upcall_mask;
   10.52 +        u8 pad0, pad1;
   10.53 +    } PACKED vcpu_data[MAX_VIRT_CPUS];  /*   0 */
   10.54 +    u32 evtchn_pending[32];             /*   4 */
   10.55 +    u32 evtchn_pending_sel;             /* 132 */
   10.56 +    u32 evtchn_mask[32];                /* 136 */
   10.57 +    u64                cpu_freq;        /* 264: CPU frequency (Hz).          */
   10.58 +    u32                time_version1;   /* 272 */
   10.59 +    u32                time_version2;   /* 276 */
   10.60 +    tsc_timestamp_t    tsc_timestamp;   /* TSC at last update of time vals.  */
   10.61 +    u64                system_time;     /* Time, in nanosecs, since boot.    */
   10.62 +    u32                wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
   10.63 +    u32                wc_usec;         /* Usecs 00:00:00 UTC, Jan 1, 1970.  */
   10.64 +    u64                domain_time;     /* Domain virtual time, in nanosecs. */
   10.65 +    u64                wall_timeout;    /* 312 */
   10.66 +    u64                domain_timeout;  /* 320 */
   10.67 +    execution_context_t execution_context; /* 328 */
   10.68 +    arch_shared_info_t arch;
   10.69 +} PACKED shared_info_t;
   10.70 +
   10.71 +/* End of stuff which belongs in a Xen header */
   10.72 +
   10.73 +
   10.74 +struct list_head {
   10.75 +	struct list_head *next, **pprev;
   10.76 +};
   10.77 +
   10.78 +struct open_connection {
   10.79 +	struct list_head connection_list;
   10.80 +	int fd;
   10.81 +	enum {
   10.82 +		OC_STATE_CONNECTED,
   10.83 +		OC_STATE_ERROR,
   10.84 +		OC_STATE_COMMAND_PENDING
   10.85 +	} state;
   10.86 +
   10.87 +	/* Buffer of stuff coming from the remote until we get a whole
   10.88 +	   command */
   10.89 +	int buf_used;
   10.90 +	int buf_allocated;
   10.91 +	char *buf;
   10.92 +};
   10.93 +
   10.94 +struct console_connection;
   10.95 +
   10.96 +/* Only ever accessed from the domain's controlling thread, unless
   10.97 +   it's dom0, in which case we perform a moderately complex dance to
   10.98 +   avoid needing any sort of locking at all. */
   10.99 +struct domain {
  10.100 +	struct list_head domain_list;
  10.101 +	int control_evtchn; /* the local port for the doain control
  10.102 +			       interface event channel. */
  10.103 +	int domid;
  10.104 +	char *name;
  10.105 +	int mem_kb;
  10.106 +	enum {
  10.107 +		DOM_STATE_CREATED, /* created but not built */
  10.108 +		DOM_STATE_PAUSED,  /* built but not started or paused */
  10.109 +		DOM_STATE_RUNNING, /* running normally */
  10.110 +		DOM_STATE_DEAD     /* dead; either destroyed, crashed,
  10.111 +				      or exitted. */
  10.112 +	} state;
  10.113 +
  10.114 +	unsigned long shared_info_mfn;
  10.115 +	shared_info_t *shared_info;
  10.116 +	control_if_t *ctrl_if;
  10.117 +	CONTROL_RING_IDX tx_req_cons;
  10.118 +	CONTROL_RING_IDX rx_resp_cons;
  10.119 +
  10.120 +	unsigned created_netif_backend:1;
  10.121 +	unsigned plugged:1;
  10.122 +	unsigned event_pending:1; /* True if an event arrived while
  10.123 +				     the domain was plugged. */
  10.124 +
  10.125 +	struct console_connection *cc;
  10.126 +
  10.127 +	char netif_mac[6];
  10.128 +
  10.129 +	/* Used for two purposes: waking up domain threads when
  10.130 +	   necessary, and synchronising access to dom0, which doesn't
  10.131 +	   have a domain thread. */
  10.132 +	pthread_mutex_t mux;
  10.133 +	pthread_cond_t cond;
  10.134 +
  10.135 +	pthread_t thread;
  10.136 +};
  10.137 +
  10.138 +struct console_connection {
  10.139 +	struct list_head list;
  10.140 +	int fd;
  10.141 +	struct domain *dom;
  10.142 +
  10.143 +	enum {
  10.144 +		CC_STATE_PENDING,
  10.145 +		CC_STATE_CONNECTED,
  10.146 +		CC_STATE_ERROR
  10.147 +	} state;
  10.148 +
  10.149 +	unsigned buf_allocated;
  10.150 +	unsigned buf_used;
  10.151 +	char *buf;
  10.152 +
  10.153 +	unsigned in_buf_allocated;
  10.154 +	unsigned in_buf_used;
  10.155 +	char *in_buf;
  10.156 +};
  10.157 +
  10.158 +
  10.159 +void *domain_thread_func(void *d);
  10.160 +void process_command(struct open_connection *oc);
  10.161 +
  10.162 +void *xmalloc(size_t s);
  10.163 +void *xrealloc(void *x, size_t s);
  10.164 +char *xstrdup(const char *s);
  10.165 +
  10.166 +int allocate_event_channel(struct domain *d, int event_ports[2]);
  10.167 +void *map_domain_mem(struct domain *d, unsigned long mfn);
  10.168 +void signal_domain(struct domain *d);
  10.169 +int our_system(const char *fmt, ...);
  10.170 +
  10.171 +extern unsigned xc_handle;
  10.172 +#define EVTCHN_BIND _IO('E', 2)
  10.173 +extern int evtchn_fd;
  10.174 +
  10.175 +#define list_item(head, type, field)                                        \
  10.176 +((type *)((unsigned)(head) - offsetof(type, field)))
  10.177 +
  10.178 +#define foreach_item(iter, head, type, field)                               \
  10.179 +for ((iter) = list_item((head)->next, type, field);                         \
  10.180 +     (iter) != list_item((head), type, field);                              \
  10.181 +     (iter) = list_item((iter)->field.next, type, field))
  10.182 +
  10.183 +#define list_insert_after(what, head)                                       \
  10.184 +do {                                                                        \
  10.185 +	(what)->next = (head)->next;                                        \
  10.186 +	(what)->pprev = &(head)->next;                                      \
  10.187 +	(head)->next->pprev = &(what)->next;                                \
  10.188 +	(head)->next = what;                                                \
  10.189 +} while (0)
  10.190 +
  10.191 +#define list_remove(head)                                                   \
  10.192 +(head)->next->pprev = (head)->pprev;                                        \
  10.193 +*(head)->pprev = (head)->next;
  10.194 +
  10.195 +#define list_foreach_safe(head, li, temp)                                   \
  10.196 +for ((li) = (head)->next, (temp) = (li)->next;                              \
  10.197 +     (li) != (head);                                                        \
  10.198 +     (li) = (temp), (temp) = (li)->next)
  10.199 +
  10.200 +#define LIST_HEAD(x) { (x), &(x)->next }
  10.201 +
  10.202 +
  10.203 +extern struct list_head head_domain;
  10.204 +extern struct list_head head_console;
  10.205 +
  10.206 +#define foreach_domain(d)                                                   \
  10.207 +foreach_item(d, &head_domain, struct domain, domain_list)
  10.208 +#define foreach_console_connection(cc)                                      \
  10.209 +foreach_item(cc, &head_console, struct console_connection, list)
  10.210 +
  10.211 +
  10.212 +#define CURRENT_LOG_LEVEL 0
  10.213 +
  10.214 +#define PRINTF(level, ...)                                         \
  10.215 +do {                                                               \
  10.216 +	if ((level) >= CURRENT_LOG_LEVEL)                          \
  10.217 +		printf(__VA_ARGS__);                               \
  10.218 +} while (0)
  10.219 +
  10.220 +
  10.221 +#endif /* MINIXEND_H__ */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/x2d2/util.c	Sat Nov 13 10:05:50 2004 +0000
    11.3 @@ -0,0 +1,132 @@
    11.4 +#define _GNU_SOURCE
    11.5 +
    11.6 +#include <sys/types.h>
    11.7 +#include <sys/wait.h>
    11.8 +#include <assert.h>
    11.9 +#include <err.h>
   11.10 +#include <errno.h>
   11.11 +#include <fcntl.h>
   11.12 +#include <stdarg.h>
   11.13 +#include <stdlib.h>
   11.14 +#include <stdio.h>
   11.15 +#include <string.h>
   11.16 +#include <unistd.h>
   11.17 +
   11.18 +void *
   11.19 +xmalloc(size_t s)
   11.20 +{
   11.21 +	void *x;
   11.22 +
   11.23 +	x = malloc(s);
   11.24 +	if (x == NULL)
   11.25 +		err(1, "allocating memory");
   11.26 +	memset(x, 0, s);
   11.27 +	return x;
   11.28 +}
   11.29 +
   11.30 +void *
   11.31 +xrealloc(void *x, size_t s)
   11.32 +{
   11.33 +	void *y;
   11.34 +	y = realloc(x, s);
   11.35 +	if (y == NULL)
   11.36 +		err(1, "allocating more memory");
   11.37 +	return y;
   11.38 +}
   11.39 +
   11.40 +char *
   11.41 +xstrdup(const char *s)
   11.42 +{
   11.43 +	char *x = strdup(s);
   11.44 +	if (x == NULL)
   11.45 +		err(1, "duplicating %s", s);
   11.46 +	return x;
   11.47 +}
   11.48 +
   11.49 +/* Slightly less stupid implementation of system().  We return
   11.50 +   negative iff there is an error executing the shell; otherwise, we
   11.51 +   return the wait status as reported by waitpid(). Also, we support
   11.52 +   printf-style escapes.  We don't handle setting the SIGCHLD handler
   11.53 +   to SIGIGN, though: in that case, we have a race. */
   11.54 +int
   11.55 +our_system(const char *fmt, ...)
   11.56 +{
   11.57 +	char *cmd = NULL;
   11.58 +	int r;
   11.59 +	va_list ap;
   11.60 +	pid_t child = -1;
   11.61 +	int pip[2] = {-1, -1};
   11.62 +	int e;
   11.63 +	fd_set fds;
   11.64 +	struct timeval to;
   11.65 +	int res;
   11.66 +	pid_t c;
   11.67 +	unsigned status;
   11.68 +
   11.69 +	va_start(ap, fmt);
   11.70 +	r = vasprintf(&cmd, fmt, ap);
   11.71 +	va_end(ap);
   11.72 +	if (r < 0)
   11.73 +		return r;
   11.74 +	r = pipe(pip);
   11.75 +	if (r < 0) {
   11.76 +		res = r;
   11.77 +		goto out;
   11.78 +	}
   11.79 +	child = fork();
   11.80 +	if (child < 0) {
   11.81 +		res = child;
   11.82 +		goto out;
   11.83 +	}
   11.84 +	if (child == 0) {
   11.85 +		close(pip[0]);
   11.86 +		fcntl(pip[1], F_SETFD, 1);
   11.87 +		r = execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
   11.88 +		/* Uh oh, exec failed */
   11.89 +		write(pip[1], &r, sizeof(r));
   11.90 +		_exit(1);
   11.91 +	}
   11.92 +
   11.93 +	close(pip[1]);
   11.94 +	pip[1] = -1;
   11.95 +
   11.96 +	c = waitpid(child, &status, 0);
   11.97 +	if (c < 0) {
   11.98 +		res = c;
   11.99 +		goto out;
  11.100 +	}
  11.101 +	assert(c == child);
  11.102 +	child = -1;
  11.103 +
  11.104 +	/* Check execl result */
  11.105 +	FD_ZERO(&fds);
  11.106 +	FD_SET(pip[0], &fds);
  11.107 +	memset(&to, 0, sizeof(to));
  11.108 +	r = select(pip[0]+1, &fds, NULL, NULL, &to);
  11.109 +	if (r == 0) {
  11.110 +		res = status;
  11.111 +	} else {
  11.112 +		assert(FD_ISSET(pip[0], &fds));
  11.113 +		r = read(pip[0], &res, sizeof(res));
  11.114 +		if (r != sizeof(res))
  11.115 +			res = status;
  11.116 +	}
  11.117 +	close(pip[0]);
  11.118 +	pip[0] = -1;
  11.119 +
  11.120 + out:
  11.121 +	e = errno;
  11.122 +	if (child >= 0) {
  11.123 +		/* Not obvious what the correct thing to do here is. */
  11.124 +		/* Don't want to kill the child; that will create a
  11.125 +		   zombie. */
  11.126 +//		kill(child, 9);
  11.127 +	}
  11.128 +	if (pip[0] >= 0)
  11.129 +		close(pip[0]);
  11.130 +	if (pip[1] >= 0)
  11.131 +		close(pip[1]);
  11.132 +	free(cmd);
  11.133 +	errno = e;
  11.134 +	return res;
  11.135 +}
    12.1 --- a/xen/arch/x86/traps.c	Fri Nov 12 12:43:41 2004 +0000
    12.2 +++ b/xen/arch/x86/traps.c	Sat Nov 13 10:05:50 2004 +0000
    12.3 @@ -51,6 +51,7 @@
    12.4  #include <asm/uaccess.h>
    12.5  #include <asm/i387.h>
    12.6  #include <asm/pdb.h>
    12.7 +#include <xen/debugger_hooks.h>
    12.8  
    12.9  extern char opt_nmi[];
   12.10  
   12.11 @@ -243,6 +244,9 @@ static inline void do_trap(int trapnr, c
   12.12          return;
   12.13      }
   12.14  
   12.15 +    if (debugger_trap(trapnr, regs))
   12.16 +	return;
   12.17 +
   12.18      show_registers(regs);
   12.19      panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
   12.20            "[error_code=%08x]\n",
   12.21 @@ -280,10 +284,8 @@ asmlinkage void do_int3(struct xen_regs 
   12.22      struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
   12.23      trap_info_t *ti;
   12.24  
   12.25 -#ifdef XEN_DEBUGGER
   12.26 -    if ( pdb_initialized && pdb_handle_exception(3, regs) == 0 )
   12.27 +    if (debugger_trap(3, regs))
   12.28          return;
   12.29 -#endif
   12.30  
   12.31      if ( (regs->cs & 3) != 3 )
   12.32      {
   12.33 @@ -329,6 +331,8 @@ asmlinkage void do_double_fault(void)
   12.34      printk("System needs manual reset.\n");
   12.35      printk("************************************\n");
   12.36  
   12.37 +    debugger_trap(8, NULL);
   12.38 +
   12.39      /* Lock up the console to prevent spurious output from other CPUs. */
   12.40      console_force_lock();
   12.41  
   12.42 @@ -407,6 +411,9 @@ asmlinkage void do_page_fault(struct xen
   12.43          return;
   12.44      }
   12.45  
   12.46 +    if (debugger_trap(14, regs))
   12.47 +	return;
   12.48 +
   12.49      if ( addr >= PAGE_OFFSET )
   12.50      {
   12.51          unsigned long page;
   12.52 @@ -424,17 +431,6 @@ asmlinkage void do_page_fault(struct xen
   12.53  #endif
   12.54      }
   12.55  
   12.56 -#ifdef XEN_DEBUGGER
   12.57 -    if ( pdb_page_fault_possible )
   12.58 -    {
   12.59 -        pdb_page_fault = 1;
   12.60 -        /* make eax & edx valid to complete the instruction */
   12.61 -        regs->eax = (long)&pdb_page_fault_scratch;
   12.62 -        regs->edx = (long)&pdb_page_fault_scratch;
   12.63 -        return;
   12.64 -    }
   12.65 -#endif
   12.66 -
   12.67      show_registers(regs);
   12.68      panic("CPU%d FATAL PAGE FAULT\n"
   12.69            "[error_code=%08x]\n"
   12.70 @@ -522,6 +518,9 @@ asmlinkage void do_general_protection(st
   12.71          return;
   12.72      }
   12.73  
   12.74 +    if (debugger_trap(13, regs))
   12.75 +	return;
   12.76 +
   12.77      die("general protection fault", regs, error_code);
   12.78  }
   12.79  
   12.80 @@ -567,6 +566,9 @@ asmlinkage void io_check_error(struct xe
   12.81  
   12.82  static void unknown_nmi_error(unsigned char reason, struct xen_regs * regs)
   12.83  {
   12.84 +    if (debugger_trap(2, regs))
   12.85 +	return;
   12.86 +
   12.87      printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
   12.88      printk("Dazed and confused, but trying to continue\n");
   12.89      printk("Do you have a strange power saving mode enabled?\n");
    13.1 --- a/xen/common/keyhandler.c	Fri Nov 12 12:43:41 2004 +0000
    13.2 +++ b/xen/common/keyhandler.c	Sat Nov 13 10:05:50 2004 +0000
    13.3 @@ -11,10 +11,13 @@
    13.4  #define STR_MAX  64
    13.5  
    13.6  static struct { 
    13.7 -    key_handler *handler; 
    13.8 +    key_handler *handler;
    13.9 +    int          flags;
   13.10      char         desc[STR_MAX]; 
   13.11  } key_table[KEY_MAX]; 
   13.12  
   13.13 +#define KEYHANDLER_NO_DEFER 0x1
   13.14 +
   13.15  static unsigned char keypress_key;
   13.16  
   13.17  void keypress_softirq(void)
   13.18 @@ -25,19 +28,33 @@ void keypress_softirq(void)
   13.19          (*h)(key);
   13.20  }
   13.21  
   13.22 -void handle_keypress(unsigned char key)
   13.23 +void handle_keypress(unsigned char key, struct xen_regs *regs)
   13.24  {
   13.25 +    key_handler  *h;
   13.26 +
   13.27      keypress_key = key;
   13.28 -    raise_softirq(KEYPRESS_SOFTIRQ);
   13.29 +    if ( (key_table[key].flags & KEYHANDLER_NO_DEFER) &&
   13.30 +         ((h = key_table[key].handler) != NULL) )
   13.31 +        ((void (*)(unsigned char, struct xen_regs *))*h)(key, regs);
   13.32 +    else
   13.33 +        raise_softirq(KEYPRESS_SOFTIRQ);
   13.34  }
   13.35  
   13.36  void add_key_handler(unsigned char key, key_handler *handler, char *desc)
   13.37  {
   13.38 -    key_table[key].handler = handler; 
   13.39 +    key_table[key].handler = handler;
   13.40 +    key_table[key].flags = 0;
   13.41      strncpy(key_table[key].desc, desc, STR_MAX);
   13.42      key_table[key].desc[STR_MAX-1] = '\0'; 
   13.43  }
   13.44  
   13.45 +void add_key_handler_no_defer(unsigned char key, key_handler *handler,
   13.46 +                              char *desc)
   13.47 +{
   13.48 +    add_key_handler(key, handler, desc);
   13.49 +    key_table[key].flags |= KEYHANDLER_NO_DEFER;
   13.50 +}
   13.51 +
   13.52  static void show_handlers(unsigned char key)
   13.53  {
   13.54      int i; 
    14.1 --- a/xen/common/vsprintf.c	Fri Nov 12 12:43:41 2004 +0000
    14.2 +++ b/xen/common/vsprintf.c	Sat Nov 13 10:05:50 2004 +0000
    14.3 @@ -315,6 +315,10 @@ int vsnprintf(char *buf, size_t size, co
    14.4                  ++fmt;
    14.5              }
    14.6          }
    14.7 +        if (*fmt == 'q') {
    14.8 +            qualifier = 'L';
    14.9 +            ++fmt;
   14.10 +        }
   14.11  
   14.12          /* default base */
   14.13          base = 10;
    15.1 --- a/xen/drivers/char/console.c	Fri Nov 12 12:43:41 2004 +0000
    15.2 +++ b/xen/drivers/char/console.c	Sat Nov 13 10:05:50 2004 +0000
    15.3 @@ -247,7 +247,7 @@ static void __serial_rx(unsigned char c,
    15.4  {
    15.5      if ( xen_rx )
    15.6      {
    15.7 -        handle_keypress(c);
    15.8 +        handle_keypress(c, regs);
    15.9      }
   15.10      else if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
   15.11      {
   15.12 @@ -436,6 +436,21 @@ void console_force_lock(void)
   15.13      spin_lock(&console_lock);
   15.14  }
   15.15  
   15.16 +void console_putc(char c)
   15.17 +{
   15.18 +    serial_putc(sercon_handle, c);
   15.19 +}
   15.20 +
   15.21 +int console_getc(void)
   15.22 +{
   15.23 +    return serial_getc(sercon_handle);
   15.24 +}
   15.25 +
   15.26 +int irq_console_getc(void)
   15.27 +{
   15.28 +    return irq_serial_getc(sercon_handle);
   15.29 +}
   15.30 +
   15.31  
   15.32  /*
   15.33   * **************************************************************
    16.1 --- a/xen/drivers/char/serial.c	Fri Nov 12 12:43:41 2004 +0000
    16.2 +++ b/xen/drivers/char/serial.c	Sat Nov 13 10:05:50 2004 +0000
    16.3 @@ -416,6 +416,30 @@ static int byte_matches(int handle, unsi
    16.4      return 0;
    16.5  }
    16.6  
    16.7 +unsigned char irq_serial_getc(int handle)
    16.8 +{
    16.9 +    uart_t *uart = &com[handle & SERHND_IDX];
   16.10 +    unsigned char c;
   16.11 +
   16.12 +    while ( uart->rxbufp != uart->rxbufc )
   16.13 +    {
   16.14 +        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
   16.15 +        if ( byte_matches(handle, &c) )
   16.16 +            goto out;
   16.17 +    }
   16.18 +    
   16.19 +    /* We now wait for the UART to receive a suitable character. */
   16.20 +    do {
   16.21 +        while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
   16.22 +            barrier();
   16.23 +        c = inb(uart->io_base + RBR);
   16.24 +    }
   16.25 +    while ( !byte_matches(handle, &c) );
   16.26 +    
   16.27 + out:
   16.28 +    return c;
   16.29 +}
   16.30 +
   16.31  unsigned char serial_getc(int handle)
   16.32  {
   16.33      uart_t *uart = &com[handle & SERHND_IDX];
   16.34 @@ -432,24 +456,9 @@ unsigned char serial_getc(int handle)
   16.35      }
   16.36      
   16.37      disable_irq(uart->irq);
   16.38 +
   16.39 +    c = irq_serial_getc(handle);
   16.40      
   16.41 -    /* disable_irq() may have raced execution of uart_rx(). */
   16.42 -    while ( uart->rxbufp != uart->rxbufc )
   16.43 -    {
   16.44 -        c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
   16.45 -        if ( byte_matches(handle, &c) )
   16.46 -            goto enable_and_out;
   16.47 -    }
   16.48 -
   16.49 -    /* We now wait for the UART to receive a suitable character. */
   16.50 -    do {
   16.51 -        while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
   16.52 -            barrier();
   16.53 -        c = inb(uart->io_base + RBR);
   16.54 -    }
   16.55 -    while ( !byte_matches(handle, &c) );
   16.56 -    
   16.57 - enable_and_out:
   16.58      enable_irq(uart->irq);
   16.59   out:
   16.60      spin_unlock_irqrestore(&uart->lock, flags);
    17.1 --- a/xen/include/asm-x86/hardirq.h	Fri Nov 12 12:43:41 2004 +0000
    17.2 +++ b/xen/include/asm-x86/hardirq.h	Sat Nov 13 10:05:50 2004 +0000
    17.3 @@ -2,7 +2,7 @@
    17.4  #define __ASM_HARDIRQ_H
    17.5  
    17.6  #include <xen/config.h>
    17.7 -#include <xen/irq.h>
    17.8 +#include <xen/cache.h>
    17.9  
   17.10  /* assembly code in softirq.h is sensitive to the offsets of these fields */
   17.11  typedef struct {
    18.1 --- a/xen/include/xen/console.h	Fri Nov 12 12:43:41 2004 +0000
    18.2 +++ b/xen/include/xen/console.h	Sat Nov 13 10:05:50 2004 +0000
    18.3 @@ -22,4 +22,8 @@ void console_endboot(int disable_vga);
    18.4  void console_force_unlock(void);
    18.5  void console_force_lock(void);
    18.6  
    18.7 +void console_putc(char c);
    18.8 +int console_getc(void);
    18.9 +int irq_console_getc(void);
   18.10 +
   18.11  #endif
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/xen/include/xen/debugger_hooks.h	Sat Nov 13 10:05:50 2004 +0000
    19.3 @@ -0,0 +1,37 @@
    19.4 +
    19.5 +#ifndef __DEBUGGER_HOOKS_H__
    19.6 +#define __DEBUGGER_HOOKS_H__
    19.7 +
    19.8 +static inline int debugger_trap(int type, struct xen_regs *regs)
    19.9 +{
   19.10 +    int ret = 0;
   19.11 +
   19.12 +#ifdef XEN_DEBUGGER
   19.13 +    switch (type) {
   19.14 +    case 3:
   19.15 +        if ( pdb_initialized && pdb_handle_exception(type, regs) == 0 )
   19.16 +            return 1;
   19.17 +        break;
   19.18 +    case 14:
   19.19 +        if ( pdb_page_fault_possible )
   19.20 +        {
   19.21 +            pdb_page_fault = 1;
   19.22 +            /* make eax & edx valid to complete the instruction */
   19.23 +            regs->eax = (long)&pdb_page_fault_scratch;
   19.24 +            regs->edx = (long)&pdb_page_fault_scratch;
   19.25 +            return 1;
   19.26 +        }
   19.27 +        break;
   19.28 +    }
   19.29 +#endif
   19.30 +
   19.31 +#if 0
   19.32 +    extern int kdb_trap(int, int, struct xen_regs *);
   19.33 +    if ((ret = kdb_trap(type, 0, regs)))
   19.34 +        return ret;
   19.35 +#endif
   19.36 +
   19.37 +    return ret;
   19.38 +}
   19.39 +
   19.40 +#endif /* __DEBUGGER_HOOKS_H__ */
    20.1 --- a/xen/include/xen/keyhandler.h	Fri Nov 12 12:43:41 2004 +0000
    20.2 +++ b/xen/include/xen/keyhandler.h	Sat Nov 13 10:05:50 2004 +0000
    20.3 @@ -4,12 +4,13 @@
    20.4  ** debug flag, dump registers, reboot, etc) to be hooked in in a slightly
    20.5  ** nicer fashion than just editing the serial/keyboard drivers. 
    20.6  */
    20.7 -#include <xen/sched.h>
    20.8 +struct xen_regs;
    20.9  
   20.10  typedef void key_handler(unsigned char key);
   20.11  
   20.12  extern void add_key_handler(unsigned char key, 
   20.13  			    key_handler *handler, char *desc); 
   20.14 +extern void add_key_handler_no_defer(unsigned char key, 
   20.15 +                                     key_handler *handler, char *desc); 
   20.16  
   20.17 -extern void handle_keypress(unsigned char key);
   20.18 -
   20.19 +extern void handle_keypress(unsigned char key, struct xen_regs *regs);
    21.1 --- a/xen/include/xen/serial.h	Fri Nov 12 12:43:41 2004 +0000
    21.2 +++ b/xen/include/xen/serial.h	Sat Nov 13 10:05:50 2004 +0000
    21.3 @@ -42,6 +42,10 @@ void serial_puts(int handle, const unsig
    21.4   * called with interrupts disabled.
    21.5   */
    21.6  unsigned char serial_getc(int handle);
    21.7 +/* 
    21.8 + * Same as serial_getc but can also be called from interrupt handlers.
    21.9 + */
   21.10 +unsigned char irq_serial_getc(int handle);
   21.11  
   21.12  void serial_force_unlock(int handle);
   21.13