debuggers.hg

view tools/libxl/libxl_dm.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents b59f04eb8978
children ccfa0527893e
line source
1 /*
2 * Copyright (C) 2010 Citrix Ltd.
3 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
4 * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
5 * Author Gianni Tedesco <gianni.tedesco@citrix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 only. with the special
10 * exception on linking described in file LICENSE.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 */
18 #include "libxl_osdeps.h"
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <signal.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include "libxl_utils.h"
27 #include "libxl_internal.h"
28 #include "libxl.h"
29 #include "flexarray.h"
31 static const char *libxl_tapif_script(libxl__gc *gc)
32 {
33 #ifdef __linux__
34 return libxl__strdup(gc, "no");
35 #else
36 return libxl__sprintf(gc, "%s/qemu-ifup", libxl_xen_script_dir_path());
37 #endif
38 }
40 static char ** libxl_build_device_model_args_old(libxl__gc *gc,
41 libxl_device_model_info *info,
42 libxl_device_nic *vifs,
43 int num_vifs)
44 {
45 int i;
46 flexarray_t *dm_args;
47 dm_args = flexarray_make(16, 1);
49 if (!dm_args)
50 return NULL;
52 flexarray_vappend(dm_args, "qemu-dm", "-d", libxl__sprintf(gc, "%d", info->domid), NULL);
54 if (info->dom_name)
55 flexarray_vappend(dm_args, "-domain-name", info->dom_name, NULL);
57 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
58 flexarray_append(dm_args, "-vnc");
59 if (info->vncdisplay) {
60 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
61 flexarray_append(dm_args,
62 libxl__sprintf(gc, "%s:%d%s",
63 info->vnclisten,
64 info->vncdisplay,
65 info->vncpasswd ? ",password" : ""));
66 } else {
67 flexarray_append(dm_args, libxl__sprintf(gc, "127.0.0.1:%d", info->vncdisplay));
68 }
69 } else if (info->vnclisten) {
70 if (strchr(info->vnclisten, ':') != NULL) {
71 flexarray_append(dm_args, info->vnclisten);
72 } else {
73 flexarray_append(dm_args, libxl__sprintf(gc, "%s:0", info->vnclisten));
74 }
75 } else {
76 flexarray_append(dm_args, "127.0.0.1:0");
77 }
78 if (info->vncunused) {
79 flexarray_append(dm_args, "-vncunused");
80 }
81 }
82 if (info->sdl) {
83 flexarray_append(dm_args, "-sdl");
84 if (!info->opengl) {
85 flexarray_append(dm_args, "-disable-opengl");
86 }
87 }
88 if (info->keymap) {
89 flexarray_vappend(dm_args, "-k", info->keymap, NULL);
90 }
91 if (info->nographic && (!info->sdl && !info->vnc)) {
92 flexarray_append(dm_args, "-nographic");
93 }
94 if (info->serial) {
95 flexarray_vappend(dm_args, "-serial", info->serial, NULL);
96 }
97 if (info->type == XENFV) {
98 int ioemu_vifs = 0;
100 if (info->videoram) {
101 flexarray_vappend(dm_args, "-videoram", libxl__sprintf(gc, "%d", info->videoram), NULL);
102 }
103 if (info->stdvga) {
104 flexarray_append(dm_args, "-std-vga");
105 }
107 if (info->boot) {
108 flexarray_vappend(dm_args, "-boot", info->boot, NULL);
109 }
110 if (info->usb || info->usbdevice) {
111 flexarray_append(dm_args, "-usb");
112 if (info->usbdevice) {
113 flexarray_vappend(dm_args, "-usbdevice", info->usbdevice, NULL);
114 }
115 }
116 if (info->soundhw) {
117 flexarray_vappend(dm_args, "-soundhw", info->soundhw, NULL);
118 }
119 if (info->apic) {
120 flexarray_append(dm_args, "-acpi");
121 }
122 if (info->vcpus > 1) {
123 flexarray_vappend(dm_args, "-vcpus", libxl__sprintf(gc, "%d", info->vcpus), NULL);
124 }
125 if (info->vcpu_avail) {
126 flexarray_vappend(dm_args, "-vcpu_avail", libxl__sprintf(gc, "0x%x", info->vcpu_avail), NULL);
127 }
128 for (i = 0; i < num_vifs; i++) {
129 if (vifs[i].nictype == NICTYPE_IOEMU) {
130 char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
131 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
132 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
133 char *ifname;
134 if (!vifs[i].ifname)
135 ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
136 else
137 ifname = vifs[i].ifname;
138 flexarray_vappend(dm_args,
139 "-net", libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
140 vifs[i].devid, smac, vifs[i].model),
141 "-net", libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,bridge=%s,script=%s",
142 vifs[i].devid, ifname, vifs[i].bridge, libxl_tapif_script(gc)),
143 NULL);
144 ioemu_vifs++;
145 }
146 }
147 /* If we have no emulated nics, tell qemu not to create any */
148 if ( ioemu_vifs == 0 ) {
149 flexarray_vappend(dm_args, "-net", "none", NULL);
150 }
151 }
152 if (info->saved_state) {
153 flexarray_vappend(dm_args, "-loadvm", info->saved_state, NULL);
154 }
155 for (i = 0; info->extra && info->extra[i] != NULL; i++)
156 flexarray_append(dm_args, info->extra[i]);
157 flexarray_append(dm_args, "-M");
158 if (info->type == XENPV)
159 flexarray_append(dm_args, "xenpv");
160 else
161 flexarray_append(dm_args, "xenfv");
162 flexarray_append(dm_args, NULL);
163 return (char **) flexarray_contents(dm_args);
164 }
166 static char ** libxl_build_device_model_args_new(libxl__gc *gc,
167 libxl_device_model_info *info,
168 libxl_device_nic *vifs,
169 int num_vifs)
170 {
171 flexarray_t *dm_args;
172 libxl_device_disk *disks;
173 int nb, i;
175 dm_args = flexarray_make(16, 1);
176 if (!dm_args)
177 return NULL;
179 flexarray_vappend(dm_args, libxl__strdup(gc, info->device_model),
180 "-xen-domid", libxl__sprintf(gc, "%d", info->domid), NULL);
182 if (info->type == XENPV) {
183 flexarray_append(dm_args, "-xen-attach");
184 }
186 if (info->dom_name) {
187 flexarray_vappend(dm_args, "-name", info->dom_name, NULL);
188 }
189 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
190 int display = 0;
191 const char *listen = "127.0.0.1";
193 flexarray_append(dm_args, "-vnc");
195 if (info->vncdisplay) {
196 display = info->vncdisplay;
197 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
198 listen = info->vnclisten;
199 }
200 } else if (info->vnclisten) {
201 listen = info->vnclisten;
202 }
204 if (strchr(listen, ':') != NULL)
205 flexarray_append(dm_args,
206 libxl__sprintf(gc, "%s%s", listen,
207 info->vncunused ? ",to=99" : ""));
208 else
209 flexarray_append(dm_args,
210 libxl__sprintf(gc, "%s:%d%s", listen, display,
211 info->vncunused ? ",to=99" : ""));
212 }
213 if (info->sdl) {
214 flexarray_append(dm_args, "-sdl");
215 }
217 if (info->type == XENPV && !info->nographic) {
218 flexarray_vappend(dm_args, "-vga", "xenfb", NULL);
219 }
221 if (info->keymap) {
222 flexarray_vappend(dm_args, "-k", info->keymap, NULL);
223 }
224 if (info->nographic && (!info->sdl && !info->vnc)) {
225 flexarray_append(dm_args, "-nographic");
226 }
227 if (info->serial) {
228 flexarray_vappend(dm_args, "-serial", info->serial, NULL);
229 }
230 if (info->type == XENFV) {
231 int ioemu_vifs = 0;
233 if (info->stdvga) {
234 flexarray_vappend(dm_args, "-vga", "std", NULL);
235 }
237 if (info->boot) {
238 flexarray_vappend(dm_args, "-boot", libxl__sprintf(gc, "order=%s", info->boot), NULL);
239 }
240 if (info->usb || info->usbdevice) {
241 flexarray_append(dm_args, "-usb");
242 if (info->usbdevice) {
243 flexarray_vappend(dm_args, "-usbdevice", info->usbdevice, NULL);
244 }
245 }
246 if (info->soundhw) {
247 flexarray_vappend(dm_args, "-soundhw", info->soundhw, NULL);
248 }
249 if (!info->apic) {
250 flexarray_append(dm_args, "-no-acpi");
251 }
252 if (info->vcpus > 1) {
253 flexarray_append(dm_args, "-smp");
254 if (info->vcpu_avail)
255 flexarray_append(dm_args, libxl__sprintf(gc, "%d,maxcpus=%d", info->vcpus, info->vcpu_avail));
256 else
257 flexarray_append(dm_args, libxl__sprintf(gc, "%d", info->vcpus));
258 }
259 for (i = 0; i < num_vifs; i++) {
260 if (vifs[i].nictype == NICTYPE_IOEMU) {
261 char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
262 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
263 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
264 char *ifname;
265 if (!vifs[i].ifname) {
266 ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
267 } else {
268 ifname = vifs[i].ifname;
269 }
270 flexarray_append(dm_args, "-net");
271 flexarray_append(dm_args, libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
272 vifs[i].devid, smac, vifs[i].model));
273 flexarray_append(dm_args, "-net");
274 flexarray_append(dm_args, libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,script=%s",
275 vifs[i].devid, ifname, libxl_tapif_script(gc)));
276 ioemu_vifs++;
277 }
278 }
279 /* If we have no emulated nics, tell qemu not to create any */
280 if ( ioemu_vifs == 0 ) {
281 flexarray_append(dm_args, "-net");
282 flexarray_append(dm_args, "none");
283 }
284 }
285 if (info->saved_state) {
286 flexarray_append(dm_args, "-loadvm");
287 flexarray_append(dm_args, info->saved_state);
288 }
289 for (i = 0; info->extra && info->extra[i] != NULL; i++)
290 flexarray_append(dm_args, info->extra[i]);
291 flexarray_append(dm_args, "-M");
292 if (info->type == XENPV)
293 flexarray_append(dm_args, "xenpv");
294 else
295 flexarray_append(dm_args, "xenfv");
297 /* RAM Size */
298 flexarray_append(dm_args, "-m");
299 flexarray_append(dm_args, libxl__sprintf(gc, "%d", info->target_ram));
301 if (info->type == XENFV) {
302 disks = libxl_device_disk_list(libxl__gc_owner(gc), info->domid, &nb);
303 for (i; i < nb; i++) {
304 if (disks[i].is_cdrom) {
305 flexarray_append(dm_args, "-cdrom");
306 flexarray_append(dm_args, libxl__strdup(gc, disks[i].physpath));
307 } else {
308 flexarray_append(dm_args, libxl__sprintf(gc, "-%s", disks[i].virtpath));
309 flexarray_append(dm_args, libxl__strdup(gc, disks[i].physpath));
310 }
311 libxl_device_disk_destroy(&disks[i]);
312 }
313 free(disks);
314 }
315 flexarray_append(dm_args, NULL);
316 return (char **) flexarray_contents(dm_args);
317 }
319 static char ** libxl_build_device_model_args(libxl__gc *gc,
320 libxl_device_model_info *info,
321 libxl_device_nic *vifs,
322 int num_vifs)
323 {
324 libxl_ctx *ctx = libxl__gc_owner(gc);
325 int new_qemu;
327 new_qemu = libxl_check_device_model_version(ctx, info->device_model);
329 if (new_qemu == 1) {
330 return libxl_build_device_model_args_new(gc, info, vifs, num_vifs);
331 } else {
332 return libxl_build_device_model_args_old(gc, info, vifs, num_vifs);
333 }
334 }
336 static void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild)
337 {
338 libxl__device_model_starting *starting = for_spawn;
339 struct xs_handle *xsh;
340 char *path = NULL, *pid = NULL;
341 int len;
343 if (asprintf(&path, "%s/%s", starting->dom_path, "image/device-model-pid") < 0)
344 goto out;
346 len = asprintf(&pid, "%d", innerchild);
347 if (len < 0)
348 goto out;
350 /* we mustn't use the parent's handle in the child */
351 xsh = xs_daemon_open();
353 xs_write(xsh, XBT_NULL, path, pid, len);
355 xs_daemon_close(xsh);
356 out:
357 free(path);
358 free(pid);
359 }
361 static int libxl_vfb_and_vkb_from_device_model_info(libxl_ctx *ctx,
362 libxl_device_model_info *info,
363 libxl_device_vfb *vfb,
364 libxl_device_vkb *vkb)
365 {
366 memset(vfb, 0x00, sizeof(libxl_device_vfb));
367 memset(vkb, 0x00, sizeof(libxl_device_vkb));
369 vfb->backend_domid = 0;
370 vfb->devid = 0;
371 vfb->vnc = info->vnc;
372 vfb->vnclisten = info->vnclisten;
373 vfb->vncdisplay = info->vncdisplay;
374 vfb->vncunused = info->vncunused;
375 vfb->vncpasswd = info->vncpasswd;
376 vfb->keymap = info->keymap;
377 vfb->sdl = info->sdl;
378 vfb->opengl = info->opengl;
380 vkb->backend_domid = 0;
381 vkb->devid = 0;
382 return 0;
383 }
385 static int libxl_write_dmargs(libxl_ctx *ctx, int domid, int guest_domid, char **args)
386 {
387 libxl__gc gc = LIBXL_INIT_GC(ctx);
388 int i;
389 char *vm_path;
390 char *dmargs, *path;
391 int dmargs_size;
392 struct xs_permissions roperm[2];
393 xs_transaction_t t;
395 roperm[0].id = 0;
396 roperm[0].perms = XS_PERM_NONE;
397 roperm[1].id = domid;
398 roperm[1].perms = XS_PERM_READ;
400 vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/vm", guest_domid));
402 i = 0;
403 dmargs_size = 0;
404 while (args[i] != NULL) {
405 dmargs_size = dmargs_size + strlen(args[i]) + 1;
406 i++;
407 }
408 dmargs_size++;
409 dmargs = (char *) malloc(dmargs_size);
410 i = 1;
411 dmargs[0] = '\0';
412 while (args[i] != NULL) {
413 if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) {
414 strcat(dmargs, " ");
415 strcat(dmargs, args[i]);
416 }
417 i++;
418 }
419 path = libxl__sprintf(&gc, "%s/image/dmargs", vm_path);
421 retry_transaction:
422 t = xs_transaction_start(ctx->xsh);
423 xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs));
424 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
425 xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm));
426 if (!xs_transaction_end(ctx->xsh, t, 0))
427 if (errno == EAGAIN)
428 goto retry_transaction;
429 free(dmargs);
430 libxl__free_all(&gc);
431 return 0;
432 }
434 static int libxl_create_stubdom(libxl_ctx *ctx,
435 libxl_device_model_info *info,
436 libxl_device_disk *disks, int num_disks,
437 libxl_device_nic *vifs, int num_vifs,
438 libxl_device_vfb *vfb,
439 libxl_device_vkb *vkb,
440 libxl__device_model_starting **starting_r)
441 {
442 libxl__gc gc = LIBXL_INIT_GC(ctx);
443 int i, num_console = STUBDOM_SPECIAL_CONSOLES, ret;
444 libxl_device_console *console;
445 libxl_domain_create_info c_info;
446 libxl_domain_build_info b_info;
447 libxl_domain_build_state state;
448 uint32_t domid;
449 char **args;
450 struct xs_permissions perm[2];
451 xs_transaction_t t;
452 libxl__device_model_starting *dm_starting = 0;
454 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
455 if (!args) {
456 ret = ERROR_FAIL;
457 goto out;
458 }
460 memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
461 c_info.hvm = 0;
462 c_info.name = libxl__sprintf(&gc, "%s-dm", libxl__domid_to_name(&gc, info->domid));
464 libxl_uuid_copy(&c_info.uuid, &info->uuid);
466 memset(&b_info, 0x00, sizeof(libxl_domain_build_info));
467 b_info.max_vcpus = 1;
468 b_info.max_memkb = 32 * 1024;
469 b_info.target_memkb = b_info.max_memkb;
470 b_info.kernel.path = libxl__abs_path(&gc, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path());
471 b_info.u.pv.cmdline = libxl__sprintf(&gc, " -d %d", info->domid);
472 b_info.u.pv.ramdisk.path = "";
473 b_info.u.pv.features = "";
474 b_info.hvm = 0;
476 ret = libxl__domain_make(ctx, &c_info, &domid);
477 if (ret)
478 goto out_free;
479 ret = libxl__domain_build(ctx, &b_info, domid, &state);
480 if (ret)
481 goto out_free;
483 libxl_write_dmargs(ctx, domid, info->domid, args);
484 libxl__xs_write(&gc, XBT_NULL,
485 libxl__sprintf(&gc, "%s/image/device-model-domid", libxl__xs_get_dompath(&gc, info->domid)),
486 "%d", domid);
487 libxl__xs_write(&gc, XBT_NULL,
488 libxl__sprintf(&gc, "%s/target", libxl__xs_get_dompath(&gc, domid)),
489 "%d", info->domid);
490 ret = xc_domain_set_target(ctx->xch, domid, info->domid);
491 if (ret<0) {
492 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting target domain %d -> %d", domid, info->domid);
493 ret = ERROR_FAIL;
494 goto out_free;
495 }
496 xs_set_target(ctx->xsh, domid, info->domid);
498 perm[0].id = domid;
499 perm[0].perms = XS_PERM_NONE;
500 perm[1].id = info->domid;
501 perm[1].perms = XS_PERM_READ;
502 retry_transaction:
503 t = xs_transaction_start(ctx->xsh);
504 xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid));
505 xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
506 xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs", domid));
507 xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
508 if (!xs_transaction_end(ctx->xsh, t, 0))
509 if (errno == EAGAIN)
510 goto retry_transaction;
512 for (i = 0; i < num_disks; i++) {
513 disks[i].domid = domid;
514 ret = libxl_device_disk_add(ctx, domid, &disks[i]);
515 if (ret)
516 goto out_free;
517 }
518 for (i = 0; i < num_vifs; i++) {
519 vifs[i].domid = domid;
520 ret = libxl_device_nic_add(ctx, domid, &vifs[i]);
521 if (ret)
522 goto out_free;
523 }
524 vfb->domid = domid;
525 ret = libxl_device_vfb_add(ctx, domid, vfb);
526 if (ret)
527 goto out_free;
528 vkb->domid = domid;
529 ret = libxl_device_vkb_add(ctx, domid, vkb);
530 if (ret)
531 goto out_free;
533 if (info->serial)
534 num_console++;
536 console = libxl__calloc(&gc, num_console, sizeof(libxl_device_console));
537 if (!console) {
538 ret = ERROR_NOMEM;
539 goto out_free;
540 }
542 for (i = 0; i < num_console; i++) {
543 console[i].devid = i;
544 console[i].consback = LIBXL_CONSBACK_IOEMU;
545 console[i].domid = domid;
546 /* STUBDOM_CONSOLE_LOGGING (console 0) is for minios logging
547 * STUBDOM_CONSOLE_SAVE (console 1) is for writing the save file
548 * STUBDOM_CONSOLE_RESTORE (console 2) is for reading the save file
549 */
550 switch (i) {
551 char *filename;
552 char *name;
553 case STUBDOM_CONSOLE_LOGGING:
554 name = libxl__sprintf(&gc, "qemu-dm-%s", libxl_domid_to_name(ctx, info->domid));
555 libxl_create_logfile(ctx, name, &filename);
556 console[i].output = libxl__sprintf(&gc, "file:%s", filename);
557 console[i].build_state = &state;
558 free(filename);
559 break;
560 case STUBDOM_CONSOLE_SAVE:
561 console[i].output = libxl__sprintf(&gc, "file:"SAVEFILE".%d", info->domid);
562 break;
563 case STUBDOM_CONSOLE_RESTORE:
564 if (info->saved_state)
565 console[i].output = libxl__sprintf(&gc, "pipe:%s", info->saved_state);
566 break;
567 default:
568 console[i].output = "pty";
569 break;
570 }
571 ret = libxl_device_console_add(ctx, domid, &console[i]);
572 if (ret)
573 goto out_free;
574 }
575 if (libxl__create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) {
576 ret = ERROR_FAIL;
577 goto out_free;
578 }
579 if (libxl__confirm_device_model_startup(ctx, dm_starting) < 0) {
580 ret = ERROR_FAIL;
581 goto out_free;
582 }
584 libxl_domain_unpause(ctx, domid);
586 if (starting_r) {
587 *starting_r = calloc(sizeof(libxl__device_model_starting), 1);
588 (*starting_r)->domid = info->domid;
589 (*starting_r)->dom_path = libxl__xs_get_dompath(&gc, info->domid);
590 (*starting_r)->for_spawn = NULL;
591 }
593 ret = 0;
595 out_free:
596 free(args);
597 out:
598 libxl__free_all(&gc);
599 return ret;
600 }
602 int libxl__create_device_model(libxl_ctx *ctx,
603 libxl_device_model_info *info,
604 libxl_device_disk *disks, int num_disks,
605 libxl_device_nic *vifs, int num_vifs,
606 libxl__device_model_starting **starting_r)
607 {
608 libxl__gc gc = LIBXL_INIT_GC(ctx);
609 char *path, *logfile;
610 int logfile_w, null;
611 int rc;
612 char **args;
613 libxl__device_model_starting buf_starting, *p;
614 xs_transaction_t t;
615 char *vm_path;
616 char **pass_stuff;
618 if (strstr(info->device_model, "stubdom-dm")) {
619 libxl_device_vfb vfb;
620 libxl_device_vkb vkb;
622 libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb);
623 rc = libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r);
624 goto out;
625 }
627 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
628 if (!args) {
629 rc = ERROR_FAIL;
630 goto out;
631 }
633 path = libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid);
634 xs_mkdir(ctx->xsh, XBT_NULL, path);
635 libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/disable_pf", path), "%d", !info->xen_platform_pci);
637 libxl_create_logfile(ctx, libxl__sprintf(&gc, "qemu-dm-%s", info->dom_name), &logfile);
638 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
639 free(logfile);
640 null = open("/dev/null", O_RDONLY);
642 if (starting_r) {
643 rc = ERROR_NOMEM;
644 *starting_r = calloc(sizeof(libxl__device_model_starting), 1);
645 if (!*starting_r)
646 goto out_close;
647 p = *starting_r;
648 p->for_spawn = calloc(sizeof(libxl__spawn_starting), 1);
649 } else {
650 p = &buf_starting;
651 p->for_spawn = NULL;
652 }
654 p->domid = info->domid;
655 p->dom_path = libxl__xs_get_dompath(&gc, info->domid);
656 if (!p->dom_path) {
657 rc = ERROR_FAIL;
658 goto out_close;
659 }
661 if (info->vncpasswd) {
662 retry_transaction:
663 /* Find uuid and the write the vnc password to xenstore for qemu. */
664 t = xs_transaction_start(ctx->xsh);
665 vm_path = libxl__xs_read(&gc,t,libxl__sprintf(&gc, "%s/vm", p->dom_path));
666 if (vm_path) {
667 /* Now write the vncpassword into it. */
668 pass_stuff = libxl__calloc(&gc, 3, sizeof(char *));
669 pass_stuff[0] = "vncpasswd";
670 pass_stuff[1] = info->vncpasswd;
671 libxl__xs_writev(&gc,t,vm_path,pass_stuff);
672 if (!xs_transaction_end(ctx->xsh, t, 0))
673 if (errno == EAGAIN)
674 goto retry_transaction;
675 }
676 }
678 rc = libxl__spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
679 if (rc < 0)
680 goto out_close;
681 if (!rc) { /* inner child */
682 libxl__exec(null, logfile_w, logfile_w,
683 libxl__abs_path(&gc, info->device_model, libxl_libexec_path()),
684 args);
685 }
687 rc = 0;
689 out_close:
690 close(null);
691 close(logfile_w);
692 free(args);
693 out:
694 libxl__free_all(&gc);
695 return rc;
696 }
698 static int detach_device_model(libxl_ctx *ctx,
699 libxl__device_model_starting *starting)
700 {
701 int rc;
702 rc = libxl__spawn_detach(ctx, starting->for_spawn);
703 if (starting->for_spawn)
704 free(starting->for_spawn);
705 free(starting);
706 return rc;
707 }
710 int libxl__confirm_device_model_startup(libxl_ctx *ctx,
711 libxl__device_model_starting *starting)
712 {
713 int problem = libxl__wait_for_device_model(ctx, starting->domid, "running", NULL, NULL);
714 int detach;
715 if ( !problem )
716 problem = libxl__spawn_check(ctx, starting->for_spawn);
717 detach = detach_device_model(ctx, starting);
718 return problem ? problem : detach;
719 }
721 int libxl__destroy_device_model(libxl_ctx *ctx, uint32_t domid)
722 {
723 libxl__gc gc = LIBXL_INIT_GC(ctx);
724 char *pid;
725 int ret;
727 pid = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid));
728 if (!pid) {
729 int stubdomid = libxl_get_stubdom_id(ctx, domid);
730 if (!stubdomid) {
731 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't find device model's pid");
732 ret = ERROR_INVAL;
733 goto out;
734 }
735 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device model is a stubdom, domid=%d\n", stubdomid);
736 ret = libxl_domain_destroy(ctx, stubdomid, 0);
737 if (ret)
738 goto out;
739 } else {
740 ret = kill(atoi(pid), SIGHUP);
741 if (ret < 0 && errno == ESRCH) {
742 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model already exited");
743 ret = 0;
744 } else if (ret == 0) {
745 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model signaled");
746 ret = 0;
747 } else {
748 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "failed to kill Device Model [%d]",
749 atoi(pid));
750 ret = ERROR_FAIL;
751 goto out;
752 }
753 }
754 xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", domid));
756 out:
757 libxl__free_all(&gc);
758 return ret;
759 }
761 static int libxl_build_xenpv_qemu_args(libxl__gc *gc,
762 uint32_t domid,
763 libxl_device_vfb *vfb,
764 libxl_device_model_info *info)
765 {
766 libxl_ctx *ctx = libxl__gc_owner(gc);
767 memset(info, 0x00, sizeof(libxl_device_model_info));
769 if (vfb != NULL) {
770 info->vnc = vfb->vnc;
771 if (vfb->vnclisten)
772 info->vnclisten = libxl__strdup(gc, vfb->vnclisten);
773 info->vncdisplay = vfb->vncdisplay;
774 info->vncunused = vfb->vncunused;
775 if (vfb->vncpasswd)
776 info->vncpasswd = vfb->vncpasswd;
777 if (vfb->keymap)
778 info->keymap = libxl__strdup(gc, vfb->keymap);
779 info->sdl = vfb->sdl;
780 info->opengl = vfb->opengl;
781 } else
782 info->nographic = 1;
783 info->domid = domid;
784 info->dom_name = libxl_domid_to_name(ctx, domid);
785 info->device_model = libxl__abs_path(gc, "qemu-dm", libxl_libexec_path());
786 info->type = XENPV;
787 return 0;
788 }
790 int libxl__need_xenpv_qemu(libxl_ctx *ctx,
791 int nr_consoles, libxl_device_console *consoles,
792 int nr_vfbs, libxl_device_vfb *vfbs,
793 int nr_disks, libxl_device_disk *disks)
794 {
795 int i, ret = 0;
796 libxl__gc gc = LIBXL_INIT_GC(ctx);
798 if (nr_consoles > 1) {
799 ret = 1;
800 goto out;
801 }
803 for (i = 0; i < nr_consoles; i++) {
804 if (consoles[i].consback == LIBXL_CONSBACK_IOEMU) {
805 ret = 1;
806 goto out;
807 }
808 }
810 if (nr_vfbs > 0) {
811 ret = 1;
812 goto out;
813 }
815 if (nr_disks > 0 && !libxl__blktap_enabled(&gc))
816 ret = 1;
818 out:
819 libxl__free_all(&gc);
820 return ret;
821 }
823 int libxl__create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb,
824 libxl__device_model_starting **starting_r)
825 {
826 libxl__gc gc = LIBXL_INIT_GC(ctx);
827 libxl_device_model_info info;
829 libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info);
830 libxl__create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
831 libxl__free_all(&gc);
832 return 0;
833 }