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