ia64/xen-unstable

changeset 2954:04d1ea76d4a6

bitkeeper revision 1.1159.170.10 (4194e863CFMzlWI0nAmHog0_NZ2vfQ)

Add in a minimal reimplementation of xend. This is mostly useful for prototyping things which would require wide-spread changes to xend, if implemented
there e.g. domain replay.

It is emphatically not useful as a replacement for xend in general use.
author sos22@douglas.cl.cam.ac.uk
date Fri Nov 12 16:44:19 2004 +0000 (2004-11-12)
parents 4fae09d780d4
children 42e5ff1b17e1
files .rootkeys BitKeeper/etc/ignore 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
line diff
     1.1 --- a/.rootkeys	Fri Nov 12 14:33:59 2004 +0000
     1.2 +++ b/.rootkeys	Fri Nov 12 16:44:19 2004 +0000
     1.3 @@ -527,6 +527,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
     2.1 --- a/BitKeeper/etc/ignore	Fri Nov 12 14:33:59 2004 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Fri Nov 12 16:44:19 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 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/x2d2/Makefile	Fri Nov 12 16:44:19 2004 +0000
     3.3 @@ -0,0 +1,10 @@
     3.4 +CFLAGS+=-Wall -g -Werror
     3.5 +
     3.6 +SRCS=main.c cntrl_con.c util.c
     3.7 +
     3.8 +all: minixend
     3.9 +
    3.10 +#$(SRCS): minixend.h
    3.11 +
    3.12 +minixend: $(subst .c,.o,$(SRCS))
    3.13 +	gcc $^ -o $@ $(LDFLAGS) -lxc -lpthread
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/x2d2/cntrl_con.c	Fri Nov 12 16:44:19 2004 +0000
     4.3 @@ -0,0 +1,458 @@
     4.4 +#define _GNU_SOURCE
     4.5 +
     4.6 +#include <sys/types.h>
     4.7 +#include <sys/ioctl.h>
     4.8 +#include <sys/socket.h>
     4.9 +#include <assert.h>
    4.10 +#include <ctype.h>
    4.11 +#include <err.h>
    4.12 +#include <errno.h>
    4.13 +#include <pthread.h>
    4.14 +#include <netinet/in.h>
    4.15 +#include <stdarg.h>
    4.16 +#include <stddef.h>
    4.17 +#include <stdio.h>
    4.18 +#include <stdlib.h>
    4.19 +#include <string.h>
    4.20 +#include <unistd.h>
    4.21 +
    4.22 +#include "minixend.h"
    4.23 +
    4.24 +struct command {
    4.25 +	const char *name;
    4.26 +	void (*func)(struct open_connection *oc, const struct command *c,
    4.27 +		     const char *, const char *);
    4.28 +};
    4.29 +
    4.30 +static void
    4.31 +domain_created(const char *name, int mem_kb, int domid)
    4.32 +{
    4.33 +	struct domain *d;
    4.34 +	d = xmalloc(sizeof(*d));
    4.35 +	d->domid = domid;
    4.36 +	d->name = xstrdup(name);
    4.37 +	d->mem_kb = mem_kb;
    4.38 +	d->state = DOM_STATE_CREATED;
    4.39 +	d->control_evtchn = -1; /* Not connected yet. */
    4.40 +
    4.41 +	memcpy(d->netif_mac, "\xaa\x00\x00\x02\x00\x00", 6);
    4.42 +	d->netif_mac[5] = d->domid;
    4.43 +
    4.44 +	pthread_mutex_init(&d->mux, NULL);
    4.45 +	pthread_cond_init(&d->cond, NULL);
    4.46 +
    4.47 +	pthread_create(&d->thread, NULL, domain_thread_func, d);
    4.48 +
    4.49 +	list_insert_after(&d->domain_list, &head_domain);
    4.50 +}
    4.51 +
    4.52 +static struct domain *
    4.53 +find_domain(int domain_id)
    4.54 +{
    4.55 +	struct domain *d;
    4.56 +
    4.57 +	foreach_domain(d) {
    4.58 +		if (d->domid == domain_id)
    4.59 +			return d;
    4.60 +	}
    4.61 +	return NULL;
    4.62 +}
    4.63 +
    4.64 +static int
    4.65 +free_event_port(struct domain *d, int port)
    4.66 +{
    4.67 +	if (d == NULL)
    4.68 +		return xc_evtchn_close(xc_handle, DOMID_SELF, port);
    4.69 +	else
    4.70 +		return xc_evtchn_close(xc_handle, d->domid, port);
    4.71 +}
    4.72 +
    4.73 +static char *
    4.74 +readline(struct open_connection *oc)
    4.75 +{
    4.76 +	char *end;
    4.77 +	char *res;
    4.78 +	int line_length;
    4.79 +
    4.80 +	if (oc->state == OC_STATE_ERROR)
    4.81 +		return NULL;
    4.82 +
    4.83 +	end = memchr(oc->buf, '\r', oc->buf_used);
    4.84 +	assert(end != NULL);
    4.85 +	line_length = end - oc->buf;
    4.86 +
    4.87 +	res = xmalloc(line_length + 1);
    4.88 +	memcpy(res, oc->buf, line_length);
    4.89 +	res[line_length] = 0;
    4.90 +	memmove(oc->buf, oc->buf + line_length + 2,
    4.91 +		oc->buf_used - line_length - 2);
    4.92 +
    4.93 +	oc->buf_used -= line_length + 2;
    4.94 +
    4.95 +	if (memchr(oc->buf, '\n', oc->buf_used))
    4.96 +		oc->state = OC_STATE_COMMAND_PENDING;
    4.97 +	else
    4.98 +		oc->state = OC_STATE_CONNECTED;
    4.99 +
   4.100 +	return res;
   4.101 +}
   4.102 +
   4.103 +static unsigned long
   4.104 +find_domain_shared_info_mfn(struct domain *d)
   4.105 +{
   4.106 +	xc_dominfo_t info;
   4.107 +
   4.108 +	xc_domain_getinfo(xc_handle, d->domid, 1, &info);
   4.109 +	return info.shared_info_frame;
   4.110 +}
   4.111 +
   4.112 +static void
   4.113 +send_message(struct open_connection *oc, const char *fmt, ...)
   4.114 +{
   4.115 +	char *buf;
   4.116 +	va_list ap;
   4.117 +	int size;
   4.118 +	int off;
   4.119 +	ssize_t r;
   4.120 +
   4.121 +	if (oc->state == OC_STATE_ERROR)
   4.122 +		return;
   4.123 +
   4.124 +	va_start(ap, fmt);
   4.125 +	size = vasprintf(&buf, fmt, ap);
   4.126 +	va_end(ap);
   4.127 +	if (size < 0)
   4.128 +		err(1, "preparing response to a query");
   4.129 +	assert(buf[0] == 'E' || buf[0] == 'N');
   4.130 +	assert(isdigit(buf[1]));
   4.131 +	assert(isdigit(buf[2]));
   4.132 +	assert(buf[3] == ' ' || buf[3] == '\n');
   4.133 +
   4.134 +	off = 0;
   4.135 +	while (off < size) {
   4.136 +		r = write(oc->fd, buf + off, size - off);
   4.137 +		if (r < 0) {
   4.138 +			warn("sending response to remote");
   4.139 +			oc->state = OC_STATE_ERROR;
   4.140 +			free(buf);
   4.141 +			return;
   4.142 +		}
   4.143 +		off += r;
   4.144 +	}
   4.145 +	free(buf);
   4.146 +}
   4.147 +
   4.148 +static void
   4.149 +default_command_handler(struct open_connection *oc, const struct command *ign,
   4.150 +			const char *buf, const char *args)
   4.151 +{
   4.152 +	warnx("bad command %s", buf);
   4.153 +	send_message(oc, "E00 unknown command %s\n", buf);
   4.154 +}
   4.155 +
   4.156 +static void
   4.157 +create_command_handler(struct open_connection *oc, const struct command *ign,
   4.158 +		       const char *buf, const char *args)
   4.159 +{
   4.160 +	char *name;
   4.161 +	unsigned mem_kb;
   4.162 +	int r;
   4.163 +	u32 domid = -1;
   4.164 +
   4.165 +	r = sscanf(args, "%d %a[^\n]", &mem_kb, &name);
   4.166 +	if (r != 2) {
   4.167 +		send_message(oc, "E01 failed to parse %s\n", args);
   4.168 +		return;
   4.169 +	}
   4.170 +	r = xc_domain_create(xc_handle, mem_kb, name, -1, 0, &domid);
   4.171 +	if (r < 0) {
   4.172 +		send_message(oc, "E02 creating domain (%s)\n",
   4.173 +			     strerror(errno));
   4.174 +		free(name);
   4.175 +		return;
   4.176 +	}
   4.177 +
   4.178 +	domain_created(name, mem_kb, domid);
   4.179 +
   4.180 +	send_message(oc, "N00 %d\n", domid);
   4.181 +	free(name);
   4.182 +}
   4.183 +
   4.184 +static void
   4.185 +build_command_handler(struct open_connection *oc, const struct command *ign,
   4.186 +		      const char *buf, const char *args)
   4.187 +{
   4.188 +	struct domain *d;
   4.189 +	int domain_id;
   4.190 +	char *image, *cmdline;
   4.191 +	int event_ports[2];
   4.192 +	int r;
   4.193 +
   4.194 +	r = sscanf(args, "%d %a[^\t] %a[^\n]", &domain_id,
   4.195 +		   &image, &cmdline);
   4.196 +	if (r != 3) {
   4.197 +		send_message(oc, "E03 failed to parse %s\n", args);
   4.198 +		return;
   4.199 +	}
   4.200 +	d = find_domain(domain_id);
   4.201 +	if (d == NULL) {
   4.202 +		send_message(oc, "E04 unknown domain %d\n", domain_id);
   4.203 +		goto out;
   4.204 +	}
   4.205 +	if (d->state != DOM_STATE_CREATED) {
   4.206 +		send_message(oc, "E05 domain %d in bad state\n", domain_id);
   4.207 +		goto out;
   4.208 +	}
   4.209 +
   4.210 +	r = allocate_event_channel(d, event_ports);
   4.211 +	if (r < 0) {
   4.212 +		send_message(oc, "E06 allocating control event channel: %s\n",
   4.213 +			     strerror(errno));
   4.214 +		goto out;
   4.215 +	}
   4.216 +
   4.217 +	r = xc_linux_build(xc_handle, domain_id, image, NULL, cmdline,
   4.218 +			   event_ports[1], 0);
   4.219 +	if (r < 0) {
   4.220 +		send_message(oc, "E07 building domain: %s\n",
   4.221 +			     strerror(errno));
   4.222 +		free_event_port(NULL, event_ports[0]);
   4.223 +		free_event_port(d, event_ports[1]);
   4.224 +		goto out;
   4.225 +	}
   4.226 +
   4.227 +	if (ioctl(evtchn_fd, EVTCHN_BIND, event_ports[0]) < 0)
   4.228 +		err(1, "binding to event control event channel");
   4.229 +
   4.230 +	d->shared_info_mfn = find_domain_shared_info_mfn(d);
   4.231 +	d->shared_info = map_domain_mem(d, d->shared_info_mfn);
   4.232 +	if (d->shared_info == NULL)
   4.233 +		err(1, "maping domain shared info page at %lx.\n",
   4.234 +		    d->shared_info_mfn);
   4.235 +	d->ctrl_if = (control_if_t *)((unsigned)d->shared_info + 2048);
   4.236 +
   4.237 +	d->control_evtchn = event_ports[0];
   4.238 +	d->state = DOM_STATE_PAUSED;
   4.239 +
   4.240 +	send_message(oc, "N00\n");
   4.241 +
   4.242 + out:
   4.243 +	free(image);
   4.244 +	free(cmdline);
   4.245 +	return;
   4.246 +}
   4.247 +
   4.248 +static void
   4.249 +unpause_command_handler(struct open_connection *oc,
   4.250 +			const struct command *ign,
   4.251 +			const char *buf,
   4.252 +			const char *args)
   4.253 +{
   4.254 +	int domain_id;
   4.255 +	int r;
   4.256 +	struct domain *d;
   4.257 +
   4.258 +	r = sscanf(args, "%d", &domain_id);
   4.259 +	if (r != 1) {
   4.260 +		send_message(oc, "E08 cannot parse %s\n", args);
   4.261 +		return;
   4.262 +	}
   4.263 +	d = find_domain(domain_id);
   4.264 +	if (d == NULL) {
   4.265 +		send_message(oc, "E09 cannot find domain %d\n", domain_id);
   4.266 +		return;
   4.267 +	}
   4.268 +	if (d->state != DOM_STATE_PAUSED) {
   4.269 +		send_message(oc, "E10 domain not paused\n");
   4.270 +		return;
   4.271 +	}
   4.272 +
   4.273 +	r = xc_domain_unpause(xc_handle, d->domid);
   4.274 +	if (r < 0) {
   4.275 +		send_message(oc, "E11 unpausing domain: %s\n",
   4.276 +			     strerror(errno));
   4.277 +		return;
   4.278 +	}
   4.279 +
   4.280 +	d->state = DOM_STATE_RUNNING;
   4.281 +	send_message(oc, "N00\n");
   4.282 +}
   4.283 +
   4.284 +static void
   4.285 +console_command_handler(struct open_connection *oc,
   4.286 +			const struct command *ign,
   4.287 +			const char *buf,
   4.288 +			const char *args)
   4.289 +{
   4.290 +	int domain_id;
   4.291 +	struct domain *d;
   4.292 +	int r;
   4.293 +	struct sockaddr_in name;
   4.294 +	socklen_t namelen;
   4.295 +
   4.296 +	r = sscanf(args, "%d", &domain_id);
   4.297 +	if (r != 1) {
   4.298 +		send_message(oc, "E12 cannot parse %s\n", args);
   4.299 +		return;
   4.300 +	}
   4.301 +	d = find_domain(domain_id);
   4.302 +	if (d == NULL) {
   4.303 +		send_message(oc, "E13 cannot find domain %d\n", domain_id);
   4.304 +		return;
   4.305 +	}
   4.306 +	if (d->cc != NULL) {
   4.307 +		send_message(oc, "E14 console already exists\n");
   4.308 +		return;
   4.309 +	}
   4.310 +
   4.311 +	d->cc = xmalloc(sizeof(*d->cc));
   4.312 +	d->cc->fd = socket(PF_INET, SOCK_STREAM, 0);
   4.313 +	if (d->cc->fd < 0)
   4.314 +		err(1, "creating console socket");
   4.315 +	d->cc->dom = d;
   4.316 +	d->cc->state = CC_STATE_PENDING;
   4.317 +	d->cc->buf_used = 0;
   4.318 +	d->cc->buf_allocated = 0;
   4.319 +	d->cc->buf = NULL;
   4.320 +
   4.321 +	r = listen(d->cc->fd, 1);
   4.322 +	if (r < 0)
   4.323 +		err(1, "listening on console socket");
   4.324 +	namelen = sizeof(name);
   4.325 +	r = getsockname(d->cc->fd, (struct sockaddr *)&name, &namelen);
   4.326 +	if (r < 0)
   4.327 +		err(1, "getting name of console socket");
   4.328 +	assert(name.sin_family == AF_INET);
   4.329 +	assert(namelen == sizeof(name));
   4.330 +	list_insert_after(&d->cc->list, &head_console);
   4.331 +	send_message(oc, "N00 %d\n", ntohs(name.sin_port));
   4.332 +}
   4.333 +
   4.334 +static void
   4.335 +plug_command_handler(struct open_connection *oc,
   4.336 +		     const struct command *ign,
   4.337 +		     const char *buf,
   4.338 +		     const char *args)
   4.339 +{
   4.340 +	unsigned domid;
   4.341 +	int r;
   4.342 +	struct domain *d;
   4.343 +
   4.344 +	r = sscanf(args, "%d", &domid);
   4.345 +	if (r != 1) {
   4.346 +		send_message(oc, "E15 cannot parse %s\n", args);
   4.347 +		return;
   4.348 +	}
   4.349 +	d = find_domain(domid);
   4.350 +	if (d == NULL) {
   4.351 +		send_message(oc, "E16 cannot find domain %d\n", domid);
   4.352 +		return;
   4.353 +	}
   4.354 +
   4.355 +	d->plugged = 1;
   4.356 +	send_message(oc, "N00\n");
   4.357 +	PRINTF(1, "set domain %d plug state to %d\n", d->domid, d->plugged);
   4.358 +}
   4.359 +
   4.360 +static void
   4.361 +destroy_command_handler(struct open_connection *oc,
   4.362 +			const struct command *ign,
   4.363 +			const char *buf,
   4.364 +			const char *args)
   4.365 +{
   4.366 +	unsigned domid;
   4.367 +	int r;
   4.368 +	struct domain *d;
   4.369 +
   4.370 +	r = sscanf(args, "%d", &domid);
   4.371 +	if (r != 1) {
   4.372 +		send_message(oc, "E17 cannot parse %s\n", args);
   4.373 +		return;
   4.374 +	}
   4.375 +	d = find_domain(domid);
   4.376 +	if (d == NULL) {
   4.377 +		send_message(oc, "E18 cannot find domain %d\n", domid);
   4.378 +		return;
   4.379 +	}
   4.380 +
   4.381 +	r = xc_domain_destroy(xc_handle, domid);
   4.382 +	if (r < 0) {
   4.383 +		send_message(oc, "E19 error destroying domain %d: %s\n",
   4.384 +			     domid, sys_errlist[errno]);
   4.385 +		return;
   4.386 +	}
   4.387 +	d->state = DOM_STATE_DEAD;
   4.388 +
   4.389 +	send_message(oc, "N00\n");
   4.390 +}
   4.391 +
   4.392 +static void
   4.393 +list_command_handler(struct open_connection *oc,
   4.394 +		     const struct command *ign,
   4.395 +		     const char *buf,
   4.396 +		     const char *args)
   4.397 +{
   4.398 +	struct domain *d;
   4.399 +	static const char *const state_strings[] = {
   4.400 +		[DOM_STATE_CREATED] = "created",
   4.401 +		[DOM_STATE_PAUSED] = "paused",
   4.402 +		[DOM_STATE_RUNNING] = "running",
   4.403 +		[DOM_STATE_DEAD] = "dead"
   4.404 +	};
   4.405 +
   4.406 +	foreach_domain(d) {
   4.407 +		send_message(oc, "N01 %d %s %d %s\n",
   4.408 +			     d->domid,
   4.409 +			     d->name,
   4.410 +			     d->mem_kb,
   4.411 +			     state_strings[d->state]);
   4.412 +	}
   4.413 +	send_message(oc, "N00\n");
   4.414 +}
   4.415 +
   4.416 +static struct command
   4.417 +default_command = { NULL, default_command_handler };
   4.418 +
   4.419 +static struct command
   4.420 +commands[] = {
   4.421 +	{ "build", build_command_handler },
   4.422 +	{ "console", console_command_handler },
   4.423 +	{ "create", create_command_handler },
   4.424 +	{ "destroy", destroy_command_handler },
   4.425 +	{ "plug", plug_command_handler },
   4.426 +	{ "list", list_command_handler },
   4.427 +	{ "unpause", unpause_command_handler }
   4.428 +};
   4.429 +
   4.430 +void
   4.431 +process_command(struct open_connection *oc)
   4.432 +{
   4.433 +	char *buf, *b;
   4.434 +	int command_len;
   4.435 +	int x;
   4.436 +	struct command *cmd;
   4.437 +
   4.438 +	buf = readline(oc);
   4.439 +	if (buf == NULL)
   4.440 +		return;
   4.441 +	b = strchr(buf, ' ');
   4.442 +	if (b == NULL)
   4.443 +		command_len = strlen(buf);
   4.444 +	else
   4.445 +		command_len = b - buf;
   4.446 +	b = buf + command_len;
   4.447 +	while (b[0] && b[0] == ' ')
   4.448 +		b++;
   4.449 +
   4.450 +	cmd = &default_command;
   4.451 +	for (x = 0; x < sizeof(commands) / sizeof(commands[0]); x++) {
   4.452 +		if (strlen(commands[x].name) == command_len &&
   4.453 +		    memcmp(commands[x].name, buf, command_len) == 0) {
   4.454 +			cmd = &commands[x];
   4.455 +			break;
   4.456 +		}
   4.457 +	}
   4.458 +	cmd->func(oc, cmd, buf, b);
   4.459 +	free(buf);
   4.460 +	return;
   4.461 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/x2d2/domain_controller.h	Fri Nov 12 16:44:19 2004 +0000
     5.3 @@ -0,0 +1,562 @@
     5.4 +/******************************************************************************
     5.5 + * domain_controller.h
     5.6 + * 
     5.7 + * Interface to server controller (e.g., 'xend'). This header file defines the 
     5.8 + * interface that is shared with guest OSes.
     5.9 + * 
    5.10 + * Copyright (c) 2004, K A Fraser
    5.11 + */
    5.12 +
    5.13 +/* I've copied this from the xen source pool as getting Xen and
    5.14 +   userspace headers to play nicely together is beyond me -- sos22 */
    5.15 +#define PACKED __attribute__ ((packed))
    5.16 +typedef unsigned long memory_t;   /* Full-sized pointer/address/memory-size. */
    5.17 +#define __MEMORY_PADDING(_X) u32 __pad_ ## _X
    5.18 +#define _MEMORY_PADDING(_X)  __MEMORY_PADDING(_X)
    5.19 +#define MEMORY_PADDING       _MEMORY_PADDING(__LINE__)
    5.20 +typedef u16 domid_t;
    5.21 +
    5.22 +/*
    5.23 + * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
    5.24 + * interpreted by control software to determine the appropriate action. These 
    5.25 + * are only really advisories: the controller can actually do as it likes.
    5.26 + */
    5.27 +#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
    5.28 +#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
    5.29 +#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
    5.30 +
    5.31 +
    5.32 +/*
    5.33 + * CONTROLLER MESSAGING INTERFACE.
    5.34 + */
    5.35 +
    5.36 +typedef struct {
    5.37 +    u8 type;     /*  0: echoed in response */
    5.38 +    u8 subtype;  /*  1: echoed in response */
    5.39 +    u8 id;       /*  2: echoed in response */
    5.40 +    u8 length;   /*  3: number of bytes in 'msg' */
    5.41 +    u8 msg[60];  /*  4: type-specific message data */
    5.42 +} PACKED control_msg_t; /* 64 bytes */
    5.43 +
    5.44 +#define CONTROL_RING_SIZE 8
    5.45 +typedef u32 CONTROL_RING_IDX;
    5.46 +#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
    5.47 +
    5.48 +typedef struct {
    5.49 +    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
    5.50 +    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
    5.51 +    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
    5.52 +    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
    5.53 +} PACKED control_if_t; /* 1040 bytes */
    5.54 +
    5.55 +/*
    5.56 + * Top-level command types.
    5.57 + */
    5.58 +#define CMSG_CONSOLE        0  /* Console                 */
    5.59 +#define CMSG_BLKIF_BE       1  /* Block-device backend    */
    5.60 +#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
    5.61 +#define CMSG_NETIF_BE       3  /* Network-device backend  */
    5.62 +#define CMSG_NETIF_FE       4  /* Network-device frontend */
    5.63 +#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
    5.64 +#define CMSG_PDB_BE         7  /* PDB backend.            */
    5.65 +#define CMSG_PDB_FE         8  /* PDB frontend.           */
    5.66 +
    5.67 +/******************************************************************************
    5.68 + * CONSOLE DEFINITIONS
    5.69 + */
    5.70 +
    5.71 +/*
    5.72 + * Subtypes for console messages.
    5.73 + */
    5.74 +#define CMSG_CONSOLE_DATA       0
    5.75 +
    5.76 +
    5.77 +/******************************************************************************
    5.78 + * BLOCK-INTERFACE FRONTEND DEFINITIONS
    5.79 + */
    5.80 +
    5.81 +/* Messages from domain controller to guest. */
    5.82 +#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
    5.83 +
    5.84 +/* Messages from guest to domain controller. */
    5.85 +#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
    5.86 +#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
    5.87 +#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
    5.88 +
    5.89 +/* These are used by both front-end and back-end drivers. */
    5.90 +#define blkif_vdev_t   u16
    5.91 +#define blkif_pdev_t   u16
    5.92 +#define blkif_sector_t u64
    5.93 +
    5.94 +/*
    5.95 + * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
    5.96 + *  Notify a guest about a status change on one of its block interfaces.
    5.97 + *  If the interface is DESTROYED or DOWN then the interface is disconnected:
    5.98 + *   1. The shared-memory frame is available for reuse.
    5.99 + *   2. Any unacknowledged messgaes pending on the interface were dropped.
   5.100 + */
   5.101 +#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
   5.102 +#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
   5.103 +#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
   5.104 +typedef struct {
   5.105 +    u32 handle; /*  0 */
   5.106 +    u32 status; /*  4 */
   5.107 +    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
   5.108 +} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
   5.109 +
   5.110 +/*
   5.111 + * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
   5.112 + *  Notify the domain controller that the front-end driver is DOWN or UP.
   5.113 + *  When the driver goes DOWN then the controller will send no more
   5.114 + *  status-change notifications. When the driver comes UP then the controller
   5.115 + *  will send a notification for each interface that currently exists.
   5.116 + *  If the driver goes DOWN while interfaces are still UP, the domain
   5.117 + *  will automatically take the interfaces DOWN.
   5.118 + */
   5.119 +#define BLKIF_DRIVER_STATUS_DOWN   0
   5.120 +#define BLKIF_DRIVER_STATUS_UP     1
   5.121 +typedef struct {
   5.122 +    /* IN */
   5.123 +    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
   5.124 +    /* OUT */
   5.125 +    /*
   5.126 +     * Tells driver how many interfaces it should expect to immediately
   5.127 +     * receive notifications about.
   5.128 +     */
   5.129 +    u32 nr_interfaces; /*  4 */
   5.130 +} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
   5.131 +
   5.132 +/*
   5.133 + * CMSG_BLKIF_FE_INTERFACE_CONNECT:
   5.134 + *  If successful, the domain controller will acknowledge with a
   5.135 + *  STATUS_CONNECTED message.
   5.136 + */
   5.137 +typedef struct {
   5.138 +    u32      handle;      /*  0 */
   5.139 +    u32      __pad;
   5.140 +    memory_t shmem_frame; /*  8 */
   5.141 +    MEMORY_PADDING;
   5.142 +} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
   5.143 +
   5.144 +/*
   5.145 + * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
   5.146 + *  If successful, the domain controller will acknowledge with a
   5.147 + *  STATUS_DISCONNECTED message.
   5.148 + */
   5.149 +typedef struct {
   5.150 +    u32 handle; /*  0 */
   5.151 +} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
   5.152 +
   5.153 +
   5.154 +/******************************************************************************
   5.155 + * BLOCK-INTERFACE BACKEND DEFINITIONS
   5.156 + */
   5.157 +
   5.158 +/* Messages from domain controller. */
   5.159 +#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
   5.160 +#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
   5.161 +#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
   5.162 +#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
   5.163 +#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
   5.164 +#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
   5.165 +#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
   5.166 +#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
   5.167 +
   5.168 +/* Messages to domain controller. */
   5.169 +#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
   5.170 +
   5.171 +/*
   5.172 + * Message request/response definitions for block-device messages.
   5.173 + */
   5.174 +
   5.175 +typedef struct {
   5.176 +    blkif_sector_t sector_start;   /*  0 */
   5.177 +    blkif_sector_t sector_length;  /*  8 */
   5.178 +    blkif_pdev_t   device;         /* 16 */
   5.179 +    u16            __pad;          /* 18 */
   5.180 +} PACKED blkif_extent_t; /* 20 bytes */
   5.181 +
   5.182 +/* Non-specific 'okay' return. */
   5.183 +#define BLKIF_BE_STATUS_OKAY                0
   5.184 +/* Non-specific 'error' return. */
   5.185 +#define BLKIF_BE_STATUS_ERROR               1
   5.186 +/* The following are specific error returns. */
   5.187 +#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
   5.188 +#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
   5.189 +#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
   5.190 +#define BLKIF_BE_STATUS_VBD_EXISTS          5
   5.191 +#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
   5.192 +#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
   5.193 +#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
   5.194 +#define BLKIF_BE_STATUS_MAPPING_ERROR       9
   5.195 +
   5.196 +/* This macro can be used to create an array of descriptive error strings. */
   5.197 +#define BLKIF_BE_STATUS_ERRORS {    \
   5.198 +    "Okay",                         \
   5.199 +    "Non-specific error",           \
   5.200 +    "Interface already exists",     \
   5.201 +    "Interface not found",          \
   5.202 +    "Interface is still connected", \
   5.203 +    "VBD already exists",           \
   5.204 +    "VBD not found",                \
   5.205 +    "Out of memory",                \
   5.206 +    "Extent not found for VBD",     \
   5.207 +    "Could not map domain memory" }
   5.208 +
   5.209 +/*
   5.210 + * CMSG_BLKIF_BE_CREATE:
   5.211 + *  When the driver sends a successful response then the interface is fully
   5.212 + *  created. The controller will send a DOWN notification to the front-end
   5.213 + *  driver.
   5.214 + */
   5.215 +typedef struct { 
   5.216 +    /* IN */
   5.217 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   5.218 +    u16        __pad;
   5.219 +    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
   5.220 +    /* OUT */
   5.221 +    u32        status;        /*  8 */
   5.222 +} PACKED blkif_be_create_t; /* 12 bytes */
   5.223 +
   5.224 +/*
   5.225 + * CMSG_BLKIF_BE_DESTROY:
   5.226 + *  When the driver sends a successful response then the interface is fully
   5.227 + *  torn down. The controller will send a DESTROYED notification to the
   5.228 + *  front-end driver.
   5.229 + */
   5.230 +typedef struct { 
   5.231 +    /* IN */
   5.232 +    domid_t    domid;         /*  0: Identify interface to be destroyed. */
   5.233 +    u16        __pad;
   5.234 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   5.235 +    /* OUT */
   5.236 +    u32        status;        /*  8 */
   5.237 +} PACKED blkif_be_destroy_t; /* 12 bytes */
   5.238 +
   5.239 +/*
   5.240 + * CMSG_BLKIF_BE_CONNECT:
   5.241 + *  When the driver sends a successful response then the interface is fully
   5.242 + *  connected. The controller will send a CONNECTED notification to the
   5.243 + *  front-end driver.
   5.244 + */
   5.245 +typedef struct { 
   5.246 +    /* IN */
   5.247 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   5.248 +    u16        __pad;
   5.249 +    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
   5.250 +    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
   5.251 +    MEMORY_PADDING;
   5.252 +    u32        evtchn;        /* 16: Event channel for notifications.    */
   5.253 +    /* OUT */
   5.254 +    u32        status;        /* 20 */
   5.255 +} PACKED blkif_be_connect_t;  /* 24 bytes */
   5.256 +
   5.257 +/*
   5.258 + * CMSG_BLKIF_BE_DISCONNECT:
   5.259 + *  When the driver sends a successful response then the interface is fully
   5.260 + *  disconnected. The controller will send a DOWN notification to the front-end
   5.261 + *  driver.
   5.262 + */
   5.263 +typedef struct { 
   5.264 +    /* IN */
   5.265 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   5.266 +    u16        __pad;
   5.267 +    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
   5.268 +    /* OUT */
   5.269 +    u32        status;        /*  8 */
   5.270 +} PACKED blkif_be_disconnect_t; /* 12 bytes */
   5.271 +
   5.272 +/* CMSG_BLKIF_BE_VBD_CREATE */
   5.273 +typedef struct { 
   5.274 +    /* IN */
   5.275 +    domid_t    domid;         /*  0: Identify blkdev interface.          */
   5.276 +    u16        __pad;
   5.277 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   5.278 +    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
   5.279 +    u16        readonly;      /* 10: Non-zero -> VBD isn't writable.     */
   5.280 +    /* OUT */
   5.281 +    u32        status;        /* 12 */
   5.282 +} PACKED blkif_be_vbd_create_t; /* 16 bytes */
   5.283 +
   5.284 +/* CMSG_BLKIF_BE_VBD_DESTROY */
   5.285 +typedef struct {
   5.286 +    /* IN */
   5.287 +    domid_t    domid;         /*  0: Identify blkdev interface.          */
   5.288 +    u16        __pad0;        /*  2 */
   5.289 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   5.290 +    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
   5.291 +    u16        __pad1;        /* 10 */
   5.292 +    /* OUT */
   5.293 +    u32        status;        /* 12 */
   5.294 +} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
   5.295 +
   5.296 +/* CMSG_BLKIF_BE_VBD_GROW */
   5.297 +typedef struct { 
   5.298 +    /* IN */
   5.299 +    domid_t    domid;         /*  0: Identify blkdev interface.          */
   5.300 +    u16        __pad0;        /*  2 */
   5.301 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   5.302 +    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
   5.303 +    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
   5.304 +    u16        __pad1;        /* 30 */
   5.305 +    /* OUT */
   5.306 +    u32        status;        /* 32 */
   5.307 +} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
   5.308 +
   5.309 +/* CMSG_BLKIF_BE_VBD_SHRINK */
   5.310 +typedef struct { 
   5.311 +    /* IN */
   5.312 +    domid_t    domid;         /*  0: Identify blkdev interface.          */
   5.313 +    u16        __pad0;        /*  2 */
   5.314 +    u32        blkif_handle;  /*  4: ...ditto...                         */
   5.315 +    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
   5.316 +    u16        __pad1;        /* 10 */
   5.317 +    /* OUT */
   5.318 +    u32        status;        /* 12 */
   5.319 +} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
   5.320 +
   5.321 +/*
   5.322 + * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
   5.323 + *  Notify the domain controller that the back-end driver is DOWN or UP.
   5.324 + *  If the driver goes DOWN while interfaces are still UP, the controller
   5.325 + *  will automatically send DOWN notifications.
   5.326 + */
   5.327 +typedef struct {
   5.328 +    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
   5.329 +} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
   5.330 +
   5.331 +
   5.332 +/******************************************************************************
   5.333 + * NETWORK-INTERFACE FRONTEND DEFINITIONS
   5.334 + */
   5.335 +
   5.336 +/* Messages from domain controller to guest. */
   5.337 +#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
   5.338 +
   5.339 +/* Messages from guest to domain controller. */
   5.340 +#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
   5.341 +#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
   5.342 +#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
   5.343 +
   5.344 +/*
   5.345 + * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
   5.346 + *  Notify a guest about a status change on one of its network interfaces.
   5.347 + *  If the interface is DESTROYED or DOWN then the interface is disconnected:
   5.348 + *   1. The shared-memory frame is available for reuse.
   5.349 + *   2. Any unacknowledged messgaes pending on the interface were dropped.
   5.350 + */
   5.351 +#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
   5.352 +#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
   5.353 +#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
   5.354 +typedef struct {
   5.355 +    u32        handle; /*  0 */
   5.356 +    u32        status; /*  4 */
   5.357 +    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
   5.358 +    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
   5.359 +} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
   5.360 +
   5.361 +/*
   5.362 + * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
   5.363 + *  Notify the domain controller that the front-end driver is DOWN or UP.
   5.364 + *  When the driver goes DOWN then the controller will send no more
   5.365 + *  status-change notifications. When the driver comes UP then the controller
   5.366 + *  will send a notification for each interface that currently exists.
   5.367 + *  If the driver goes DOWN while interfaces are still UP, the domain
   5.368 + *  will automatically take the interfaces DOWN.
   5.369 + */
   5.370 +#define NETIF_DRIVER_STATUS_DOWN   0
   5.371 +#define NETIF_DRIVER_STATUS_UP     1
   5.372 +typedef struct {
   5.373 +    /* IN */
   5.374 +    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
   5.375 +    /* OUT */
   5.376 +    /*
   5.377 +     * Tells driver how many interfaces it should expect to immediately
   5.378 +     * receive notifications about.
   5.379 +     */
   5.380 +    u32        nr_interfaces; /*  4 */
   5.381 +} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
   5.382 +
   5.383 +/*
   5.384 + * CMSG_NETIF_FE_INTERFACE_CONNECT:
   5.385 + *  If successful, the domain controller will acknowledge with a
   5.386 + *  STATUS_CONNECTED message.
   5.387 + */
   5.388 +typedef struct {
   5.389 +    u32        handle;         /*  0 */
   5.390 +    u32        __pad;          /*  4 */
   5.391 +    memory_t   tx_shmem_frame; /*  8 */
   5.392 +    MEMORY_PADDING;
   5.393 +    memory_t   rx_shmem_frame; /* 16 */
   5.394 +    MEMORY_PADDING;
   5.395 +} PACKED netif_fe_interface_connect_t; /* 24 bytes */
   5.396 +
   5.397 +/*
   5.398 + * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
   5.399 + *  If successful, the domain controller will acknowledge with a
   5.400 + *  STATUS_DISCONNECTED message.
   5.401 + */
   5.402 +typedef struct {
   5.403 +    u32        handle;        /*  0 */
   5.404 +} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
   5.405 +
   5.406 +
   5.407 +/******************************************************************************
   5.408 + * NETWORK-INTERFACE BACKEND DEFINITIONS
   5.409 + */
   5.410 +
   5.411 +/* Messages from domain controller. */
   5.412 +#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
   5.413 +#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
   5.414 +#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
   5.415 +#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
   5.416 +
   5.417 +/* Messages to domain controller. */
   5.418 +#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
   5.419 +
   5.420 +/*
   5.421 + * Message request/response definitions for net-device messages.
   5.422 + */
   5.423 +
   5.424 +/* Non-specific 'okay' return. */
   5.425 +#define NETIF_BE_STATUS_OKAY                0
   5.426 +/* Non-specific 'error' return. */
   5.427 +#define NETIF_BE_STATUS_ERROR               1
   5.428 +/* The following are specific error returns. */
   5.429 +#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
   5.430 +#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
   5.431 +#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
   5.432 +#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
   5.433 +#define NETIF_BE_STATUS_MAPPING_ERROR       6
   5.434 +
   5.435 +/* This macro can be used to create an array of descriptive error strings. */
   5.436 +#define NETIF_BE_STATUS_ERRORS {    \
   5.437 +    "Okay",                         \
   5.438 +    "Non-specific error",           \
   5.439 +    "Interface already exists",     \
   5.440 +    "Interface not found",          \
   5.441 +    "Interface is still connected", \
   5.442 +    "Out of memory",                \
   5.443 +    "Could not map domain memory" }
   5.444 +
   5.445 +/*
   5.446 + * CMSG_NETIF_BE_CREATE:
   5.447 + *  When the driver sends a successful response then the interface is fully
   5.448 + *  created. The controller will send a DOWN notification to the front-end
   5.449 + *  driver.
   5.450 + */
   5.451 +typedef struct { 
   5.452 +    /* IN */
   5.453 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   5.454 +    u16        __pad0;        /*  2 */
   5.455 +    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
   5.456 +    u8         mac[6];        /*  8 */
   5.457 +    u16        __pad1;        /* 14 */
   5.458 +    /* OUT */
   5.459 +    u32        status;        /* 16 */
   5.460 +} PACKED netif_be_create_t; /* 20 bytes */
   5.461 +
   5.462 +/*
   5.463 + * CMSG_NETIF_BE_DESTROY:
   5.464 + *  When the driver sends a successful response then the interface is fully
   5.465 + *  torn down. The controller will send a DESTROYED notification to the
   5.466 + *  front-end driver.
   5.467 + */
   5.468 +typedef struct { 
   5.469 +    /* IN */
   5.470 +    domid_t    domid;         /*  0: Identify interface to be destroyed. */
   5.471 +    u16        __pad;
   5.472 +    u32        netif_handle;  /*  4: ...ditto...                         */
   5.473 +    /* OUT */
   5.474 +    u32   status;             /*  8 */
   5.475 +} PACKED netif_be_destroy_t; /* 12 bytes */
   5.476 +
   5.477 +/*
   5.478 + * CMSG_NETIF_BE_CONNECT:
   5.479 + *  When the driver sends a successful response then the interface is fully
   5.480 + *  connected. The controller will send a CONNECTED notification to the
   5.481 + *  front-end driver.
   5.482 + */
   5.483 +typedef struct { 
   5.484 +    /* IN */
   5.485 +    domid_t    domid;          /*  0: Domain attached to new interface.   */
   5.486 +    u16        __pad0;         /*  2 */
   5.487 +    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
   5.488 +    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
   5.489 +    MEMORY_PADDING;
   5.490 +    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
   5.491 +    MEMORY_PADDING;
   5.492 +    u16        evtchn;         /* 24: Event channel for notifications.    */
   5.493 +    u16        __pad1;         /* 26 */
   5.494 +    /* OUT */
   5.495 +    u32        status;         /* 28 */
   5.496 +} PACKED netif_be_connect_t; /* 32 bytes */
   5.497 +
   5.498 +/*
   5.499 + * CMSG_NETIF_BE_DISCONNECT:
   5.500 + *  When the driver sends a successful response then the interface is fully
   5.501 + *  disconnected. The controller will send a DOWN notification to the front-end
   5.502 + *  driver.
   5.503 + */
   5.504 +typedef struct { 
   5.505 +    /* IN */
   5.506 +    domid_t    domid;         /*  0: Domain attached to new interface.   */
   5.507 +    u16        __pad;
   5.508 +    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
   5.509 +    /* OUT */
   5.510 +    u32        status;        /*  8 */
   5.511 +} PACKED netif_be_disconnect_t; /* 12 bytes */
   5.512 +
   5.513 +/*
   5.514 + * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
   5.515 + *  Notify the domain controller that the back-end driver is DOWN or UP.
   5.516 + *  If the driver goes DOWN while interfaces are still UP, the domain
   5.517 + *  will automatically send DOWN notifications.
   5.518 + */
   5.519 +typedef struct {
   5.520 +    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
   5.521 +} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
   5.522 +
   5.523 +
   5.524 +/******************************************************************************
   5.525 + * SHUTDOWN DEFINITIONS
   5.526 + */
   5.527 +
   5.528 +/*
   5.529 + * Subtypes for shutdown messages.
   5.530 + */
   5.531 +#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
   5.532 +#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
   5.533 +#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
   5.534 +                                    /* SHUTDOWN_suspend.                     */
   5.535 +
   5.536 +/******************************************************************************
   5.537 + * PDB DEFINITIONS
   5.538 + */
   5.539 +
   5.540 +/* Notify the backend that a new frontend has connected. */
   5.541 +#define CMSG_PDB_BE_INTERFACE_CONNECTED 0
   5.542 +typedef struct {
   5.543 +    int assist_port;
   5.544 +    int event_port;
   5.545 +} pdb_be_connected_t;
   5.546 +
   5.547 +/* Notify the domain controller that the status of the backend has
   5.548 +   changed. */
   5.549 +#define CMSG_PDB_BE_DRIVER_STATUS_CHANGED 1
   5.550 +typedef struct {
   5.551 +    unsigned status;
   5.552 +#define PDB_DRIVER_STATUS_UP 1
   5.553 +    unsigned long event_page;
   5.554 +    unsigned long assist_page;
   5.555 +} pdb_be_driver_status_changed_t;
   5.556 +
   5.557 +/* Notify a front end that a back end just popped up. */
   5.558 +#define CMSG_PDB_FE_NEW_BE 0
   5.559 +typedef struct {
   5.560 +    int domain;
   5.561 +    int assist_evtchn;
   5.562 +    int event_evtchn;
   5.563 +    unsigned long assist_frame;
   5.564 +    unsigned long event_frame;
   5.565 +} pdb_fe_new_be_t;
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/x2d2/main.c	Fri Nov 12 16:44:19 2004 +0000
     6.3 @@ -0,0 +1,1012 @@
     6.4 +#define _GNU_SOURCE
     6.5 +
     6.6 +#include <sys/types.h>
     6.7 +#include <sys/fcntl.h>
     6.8 +#include <sys/ioctl.h>
     6.9 +#include <sys/mman.h>
    6.10 +#include <sys/select.h>
    6.11 +#include <sys/socket.h>
    6.12 +#include <sys/wait.h>
    6.13 +#include <asm/page.h>
    6.14 +#include <assert.h>
    6.15 +#include <ctype.h>
    6.16 +#include <err.h>
    6.17 +#include <errno.h>
    6.18 +#include <netinet/in.h>
    6.19 +#include <printf.h>
    6.20 +#include <pthread.h>
    6.21 +#include <stdarg.h>
    6.22 +#include <stddef.h>
    6.23 +#include <stdio.h>
    6.24 +#include <stdlib.h>
    6.25 +#include <string.h>
    6.26 +#include <unistd.h>
    6.27 +
    6.28 +#include "minixend.h"
    6.29 +
    6.30 +#define MINIXEND_PORT 5123
    6.31 +
    6.32 +#define mb() asm volatile ("" ::: "memory")
    6.33 +
    6.34 +static void send_control_message(int type, int subtype, int id,
    6.35 +				 int size, void *payload,
    6.36 +				 struct domain *target);
    6.37 +
    6.38 +struct list_head
    6.39 +head_domain = LIST_HEAD(&head_domain);
    6.40 +
    6.41 +static struct list_head
    6.42 +head_connection = LIST_HEAD(&head_connection);
    6.43 +
    6.44 +struct list_head
    6.45 +head_console = LIST_HEAD(&head_console);
    6.46 +
    6.47 +#define foreach_open_connection(d)                                          \
    6.48 +foreach_item(d, &head_connection, struct open_connection, connection_list)
    6.49 +
    6.50 +/* Not modified after initial start up */
    6.51 +static struct domain *
    6.52 +dom0;
    6.53 +unsigned
    6.54 +xc_handle;
    6.55 +static int
    6.56 +listen_fd;
    6.57 +int
    6.58 +evtchn_fd;
    6.59 +
    6.60 +static struct list_head
    6.61 +head_event_receiver = LIST_HEAD(&head_event_receiver);
    6.62 +
    6.63 +struct event_receiver {
    6.64 +	struct list_head list;
    6.65 +	int id;
    6.66 +	pthread_cond_t cond;
    6.67 +};
    6.68 +
    6.69 +/* We're protected by the dom0 mutex in here */
    6.70 +static struct event_receiver *
    6.71 +allocate_event_receiver(struct domain *d)
    6.72 +{
    6.73 +	static int next_message_id;
    6.74 +	struct event_receiver *work;
    6.75 +
    6.76 +	assert(d == dom0);
    6.77 +	work = xmalloc(sizeof(*work));
    6.78 +	work->id = next_message_id++;
    6.79 +	pthread_cond_init(&work->cond, NULL);
    6.80 +
    6.81 +	list_insert_after(&work->list, &head_event_receiver);
    6.82 +
    6.83 +	return work;
    6.84 +}
    6.85 +
    6.86 +static struct event_receiver *
    6.87 +find_event_receiver(int id)
    6.88 +{
    6.89 +	struct event_receiver *work;
    6.90 +	foreach_item(work, &head_event_receiver, struct event_receiver, list)
    6.91 +		if (work->id == id)
    6.92 +			return work;
    6.93 +	return NULL;
    6.94 +}
    6.95 +
    6.96 +static void
    6.97 +release_event_receiver(struct event_receiver *w)
    6.98 +{
    6.99 +	list_remove(&w->list);
   6.100 +	pthread_cond_destroy(&w->cond);
   6.101 +	free(w);
   6.102 +}
   6.103 +
   6.104 +/* Send a message to dom0, and then block awaiting a reply. */
   6.105 +/* Make sure we don't hold any domain mutexs */
   6.106 +static void
   6.107 +send_dom0_message_block(control_msg_t *msg)
   6.108 +{
   6.109 +	CONTROL_RING_IDX c;
   6.110 +	struct event_receiver *er;
   6.111 +	control_msg_t buf;
   6.112 +
   6.113 +	PRINTF(0, "sending message to dom0 and blocking for reply.\n");
   6.114 +	pthread_mutex_lock(&dom0->mux);
   6.115 +	PRINTF(0, "got dom0 lock.\n");
   6.116 +	er = allocate_event_receiver(dom0);
   6.117 +	PRINTF(0, "allocated evetn receiver.\n");
   6.118 +	msg->id = er->id;
   6.119 +	PRINTF(1, "sending message with id %d\n", msg->id);
   6.120 +	send_control_message(msg->type, msg->subtype,
   6.121 +			     msg->id, msg->length, msg->msg, dom0);
   6.122 +	xc_evtchn_send(xc_handle, dom0->control_evtchn);
   6.123 +
   6.124 +	PRINTF(0, "waiting for reply\n");
   6.125 +	pthread_cond_wait(&er->cond, &dom0->mux);
   6.126 +	PRINTF(0, "got reply\n");
   6.127 +
   6.128 +	c = dom0->rx_resp_cons % CONTROL_RING_SIZE;
   6.129 +	memcpy(&buf, &dom0->ctrl_if->rx_ring[c], sizeof(buf));
   6.130 +	assert(msg->id == buf.id);
   6.131 +	assert(msg->type == buf.type);
   6.132 +	assert(msg->subtype == buf.subtype);
   6.133 +	memcpy(msg, &buf, sizeof(*msg));
   6.134 +	dom0->rx_resp_cons++;
   6.135 +
   6.136 +	release_event_receiver(er);
   6.137 +
   6.138 +	pthread_mutex_unlock(&dom0->mux);
   6.139 +
   6.140 +	PRINTF(1, "got reply to message with id %d\n", msg->id);
   6.141 +}
   6.142 +
   6.143 +/* Allocate an interdomain event channel.  event_ports[0] is the
   6.144 +   local event port number, event_ports[1] the remote */
   6.145 +int
   6.146 +allocate_event_channel(struct domain *d, int event_ports[2])
   6.147 +{
   6.148 +	return xc_evtchn_bind_interdomain(xc_handle, DOMID_SELF,
   6.149 +					  d->domid, event_ports,
   6.150 +					  event_ports+1);
   6.151 +}
   6.152 +
   6.153 +static void
   6.154 +accept_new_connection(void)
   6.155 +{
   6.156 +	int fd;
   6.157 +	struct open_connection *oc;
   6.158 +
   6.159 +	fd = accept(listen_fd, NULL, NULL);
   6.160 +	if (fd < 0)
   6.161 +		return;
   6.162 +	oc = xmalloc(sizeof(*oc));
   6.163 +	oc->fd = fd;
   6.164 +	oc->state = OC_STATE_CONNECTED;
   6.165 +	oc->buf_used = 0;
   6.166 +	oc->buf_allocated = 16;
   6.167 +	oc->buf = xmalloc(oc->buf_allocated);
   6.168 +	list_insert_after(&oc->connection_list, &head_connection);
   6.169 +}
   6.170 +
   6.171 +static void
   6.172 +closedown_connection(struct open_connection *oc)
   6.173 +{
   6.174 +	close(oc->fd);
   6.175 +	assert(oc->buf);
   6.176 +	free(oc->buf);
   6.177 +	free(oc);
   6.178 +}
   6.179 +
   6.180 +#if 0
   6.181 +/* Hackl for the benefit of domain replay */
   6.182 +static unsigned
   6.183 +report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
   6.184 +{
   6.185 +	if (!do_direct) {
   6.186 +		int rc;
   6.187 +		asm("int $0x80" : "=a" (rc)
   6.188 +		    : "0" (264), "b" (ptr), "c" (val), "d" (dom));
   6.189 +		if (rc < 0) {
   6.190 +			errno = -rc;
   6.191 +			rc = -1;
   6.192 +		}
   6.193 +		return rc;
   6.194 +	} else {
   6.195 +		*ptr = val;
   6.196 +		return 0;
   6.197 +	}
   6.198 +}
   6.199 +#else
   6.200 +static unsigned
   6.201 +report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
   6.202 +{
   6.203 +	*ptr = val;
   6.204 +	return 0;
   6.205 +}
   6.206 +#endif
   6.207 +
   6.208 +static void
   6.209 +send_control_reply(const control_msg_t *msg, struct domain *d)
   6.210 +{
   6.211 +	CONTROL_RING_IDX c;
   6.212 +
   6.213 +	PRINTF(3,"Control reply, type %d:%d, length %d.\n",
   6.214 +	       msg->type, msg->subtype, msg->length);
   6.215 +	c = d->ctrl_if->tx_resp_prod % CONTROL_RING_SIZE;
   6.216 +	memcpy(&d->ctrl_if->tx_ring[c], msg, sizeof(*msg));
   6.217 +	report_work(&d->ctrl_if->tx_resp_prod,
   6.218 +		    d->ctrl_if->tx_resp_prod + 1,
   6.219 +		    d->domid,
   6.220 +		    0);
   6.221 +	PRINTF(4,"tx_resp_prod %ld.\n", d->ctrl_if->tx_resp_prod);
   6.222 +	assert(!d->plugged);
   6.223 +}
   6.224 +
   6.225 +static void
   6.226 +send_trivial_control_reply(const control_msg_t *msg, struct domain *d)
   6.227 +{
   6.228 +	control_msg_t rep;
   6.229 +
   6.230 +	memset(&rep, 0, sizeof(rep));
   6.231 +	rep.type = msg->type;
   6.232 +	rep.subtype = msg->subtype;
   6.233 +	rep.id = msg->id;
   6.234 +	send_control_reply(&rep, d);
   6.235 +}
   6.236 +
   6.237 +static void
   6.238 +process_console_control_message(control_msg_t *m, struct domain *d)
   6.239 +{
   6.240 +	int off;
   6.241 +	int r;
   6.242 +
   6.243 +	if (m->subtype != CMSG_CONSOLE_DATA) {
   6.244 +		warnx("unknown console message subtype %d",
   6.245 +		      m->subtype);
   6.246 +		return;
   6.247 +	}
   6.248 +
   6.249 +	if (m->length > 60) {
   6.250 +		warnx("truncating message from domain %d (was length %d)",
   6.251 +		      d->domid, m->length);
   6.252 +		m->length = 60;
   6.253 +	}
   6.254 +	PRINTF(1, "DOM%d: %.*s\n", d->domid, m->length, m->msg);
   6.255 +	send_trivial_control_reply(m, d);
   6.256 +
   6.257 +	if (d->cc) {
   6.258 +		PRINTF(5, "Have a console connection.\n");
   6.259 +		if (d->cc->state == CC_STATE_CONNECTED) {
   6.260 +			PRINTF(5, "Console is connected, sending directly.\n");
   6.261 +			for (off = 0; off < m->length; off += r) {
   6.262 +				r = write(d->cc->fd, m->msg + off,
   6.263 +					  m->length - off);
   6.264 +				if (r <= 0) {
   6.265 +					d->cc->state = CC_STATE_ERROR;
   6.266 +					break;
   6.267 +				}
   6.268 +			}
   6.269 +		} else {
   6.270 +			PRINTF(5, "Console not connected, buffering.\n");
   6.271 +			if (d->cc->buf_allocated == 0) {
   6.272 +				d->cc->buf_allocated = 60;
   6.273 +				d->cc->buf = xmalloc(d->cc->buf_allocated);
   6.274 +				d->cc->buf_used = 0;
   6.275 +			} else if (d->cc->buf_allocated <
   6.276 +				   d->cc->buf_used + m->length) {
   6.277 +				d->cc->buf_allocated += 60;
   6.278 +				d->cc->buf = xrealloc(d->cc->buf,
   6.279 +						      d->cc->buf_allocated);
   6.280 +			}
   6.281 +			assert(d->cc->buf_allocated >=
   6.282 +			       d->cc->buf_used + m->length);
   6.283 +			memcpy(d->cc->buf + d->cc->buf_used,
   6.284 +			       m->msg,
   6.285 +			       m->length);
   6.286 +			d->cc->buf_used += m->length;
   6.287 +		}
   6.288 +	}
   6.289 +}
   6.290 +
   6.291 +static void
   6.292 +process_blkif_fe_message(control_msg_t *m, struct domain *d)
   6.293 +{
   6.294 +	switch (m->subtype) {
   6.295 +	default:
   6.296 +		warnx("unknown blkif front end message subtype %d",
   6.297 +		      m->subtype);
   6.298 +	}
   6.299 +}
   6.300 +
   6.301 +static void
   6.302 +send_control_message(int type, int subtype, int id,
   6.303 +		     int size, void *payload, struct domain *target)
   6.304 +{
   6.305 +	control_msg_t msg;
   6.306 +	CONTROL_RING_IDX c;
   6.307 +
   6.308 +	msg.type = type;
   6.309 +	msg.subtype = subtype;
   6.310 +	msg.id = id;
   6.311 +	msg.length = size;
   6.312 +	memcpy(msg.msg, payload, size);
   6.313 +
   6.314 +	c = target->ctrl_if->rx_req_prod % CONTROL_RING_SIZE;
   6.315 +	memcpy(&target->ctrl_if->rx_ring[c], &msg, sizeof(msg));
   6.316 +	report_work(&target->ctrl_if->rx_req_prod,
   6.317 +		    target->ctrl_if->rx_req_prod + 1,
   6.318 +		    target->domid,
   6.319 +		    0);
   6.320 +	assert(!target->plugged);
   6.321 +}
   6.322 +
   6.323 +/* Procedure for bringing a new netif front end up:
   6.324 +
   6.325 +   -- Front end sends us NETIF_FE_DRIVER_STATUS_CHANGED
   6.326 +   -- We send back end NETIF_BE_CREATE, wait for a reply
   6.327 +   -- Back end creates a new netif for us, replies
   6.328 +   -- We send front end a NETIF_FE_DRIVER_STATUS_CHANGED message saying
   6.329 +      how many interfaces we've created for it
   6.330 +   -- We send front end a NETIF_FE_INTERFACE_STATUS_CHANGED for each
   6.331 +      netif created
   6.332 +   -- Front end sends us a NETIF_FE_INTERFACE_CONNECT for each netif
   6.333 +*/
   6.334 +static void
   6.335 +handle_netif_fe_driver_status_changed(control_msg_t *m,
   6.336 +				      netif_fe_driver_status_changed_t *sh,
   6.337 +				      struct domain *d)
   6.338 +{
   6.339 +	netif_fe_interface_status_changed_t if_s;
   6.340 +	control_msg_t be_msg;
   6.341 +	netif_be_create_t *be = (void *)be_msg.msg;
   6.342 +	int r;
   6.343 +
   6.344 +	switch (sh->status) {
   6.345 +	case NETIF_DRIVER_STATUS_UP:
   6.346 +		/* Tell the back end about the new interface coming
   6.347 +		 * up. */
   6.348 +		if (d->created_netif_backend) {
   6.349 +			PRINTF(10, "Front end came up twice in dom %d -> reporting no interfaces this time around.\n", d->domid);
   6.350 +			sh->nr_interfaces = 0;
   6.351 +			send_control_reply(m, d);
   6.352 +			send_control_message(CMSG_NETIF_FE,
   6.353 +					     CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
   6.354 +					     1,
   6.355 +					     sizeof(*sh),
   6.356 +					     sh,
   6.357 +					     d);
   6.358 +			return;
   6.359 +		}
   6.360 +		be_msg.type = CMSG_NETIF_BE;
   6.361 +		be_msg.subtype = CMSG_NETIF_BE_CREATE;
   6.362 +		be_msg.id = d->domid;
   6.363 +		be_msg.length = sizeof(*be);
   6.364 +		be->domid = d->domid;
   6.365 +		be->netif_handle = 0;
   6.366 +		memcpy(be->mac, d->netif_mac, 6);
   6.367 +
   6.368 +		PRINTF(2,"Telling back end about new front end.\n");
   6.369 +		pthread_mutex_unlock(&d->mux);
   6.370 +		send_dom0_message_block(&be_msg);
   6.371 +		pthread_mutex_lock(&d->mux);
   6.372 +		PRINTF(3,"Done.\n");
   6.373 +
   6.374 +		if (be->status != NETIF_BE_STATUS_OKAY) {
   6.375 +			/* Uh oh... can't bring back end
   6.376 +			 * up. */
   6.377 +			sh->nr_interfaces = 0;
   6.378 +			send_control_reply(m, d);
   6.379 +			send_control_message(CMSG_NETIF_FE,
   6.380 +					     CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
   6.381 +					     1,
   6.382 +					     sizeof(*sh),
   6.383 +					     sh,
   6.384 +					     d);
   6.385 +			return;
   6.386 +		}
   6.387 +		d->created_netif_backend = 1;
   6.388 +
   6.389 +		r = our_system("/etc/xen/vif-bridge up domain=%s mac=%.02x:%.02x:%.02x:%.02x:%.02x:%.02x vif=vif%d.0 bridge=xen-br0",
   6.390 +			       d->name,
   6.391 +			       d->netif_mac[0],
   6.392 +			       d->netif_mac[1],
   6.393 +			       d->netif_mac[2],
   6.394 +			       d->netif_mac[3],
   6.395 +			       d->netif_mac[4],
   6.396 +			       d->netif_mac[5],
   6.397 +			       d->domid);
   6.398 +		if (r != 0)
   6.399 +			warn("error %d running vif-bridge script", r);
   6.400 +
   6.401 +		/* Tell domain how many interfaces it has to deal
   6.402 +		 * with. */
   6.403 +		sh->nr_interfaces = 1;
   6.404 +		send_control_reply(m, d);
   6.405 +		send_control_message(CMSG_NETIF_FE,
   6.406 +				     CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
   6.407 +				     1,
   6.408 +				     sizeof(*sh),
   6.409 +				     sh,
   6.410 +				     d);
   6.411 +
   6.412 +		PRINTF(2,"Telling front end about its interfaces.\n");
   6.413 +		if_s.handle = 0;
   6.414 +		if_s.status = NETIF_INTERFACE_STATUS_DISCONNECTED;
   6.415 +		send_control_message(CMSG_NETIF_FE,
   6.416 +				     CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED,
   6.417 +				     1,
   6.418 +				     sizeof(if_s),
   6.419 +				     &if_s,
   6.420 +				     d);
   6.421 +		PRINTF(3,"Done.\n");
   6.422 +
   6.423 +		break;
   6.424 +	default:
   6.425 +		warnx("unknown netif status %ld", sh->status);
   6.426 +		break;
   6.427 +	}
   6.428 +}
   6.429 +
   6.430 +static void
   6.431 +handle_netif_fe_interface_connect(control_msg_t *m,
   6.432 +				  netif_fe_interface_connect_t *ic,
   6.433 +				  struct domain *d)
   6.434 +{
   6.435 +	control_msg_t be_msg;
   6.436 +	netif_be_connect_t *bmsg = (void *)be_msg.msg;
   6.437 +	netif_fe_interface_status_changed_t fmsg = {0};
   6.438 +	int evtchn_ports[2];
   6.439 +	int r;
   6.440 +
   6.441 +	PRINTF(4, "front end sent us an interface connect message.\n");
   6.442 +	send_trivial_control_reply(m, d);
   6.443 +
   6.444 +	r = xc_evtchn_bind_interdomain(xc_handle,
   6.445 +				       dom0->domid,
   6.446 +				       d->domid,
   6.447 +				       &evtchn_ports[0],
   6.448 +				       &evtchn_ports[1]);
   6.449 +	if (r < 0)
   6.450 +		err(1, "allocating network event channel");
   6.451 +
   6.452 +	be_msg.type = CMSG_NETIF_BE;
   6.453 +	be_msg.subtype = CMSG_NETIF_BE_CONNECT;
   6.454 +	be_msg.id = 0;
   6.455 +	be_msg.length = sizeof(*bmsg);
   6.456 +	bmsg->domid = d->domid;
   6.457 +	bmsg->netif_handle = ic->handle;
   6.458 +	bmsg->tx_shmem_frame = ic->tx_shmem_frame;
   6.459 +	bmsg->rx_shmem_frame = ic->rx_shmem_frame;
   6.460 +	bmsg->evtchn = evtchn_ports[0];
   6.461 +
   6.462 +	pthread_mutex_unlock(&d->mux);
   6.463 +	send_dom0_message_block(&be_msg);
   6.464 +	pthread_mutex_lock(&d->mux);
   6.465 +
   6.466 +	if (bmsg->status != NETIF_BE_STATUS_OKAY) {
   6.467 +		PRINTF(2, "error connected backend netif: %ld\n",
   6.468 +		       bmsg->status);
   6.469 +		abort(); /* Need to handle this */
   6.470 +	} else {
   6.471 +		PRINTF(3, "connect backend netif\n");
   6.472 +
   6.473 +		/* Tell the domain that we've connected it up. */
   6.474 +		fmsg.handle = ic->handle;
   6.475 +		fmsg.status = NETIF_INTERFACE_STATUS_CONNECTED;
   6.476 +		fmsg.evtchn = evtchn_ports[1];
   6.477 +		memcpy(fmsg.mac, d->netif_mac, 6);
   6.478 +
   6.479 +		send_control_message(CMSG_NETIF_FE,
   6.480 +				     CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED,
   6.481 +				     0,
   6.482 +				     sizeof(fmsg),
   6.483 +				     &fmsg,
   6.484 +				     d);
   6.485 +	}
   6.486 +}
   6.487 +
   6.488 +static void
   6.489 +process_netif_fe_message(control_msg_t *m, struct domain *d)
   6.490 +{
   6.491 +	switch (m->subtype) {
   6.492 +	case CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
   6.493 +	{
   6.494 +		netif_fe_driver_status_changed_t *sh =
   6.495 +			(netif_fe_driver_status_changed_t *)m->msg;
   6.496 +		handle_netif_fe_driver_status_changed(m, sh, d);
   6.497 +		break;
   6.498 +	}
   6.499 +	case CMSG_NETIF_FE_INTERFACE_CONNECT:
   6.500 +	{
   6.501 +		netif_fe_interface_connect_t *ic =
   6.502 +			(netif_fe_interface_connect_t *)m->msg;
   6.503 +		handle_netif_fe_interface_connect(m, ic, d);
   6.504 +		break;
   6.505 +	}
   6.506 +	default:
   6.507 +		warnx("unknown netif front end message subtype %d",
   6.508 +		      m->subtype);
   6.509 +	}
   6.510 +}
   6.511 +
   6.512 +static void
   6.513 +process_pdb_be_driver_status_changed_message(control_msg_t *msg,
   6.514 +					     pdb_be_driver_status_changed_t*pe,
   6.515 +					     struct domain *d)
   6.516 +{
   6.517 +	pdb_be_connected_t conn;
   6.518 +	pdb_fe_new_be_t new_be;
   6.519 +	int assist_channel[2];
   6.520 +	int event_channel[2];
   6.521 +	int r;
   6.522 +
   6.523 +	switch (pe->status) {
   6.524 +	case PDB_DRIVER_STATUS_UP:
   6.525 +		PRINTF(4, "creating event channel for PDB device\n");
   6.526 +		r = allocate_event_channel(d, assist_channel);
   6.527 +		r |= allocate_event_channel(d, event_channel);
   6.528 +		if (r < 0)
   6.529 +			abort(); /* XXX need to handle this */
   6.530 +
   6.531 +		send_trivial_control_reply(msg, d);
   6.532 +
   6.533 +		PRINTF(4, "informing front end of event channel\n");
   6.534 +		conn.assist_port = assist_channel[1];
   6.535 +		conn.event_port = event_channel[1];
   6.536 +		send_control_message(CMSG_PDB_BE,
   6.537 +				     CMSG_PDB_BE_INTERFACE_CONNECTED,
   6.538 +				     0,
   6.539 +				     sizeof(conn),
   6.540 +				     &conn,
   6.541 +				     d);
   6.542 +
   6.543 +		PRINTF(4, "informing back end of front end\n");
   6.544 +		new_be.domain = d->domid;
   6.545 +		new_be.assist_evtchn = assist_channel[0];
   6.546 +		new_be.event_evtchn = event_channel[0];
   6.547 +		new_be.assist_frame = pe->assist_page;
   6.548 +		new_be.event_frame = pe->event_page;
   6.549 +		send_control_message(CMSG_PDB_FE,
   6.550 +				     CMSG_PDB_FE_NEW_BE,
   6.551 +				     0,
   6.552 +				     sizeof(new_be),
   6.553 +				     &new_be,
   6.554 +				     dom0);
   6.555 +		break;
   6.556 +	default:
   6.557 +		warnx("unknown pdb status %d", pe->status);
   6.558 +	}
   6.559 +}
   6.560 +
   6.561 +static void
   6.562 +process_pdb_be_message(control_msg_t *msg, struct domain *d)
   6.563 +{
   6.564 +	switch (msg->subtype) {
   6.565 +	case CMSG_PDB_BE_DRIVER_STATUS_CHANGED:
   6.566 +	{
   6.567 +		pdb_be_driver_status_changed_t *pe =
   6.568 +			(pdb_be_driver_status_changed_t *)msg->msg;
   6.569 +		process_pdb_be_driver_status_changed_message(msg, pe, d);
   6.570 +		break;
   6.571 +	}
   6.572 +	default:
   6.573 +		warnx("unknown pdb back end message subtype %d",
   6.574 +		      msg->subtype);
   6.575 +	}
   6.576 +}
   6.577 +
   6.578 +static void
   6.579 +process_control_message(control_msg_t *msg, struct domain *d)
   6.580 +{
   6.581 +	control_msg_t m;
   6.582 +
   6.583 +	/* Don't want a malicous domain messing us about, so copy the
   6.584 +	   control mesasge into a local buffer. */
   6.585 +	memcpy(&m, msg, sizeof(m));
   6.586 +	switch (m.type) {
   6.587 +	case CMSG_CONSOLE:
   6.588 +		process_console_control_message(&m, d);
   6.589 +		break;
   6.590 +	case CMSG_BLKIF_FE:
   6.591 +		process_blkif_fe_message(&m, d);
   6.592 +		break;
   6.593 +	case CMSG_NETIF_FE:
   6.594 +		process_netif_fe_message(&m, d);
   6.595 +		break;
   6.596 +	case CMSG_PDB_BE:
   6.597 +		process_pdb_be_message(&m, d);
   6.598 +		break;
   6.599 +	default:
   6.600 +		warnx("unknown control message type %d", m.type);
   6.601 +	}
   6.602 +}
   6.603 +
   6.604 +static void
   6.605 +domain_did_control_event(struct domain *d)
   6.606 +{
   6.607 +	CONTROL_RING_IDX c;
   6.608 +
   6.609 +	/* Pick up and process control ring messages. */
   6.610 +	while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
   6.611 +		c = d->tx_req_cons % CONTROL_RING_SIZE;
   6.612 +		process_control_message(&d->ctrl_if->tx_ring[c], d);
   6.613 +		d->tx_req_cons++;
   6.614 +		assert(d->tx_req_cons <= d->ctrl_if->tx_req_prod);
   6.615 +		PRINTF(5, "req_cons %ld, req_prod %ld.\n",
   6.616 +		       d->tx_req_cons, d->ctrl_if->tx_req_prod);
   6.617 +	}
   6.618 +
   6.619 +	/* Take any replies off, and discard them. */
   6.620 +	if (d->rx_resp_cons != d->ctrl_if->rx_resp_prod)
   6.621 +		PRINTF(1, "discard %ld events\n",
   6.622 +		       d->ctrl_if->rx_resp_prod -
   6.623 +		       d->rx_resp_cons);
   6.624 +	d->rx_resp_cons = d->ctrl_if->rx_resp_prod;
   6.625 +}
   6.626 +
   6.627 +/* This is the main function for domain control threads */
   6.628 +void *
   6.629 +domain_thread_func(void *D)
   6.630 +{
   6.631 +	struct domain *d = D;
   6.632 +	int r;
   6.633 +	CONTROL_RING_IDX old_resp_prod, old_req_prod;
   6.634 +
   6.635 +	pthread_mutex_lock(&d->mux);
   6.636 +	for (;;) {
   6.637 +		pthread_cond_wait(&d->cond, &d->mux);
   6.638 +
   6.639 +		old_resp_prod = d->ctrl_if->tx_resp_prod;
   6.640 +		old_req_prod = d->ctrl_if->rx_req_prod;
   6.641 +
   6.642 +		domain_did_control_event(d);
   6.643 +		if (d->cc && d->cc->in_buf_used != 0 && d->plugged == 0) {
   6.644 +			r = d->cc->in_buf_used;
   6.645 +			if (r > 60)
   6.646 +				r = 60;
   6.647 +			PRINTF(1, "Sending to domain: %.*s\n",
   6.648 +			       r, d->cc->in_buf);
   6.649 +			send_control_message(CMSG_CONSOLE,
   6.650 +					     CMSG_CONSOLE_DATA,
   6.651 +					     0,
   6.652 +					     r,
   6.653 +					     d->cc->in_buf,
   6.654 +					     d);
   6.655 +			memmove(d->cc->in_buf, d->cc->in_buf + r,
   6.656 +				d->cc->in_buf_used - r);
   6.657 +			d->cc->in_buf_used -= r;
   6.658 +		}
   6.659 +
   6.660 +		if (d->ctrl_if->tx_resp_prod != old_resp_prod ||
   6.661 +		    d->ctrl_if->rx_req_prod != old_req_prod)
   6.662 +			xc_evtchn_send(xc_handle, d->control_evtchn);
   6.663 +	}
   6.664 +}
   6.665 +
   6.666 +/* This is the only thing you can do with a domain structure if you're
   6.667 +   not in the thread which controls that domain.  Domain 0 is
   6.668 +   special. */
   6.669 +void
   6.670 +signal_domain(struct domain *d)
   6.671 +{
   6.672 +	CONTROL_RING_IDX c;
   6.673 +	int id;
   6.674 +	struct event_receiver *evt;
   6.675 +
   6.676 +	pthread_mutex_lock(&d->mux);
   6.677 +	if (d == dom0) {
   6.678 +		/* Take events off of dom0's control ring, and send
   6.679 +		   them to the event receivers. */
   6.680 +		while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
   6.681 +			c = d->tx_req_cons % CONTROL_RING_SIZE;
   6.682 +			id = d->ctrl_if->tx_ring[c].id;
   6.683 +			evt = find_event_receiver(id);
   6.684 +			if (evt != NULL) {
   6.685 +				PRINTF(1, "delivering event id %d\n", evt->id);
   6.686 +				pthread_cond_broadcast(&evt->cond);
   6.687 +				pthread_mutex_unlock(&d->mux);
   6.688 +				pthread_yield();
   6.689 +				pthread_mutex_lock(&d->mux);
   6.690 +			} else {
   6.691 +				warnx("unexpected message id %d discarded",
   6.692 +				      id);
   6.693 +				d->tx_req_cons++;
   6.694 +			}
   6.695 +		}
   6.696 +		while (d->rx_resp_cons != d->ctrl_if->rx_resp_prod) {
   6.697 +			c = d->rx_resp_cons % CONTROL_RING_SIZE;
   6.698 +			id = d->ctrl_if->rx_ring[c].id;
   6.699 +			evt = find_event_receiver(id);
   6.700 +			if (evt != NULL) {
   6.701 +				PRINTF(1, "delivering event rep id %d\n", evt->id);
   6.702 +				pthread_cond_broadcast(&evt->cond);
   6.703 +				pthread_mutex_unlock(&d->mux);
   6.704 +				pthread_yield();
   6.705 +				pthread_mutex_lock(&d->mux);
   6.706 +			} else {
   6.707 +				warnx("unexpected message reply id %d discarded",
   6.708 +				      id);
   6.709 +				d->rx_resp_cons++;
   6.710 +			}
   6.711 +		}
   6.712 +	} else {
   6.713 +		if (d->plugged) {
   6.714 +			d->event_pending = 1;
   6.715 +		} else {
   6.716 +			pthread_cond_broadcast(&d->cond);
   6.717 +		}
   6.718 +	}
   6.719 +	pthread_mutex_unlock(&d->mux);
   6.720 +}
   6.721 +
   6.722 +static void
   6.723 +handle_evtchn_event(void)
   6.724 +{
   6.725 +	short port;
   6.726 +	struct domain *d;
   6.727 +
   6.728 +	read(evtchn_fd, &port, sizeof(short));
   6.729 +	write(evtchn_fd, &port, sizeof(short));
   6.730 +	foreach_domain (d) {
   6.731 +		if (d->control_evtchn == port) {
   6.732 +			signal_domain(d);
   6.733 +			return;
   6.734 +		}
   6.735 +	}
   6.736 +	warnx("got an event on an unknown port %d", port);
   6.737 +}
   6.738 +
   6.739 +void *
   6.740 +map_domain_mem(struct domain *d, unsigned long mfn)
   6.741 +{
   6.742 +	return xc_map_foreign_range(xc_handle, d->domid,
   6.743 +				    PAGE_SIZE, PROT_READ | PROT_WRITE,
   6.744 +				    mfn);
   6.745 +}
   6.746 +
   6.747 +static void
   6.748 +handle_console_event(struct console_connection *cc)
   6.749 +{
   6.750 +	int r;
   6.751 +	int fd;
   6.752 +
   6.753 +	switch (cc->state) {
   6.754 +	case CC_STATE_ERROR:
   6.755 +		/* Errors shouldn't get here. */
   6.756 +		abort();
   6.757 +	case CC_STATE_PENDING:
   6.758 +		fd = accept(cc->fd, NULL, NULL);
   6.759 +		if (fd >= 0) {
   6.760 +			PRINTF(3, "Accepted console connection for domain %d",
   6.761 +			       cc->dom->domid);
   6.762 +			close(cc->fd);
   6.763 +			cc->fd = fd;
   6.764 +			cc->state = CC_STATE_CONNECTED;
   6.765 +			while (cc->buf_used != 0) {
   6.766 +				r = write(cc->fd,
   6.767 +					  cc->buf,
   6.768 +					  cc->buf_used);
   6.769 +				if (r <= 0) {
   6.770 +					cc->state = CC_STATE_ERROR;
   6.771 +					break;
   6.772 +				}
   6.773 +				memmove(cc->buf,
   6.774 +					cc->buf + r,
   6.775 +					cc->buf_used - r);
   6.776 +				cc->buf_used -= r;
   6.777 +			}
   6.778 +			free(cc->buf);
   6.779 +			cc->buf = NULL;
   6.780 +			cc->buf_allocated = 0;
   6.781 +		} else {
   6.782 +			PRINTF(1, "error %s accepting console", strerror(errno));
   6.783 +		}
   6.784 +		pthread_mutex_unlock(&cc->dom->mux);
   6.785 +		break;
   6.786 +	case CC_STATE_CONNECTED:
   6.787 +		if (cc->in_buf_allocated == 0) {
   6.788 +			assert(cc->in_buf_used == 0);
   6.789 +			cc->in_buf_allocated = 128;
   6.790 +			cc->in_buf = xmalloc(cc->in_buf_allocated);
   6.791 +		}
   6.792 +		if (cc->in_buf_used == cc->in_buf_allocated) {
   6.793 +			cc->in_buf_allocated *= 2;
   6.794 +			cc->in_buf = xrealloc(cc->in_buf, cc->in_buf_allocated);
   6.795 +		}
   6.796 +		r = read(cc->fd, cc->in_buf + cc->in_buf_used,
   6.797 +			 cc->in_buf_allocated - cc->in_buf_used);
   6.798 +		if (r <= 0) {
   6.799 +			cc->state = CC_STATE_ERROR;
   6.800 +		} else {
   6.801 +			cc->in_buf_used += r;
   6.802 +		}
   6.803 +		pthread_mutex_unlock(&cc->dom->mux);
   6.804 +		signal_domain(cc->dom);
   6.805 +		break;
   6.806 +	}
   6.807 +}
   6.808 +
   6.809 +static void
   6.810 +handle_connection_event(struct open_connection *oc)
   6.811 +{
   6.812 +	int r;
   6.813 +
   6.814 +	/* We know that some amount of data is ready and waiting for
   6.815 +	   us.  Slurp it in. */
   6.816 +	if (oc->buf_used == oc->buf_allocated) {
   6.817 +		oc->buf_allocated *= 2;
   6.818 +		oc->buf = xrealloc(oc->buf, oc->buf_allocated);
   6.819 +	}
   6.820 +	r = read(oc->fd, oc->buf + oc->buf_used,
   6.821 +		 oc->buf_allocated - oc->buf_used);
   6.822 +	if (r < 0) {
   6.823 +		warn("reading command from remote");
   6.824 +		oc->state = OC_STATE_ERROR;
   6.825 +	} else if (r == 0) {
   6.826 +		warnx("reading command from remote");
   6.827 +		oc->state = OC_STATE_ERROR;
   6.828 +	} else {
   6.829 +		oc->buf_used += r;
   6.830 +		if (strchr(oc->buf, '\n'))
   6.831 +			oc->state = OC_STATE_COMMAND_PENDING;
   6.832 +	}
   6.833 +}
   6.834 +
   6.835 +static void
   6.836 +get_and_process_event(void)
   6.837 +{
   6.838 +	fd_set read_fds, except_fds;
   6.839 +	struct open_connection *oc;
   6.840 +	struct console_connection *cc;
   6.841 +	int max_fd = listen_fd;
   6.842 +	int r;
   6.843 +	struct list_head *li, *temp_li;
   6.844 +
   6.845 +	FD_ZERO(&read_fds);
   6.846 +	FD_ZERO(&except_fds);
   6.847 +	FD_SET(listen_fd, &read_fds);
   6.848 +	FD_SET(evtchn_fd, &read_fds);
   6.849 +	if (evtchn_fd > max_fd)
   6.850 +		max_fd = evtchn_fd;
   6.851 +	foreach_open_connection(oc) {
   6.852 +		FD_SET(oc->fd, &read_fds);
   6.853 +		FD_SET(oc->fd, &except_fds);
   6.854 +		if (oc->fd > max_fd)
   6.855 +			max_fd = oc->fd;
   6.856 +	}
   6.857 +	foreach_console_connection(cc) {
   6.858 +		FD_SET(cc->fd, &read_fds);
   6.859 +		FD_SET(cc->fd, &except_fds);
   6.860 +		if (cc->fd > max_fd)
   6.861 +			max_fd = cc->fd;
   6.862 +	}
   6.863 +
   6.864 +	r = select(max_fd + 1, &read_fds, NULL, &except_fds, NULL);
   6.865 +	if (r < 0)
   6.866 +		err(1, "select");
   6.867 +	if (FD_ISSET(listen_fd, &read_fds)) {
   6.868 +		accept_new_connection();
   6.869 +	} else if (FD_ISSET(evtchn_fd, &read_fds))
   6.870 +		handle_evtchn_event();
   6.871 +
   6.872 +
   6.873 +	foreach_open_connection(oc) {
   6.874 +		if (FD_ISSET(oc->fd, &read_fds))
   6.875 +			handle_connection_event(oc);
   6.876 +		if (FD_ISSET(oc->fd, &except_fds))
   6.877 +			oc->state = OC_STATE_ERROR;
   6.878 +	}
   6.879 +	list_foreach_safe(&head_console, li, temp_li) {
   6.880 +		cc = list_item(li, struct console_connection, list);
   6.881 +		if (FD_ISSET(cc->fd, &read_fds))
   6.882 +			handle_console_event(cc);
   6.883 +		if (FD_ISSET(cc->fd, &except_fds) ||
   6.884 +		    cc->state == CC_STATE_ERROR) {
   6.885 +			PRINTF(1, "Cleaning up console connection");
   6.886 +			cc->dom->cc = NULL;
   6.887 +			list_remove(&cc->list);
   6.888 +			close(cc->fd);
   6.889 +			if (cc->buf_allocated != 0)
   6.890 +				free(cc->buf);
   6.891 +			if (cc->in_buf_allocated != 0)
   6.892 +				free(cc->in_buf);
   6.893 +			free(cc);
   6.894 +		}
   6.895 +	}
   6.896 +
   6.897 +	/* Run pending stuff on the open connections. */
   6.898 +	list_foreach_safe(&head_connection, li, temp_li) {
   6.899 +		oc = list_item(li, struct open_connection, connection_list);
   6.900 +		switch (oc->state) {
   6.901 +		case OC_STATE_ERROR:
   6.902 +			list_remove(&oc->connection_list);
   6.903 +			closedown_connection(oc);
   6.904 +			break;
   6.905 +		case OC_STATE_COMMAND_PENDING:
   6.906 +			process_command(oc);
   6.907 +			break;
   6.908 +		case OC_STATE_CONNECTED:
   6.909 +			/* Don't need to do anything */
   6.910 +			break;
   6.911 +		}
   6.912 +	}
   6.913 +}
   6.914 +
   6.915 +static int
   6.916 +start_listening(void)
   6.917 +{
   6.918 +	int sock;
   6.919 +	struct sockaddr_in inaddr;
   6.920 +
   6.921 +	sock = socket(PF_INET, SOCK_STREAM, 0);
   6.922 +	if (sock < 0)
   6.923 +		err(1, "creating socket");
   6.924 +	memset(&inaddr, 0, sizeof(inaddr));
   6.925 +	inaddr.sin_family = AF_INET;
   6.926 +	inaddr.sin_port = htons(MINIXEND_PORT);
   6.927 +
   6.928 +	if (bind(sock, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
   6.929 +		err(1, "binding to port %d", MINIXEND_PORT);
   6.930 +	if (listen(sock, 5) < 0)
   6.931 +		err(1, "listening for connections");
   6.932 +
   6.933 +	return sock;
   6.934 +}
   6.935 +
   6.936 +static struct domain *
   6.937 +find_dom0(void)
   6.938 +{
   6.939 +	int r;
   6.940 +	xc_dominfo_t info;
   6.941 +	struct domain *work;
   6.942 +
   6.943 +	r = xc_domain_getinfo(xc_handle, 0, 1, &info);
   6.944 +	if (r < 0)
   6.945 +		err(1, "getting domain 0 information");
   6.946 +	work = xmalloc(sizeof(*work));
   6.947 +	work->control_evtchn = 2;
   6.948 +	if (ioctl(evtchn_fd, EVTCHN_BIND, 2) < 0)
   6.949 +		err(1, "binding to domain 0 control event channel");
   6.950 +
   6.951 +	work->domid = 0;
   6.952 +	work->name = xstrdup("dom0");
   6.953 +	work->mem_kb = info.max_memkb;
   6.954 +	work->state = DOM_STATE_RUNNING;
   6.955 +	work->shared_info_mfn = info.shared_info_frame;
   6.956 +
   6.957 +	work->shared_info = map_domain_mem(work, info.shared_info_frame);
   6.958 +	work->ctrl_if = (control_if_t *)((unsigned)work->shared_info + 2048);
   6.959 +	work->tx_req_cons = work->ctrl_if->tx_req_prod;
   6.960 +	work->rx_resp_cons = work->ctrl_if->rx_resp_prod;
   6.961 +
   6.962 +	pthread_mutex_init(&work->mux, NULL);
   6.963 +	pthread_cond_init(&work->cond, NULL);
   6.964 +
   6.965 +	list_insert_after(&work->domain_list, &head_domain);
   6.966 +
   6.967 +	return work;
   6.968 +}
   6.969 +
   6.970 +int
   6.971 +main(int argc, char *argv[])
   6.972 +{
   6.973 +	int r;
   6.974 +
   6.975 +	r = our_system("/etc/xen/network start antispoof=no");
   6.976 +	if (r < 0)
   6.977 +		err(1, "running /etc/xen/network");
   6.978 +	if (!WIFEXITED(r)) {
   6.979 +		if (WIFSIGNALED(r)) {
   6.980 +			errx(1, "/etc/xen/network killed by signal %d",
   6.981 +			     WTERMSIG(r));
   6.982 +		}
   6.983 +		errx(1, "/etc/xen/network terminated abnormally");
   6.984 +	}
   6.985 +	if (WEXITSTATUS(r) != 0)
   6.986 +		errx(1, "/etc/xen/network returned error status %d",
   6.987 +		     WEXITSTATUS(r));
   6.988 +
   6.989 +	xc_handle = xc_interface_open();
   6.990 +
   6.991 +	listen_fd = start_listening();
   6.992 +
   6.993 +	evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
   6.994 +	if (evtchn_fd < 0)
   6.995 +		err(1, "openning /dev/xen/evtchn");
   6.996 +
   6.997 +	dom0 = find_dom0();
   6.998 +
   6.999 +	while (1) {
  6.1000 +		get_and_process_event();
  6.1001 +
  6.1002 +		PRINTF(5, "Dom0 ring state:\n");
  6.1003 +		PRINTF(5, "RX: req_prod %ld, resp_prod %ld, resp_cons %ld\n",
  6.1004 +		       dom0->ctrl_if->rx_req_prod,
  6.1005 +		       dom0->ctrl_if->rx_resp_prod,
  6.1006 +		       dom0->rx_resp_cons);
  6.1007 +		PRINTF(5, "TX: req_prod %ld, resp_prod %ld, req_cons %ld\n",
  6.1008 +		       dom0->ctrl_if->tx_req_prod,
  6.1009 +		       dom0->ctrl_if->tx_resp_prod,
  6.1010 +		       dom0->tx_req_cons);
  6.1011 +	}
  6.1012 +
  6.1013 +	return 0;
  6.1014 +}
  6.1015 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/x2d2/minixend.h	Fri Nov 12 16:44:19 2004 +0000
     7.3 @@ -0,0 +1,218 @@
     7.4 +#ifndef MINIXEND_H__
     7.5 +#define MINIXEND_H__
     7.6 +
     7.7 +#include <sys/types.h>
     7.8 +#include <xc.h>
     7.9 +#include "domain_controller.h"
    7.10 +
    7.11 +/* Yet again, persuading Xen headers to include successfully in a
    7.12 +   userspace process proves to be beyond me.  Sigh. */
    7.13 +#define MAX_VIRT_CPUS 1
    7.14 +
    7.15 +typedef struct {
    7.16 +    u32  tsc_bits;      /* 0: 32 bits read from the CPU's TSC. */
    7.17 +    u32  tsc_bitshift;  /* 4: 'tsc_bits' uses N:N+31 of TSC.   */
    7.18 +} PACKED tsc_timestamp_t; /* 8 bytes */
    7.19 +
    7.20 +typedef struct {
    7.21 +    u64 mfn_to_pfn_start;      /* MFN of start of m2p table */
    7.22 +    u64 pfn_to_mfn_frame_list; /* MFN of a table of MFNs that 
    7.23 +				  make up p2m table */
    7.24 +} PACKED arch_shared_info_t;
    7.25 +
    7.26 +typedef struct
    7.27 +{
    7.28 +    unsigned long ebx;
    7.29 +    unsigned long ecx;
    7.30 +    unsigned long edx;
    7.31 +    unsigned long esi;
    7.32 +    unsigned long edi;
    7.33 +    unsigned long ebp;
    7.34 +    unsigned long eax;
    7.35 +    unsigned long ds;
    7.36 +    unsigned long es;
    7.37 +    unsigned long fs;
    7.38 +    unsigned long gs;
    7.39 +    unsigned long _unused;
    7.40 +    unsigned long eip;
    7.41 +    unsigned long cs;
    7.42 +    unsigned long eflags;
    7.43 +    unsigned long esp;
    7.44 +    unsigned long ss;
    7.45 +} PACKED execution_context_t;
    7.46 +
    7.47 +typedef struct shared_info_st
    7.48 +{
    7.49 +    struct {
    7.50 +        u8 evtchn_upcall_pending;
    7.51 +        u8 evtchn_upcall_mask;
    7.52 +        u8 pad0, pad1;
    7.53 +    } PACKED vcpu_data[MAX_VIRT_CPUS];  /*   0 */
    7.54 +    u32 evtchn_pending[32];             /*   4 */
    7.55 +    u32 evtchn_pending_sel;             /* 132 */
    7.56 +    u32 evtchn_mask[32];                /* 136 */
    7.57 +    u64                cpu_freq;        /* 264: CPU frequency (Hz).          */
    7.58 +    u32                time_version1;   /* 272 */
    7.59 +    u32                time_version2;   /* 276 */
    7.60 +    tsc_timestamp_t    tsc_timestamp;   /* TSC at last update of time vals.  */
    7.61 +    u64                system_time;     /* Time, in nanosecs, since boot.    */
    7.62 +    u32                wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
    7.63 +    u32                wc_usec;         /* Usecs 00:00:00 UTC, Jan 1, 1970.  */
    7.64 +    u64                domain_time;     /* Domain virtual time, in nanosecs. */
    7.65 +    u64                wall_timeout;    /* 312 */
    7.66 +    u64                domain_timeout;  /* 320 */
    7.67 +    execution_context_t execution_context; /* 328 */
    7.68 +    arch_shared_info_t arch;
    7.69 +} PACKED shared_info_t;
    7.70 +
    7.71 +/* End of stuff which belongs in a Xen header */
    7.72 +
    7.73 +
    7.74 +struct list_head {
    7.75 +	struct list_head *next, **pprev;
    7.76 +};
    7.77 +
    7.78 +struct open_connection {
    7.79 +	struct list_head connection_list;
    7.80 +	int fd;
    7.81 +	enum {
    7.82 +		OC_STATE_CONNECTED,
    7.83 +		OC_STATE_ERROR,
    7.84 +		OC_STATE_COMMAND_PENDING
    7.85 +	} state;
    7.86 +
    7.87 +	/* Buffer of stuff coming from the remote until we get a whole
    7.88 +	   command */
    7.89 +	int buf_used;
    7.90 +	int buf_allocated;
    7.91 +	char *buf;
    7.92 +};
    7.93 +
    7.94 +struct console_connection;
    7.95 +
    7.96 +/* Only ever accessed from the domain's controlling thread, unless
    7.97 +   it's dom0, in which case we perform a moderately complex dance to
    7.98 +   avoid needing any sort of locking at all. */
    7.99 +struct domain {
   7.100 +	struct list_head domain_list;
   7.101 +	int control_evtchn; /* the local port for the doain control
   7.102 +			       interface event channel. */
   7.103 +	int domid;
   7.104 +	char *name;
   7.105 +	int mem_kb;
   7.106 +	enum {
   7.107 +		DOM_STATE_CREATED, /* created but not built */
   7.108 +		DOM_STATE_PAUSED,  /* built but not started or paused */
   7.109 +		DOM_STATE_RUNNING, /* running normally */
   7.110 +		DOM_STATE_DEAD     /* dead; either destroyed, crashed,
   7.111 +				      or exitted. */
   7.112 +	} state;
   7.113 +
   7.114 +	unsigned long shared_info_mfn;
   7.115 +	shared_info_t *shared_info;
   7.116 +	control_if_t *ctrl_if;
   7.117 +	CONTROL_RING_IDX tx_req_cons;
   7.118 +	CONTROL_RING_IDX rx_resp_cons;
   7.119 +
   7.120 +	unsigned created_netif_backend:1;
   7.121 +	unsigned plugged:1;
   7.122 +	unsigned event_pending:1; /* True if an event arrived while
   7.123 +				     the domain was plugged. */
   7.124 +
   7.125 +	struct console_connection *cc;
   7.126 +
   7.127 +	char netif_mac[6];
   7.128 +
   7.129 +	/* Used for two purposes: waking up domain threads when
   7.130 +	   necessary, and synchronising access to dom0, which doesn't
   7.131 +	   have a domain thread. */
   7.132 +	pthread_mutex_t mux;
   7.133 +	pthread_cond_t cond;
   7.134 +
   7.135 +	pthread_t thread;
   7.136 +};
   7.137 +
   7.138 +struct console_connection {
   7.139 +	struct list_head list;
   7.140 +	int fd;
   7.141 +	struct domain *dom;
   7.142 +
   7.143 +	enum {
   7.144 +		CC_STATE_PENDING,
   7.145 +		CC_STATE_CONNECTED,
   7.146 +		CC_STATE_ERROR
   7.147 +	} state;
   7.148 +
   7.149 +	unsigned buf_allocated;
   7.150 +	unsigned buf_used;
   7.151 +	char *buf;
   7.152 +
   7.153 +	unsigned in_buf_allocated;
   7.154 +	unsigned in_buf_used;
   7.155 +	char *in_buf;
   7.156 +};
   7.157 +
   7.158 +
   7.159 +void *domain_thread_func(void *d);
   7.160 +void process_command(struct open_connection *oc);
   7.161 +
   7.162 +void *xmalloc(size_t s);
   7.163 +void *xrealloc(void *x, size_t s);
   7.164 +char *xstrdup(const char *s);
   7.165 +
   7.166 +int allocate_event_channel(struct domain *d, int event_ports[2]);
   7.167 +void *map_domain_mem(struct domain *d, unsigned long mfn);
   7.168 +void signal_domain(struct domain *d);
   7.169 +int our_system(const char *fmt, ...);
   7.170 +
   7.171 +extern unsigned xc_handle;
   7.172 +#define EVTCHN_BIND _IO('E', 2)
   7.173 +extern int evtchn_fd;
   7.174 +
   7.175 +#define list_item(head, type, field)                                        \
   7.176 +((type *)((unsigned)(head) - offsetof(type, field)))
   7.177 +
   7.178 +#define foreach_item(iter, head, type, field)                               \
   7.179 +for ((iter) = list_item((head)->next, type, field);                         \
   7.180 +     (iter) != list_item((head), type, field);                              \
   7.181 +     (iter) = list_item((iter)->field.next, type, field))
   7.182 +
   7.183 +#define list_insert_after(what, head)                                       \
   7.184 +do {                                                                        \
   7.185 +	(what)->next = (head)->next;                                        \
   7.186 +	(what)->pprev = &(head)->next;                                      \
   7.187 +	(head)->next->pprev = &(what)->next;                                \
   7.188 +	(head)->next = what;                                                \
   7.189 +} while (0)
   7.190 +
   7.191 +#define list_remove(head)                                                   \
   7.192 +(head)->next->pprev = (head)->pprev;                                        \
   7.193 +*(head)->pprev = (head)->next;
   7.194 +
   7.195 +#define list_foreach_safe(head, li, temp)                                   \
   7.196 +for ((li) = (head)->next, (temp) = (li)->next;                              \
   7.197 +     (li) != (head);                                                        \
   7.198 +     (li) = (temp), (temp) = (li)->next)
   7.199 +
   7.200 +#define LIST_HEAD(x) { (x), &(x)->next }
   7.201 +
   7.202 +
   7.203 +extern struct list_head head_domain;
   7.204 +extern struct list_head head_console;
   7.205 +
   7.206 +#define foreach_domain(d)                                                   \
   7.207 +foreach_item(d, &head_domain, struct domain, domain_list)
   7.208 +#define foreach_console_connection(cc)                                      \
   7.209 +foreach_item(cc, &head_console, struct console_connection, list)
   7.210 +
   7.211 +
   7.212 +#define CURRENT_LOG_LEVEL 0
   7.213 +
   7.214 +#define PRINTF(level, ...)                                         \
   7.215 +do {                                                               \
   7.216 +	if ((level) >= CURRENT_LOG_LEVEL)                          \
   7.217 +		printf(__VA_ARGS__);                               \
   7.218 +} while (0)
   7.219 +
   7.220 +
   7.221 +#endif /* MINIXEND_H__ */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/x2d2/util.c	Fri Nov 12 16:44:19 2004 +0000
     8.3 @@ -0,0 +1,132 @@
     8.4 +#define _GNU_SOURCE
     8.5 +
     8.6 +#include <sys/types.h>
     8.7 +#include <sys/wait.h>
     8.8 +#include <assert.h>
     8.9 +#include <err.h>
    8.10 +#include <errno.h>
    8.11 +#include <fcntl.h>
    8.12 +#include <stdarg.h>
    8.13 +#include <stdlib.h>
    8.14 +#include <stdio.h>
    8.15 +#include <string.h>
    8.16 +#include <unistd.h>
    8.17 +
    8.18 +void *
    8.19 +xmalloc(size_t s)
    8.20 +{
    8.21 +	void *x;
    8.22 +
    8.23 +	x = malloc(s);
    8.24 +	if (x == NULL)
    8.25 +		err(1, "allocating memory");
    8.26 +	memset(x, 0, s);
    8.27 +	return x;
    8.28 +}
    8.29 +
    8.30 +void *
    8.31 +xrealloc(void *x, size_t s)
    8.32 +{
    8.33 +	void *y;
    8.34 +	y = realloc(x, s);
    8.35 +	if (y == NULL)
    8.36 +		err(1, "allocating more memory");
    8.37 +	return y;
    8.38 +}
    8.39 +
    8.40 +char *
    8.41 +xstrdup(const char *s)
    8.42 +{
    8.43 +	char *x = strdup(s);
    8.44 +	if (x == NULL)
    8.45 +		err(1, "duplicating %s", s);
    8.46 +	return x;
    8.47 +}
    8.48 +
    8.49 +/* Slightly less stupid implementation of system().  We return
    8.50 +   negative iff there is an error executing the shell; otherwise, we
    8.51 +   return the wait status as reported by waitpid(). Also, we support
    8.52 +   printf-style escapes.  We don't handle setting the SIGCHLD handler
    8.53 +   to SIGIGN, though: in that case, we have a race. */
    8.54 +int
    8.55 +our_system(const char *fmt, ...)
    8.56 +{
    8.57 +	char *cmd = NULL;
    8.58 +	int r;
    8.59 +	va_list ap;
    8.60 +	pid_t child = -1;
    8.61 +	int pip[2] = {-1, -1};
    8.62 +	int e;
    8.63 +	fd_set fds;
    8.64 +	struct timeval to;
    8.65 +	int res;
    8.66 +	pid_t c;
    8.67 +	unsigned status;
    8.68 +
    8.69 +	va_start(ap, fmt);
    8.70 +	r = vasprintf(&cmd, fmt, ap);
    8.71 +	va_end(ap);
    8.72 +	if (r < 0)
    8.73 +		return r;
    8.74 +	r = pipe(pip);
    8.75 +	if (r < 0) {
    8.76 +		res = r;
    8.77 +		goto out;
    8.78 +	}
    8.79 +	child = fork();
    8.80 +	if (child < 0) {
    8.81 +		res = child;
    8.82 +		goto out;
    8.83 +	}
    8.84 +	if (child == 0) {
    8.85 +		close(pip[0]);
    8.86 +		fcntl(pip[1], F_SETFD, 1);
    8.87 +		r = execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
    8.88 +		/* Uh oh, exec failed */
    8.89 +		write(pip[1], &r, sizeof(r));
    8.90 +		_exit(1);
    8.91 +	}
    8.92 +
    8.93 +	close(pip[1]);
    8.94 +	pip[1] = -1;
    8.95 +
    8.96 +	c = waitpid(child, &status, 0);
    8.97 +	if (c < 0) {
    8.98 +		res = c;
    8.99 +		goto out;
   8.100 +	}
   8.101 +	assert(c == child);
   8.102 +	child = -1;
   8.103 +
   8.104 +	/* Check execl result */
   8.105 +	FD_ZERO(&fds);
   8.106 +	FD_SET(pip[0], &fds);
   8.107 +	memset(&to, 0, sizeof(to));
   8.108 +	r = select(pip[0]+1, &fds, NULL, NULL, &to);
   8.109 +	if (r == 0) {
   8.110 +		res = status;
   8.111 +	} else {
   8.112 +		assert(FD_ISSET(pip[0], &fds));
   8.113 +		r = read(pip[0], &res, sizeof(res));
   8.114 +		if (r != sizeof(res))
   8.115 +			res = status;
   8.116 +	}
   8.117 +	close(pip[0]);
   8.118 +	pip[0] = -1;
   8.119 +
   8.120 + out:
   8.121 +	e = errno;
   8.122 +	if (child >= 0) {
   8.123 +		/* Not obvious what the correct thing to do here is. */
   8.124 +		/* Don't want to kill the child; that will create a
   8.125 +		   zombie. */
   8.126 +//		kill(child, 9);
   8.127 +	}
   8.128 +	if (pip[0] >= 0)
   8.129 +		close(pip[0]);
   8.130 +	if (pip[1] >= 0)
   8.131 +		close(pip[1]);
   8.132 +	free(cmd);
   8.133 +	errno = e;
   8.134 +	return res;
   8.135 +}