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 */
17
18 #include "libxl_osdeps.h" /* must come before any other headers */
19
20 #include "libxl_internal.h"
21 #include "libxl_arch.h"
22
23 #include <xc_dom.h>
24 #include <xenguest.h>
25 #include <xen/hvm/hvm_info_table.h>
26 #include <xen/hvm/e820.h>
27
28 #include <xen-xsm/flask/flask.h>
29
libxl__domain_create_info_setdefault(libxl__gc * gc,libxl_domain_create_info * c_info,const libxl_physinfo * info)30 int libxl__domain_create_info_setdefault(libxl__gc *gc,
31 libxl_domain_create_info *c_info,
32 const libxl_physinfo *info)
33 {
34 if (!c_info->type) {
35 LOG(ERROR, "domain type unspecified");
36 return ERROR_INVAL;
37 }
38
39 libxl__arch_domain_create_info_setdefault(gc, c_info);
40
41 if (c_info->type != LIBXL_DOMAIN_TYPE_PV) {
42 if (info->cap_hap) {
43 libxl_defbool_setdefault(&c_info->hap, true);
44 } else if (info->cap_shadow) {
45 libxl_defbool_setdefault(&c_info->hap, false);
46 } else {
47 LOG(ERROR, "neither hap nor shadow paging available");
48 return ERROR_INVAL;
49 }
50
51 libxl_defbool_setdefault(&c_info->oos, true);
52 }
53
54 libxl_defbool_setdefault(&c_info->run_hotplug_scripts, true);
55 libxl_defbool_setdefault(&c_info->driver_domain, false);
56
57 if (!c_info->ssidref)
58 c_info->ssidref = SECINITSID_DOMU;
59
60 libxl_defbool_setdefault(&c_info->xend_suspend_evtchn_compat, false);
61
62 return 0;
63 }
64
libxl__rdm_setdefault(libxl__gc * gc,libxl_domain_build_info * b_info)65 void libxl__rdm_setdefault(libxl__gc *gc, libxl_domain_build_info *b_info)
66 {
67 if (b_info->u.hvm.rdm.policy == LIBXL_RDM_RESERVE_POLICY_INVALID)
68 b_info->u.hvm.rdm.policy = LIBXL_RDM_RESERVE_POLICY_RELAXED;
69
70 if (b_info->u.hvm.rdm_mem_boundary_memkb == LIBXL_MEMKB_DEFAULT)
71 b_info->u.hvm.rdm_mem_boundary_memkb =
72 LIBXL_RDM_MEM_BOUNDARY_MEMKB_DEFAULT;
73 }
74
libxl__domain_build_info_setdefault(libxl__gc * gc,libxl_domain_build_info * b_info)75 int libxl__domain_build_info_setdefault(libxl__gc *gc,
76 libxl_domain_build_info *b_info)
77 {
78 int i, rc;
79
80 if (b_info->type != LIBXL_DOMAIN_TYPE_HVM &&
81 b_info->type != LIBXL_DOMAIN_TYPE_PV &&
82 b_info->type != LIBXL_DOMAIN_TYPE_PVH) {
83 LOG(ERROR, "invalid domain type");
84 return ERROR_INVAL;
85 }
86
87 /* Copy deprecated options to it's new position. */
88 rc = libxl__domain_build_info_copy_deprecated(CTX, b_info);
89 if (rc) {
90 LOG(ERROR, "Unable to copy deprecated fields");
91 return rc;
92 }
93
94 libxl_defbool_setdefault(&b_info->device_model_stubdomain, false);
95
96 if (libxl_defbool_val(b_info->device_model_stubdomain) &&
97 !b_info->device_model_ssidref)
98 b_info->device_model_ssidref = SECINITSID_DOMDM;
99
100 if (!b_info->device_model_version) {
101 if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) {
102 if (libxl_defbool_val(b_info->device_model_stubdomain)) {
103 b_info->device_model_version =
104 LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
105 } else {
106 b_info->device_model_version = libxl__default_device_model(gc);
107 }
108 } else {
109 b_info->device_model_version =
110 LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
111 }
112 if (b_info->device_model_version
113 == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
114 const char *dm;
115
116 dm = libxl__domain_device_model(gc, b_info);
117 rc = access(dm, X_OK);
118 if (rc < 0) {
119 /* qemu-xen unavailable, use qemu-xen-traditional */
120 if (errno == ENOENT) {
121 LOGE(INFO, "qemu-xen is unavailable"
122 ", using qemu-xen-traditional instead");
123 b_info->device_model_version =
124 LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
125 } else {
126 LOGE(ERROR, "qemu-xen access error");
127 return ERROR_FAIL;
128 }
129 }
130 }
131 }
132
133 if (b_info->blkdev_start == NULL)
134 b_info->blkdev_start = libxl__strdup(NOGC, "xvda");
135
136 if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) {
137 if (!b_info->u.hvm.bios)
138 switch (b_info->device_model_version) {
139 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
140 b_info->u.hvm.bios = LIBXL_BIOS_TYPE_ROMBIOS; break;
141 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
142 b_info->u.hvm.bios = LIBXL_BIOS_TYPE_SEABIOS; break;
143 default:
144 LOG(ERROR, "unknown device model version");
145 return ERROR_INVAL;
146 }
147
148 /* Enforce BIOS<->Device Model version relationship */
149 switch (b_info->device_model_version) {
150 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
151 if (b_info->u.hvm.bios != LIBXL_BIOS_TYPE_ROMBIOS) {
152 LOG(ERROR, "qemu-xen-traditional requires bios=rombios.");
153 return ERROR_INVAL;
154 }
155 break;
156 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
157 if (b_info->u.hvm.bios == LIBXL_BIOS_TYPE_ROMBIOS) {
158 LOG(ERROR, "qemu-xen does not support bios=rombios.");
159 return ERROR_INVAL;
160 }
161 break;
162 default:abort();
163 }
164
165 /* Check HVM direct boot parameters, we should honour ->ramdisk and
166 * ->cmdline iff ->kernel is set.
167 */
168 if (!b_info->kernel && (b_info->ramdisk || b_info->cmdline)) {
169 LOG(ERROR, "direct boot parameters specified but kernel missing");
170 return ERROR_INVAL;
171 }
172 }
173
174 if (b_info->type == LIBXL_DOMAIN_TYPE_HVM &&
175 libxl_defbool_val(b_info->device_model_stubdomain)) {
176 if (!b_info->stubdomain_kernel) {
177 switch (b_info->device_model_version) {
178 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
179 b_info->stubdomain_kernel =
180 libxl__abs_path(NOGC, "ioemu-stubdom.gz", libxl__xenfirmwaredir_path());
181 break;
182 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
183 b_info->stubdomain_kernel =
184 libxl__abs_path(NOGC,
185 "qemu-stubdom-linux-kernel",
186 libxl__xenfirmwaredir_path());
187 break;
188 default:
189 abort();
190 }
191 }
192 if (!b_info->stubdomain_ramdisk) {
193 switch (b_info->device_model_version) {
194 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
195 break;
196 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
197 b_info->stubdomain_ramdisk =
198 libxl__abs_path(NOGC,
199 "qemu-stubdom-linux-rootfs",
200 libxl__xenfirmwaredir_path());
201 break;
202 default:
203 abort();
204 }
205 }
206 }
207
208 if (!b_info->max_vcpus)
209 b_info->max_vcpus = 1;
210 if (!b_info->avail_vcpus.size) {
211 if (libxl_cpu_bitmap_alloc(CTX, &b_info->avail_vcpus, 1)) {
212 LOG(ERROR, "unable to allocate avail_vcpus bitmap");
213 return ERROR_FAIL;
214 }
215 libxl_bitmap_set(&b_info->avail_vcpus, 0);
216 } else if (b_info->avail_vcpus.size > HVM_MAX_VCPUS) {
217 LOG(ERROR, "avail_vcpus bitmap contains too many VCPUS");
218 return ERROR_FAIL;
219 }
220
221 /* In libxl internals, we want to deal with vcpu_hard_affinity only! */
222 if (b_info->cpumap.size && !b_info->num_vcpu_hard_affinity) {
223 b_info->vcpu_hard_affinity = libxl__calloc(gc, b_info->max_vcpus,
224 sizeof(libxl_bitmap));
225 for (i = 0; i < b_info->max_vcpus; i++) {
226 if (libxl_cpu_bitmap_alloc(CTX, &b_info->vcpu_hard_affinity[i], 0)) {
227 LOG(ERROR, "failed to allocate vcpu hard affinity bitmap");
228 return ERROR_FAIL;
229 }
230 libxl_bitmap_copy(CTX, &b_info->vcpu_hard_affinity[i],
231 &b_info->cpumap);
232 }
233 b_info->num_vcpu_hard_affinity = b_info->max_vcpus;
234 }
235
236 libxl_defbool_setdefault(&b_info->numa_placement, true);
237
238 if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
239 b_info->max_memkb = 32 * 1024;
240 if (b_info->target_memkb == LIBXL_MEMKB_DEFAULT)
241 b_info->target_memkb = b_info->max_memkb;
242
243 if (b_info->stubdomain_memkb == LIBXL_MEMKB_DEFAULT) {
244 if (libxl_defbool_val(b_info->device_model_stubdomain)) {
245 if (libxl__stubdomain_is_linux(b_info))
246 b_info->stubdomain_memkb = LIBXL_LINUX_STUBDOM_MEM * 1024;
247 else
248 b_info->stubdomain_memkb = 28 * 1024; // MiniOS
249 } else {
250 b_info->stubdomain_memkb = 0; // no stubdomain
251 }
252 }
253
254 libxl_defbool_setdefault(&b_info->claim_mode, false);
255
256 libxl_defbool_setdefault(&b_info->localtime, false);
257
258 libxl_defbool_setdefault(&b_info->disable_migrate, false);
259
260 for (i = 0 ; i < b_info->num_iomem; i++)
261 if (b_info->iomem[i].gfn == LIBXL_INVALID_GFN)
262 b_info->iomem[i].gfn = b_info->iomem[i].start;
263
264 if (!b_info->event_channels)
265 b_info->event_channels = 1023;
266
267 libxl__arch_domain_build_info_setdefault(gc, b_info);
268 libxl_defbool_setdefault(&b_info->dm_restrict, false);
269
270 if (b_info->iommu_memkb == LIBXL_MEMKB_DEFAULT)
271 /* Normally defaulted in libxl__domain_create_info_setdefault */
272 b_info->iommu_memkb = 0;
273
274 switch (b_info->type) {
275 case LIBXL_DOMAIN_TYPE_HVM:
276 if (b_info->shadow_memkb == LIBXL_MEMKB_DEFAULT)
277 /* Normally defaulted in libxl__domain_create_info_setdefault */
278 b_info->shadow_memkb = 0;
279 if (b_info->u.hvm.mmio_hole_memkb == LIBXL_MEMKB_DEFAULT)
280 b_info->u.hvm.mmio_hole_memkb = 0;
281
282 if (b_info->u.hvm.vga.kind == LIBXL_VGA_INTERFACE_TYPE_UNKNOWN) {
283 b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
284 }
285
286 if (!b_info->u.hvm.hdtype)
287 b_info->u.hvm.hdtype = LIBXL_HDTYPE_IDE;
288
289 switch (b_info->device_model_version) {
290 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
291 switch (b_info->u.hvm.vga.kind) {
292 case LIBXL_VGA_INTERFACE_TYPE_NONE:
293 if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
294 b_info->video_memkb = 0;
295 break;
296 case LIBXL_VGA_INTERFACE_TYPE_QXL:
297 LOG(ERROR,"qemu upstream required for qxl vga");
298 return ERROR_INVAL;
299 break;
300 case LIBXL_VGA_INTERFACE_TYPE_STD:
301 if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
302 b_info->video_memkb = 8 * 1024;
303 if (b_info->video_memkb < 8 * 1024) {
304 LOG(ERROR, "videoram must be at least 8 MB for STDVGA on QEMU_XEN_TRADITIONAL");
305 return ERROR_INVAL;
306 }
307 break;
308 case LIBXL_VGA_INTERFACE_TYPE_CIRRUS:
309 default:
310 if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
311 b_info->video_memkb = 4 * 1024;
312 if (b_info->video_memkb != 4 * 1024)
313 LOG(WARN, "ignoring videoram other than 4 MB for CIRRUS on QEMU_XEN_TRADITIONAL");
314 break;
315 }
316 break;
317 case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
318 default:
319 switch (b_info->u.hvm.vga.kind) {
320 case LIBXL_VGA_INTERFACE_TYPE_NONE:
321 if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
322 b_info->video_memkb = 0;
323 break;
324 case LIBXL_VGA_INTERFACE_TYPE_QXL:
325 if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT) {
326 b_info->video_memkb = (128 * 1024);
327 } else if (b_info->video_memkb < (128 * 1024)) {
328 LOG(ERROR,
329 "128 Mib videoram is the minimum for qxl default");
330 return ERROR_INVAL;
331 }
332 break;
333 case LIBXL_VGA_INTERFACE_TYPE_STD:
334 if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
335 b_info->video_memkb = 16 * 1024;
336 if (b_info->video_memkb < 16 * 1024) {
337 LOG(ERROR, "videoram must be at least 16 MB for STDVGA on QEMU_XEN");
338 return ERROR_INVAL;
339 }
340 break;
341 case LIBXL_VGA_INTERFACE_TYPE_CIRRUS:
342 default:
343 if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
344 b_info->video_memkb = 8 * 1024;
345 if (b_info->video_memkb < 8 * 1024) {
346 LOG(ERROR, "videoram must be at least 8 MB for CIRRUS on QEMU_XEN");
347 return ERROR_INVAL;
348 }
349 break;
350 }
351 break;
352 }
353
354 libxl_defbool_setdefault(&b_info->u.hvm.pae, true);
355 libxl_defbool_setdefault(&b_info->u.hvm.acpi, true);
356 libxl_defbool_setdefault(&b_info->u.hvm.acpi_s3, true);
357 libxl_defbool_setdefault(&b_info->u.hvm.acpi_s4, true);
358 libxl_defbool_setdefault(&b_info->u.hvm.acpi_laptop_slate, false);
359 libxl_defbool_setdefault(&b_info->u.hvm.nx, true);
360 libxl_defbool_setdefault(&b_info->u.hvm.viridian, false);
361 libxl_defbool_setdefault(&b_info->u.hvm.hpet, true);
362 libxl_defbool_setdefault(&b_info->u.hvm.vpt_align, true);
363 libxl_defbool_setdefault(&b_info->u.hvm.altp2m, false);
364 libxl_defbool_setdefault(&b_info->u.hvm.usb, false);
365 libxl_defbool_setdefault(&b_info->u.hvm.vkb_device, true);
366 libxl_defbool_setdefault(&b_info->u.hvm.xen_platform_pci, true);
367
368 libxl_defbool_setdefault(&b_info->u.hvm.spice.enable, false);
369 if (!libxl_defbool_val(b_info->u.hvm.spice.enable) &&
370 (b_info->u.hvm.spice.usbredirection > 0) ){
371 b_info->u.hvm.spice.usbredirection = 0;
372 LOG(WARN, "spice disabled, disabling usbredirection");
373 }
374
375 if (!b_info->u.hvm.usbversion &&
376 (b_info->u.hvm.spice.usbredirection > 0) )
377 b_info->u.hvm.usbversion = 2;
378
379 if ((b_info->u.hvm.usbversion || b_info->u.hvm.spice.usbredirection) &&
380 ( libxl_defbool_val(b_info->u.hvm.usb)
381 || b_info->u.hvm.usbdevice_list
382 || b_info->u.hvm.usbdevice) ){
383 LOG(ERROR,"usbversion and/or usbredirection cannot be "
384 "enabled with usb and/or usbdevice parameters.");
385 return ERROR_INVAL;
386 }
387
388 if (!b_info->u.hvm.boot)
389 b_info->u.hvm.boot = libxl__strdup(NOGC, "cda");
390
391 libxl_defbool_setdefault(&b_info->u.hvm.vnc.enable, true);
392 if (libxl_defbool_val(b_info->u.hvm.vnc.enable)) {
393 libxl_defbool_setdefault(&b_info->u.hvm.vnc.findunused, true);
394 if (!b_info->u.hvm.vnc.listen)
395 b_info->u.hvm.vnc.listen = libxl__strdup(NOGC, "127.0.0.1");
396 }
397
398 libxl_defbool_setdefault(&b_info->u.hvm.sdl.enable, false);
399 if (libxl_defbool_val(b_info->u.hvm.sdl.enable)) {
400 libxl_defbool_setdefault(&b_info->u.hvm.sdl.opengl, false);
401 }
402
403 if (libxl_defbool_val(b_info->u.hvm.spice.enable)) {
404 libxl_defbool_setdefault(&b_info->u.hvm.spice.disable_ticketing,
405 false);
406 libxl_defbool_setdefault(&b_info->u.hvm.spice.agent_mouse, true);
407 libxl_defbool_setdefault(&b_info->u.hvm.spice.vdagent, false);
408 libxl_defbool_setdefault(&b_info->u.hvm.spice.clipboard_sharing,
409 false);
410 }
411
412 libxl_defbool_setdefault(&b_info->u.hvm.nographic, false);
413
414 libxl_defbool_setdefault(&b_info->u.hvm.gfx_passthru, false);
415
416 libxl__rdm_setdefault(gc, b_info);
417 break;
418 case LIBXL_DOMAIN_TYPE_PV:
419 libxl_defbool_setdefault(&b_info->u.pv.e820_host, false);
420 if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT)
421 b_info->video_memkb = 0;
422 if (b_info->shadow_memkb == LIBXL_MEMKB_DEFAULT)
423 /* Normally defaulted in libxl__domain_create_info_setdefault */
424 b_info->shadow_memkb = 0;
425 if (b_info->u.pv.slack_memkb == LIBXL_MEMKB_DEFAULT)
426 b_info->u.pv.slack_memkb = 0;
427 break;
428 case LIBXL_DOMAIN_TYPE_PVH:
429 libxl_defbool_setdefault(&b_info->u.pvh.pvshim, false);
430 if (libxl_defbool_val(b_info->u.pvh.pvshim)) {
431 if (!b_info->u.pvh.pvshim_path)
432 b_info->u.pvh.pvshim_path =
433 libxl__sprintf(NOGC, "%s/%s",
434 libxl__xenfirmwaredir_path(),
435 PVSHIM_BASENAME);
436 if (!b_info->u.pvh.pvshim_cmdline)
437 b_info->u.pvh.pvshim_cmdline =
438 libxl__strdup(NOGC, PVSHIM_CMDLINE);
439 }
440
441 break;
442 default:
443 LOG(ERROR, "invalid domain type %s in create info",
444 libxl_domain_type_to_string(b_info->type));
445 return ERROR_INVAL;
446 }
447
448 /* Configuration fields shared between PVH and HVM. */
449 if (b_info->type != LIBXL_DOMAIN_TYPE_PV) {
450 if (libxl__timer_mode_is_default(&b_info->timer_mode))
451 b_info->timer_mode = LIBXL_TIMER_MODE_NO_DELAY_FOR_MISSED_TICKS;
452
453 libxl_defbool_setdefault(&b_info->apic, true);
454 libxl_defbool_setdefault(&b_info->nested_hvm, false);
455 }
456
457 return 0;
458 }
459
init_console_info(libxl__gc * gc,libxl__device_console * console,int dev_num)460 static void init_console_info(libxl__gc *gc,
461 libxl__device_console *console,
462 int dev_num)
463 {
464 libxl__device_console_init(console);
465 console->devid = dev_num;
466 console->consback = LIBXL__CONSOLE_BACKEND_XENCONSOLED;
467 console->output = libxl__strdup(NOGC, "pty");
468 /* console->{name,connection,path} are NULL on normal consoles.
469 Only 'channels' when mapped to consoles have a string name. */
470 }
471
libxl__domain_build(libxl__gc * gc,libxl_domain_config * d_config,uint32_t domid,libxl__domain_build_state * state)472 int libxl__domain_build(libxl__gc *gc,
473 libxl_domain_config *d_config,
474 uint32_t domid,
475 libxl__domain_build_state *state)
476 {
477 libxl_domain_build_info *const info = &d_config->b_info;
478 char **vments = NULL, **localents = NULL;
479 struct timeval start_time;
480 int i, ret;
481
482 ret = libxl__build_pre(gc, domid, d_config, state);
483 if (ret)
484 goto out;
485
486 gettimeofday(&start_time, NULL);
487
488 switch (info->type) {
489 case LIBXL_DOMAIN_TYPE_HVM:
490 ret = libxl__build_hvm(gc, domid, d_config, state);
491 if (ret)
492 goto out;
493
494 vments = libxl__calloc(gc, 7, sizeof(char *));
495 vments[0] = "rtc/timeoffset";
496 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
497 vments[2] = "image/ostype";
498 vments[3] = "hvm";
499 vments[4] = "start_time";
500 vments[5] = GCSPRINTF("%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
501
502 localents = libxl__calloc(gc, 13, sizeof(char *));
503 i = 0;
504 localents[i++] = "platform/acpi";
505 localents[i++] = libxl__acpi_defbool_val(info) ? "1" : "0";
506 localents[i++] = "platform/acpi_s3";
507 localents[i++] = libxl_defbool_val(info->u.hvm.acpi_s3) ? "1" : "0";
508 localents[i++] = "platform/acpi_s4";
509 localents[i++] = libxl_defbool_val(info->u.hvm.acpi_s4) ? "1" : "0";
510 localents[i++] = "platform/acpi_laptop_slate";
511 localents[i++] = libxl_defbool_val(info->u.hvm.acpi_laptop_slate) ? "1" : "0";
512 if (info->u.hvm.mmio_hole_memkb) {
513 uint64_t max_ram_below_4g =
514 (1ULL << 32) - (info->u.hvm.mmio_hole_memkb << 10);
515
516 if (max_ram_below_4g <= HVM_BELOW_4G_MMIO_START) {
517 localents[i++] = "platform/mmio_hole_size";
518 localents[i++] =
519 GCSPRINTF("%"PRIu64,
520 info->u.hvm.mmio_hole_memkb << 10);
521 }
522 }
523 localents[i++] = "platform/device-model";
524 localents[i++] = (char *)libxl_device_model_version_to_string(info->device_model_version);
525
526 break;
527 case LIBXL_DOMAIN_TYPE_PV:
528 ret = libxl__build_pv(gc, domid, d_config, state);
529 if (ret)
530 goto out;
531
532 vments = libxl__calloc(gc, 11, sizeof(char *));
533 i = 0;
534 vments[i++] = "image/ostype";
535 vments[i++] = "linux";
536 vments[i++] = "image/kernel";
537 vments[i++] = (char *) state->pv_kernel.path;
538 vments[i++] = "start_time";
539 vments[i++] = GCSPRINTF("%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
540 if (state->pv_ramdisk.path) {
541 vments[i++] = "image/ramdisk";
542 vments[i++] = (char *) state->pv_ramdisk.path;
543 }
544 if (state->pv_cmdline) {
545 vments[i++] = "image/cmdline";
546 vments[i++] = (char *) state->pv_cmdline;
547 }
548
549 break;
550 case LIBXL_DOMAIN_TYPE_PVH:
551 state->shim_path = info->u.pvh.pvshim_path;
552 state->shim_cmdline = GCSPRINTF("%s%s%s",
553 info->u.pvh.pvshim_cmdline,
554 info->u.pvh.pvshim_extra ? " " : "",
555 info->u.pvh.pvshim_extra ? info->u.pvh.pvshim_extra : "");
556
557 ret = libxl__build_hvm(gc, domid, d_config, state);
558 if (ret)
559 goto out;
560
561 vments = libxl__calloc(gc, 3, sizeof(char *));
562 vments[0] = "start_time";
563 vments[1] = GCSPRINTF("%"PRIu64".%02ld",
564 (uint64_t)start_time.tv_sec,
565 (long)start_time.tv_usec/10000);
566
567 break;
568 default:
569 ret = ERROR_INVAL;
570 goto out;
571 }
572 ret = libxl__build_post(gc, domid, info, state, vments, localents);
573 out:
574 return ret;
575 }
576
libxl__domain_make(libxl__gc * gc,libxl_domain_config * d_config,libxl__domain_build_state * state,uint32_t * domid,bool soft_reset)577 int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
578 libxl__domain_build_state *state,
579 uint32_t *domid, bool soft_reset)
580 {
581 libxl_ctx *ctx = libxl__gc_owner(gc);
582 int ret, rc, nb_vm;
583 const char *dom_type;
584 char *uuid_string;
585 char *dom_path, *vm_path, *libxl_path;
586 struct xs_permissions roperm[2];
587 struct xs_permissions rwperm[1];
588 struct xs_permissions noperm[1];
589 xs_transaction_t t = 0;
590 libxl_vminfo *vm_list;
591
592 /* convenience aliases */
593 libxl_domain_create_info *info = &d_config->c_info;
594 libxl_domain_build_info *b_info = &d_config->b_info;
595
596 assert(soft_reset || *domid == INVALID_DOMID);
597
598 uuid_string = libxl__uuid2string(gc, info->uuid);
599 if (!uuid_string) {
600 rc = ERROR_NOMEM;
601 goto out;
602 }
603
604 if (!soft_reset) {
605 struct xen_domctl_createdomain create = {
606 .ssidref = info->ssidref,
607 .max_vcpus = b_info->max_vcpus,
608 .max_evtchn_port = b_info->event_channels,
609 .max_grant_frames = b_info->max_grant_frames,
610 .max_maptrack_frames = b_info->max_maptrack_frames,
611 };
612
613 if (info->type != LIBXL_DOMAIN_TYPE_PV) {
614 create.flags |= XEN_DOMCTL_CDF_hvm;
615 create.flags |=
616 libxl_defbool_val(info->hap) ? XEN_DOMCTL_CDF_hap : 0;
617 create.flags |=
618 libxl_defbool_val(info->oos) ? 0 : XEN_DOMCTL_CDF_oos_off;
619 }
620
621 assert(info->passthrough != LIBXL_PASSTHROUGH_DEFAULT);
622 LOG(DETAIL, "passthrough: %s",
623 libxl_passthrough_to_string(info->passthrough));
624
625 if (info->passthrough != LIBXL_PASSTHROUGH_DISABLED)
626 create.flags |= XEN_DOMCTL_CDF_iommu;
627
628 if (info->passthrough == LIBXL_PASSTHROUGH_SYNC_PT)
629 create.iommu_opts |= XEN_DOMCTL_IOMMU_no_sharept;
630
631 /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
632 libxl_uuid_copy(ctx, (libxl_uuid *)&create.handle, &info->uuid);
633
634 ret = libxl__arch_domain_prepare_config(gc, d_config, &create);
635 if (ret < 0) {
636 LOGED(ERROR, *domid, "fail to get domain config");
637 rc = ERROR_FAIL;
638 goto out;
639 }
640
641 for (;;) {
642 uint32_t local_domid;
643 bool recent;
644
645 if (info->domid == RANDOM_DOMID) {
646 uint16_t v;
647
648 ret = libxl__random_bytes(gc, (void *)&v, sizeof(v));
649 if (ret < 0)
650 break;
651
652 v &= DOMID_MASK;
653 if (!libxl_domid_valid_guest(v))
654 continue;
655
656 local_domid = v;
657 } else {
658 local_domid = info->domid; /* May not be valid */
659 }
660
661 ret = xc_domain_create(ctx->xch, &local_domid, &create);
662 if (ret < 0) {
663 /*
664 * If we generated a random domid and creation failed
665 * because that domid already exists then simply try
666 * again.
667 */
668 if (errno == EEXIST && info->domid == RANDOM_DOMID)
669 continue;
670
671 LOGED(ERROR, local_domid, "domain creation fail");
672 rc = ERROR_FAIL;
673 goto out;
674 }
675
676 /* A new domain now exists */
677 *domid = local_domid;
678
679 rc = libxl__is_domid_recent(gc, local_domid, &recent);
680 if (rc)
681 goto out;
682
683 /* The domid is not recent, so we're done */
684 if (!recent)
685 break;
686
687 /*
688 * If the domid was specified then there's no point in
689 * trying again.
690 */
691 if (libxl_domid_valid_guest(info->domid)) {
692 LOGED(ERROR, local_domid, "domain id recently used");
693 rc = ERROR_FAIL;
694 goto out;
695 }
696
697 /*
698 * The domain is recent and so cannot be used. Clear domid
699 * here since, if xc_domain_destroy() fails below there is
700 * little point calling it again in the error path.
701 */
702 *domid = INVALID_DOMID;
703
704 ret = xc_domain_destroy(ctx->xch, local_domid);
705 if (ret < 0) {
706 LOGED(ERROR, local_domid, "domain destroy fail");
707 rc = ERROR_FAIL;
708 goto out;
709 }
710
711 /* The domain was successfully destroyed, so we can try again */
712 }
713
714 rc = libxl__arch_domain_save_config(gc, d_config, state, &create);
715 if (rc < 0)
716 goto out;
717 }
718
719 /*
720 * If soft_reset is set the the domid will have been valid on entry.
721 * If it was not set then xc_domain_create() should have assigned a
722 * valid value. Either way, if we reach this point, domid should be
723 * valid.
724 */
725 assert(libxl_domid_valid_guest(*domid));
726
727 ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid);
728 if (ret < 0) {
729 LOGED(ERROR, *domid, "domain move fail");
730 rc = ERROR_FAIL;
731 goto out;
732 }
733
734 dom_path = libxl__xs_get_dompath(gc, *domid);
735 if (!dom_path) {
736 rc = ERROR_FAIL;
737 goto out;
738 }
739
740 vm_path = GCSPRINTF("/vm/%s", uuid_string);
741 if (!vm_path) {
742 LOGD(ERROR, *domid, "cannot allocate create paths");
743 rc = ERROR_FAIL;
744 goto out;
745 }
746
747 libxl_path = libxl__xs_libxl_path(gc, *domid);
748 if (!libxl_path) {
749 rc = ERROR_FAIL;
750 goto out;
751 }
752
753 noperm[0].id = 0;
754 noperm[0].perms = XS_PERM_NONE;
755
756 roperm[0].id = 0;
757 roperm[0].perms = XS_PERM_NONE;
758 roperm[1].id = *domid;
759 roperm[1].perms = XS_PERM_READ;
760
761 rwperm[0].id = *domid;
762 rwperm[0].perms = XS_PERM_NONE;
763
764 retry_transaction:
765 t = xs_transaction_start(ctx->xsh);
766
767 xs_rm(ctx->xsh, t, dom_path);
768 libxl__xs_mknod(gc, t, dom_path, roperm, ARRAY_SIZE(roperm));
769
770 xs_rm(ctx->xsh, t, vm_path);
771 libxl__xs_mknod(gc, t, vm_path, roperm, ARRAY_SIZE(roperm));
772
773 xs_rm(ctx->xsh, t, libxl_path);
774 libxl__xs_mknod(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));
775 libxl__xs_mknod(gc, t, GCSPRINTF("%s/device", libxl_path),
776 noperm, ARRAY_SIZE(noperm));
777
778 xs_write(ctx->xsh, t, GCSPRINTF("%s/vm", dom_path), vm_path, strlen(vm_path));
779 rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
780 if (rc)
781 goto out;
782
783 libxl__xs_mknod(gc, t,
784 GCSPRINTF("%s/cpu", dom_path),
785 roperm, ARRAY_SIZE(roperm));
786 libxl__xs_mknod(gc, t,
787 GCSPRINTF("%s/memory", dom_path),
788 roperm, ARRAY_SIZE(roperm));
789
790 if (!libxl_defbool_val(info->xend_suspend_evtchn_compat)) {
791 libxl__xs_mknod(gc, t,
792 GCSPRINTF("%s/device", dom_path),
793 roperm, ARRAY_SIZE(roperm));
794 libxl__xs_mknod(gc, t,
795 GCSPRINTF("%s/device/suspend/event-channel",
796 dom_path),
797 rwperm, ARRAY_SIZE(rwperm));
798 } else {
799 libxl__xs_mknod(gc, t,
800 GCSPRINTF("%s/device", dom_path),
801 rwperm, ARRAY_SIZE(rwperm));
802 }
803
804 libxl__xs_mknod(gc, t,
805 GCSPRINTF("%s/control", dom_path),
806 roperm, ARRAY_SIZE(roperm));
807 if (info->type == LIBXL_DOMAIN_TYPE_HVM)
808 libxl__xs_mknod(gc, t,
809 GCSPRINTF("%s/hvmloader", dom_path),
810 roperm, ARRAY_SIZE(roperm));
811
812 libxl__xs_mknod(gc, t,
813 GCSPRINTF("%s/control/shutdown", dom_path),
814 rwperm, ARRAY_SIZE(rwperm));
815 libxl__xs_mknod(gc, t,
816 GCSPRINTF("%s/control/feature-poweroff", dom_path),
817 rwperm, ARRAY_SIZE(rwperm));
818 libxl__xs_mknod(gc, t,
819 GCSPRINTF("%s/control/feature-reboot", dom_path),
820 rwperm, ARRAY_SIZE(rwperm));
821 libxl__xs_mknod(gc, t,
822 GCSPRINTF("%s/control/feature-suspend", dom_path),
823 rwperm, ARRAY_SIZE(rwperm));
824 if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
825 libxl__xs_mknod(gc, t,
826 GCSPRINTF("%s/control/feature-s3", dom_path),
827 rwperm, ARRAY_SIZE(rwperm));
828 libxl__xs_mknod(gc, t,
829 GCSPRINTF("%s/control/feature-s4", dom_path),
830 rwperm, ARRAY_SIZE(rwperm));
831 }
832 libxl__xs_mknod(gc, t,
833 GCSPRINTF("%s/control/sysrq", dom_path),
834 rwperm, ARRAY_SIZE(rwperm));
835
836 libxl__xs_mknod(gc, t,
837 GCSPRINTF("%s/data", dom_path),
838 rwperm, ARRAY_SIZE(rwperm));
839 libxl__xs_mknod(gc, t,
840 GCSPRINTF("%s/drivers", dom_path),
841 rwperm, ARRAY_SIZE(rwperm));
842 libxl__xs_mknod(gc, t,
843 GCSPRINTF("%s/feature", dom_path),
844 rwperm, ARRAY_SIZE(rwperm));
845 libxl__xs_mknod(gc, t,
846 GCSPRINTF("%s/attr", dom_path),
847 rwperm, ARRAY_SIZE(rwperm));
848 libxl__xs_mknod(gc, t,
849 GCSPRINTF("%s/error", dom_path),
850 rwperm, ARRAY_SIZE(rwperm));
851
852 if (libxl_defbool_val(info->driver_domain)) {
853 /*
854 * Create a local "libxl" directory for each guest, since we might want
855 * to use libxl from inside the guest
856 */
857 libxl__xs_mknod(gc, t, GCSPRINTF("%s/libxl", dom_path), rwperm,
858 ARRAY_SIZE(rwperm));
859 /*
860 * Create a local "device-model" directory for each guest, since we
861 * might want to use Qemu from inside the guest
862 */
863 libxl__xs_mknod(gc, t, GCSPRINTF("%s/device-model", dom_path), rwperm,
864 ARRAY_SIZE(rwperm));
865 }
866
867 vm_list = libxl_list_vm(ctx, &nb_vm);
868 if (!vm_list) {
869 LOGD(ERROR, *domid, "cannot get number of running guests");
870 rc = ERROR_FAIL;
871 goto out;
872 }
873 libxl_vminfo_list_free(vm_list, nb_vm);
874
875 xs_write(ctx->xsh, t, GCSPRINTF("%s/uuid", vm_path), uuid_string, strlen(uuid_string));
876 xs_write(ctx->xsh, t, GCSPRINTF("%s/name", vm_path), info->name, strlen(info->name));
877
878 libxl__xs_writev(gc, t, dom_path, info->xsdata);
879 libxl__xs_writev(gc, t, GCSPRINTF("%s/platform", dom_path), info->platformdata);
880
881 xs_write(ctx->xsh, t, GCSPRINTF("%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
882 xs_write(ctx->xsh, t, GCSPRINTF("%s/control/platform-feature-xs_reset_watches", dom_path), "1", 1);
883
884 dom_type = libxl_domain_type_to_string(info->type);
885 xs_write(ctx->xsh, t, GCSPRINTF("%s/type", libxl_path), dom_type,
886 strlen(dom_type));
887
888 if (!xs_transaction_end(ctx->xsh, t, 0)) {
889 if (errno == EAGAIN) {
890 t = 0;
891 goto retry_transaction;
892 }
893 LOGED(ERROR, *domid, "domain creation ""xenstore transaction commit failed");
894 rc = ERROR_FAIL;
895 goto out;
896 }
897 t = 0;
898
899 rc = 0;
900 out:
901 if (t) xs_transaction_end(ctx->xsh, t, 1);
902 return rc;
903 }
904
store_libxl_entry(libxl__gc * gc,uint32_t domid,libxl_domain_build_info * b_info)905 static int store_libxl_entry(libxl__gc *gc, uint32_t domid,
906 libxl_domain_build_info *b_info)
907 {
908 char *path = NULL;
909
910 path = libxl__xs_libxl_path(gc, domid);
911 path = GCSPRINTF("%s/dm-version", path);
912 return libxl__xs_printf(gc, XBT_NULL, path, "%s",
913 libxl_device_model_version_to_string(b_info->device_model_version));
914 }
915
libxl__domain_build_state_init(libxl__domain_build_state * state)916 void libxl__domain_build_state_init(libxl__domain_build_state *state)
917 {
918 state->dm_monitor_fd = -1;
919 }
920
libxl__domain_build_state_dispose(libxl__domain_build_state * state)921 void libxl__domain_build_state_dispose(libxl__domain_build_state *state)
922 {
923 libxl__file_reference_unmap(&state->pv_kernel);
924 libxl__file_reference_unmap(&state->pv_ramdisk);
925 if (state->dm_monitor_fd >= 0) {
926 close(state->dm_monitor_fd);
927 state->dm_monitor_fd = -1;
928 }
929 }
930
931 /*----- main domain creation -----*/
932
933 /* We have a linear control flow; only one event callback is
934 * outstanding at any time. Each initiation and callback function
935 * arranges for the next to be called, as the very last thing it
936 * does. (If that particular sub-operation is not needed, a
937 * function will call the next event callback directly.)
938 */
939
940 /* Event callbacks, in this order: */
941 static void domcreate_bootloader_console_available(libxl__egc *egc,
942 libxl__bootloader_state *bl);
943 static void domcreate_console_available(libxl__egc *egc,
944 libxl__domain_create_state *dcs);
945
946 static void domcreate_bootloader_done(libxl__egc *egc,
947 libxl__bootloader_state *bl,
948 int rc);
949 static void libxl__colo_restore_setup_done(libxl__egc *egc,
950 libxl__colo_restore_state *crs,
951 int rc);
952 static void domcreate_stream_done(libxl__egc *egc,
953 libxl__stream_read_state *srs,
954 int ret);
955 static void domcreate_rebuild_done(libxl__egc *egc,
956 libxl__domain_create_state *dcs,
957 int ret);
958 static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *aodevs,
959 int ret);
960 static void domcreate_devmodel_started(libxl__egc *egc,
961 libxl__dm_spawn_state *dmss,
962 int rc);
963 static void domcreate_attach_devices(libxl__egc *egc,
964 libxl__multidev *multidev,
965 int ret);
966 static void console_xswait_callback(libxl__egc *egc, libxl__xswait_state *xswa,
967 int rc, const char *p);
968
969 /* Our own function to clean up and call the user's callback.
970 * The final call in the sequence. */
971 static void domcreate_complete(libxl__egc *egc,
972 libxl__domain_create_state *dcs,
973 int rc);
974
975 /* If creation is not successful, this callback will be executed
976 * when domain destruction is finished */
977 static void domcreate_destruction_cb(libxl__egc *egc,
978 libxl__domain_destroy_state *dds,
979 int rc);
980
ok_to_default_memkb_in_create(libxl__gc * gc)981 static bool ok_to_default_memkb_in_create(libxl__gc *gc)
982 {
983 /*
984 * This is a fudge. We are trying to find whether the caller
985 * calls the old version of libxl_domain_need_memory. If they do
986 * then, because it only gets the b_info, and because it can't
987 * update the b_info (because it's const), it will base its
988 * calculations on defaulting shadow_memkb and iommu_memkb to 0
989 * In that case we probably shouldn't default them differently
990 * during libxl_domain_create.
991 *
992 * The result is that the behaviour with old callers is the same
993 * as in 4.13: no additional memory is allocated for shadow and
994 * iommu (unless the caller set shadow_memkb, eg from a call to
995 * libxl_get_required_shadow_memory).
996 */
997 return !CTX->libxl_domain_need_memory_0x041200_called ||
998 CTX->libxl_domain_need_memory_called;
999 /*
1000 * Treat mixed callers as new callers. Presumably they know what
1001 * they are doing.
1002 */
1003 }
1004
libxl__get_required_iommu_memory(unsigned long maxmem_kb)1005 static unsigned long libxl__get_required_iommu_memory(unsigned long maxmem_kb)
1006 {
1007 unsigned long iommu_pages = 0, mem_pages = maxmem_kb / 4;
1008 unsigned int level;
1009
1010 /* Assume a 4 level page table with 512 entries per level */
1011 for (level = 0; level < 4; level++)
1012 {
1013 mem_pages = DIV_ROUNDUP(mem_pages, 512);
1014 iommu_pages += mem_pages;
1015 }
1016
1017 return iommu_pages * 4;
1018 }
1019
libxl__domain_config_setdefault(libxl__gc * gc,libxl_domain_config * d_config,uint32_t domid)1020 int libxl__domain_config_setdefault(libxl__gc *gc,
1021 libxl_domain_config *d_config,
1022 uint32_t domid /* for logging, only */)
1023 {
1024 libxl_ctx *ctx = libxl__gc_owner(gc);
1025 int ret;
1026 bool pod_enabled = false;
1027 libxl_domain_create_info *c_info = &d_config->c_info;
1028
1029 libxl_physinfo physinfo;
1030 ret = libxl_get_physinfo(CTX, &physinfo);
1031 if (ret) goto error_out;
1032
1033 if (d_config->c_info.ssid_label) {
1034 char *s = d_config->c_info.ssid_label;
1035 ret = libxl_flask_context_to_sid(ctx, s, strlen(s),
1036 &d_config->c_info.ssidref);
1037 if (ret) {
1038 if (errno == ENOSYS) {
1039 LOGD(WARN, domid, "XSM Disabled: init_seclabel not supported");
1040 ret = 0;
1041 } else {
1042 LOGD(ERROR, domid, "Invalid init_seclabel: %s", s);
1043 goto error_out;
1044 }
1045 }
1046 }
1047
1048 if (d_config->b_info.exec_ssid_label) {
1049 char *s = d_config->b_info.exec_ssid_label;
1050 ret = libxl_flask_context_to_sid(ctx, s, strlen(s),
1051 &d_config->b_info.exec_ssidref);
1052 if (ret) {
1053 if (errno == ENOSYS) {
1054 LOGD(WARN, domid, "XSM Disabled: seclabel not supported");
1055 ret = 0;
1056 } else {
1057 LOGD(ERROR, domid, "Invalid seclabel: %s", s);
1058 goto error_out;
1059 }
1060 }
1061 }
1062
1063 if (d_config->b_info.device_model_ssid_label) {
1064 char *s = d_config->b_info.device_model_ssid_label;
1065 ret = libxl_flask_context_to_sid(ctx, s, strlen(s),
1066 &d_config->b_info.device_model_ssidref);
1067 if (ret) {
1068 if (errno == ENOSYS) {
1069 LOGD(WARN, domid,
1070 "XSM Disabled: device_model_stubdomain_seclabel not supported");
1071 ret = 0;
1072 } else {
1073 LOGD(ERROR, domid, "Invalid device_model_stubdomain_seclabel: %s", s);
1074 goto error_out;
1075 }
1076 }
1077 }
1078
1079 if (d_config->c_info.pool_name) {
1080 d_config->c_info.poolid = -1;
1081 libxl_cpupool_qualifier_to_cpupoolid(ctx, d_config->c_info.pool_name,
1082 &d_config->c_info.poolid,
1083 NULL);
1084 }
1085 if (!libxl_cpupoolid_is_valid(ctx, d_config->c_info.poolid)) {
1086 LOGD(ERROR, domid, "Illegal pool specified: %s",
1087 d_config->c_info.pool_name);
1088 ret = ERROR_INVAL;
1089 goto error_out;
1090 }
1091
1092 ret = libxl__domain_create_info_setdefault(gc, &d_config->c_info,
1093 &physinfo);
1094 if (ret) {
1095 LOGD(ERROR, domid, "Unable to set domain create info defaults");
1096 goto error_out;
1097 }
1098
1099 bool need_pt = d_config->num_pcidevs || d_config->num_dtdevs;
1100 if (c_info->passthrough == LIBXL_PASSTHROUGH_DEFAULT) {
1101 c_info->passthrough = need_pt
1102 ? LIBXL_PASSTHROUGH_ENABLED : LIBXL_PASSTHROUGH_DISABLED;
1103 }
1104
1105 bool iommu_enabled = physinfo.cap_hvm_directio;
1106 if (c_info->passthrough != LIBXL_PASSTHROUGH_DISABLED && !iommu_enabled) {
1107 LOGD(ERROR, domid,
1108 "passthrough not supported on this platform\n");
1109 ret = ERROR_INVAL;
1110 goto error_out;
1111 }
1112
1113 if (c_info->passthrough == LIBXL_PASSTHROUGH_DISABLED && need_pt) {
1114 LOGD(ERROR, domid,
1115 "passthrough disabled but devices are specified");
1116 ret = ERROR_INVAL;
1117 goto error_out;
1118 }
1119
1120 ret = libxl__arch_passthrough_mode_setdefault(gc,domid,d_config,&physinfo);
1121 if (ret) goto error_out;
1122
1123 /* An explicit setting should now have been chosen */
1124 assert(c_info->passthrough != LIBXL_PASSTHROUGH_DEFAULT);
1125 assert(c_info->passthrough != LIBXL_PASSTHROUGH_ENABLED);
1126
1127 /* If target_memkb is smaller than max_memkb, the subsequent call
1128 * to libxc when building HVM domain will enable PoD mode.
1129 */
1130 pod_enabled = (d_config->c_info.type != LIBXL_DOMAIN_TYPE_PV) &&
1131 (d_config->b_info.target_memkb < d_config->b_info.max_memkb);
1132
1133 /* We cannot have PoD and PCI device assignment at the same time
1134 * for HVM guest. It was reported that IOMMU cannot work with PoD
1135 * enabled because it needs to populated entire page table for
1136 * guest. To stay on the safe side, we disable PCI device
1137 * assignment when PoD is enabled.
1138 */
1139 if (d_config->c_info.type != LIBXL_DOMAIN_TYPE_PV &&
1140 d_config->num_pcidevs && pod_enabled) {
1141 ret = ERROR_INVAL;
1142 LOGD(ERROR, domid,
1143 "PCI device assignment for HVM guest failed due to PoD enabled");
1144 goto error_out;
1145 }
1146
1147 /* Disallow PoD and vNUMA to be enabled at the same time because PoD
1148 * pool is not vNUMA-aware yet.
1149 */
1150 if (pod_enabled && d_config->b_info.num_vnuma_nodes) {
1151 ret = ERROR_INVAL;
1152 LOGD(ERROR, domid, "Cannot enable PoD and vNUMA at the same time");
1153 goto error_out;
1154 }
1155
1156 /* PV vNUMA is not yet supported because there is an issue with
1157 * cpuid handling.
1158 */
1159 if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_PV &&
1160 d_config->b_info.num_vnuma_nodes) {
1161 ret = ERROR_INVAL;
1162 LOGD(ERROR, domid, "PV vNUMA is not yet supported");
1163 goto error_out;
1164 }
1165
1166 if (d_config->b_info.shadow_memkb == LIBXL_MEMKB_DEFAULT
1167 && ok_to_default_memkb_in_create(gc))
1168 d_config->b_info.shadow_memkb =
1169 libxl_get_required_shadow_memory(d_config->b_info.max_memkb,
1170 d_config->b_info.max_vcpus);
1171
1172 /* No IOMMU reservation is needed if passthrough mode is not 'sync_pt' */
1173 if (d_config->b_info.iommu_memkb == LIBXL_MEMKB_DEFAULT
1174 && ok_to_default_memkb_in_create(gc))
1175 d_config->b_info.iommu_memkb =
1176 (d_config->c_info.passthrough == LIBXL_PASSTHROUGH_SYNC_PT)
1177 ? libxl__get_required_iommu_memory(d_config->b_info.max_memkb)
1178 : 0;
1179
1180 ret = libxl__domain_build_info_setdefault(gc, &d_config->b_info);
1181 if (ret) {
1182 LOGD(ERROR, domid, "Unable to set domain build info defaults");
1183 goto error_out;
1184 }
1185
1186 if (d_config->c_info.type != LIBXL_DOMAIN_TYPE_PV &&
1187 (libxl_defbool_val(d_config->b_info.nested_hvm) &&
1188 ((d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM &&
1189 libxl_defbool_val(d_config->b_info.u.hvm.altp2m)) ||
1190 (d_config->b_info.altp2m != LIBXL_ALTP2M_MODE_DISABLED)))) {
1191 ret = ERROR_INVAL;
1192 LOGD(ERROR, domid, "nestedhvm and altp2mhvm cannot be used together");
1193 goto error_out;
1194 }
1195
1196 if (((d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM &&
1197 libxl_defbool_val(d_config->b_info.u.hvm.altp2m)) ||
1198 (d_config->c_info.type != LIBXL_DOMAIN_TYPE_PV &&
1199 d_config->b_info.altp2m != LIBXL_ALTP2M_MODE_DISABLED)) &&
1200 pod_enabled) {
1201 ret = ERROR_INVAL;
1202 LOGD(ERROR, domid, "Cannot enable PoD and ALTP2M at the same time");
1203 goto error_out;
1204 }
1205
1206 ret = 0;
1207 error_out:
1208 return ret;
1209 }
1210
initiate_domain_create(libxl__egc * egc,libxl__domain_create_state * dcs)1211 static void initiate_domain_create(libxl__egc *egc,
1212 libxl__domain_create_state *dcs)
1213 {
1214 STATE_AO_GC(dcs->ao);
1215 uint32_t domid;
1216 int i, ret;
1217
1218 /* convenience aliases */
1219 libxl_domain_config *const d_config = dcs->guest_config;
1220 libxl__domain_build_state *dbs = &dcs->build_state;
1221
1222 libxl__xswait_init(&dcs->console_xswait);
1223
1224 domid = dcs->domid;
1225 libxl__domain_build_state_init(dbs);
1226 dbs->restore = dcs->restore_fd >= 0;
1227
1228 ret = libxl__domain_config_setdefault(gc,d_config,domid);
1229 if (ret) goto error_out;
1230
1231 ret = libxl__domain_make(gc, d_config, dbs, &domid, dcs->soft_reset);
1232 if (ret) {
1233 LOGD(ERROR, domid, "cannot make domain: %d", ret);
1234 dcs->guest_domid = domid;
1235 ret = ERROR_FAIL;
1236 goto error_out;
1237 }
1238
1239 dcs->guest_domid = domid;
1240 dcs->sdss.dm.guest_domid = 0; /* means we haven't spawned */
1241
1242 /* post-4.13 todo: move these next bits of defaulting to
1243 * libxl__domain_config_setdefault */
1244
1245 /*
1246 * Set the dm version quite early so that libxl doesn't have to pass the
1247 * build info around just to know if the domain has a device model or not.
1248 */
1249 store_libxl_entry(gc, domid, &d_config->b_info);
1250
1251 for (i = 0; i < d_config->num_disks; i++) {
1252 ret = libxl__disk_devtype.set_default(gc, domid, &d_config->disks[i],
1253 false);
1254 if (ret) {
1255 LOGD(ERROR, domid, "Unable to set disk defaults for disk %d", i);
1256 goto error_out;
1257 }
1258 }
1259
1260 dcs->bl.ao = ao;
1261 libxl_device_disk *bootdisk =
1262 d_config->num_disks > 0 ? &d_config->disks[0] : NULL;
1263
1264 /*
1265 * The devid has to be set before launching the device model. For the
1266 * hotplug case this is done in libxl_device_nic_add but on domain
1267 * creation this is called too late.
1268 * Make two runs over configured NICs in order to avoid duplicate IDs
1269 * in case the caller partially assigned IDs.
1270 */
1271 ret = libxl__device_nic_set_devids(gc, d_config, domid);
1272 if (ret)
1273 goto error_out;
1274
1275 if (dbs->restore || dcs->soft_reset) {
1276 LOGD(DEBUG, domid, "restoring, not running bootloader");
1277 domcreate_bootloader_done(egc, &dcs->bl, 0);
1278 } else {
1279 LOGD(DEBUG, domid, "running bootloader");
1280 dcs->bl.callback = domcreate_bootloader_done;
1281 dcs->bl.console_available = domcreate_bootloader_console_available;
1282 dcs->bl.info = &d_config->b_info;
1283 dcs->bl.disk = bootdisk;
1284 dcs->bl.domid = dcs->guest_domid;
1285
1286 dcs->bl.kernel = &dbs->pv_kernel;
1287 dcs->bl.ramdisk = &dbs->pv_ramdisk;
1288
1289 libxl__bootloader_run(egc, &dcs->bl);
1290 }
1291 return;
1292
1293 error_out:
1294 assert(ret);
1295 domcreate_complete(egc, dcs, ret);
1296 }
1297
domcreate_bootloader_console_available(libxl__egc * egc,libxl__bootloader_state * bl)1298 static void domcreate_bootloader_console_available(libxl__egc *egc,
1299 libxl__bootloader_state *bl)
1300 {
1301 libxl__domain_create_state *dcs = CONTAINER_OF(bl, *dcs, bl);
1302 STATE_AO_GC(bl->ao);
1303 domcreate_console_available(egc, dcs);
1304 }
1305
domcreate_console_available(libxl__egc * egc,libxl__domain_create_state * dcs)1306 static void domcreate_console_available(libxl__egc *egc,
1307 libxl__domain_create_state *dcs) {
1308 libxl__ao_progress_report(egc, dcs->ao, &dcs->aop_console_how,
1309 NEW_EVENT(egc, DOMAIN_CREATE_CONSOLE_AVAILABLE,
1310 dcs->guest_domid,
1311 dcs->aop_console_how.for_event));
1312 }
1313
domcreate_bootloader_done(libxl__egc * egc,libxl__bootloader_state * bl,int rc)1314 static void domcreate_bootloader_done(libxl__egc *egc,
1315 libxl__bootloader_state *bl,
1316 int rc)
1317 {
1318 libxl__domain_create_state *dcs = CONTAINER_OF(bl, *dcs, bl);
1319 STATE_AO_GC(bl->ao);
1320
1321 /* convenience aliases */
1322 const uint32_t domid = dcs->guest_domid;
1323 libxl_domain_config *const d_config = dcs->guest_config;
1324 const int restore_fd = dcs->restore_fd;
1325 libxl__domain_build_state *const state = &dcs->build_state;
1326 const int checkpointed_stream = dcs->restore_params.checkpointed_stream;
1327 libxl__colo_restore_state *const crs = &dcs->crs;
1328 libxl_domain_build_info *const info = &d_config->b_info;
1329 libxl__srm_restore_autogen_callbacks *const callbacks =
1330 &dcs->srs.shs.callbacks.restore.a;
1331
1332 if (rc) {
1333 domcreate_rebuild_done(egc, dcs, rc);
1334 return;
1335 }
1336
1337 /* consume bootloader outputs. state->pv_{kernel,ramdisk} have
1338 * been initialised by the bootloader already.
1339 */
1340 state->pv_cmdline = bl->cmdline;
1341
1342 /* We might be going to call libxl__spawn_local_dm, or _spawn_stub_dm.
1343 * Fill in any field required by either, including both relevant
1344 * callbacks (_spawn_stub_dm will overwrite our trespass if needed). */
1345 dcs->sdss.dm.spawn.ao = ao;
1346 dcs->sdss.dm.guest_config = dcs->guest_config;
1347 dcs->sdss.dm.build_state = &dcs->build_state;
1348 dcs->sdss.dm.callback = domcreate_devmodel_started;
1349 dcs->sdss.callback = domcreate_devmodel_started;
1350
1351 if (restore_fd < 0 && !dcs->soft_reset) {
1352 rc = libxl__domain_build(gc, d_config, domid, state);
1353 domcreate_rebuild_done(egc, dcs, rc);
1354 return;
1355 }
1356
1357 /* Prepare environment for domcreate_stream_done */
1358 dcs->srs.dcs = dcs;
1359
1360 /* Restore */
1361 callbacks->static_data_done = libxl__srm_callout_callback_static_data_done;
1362 callbacks->restore_results = libxl__srm_callout_callback_restore_results;
1363
1364 /* COLO only supports HVM now because it does not work very
1365 * well with pv drivers:
1366 * 1. We need to resume vm in the slow path. In this case we
1367 * need to disconnect/reconnect backend and frontend. It
1368 * will take too much time and the performance is very slow.
1369 * 2. PV disk cannot reuse block replication that is implemented
1370 * in QEMU.
1371 */
1372 if (info->type != LIBXL_DOMAIN_TYPE_HVM &&
1373 checkpointed_stream == LIBXL_CHECKPOINTED_STREAM_COLO) {
1374 LOGD(ERROR, domid, "COLO only supports HVM, unable to restore domain");
1375 rc = ERROR_FAIL;
1376 goto out;
1377 }
1378
1379 rc = libxl__build_pre(gc, domid, d_config, state);
1380 if (rc)
1381 goto out;
1382
1383 dcs->srs.ao = ao;
1384 dcs->srs.fd = restore_fd;
1385 dcs->srs.legacy = (dcs->restore_params.stream_version == 1);
1386 dcs->srs.back_channel = false;
1387 dcs->srs.completion_callback = domcreate_stream_done;
1388
1389 if (restore_fd >= 0) {
1390 switch (checkpointed_stream) {
1391 case LIBXL_CHECKPOINTED_STREAM_COLO:
1392 /* colo restore setup */
1393 crs->ao = ao;
1394 crs->domid = domid;
1395 crs->send_back_fd = dcs->send_back_fd;
1396 crs->recv_fd = restore_fd;
1397 crs->hvm = (info->type != LIBXL_DOMAIN_TYPE_PV);
1398 crs->callback = libxl__colo_restore_setup_done;
1399 libxl__colo_restore_setup(egc, crs);
1400 break;
1401 case LIBXL_CHECKPOINTED_STREAM_REMUS:
1402 libxl__remus_restore_setup(egc, dcs);
1403 /* fall through */
1404 case LIBXL_CHECKPOINTED_STREAM_NONE:
1405 libxl__stream_read_start(egc, &dcs->srs);
1406 }
1407 return;
1408 }
1409
1410 out:
1411 domcreate_stream_done(egc, &dcs->srs, rc);
1412 }
1413
libxl__colo_restore_setup_done(libxl__egc * egc,libxl__colo_restore_state * crs,int rc)1414 static void libxl__colo_restore_setup_done(libxl__egc *egc,
1415 libxl__colo_restore_state *crs,
1416 int rc)
1417 {
1418 libxl__domain_create_state *dcs = CONTAINER_OF(crs, *dcs, crs);
1419
1420 EGC_GC;
1421
1422 if (rc) {
1423 LOGD(ERROR, dcs->guest_domid, "colo restore setup fails: %d", rc);
1424 domcreate_stream_done(egc, &dcs->srs, rc);
1425 return;
1426 }
1427
1428 libxl__stream_read_start(egc, &dcs->srs);
1429 }
1430
libxl__srm_callout_callback_static_data_done(unsigned int missing,void * user)1431 int libxl__srm_callout_callback_static_data_done(unsigned int missing,
1432 void *user)
1433 {
1434 libxl__save_helper_state *shs = user;
1435 libxl__domain_create_state *dcs = shs->caller_state;
1436 STATE_AO_GC(dcs->ao);
1437 libxl_ctx *ctx = libxl__gc_owner(gc);
1438
1439 libxl_domain_config *d_config = dcs->guest_config;
1440 libxl_domain_build_info *info = &d_config->b_info;
1441
1442 /*
1443 * CPUID/MSR information is not present in pre Xen-4.14 streams.
1444 *
1445 * Libxl used to always regenerate the CPUID policy from first principles
1446 * on migrate. Continue to do so for backwards compatibility when the
1447 * stream doesn't contain any CPUID data.
1448 */
1449 if (missing & XGR_SDD_MISSING_CPUID)
1450 libxl__cpuid_legacy(ctx, dcs->guest_domid, true, info);
1451
1452 return 0;
1453 }
1454
libxl__srm_callout_callback_restore_results(xen_pfn_t store_mfn,xen_pfn_t console_mfn,void * user)1455 void libxl__srm_callout_callback_restore_results(xen_pfn_t store_mfn,
1456 xen_pfn_t console_mfn, void *user)
1457 {
1458 libxl__save_helper_state *shs = user;
1459 libxl__domain_create_state *dcs = shs->caller_state;
1460 STATE_AO_GC(dcs->ao);
1461 libxl__domain_build_state *const state = &dcs->build_state;
1462
1463 state->store_mfn = store_mfn;
1464 state->console_mfn = console_mfn;
1465 shs->need_results = 0;
1466 }
1467
domcreate_stream_done(libxl__egc * egc,libxl__stream_read_state * srs,int ret)1468 static void domcreate_stream_done(libxl__egc *egc,
1469 libxl__stream_read_state *srs,
1470 int ret)
1471 {
1472 /* NB perhaps only srs->dcs is valid; eg in the case of an
1473 * early branch to domcreate_bootloader_done's `out' block */
1474 libxl__domain_create_state *dcs = srs->dcs;
1475 STATE_AO_GC(dcs->ao);
1476 libxl_ctx *ctx = libxl__gc_owner(gc);
1477 char **vments = NULL, **localents = NULL;
1478 struct timeval start_time;
1479 int i, esave;
1480
1481 /* convenience aliases */
1482 const uint32_t domid = dcs->guest_domid;
1483 libxl_domain_config *const d_config = dcs->guest_config;
1484 libxl_domain_build_info *const info = &d_config->b_info;
1485 libxl__domain_build_state *const state = &dcs->build_state;
1486 const int fd = dcs->restore_fd;
1487
1488 if (ret)
1489 goto out;
1490
1491 gettimeofday(&start_time, NULL);
1492
1493 switch (info->type) {
1494 case LIBXL_DOMAIN_TYPE_HVM:
1495 vments = libxl__calloc(gc, 7, sizeof(char *));
1496 vments[0] = "rtc/timeoffset";
1497 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
1498 vments[2] = "image/ostype";
1499 vments[3] = "hvm";
1500 vments[4] = "start_time";
1501 vments[5] = GCSPRINTF("%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
1502 break;
1503 case LIBXL_DOMAIN_TYPE_PV:
1504 vments = libxl__calloc(gc, 11, sizeof(char *));
1505 i = 0;
1506 vments[i++] = "image/ostype";
1507 vments[i++] = "linux";
1508 vments[i++] = "image/kernel";
1509 vments[i++] = (char *) state->pv_kernel.path;
1510 vments[i++] = "start_time";
1511 vments[i++] = GCSPRINTF("%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
1512 if (state->pv_ramdisk.path) {
1513 vments[i++] = "image/ramdisk";
1514 vments[i++] = (char *) state->pv_ramdisk.path;
1515 }
1516 if (state->pv_cmdline) {
1517 vments[i++] = "image/cmdline";
1518 vments[i++] = (char *) state->pv_cmdline;
1519 }
1520 break;
1521 case LIBXL_DOMAIN_TYPE_PVH:
1522 vments = libxl__calloc(gc, 3, sizeof(char *));
1523 vments[0] = "start_time";
1524 vments[1] = GCSPRINTF("%"PRIu64".%02ld",
1525 (uint64_t)start_time.tv_sec,
1526 (long)start_time.tv_usec/10000);
1527 break;
1528 default:
1529 ret = ERROR_INVAL;
1530 goto out;
1531 }
1532
1533 /*
1534 * The scheduler on the sending domain may be different than the
1535 * scheduler running here. Setting the scheduler to UNKNOWN will
1536 * cause the code to take to take whatever parameters are
1537 * available in that scheduler, while discarding the rest.
1538 */
1539 info->sched_params.sched = LIBXL_SCHEDULER_UNKNOWN;
1540
1541 ret = libxl__build_post(gc, domid, info, state, vments, localents);
1542 if (ret)
1543 goto out;
1544
1545 if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
1546 state->saved_state = GCSPRINTF(
1547 LIBXL_DEVICE_MODEL_RESTORE_FILE".%d", domid);
1548 }
1549
1550 out:
1551 if (info->type == LIBXL_DOMAIN_TYPE_PV) {
1552 libxl__file_reference_unmap(&state->pv_kernel);
1553 libxl__file_reference_unmap(&state->pv_ramdisk);
1554 }
1555
1556 /* fd == -1 here means we're doing soft reset. */
1557 if (fd != -1) {
1558 esave = errno;
1559 libxl_fd_set_nonblock(ctx, fd, 0);
1560 errno = esave;
1561 }
1562 domcreate_rebuild_done(egc, dcs, ret);
1563 }
1564
domcreate_rebuild_done(libxl__egc * egc,libxl__domain_create_state * dcs,int ret)1565 static void domcreate_rebuild_done(libxl__egc *egc,
1566 libxl__domain_create_state *dcs,
1567 int ret)
1568 {
1569 STATE_AO_GC(dcs->ao);
1570
1571 /* convenience aliases */
1572 const uint32_t domid = dcs->guest_domid;
1573 libxl_domain_config *const d_config = dcs->guest_config;
1574
1575 if (ret) {
1576 LOGD(ERROR, domid, "cannot (re-)build domain: %d", ret);
1577 ret = ERROR_FAIL;
1578 goto error_out;
1579 }
1580
1581 store_libxl_entry(gc, domid, &d_config->b_info);
1582
1583 libxl__multidev_begin(ao, &dcs->multidev);
1584 dcs->multidev.callback = domcreate_launch_dm;
1585 libxl__add_disks(egc, ao, domid, d_config, &dcs->multidev);
1586 libxl__multidev_prepared(egc, &dcs->multidev, 0);
1587
1588 return;
1589
1590 error_out:
1591 assert(ret);
1592 domcreate_complete(egc, dcs, ret);
1593 }
1594
domcreate_launch_dm(libxl__egc * egc,libxl__multidev * multidev,int ret)1595 static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
1596 int ret)
1597 {
1598 libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
1599 STATE_AO_GC(dcs->ao);
1600 int i;
1601
1602 /* convenience aliases */
1603 const uint32_t domid = dcs->guest_domid;
1604 libxl_domain_config *const d_config = dcs->guest_config;
1605 libxl__domain_build_state *const state = &dcs->build_state;
1606
1607 if (ret) {
1608 LOGD(ERROR, domid, "unable to add disk devices");
1609 goto error_out;
1610 }
1611
1612 for (i = 0; i < d_config->b_info.num_ioports; i++) {
1613 libxl_ioport_range *io = &d_config->b_info.ioports[i];
1614
1615 LOGD(DEBUG, domid, "ioports %"PRIx32"-%"PRIx32,
1616 io->first, io->first + io->number - 1);
1617
1618 ret = xc_domain_ioport_permission(CTX->xch, domid,
1619 io->first, io->number, 1);
1620 if (ret < 0) {
1621 LOGED(ERROR, domid,
1622 "failed give domain access to ioports %"PRIx32"-%"PRIx32,
1623 io->first, io->first + io->number - 1);
1624 ret = ERROR_FAIL;
1625 goto error_out;
1626 }
1627 }
1628
1629 for (i = 0; i < d_config->b_info.num_irqs; i++) {
1630 int irq = d_config->b_info.irqs[i];
1631
1632 LOGD(DEBUG, domid, "irq %d", irq);
1633
1634 ret = irq >= 0 ? libxl__arch_domain_map_irq(gc, domid, irq)
1635 : -EOVERFLOW;
1636 if (ret) {
1637 LOGED(ERROR, domid, "failed give domain access to irq %d", irq);
1638 ret = ERROR_FAIL;
1639 goto error_out;
1640 }
1641 }
1642
1643 for (i = 0; i < d_config->b_info.num_iomem; i++) {
1644 libxl_iomem_range *io = &d_config->b_info.iomem[i];
1645
1646 LOGD(DEBUG, domid, "iomem %"PRIx64"-%"PRIx64,
1647 io->start, io->start + io->number - 1);
1648
1649 ret = xc_domain_iomem_permission(CTX->xch, domid,
1650 io->start, io->number, 1);
1651 if (ret < 0) {
1652 LOGED(ERROR, domid,
1653 "failed give domain access to iomem range %"PRIx64"-%"PRIx64,
1654 io->start, io->start + io->number - 1);
1655 ret = ERROR_FAIL;
1656 goto error_out;
1657 }
1658 ret = xc_domain_memory_mapping(CTX->xch, domid,
1659 io->gfn, io->start,
1660 io->number, 1);
1661 if (ret < 0) {
1662 LOGED(ERROR, domid,
1663 "failed to map to domain iomem range %"PRIx64"-%"PRIx64
1664 " to guest address %"PRIx64,
1665 io->start, io->start + io->number - 1, io->gfn);
1666 ret = ERROR_FAIL;
1667 goto error_out;
1668 }
1669 }
1670
1671 /* For both HVM and PV the 0th console is a regular console. We
1672 map channels to IOEMU consoles starting at 1 */
1673 for (i = 0; i < d_config->num_channels; i++) {
1674 libxl__device_console console;
1675 libxl__device device;
1676 ret = libxl__init_console_from_channel(gc, &console, i + 1,
1677 &d_config->channels[i]);
1678 if ( ret ) {
1679 libxl__device_console_dispose(&console);
1680 goto error_out;
1681 }
1682 libxl__device_console_add(gc, domid, &console, NULL, &device);
1683 libxl__device_console_dispose(&console);
1684 }
1685
1686 for (i = 0; i < d_config->num_p9s; i++)
1687 libxl__device_add(gc, domid, &libxl__p9_devtype, &d_config->p9s[i]);
1688
1689 for (i = 0; i < d_config->num_pvcallsifs; i++)
1690 libxl__device_add(gc, domid, &libxl__pvcallsif_devtype,
1691 &d_config->pvcallsifs[i]);
1692
1693 switch (d_config->c_info.type) {
1694 case LIBXL_DOMAIN_TYPE_HVM:
1695 {
1696 libxl__device_console console;
1697 libxl__device device;
1698 libxl_device_vkb vkb;
1699
1700 init_console_info(gc, &console, 0);
1701 console.backend_domid = state->console_domid;
1702 libxl__device_console_add(gc, domid, &console, state, &device);
1703 libxl__device_console_dispose(&console);
1704
1705 if (libxl_defbool_val(d_config->b_info.u.hvm.vkb_device)) {
1706 libxl_device_vkb_init(&vkb);
1707 libxl__device_add(gc, domid, &libxl__vkb_devtype, &vkb);
1708 libxl_device_vkb_dispose(&vkb);
1709 }
1710
1711 dcs->sdss.dm.guest_domid = domid;
1712 if (libxl_defbool_val(d_config->b_info.device_model_stubdomain))
1713 libxl__spawn_stub_dm(egc, &dcs->sdss);
1714 else
1715 libxl__spawn_local_dm(egc, &dcs->sdss.dm);
1716
1717 /*
1718 * Handle the domain's (and the related stubdomain's) access to
1719 * the VGA framebuffer.
1720 */
1721 ret = libxl__grant_vga_iomem_permission(gc, domid, d_config);
1722 if ( ret )
1723 goto error_out;
1724
1725 return;
1726 }
1727 case LIBXL_DOMAIN_TYPE_PV:
1728 case LIBXL_DOMAIN_TYPE_PVH:
1729 {
1730 libxl__device_console console, vuart;
1731 libxl__device device;
1732
1733 for (i = 0; i < d_config->num_vfbs; i++) {
1734 libxl__device_add(gc, domid, &libxl__vfb_devtype,
1735 &d_config->vfbs[i]);
1736 }
1737
1738 for (i = 0; i < d_config->num_vkbs; i++) {
1739 libxl__device_add(gc, domid, &libxl__vkb_devtype,
1740 &d_config->vkbs[i]);
1741 }
1742
1743 if (d_config->b_info.arch_arm.vuart == LIBXL_VUART_TYPE_SBSA_UART) {
1744 init_console_info(gc, &vuart, 0);
1745 vuart.backend_domid = state->console_domid;
1746 libxl__device_vuart_add(gc, domid, &vuart, state);
1747 libxl__device_console_dispose(&vuart);
1748 }
1749
1750 init_console_info(gc, &console, 0);
1751 console.backend_domid = state->console_domid;
1752 libxl__device_console_add(gc, domid, &console, state, &device);
1753 libxl__device_console_dispose(&console);
1754
1755 ret = libxl__need_xenpv_qemu(gc, d_config);
1756 if (ret < 0)
1757 goto error_out;
1758 if (ret) {
1759 dcs->sdss.dm.guest_domid = domid;
1760 libxl__spawn_local_dm(egc, &dcs->sdss.dm);
1761 return;
1762 } else {
1763 assert(!dcs->sdss.dm.guest_domid);
1764 domcreate_devmodel_started(egc, &dcs->sdss.dm, 0);
1765 return;
1766 }
1767 }
1768 default:
1769 ret = ERROR_INVAL;
1770 goto error_out;
1771 }
1772 abort(); /* not reached */
1773
1774 error_out:
1775 assert(ret);
1776 domcreate_complete(egc, dcs, ret);
1777 }
1778
libxl__add_dtdevs(libxl__egc * egc,libxl__ao * ao,uint32_t domid,libxl_domain_config * d_config,libxl__multidev * multidev)1779 static void libxl__add_dtdevs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
1780 libxl_domain_config *d_config,
1781 libxl__multidev *multidev)
1782 {
1783 AO_GC;
1784 libxl__ao_device *aodev = libxl__multidev_prepare(multidev);
1785 int i, rc = 0;
1786
1787 for (i = 0; i < d_config->num_dtdevs; i++) {
1788 const libxl_device_dtdev *dtdev = &d_config->dtdevs[i];
1789
1790 LOGD(DEBUG, domid, "Assign device \"%s\" to domain", dtdev->path);
1791 rc = xc_assign_dt_device(CTX->xch, domid, dtdev->path);
1792 if (rc < 0) {
1793 LOGD(ERROR, domid, "xc_assign_dtdevice failed: %d", rc);
1794 goto out;
1795 }
1796 }
1797
1798 out:
1799 aodev->rc = rc;
1800 aodev->callback(egc, aodev);
1801 }
1802
1803 #define libxl_device_dtdev_list NULL
1804 #define libxl_device_dtdev_compare NULL
1805 #define libxl__device_from_dtdev NULL
1806 #define libxl__device_dtdev_setdefault NULL
1807 #define libxl__device_dtdev_update_devid NULL
1808 static DEFINE_DEVICE_TYPE_STRUCT(dtdev, NONE);
1809
1810 const libxl__device_type *device_type_tbl[] = {
1811 &libxl__disk_devtype,
1812 &libxl__nic_devtype,
1813 &libxl__vtpm_devtype,
1814 &libxl__usbctrl_devtype,
1815 &libxl__usbdev_devtype,
1816 &libxl__pcidev_devtype,
1817 &libxl__dtdev_devtype,
1818 &libxl__vdispl_devtype,
1819 &libxl__vsnd_devtype,
1820 NULL
1821 };
1822
domcreate_devmodel_started(libxl__egc * egc,libxl__dm_spawn_state * dmss,int ret)1823 static void domcreate_devmodel_started(libxl__egc *egc,
1824 libxl__dm_spawn_state *dmss,
1825 int ret)
1826 {
1827 libxl__domain_create_state *dcs = CONTAINER_OF(dmss, *dcs, sdss.dm);
1828 STATE_AO_GC(dmss->spawn.ao);
1829 int domid = dcs->guest_domid;
1830
1831 if (ret) {
1832 LOGD(ERROR, domid, "device model did not start: %d", ret);
1833 goto error_out;
1834 }
1835
1836 dcs->device_type_idx = -1;
1837 domcreate_attach_devices(egc, &dcs->multidev, 0);
1838 return;
1839
1840 error_out:
1841 assert(ret);
1842 domcreate_complete(egc, dcs, ret);
1843 }
1844
domcreate_attach_devices(libxl__egc * egc,libxl__multidev * multidev,int ret)1845 static void domcreate_attach_devices(libxl__egc *egc,
1846 libxl__multidev *multidev,
1847 int ret)
1848 {
1849 libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
1850 STATE_AO_GC(dcs->ao);
1851 int domid = dcs->guest_domid;
1852 libxl_domain_config *const d_config = dcs->guest_config;
1853 const libxl__device_type *dt;
1854 char *tty_path;
1855
1856 if (ret) {
1857 LOGD(ERROR, domid, "unable to add %s devices",
1858 libxl__device_kind_to_string(device_type_tbl[dcs->device_type_idx]->type));
1859 goto error_out;
1860 }
1861
1862 dcs->device_type_idx++;
1863 dt = device_type_tbl[dcs->device_type_idx];
1864 if (dt) {
1865 if (*libxl__device_type_get_num(dt, d_config) > 0 && !dt->skip_attach) {
1866 /* Attach devices */
1867 libxl__multidev_begin(ao, &dcs->multidev);
1868 dcs->multidev.callback = domcreate_attach_devices;
1869 dt->add(egc, ao, domid, d_config, &dcs->multidev);
1870 libxl__multidev_prepared(egc, &dcs->multidev, 0);
1871 return;
1872 }
1873
1874 domcreate_attach_devices(egc, &dcs->multidev, 0);
1875 return;
1876 }
1877
1878 ret = libxl__console_tty_path(gc, domid, 0, LIBXL_CONSOLE_TYPE_PV, &tty_path);
1879 if (ret) {
1880 LOG(ERROR, "failed to get domain %d console tty path",
1881 domid);
1882 goto error_out;
1883 }
1884
1885 dcs->console_xswait.ao = ao;
1886 dcs->console_xswait.what = GCSPRINTF("domain %d console tty", domid);
1887 dcs->console_xswait.path = tty_path;
1888 dcs->console_xswait.timeout_ms = LIBXL_INIT_TIMEOUT * 1000;
1889 dcs->console_xswait.callback = console_xswait_callback;
1890 ret = libxl__xswait_start(gc, &dcs->console_xswait);
1891 if (ret) {
1892 LOG(ERROR, "unable to set up watch for domain %d console tty path",
1893 domid);
1894 goto error_out;
1895 }
1896
1897 return;
1898
1899 error_out:
1900 assert(ret);
1901 domcreate_complete(egc, dcs, ret);
1902 }
1903
console_xswait_callback(libxl__egc * egc,libxl__xswait_state * xswa,int rc,const char * p)1904 static void console_xswait_callback(libxl__egc *egc, libxl__xswait_state *xswa,
1905 int rc, const char *p)
1906 {
1907 EGC_GC;
1908 libxl__domain_create_state *dcs = CONTAINER_OF(xswa, *dcs, console_xswait);
1909
1910 if (rc) {
1911 if (rc == ERROR_TIMEDOUT)
1912 LOG(ERROR, "%s: timed out", xswa->what);
1913 goto out;
1914 }
1915
1916 if (p && p[0] != '\0') {
1917 domcreate_console_available(egc, dcs);
1918 goto out;
1919 }
1920
1921 return;
1922
1923 out:
1924 libxl__xswait_stop(gc, xswa);
1925 domcreate_complete(egc, dcs, rc);
1926 }
1927
domcreate_complete(libxl__egc * egc,libxl__domain_create_state * dcs,int rc)1928 static void domcreate_complete(libxl__egc *egc,
1929 libxl__domain_create_state *dcs,
1930 int rc)
1931 {
1932 STATE_AO_GC(dcs->ao);
1933 libxl_domain_config *const d_config = dcs->guest_config;
1934 libxl_domain_config *d_config_saved = &dcs->guest_config_saved;
1935
1936 libxl__xswait_stop(gc, &dcs->console_xswait);
1937
1938 libxl__domain_build_state_dispose(&dcs->build_state);
1939
1940 if (!rc && d_config->b_info.exec_ssidref)
1941 rc = xc_flask_relabel_domain(CTX->xch, dcs->guest_domid, d_config->b_info.exec_ssidref);
1942
1943 bool retain_domain = !rc || rc == ERROR_ABORTED;
1944
1945 if (retain_domain) {
1946 libxl__flock *lock;
1947
1948 /* Note that we hold CTX lock at this point so only need to
1949 * take data store lock
1950 */
1951 lock = libxl__lock_domain_userdata(gc, dcs->guest_domid);
1952 if (!lock) {
1953 rc = ERROR_LOCK_FAIL;
1954 } else {
1955 libxl__update_domain_configuration(gc, d_config_saved, d_config);
1956 int cfg_rc = libxl__set_domain_configuration
1957 (gc, dcs->guest_domid, d_config_saved);
1958 if (!rc)
1959 rc = cfg_rc;
1960 libxl__unlock_file(lock);
1961 }
1962 }
1963
1964 libxl_domain_config_dispose(d_config_saved);
1965
1966 if (!retain_domain) {
1967 if (dcs->guest_domid > 0) {
1968 dcs->dds.ao = ao;
1969 dcs->dds.domid = dcs->guest_domid;
1970 dcs->dds.callback = domcreate_destruction_cb;
1971 libxl__domain_destroy(egc, &dcs->dds);
1972 return;
1973 }
1974 dcs->guest_domid = INVALID_DOMID;
1975 }
1976 dcs->callback(egc, dcs, rc, dcs->guest_domid);
1977 }
1978
domcreate_destruction_cb(libxl__egc * egc,libxl__domain_destroy_state * dds,int rc)1979 static void domcreate_destruction_cb(libxl__egc *egc,
1980 libxl__domain_destroy_state *dds,
1981 int rc)
1982 {
1983 STATE_AO_GC(dds->ao);
1984 libxl__domain_create_state *dcs = CONTAINER_OF(dds, *dcs, dds);
1985
1986 if (rc)
1987 LOGD(ERROR, dds->domid, "unable to destroy domain following failed creation");
1988
1989 dcs->callback(egc, dcs, ERROR_FAIL, dcs->guest_domid);
1990 }
1991
1992 /*----- application-facing domain creation interface -----*/
1993
1994 typedef struct {
1995 libxl__domain_create_state dcs;
1996 uint32_t *domid_out;
1997 } libxl__app_domain_create_state;
1998
1999 typedef struct {
2000 libxl__app_domain_create_state cdcs;
2001 libxl__domain_destroy_state dds;
2002 libxl__domain_save_state dss;
2003 char *toolstack_buf;
2004 uint32_t toolstack_len;
2005 } libxl__domain_soft_reset_state;
2006
2007 static void domain_create_cb(libxl__egc *egc,
2008 libxl__domain_create_state *dcs,
2009 int rc, uint32_t domid);
2010
do_domain_create(libxl_ctx * ctx,libxl_domain_config * d_config,uint32_t * domid,int restore_fd,int send_back_fd,const libxl_domain_restore_params * params,const libxl_asyncop_how * ao_how,const libxl_asyncprogress_how * aop_console_how)2011 static int do_domain_create(libxl_ctx *ctx, libxl_domain_config *d_config,
2012 uint32_t *domid, int restore_fd, int send_back_fd,
2013 const libxl_domain_restore_params *params,
2014 const libxl_asyncop_how *ao_how,
2015 const libxl_asyncprogress_how *aop_console_how)
2016 {
2017 AO_CREATE(ctx, 0, ao_how);
2018 libxl__app_domain_create_state *cdcs;
2019 int rc;
2020
2021 GCNEW(cdcs);
2022 cdcs->dcs.ao = ao;
2023 cdcs->dcs.guest_config = d_config;
2024 libxl_domain_config_init(&cdcs->dcs.guest_config_saved);
2025 libxl_domain_config_copy(ctx, &cdcs->dcs.guest_config_saved, d_config);
2026 cdcs->dcs.restore_fd = cdcs->dcs.libxc_fd = restore_fd;
2027 cdcs->dcs.send_back_fd = send_back_fd;
2028 if (restore_fd >= 0) {
2029 cdcs->dcs.restore_params = *params;
2030 rc = libxl__fd_flags_modify_save(gc, cdcs->dcs.restore_fd,
2031 ~(O_NONBLOCK|O_NDELAY), 0,
2032 &cdcs->dcs.restore_fdfl);
2033 if (rc < 0) goto out_err;
2034 }
2035 cdcs->dcs.callback = domain_create_cb;
2036 cdcs->dcs.domid = INVALID_DOMID;
2037 cdcs->dcs.soft_reset = false;
2038
2039 if (cdcs->dcs.restore_params.checkpointed_stream ==
2040 LIBXL_CHECKPOINTED_STREAM_COLO) {
2041 cdcs->dcs.colo_proxy_script =
2042 cdcs->dcs.restore_params.colo_proxy_script;
2043 cdcs->dcs.crs.cps.is_userspace_proxy =
2044 libxl_defbool_val(cdcs->dcs.restore_params.userspace_colo_proxy);
2045 } else {
2046 cdcs->dcs.colo_proxy_script = NULL;
2047 cdcs->dcs.crs.cps.is_userspace_proxy = false;
2048 }
2049
2050 libxl__ao_progress_gethow(&cdcs->dcs.aop_console_how, aop_console_how);
2051 cdcs->domid_out = domid;
2052
2053 initiate_domain_create(egc, &cdcs->dcs);
2054
2055 return AO_INPROGRESS;
2056
2057 out_err:
2058 return AO_CREATE_FAIL(rc);
2059
2060 }
2061
domain_soft_reset_cb(libxl__egc * egc,libxl__domain_destroy_state * dds,int rc)2062 static void domain_soft_reset_cb(libxl__egc *egc,
2063 libxl__domain_destroy_state *dds,
2064 int rc)
2065 {
2066 STATE_AO_GC(dds->ao);
2067 libxl__domain_soft_reset_state *srs = CONTAINER_OF(dds, *srs, dds);
2068 libxl__app_domain_create_state *cdcs = &srs->cdcs;
2069 char *savefile, *restorefile;
2070
2071 if (rc) {
2072 LOGD(ERROR, dds->domid, "destruction of domain failed.");
2073 goto error;
2074 }
2075
2076 cdcs->dcs.guest_domid = dds->domid;
2077 rc = libxl__restore_emulator_xenstore_data(&cdcs->dcs, srs->toolstack_buf,
2078 srs->toolstack_len);
2079 if (rc) {
2080 LOGD(ERROR, dds->domid, "failed to restore toolstack record.");
2081 goto error;
2082 }
2083
2084 if (cdcs->dcs.guest_config->b_info.type == LIBXL_DOMAIN_TYPE_HVM) {
2085 savefile = GCSPRINTF(LIBXL_DEVICE_MODEL_SAVE_FILE".%d", dds->domid);
2086 restorefile = GCSPRINTF(LIBXL_DEVICE_MODEL_RESTORE_FILE".%d",
2087 dds->domid);
2088 rc = rename(savefile, restorefile);
2089 if (rc) {
2090 LOGD(ERROR, dds->domid, "failed to rename dm save file.");
2091 goto error;
2092 }
2093 }
2094
2095 initiate_domain_create(egc, &cdcs->dcs);
2096 return;
2097
2098 error:
2099 domcreate_complete(egc, &cdcs->dcs, rc);
2100 }
2101
2102 static void soft_reset_dm_suspended(libxl__egc *egc,
2103 libxl__domain_suspend_state *dsps,
2104 int rc);
do_domain_soft_reset(libxl_ctx * ctx,libxl_domain_config * d_config,uint32_t domid,const libxl_asyncop_how * ao_how,const libxl_asyncprogress_how * aop_console_how)2105 static int do_domain_soft_reset(libxl_ctx *ctx,
2106 libxl_domain_config *d_config,
2107 uint32_t domid,
2108 const libxl_asyncop_how *ao_how,
2109 const libxl_asyncprogress_how
2110 *aop_console_how)
2111 {
2112 AO_CREATE(ctx, 0, ao_how);
2113 libxl__domain_soft_reset_state *srs;
2114 libxl__app_domain_create_state *cdcs;
2115 libxl__domain_create_state *dcs;
2116 libxl__domain_build_state *state;
2117 libxl__domain_save_state *dss;
2118 const char *console_tty, *xs_store_mfn, *xs_console_mfn;
2119 char *dom_path;
2120 uint32_t domid_out;
2121 int rc;
2122
2123 GCNEW(srs);
2124 cdcs = &srs->cdcs;
2125 dcs = &cdcs->dcs;
2126 state = &dcs->build_state;
2127 dss = &srs->dss;
2128
2129 srs->cdcs.dcs.ao = ao;
2130 srs->cdcs.dcs.guest_config = d_config;
2131 libxl_domain_config_init(&srs->cdcs.dcs.guest_config_saved);
2132 libxl_domain_config_copy(ctx, &srs->cdcs.dcs.guest_config_saved,
2133 d_config);
2134 cdcs->dcs.restore_fd = -1;
2135 cdcs->dcs.domid = domid;
2136 cdcs->dcs.soft_reset = true;
2137 cdcs->dcs.callback = domain_create_cb;
2138 libxl__ao_progress_gethow(&srs->cdcs.dcs.aop_console_how,
2139 aop_console_how);
2140 cdcs->domid_out = &domid_out;
2141
2142 dom_path = libxl__xs_get_dompath(gc, domid);
2143 if (!dom_path) {
2144 LOGD(ERROR, domid, "failed to read domain path");
2145 rc = ERROR_FAIL;
2146 goto out;
2147 }
2148
2149 rc = libxl__xs_read_checked(gc, XBT_NULL,
2150 GCSPRINTF("%s/store/ring-ref", dom_path),
2151 &xs_store_mfn);
2152 if (rc) {
2153 LOGD(ERROR, domid, "failed to read store/ring-ref.");
2154 goto out;
2155 }
2156 state->store_mfn = xs_store_mfn ? atol(xs_store_mfn): 0;
2157
2158 rc = libxl__xs_read_checked(gc, XBT_NULL,
2159 GCSPRINTF("%s/console/ring-ref", dom_path),
2160 &xs_console_mfn);
2161 if (rc) {
2162 LOGD(ERROR, domid, "failed to read console/ring-ref.");
2163 goto out;
2164 }
2165 state->console_mfn = xs_console_mfn ? atol(xs_console_mfn): 0;
2166
2167 rc = libxl__xs_read_mandatory(gc, XBT_NULL,
2168 GCSPRINTF("%s/console/tty", dom_path),
2169 &console_tty);
2170 if (rc) {
2171 LOGD(ERROR, domid, "failed to read console/tty.");
2172 goto out;
2173 }
2174 state->console_tty = libxl__strdup(gc, console_tty);
2175
2176 dss->ao = ao;
2177 dss->domid = dss->dsps.domid = domid;
2178 dss->dsps.dm_savefile = GCSPRINTF(LIBXL_DEVICE_MODEL_SAVE_FILE".%d",
2179 domid);
2180
2181 rc = libxl__save_emulator_xenstore_data(dss, &srs->toolstack_buf,
2182 &srs->toolstack_len);
2183 if (rc) {
2184 LOGD(ERROR, domid, "failed to save toolstack record.");
2185 goto out;
2186 }
2187
2188 dss->dsps.ao = ao;
2189 dss->dsps.callback_device_model_done = soft_reset_dm_suspended;
2190 libxl__domain_suspend_device_model(egc, &dss->dsps); /* must be last */
2191
2192 return AO_INPROGRESS;
2193
2194 out:
2195 return AO_CREATE_FAIL(rc);
2196 }
2197
soft_reset_dm_suspended(libxl__egc * egc,libxl__domain_suspend_state * dsps,int rc)2198 static void soft_reset_dm_suspended(libxl__egc *egc,
2199 libxl__domain_suspend_state *dsps,
2200 int rc)
2201 {
2202 STATE_AO_GC(dsps->ao);
2203 libxl__domain_soft_reset_state *srs =
2204 CONTAINER_OF(dsps, *srs, dss.dsps);
2205 libxl__app_domain_create_state *cdcs = &srs->cdcs;
2206
2207 /*
2208 * Ask all backends to disconnect by removing the domain from
2209 * xenstore. On the creation path the domain will be introduced to
2210 * xenstore again with probably different store/console/...
2211 * channels.
2212 */
2213 xs_release_domain(CTX->xsh, cdcs->dcs.domid);
2214
2215 srs->dds.ao = ao;
2216 srs->dds.domid = cdcs->dcs.domid;
2217 srs->dds.callback = domain_soft_reset_cb;
2218 srs->dds.soft_reset = true;
2219 libxl__domain_destroy(egc, &srs->dds);
2220 }
2221
domain_create_cb(libxl__egc * egc,libxl__domain_create_state * dcs,int rc,uint32_t domid)2222 static void domain_create_cb(libxl__egc *egc,
2223 libxl__domain_create_state *dcs,
2224 int rc, uint32_t domid)
2225 {
2226 libxl__app_domain_create_state *cdcs = CONTAINER_OF(dcs, *cdcs, dcs);
2227 int flrc;
2228 STATE_AO_GC(cdcs->dcs.ao);
2229
2230 *cdcs->domid_out = domid;
2231
2232 if (dcs->restore_fd >= 0) {
2233 flrc = libxl__fd_flags_restore(gc,
2234 dcs->restore_fd, dcs->restore_fdfl);
2235 /*
2236 * If restore has failed already then report that error not
2237 * this one.
2238 */
2239 if (flrc && !rc) rc = flrc;
2240 }
2241
2242 libxl__ao_complete(egc, ao, rc);
2243 }
2244
2245
set_disk_colo_restore(libxl_domain_config * d_config)2246 static void set_disk_colo_restore(libxl_domain_config *d_config)
2247 {
2248 int i;
2249
2250 for (i = 0; i < d_config->num_disks; i++)
2251 libxl_defbool_set(&d_config->disks[i].colo_restore_enable, true);
2252 }
2253
unset_disk_colo_restore(libxl_domain_config * d_config)2254 static void unset_disk_colo_restore(libxl_domain_config *d_config)
2255 {
2256 int i;
2257
2258 for (i = 0; i < d_config->num_disks; i++)
2259 libxl_defbool_set(&d_config->disks[i].colo_restore_enable, false);
2260 }
2261
libxl_domain_create_new(libxl_ctx * ctx,libxl_domain_config * d_config,uint32_t * domid,const libxl_asyncop_how * ao_how,const libxl_asyncprogress_how * aop_console_how)2262 int libxl_domain_create_new(libxl_ctx *ctx, libxl_domain_config *d_config,
2263 uint32_t *domid,
2264 const libxl_asyncop_how *ao_how,
2265 const libxl_asyncprogress_how *aop_console_how)
2266 {
2267 unset_disk_colo_restore(d_config);
2268 return do_domain_create(ctx, d_config, domid, -1, -1, NULL,
2269 ao_how, aop_console_how);
2270 }
2271
libxl_domain_create_restore(libxl_ctx * ctx,libxl_domain_config * d_config,uint32_t * domid,int restore_fd,int send_back_fd,const libxl_domain_restore_params * params,const libxl_asyncop_how * ao_how,const libxl_asyncprogress_how * aop_console_how)2272 int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_config,
2273 uint32_t *domid, int restore_fd,
2274 int send_back_fd,
2275 const libxl_domain_restore_params *params,
2276 const libxl_asyncop_how *ao_how,
2277 const libxl_asyncprogress_how *aop_console_how)
2278 {
2279 if (params->checkpointed_stream == LIBXL_CHECKPOINTED_STREAM_COLO) {
2280 set_disk_colo_restore(d_config);
2281 } else {
2282 unset_disk_colo_restore(d_config);
2283 }
2284
2285 return do_domain_create(ctx, d_config, domid, restore_fd, send_back_fd,
2286 params, ao_how, aop_console_how);
2287 }
2288
libxl_domain_soft_reset(libxl_ctx * ctx,libxl_domain_config * d_config,uint32_t domid,const libxl_asyncop_how * ao_how,const libxl_asyncprogress_how * aop_console_how)2289 int libxl_domain_soft_reset(libxl_ctx *ctx,
2290 libxl_domain_config *d_config,
2291 uint32_t domid,
2292 const libxl_asyncop_how *ao_how,
2293 const libxl_asyncprogress_how
2294 *aop_console_how)
2295 {
2296 libxl_domain_build_info *const info = &d_config->b_info;
2297
2298 if (info->type != LIBXL_DOMAIN_TYPE_HVM) return ERROR_INVAL;
2299
2300 return do_domain_soft_reset(ctx, d_config, domid, ao_how,
2301 aop_console_how);
2302 }
2303
2304 /*
2305 * Local variables:
2306 * mode: C
2307 * c-basic-offset: 4
2308 * indent-tabs-mode: nil
2309 * End:
2310 */
2311