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.
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 +}