1 /*
2 * qemu_command.c: QEMU command generation
3 *
4 * Copyright (C) 2006-2016 Red Hat, Inc.
5 * Copyright (C) 2006 Daniel P. Berrange
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23
24 #include "qemu_command.h"
25 #include "qemu_hostdev.h"
26 #include "qemu_capabilities.h"
27 #include "qemu_dbus.h"
28 #include "qemu_interface.h"
29 #include "qemu_alias.h"
30 #include "qemu_security.h"
31 #include "qemu_slirp.h"
32 #include "qemu_block.h"
33 #include "cpu/cpu.h"
34 #include "viralloc.h"
35 #include "virlog.h"
36 #include "virarch.h"
37 #include "virerror.h"
38 #include "virfile.h"
39 #include "virnetdev.h"
40 #include "virnetdevbridge.h"
41 #include "virqemu.h"
42 #include "virstring.h"
43 #include "virtime.h"
44 #include "viruuid.h"
45 #include "domain_nwfilter.h"
46 #include "domain_addr.h"
47 #include "domain_audit.h"
48 #include "domain_conf.h"
49 #include "netdev_bandwidth_conf.h"
50 #include "snapshot_conf.h"
51 #include "storage_conf.h"
52 #include "secret_conf.h"
53 #include "virnetdevtap.h"
54 #include "virnetdevopenvswitch.h"
55 #include "device_conf.h"
56 #include "storage_source_conf.h"
57 #include "virtpm.h"
58 #include "virscsi.h"
59 #include "virnuma.h"
60 #include "virgic.h"
61 #include "virmdev.h"
62 #include "virdomainsnapshotobjlist.h"
63 #if defined(__linux__)
64 # include <linux/capability.h>
65 #endif
66 #include "logging/log_manager.h"
67 #include "logging/log_protocol.h"
68 #include "virutil.h"
69 #include "virsecureerase.h"
70
71 #include <sys/stat.h>
72 #include <fcntl.h>
73
74 #define VIR_FROM_THIS VIR_FROM_QEMU
75
76 VIR_LOG_INIT("qemu.qemu_command");
77
78 VIR_ENUM_DECL(qemuDiskCacheV2);
79
80 VIR_ENUM_IMPL(qemuDiskCacheV2,
81 VIR_DOMAIN_DISK_CACHE_LAST,
82 "default",
83 "none",
84 "writethrough",
85 "writeback",
86 "directsync",
87 "unsafe",
88 );
89
90 VIR_ENUM_IMPL(qemuVideo,
91 VIR_DOMAIN_VIDEO_TYPE_LAST,
92 "", /* default value, we shouldn't see this */
93 "std",
94 "cirrus",
95 "vmware",
96 "", /* don't support xen */
97 "", /* don't support vbox */
98 "qxl",
99 "", /* don't support parallels */
100 "", /* no need for virtio */
101 "" /* don't support gop */,
102 "" /* 'none' doesn't make sense here */,
103 "bochs-display",
104 "", /* ramfb can't be used with -vga */
105 );
106
107 VIR_ENUM_IMPL(qemuSoundCodec,
108 VIR_DOMAIN_SOUND_CODEC_TYPE_LAST,
109 "hda-duplex",
110 "hda-micro",
111 "hda-output",
112 );
113
114 VIR_ENUM_DECL(qemuControllerModelUSB);
115
116 VIR_ENUM_IMPL(qemuControllerModelUSB,
117 VIR_DOMAIN_CONTROLLER_MODEL_USB_LAST,
118 "piix3-usb-uhci",
119 "piix4-usb-uhci",
120 "usb-ehci",
121 "ich9-usb-ehci1",
122 "ich9-usb-uhci1",
123 "ich9-usb-uhci2",
124 "ich9-usb-uhci3",
125 "vt82c686b-usb-uhci",
126 "pci-ohci",
127 "nec-usb-xhci",
128 "qusb1",
129 "qusb2",
130 "qemu-xhci",
131 "none",
132 );
133
134 VIR_ENUM_DECL(qemuNumaPolicy);
135 VIR_ENUM_IMPL(qemuNumaPolicy,
136 VIR_DOMAIN_NUMATUNE_MEM_LAST,
137 "bind",
138 "preferred",
139 "interleave",
140 "restrictive",
141 );
142
143 VIR_ENUM_DECL(qemuAudioDriver);
144 VIR_ENUM_IMPL(qemuAudioDriver,
145 VIR_DOMAIN_AUDIO_TYPE_LAST,
146 "none",
147 "alsa",
148 "coreaudio",
149 "jack",
150 "oss",
151 "pa",
152 "sdl",
153 "spice",
154 "wav",
155 );
156
157
158 static const char *
qemuOnOffAuto(virTristateSwitch s)159 qemuOnOffAuto(virTristateSwitch s)
160 {
161 if (s == VIR_TRISTATE_SWITCH_ABSENT)
162 return NULL;
163
164 return virTristateSwitchTypeToString(s);
165 }
166
167
168 static int
qemuBuildObjectCommandlineFromJSON(virCommand * cmd,virJSONValue * props,virQEMUCaps * qemuCaps)169 qemuBuildObjectCommandlineFromJSON(virCommand *cmd,
170 virJSONValue *props,
171 virQEMUCaps *qemuCaps)
172 {
173 g_autofree char *arg = NULL;
174
175 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_JSON)) {
176 if (!(arg = virJSONValueToString(props, false)))
177 return -1;
178 } else {
179 const char *type = virJSONValueObjectGetString(props, "qom-type");
180 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
181
182 virBufferAsprintf(&buf, "%s,", type);
183
184 if (virQEMUBuildCommandLineJSON(props, &buf, "qom-type",
185 virQEMUBuildCommandLineJSONArrayBitmap) < 0)
186 return -1;
187
188 arg = virBufferContentAndReset(&buf);
189 }
190
191 virCommandAddArgList(cmd, "-object", arg, NULL);
192 return 0;
193 }
194
195
196 static int
qemuBuildNetdevCommandlineFromJSON(virCommand * cmd,virJSONValue * props,virQEMUCaps * qemuCaps)197 qemuBuildNetdevCommandlineFromJSON(virCommand *cmd,
198 virJSONValue *props,
199 virQEMUCaps *qemuCaps)
200 {
201 g_autofree char *arg = NULL;
202
203 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV_JSON)) {
204 if (!(arg = virJSONValueToString(props, false)))
205 return -1;
206 } else {
207 const char *type = virJSONValueObjectGetString(props, "type");
208 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
209
210 virBufferAsprintf(&buf, "%s,", type);
211
212 if (virQEMUBuildCommandLineJSON(props, &buf, "type",
213 virQEMUBuildCommandLineJSONArrayObjectsStr) < 0)
214 return -1;
215
216 arg = virBufferContentAndReset(&buf);
217 }
218
219 virCommandAddArgList(cmd, "-netdev", arg, NULL);
220 return 0;
221 }
222
223
224 static int
qemuBuildDeviceCommandlineFromJSON(virCommand * cmd,virJSONValue * props,virQEMUCaps * qemuCaps)225 qemuBuildDeviceCommandlineFromJSON(virCommand *cmd,
226 virJSONValue *props,
227 virQEMUCaps *qemuCaps)
228 {
229 g_autofree char *arg = NULL;
230
231 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_JSON)) {
232 if (!(arg = virJSONValueToString(props, false)))
233 return -1;
234 } else {
235 const char *driver = virJSONValueObjectGetString(props, "driver");
236 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
237
238 virBufferAsprintf(&buf, "%s,", driver);
239
240 if (virQEMUBuildCommandLineJSON(props, &buf, "driver", NULL) < 0)
241 return -1;
242
243 arg = virBufferContentAndReset(&buf);
244 }
245
246 virCommandAddArgList(cmd, "-device", arg, NULL);
247 return 0;
248 }
249
250
251 /**
252 * qemuBuildMasterKeyCommandLine:
253 * @cmd: the command to modify
254 * @qemuCaps qemu capabilities object
255 * @domainLibDir: location to find the master key
256
257 * Formats the command line for a master key if available
258 *
259 * Returns 0 on success, -1 w/ error message on failure
260 */
261 static int
qemuBuildMasterKeyCommandLine(virCommand * cmd,qemuDomainObjPrivate * priv)262 qemuBuildMasterKeyCommandLine(virCommand *cmd,
263 qemuDomainObjPrivate *priv)
264 {
265 g_autofree char *alias = NULL;
266 g_autofree char *path = NULL;
267 g_autoptr(virJSONValue) props = NULL;
268
269 if (!(alias = qemuDomainGetMasterKeyAlias()))
270 return -1;
271
272 /* Get the path. NB, the mocked test will not have the created
273 * file so we cannot check for existence, which is no different
274 * than other command line options which do not check for the
275 * existence of socket files before using.
276 */
277 if (!(path = qemuDomainGetMasterKeyFilePath(priv->libDir)))
278 return -1;
279
280 if (qemuMonitorCreateObjectProps(&props, "secret", alias,
281 "s:format", "raw",
282 "s:file", path,
283 NULL) < 0)
284 return -1;
285
286 if (qemuBuildObjectCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0)
287 return -1;
288
289 return 0;
290 }
291
292
293 /**
294 * qemuBuildFDSet:
295 * @fd: fd to reassign to the child
296 * @idx: index in the fd set
297 *
298 * Format the parameters for the -add-fd command line option
299 * for the given file descriptor. The file descriptor must previously
300 * have been 'transferred' in a virCommandPassFDIndex() call,
301 * and @idx is the value returned by that call.
302 */
303 static char *
qemuBuildFDSet(int fd,size_t idx)304 qemuBuildFDSet(int fd, size_t idx)
305 {
306 return g_strdup_printf("set=%zu,fd=%d", idx, fd);
307 }
308
309
310 /**
311 * qemuVirCommandGetFDSet:
312 * @cmd: the command to modify
313 * @fd: fd to reassign to the child
314 *
315 * Get the parameters for the QEMU -add-fd command line option
316 * for the given file descriptor. The file descriptor must previously
317 * have been 'transferred' in a virCommandPassFD() call.
318 * This function for example returns "set=10,fd=20".
319 */
320 static char *
qemuVirCommandGetFDSet(virCommand * cmd,int fd)321 qemuVirCommandGetFDSet(virCommand *cmd, int fd)
322 {
323 int idx = virCommandPassFDGetFDIndex(cmd, fd);
324
325 if (idx < 0) {
326 virReportError(VIR_ERR_INTERNAL_ERROR,
327 _("file descriptor %d has not been transferred"), fd);
328 return NULL;
329 }
330
331 return g_strdup_printf("set=%d,fd=%d", idx, fd);
332 }
333
334
335 /**
336 * qemuVirCommandGetDevSet:
337 * @cmd: the command to modify
338 * @fd: fd to reassign to the child
339 *
340 * Get the parameters for the QEMU path= parameter where a file
341 * descriptor is accessed via a file descriptor set, for example
342 * /dev/fdset/10. The file descriptor must previously have been
343 * 'transferred' in a virCommandPassFD() call.
344 */
345 static char *
qemuVirCommandGetDevSet(virCommand * cmd,int fd)346 qemuVirCommandGetDevSet(virCommand *cmd, int fd)
347 {
348 int idx = virCommandPassFDGetFDIndex(cmd, fd);
349
350 if (idx < 0) {
351 virReportError(VIR_ERR_INTERNAL_ERROR,
352 _("file descriptor %d has not been transferred"), fd);
353 return NULL;
354 }
355
356 return g_strdup_printf("/dev/fdset/%d", idx);
357 }
358
359
360 static char *
qemuBuildDeviceAddressPCIGetBus(const virDomainDef * domainDef,const virDomainDeviceInfo * info)361 qemuBuildDeviceAddressPCIGetBus(const virDomainDef *domainDef,
362 const virDomainDeviceInfo *info)
363 {
364 g_autofree char *devStr = NULL;
365 const char *contAlias = NULL;
366 bool contIsPHB = false;
367 int contTargetIndex = 0;
368 size_t i;
369
370 if (!(devStr = virPCIDeviceAddressAsString(&info->addr.pci)))
371 return NULL;
372
373 for (i = 0; i < domainDef->ncontrollers; i++) {
374 virDomainControllerDef *cont = domainDef->controllers[i];
375
376 if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
377 cont->idx == info->addr.pci.bus) {
378 contAlias = cont->info.alias;
379 contIsPHB = virDomainControllerIsPSeriesPHB(cont);
380 contTargetIndex = cont->opts.pciopts.targetIndex;
381
382 if (!contAlias) {
383 virReportError(VIR_ERR_INTERNAL_ERROR,
384 _("Device alias was not set for PCI controller with index '%u' required for device at address '%s'"),
385 info->addr.pci.bus, devStr);
386 return NULL;
387 }
388
389 if (virDomainDeviceAliasIsUserAlias(contAlias)) {
390 /* When domain has builtin pci-root controller we don't put it
391 * onto cmd line. Therefore we can't set its alias. In that
392 * case, use the default one. */
393 if (!qemuDomainIsPSeries(domainDef) &&
394 cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
395 if (virQEMUCapsHasPCIMultiBus(domainDef))
396 contAlias = "pci.0";
397 else
398 contAlias = "pci";
399 } else if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) {
400 contAlias = "pcie.0";
401 }
402 }
403 break;
404 }
405 }
406
407 if (!contAlias) {
408 virReportError(VIR_ERR_INTERNAL_ERROR,
409 _("Could not find PCI controller with index '%u' required for device at address '%s'"),
410 info->addr.pci.bus, devStr);
411 return NULL;
412 }
413
414 /* The PCI bus created by a spapr-pci-host-bridge device with
415 * alias 'x' will be called 'x.0' rather than 'x'; however,
416 * this does not apply to the implicit PHB in a pSeries guest,
417 * which always has the hardcoded name 'pci.0' */
418 if (contIsPHB && contTargetIndex > 0)
419 return g_strdup_printf("%s.0", contAlias);
420
421 /* For all other controllers, the bus name matches the alias
422 * of the corresponding controller */
423 return g_strdup(contAlias);
424 }
425
426
427 static int
qemuBuildDeviceAddresDriveProps(virJSONValue * props,const virDomainDef * domainDef,const virDomainDeviceInfo * info)428 qemuBuildDeviceAddresDriveProps(virJSONValue *props,
429 const virDomainDef *domainDef,
430 const virDomainDeviceInfo *info)
431 {
432 g_autofree char *bus = NULL;
433 virDomainControllerDef *controller = NULL;
434 const char *controllerAlias = NULL;
435
436 switch ((virDomainDiskBus) info->addr.drive.diskbus) {
437 case VIR_DOMAIN_DISK_BUS_IDE:
438 /* When domain has builtin IDE controller we don't put it onto cmd
439 * line. Therefore we can't set its alias. In that case, use the
440 * default one. */
441 if (qemuDomainHasBuiltinIDE(domainDef)) {
442 controllerAlias = "ide";
443 } else {
444 if (!(controllerAlias = virDomainControllerAliasFind(domainDef,
445 VIR_DOMAIN_CONTROLLER_TYPE_IDE,
446 info->addr.drive.controller)))
447 return -1;
448 }
449
450 bus = g_strdup_printf("%s.%u", controllerAlias, info->addr.drive.bus);
451
452 if (virJSONValueObjectAdd(&props,
453 "s:bus", bus,
454 "u:unit", info->addr.drive.unit,
455 NULL) < 0)
456 return -1;
457
458 break;
459
460 case VIR_DOMAIN_DISK_BUS_SATA:
461 /* When domain has builtin SATA controller we don't put it onto cmd
462 * line. Therefore we can't set its alias. In that case, use the
463 * default one. */
464 if (qemuDomainIsQ35(domainDef) &&
465 info->addr.drive.controller == 0) {
466 controllerAlias = "ide";
467 } else {
468 if (!(controllerAlias = virDomainControllerAliasFind(domainDef,
469 VIR_DOMAIN_CONTROLLER_TYPE_SATA,
470 info->addr.drive.controller)))
471 return -1;
472 }
473
474 bus = g_strdup_printf("%s.%u", controllerAlias, info->addr.drive.unit);
475
476 if (virJSONValueObjectAdd(&props,
477 "s:bus", bus,
478 NULL) < 0)
479 return -1;
480
481 break;
482
483 case VIR_DOMAIN_DISK_BUS_FDC:
484 if (virJSONValueObjectAdd(&props,
485 "u:unit", info->addr.drive.unit,
486 NULL) < 0)
487 return -1;
488
489 break;
490
491 case VIR_DOMAIN_DISK_BUS_SCSI:
492 if (!(controller = virDomainDeviceFindSCSIController(domainDef, &info->addr.drive))) {
493 virReportError(VIR_ERR_INTERNAL_ERROR,
494 _("unable to find a SCSI controller for idx=%d"),
495 info->addr.drive.controller);
496 return -1;
497 }
498
499 switch ((virDomainControllerModelSCSI) controller->model) {
500 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC:
501 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_NCR53C90:
502 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DC390:
503 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AM53C974:
504 bus = g_strdup_printf("%s.%u", controller->info.alias, info->addr.drive.bus);
505
506 if (virJSONValueObjectAdd(&props,
507 "s:bus", bus,
508 "u:scsi-id", info->addr.drive.unit,
509 NULL) < 0)
510 return -1;
511
512 break;
513
514 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO:
515 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC:
516 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068:
517 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI:
518 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
519 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI:
520 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078:
521 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL:
522 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL:
523 bus = g_strdup_printf("%s.0", controller->info.alias);
524
525 if (virJSONValueObjectAdd(&props,
526 "s:bus", bus,
527 "u:channel", info->addr.drive.bus,
528 "u:scsi-id", info->addr.drive.target,
529 "u:lun", info->addr.drive.unit,
530 NULL) < 0)
531 return -1;
532
533 break;
534
535 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT:
536 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST:
537 virReportError(VIR_ERR_INTERNAL_ERROR,
538 _("Unexpected SCSI controller model %d"),
539 controller->model);
540 return -1;
541 }
542
543 break;
544
545 case VIR_DOMAIN_DISK_BUS_VIRTIO:
546 case VIR_DOMAIN_DISK_BUS_USB:
547 case VIR_DOMAIN_DISK_BUS_XEN:
548 case VIR_DOMAIN_DISK_BUS_UML:
549 case VIR_DOMAIN_DISK_BUS_SD:
550 case VIR_DOMAIN_DISK_BUS_NONE:
551 case VIR_DOMAIN_DISK_BUS_LAST:
552 default:
553 virReportError(VIR_ERR_INTERNAL_ERROR,
554 _("address type drive is not supported for bus '%s'"),
555 NULLSTR(virDomainDiskBusTypeToString(info->addr.drive.diskbus)));
556 return -1;
557 }
558
559 return 0;
560 }
561
562
563 static int
qemuBuildDeviceAddressProps(virJSONValue * props,const virDomainDef * domainDef,const virDomainDeviceInfo * info)564 qemuBuildDeviceAddressProps(virJSONValue *props,
565 const virDomainDef *domainDef,
566 const virDomainDeviceInfo *info)
567 {
568 switch ((virDomainDeviceAddressType) info->type) {
569 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: {
570 g_autofree char *pciaddr = NULL;
571 g_autofree char *bus = qemuBuildDeviceAddressPCIGetBus(domainDef, info);
572
573 if (!bus)
574 return -1;
575
576 if (info->addr.pci.function != 0)
577 pciaddr = g_strdup_printf("0x%x.0x%x", info->addr.pci.slot, info->addr.pci.function);
578 else
579 pciaddr = g_strdup_printf("0x%x", info->addr.pci.slot);
580
581 if (virJSONValueObjectAdd(&props,
582 "s:bus", bus,
583 "T:multifunction", info->addr.pci.multi,
584 "s:addr", pciaddr,
585 "p:acpi-index", info->acpiIndex,
586 NULL) < 0)
587 return -1;
588
589 return 0;
590 }
591 break;
592
593 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB: {
594 const char *contAlias = NULL;
595 g_auto(virBuffer) port = VIR_BUFFER_INITIALIZER;
596 g_autofree char *bus = NULL;
597
598 if (!(contAlias = virDomainControllerAliasFind(domainDef,
599 VIR_DOMAIN_CONTROLLER_TYPE_USB,
600 info->addr.usb.bus)))
601 return -1;
602
603 bus = g_strdup_printf("%s.0", contAlias);
604
605 virDomainUSBAddressPortFormatBuf(&port, info->addr.usb.port);
606
607 if (virJSONValueObjectAdd(&props,
608 "s:bus", bus,
609 "S:port", virBufferCurrentContent(&port),
610 NULL) < 0)
611 return -1;
612
613 return 0;
614 }
615
616 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
617 if (info->addr.spaprvio.has_reg) {
618 if (virJSONValueObjectAdd(&props,
619 "P:reg", info->addr.spaprvio.reg,
620 NULL) < 0)
621 return -1;
622 }
623 return 0;
624
625 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: {
626 g_autofree char *devno = g_strdup_printf("%x.%x.%04x",
627 info->addr.ccw.cssid,
628 info->addr.ccw.ssid,
629 info->addr.ccw.devno);
630
631 if (virJSONValueObjectAdd(&props, "s:devno", devno, NULL) < 0)
632 return -1;
633
634 return 0;
635 }
636
637 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
638 if (virJSONValueObjectAdd(&props,
639 "u:iobase", info->addr.isa.iobase,
640 "p:irq", info->addr.isa.irq,
641 NULL) < 0)
642 return -1;
643
644 return 0;
645
646 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM:
647 if (virJSONValueObjectAdd(&props,
648 "u:slot", info->addr.dimm.slot,
649 "P:addr", info->addr.dimm.base,
650 NULL) < 0)
651 return -1;
652
653 return 0;
654
655 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
656 return qemuBuildDeviceAddresDriveProps(props, domainDef, info);
657
658 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL: {
659 const char *contAlias;
660 g_autofree char *bus = NULL;
661
662 if (!(contAlias = virDomainControllerAliasFind(domainDef,
663 VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL,
664 info->addr.vioserial.controller)))
665 return -1;
666
667 bus = g_strdup_printf("%s.%d", contAlias, info->addr.vioserial.bus);
668
669 if (virJSONValueObjectAdd(&props,
670 "s:bus", bus,
671 "i:nr", info->addr.vioserial.port,
672 NULL) < 0)
673 return -1;
674
675 return 0;
676 }
677
678 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
679 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID:
680 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390:
681 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
682 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
683 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
684 default:
685 return 0;
686 }
687 }
688
689
690 /**
691 * qemuDeviceVideoGetModel:
692 * @qemuCaps: qemu capabilities
693 * @video: video device definition
694 * @virtio: the returned video device is a 'virtio' device
695 * @virtioBusSuffix: the returned device needs to get the bus-suffix
696 *
697 * Returns the model of the device for @video and @qemuCaps. @virtio and
698 * @virtioBusSuffix are filled with the corresponding flags.
699 */
700 static const char *
qemuDeviceVideoGetModel(virQEMUCaps * qemuCaps,const virDomainVideoDef * video,bool * virtio,bool * virtioBusSuffix)701 qemuDeviceVideoGetModel(virQEMUCaps *qemuCaps,
702 const virDomainVideoDef *video,
703 bool *virtio,
704 bool *virtioBusSuffix)
705 {
706 const char *model = NULL;
707 bool primaryVga = false;
708 virTristateSwitch accel3d = VIR_TRISTATE_SWITCH_ABSENT;
709
710 *virtio = false;
711 *virtioBusSuffix = false;
712
713 if (video->accel)
714 accel3d = video->accel->accel3d;
715
716 if (video->primary && qemuDomainSupportsVideoVga(video, qemuCaps))
717 primaryVga = true;
718
719 /* We try to chose the best model for primary video device by preferring
720 * model with VGA compatibility mode. For some video devices on some
721 * architectures there might not be such model so fallback to one
722 * without VGA compatibility mode. */
723 if (video->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER) {
724 if (primaryVga) {
725 model = "vhost-user-vga";
726 } else {
727 model = "vhost-user-gpu";
728 *virtio = true;
729 *virtioBusSuffix = true;
730 }
731 } else {
732 if (primaryVga) {
733 switch ((virDomainVideoType) video->type) {
734 case VIR_DOMAIN_VIDEO_TYPE_VGA:
735 model = "VGA";
736 break;
737 case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
738 model = "cirrus-vga";
739 break;
740 case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
741 model = "vmware-svga";
742 break;
743 case VIR_DOMAIN_VIDEO_TYPE_QXL:
744 model = "qxl-vga";
745 break;
746 case VIR_DOMAIN_VIDEO_TYPE_VIRTIO:
747 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_VGA_GL) &&
748 accel3d == VIR_TRISTATE_SWITCH_ON)
749 model = "virtio-vga-gl";
750 else
751 model = "virtio-vga";
752
753 *virtio = true;
754 *virtioBusSuffix = false;
755 break;
756 case VIR_DOMAIN_VIDEO_TYPE_BOCHS:
757 model = "bochs-display";
758 break;
759 case VIR_DOMAIN_VIDEO_TYPE_RAMFB:
760 model = "ramfb";
761 break;
762 case VIR_DOMAIN_VIDEO_TYPE_DEFAULT:
763 case VIR_DOMAIN_VIDEO_TYPE_XEN:
764 case VIR_DOMAIN_VIDEO_TYPE_VBOX:
765 case VIR_DOMAIN_VIDEO_TYPE_PARALLELS:
766 case VIR_DOMAIN_VIDEO_TYPE_GOP:
767 case VIR_DOMAIN_VIDEO_TYPE_NONE:
768 case VIR_DOMAIN_VIDEO_TYPE_LAST:
769 break;
770 }
771 } else {
772 switch ((virDomainVideoType) video->type) {
773 case VIR_DOMAIN_VIDEO_TYPE_QXL:
774 model = "qxl";
775 break;
776 case VIR_DOMAIN_VIDEO_TYPE_VIRTIO:
777 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_GPU_GL_PCI) &&
778 accel3d == VIR_TRISTATE_SWITCH_ON)
779 model = "virtio-gpu-gl";
780 else
781 model = "virtio-gpu";
782
783 *virtio = true;
784 *virtioBusSuffix = true;
785 break;
786 case VIR_DOMAIN_VIDEO_TYPE_DEFAULT:
787 case VIR_DOMAIN_VIDEO_TYPE_VGA:
788 case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
789 case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
790 case VIR_DOMAIN_VIDEO_TYPE_XEN:
791 case VIR_DOMAIN_VIDEO_TYPE_VBOX:
792 case VIR_DOMAIN_VIDEO_TYPE_PARALLELS:
793 case VIR_DOMAIN_VIDEO_TYPE_GOP:
794 case VIR_DOMAIN_VIDEO_TYPE_NONE:
795 case VIR_DOMAIN_VIDEO_TYPE_BOCHS:
796 case VIR_DOMAIN_VIDEO_TYPE_RAMFB:
797 case VIR_DOMAIN_VIDEO_TYPE_LAST:
798 break;
799 }
800 }
801 }
802
803 if (!model || STREQ(model, "")) {
804 virReportError(VIR_ERR_INTERNAL_ERROR,
805 _("invalid model for video type '%s'"),
806 virDomainVideoTypeToString(video->type));
807 return NULL;
808 }
809
810 return model;
811 }
812
813
814 static void
qemuBuildVirtioDevGetConfigDev(const virDomainDeviceDef * device,virQEMUCaps * qemuCaps,const char ** baseName,virDomainVirtioOptions ** virtioOptions,bool * has_tmodel,bool * has_ntmodel,bool * useBusSuffix)815 qemuBuildVirtioDevGetConfigDev(const virDomainDeviceDef *device,
816 virQEMUCaps *qemuCaps,
817 const char **baseName,
818 virDomainVirtioOptions **virtioOptions,
819 bool *has_tmodel,
820 bool *has_ntmodel,
821 bool *useBusSuffix)
822 {
823 switch ((virDomainDeviceType) device->type) {
824 case VIR_DOMAIN_DEVICE_DISK:
825 if (virStorageSourceGetActualType(device->data.disk->src) == VIR_STORAGE_TYPE_VHOST_USER)
826 *baseName = "vhost-user-blk";
827 else
828 *baseName = "virtio-blk";
829
830 *virtioOptions = device->data.disk->virtio;
831 *has_tmodel = device->data.disk->model == VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL;
832 *has_ntmodel = device->data.disk->model == VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL;
833 break;
834
835 case VIR_DOMAIN_DEVICE_NET:
836 *baseName = "virtio-net";
837 *virtioOptions = device->data.net->virtio;
838 *has_tmodel = device->data.net->model == VIR_DOMAIN_NET_MODEL_VIRTIO_TRANSITIONAL;
839 *has_ntmodel = device->data.net->model == VIR_DOMAIN_NET_MODEL_VIRTIO_NON_TRANSITIONAL;
840 break;
841
842 case VIR_DOMAIN_DEVICE_HOSTDEV:
843 if (device->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
844 *baseName = "vhost-scsi";
845 *has_tmodel = device->data.hostdev->source.subsys.u.scsi_host.model == VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_VHOST_MODEL_TYPE_VIRTIO_TRANSITIONAL;
846 *has_ntmodel = device->data.hostdev->source.subsys.u.scsi_host.model == VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_VHOST_MODEL_TYPE_VIRTIO_NON_TRANSITIONAL;
847 }
848 break;
849
850 case VIR_DOMAIN_DEVICE_RNG:
851 *baseName = "virtio-rng";
852 *virtioOptions = device->data.rng->virtio;
853 *has_tmodel = device->data.rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO_TRANSITIONAL;
854 *has_ntmodel = device->data.rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO_NON_TRANSITIONAL;
855 break;
856
857 case VIR_DOMAIN_DEVICE_FS:
858 switch ((virDomainFSDriverType) device->data.fs->fsdriver) {
859 case VIR_DOMAIN_FS_DRIVER_TYPE_DEFAULT:
860 case VIR_DOMAIN_FS_DRIVER_TYPE_PATH:
861 case VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE:
862 *baseName = "virtio-9p";
863 break;
864
865 case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS:
866 *baseName = "vhost-user-fs";
867 break;
868
869 case VIR_DOMAIN_FS_DRIVER_TYPE_LOOP:
870 case VIR_DOMAIN_FS_DRIVER_TYPE_NBD:
871 case VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP:
872 case VIR_DOMAIN_FS_DRIVER_TYPE_LAST:
873 break;
874
875 }
876 *virtioOptions = device->data.fs->virtio;
877 *has_tmodel = device->data.fs->model == VIR_DOMAIN_FS_MODEL_VIRTIO_TRANSITIONAL;
878 *has_ntmodel = device->data.fs->model == VIR_DOMAIN_FS_MODEL_VIRTIO_NON_TRANSITIONAL;
879 break;
880
881 case VIR_DOMAIN_DEVICE_MEMBALLOON:
882 *baseName = "virtio-balloon";
883 *virtioOptions = device->data.memballoon->virtio;
884 *has_tmodel = device->data.memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO_TRANSITIONAL;
885 *has_ntmodel = device->data.memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO_NON_TRANSITIONAL;
886 break;
887
888 case VIR_DOMAIN_DEVICE_VSOCK:
889 *baseName = "vhost-vsock";
890 *virtioOptions = device->data.vsock->virtio;
891 *has_tmodel = device->data.vsock->model == VIR_DOMAIN_VSOCK_MODEL_VIRTIO_TRANSITIONAL;
892 *has_ntmodel = device->data.vsock->model == VIR_DOMAIN_VSOCK_MODEL_VIRTIO_NON_TRANSITIONAL;
893 break;
894
895 case VIR_DOMAIN_DEVICE_INPUT:
896 *virtioOptions = device->data.input->virtio;
897
898 switch ((virDomainInputType) device->data.input->type) {
899 case VIR_DOMAIN_INPUT_TYPE_MOUSE:
900 *baseName = "virtio-mouse";
901 break;
902
903 case VIR_DOMAIN_INPUT_TYPE_TABLET:
904 *baseName = "virtio-tablet";
905 break;
906
907 case VIR_DOMAIN_INPUT_TYPE_KBD:
908 *baseName = "virtio-keyboard";
909 break;
910
911 case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
912 *baseName = "virtio-input-host";
913 *has_tmodel = device->data.input->model == VIR_DOMAIN_INPUT_MODEL_VIRTIO_TRANSITIONAL;
914 *has_ntmodel = device->data.input->model == VIR_DOMAIN_INPUT_MODEL_VIRTIO_NON_TRANSITIONAL;
915 break;
916
917 case VIR_DOMAIN_INPUT_TYPE_EVDEV:
918 case VIR_DOMAIN_INPUT_TYPE_LAST:
919 default:
920 break;
921 }
922 break;
923
924 case VIR_DOMAIN_DEVICE_CONTROLLER:
925 if (device->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL) {
926 *baseName = "virtio-serial";
927 *virtioOptions = device->data.controller->virtio;
928 *has_tmodel = device->data.controller->model == VIR_DOMAIN_CONTROLLER_MODEL_VIRTIO_SERIAL_VIRTIO_TRANSITIONAL;
929 *has_ntmodel = device->data.controller->model == VIR_DOMAIN_CONTROLLER_MODEL_VIRTIO_SERIAL_VIRTIO_NON_TRANSITIONAL;
930 } else if (device->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
931 *baseName = "virtio-scsi";
932 *virtioOptions = device->data.controller->virtio;
933 *has_tmodel = device->data.controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL;
934 *has_ntmodel = device->data.controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL;
935 }
936 break;
937
938 case VIR_DOMAIN_DEVICE_VIDEO: {
939 bool virtio;
940 bool virtioBusSuffix;
941
942 if (!(*baseName = qemuDeviceVideoGetModel(qemuCaps,
943 device->data.video,
944 &virtio,
945 &virtioBusSuffix)))
946 return;
947
948 if (!virtioBusSuffix)
949 *useBusSuffix = false;
950
951 *virtioOptions = device->data.video->virtio;
952 }
953 break;
954
955 case VIR_DOMAIN_DEVICE_LEASE:
956 case VIR_DOMAIN_DEVICE_SOUND:
957 case VIR_DOMAIN_DEVICE_WATCHDOG:
958 case VIR_DOMAIN_DEVICE_GRAPHICS:
959 case VIR_DOMAIN_DEVICE_HUB:
960 case VIR_DOMAIN_DEVICE_REDIRDEV:
961 case VIR_DOMAIN_DEVICE_NONE:
962 case VIR_DOMAIN_DEVICE_SMARTCARD:
963 case VIR_DOMAIN_DEVICE_CHR:
964 case VIR_DOMAIN_DEVICE_NVRAM:
965 case VIR_DOMAIN_DEVICE_SHMEM:
966 case VIR_DOMAIN_DEVICE_TPM:
967 case VIR_DOMAIN_DEVICE_PANIC:
968 case VIR_DOMAIN_DEVICE_MEMORY:
969 case VIR_DOMAIN_DEVICE_IOMMU:
970 case VIR_DOMAIN_DEVICE_AUDIO:
971 case VIR_DOMAIN_DEVICE_LAST:
972 default:
973 break;
974 }
975 }
976
977
978 static int
qemuBuildVirtioDevGetConfig(const virDomainDeviceDef * device,virQEMUCaps * qemuCaps,char ** devtype,virDomainVirtioOptions ** virtioOptions,virTristateSwitch * disableLegacy,virTristateSwitch * disableModern)979 qemuBuildVirtioDevGetConfig(const virDomainDeviceDef *device,
980 virQEMUCaps *qemuCaps,
981 char **devtype,
982 virDomainVirtioOptions **virtioOptions,
983 virTristateSwitch *disableLegacy,
984 virTristateSwitch *disableModern)
985 {
986 virDomainDeviceInfo *info = virDomainDeviceGetInfo(device);
987 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
988 const char *baseName = NULL;
989 const char *implName = NULL;
990 bool has_tmodel = false;
991 bool has_ntmodel = false;
992 bool useBusSuffix = true;
993
994 *disableLegacy = VIR_TRISTATE_SWITCH_ABSENT;
995 *disableModern = VIR_TRISTATE_SWITCH_ABSENT;
996
997 qemuBuildVirtioDevGetConfigDev(device, qemuCaps, &baseName,
998 virtioOptions, &has_tmodel,
999 &has_ntmodel, &useBusSuffix);
1000
1001 if (!baseName) {
1002 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1003 _("unknown base name while formatting virtio device"));
1004 return -1;
1005 }
1006
1007 virBufferAdd(&buf, baseName, -1);
1008
1009 switch ((virDomainDeviceAddressType) info->type) {
1010 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
1011 implName = "pci";
1012 break;
1013
1014 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
1015 implName = "device";
1016 break;
1017
1018 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
1019 implName = "ccw";
1020 break;
1021
1022 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390:
1023 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
1024 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL:
1025 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID:
1026 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
1027 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
1028 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
1029 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM:
1030 virReportError(VIR_ERR_INTERNAL_ERROR,
1031 _("Unexpected address type for '%s'"), baseName);
1032 return -1;
1033
1034 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
1035 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
1036 case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
1037 default:
1038 virReportEnumRangeError(virDomainDeviceAddressType, info->type);
1039 return -1;
1040 }
1041
1042 if (useBusSuffix)
1043 virBufferAsprintf(&buf, "-%s", implName);
1044
1045 if (has_tmodel || has_ntmodel) {
1046 if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
1047 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1048 _("virtio (non-)transitional models are not "
1049 "supported for address type=%s"),
1050 virDomainDeviceAddressTypeToString(info->type));
1051 }
1052
1053 if (has_tmodel) {
1054 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_PCI_TRANSITIONAL)) {
1055 virBufferAddLit(&buf, "-transitional");
1056 } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY)) {
1057 *disableLegacy = VIR_TRISTATE_SWITCH_OFF;
1058 *disableModern = VIR_TRISTATE_SWITCH_OFF;
1059 }
1060 /* No error if -transitional is not supported: our address
1061 * allocation will force the device into plain PCI bus, which
1062 * is functionally identical to standard 'virtio-XXX' behavior
1063 */
1064 } else if (has_ntmodel) {
1065 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_PCI_TRANSITIONAL)) {
1066 virBufferAddLit(&buf, "-non-transitional");
1067 } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY)) {
1068 /* Even if the QEMU binary doesn't support the non-transitional
1069 * device, we can still make it work by manually disabling legacy
1070 * VirtIO and enabling modern VirtIO */
1071 *disableLegacy = VIR_TRISTATE_SWITCH_ON;
1072 *disableModern = VIR_TRISTATE_SWITCH_OFF;
1073 } else {
1074 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1075 _("virtio non-transitional model not supported for this qemu"));
1076 return -1;
1077 }
1078 }
1079 }
1080
1081 *devtype = virBufferContentAndReset(&buf);
1082
1083 return 0;
1084 }
1085
1086
1087 /**
1088 * qemuBuildVirtioDevProps
1089 * @devtype: virDomainDeviceType of the device. Ex: VIR_DOMAIN_DEVICE_TYPE_RNG
1090 * @devdata: *Def * of the device definition
1091 * @qemuCaps: qemu capabilities
1092 *
1093 * Build the qemu virtio -device JSON properties name from the passed parameters.
1094 */
1095 static virJSONValue *
qemuBuildVirtioDevProps(virDomainDeviceType devtype,const void * devdata,virQEMUCaps * qemuCaps)1096 qemuBuildVirtioDevProps(virDomainDeviceType devtype,
1097 const void *devdata,
1098 virQEMUCaps *qemuCaps)
1099 {
1100 g_autoptr(virJSONValue) props = NULL;
1101 const virDomainDeviceDef device = { .type = devtype };
1102 g_autofree char *model = NULL;
1103 virTristateSwitch disableLegacy = VIR_TRISTATE_SWITCH_ABSENT;
1104 virTristateSwitch disableModern = VIR_TRISTATE_SWITCH_ABSENT;
1105 virDomainVirtioOptions *virtioOptions = NULL;
1106
1107 /* We temporarily cast the const away here, but that's safe to do
1108 * because the called function simply sets the correct member of
1109 * device to devdata based on devtype. Further uses of device will
1110 * not touch its contents */
1111 virDomainDeviceSetData((virDomainDeviceDef *) &device, (void *) devdata);
1112
1113 if (qemuBuildVirtioDevGetConfig(&device, qemuCaps, &model, &virtioOptions,
1114 &disableLegacy, &disableModern) < 0)
1115 return NULL;
1116
1117 if (virJSONValueObjectAdd(&props,
1118 "s:driver", model,
1119 "S:disable-legacy", qemuOnOffAuto(disableLegacy),
1120 "T:disable-modern", disableModern,
1121 NULL) < 0)
1122 return NULL;
1123
1124 if (virtioOptions) {
1125 if (virJSONValueObjectAdd(&props,
1126 "T:iommu_platform", virtioOptions->iommu,
1127 "T:ats", virtioOptions->ats,
1128 "T:packed", virtioOptions->packed,
1129 "T:page-per-vq", virtioOptions->page_per_vq,
1130 NULL) < 0)
1131 return NULL;
1132 }
1133
1134 return g_steal_pointer(&props);
1135 }
1136
1137
1138 static int
qemuBuildRomProps(virJSONValue * props,virDomainDeviceInfo * info)1139 qemuBuildRomProps(virJSONValue *props,
1140 virDomainDeviceInfo *info)
1141 {
1142 const char *romfile = NULL;
1143 int rombar = -1;
1144
1145 if (info->romenabled == VIR_TRISTATE_BOOL_ABSENT &&
1146 info->rombar == VIR_TRISTATE_SWITCH_ABSENT &&
1147 !info->romfile)
1148 return 0;
1149
1150 if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
1151 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1152 _("ROM tuning is only supported for PCI devices"));
1153 return -1;
1154 }
1155
1156 if (info->romenabled == VIR_TRISTATE_BOOL_NO) {
1157 romfile = "";
1158 } else {
1159 romfile = info->romfile;
1160
1161 switch (info->rombar) {
1162 case VIR_TRISTATE_SWITCH_OFF:
1163 rombar = 0;
1164 break;
1165 case VIR_TRISTATE_SWITCH_ON:
1166 rombar = 1;
1167 break;
1168 case VIR_TRISTATE_SWITCH_ABSENT:
1169 case VIR_TRISTATE_SWITCH_LAST:
1170 break;
1171 }
1172 }
1173
1174 if (virJSONValueObjectAdd(&props,
1175 "k:rombar", rombar,
1176 "S:romfile", romfile,
1177 NULL) < 0)
1178 return -1;
1179
1180 return 0;
1181 }
1182
1183
1184 /**
1185 * qemuBuildSecretInfoProps:
1186 * @secinfo: pointer to the secret info object
1187 * @props: json properties to return
1188 *
1189 * Build the JSON properties for the secret info type.
1190 *
1191 * Returns 0 on success with the filled in JSON property; otherwise,
1192 * returns -1 on failure error message set.
1193 */
1194 int
qemuBuildSecretInfoProps(qemuDomainSecretInfo * secinfo,virJSONValue ** propsret)1195 qemuBuildSecretInfoProps(qemuDomainSecretInfo *secinfo,
1196 virJSONValue **propsret)
1197 {
1198 g_autofree char *keyid = NULL;
1199
1200 if (!(keyid = qemuDomainGetMasterKeyAlias()))
1201 return -1;
1202
1203 return qemuMonitorCreateObjectProps(propsret, "secret",
1204 secinfo->alias, "s:data",
1205 secinfo->ciphertext, "s:keyid",
1206 keyid, "s:iv", secinfo->iv,
1207 "s:format", "base64", NULL);
1208 }
1209
1210
1211 /**
1212 * qemuBuildObjectSecretCommandLine:
1213 * @cmd: the command to modify
1214 * @secinfo: pointer to the secret info object
1215 * @qemuCaps: qemu capabilities
1216 *
1217 * If the secinfo is available and associated with an AES secret,
1218 * then format the command line for the secret object. This object
1219 * will be referenced by the device that needs/uses it, so it needs
1220 * to be in place first.
1221 *
1222 * Returns 0 on success, -1 w/ error message on failure
1223 */
1224 static int
qemuBuildObjectSecretCommandLine(virCommand * cmd,qemuDomainSecretInfo * secinfo,virQEMUCaps * qemuCaps)1225 qemuBuildObjectSecretCommandLine(virCommand *cmd,
1226 qemuDomainSecretInfo *secinfo,
1227 virQEMUCaps *qemuCaps)
1228 {
1229 g_autoptr(virJSONValue) props = NULL;
1230
1231 if (qemuBuildSecretInfoProps(secinfo, &props) < 0)
1232 return -1;
1233
1234 if (qemuBuildObjectCommandlineFromJSON(cmd, props, qemuCaps) < 0)
1235 return -1;
1236
1237 return 0;
1238 }
1239
1240
1241 /* qemuBuildTLSx509BackendProps:
1242 * @tlspath: path to the TLS credentials
1243 * @listen: boolean listen for client or server setting
1244 * @verifypeer: boolean to enable peer verification (form of authorization)
1245 * @alias: alias for the TLS credentials object
1246 * @secalias: if one exists, the alias of the security object for passwordid
1247 * @propsret: json properties to return
1248 *
1249 * Create a backend string for the tls-creds-x509 object.
1250 *
1251 * Returns 0 on success, -1 on failure with error set.
1252 */
1253 int
qemuBuildTLSx509BackendProps(const char * tlspath,bool isListen,bool verifypeer,const char * alias,const char * secalias,virJSONValue ** propsret)1254 qemuBuildTLSx509BackendProps(const char *tlspath,
1255 bool isListen,
1256 bool verifypeer,
1257 const char *alias,
1258 const char *secalias,
1259 virJSONValue **propsret)
1260 {
1261 if (qemuMonitorCreateObjectProps(propsret, "tls-creds-x509", alias,
1262 "s:dir", tlspath,
1263 "s:endpoint", (isListen ? "server": "client"),
1264 "b:verify-peer", (isListen ? verifypeer : true),
1265 "S:passwordid", secalias,
1266 NULL) < 0)
1267 return -1;
1268
1269 return 0;
1270 }
1271
1272
1273 /* qemuBuildTLSx509CommandLine:
1274 * @cmd: Pointer to command
1275 * @tlspath: path to the TLS credentials
1276 * @listen: boolean listen for client or server setting
1277 * @verifypeer: boolean to enable peer verification (form of authorization)
1278 * @certEncSecretAlias: alias of a 'secret' object for decrypting TLS private key
1279 * (optional)
1280 * @alias: TLS object alias
1281 * @qemuCaps: capabilities
1282 *
1283 * Create the command line for a TLS object
1284 *
1285 * Returns 0 on success, -1 on failure with error set.
1286 */
1287 static int
qemuBuildTLSx509CommandLine(virCommand * cmd,const char * tlspath,bool isListen,bool verifypeer,const char * certEncSecretAlias,const char * alias,virQEMUCaps * qemuCaps)1288 qemuBuildTLSx509CommandLine(virCommand *cmd,
1289 const char *tlspath,
1290 bool isListen,
1291 bool verifypeer,
1292 const char *certEncSecretAlias,
1293 const char *alias,
1294 virQEMUCaps *qemuCaps)
1295 {
1296 g_autoptr(virJSONValue) props = NULL;
1297
1298 if (qemuBuildTLSx509BackendProps(tlspath, isListen, verifypeer, alias,
1299 certEncSecretAlias, &props) < 0)
1300 return -1;
1301
1302 if (qemuBuildObjectCommandlineFromJSON(cmd, props, qemuCaps) < 0)
1303 return -1;
1304
1305 return 0;
1306 }
1307
1308
1309 static char *
qemuBuildNetworkDriveURI(virStorageSource * src)1310 qemuBuildNetworkDriveURI(virStorageSource *src)
1311 {
1312 g_autoptr(virURI) uri = NULL;
1313
1314 if (!(uri = qemuBlockStorageSourceGetURI(src)))
1315 return NULL;
1316
1317 if (src->hosts->socket)
1318 uri->query = g_strdup_printf("socket=%s", src->hosts->socket);
1319
1320 return virURIFormat(uri);
1321 }
1322
1323
1324 static char *
qemuBuildNetworkDriveStr(virStorageSource * src,qemuDomainSecretInfo * secinfo)1325 qemuBuildNetworkDriveStr(virStorageSource *src,
1326 qemuDomainSecretInfo *secinfo)
1327 {
1328 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1329 size_t i;
1330 char *ret = NULL;
1331
1332 switch ((virStorageNetProtocol) src->protocol) {
1333 case VIR_STORAGE_NET_PROTOCOL_NBD:
1334 if (src->nhosts != 1) {
1335 virReportError(VIR_ERR_INTERNAL_ERROR,
1336 _("protocol '%s' accepts only one host"),
1337 virStorageNetProtocolTypeToString(src->protocol));
1338 return NULL;
1339 }
1340
1341 if (!((src->hosts->name && strchr(src->hosts->name, ':')) ||
1342 (src->hosts->transport == VIR_STORAGE_NET_HOST_TRANS_TCP &&
1343 !src->hosts->name) ||
1344 (src->hosts->transport == VIR_STORAGE_NET_HOST_TRANS_UNIX &&
1345 src->hosts->socket &&
1346 !g_path_is_absolute(src->hosts->socket)))) {
1347
1348 virBufferAddLit(&buf, "nbd:");
1349
1350 switch (src->hosts->transport) {
1351 case VIR_STORAGE_NET_HOST_TRANS_TCP:
1352 virBufferAsprintf(&buf, "%s:%u",
1353 src->hosts->name, src->hosts->port);
1354 break;
1355
1356 case VIR_STORAGE_NET_HOST_TRANS_UNIX:
1357 if (!src->hosts->socket) {
1358 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1359 _("socket attribute required for "
1360 "unix transport"));
1361 return NULL;
1362 }
1363
1364 virBufferAsprintf(&buf, "unix:%s", src->hosts->socket);
1365 break;
1366
1367 default:
1368 virReportError(VIR_ERR_INTERNAL_ERROR,
1369 _("nbd does not support transport '%s'"),
1370 virStorageNetHostTransportTypeToString(src->hosts->transport));
1371 return NULL;
1372 }
1373
1374 if (src->path)
1375 virBufferAsprintf(&buf, ":exportname=%s", src->path);
1376
1377 return virBufferContentAndReset(&buf);
1378 }
1379 /* NBD code uses URI formatting scheme as others in some cases */
1380 ret = qemuBuildNetworkDriveURI(src);
1381 break;
1382
1383 case VIR_STORAGE_NET_PROTOCOL_HTTP:
1384 case VIR_STORAGE_NET_PROTOCOL_HTTPS:
1385 case VIR_STORAGE_NET_PROTOCOL_FTP:
1386 case VIR_STORAGE_NET_PROTOCOL_FTPS:
1387 case VIR_STORAGE_NET_PROTOCOL_TFTP:
1388 case VIR_STORAGE_NET_PROTOCOL_ISCSI:
1389 case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
1390 ret = qemuBuildNetworkDriveURI(src);
1391 break;
1392
1393 case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
1394 if (!src->path) {
1395 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1396 _("missing disk source for 'sheepdog' protocol"));
1397 return NULL;
1398 }
1399
1400 if (src->nhosts == 0) {
1401 ret = g_strdup_printf("sheepdog:%s", src->path);
1402 } else if (src->nhosts == 1) {
1403 ret = g_strdup_printf("sheepdog:%s:%u:%s", src->hosts->name,
1404 src->hosts->port, src->path);
1405 } else {
1406 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1407 _("protocol 'sheepdog' accepts up to one host"));
1408 return NULL;
1409 }
1410
1411 break;
1412
1413 case VIR_STORAGE_NET_PROTOCOL_RBD:
1414 if (strchr(src->path, ':')) {
1415 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1416 _("':' not allowed in RBD source volume name '%s'"),
1417 src->path);
1418 return NULL;
1419 }
1420
1421 virBufferStrcat(&buf, "rbd:", src->volume, "/", src->path, NULL);
1422
1423 if (src->snapshot)
1424 virBufferEscape(&buf, '\\', ":", "@%s", src->snapshot);
1425
1426 if (!secinfo)
1427 virBufferAddLit(&buf, ":auth_supported=none");
1428 else
1429 virBufferEscape(&buf, '\\', ":", ":id=%s:auth_supported=cephx\\;none",
1430 secinfo->username);
1431
1432 if (src->nhosts > 0) {
1433 virBufferAddLit(&buf, ":mon_host=");
1434 for (i = 0; i < src->nhosts; i++) {
1435 if (i)
1436 virBufferAddLit(&buf, "\\;");
1437
1438 /* assume host containing : is ipv6 */
1439 if (strchr(src->hosts[i].name, ':'))
1440 virBufferEscape(&buf, '\\', ":", "[%s]",
1441 src->hosts[i].name);
1442 else
1443 virBufferAsprintf(&buf, "%s", src->hosts[i].name);
1444
1445 if (src->hosts[i].port)
1446 virBufferAsprintf(&buf, "\\:%u", src->hosts[i].port);
1447 }
1448 }
1449
1450 if (src->configFile)
1451 virBufferEscape(&buf, '\\', ":", ":conf=%s", src->configFile);
1452
1453 ret = virBufferContentAndReset(&buf);
1454 break;
1455
1456 case VIR_STORAGE_NET_PROTOCOL_VXHS:
1457 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1458 _("VxHS protocol does not support URI syntax"));
1459 return NULL;
1460
1461 case VIR_STORAGE_NET_PROTOCOL_SSH:
1462 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1463 _("'ssh' protocol is not yet supported"));
1464 return NULL;
1465
1466 case VIR_STORAGE_NET_PROTOCOL_NFS:
1467 case VIR_STORAGE_NET_PROTOCOL_LAST:
1468 case VIR_STORAGE_NET_PROTOCOL_NONE:
1469 virReportError(VIR_ERR_INTERNAL_ERROR,
1470 _("Unexpected network protocol '%s'"),
1471 virStorageNetProtocolTypeToString(src->protocol));
1472 return NULL;
1473 }
1474
1475 return ret;
1476 }
1477
1478
1479 int
qemuGetDriveSourceString(virStorageSource * src,qemuDomainSecretInfo * secinfo,char ** source)1480 qemuGetDriveSourceString(virStorageSource *src,
1481 qemuDomainSecretInfo *secinfo,
1482 char **source)
1483 {
1484 int actualType = virStorageSourceGetActualType(src);
1485
1486 *source = NULL;
1487
1488 /* return 1 for empty sources */
1489 if (virStorageSourceIsEmpty(src))
1490 return 1;
1491
1492 switch ((virStorageType)actualType) {
1493 case VIR_STORAGE_TYPE_BLOCK:
1494 case VIR_STORAGE_TYPE_FILE:
1495 case VIR_STORAGE_TYPE_DIR:
1496 *source = g_strdup(src->path);
1497
1498 break;
1499
1500 case VIR_STORAGE_TYPE_NETWORK:
1501 if (!(*source = qemuBuildNetworkDriveStr(src, secinfo)))
1502 return -1;
1503 break;
1504
1505 case VIR_STORAGE_TYPE_VOLUME:
1506 case VIR_STORAGE_TYPE_NVME:
1507 case VIR_STORAGE_TYPE_VHOST_USER:
1508 case VIR_STORAGE_TYPE_NONE:
1509 case VIR_STORAGE_TYPE_LAST:
1510 break;
1511 }
1512
1513 return 0;
1514 }
1515
1516
1517 bool
qemuDiskConfigBlkdeviotuneEnabled(virDomainDiskDef * disk)1518 qemuDiskConfigBlkdeviotuneEnabled(virDomainDiskDef *disk)
1519 {
1520 return !!disk->blkdeviotune.group_name ||
1521 virDomainBlockIoTuneInfoHasAny(&disk->blkdeviotune);
1522 }
1523
1524
1525 /* QEMU 1.2 and later have a binary flag -enable-fips that must be
1526 * used for VNC auth to obey FIPS settings; but the flag only
1527 * exists on Linux, and with no way to probe for it via QMP. Our
1528 * solution: if FIPS mode is required, then unconditionally use
1529 * the flag, regardless of qemu version, for the following matrix:
1530 *
1531 * old QEMU new QEMU
1532 * FIPS enabled doesn't start VNC auth disabled
1533 * FIPS disabled/missing VNC auth enabled VNC auth enabled
1534 *
1535 * In QEMU 5.2.0, use of -enable-fips was deprecated. In scenarios
1536 * where FIPS is required, QEMU must be built against libgcrypt
1537 * which automatically enforces FIPS compliance.
1538 */
1539 bool
qemuCheckFips(virDomainObj * vm)1540 qemuCheckFips(virDomainObj *vm)
1541 {
1542 qemuDomainObjPrivate *priv = vm->privateData;
1543 virQEMUCaps *qemuCaps = priv->qemuCaps;
1544
1545 if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_ENABLE_FIPS))
1546 return false;
1547
1548 if (virFileExists("/proc/sys/crypto/fips_enabled")) {
1549 g_autofree char *buf = NULL;
1550
1551 if (virFileReadAll("/proc/sys/crypto/fips_enabled", 10, &buf) < 0)
1552 return false;
1553 if (STREQ(buf, "1\n"))
1554 return true;
1555 }
1556
1557 return false;
1558 }
1559
1560
1561 /**
1562 * qemuDiskBusIsSD:
1563 * @bus: disk bus
1564 *
1565 * Unfortunately it is not possible to use -device for SD devices.
1566 * Fortunately, those don't need static PCI addresses, so we can use -drive
1567 * without -device.
1568 */
1569 bool
qemuDiskBusIsSD(int bus)1570 qemuDiskBusIsSD(int bus)
1571 {
1572 return bus == VIR_DOMAIN_DISK_BUS_SD;
1573 }
1574
1575
1576 /**
1577 * qemuDiskSourceNeedsProps:
1578 * @src: disk source
1579 *
1580 * Returns true, if the disk source needs to be generated from the JSON
1581 * representation. Otherwise, the disk source should be represented using
1582 * the legacy representation.
1583 */
1584 static bool
qemuDiskSourceNeedsProps(virStorageSource * src)1585 qemuDiskSourceNeedsProps(virStorageSource *src)
1586 {
1587 int actualType = virStorageSourceGetActualType(src);
1588
1589 if (actualType == VIR_STORAGE_TYPE_NETWORK &&
1590 src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER &&
1591 src->nhosts > 1)
1592 return true;
1593
1594 if (actualType == VIR_STORAGE_TYPE_NETWORK &&
1595 src->protocol == VIR_STORAGE_NET_PROTOCOL_VXHS)
1596 return true;
1597
1598 if (actualType == VIR_STORAGE_TYPE_NETWORK &&
1599 src->protocol == VIR_STORAGE_NET_PROTOCOL_ISCSI)
1600 return true;
1601
1602 if (actualType == VIR_STORAGE_TYPE_NETWORK &&
1603 src->protocol == VIR_STORAGE_NET_PROTOCOL_NBD &&
1604 src->haveTLS == VIR_TRISTATE_BOOL_YES)
1605 return true;
1606
1607 if (actualType == VIR_STORAGE_TYPE_NVME)
1608 return true;
1609
1610 return false;
1611 }
1612
1613
1614 /**
1615 * qemuDiskSourceGetProps:
1616 * @src: disk source struct
1617 *
1618 * Returns the disk source struct wrapped so that it can be used as disk source
1619 * directly by converting it from json.
1620 */
1621 static virJSONValue *
qemuDiskSourceGetProps(virStorageSource * src)1622 qemuDiskSourceGetProps(virStorageSource *src)
1623 {
1624 g_autoptr(virJSONValue) props = NULL;
1625 virJSONValue *ret = NULL;
1626
1627 if (!(props = qemuBlockStorageSourceGetBackendProps(src,
1628 QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_LEGACY)))
1629 return NULL;
1630
1631 if (virJSONValueObjectAdd(&ret, "a:file", &props, NULL) < 0)
1632 return NULL;
1633
1634 return ret;
1635 }
1636
1637
1638 static int
qemuBuildDriveSourcePR(virBuffer * buf,virDomainDiskDef * disk)1639 qemuBuildDriveSourcePR(virBuffer *buf,
1640 virDomainDiskDef *disk)
1641 {
1642 g_autofree char *alias = NULL;
1643 const char *defaultAlias = NULL;
1644
1645 if (!disk->src->pr)
1646 return 0;
1647
1648 if (virStoragePRDefIsManaged(disk->src->pr))
1649 defaultAlias = qemuDomainGetManagedPRAlias();
1650 else if (!(alias = qemuDomainGetUnmanagedPRAlias(disk->info.alias)))
1651 return -1;
1652
1653
1654 virBufferAsprintf(buf, ",file.pr-manager=%s", alias ? alias : defaultAlias);
1655 return 0;
1656 }
1657
1658
1659 static int
qemuBuildDriveSourceStr(virDomainDiskDef * disk,virBuffer * buf)1660 qemuBuildDriveSourceStr(virDomainDiskDef *disk,
1661 virBuffer *buf)
1662 {
1663 int actualType = virStorageSourceGetActualType(disk->src);
1664 qemuDomainStorageSourcePrivate *srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(disk->src);
1665 qemuDomainSecretInfo *secinfo = NULL;
1666 qemuDomainSecretInfo *encinfo = NULL;
1667 g_autoptr(virJSONValue) srcprops = NULL;
1668 g_autofree char *source = NULL;
1669 bool rawluks = false;
1670
1671 if (srcpriv) {
1672 secinfo = srcpriv->secinfo;
1673 encinfo = srcpriv->encinfo;
1674 }
1675
1676 if (qemuDiskSourceNeedsProps(disk->src) &&
1677 !(srcprops = qemuDiskSourceGetProps(disk->src)))
1678 return -1;
1679
1680 if (!srcprops &&
1681 qemuGetDriveSourceString(disk->src, secinfo, &source) < 0)
1682 return -1;
1683
1684 /* nothing to format if the drive is empty */
1685 if (!(source || srcprops) ||
1686 ((disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY ||
1687 disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
1688 disk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN)) {
1689 return 0;
1690 }
1691
1692 if (actualType == VIR_STORAGE_TYPE_BLOCK &&
1693 disk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN) {
1694 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1695 disk->src->type == VIR_STORAGE_TYPE_VOLUME ?
1696 _("tray status 'open' is invalid for block type volume") :
1697 _("tray status 'open' is invalid for block type disk"));
1698 return -1;
1699 }
1700
1701 if (source) {
1702 virBufferAddLit(buf, "file=");
1703
1704 /* for now the DIR based storage is handled by the magic FAT format */
1705 if (actualType == VIR_STORAGE_TYPE_DIR) {
1706 virBufferAddLit(buf, "fat:");
1707
1708 if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
1709 virBufferAddLit(buf, "floppy:");
1710 }
1711
1712 virQEMUBuildBufferEscapeComma(buf, source);
1713
1714 if (secinfo)
1715 virBufferAsprintf(buf, ",file.password-secret=%s", secinfo->alias);
1716
1717 if (disk->src->debug)
1718 virBufferAsprintf(buf, ",file.debug=%d", disk->src->debugLevel);
1719
1720 if (qemuBuildDriveSourcePR(buf, disk) < 0)
1721 return -1;
1722 } else {
1723 if (virQEMUBuildCommandLineJSON(srcprops, buf, NULL,
1724 virQEMUBuildCommandLineJSONArrayNumbered) < 0)
1725 return -1;
1726 }
1727 virBufferAddLit(buf, ",");
1728
1729 if (encinfo) {
1730 if (disk->src->format == VIR_STORAGE_FILE_RAW) {
1731 virBufferAsprintf(buf, "key-secret=%s,", encinfo->alias);
1732 rawluks = true;
1733 } else if (disk->src->format == VIR_STORAGE_FILE_QCOW2 &&
1734 disk->src->encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
1735 virBufferAddLit(buf, "encrypt.format=luks,");
1736 virBufferAsprintf(buf, "encrypt.key-secret=%s,", encinfo->alias);
1737 }
1738 }
1739
1740 if (disk->src->format > 0 &&
1741 actualType != VIR_STORAGE_TYPE_DIR) {
1742 const char *qemuformat = virStorageFileFormatTypeToString(disk->src->format);
1743 if (rawluks)
1744 qemuformat = "luks";
1745 virBufferAsprintf(buf, "format=%s,", qemuformat);
1746 }
1747
1748 return 0;
1749 }
1750
1751
1752 static void
qemuBuildDiskThrottling(virDomainDiskDef * disk,virBuffer * buf)1753 qemuBuildDiskThrottling(virDomainDiskDef *disk,
1754 virBuffer *buf)
1755 {
1756 #define IOTUNE_ADD(_field, _label) \
1757 if (disk->blkdeviotune._field) { \
1758 virBufferAsprintf(buf, ",throttling." _label "=%llu", \
1759 disk->blkdeviotune._field); \
1760 }
1761
1762 IOTUNE_ADD(total_bytes_sec, "bps-total");
1763 IOTUNE_ADD(read_bytes_sec, "bps-read");
1764 IOTUNE_ADD(write_bytes_sec, "bps-write");
1765 IOTUNE_ADD(total_iops_sec, "iops-total");
1766 IOTUNE_ADD(read_iops_sec, "iops-read");
1767 IOTUNE_ADD(write_iops_sec, "iops-write");
1768
1769 IOTUNE_ADD(total_bytes_sec_max, "bps-total-max");
1770 IOTUNE_ADD(read_bytes_sec_max, "bps-read-max");
1771 IOTUNE_ADD(write_bytes_sec_max, "bps-write-max");
1772 IOTUNE_ADD(total_iops_sec_max, "iops-total-max");
1773 IOTUNE_ADD(read_iops_sec_max, "iops-read-max");
1774 IOTUNE_ADD(write_iops_sec_max, "iops-write-max");
1775
1776 IOTUNE_ADD(size_iops_sec, "iops-size");
1777 if (disk->blkdeviotune.group_name) {
1778 virBufferAddLit(buf, ",throttling.group=");
1779 virQEMUBuildBufferEscapeComma(buf, disk->blkdeviotune.group_name);
1780 }
1781
1782 IOTUNE_ADD(total_bytes_sec_max_length, "bps-total-max-length");
1783 IOTUNE_ADD(read_bytes_sec_max_length, "bps-read-max-length");
1784 IOTUNE_ADD(write_bytes_sec_max_length, "bps-write-max-length");
1785 IOTUNE_ADD(total_iops_sec_max_length, "iops-total-max-length");
1786 IOTUNE_ADD(read_iops_sec_max_length, "iops-read-max-length");
1787 IOTUNE_ADD(write_iops_sec_max_length, "iops-write-max-length");
1788 #undef IOTUNE_ADD
1789 }
1790
1791
1792 static void
qemuBuildDiskGetErrorPolicy(virDomainDiskDef * disk,const char ** wpolicy,const char ** rpolicy)1793 qemuBuildDiskGetErrorPolicy(virDomainDiskDef *disk,
1794 const char **wpolicy,
1795 const char **rpolicy)
1796 {
1797 if (disk->error_policy)
1798 *wpolicy = virDomainDiskErrorPolicyTypeToString(disk->error_policy);
1799
1800 if (disk->rerror_policy)
1801 *rpolicy = virDomainDiskErrorPolicyTypeToString(disk->rerror_policy);
1802
1803 if (disk->error_policy == VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE) {
1804 /* in the case of enospace, the option is spelled
1805 * differently in qemu, and it's only valid for werror,
1806 * not for rerror, so leave rerror NULL.
1807 */
1808 *wpolicy = "enospc";
1809 } else if (!*rpolicy) {
1810 /* for other policies, rpolicy can match wpolicy */
1811 *rpolicy = *wpolicy;
1812 }
1813 }
1814
1815
1816 static void
qemuBuildDiskFrontendAttributeErrorPolicy(virDomainDiskDef * disk,virBuffer * buf)1817 qemuBuildDiskFrontendAttributeErrorPolicy(virDomainDiskDef *disk,
1818 virBuffer *buf)
1819 {
1820 const char *wpolicy = NULL;
1821 const char *rpolicy = NULL;
1822
1823 qemuBuildDiskGetErrorPolicy(disk, &wpolicy, &rpolicy);
1824
1825 if (wpolicy)
1826 virBufferAsprintf(buf, ",werror=%s", wpolicy);
1827 if (rpolicy)
1828 virBufferAsprintf(buf, ",rerror=%s", rpolicy);
1829 }
1830
1831
1832 static char *
qemuBuildDriveStr(virDomainDiskDef * disk,virQEMUCaps * qemuCaps)1833 qemuBuildDriveStr(virDomainDiskDef *disk,
1834 virQEMUCaps *qemuCaps)
1835 {
1836 g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
1837 int detect_zeroes = virDomainDiskGetDetectZeroesMode(disk->discard,
1838 disk->detect_zeroes);
1839
1840 if (qemuBuildDriveSourceStr(disk, &opt) < 0)
1841 return NULL;
1842
1843 if (!qemuDiskBusIsSD(disk->bus)) {
1844 g_autofree char *drivealias = qemuAliasDiskDriveFromDisk(disk);
1845 if (!drivealias)
1846 return NULL;
1847
1848 virBufferAddLit(&opt, "if=none");
1849 virBufferAsprintf(&opt, ",id=%s", drivealias);
1850 } else {
1851 virBufferAsprintf(&opt, "if=sd,index=%d",
1852 virDiskNameToIndex(disk->dst));
1853 }
1854
1855 /* werror/rerror are really frontend attributes, but older
1856 * qemu requires them on -drive instead of -device */
1857 if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_STORAGE_WERROR))
1858 qemuBuildDiskFrontendAttributeErrorPolicy(disk, &opt);
1859
1860 if (disk->src->readonly)
1861 virBufferAddLit(&opt, ",readonly=on");
1862
1863 /* qemu rejects some parameters for an empty -drive, so we need to skip
1864 * them in that case:
1865 * cache: modifies properties of the format driver which is not present
1866 * copy_on_read: really only works for floppies
1867 * discard: modifies properties of format driver
1868 * detect_zeroes: works but really depends on discard so it's useless
1869 * iomode: setting it to 'native' requires a specific cache mode
1870 */
1871 if (!virStorageSourceIsEmpty(disk->src)) {
1872 if (disk->cachemode) {
1873 virBufferAsprintf(&opt, ",cache=%s",
1874 qemuDiskCacheV2TypeToString(disk->cachemode));
1875 }
1876
1877 if (disk->copy_on_read) {
1878 virBufferAsprintf(&opt, ",copy-on-read=%s",
1879 virTristateSwitchTypeToString(disk->copy_on_read));
1880 }
1881
1882 if (disk->discard) {
1883 virBufferAsprintf(&opt, ",discard=%s",
1884 virDomainDiskDiscardTypeToString(disk->discard));
1885 }
1886
1887 if (detect_zeroes) {
1888 virBufferAsprintf(&opt, ",detect-zeroes=%s",
1889 virDomainDiskDetectZeroesTypeToString(detect_zeroes));
1890 }
1891
1892 if (disk->iomode) {
1893 virBufferAsprintf(&opt, ",aio=%s",
1894 virDomainDiskIoTypeToString(disk->iomode));
1895 }
1896 }
1897
1898 qemuBuildDiskThrottling(disk, &opt);
1899
1900 return virBufferContentAndReset(&opt);
1901 }
1902
1903
1904 virJSONValue *
qemuBuildDiskDeviceProps(const virDomainDef * def,virDomainDiskDef * disk,virQEMUCaps * qemuCaps)1905 qemuBuildDiskDeviceProps(const virDomainDef *def,
1906 virDomainDiskDef *disk,
1907 virQEMUCaps *qemuCaps)
1908 {
1909 g_autoptr(virJSONValue) props = NULL;
1910 const char *driver = NULL;
1911 g_autofree char *scsiVPDDeviceId = NULL;
1912 virTristateSwitch shareRW = VIR_TRISTATE_SWITCH_ABSENT;
1913 g_autofree char *chardev = NULL;
1914 g_autofree char *drive = NULL;
1915 unsigned int bootindex = 0;
1916 unsigned int logical_block_size = 0;
1917 unsigned int physical_block_size = 0;
1918 g_autoptr(virJSONValue) wwn = NULL;
1919 g_autofree char *serial = NULL;
1920 virTristateSwitch removable = VIR_TRISTATE_SWITCH_ABSENT;
1921 virTristateSwitch writeCache = VIR_TRISTATE_SWITCH_ABSENT;
1922 const char *biosCHSTrans = NULL;
1923 const char *wpolicy = NULL;
1924 const char *rpolicy = NULL;
1925
1926 switch ((virDomainDiskBus) disk->bus) {
1927 case VIR_DOMAIN_DISK_BUS_IDE:
1928 case VIR_DOMAIN_DISK_BUS_SATA:
1929 if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
1930 driver = "ide-cd";
1931 else
1932 driver = "ide-hd";
1933
1934 break;
1935
1936 case VIR_DOMAIN_DISK_BUS_SCSI:
1937 if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
1938 driver = "scsi-block";
1939 } else {
1940 if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
1941 driver = "scsi-cd";
1942 else
1943 driver = "scsi-hd";
1944
1945 /* qemu historically used the name of -drive as one of the device
1946 * ids in the Vital Product Data Device Identification page if
1947 * disk serial was not set and the disk serial otherwise.
1948 * To avoid a guest-visible regression we need to provide it
1949 * ourselves especially for cases when -blockdev will be used */
1950 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_DISK_DEVICE_ID)) {
1951 if (disk->serial) {
1952 scsiVPDDeviceId = g_strdup(disk->serial);
1953 } else {
1954 if (!(scsiVPDDeviceId = qemuAliasDiskDriveFromDisk(disk)))
1955 return NULL;
1956 }
1957 }
1958 }
1959
1960 break;
1961
1962 case VIR_DOMAIN_DISK_BUS_VIRTIO: {
1963 virTristateSwitch scsi = VIR_TRISTATE_SWITCH_ABSENT;
1964 g_autofree char *iothread = NULL;
1965
1966 if (disk->iothread > 0)
1967 iothread = g_strdup_printf("iothread%u", disk->iothread);
1968
1969 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SCSI)) {
1970 /* if sg_io is true but the scsi option isn't supported,
1971 * that means it's just always on in this version of qemu.
1972 */
1973 if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
1974 scsi = VIR_TRISTATE_SWITCH_ON;
1975 } else {
1976 if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SCSI_DEFAULT_DISABLED))
1977 scsi = VIR_TRISTATE_SWITCH_OFF;
1978 }
1979 }
1980
1981 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_DISK, disk, qemuCaps)))
1982 return NULL;
1983
1984 if (virJSONValueObjectAdd(&props,
1985 "S:iothread", iothread,
1986 "T:ioeventfd", disk->ioeventfd,
1987 "T:event_idx", disk->event_idx,
1988 "T:scsi", scsi,
1989 "p:num-queues", disk->queues,
1990 "p:queue-size", disk->queue_size,
1991 NULL) < 0)
1992 return NULL;
1993 }
1994 break;
1995
1996 case VIR_DOMAIN_DISK_BUS_USB:
1997 driver = "usb-storage";
1998
1999 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_STORAGE_REMOVABLE)) {
2000 if (disk->removable == VIR_TRISTATE_SWITCH_ABSENT)
2001 removable = VIR_TRISTATE_SWITCH_OFF;
2002 else
2003 removable = disk->removable;
2004 }
2005
2006 break;
2007
2008 case VIR_DOMAIN_DISK_BUS_FDC:
2009 driver = "floppy";
2010 break;
2011
2012 case VIR_DOMAIN_DISK_BUS_XEN:
2013 case VIR_DOMAIN_DISK_BUS_UML:
2014 case VIR_DOMAIN_DISK_BUS_SD:
2015 case VIR_DOMAIN_DISK_BUS_NONE:
2016 case VIR_DOMAIN_DISK_BUS_LAST:
2017 default:
2018 virReportError(VIR_ERR_INTERNAL_ERROR,
2019 _("unsupported disk bus '%s' with device setup"),
2020 NULLSTR(virDomainDiskBusTypeToString(disk->bus)));
2021 return NULL;
2022 }
2023
2024 if (driver) {
2025 if (virJSONValueObjectAdd(&props,
2026 "s:driver", driver,
2027 NULL) < 0)
2028 return NULL;
2029 }
2030
2031 if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
2032 disk->info.addr.drive.diskbus = disk->bus;
2033
2034 if (qemuBuildDeviceAddressProps(props, def, &disk->info) < 0)
2035 return NULL;
2036
2037 if (disk->src->shared &&
2038 virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_SHARE_RW))
2039 shareRW = VIR_TRISTATE_SWITCH_ON;
2040
2041 if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
2042 chardev = qemuDomainGetVhostUserChrAlias(disk->info.alias);
2043 } else {
2044 if (qemuDomainDiskGetBackendAlias(disk, qemuCaps, &drive) < 0)
2045 return NULL;
2046 }
2047
2048 /* bootindex for floppies is configured via the fdc controller */
2049 if (disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY)
2050 bootindex = disk->info.effectiveBootIndex;
2051
2052 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKIO)) {
2053 logical_block_size = disk->blockio.logical_block_size;
2054 physical_block_size = disk->blockio.physical_block_size;
2055 }
2056
2057 if (disk->wwn) {
2058 unsigned long long w = 0;
2059
2060 if (virStrToLong_ull(disk->wwn, NULL, 16, &w) < 0) {
2061 virReportError(VIR_ERR_INVALID_ARG,
2062 _("Failed to parse wwn '%s' as number"), disk->wwn);
2063 return NULL;
2064 }
2065
2066 wwn = virJSONValueNewNumberUlong(w);
2067 }
2068
2069 if (disk->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT) {
2070 /* VIR_DOMAIN_DISK_DEVICE_LUN translates into 'scsi-block'
2071 * where any caching setting makes no sense. */
2072 if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN &&
2073 virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_WRITE_CACHE)) {
2074 bool wb;
2075
2076 if (qemuDomainDiskCachemodeFlags(disk->cachemode, &wb, NULL,
2077 NULL) < 0)
2078 return NULL;
2079
2080 writeCache = virTristateSwitchFromBool(wb);
2081 }
2082 }
2083
2084 if (disk->geometry.trans != VIR_DOMAIN_DISK_TRANS_DEFAULT)
2085 biosCHSTrans = virDomainDiskGeometryTransTypeToString(disk->geometry.trans);
2086
2087 if (disk->serial) {
2088 virBuffer buf = VIR_BUFFER_INITIALIZER;
2089
2090 virBufferEscape(&buf, '\\', " ", "%s", disk->serial);
2091 serial = virBufferContentAndReset(&buf);
2092 }
2093
2094 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_STORAGE_WERROR))
2095 qemuBuildDiskGetErrorPolicy(disk, &wpolicy, &rpolicy);
2096
2097 if (virJSONValueObjectAdd(&props,
2098 "S:device_id", scsiVPDDeviceId,
2099 "T:share-rw", shareRW,
2100 "S:drive", drive,
2101 "S:chardev", chardev,
2102 "s:id", disk->info.alias,
2103 "p:bootindex", bootindex,
2104 "p:logical_block_size", logical_block_size,
2105 "p:physical_block_size", physical_block_size,
2106 "A:wwn", &wwn,
2107 "p:rotation_rate", disk->rotation_rate,
2108 "S:vendor", disk->vendor,
2109 "S:product", disk->product,
2110 "T:removable", removable,
2111 "S:write-cache", qemuOnOffAuto(writeCache),
2112 "p:cyls", disk->geometry.cylinders,
2113 "p:heads", disk->geometry.heads,
2114 "p:secs", disk->geometry.sectors,
2115 "S:bios-chs-trans", biosCHSTrans,
2116 "S:serial", serial,
2117 "S:werror", wpolicy,
2118 "S:rerror", rpolicy,
2119 NULL) < 0)
2120 return NULL;
2121
2122 return g_steal_pointer(&props);
2123 }
2124
2125
2126 virJSONValue *
qemuBuildZPCIDevProps(virDomainDeviceInfo * dev)2127 qemuBuildZPCIDevProps(virDomainDeviceInfo *dev)
2128 {
2129 virJSONValue *props = NULL;
2130 g_autofree char *alias = g_strdup_printf("zpci%u", dev->addr.pci.zpci.uid.value);
2131
2132 virJSONValueObjectAdd(&props,
2133 "s:driver", "zpci",
2134 "u:uid", dev->addr.pci.zpci.uid.value,
2135 "u:fid", dev->addr.pci.zpci.fid.value,
2136 "s:target", dev->alias,
2137 "s:id", alias,
2138 NULL);
2139
2140 return props;
2141 }
2142
2143
2144 static int
qemuCommandAddExtDevice(virCommand * cmd,virDomainDeviceInfo * dev,virQEMUCaps * qemuCaps)2145 qemuCommandAddExtDevice(virCommand *cmd,
2146 virDomainDeviceInfo *dev,
2147 virQEMUCaps *qemuCaps)
2148 {
2149 if (dev->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
2150 dev->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
2151 return 0;
2152 }
2153
2154 if (dev->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
2155 g_autoptr(virJSONValue) devprops = NULL;
2156
2157 if (!(devprops = qemuBuildZPCIDevProps(dev)))
2158 return -1;
2159
2160 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
2161 return -1;
2162 }
2163
2164 return 0;
2165 }
2166
2167
2168 static void
qemuBuildFloppyCommandLineControllerOptionsImplicit(virCommand * cmd,unsigned int bootindexA,unsigned int bootindexB,const char * backendA,const char * backendB)2169 qemuBuildFloppyCommandLineControllerOptionsImplicit(virCommand *cmd,
2170 unsigned int bootindexA,
2171 unsigned int bootindexB,
2172 const char *backendA,
2173 const char *backendB)
2174 {
2175 if (backendA) {
2176 virCommandAddArg(cmd, "-global");
2177 virCommandAddArgFormat(cmd, "isa-fdc.driveA=%s", backendA);
2178 }
2179
2180 if (bootindexA > 0) {
2181 virCommandAddArg(cmd, "-global");
2182 virCommandAddArgFormat(cmd, "isa-fdc.bootindexA=%u", bootindexA);
2183 }
2184
2185 if (backendB) {
2186 virCommandAddArg(cmd, "-global");
2187 virCommandAddArgFormat(cmd, "isa-fdc.driveB=%s", backendB);
2188 }
2189
2190 if (bootindexB > 0) {
2191 virCommandAddArg(cmd, "-global");
2192 virCommandAddArgFormat(cmd, "isa-fdc.bootindexB=%u", bootindexB);
2193 }
2194 }
2195
2196
2197 static int
qemuBuildFloppyCommandLineControllerOptionsExplicit(virCommand * cmd,unsigned int bootindexA,unsigned int bootindexB,const char * backendA,const char * backendB,virQEMUCaps * qemuCaps)2198 qemuBuildFloppyCommandLineControllerOptionsExplicit(virCommand *cmd,
2199 unsigned int bootindexA,
2200 unsigned int bootindexB,
2201 const char *backendA,
2202 const char *backendB,
2203 virQEMUCaps *qemuCaps)
2204 {
2205 g_autoptr(virJSONValue) props = NULL;
2206
2207 if (virJSONValueObjectAdd(&props,
2208 "s:driver", "isa-fdc",
2209 "S:driveA", backendA,
2210 "p:bootindexA", bootindexA,
2211 "S:driveB", backendB,
2212 "p:bootindexB", bootindexB,
2213 NULL) < 0)
2214 return -1;
2215
2216 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
2217 return -1;
2218
2219 return 0;
2220 }
2221
2222
2223 static int
qemuBuildFloppyCommandLineControllerOptions(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)2224 qemuBuildFloppyCommandLineControllerOptions(virCommand *cmd,
2225 const virDomainDef *def,
2226 virQEMUCaps *qemuCaps)
2227 {
2228 unsigned int bootindexA = 0;
2229 unsigned int bootindexB = 0;
2230 g_autofree char *backendA = NULL;
2231 g_autofree char *backendB = NULL;
2232 bool hasfloppy = false;
2233 size_t i;
2234
2235 for (i = 0; i < def->ndisks; i++) {
2236 g_autofree char *backendAlias = NULL;
2237 virDomainDiskDef *disk = def->disks[i];
2238
2239 if (disk->bus != VIR_DOMAIN_DISK_BUS_FDC)
2240 continue;
2241
2242 hasfloppy = true;
2243
2244 /* with -blockdev we setup the floppy device and it's backend with -device */
2245 if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV) &&
2246 qemuDomainDiskGetBackendAlias(disk, qemuCaps, &backendAlias) < 0)
2247 return -1;
2248
2249 if (disk->info.addr.drive.unit) {
2250 bootindexB = disk->info.effectiveBootIndex;
2251 backendB = g_steal_pointer(&backendAlias);
2252 } else {
2253 bootindexA = disk->info.effectiveBootIndex;
2254 backendA = g_steal_pointer(&backendAlias);
2255 }
2256 }
2257
2258 if (!hasfloppy)
2259 return 0;
2260
2261 if (qemuDomainNeedsFDC(def)) {
2262 if (qemuBuildFloppyCommandLineControllerOptionsExplicit(cmd,
2263 bootindexA,
2264 bootindexB,
2265 backendA,
2266 backendB,
2267 qemuCaps) < 0)
2268 return -1;
2269 } else {
2270 qemuBuildFloppyCommandLineControllerOptionsImplicit(cmd,
2271 bootindexA,
2272 bootindexB,
2273 backendA,
2274 backendB);
2275 }
2276
2277 return 0;
2278 }
2279
2280
2281 static int
qemuBuildObjectCommandline(virCommand * cmd,virJSONValue * objProps,virQEMUCaps * qemuCaps)2282 qemuBuildObjectCommandline(virCommand *cmd,
2283 virJSONValue *objProps,
2284 virQEMUCaps *qemuCaps)
2285 {
2286 if (!objProps)
2287 return 0;
2288
2289 if (qemuBuildObjectCommandlineFromJSON(cmd, objProps, qemuCaps) < 0)
2290 return -1;
2291
2292 return 0;
2293 }
2294
2295
2296 static int
qemuBuildBlockStorageSourceAttachDataCommandline(virCommand * cmd,qemuBlockStorageSourceAttachData * data,virQEMUCaps * qemuCaps)2297 qemuBuildBlockStorageSourceAttachDataCommandline(virCommand *cmd,
2298 qemuBlockStorageSourceAttachData *data,
2299 virQEMUCaps *qemuCaps)
2300 {
2301 char *tmp;
2302
2303 if (qemuBuildObjectCommandline(cmd, data->prmgrProps, qemuCaps) < 0 ||
2304 qemuBuildObjectCommandline(cmd, data->authsecretProps, qemuCaps) < 0 ||
2305 qemuBuildObjectCommandline(cmd, data->encryptsecretProps, qemuCaps) < 0 ||
2306 qemuBuildObjectCommandline(cmd, data->httpcookiesecretProps, qemuCaps) < 0 ||
2307 qemuBuildObjectCommandline(cmd, data->tlsKeySecretProps, qemuCaps) < 0 ||
2308 qemuBuildObjectCommandline(cmd, data->tlsProps, qemuCaps) < 0)
2309 return -1;
2310
2311 if (data->driveCmd)
2312 virCommandAddArgList(cmd, "-drive", data->driveCmd, NULL);
2313
2314 if (data->chardevCmd)
2315 virCommandAddArgList(cmd, "-chardev", data->chardevCmd, NULL);
2316
2317 if (data->storageProps) {
2318 if (!(tmp = virJSONValueToString(data->storageProps, false)))
2319 return -1;
2320
2321 virCommandAddArgList(cmd, "-blockdev", tmp, NULL);
2322 VIR_FREE(tmp);
2323 }
2324
2325 if (data->storageSliceProps) {
2326 if (!(tmp = virJSONValueToString(data->storageSliceProps, false)))
2327 return -1;
2328
2329 virCommandAddArgList(cmd, "-blockdev", tmp, NULL);
2330 VIR_FREE(tmp);
2331 }
2332
2333 if (data->formatProps) {
2334 if (!(tmp = virJSONValueToString(data->formatProps, false)))
2335 return -1;
2336
2337 virCommandAddArgList(cmd, "-blockdev", tmp, NULL);
2338 VIR_FREE(tmp);
2339 }
2340
2341 return 0;
2342 }
2343
2344
2345 static int
qemuBuildDiskSourceCommandLine(virCommand * cmd,virDomainDiskDef * disk,virQEMUCaps * qemuCaps)2346 qemuBuildDiskSourceCommandLine(virCommand *cmd,
2347 virDomainDiskDef *disk,
2348 virQEMUCaps *qemuCaps)
2349 {
2350 g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
2351 g_autoptr(virJSONValue) copyOnReadProps = NULL;
2352 g_autofree char *copyOnReadPropsStr = NULL;
2353 size_t i;
2354
2355 if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
2356 if (!(data = qemuBuildStorageSourceChainAttachPrepareChardev(disk)))
2357 return -1;
2358 } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV) &&
2359 !qemuDiskBusIsSD(disk->bus)) {
2360 if (virStorageSourceIsEmpty(disk->src))
2361 return 0;
2362
2363 if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(disk->src)))
2364 return -1;
2365
2366 if (disk->copy_on_read == VIR_TRISTATE_SWITCH_ON &&
2367 !(copyOnReadProps = qemuBlockStorageGetCopyOnReadProps(disk)))
2368 return -1;
2369 } else {
2370 if (!(data = qemuBuildStorageSourceChainAttachPrepareDrive(disk, qemuCaps)))
2371 return -1;
2372 }
2373
2374 for (i = data->nsrcdata; i > 0; i--) {
2375 if (qemuBuildBlockStorageSourceAttachDataCommandline(cmd,
2376 data->srcdata[i - 1],
2377 qemuCaps) < 0)
2378 return -1;
2379 }
2380
2381 if (copyOnReadProps) {
2382 if (!(copyOnReadPropsStr = virJSONValueToString(copyOnReadProps, false)))
2383 return -1;
2384
2385 virCommandAddArgList(cmd, "-blockdev", copyOnReadPropsStr, NULL);
2386 }
2387
2388 return 0;
2389 }
2390
2391
2392 static int
qemuBuildDiskCommandLine(virCommand * cmd,const virDomainDef * def,virDomainDiskDef * disk,virQEMUCaps * qemuCaps)2393 qemuBuildDiskCommandLine(virCommand *cmd,
2394 const virDomainDef *def,
2395 virDomainDiskDef *disk,
2396 virQEMUCaps *qemuCaps)
2397 {
2398 g_autoptr(virJSONValue) devprops = NULL;
2399
2400 if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps) < 0)
2401 return -1;
2402
2403 /* SD cards are currently instantiated via -drive if=sd, so the -device
2404 * part must be skipped */
2405 if (qemuDiskBusIsSD(disk->bus))
2406 return 0;
2407
2408 /* floppy devices are instantiated via -drive ...,if=none and bound to the
2409 * controller via -global isa-fdc.driveA/B options in the pre-blockdev era */
2410 if (disk->bus == VIR_DOMAIN_DISK_BUS_FDC &&
2411 !virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV))
2412 return 0;
2413
2414 if (qemuCommandAddExtDevice(cmd, &disk->info, qemuCaps) < 0)
2415 return -1;
2416
2417 if (!(devprops = qemuBuildDiskDeviceProps(def, disk, qemuCaps)))
2418 return -1;
2419
2420 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
2421 return -1;
2422
2423 return 0;
2424 }
2425
2426
2427 static int
qemuBuildDisksCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)2428 qemuBuildDisksCommandLine(virCommand *cmd,
2429 const virDomainDef *def,
2430 virQEMUCaps *qemuCaps)
2431 {
2432 size_t i;
2433 bool blockdev = virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV);
2434
2435 /* If we want to express the floppy drives via -device, the controller needs
2436 * to be instantiated prior to that */
2437 if (blockdev &&
2438 qemuBuildFloppyCommandLineControllerOptions(cmd, def, qemuCaps) < 0)
2439 return -1;
2440
2441 for (i = 0; i < def->ndisks; i++) {
2442 virDomainDiskDef *disk = def->disks[i];
2443
2444 /* transient disks with shared backing image will be hotplugged after
2445 * the VM is started */
2446 if (disk->transient &&
2447 disk->transientShareBacking == VIR_TRISTATE_BOOL_YES)
2448 continue;
2449
2450 if (qemuBuildDiskCommandLine(cmd, def, disk, qemuCaps) < 0)
2451 return -1;
2452 }
2453
2454 if (!blockdev &&
2455 qemuBuildFloppyCommandLineControllerOptions(cmd, def, qemuCaps) < 0)
2456 return -1;
2457
2458 return 0;
2459 }
2460
2461
2462 static char *
qemuBuildVHostUserFsChardevStr(const virDomainFSDef * fs,const char * chardev_alias,qemuDomainObjPrivate * priv)2463 qemuBuildVHostUserFsChardevStr(const virDomainFSDef *fs,
2464 const char *chardev_alias,
2465 qemuDomainObjPrivate *priv)
2466 {
2467 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
2468 g_autofree char *socket_path = qemuDomainGetVHostUserFSSocketPath(priv, fs);
2469
2470 virBufferAddLit(&buf, "socket");
2471 virBufferAsprintf(&buf, ",id=%s", chardev_alias);
2472 virBufferAddLit(&buf, ",path=");
2473 virQEMUBuildBufferEscapeComma(&buf, socket_path);
2474 return virBufferContentAndReset(&buf);
2475 }
2476
2477
2478 virJSONValue *
qemuBuildVHostUserFsDevProps(virDomainFSDef * fs,const virDomainDef * def,const char * chardev_alias,qemuDomainObjPrivate * priv)2479 qemuBuildVHostUserFsDevProps(virDomainFSDef *fs,
2480 const virDomainDef *def,
2481 const char *chardev_alias,
2482 qemuDomainObjPrivate *priv)
2483 {
2484 g_autoptr(virJSONValue) props = NULL;
2485
2486 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_FS, fs, priv->qemuCaps)))
2487 return NULL;
2488
2489 if (virJSONValueObjectAdd(&props,
2490 "s:id", fs->info.alias,
2491 "s:chardev", chardev_alias,
2492 "P:queue-size", fs->queue_size,
2493 "s:tag", fs->dst,
2494 "p:bootindex", fs->info.bootIndex,
2495 NULL) < 0)
2496 return NULL;
2497
2498 if (qemuBuildDeviceAddressProps(props, def, &fs->info) < 0)
2499 return NULL;
2500
2501 return g_steal_pointer(&props);
2502 }
2503
2504
2505 static int
qemuBuildVHostUserFsCommandLine(virCommand * cmd,virDomainFSDef * fs,const virDomainDef * def,qemuDomainObjPrivate * priv)2506 qemuBuildVHostUserFsCommandLine(virCommand *cmd,
2507 virDomainFSDef *fs,
2508 const virDomainDef *def,
2509 qemuDomainObjPrivate *priv)
2510 {
2511 g_autofree char *chardev_alias = NULL;
2512 g_autofree char *chrdevstr = NULL;
2513 g_autoptr(virJSONValue) devprops = NULL;
2514
2515 chardev_alias = qemuDomainGetVhostUserChrAlias(fs->info.alias);
2516 chrdevstr = qemuBuildVHostUserFsChardevStr(fs, chardev_alias, priv);
2517
2518 virCommandAddArg(cmd, "-chardev");
2519 virCommandAddArg(cmd, chrdevstr);
2520
2521 if (qemuCommandAddExtDevice(cmd, &fs->info, priv->qemuCaps) < 0)
2522 return -1;
2523
2524 if (!(devprops = qemuBuildVHostUserFsDevProps(fs, def, chardev_alias, priv)))
2525 return -1;
2526
2527 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, priv->qemuCaps) < 0)
2528 return -1;
2529
2530 return 0;
2531 }
2532
2533
2534 static char *
qemuBuildFSStr(virDomainFSDef * fs)2535 qemuBuildFSStr(virDomainFSDef *fs)
2536 {
2537 g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
2538 const char *wrpolicy = virDomainFSWrpolicyTypeToString(fs->wrpolicy);
2539
2540 if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_PATH ||
2541 fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_DEFAULT) {
2542 virBufferAddLit(&opt, "local");
2543 if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_MAPPED) {
2544 virBufferAddLit(&opt, ",security_model=mapped");
2545 } else if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
2546 virBufferAddLit(&opt, ",security_model=passthrough");
2547 } else if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_SQUASH) {
2548 virBufferAddLit(&opt, ",security_model=none");
2549 }
2550 if (fs->multidevs == VIR_DOMAIN_FS_MULTIDEVS_REMAP) {
2551 virBufferAddLit(&opt, ",multidevs=remap");
2552 } else if (fs->multidevs == VIR_DOMAIN_FS_MULTIDEVS_FORBID) {
2553 virBufferAddLit(&opt, ",multidevs=forbid");
2554 } else if (fs->multidevs == VIR_DOMAIN_FS_MULTIDEVS_WARN) {
2555 virBufferAddLit(&opt, ",multidevs=warn");
2556 }
2557 if (fs->fmode) {
2558 virBufferAsprintf(&opt, ",fmode=%04o", fs->fmode);
2559 }
2560 if (fs->dmode) {
2561 virBufferAsprintf(&opt, ",dmode=%04o", fs->dmode);
2562 }
2563 } else if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE) {
2564 /* removed since qemu 4.0.0 see v3.1.0-29-g93aee84f57 */
2565 virBufferAddLit(&opt, "handle");
2566 }
2567
2568 if (fs->wrpolicy)
2569 virBufferAsprintf(&opt, ",writeout=%s", wrpolicy);
2570
2571 virBufferAsprintf(&opt, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
2572 virBufferAddLit(&opt, ",path=");
2573 virQEMUBuildBufferEscapeComma(&opt, fs->src->path);
2574
2575 if (fs->readonly)
2576 virBufferAddLit(&opt, ",readonly");
2577
2578 return virBufferContentAndReset(&opt);
2579 }
2580
2581
2582 static int
qemuBuildFSDevCmd(virCommand * cmd,const virDomainDef * def,virDomainFSDef * fs,virQEMUCaps * qemuCaps)2583 qemuBuildFSDevCmd(virCommand *cmd,
2584 const virDomainDef *def,
2585 virDomainFSDef *fs,
2586 virQEMUCaps *qemuCaps)
2587 {
2588 g_autoptr(virJSONValue) devprops = NULL;
2589 g_autofree char *fsdev = g_strdup_printf("%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
2590
2591 if (!(devprops = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_FS, fs, qemuCaps)))
2592 return -1;
2593
2594 if (virJSONValueObjectAdd(&devprops,
2595 "s:id", fs->info.alias,
2596 "s:fsdev", fsdev,
2597 "s:mount_tag", fs->dst,
2598 NULL) < 0)
2599 return -1;
2600
2601 if (qemuBuildDeviceAddressProps(devprops, def, &fs->info) < 0)
2602 return -1;
2603
2604 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
2605 return -1;
2606
2607 return 0;
2608 }
2609
2610
2611 static int
qemuBuildFSDevCommandLine(virCommand * cmd,virDomainFSDef * fs,const virDomainDef * def,virQEMUCaps * qemuCaps)2612 qemuBuildFSDevCommandLine(virCommand *cmd,
2613 virDomainFSDef *fs,
2614 const virDomainDef *def,
2615 virQEMUCaps *qemuCaps)
2616 {
2617 g_autofree char *fsdevstr = NULL;
2618
2619 virCommandAddArg(cmd, "-fsdev");
2620 if (!(fsdevstr = qemuBuildFSStr(fs)))
2621 return -1;
2622 virCommandAddArg(cmd, fsdevstr);
2623
2624 if (qemuCommandAddExtDevice(cmd, &fs->info, qemuCaps) < 0)
2625 return -1;
2626
2627 if (qemuBuildFSDevCmd(cmd, def, fs, qemuCaps) < 0)
2628 return -1;
2629
2630 return 0;
2631 }
2632
2633
2634 static int
qemuBuildFilesystemCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps,qemuDomainObjPrivate * priv)2635 qemuBuildFilesystemCommandLine(virCommand *cmd,
2636 const virDomainDef *def,
2637 virQEMUCaps *qemuCaps,
2638 qemuDomainObjPrivate *priv)
2639 {
2640 size_t i;
2641
2642 for (i = 0; i < def->nfss; i++) {
2643 switch ((virDomainFSDriverType) def->fss[i]->fsdriver) {
2644 case VIR_DOMAIN_FS_DRIVER_TYPE_DEFAULT:
2645 case VIR_DOMAIN_FS_DRIVER_TYPE_PATH:
2646 case VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE:
2647 /* these drivers are handled by virtio-9p-pci */
2648 if (qemuBuildFSDevCommandLine(cmd, def->fss[i], def, qemuCaps) < 0)
2649 return -1;
2650 break;
2651
2652 case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS:
2653 /* vhost-user-fs-pci */
2654 if (qemuBuildVHostUserFsCommandLine(cmd, def->fss[i], def, priv) < 0)
2655 return -1;
2656 break;
2657
2658 case VIR_DOMAIN_FS_DRIVER_TYPE_LOOP:
2659 case VIR_DOMAIN_FS_DRIVER_TYPE_NBD:
2660 case VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP:
2661 case VIR_DOMAIN_FS_DRIVER_TYPE_LAST:
2662 break;
2663 }
2664 }
2665
2666 return 0;
2667 }
2668
2669
2670 static int
qemuControllerModelUSBToCaps(int model)2671 qemuControllerModelUSBToCaps(int model)
2672 {
2673 switch (model) {
2674 case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI:
2675 return QEMU_CAPS_PIIX3_USB_UHCI;
2676 case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI:
2677 return QEMU_CAPS_PIIX4_USB_UHCI;
2678 case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI:
2679 return QEMU_CAPS_USB_EHCI;
2680 case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
2681 case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
2682 case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
2683 case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
2684 return QEMU_CAPS_ICH9_USB_EHCI1;
2685 case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI:
2686 return QEMU_CAPS_VT82C686B_USB_UHCI;
2687 case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI:
2688 return QEMU_CAPS_PCI_OHCI;
2689 case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI:
2690 return QEMU_CAPS_NEC_USB_XHCI;
2691 case VIR_DOMAIN_CONTROLLER_MODEL_USB_QEMU_XHCI:
2692 return QEMU_CAPS_DEVICE_QEMU_XHCI;
2693 default:
2694 return -1;
2695 }
2696 }
2697
2698
2699 static int
qemuValidateDomainDeviceDefControllerUSB(const virDomainControllerDef * def,virQEMUCaps * qemuCaps)2700 qemuValidateDomainDeviceDefControllerUSB(const virDomainControllerDef *def,
2701 virQEMUCaps *qemuCaps)
2702 {
2703 if (def->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_DEFAULT) {
2704 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2705 _("no model provided for USB controller"));
2706 return -1;
2707 }
2708
2709 if (!virQEMUCapsGet(qemuCaps, qemuControllerModelUSBToCaps(def->model))) {
2710 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2711 _("USB controller model '%s' not supported in this QEMU binary"),
2712 virDomainControllerModelUSBTypeToString(def->model));
2713 return -1;
2714 }
2715
2716 if (def->opts.usbopts.ports != -1) {
2717 if ((def->model != VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI ||
2718 !virQEMUCapsGet(qemuCaps, QEMU_CAPS_NEC_USB_XHCI_PORTS)) &&
2719 def->model != VIR_DOMAIN_CONTROLLER_MODEL_USB_QEMU_XHCI) {
2720 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2721 _("usb controller type '%s' doesn't support 'ports' with this QEMU binary"),
2722 virDomainControllerModelUSBTypeToString(def->model));
2723 return -1;
2724 }
2725 }
2726
2727 return 0;
2728 }
2729
2730
2731 static const char *
qemuBuildUSBControllerFindMasterAlias(const virDomainDef * domainDef,const virDomainControllerDef * def)2732 qemuBuildUSBControllerFindMasterAlias(const virDomainDef *domainDef,
2733 const virDomainControllerDef *def)
2734 {
2735 size_t i;
2736
2737 for (i = 0; i < domainDef->ncontrollers; i++) {
2738 const virDomainControllerDef *tmp = domainDef->controllers[i];
2739
2740 if (tmp->type != VIR_DOMAIN_CONTROLLER_TYPE_USB)
2741 continue;
2742
2743 if (tmp->idx != def->idx)
2744 continue;
2745
2746 if (tmp->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB)
2747 continue;
2748
2749 return tmp->info.alias;
2750 }
2751
2752 return NULL;
2753 }
2754
2755
2756 static virJSONValue *
qemuBuildUSBControllerDevProps(const virDomainDef * domainDef,virDomainControllerDef * def,virQEMUCaps * qemuCaps)2757 qemuBuildUSBControllerDevProps(const virDomainDef *domainDef,
2758 virDomainControllerDef *def,
2759 virQEMUCaps *qemuCaps)
2760 {
2761 g_autoptr(virJSONValue) props = NULL;
2762
2763 if (qemuValidateDomainDeviceDefControllerUSB(def, qemuCaps) < 0)
2764 return NULL;
2765
2766 if (virJSONValueObjectAdd(&props,
2767 "s:driver", qemuControllerModelUSBTypeToString(def->model),
2768 "k:p2", def->opts.usbopts.ports,
2769 "k:p3", def->opts.usbopts.ports,
2770 NULL) < 0)
2771 return NULL;
2772
2773 if (def->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
2774 g_autofree char *masterbus = NULL;
2775 const char *alias;
2776
2777 if (!(alias = qemuBuildUSBControllerFindMasterAlias(domainDef, def))) {
2778 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2779 _("masterbus not found"));
2780 return NULL;
2781 }
2782
2783 masterbus = g_strdup_printf("%s.0", alias);
2784
2785 if (virJSONValueObjectAdd(&props,
2786 "s:masterbus", masterbus,
2787 "i:firstport", def->info.master.usb.startport,
2788 NULL) < 0)
2789 return NULL;
2790 } else {
2791 if (virJSONValueObjectAdd(&props,
2792 "s:id", def->info.alias,
2793 NULL) < 0)
2794 return NULL;
2795 }
2796
2797 return g_steal_pointer(&props);
2798 }
2799
2800
2801 static virJSONValue *
qemuBuildControllerSCSIDevProps(virDomainControllerDef * def,virQEMUCaps * qemuCaps)2802 qemuBuildControllerSCSIDevProps(virDomainControllerDef *def,
2803 virQEMUCaps *qemuCaps)
2804 {
2805 g_autoptr(virJSONValue) props = NULL;
2806 g_autofree char *iothread = NULL;
2807 const char *driver = NULL;
2808
2809 switch ((virDomainControllerModelSCSI) def->model) {
2810 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI:
2811 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL:
2812 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL:
2813 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_CONTROLLER, def,
2814 qemuCaps)))
2815 return NULL;
2816
2817 if (def->iothread > 0)
2818 iothread = g_strdup_printf("iothread%u", def->iothread);
2819
2820 if (virJSONValueObjectAdd(&props,
2821 "S:iothread", iothread,
2822 "s:id", def->info.alias,
2823 "p:num_queues", def->queues,
2824 "p:cmd_per_lun", def->cmd_per_lun,
2825 "p:max_sectors", def->max_sectors,
2826 "T:ioeventfd", def->ioeventfd,
2827 NULL) < 0)
2828 return NULL;
2829 break;
2830
2831 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC:
2832 driver = "lsi";
2833 break;
2834 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
2835 driver = "spapr-vscsi";
2836 break;
2837 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068:
2838 driver = "mptsas1068";
2839 break;
2840 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078:
2841 driver = "megasas";
2842 break;
2843 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI:
2844 driver = "pvscsi";
2845 break;
2846 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AM53C974:
2847 driver = "am53c974";
2848 break;
2849 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DC390:
2850 driver = "dc-390";
2851 break;
2852 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO:
2853 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC:
2854 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_NCR53C90: /* It is built-in dev */
2855 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2856 _("Unsupported controller model: %s"),
2857 virDomainControllerModelSCSITypeToString(def->model));
2858 return NULL;
2859 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT:
2860 case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST:
2861 virReportError(VIR_ERR_INTERNAL_ERROR,
2862 _("Unexpected SCSI controller model %d"),
2863 def->model);
2864 return NULL;
2865 }
2866
2867 if (driver) {
2868 if (virJSONValueObjectAdd(&props,
2869 "s:driver", driver,
2870 "s:id", def->info.alias,
2871 NULL) < 0)
2872 return NULL;
2873 }
2874
2875 return g_steal_pointer(&props);
2876 }
2877
2878
2879 static int
qemuBuildControllerPCIDevProps(virDomainControllerDef * def,virJSONValue ** devprops)2880 qemuBuildControllerPCIDevProps(virDomainControllerDef *def,
2881 virJSONValue **devprops)
2882 {
2883 g_autoptr(virJSONValue) props = NULL;
2884 const virDomainPCIControllerOpts *pciopts = &def->opts.pciopts;
2885 const char *modelName = virDomainControllerPCIModelNameTypeToString(pciopts->modelName);
2886
2887 *devprops = NULL;
2888
2889 /* Skip the implicit PHB for pSeries guests */
2890 if (def->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT &&
2891 pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE &&
2892 pciopts->targetIndex == 0) {
2893 return 0;
2894 }
2895
2896 if (!modelName) {
2897 virReportError(VIR_ERR_INTERNAL_ERROR,
2898 _("Unknown virDomainControllerPCIModelName value: %d"),
2899 pciopts->modelName);
2900 return -1;
2901 }
2902
2903 switch ((virDomainControllerModelPCI) def->model) {
2904 case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
2905 if (virJSONValueObjectAdd(&props,
2906 "s:driver", modelName,
2907 "i:chassis_nr", pciopts->chassisNr,
2908 "s:id", def->info.alias,
2909 NULL) < 0)
2910 return -1;
2911
2912 break;
2913
2914 case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS:
2915 case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS:
2916 if (virJSONValueObjectAdd(&props,
2917 "s:driver", modelName,
2918 "i:bus_nr", pciopts->busNr,
2919 "s:id", def->info.alias,
2920 NULL) < 0)
2921 return -1;
2922
2923 if (pciopts->numaNode != -1 &&
2924 virJSONValueObjectAdd(&props, "i:numa_node", pciopts->numaNode, NULL) < 0)
2925 return -1;
2926
2927 break;
2928
2929 case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
2930 case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
2931 case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE:
2932 if (virJSONValueObjectAdd(&props,
2933 "s:driver", modelName,
2934 "s:id", def->info.alias,
2935 NULL) < 0)
2936 return -1;
2937
2938 break;
2939
2940 case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
2941 case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
2942 if (virJSONValueObjectAdd(&props,
2943 "s:driver", modelName,
2944 "i:port", pciopts->port,
2945 "i:chassis", pciopts->chassis,
2946 "s:id", def->info.alias,
2947 "T:hotplug", pciopts->hotplug,
2948 NULL) < 0)
2949 return -1;
2950
2951 break;
2952 case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
2953 if (virJSONValueObjectAdd(&props,
2954 "s:driver", modelName,
2955 "i:index", pciopts->targetIndex,
2956 "s:id", def->info.alias,
2957 NULL) < 0)
2958 return -1;
2959
2960 if (pciopts->numaNode != -1 &&
2961 virJSONValueObjectAdd(&props, "i:numa_node", pciopts->numaNode, NULL) < 0)
2962 return -1;
2963
2964 break;
2965 case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
2966 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2967 _("Unsupported PCI Express root controller"));
2968 return -1;
2969 case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT:
2970 case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
2971 virReportError(VIR_ERR_INTERNAL_ERROR,
2972 _("Unexpected PCI controller model %d"),
2973 def->model);
2974 return -1;
2975 }
2976
2977 *devprops = g_steal_pointer(&props);
2978 return 0;
2979 }
2980
2981
2982
2983 /**
2984 * qemuBuildControllerDevStr:
2985 * @domainDef: domain definition
2986 * @def: controller definition
2987 * @qemuCaps: QEMU binary capabilities
2988 * @devprops: filled with JSON object describing @def
2989 *
2990 * Turn @def into a description of the controller that QEMU will understand,
2991 * to be used either on the command line or through the monitor.
2992 *
2993 * The description will be returned in @devstr and can be NULL, eg. when
2994 * passing in one of the built-in controllers. The returned string must be
2995 * freed by the caller.
2996 *
2997 * The number pointed to by @nusbcontroller will be increased by one every
2998 * time the description for a USB controller has been generated successfully.
2999 *
3000 * Returns: 0 on success, <0 on failure
3001 */
3002 int
qemuBuildControllerDevProps(const virDomainDef * domainDef,virDomainControllerDef * def,virQEMUCaps * qemuCaps,virJSONValue ** devprops)3003 qemuBuildControllerDevProps(const virDomainDef *domainDef,
3004 virDomainControllerDef *def,
3005 virQEMUCaps *qemuCaps,
3006 virJSONValue **devprops)
3007 {
3008 g_autoptr(virJSONValue) props = NULL;
3009
3010 *devprops = NULL;
3011
3012 switch ((virDomainControllerType)def->type) {
3013 case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
3014 if (!(props = qemuBuildControllerSCSIDevProps(def, qemuCaps)))
3015 return -1;
3016
3017 break;
3018
3019 case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
3020 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_CONTROLLER, def,
3021 qemuCaps)))
3022 return -1;
3023
3024 if (virJSONValueObjectAdd(&props,
3025 "s:id", def->info.alias,
3026 "k:max_ports", def->opts.vioserial.ports,
3027 "k:vectors", def->opts.vioserial.vectors,
3028 NULL) < 0)
3029 return -1;
3030
3031 break;
3032
3033 case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
3034 if (virJSONValueObjectAdd(&props,
3035 "s:driver", "usb-ccid",
3036 "s:id", def->info.alias,
3037 NULL) < 0)
3038 return -1;
3039
3040 break;
3041
3042 case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
3043 if (virJSONValueObjectAdd(&props,
3044 "s:driver", "ahci",
3045 "s:id", def->info.alias,
3046 NULL) < 0)
3047 return -1;
3048
3049 break;
3050
3051 case VIR_DOMAIN_CONTROLLER_TYPE_USB:
3052 if (!(props = qemuBuildUSBControllerDevProps(domainDef, def, qemuCaps)))
3053 return -1;
3054
3055 break;
3056
3057 case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
3058 if (qemuBuildControllerPCIDevProps(def, &props) < 0)
3059 return -1;
3060
3061 break;
3062
3063 case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
3064 case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
3065 case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
3066 case VIR_DOMAIN_CONTROLLER_TYPE_ISA:
3067 case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
3068 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3069 _("Unsupported controller type: %s"),
3070 virDomainControllerTypeToString(def->type));
3071 return -1;
3072 }
3073
3074 if (!props)
3075 return 0;
3076
3077 if (qemuBuildDeviceAddressProps(props, domainDef, &def->info) < 0)
3078 return -1;
3079
3080 *devprops = g_steal_pointer(&props);
3081 return 0;
3082 }
3083
3084
3085 static bool
qemuBuildDomainForbidLegacyUSBController(const virDomainDef * def)3086 qemuBuildDomainForbidLegacyUSBController(const virDomainDef *def)
3087 {
3088 if (qemuDomainIsQ35(def) ||
3089 qemuDomainIsARMVirt(def) ||
3090 qemuDomainIsRISCVVirt(def))
3091 return true;
3092
3093 return false;
3094 }
3095
3096
3097 static int
qemuBuildLegacyUSBControllerCommandLine(virCommand * cmd,const virDomainDef * def)3098 qemuBuildLegacyUSBControllerCommandLine(virCommand *cmd,
3099 const virDomainDef *def)
3100 {
3101 size_t i;
3102 size_t nlegacy = 0;
3103 size_t nusb = 0;
3104
3105 for (i = 0; i < def->ncontrollers; i++) {
3106 virDomainControllerDef *cont = def->controllers[i];
3107
3108 if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_USB)
3109 continue;
3110
3111 /* If we have mode='none', there are no other USB controllers */
3112 if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE)
3113 return 0;
3114
3115 if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_DEFAULT)
3116 nlegacy++;
3117 else
3118 nusb++;
3119 }
3120
3121 if (nlegacy > 1) {
3122 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3123 _("Multiple legacy USB controllers are "
3124 "not supported"));
3125 return -1;
3126 }
3127
3128 if (nusb == 0 &&
3129 !qemuBuildDomainForbidLegacyUSBController(def) &&
3130 !ARCH_IS_S390(def->os.arch)) {
3131 /* We haven't added any USB controller yet, but we haven't been asked
3132 * not to add one either. Add a legacy USB controller, unless we're
3133 * creating a kind of guest we want to keep legacy-free */
3134 virCommandAddArg(cmd, "-usb");
3135 }
3136
3137 return 0;
3138 }
3139
3140
3141 /**
3142 * qemuBuildSkipController:
3143 * @controller: Controller to check
3144 * @def: Domain definition
3145 *
3146 * Returns true if this controller can be skipped for command line
3147 * generation or device validation.
3148 */
3149 static bool
qemuBuildSkipController(const virDomainControllerDef * controller,const virDomainDef * def)3150 qemuBuildSkipController(const virDomainControllerDef *controller,
3151 const virDomainDef *def)
3152 {
3153 /* skip pcie-root */
3154 if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
3155 controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)
3156 return true;
3157
3158 /* Skip pci-root, except for pSeries guests (which actually
3159 * support more than one PCI Host Bridge per guest) */
3160 if (!qemuDomainIsPSeries(def) &&
3161 controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
3162 controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT)
3163 return true;
3164
3165 /* first SATA controller on Q35 machines is implicit */
3166 if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA &&
3167 controller->idx == 0 && qemuDomainIsQ35(def))
3168 return true;
3169
3170 /* first IDE controller is implicit on various machines */
3171 if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
3172 controller->idx == 0 && qemuDomainHasBuiltinIDE(def))
3173 return true;
3174
3175 /* first ESP SCSI controller is implicit on certain machine types */
3176 if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI &&
3177 controller->idx == 0 &&
3178 controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_NCR53C90 &&
3179 qemuDomainHasBuiltinESP(def)) {
3180 return true;
3181 }
3182
3183 return false;
3184 }
3185
3186 static void
qemuBuildPMPCIRootHotplugCommandLine(virCommand * cmd,const virDomainControllerDef * controller)3187 qemuBuildPMPCIRootHotplugCommandLine(virCommand *cmd,
3188 const virDomainControllerDef *controller)
3189 {
3190 if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
3191 controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT &&
3192 controller->idx == 0 &&
3193 controller->opts.pciopts.hotplug != VIR_TRISTATE_SWITCH_ABSENT) {
3194 virCommandAddArg(cmd, "-global");
3195 virCommandAddArgFormat(cmd, "PIIX4_PM.acpi-root-pci-hotplug=%s",
3196 virTristateSwitchTypeToString(controller->opts.pciopts.hotplug));
3197 }
3198 return;
3199 }
3200
3201 static int
qemuBuildControllersByTypeCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps,virDomainControllerType type)3202 qemuBuildControllersByTypeCommandLine(virCommand *cmd,
3203 const virDomainDef *def,
3204 virQEMUCaps *qemuCaps,
3205 virDomainControllerType type)
3206 {
3207 size_t i;
3208
3209 for (i = 0; i < def->ncontrollers; i++) {
3210 virDomainControllerDef *cont = def->controllers[i];
3211 g_autoptr(virJSONValue) props = NULL;
3212
3213 if (cont->type != type)
3214 continue;
3215
3216 qemuBuildPMPCIRootHotplugCommandLine(cmd, cont);
3217
3218 if (qemuBuildSkipController(cont, def))
3219 continue;
3220
3221 /* skip USB controllers with type none.*/
3222 if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
3223 cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE) {
3224 continue;
3225 }
3226
3227 if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
3228 cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_DEFAULT &&
3229 !qemuBuildDomainForbidLegacyUSBController(def)) {
3230
3231 /* An appropriate default USB controller model should already
3232 * have been selected in qemuDomainDeviceDefPostParse(); if
3233 * we still have no model by now, we have to fall back to the
3234 * legacy USB controller.
3235 *
3236 * Note that we *don't* want to end up with the legacy USB
3237 * controller for q35 and virt machines, so we go ahead and
3238 * fail in qemuBuildControllerDevStr(); on the other hand,
3239 * for s390 machines we want to ignore any USB controller
3240 * (see 548ba43028 for the full story), so we skip
3241 * qemuBuildControllerDevStr() but we don't ultimately end
3242 * up adding the legacy USB controller */
3243 continue;
3244 }
3245
3246 if (qemuBuildControllerDevProps(def, cont, qemuCaps, &props) < 0)
3247 return -1;
3248
3249 if (!props)
3250 continue;
3251
3252 if (qemuCommandAddExtDevice(cmd, &cont->info, qemuCaps) < 0)
3253 return -1;
3254
3255 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
3256 return -1;
3257 }
3258
3259 return 0;
3260 }
3261
3262
3263 static int
qemuBuildControllersCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)3264 qemuBuildControllersCommandLine(virCommand *cmd,
3265 const virDomainDef *def,
3266 virQEMUCaps *qemuCaps)
3267 {
3268 size_t i;
3269 int contOrder[] = {
3270 /*
3271 * List of controller types that we add commandline args for,
3272 * *in the order we want to add them*.
3273 *
3274 * The floppy controller is implicit on PIIX4 and older Q35
3275 * machines. For newer Q35 machines it is added out of the
3276 * controllers loop, after the floppy drives.
3277 *
3278 * We don't add PCI/PCIe root controller either, because it's
3279 * implicit, but we do add PCI bridges and other PCI
3280 * controllers, so we leave that in to check each
3281 * one. Likewise, we don't do anything for the primary IDE
3282 * controller on an i440fx machine or primary SATA on q35, but
3283 * we do add those beyond these two exceptions.
3284 *
3285 * CCID controllers are formatted separately after USB hubs,
3286 * because they go on the USB bus.
3287 */
3288 VIR_DOMAIN_CONTROLLER_TYPE_PCI,
3289 VIR_DOMAIN_CONTROLLER_TYPE_USB,
3290 VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
3291 VIR_DOMAIN_CONTROLLER_TYPE_IDE,
3292 VIR_DOMAIN_CONTROLLER_TYPE_SATA,
3293 VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL,
3294 };
3295
3296 for (i = 0; i < G_N_ELEMENTS(contOrder); i++) {
3297 if (qemuBuildControllersByTypeCommandLine(cmd, def, qemuCaps, contOrder[i]) < 0)
3298 return -1;
3299 }
3300
3301 if (qemuBuildLegacyUSBControllerCommandLine(cmd, def) < 0)
3302 return -1;
3303
3304 return 0;
3305 }
3306
3307
3308 static int
qemuBuildMemoryBackendPropsShare(virJSONValue * props,virDomainMemoryAccess memAccess)3309 qemuBuildMemoryBackendPropsShare(virJSONValue *props,
3310 virDomainMemoryAccess memAccess)
3311 {
3312 switch (memAccess) {
3313 case VIR_DOMAIN_MEMORY_ACCESS_SHARED:
3314 return virJSONValueObjectAdd(&props, "b:share", true, NULL);
3315
3316 case VIR_DOMAIN_MEMORY_ACCESS_PRIVATE:
3317 return virJSONValueObjectAdd(&props, "b:share", false, NULL);
3318
3319 case VIR_DOMAIN_MEMORY_ACCESS_DEFAULT:
3320 case VIR_DOMAIN_MEMORY_ACCESS_LAST:
3321 break;
3322 }
3323
3324 return 0;
3325 }
3326
3327
3328 static int
qemuBuildMemoryGetDefaultPagesize(virQEMUDriverConfig * cfg,unsigned long long * pagesize)3329 qemuBuildMemoryGetDefaultPagesize(virQEMUDriverConfig *cfg,
3330 unsigned long long *pagesize)
3331 {
3332 virHugeTLBFS *p;
3333
3334 if (!cfg->nhugetlbfs) {
3335 virReportError(VIR_ERR_INTERNAL_ERROR,
3336 "%s", _("hugetlbfs filesystem is not mounted "
3337 "or disabled by administrator config"));
3338 return -1;
3339 }
3340
3341 if (!(p = virFileGetDefaultHugepage(cfg->hugetlbfs, cfg->nhugetlbfs)))
3342 p = &cfg->hugetlbfs[0];
3343
3344 *pagesize = p->size;
3345 return 0;
3346 }
3347
3348
3349 /**
3350 * qemuBuildMemoryBackendProps:
3351 * @backendProps: [out] constructed object
3352 * @alias: alias of the device
3353 * @cfg: qemu driver config object
3354 * @priv: pointer to domain private object
3355 * @def: domain definition object
3356 * @mem: memory definition object
3357 * @force: forcibly use one of the backends
3358 *
3359 * Creates a configuration object that represents memory backend of given guest
3360 * NUMA node (domain @def and @mem). Use @priv->autoNodeset to fine tune the
3361 * placement of the memory on the host NUMA nodes.
3362 *
3363 * By default, if no memory-backend-* object is necessary to fulfil the guest
3364 * configuration value of 1 is returned. This behaviour can be suppressed by
3365 * setting @force to true in which case 0 would be returned.
3366 *
3367 * Then, if one of the three memory-backend-* should be used, the @priv->qemuCaps
3368 * is consulted to check if qemu does support it.
3369 *
3370 * Returns: 0 on success,
3371 * 1 on success and if there's no need to use memory-backend-*
3372 * -1 on error.
3373 */
3374 int
qemuBuildMemoryBackendProps(virJSONValue ** backendProps,const char * alias,virQEMUDriverConfig * cfg,qemuDomainObjPrivate * priv,const virDomainDef * def,const virDomainMemoryDef * mem,bool force,bool systemMemory)3375 qemuBuildMemoryBackendProps(virJSONValue **backendProps,
3376 const char *alias,
3377 virQEMUDriverConfig *cfg,
3378 qemuDomainObjPrivate *priv,
3379 const virDomainDef *def,
3380 const virDomainMemoryDef *mem,
3381 bool force,
3382 bool systemMemory)
3383 {
3384 const char *backendType = "memory-backend-file";
3385 virDomainNumatuneMemMode mode;
3386 const long system_page_size = virGetSystemPageSizeKB();
3387 virDomainMemoryAccess memAccess = mem->access;
3388 size_t i;
3389 g_autofree char *memPath = NULL;
3390 bool prealloc = false;
3391 virBitmap *nodemask = NULL;
3392 int rc;
3393 g_autoptr(virJSONValue) props = NULL;
3394 bool nodeSpecified = virDomainNumatuneNodeSpecified(def->numa, mem->targetNode);
3395 unsigned long long pagesize = mem->pagesize;
3396 bool needHugepage = !!pagesize;
3397 bool useHugepage = !!pagesize;
3398 int discard = mem->discard;
3399 bool disableCanonicalPath = false;
3400
3401 /* Disabling canonical path is required for migration compatibility of
3402 * system memory objects, see below */
3403
3404 /* The difference between @needHugepage and @useHugepage is that the latter
3405 * is true whenever huge page is defined for the current memory cell.
3406 * Either directly, or transitively via global domain huge pages. The
3407 * former is true whenever "memory-backend-file" must be used to satisfy
3408 * @useHugepage. */
3409
3410 *backendProps = NULL;
3411
3412 if (mem->targetNode >= 0) {
3413 /* memory devices could provide a invalid guest node */
3414 if (mem->targetNode >= virDomainNumaGetNodeCount(def->numa)) {
3415 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3416 _("can't add memory backend for guest node '%d' as "
3417 "the guest has only '%zu' NUMA nodes configured"),
3418 mem->targetNode, virDomainNumaGetNodeCount(def->numa));
3419 return -1;
3420 }
3421
3422 if (memAccess == VIR_DOMAIN_MEMORY_ACCESS_DEFAULT)
3423 memAccess = virDomainNumaGetNodeMemoryAccessMode(def->numa, mem->targetNode);
3424
3425 if (discard == VIR_TRISTATE_BOOL_ABSENT)
3426 discard = virDomainNumaGetNodeDiscard(def->numa, mem->targetNode);
3427 }
3428
3429 if (memAccess == VIR_DOMAIN_MEMORY_ACCESS_DEFAULT)
3430 memAccess = def->mem.access;
3431
3432 if (discard == VIR_TRISTATE_BOOL_ABSENT)
3433 discard = def->mem.discard;
3434
3435 if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE)
3436 prealloc = true;
3437
3438 if (virDomainNumatuneGetMode(def->numa, mem->targetNode, &mode) < 0 &&
3439 virDomainNumatuneGetMode(def->numa, -1, &mode) < 0)
3440 mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
3441
3442 if (pagesize == 0) {
3443 virDomainHugePage *master_hugepage = NULL;
3444 virDomainHugePage *hugepage = NULL;
3445 bool thisHugepage = false;
3446
3447 /* Find the huge page size we want to use */
3448 for (i = 0; i < def->mem.nhugepages; i++) {
3449 hugepage = &def->mem.hugepages[i];
3450
3451 if (!hugepage->nodemask) {
3452 master_hugepage = hugepage;
3453 continue;
3454 }
3455
3456 /* just find the master hugepage in case we don't use NUMA */
3457 if (mem->targetNode < 0)
3458 continue;
3459
3460 if (virBitmapGetBit(hugepage->nodemask, mem->targetNode,
3461 &thisHugepage) < 0) {
3462 /* Ignore this error. It's not an error after all. Well,
3463 * the nodemask for this <page/> can contain lower NUMA
3464 * nodes than we are querying in here. */
3465 continue;
3466 }
3467
3468 if (thisHugepage) {
3469 /* Hooray, we've found the page size */
3470 needHugepage = true;
3471 break;
3472 }
3473 }
3474
3475 if (i == def->mem.nhugepages) {
3476 /* We have not found specific huge page to be used with this
3477 * NUMA node. Use the generic setting then (<page/> without any
3478 * @nodemask) if possible. */
3479 hugepage = master_hugepage;
3480 }
3481
3482 if (hugepage) {
3483 pagesize = hugepage->size;
3484 useHugepage = true;
3485 }
3486 }
3487
3488 if (pagesize == system_page_size) {
3489 /* However, if user specified to use "huge" page
3490 * of regular system page size, it's as if they
3491 * hasn't specified any huge pages at all. */
3492 pagesize = 0;
3493 needHugepage = false;
3494 useHugepage = false;
3495 } else if (useHugepage && pagesize == 0) {
3496 if (qemuBuildMemoryGetDefaultPagesize(cfg, &pagesize) < 0)
3497 return -1;
3498 }
3499
3500 props = virJSONValueNewObject();
3501
3502 if (!mem->nvdimmPath &&
3503 def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_MEMFD) {
3504 backendType = "memory-backend-memfd";
3505
3506 if (useHugepage) {
3507 if (virJSONValueObjectAdd(&props, "b:hugetlb", useHugepage, NULL) < 0 ||
3508 virJSONValueObjectAdd(&props, "U:hugetlbsize", pagesize << 10, NULL) < 0) {
3509 return -1;
3510 }
3511
3512 prealloc = true;
3513 }
3514
3515 if (qemuBuildMemoryBackendPropsShare(props, memAccess) < 0)
3516 return -1;
3517
3518 if (systemMemory)
3519 disableCanonicalPath = true;
3520
3521 } else if (useHugepage || mem->nvdimmPath || memAccess ||
3522 def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) {
3523
3524 if (mem->nvdimmPath) {
3525 memPath = g_strdup(mem->nvdimmPath);
3526 /* If the NVDIMM is a real device then there's nothing to prealloc.
3527 * If anything, we would be only wearing off the device.
3528 * Similarly, virtio-pmem-pci doesn't need prealloc either. */
3529 if (!mem->nvdimmPmem && mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM)
3530 prealloc = true;
3531 } else if (useHugepage) {
3532 if (qemuGetDomainHupageMemPath(priv->driver, def, pagesize, &memPath) < 0)
3533 return -1;
3534 prealloc = true;
3535 } else {
3536 /* We can have both pagesize and mem source. If that's the case,
3537 * prefer hugepages as those are more specific. */
3538 if (qemuGetMemoryBackingPath(priv->driver, def, mem->info.alias, &memPath) < 0)
3539 return -1;
3540 }
3541
3542 if (virJSONValueObjectAdd(&props,
3543 "s:mem-path", memPath,
3544 NULL) < 0)
3545 return -1;
3546
3547 if (!mem->nvdimmPath &&
3548 discard == VIR_TRISTATE_BOOL_YES) {
3549 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE_DISCARD)) {
3550 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3551 _("this QEMU doesn't support memory discard"));
3552 return -1;
3553 }
3554
3555 if (virJSONValueObjectAdd(&props,
3556 "B:discard-data", true,
3557 NULL) < 0)
3558 return -1;
3559 }
3560
3561 if (qemuBuildMemoryBackendPropsShare(props, memAccess) < 0)
3562 return -1;
3563
3564 if (systemMemory)
3565 disableCanonicalPath = true;
3566
3567 } else {
3568 backendType = "memory-backend-ram";
3569 }
3570
3571 /* This is a terrible hack, but unfortunately there is no better way.
3572 * The replacement for '-m X' argument is not simple '-machine
3573 * memory-backend' and '-object memory-backend-*,size=X' (which was the
3574 * idea). This is because of create_default_memdev() in QEMU sets
3575 * 'x-use-canonical-path-for-ramblock-id' attribute to false and is
3576 * documented in QEMU in qemu-options.hx under 'memory-backend'. Note
3577 * that QEMU considers 'x-use-canonical-path-for-ramblock-id' stable
3578 * and supported despite the 'x-' prefix.
3579 * See QEMU commit 8db0b20415c129cf5e577a593a4a0372d90b7cc9.
3580 */
3581 if (disableCanonicalPath &&
3582 virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_X_USE_CANONICAL_PATH_FOR_RAMBLOCK_ID) &&
3583 virJSONValueObjectAdd(&props, "b:x-use-canonical-path-for-ramblock-id", false, NULL) < 0)
3584 return -1;
3585
3586 if (mem->model == VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM) {
3587 /* Explicitly disable prealloc for virtio-mem as it's not supported
3588 * currently. Warn users if their config would result in prealloc. */
3589 if (priv->memPrealloc || prealloc) {
3590 VIR_WARN("Memory preallocation is unsupported for virtio-mem memory devices");
3591 }
3592 if (priv->memPrealloc &&
3593 virJSONValueObjectAppendBoolean(props, "prealloc", 0) < 0)
3594 return -1;
3595 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MEMORY_BACKEND_RESERVE) &&
3596 virJSONValueObjectAppendBoolean(props, "reserve", 0) < 0)
3597 return -1;
3598 } else {
3599 if (!priv->memPrealloc &&
3600 virJSONValueObjectAdd(&props, "B:prealloc", prealloc, NULL) < 0)
3601 return -1;
3602 }
3603
3604 if (virJSONValueObjectAdd(&props, "U:size", mem->size * 1024, NULL) < 0)
3605 return -1;
3606
3607 if (mem->alignsize) {
3608 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE_ALIGN)) {
3609 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3610 _("nvdimm align property is not available "
3611 "with this QEMU binary"));
3612 return -1;
3613 }
3614 if (virJSONValueObjectAdd(&props, "U:align", mem->alignsize * 1024, NULL) < 0)
3615 return -1;
3616 }
3617
3618 if (mem->nvdimmPmem) {
3619 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE_PMEM)) {
3620 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3621 _("nvdimm pmem property is not available "
3622 "with this QEMU binary"));
3623 return -1;
3624 }
3625 if (virJSONValueObjectAdd(&props, "b:pmem", true, NULL) < 0)
3626 return -1;
3627 }
3628
3629 if (mem->sourceNodes) {
3630 nodemask = mem->sourceNodes;
3631 } else {
3632 if (virDomainNumatuneMaybeGetNodeset(def->numa, priv->autoNodeset,
3633 &nodemask, mem->targetNode) < 0)
3634 return -1;
3635 }
3636
3637 /* If mode is "restrictive", we should only use cgroups setting allowed memory
3638 * nodes, and skip passing the host-nodes and policy parameters to QEMU command
3639 * line which means we will use system default memory policy. */
3640 if (!systemMemory && nodemask &&
3641 mode != VIR_DOMAIN_NUMATUNE_MEM_RESTRICTIVE) {
3642 if (!virNumaNodesetIsAvailable(nodemask))
3643 return -1;
3644 if (virJSONValueObjectAdd(&props,
3645 "m:host-nodes", nodemask,
3646 "S:policy", qemuNumaPolicyTypeToString(mode),
3647 NULL) < 0)
3648 return -1;
3649 }
3650
3651 /* If none of the following is requested... */
3652 if (!needHugepage && !mem->sourceNodes && !nodeSpecified &&
3653 !mem->nvdimmPath &&
3654 memAccess == VIR_DOMAIN_MEMORY_ACCESS_DEFAULT &&
3655 def->mem.source != VIR_DOMAIN_MEMORY_SOURCE_FILE &&
3656 def->mem.source != VIR_DOMAIN_MEMORY_SOURCE_MEMFD &&
3657 !force) {
3658 /* report back that using the new backend is not necessary
3659 * to achieve the desired configuration */
3660 rc = 1;
3661 } else {
3662 /* otherwise check the required capability */
3663 if (STREQ(backendType, "memory-backend-file") &&
3664 !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) {
3665 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3666 _("this qemu doesn't support the "
3667 "memory-backend-file object"));
3668 return -1;
3669 } else if (STREQ(backendType, "memory-backend-ram") &&
3670 !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM)) {
3671 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3672 _("this qemu doesn't support the "
3673 "memory-backend-ram object"));
3674 return -1;
3675 } else if (STREQ(backendType, "memory-backend-memfd") &&
3676 !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD)) {
3677 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3678 _("this qemu doesn't support the "
3679 "memory-backend-memfd object"));
3680 return -1;
3681 }
3682
3683 rc = 0;
3684 }
3685
3686 if (virJSONValueObjectPrependString(props, "id", alias) < 0 ||
3687 virJSONValueObjectPrependString(props, "qom-type", backendType) < 0)
3688 return -1;
3689
3690 *backendProps = g_steal_pointer(&props);
3691
3692 return rc;
3693 }
3694
3695
3696 static int
qemuBuildMemoryCellBackendProps(virDomainDef * def,virQEMUDriverConfig * cfg,size_t cell,qemuDomainObjPrivate * priv,virJSONValue ** props)3697 qemuBuildMemoryCellBackendProps(virDomainDef *def,
3698 virQEMUDriverConfig *cfg,
3699 size_t cell,
3700 qemuDomainObjPrivate *priv,
3701 virJSONValue **props)
3702 {
3703 g_autofree char *alias = NULL;
3704 virDomainMemoryDef mem = { 0 };
3705 unsigned long long memsize = virDomainNumaGetNodeMemorySize(def->numa,
3706 cell);
3707
3708 alias = g_strdup_printf("ram-node%zu", cell);
3709
3710 mem.size = memsize;
3711 mem.targetNode = cell;
3712 mem.info.alias = alias;
3713
3714 return qemuBuildMemoryBackendProps(props, alias, cfg, priv, def, &mem, false, false);
3715 }
3716
3717
3718 static int
qemuBuildMemoryDimmBackendStr(virCommand * cmd,virDomainMemoryDef * mem,virDomainDef * def,virQEMUDriverConfig * cfg,qemuDomainObjPrivate * priv)3719 qemuBuildMemoryDimmBackendStr(virCommand *cmd,
3720 virDomainMemoryDef *mem,
3721 virDomainDef *def,
3722 virQEMUDriverConfig *cfg,
3723 qemuDomainObjPrivate *priv)
3724 {
3725 g_autoptr(virJSONValue) props = NULL;
3726 g_autofree char *alias = NULL;
3727
3728 if (!mem->info.alias) {
3729 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3730 _("memory device alias is not assigned"));
3731 return -1;
3732 }
3733
3734 alias = g_strdup_printf("mem%s", mem->info.alias);
3735
3736 if (qemuBuildMemoryBackendProps(&props, alias, cfg,
3737 priv, def, mem, true, false) < 0)
3738 return -1;
3739
3740 if (qemuBuildObjectCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0)
3741 return -1;
3742
3743 return 0;
3744 }
3745
3746
3747 virJSONValue *
qemuBuildMemoryDeviceProps(const virDomainDef * def,virDomainMemoryDef * mem)3748 qemuBuildMemoryDeviceProps(const virDomainDef *def,
3749 virDomainMemoryDef *mem)
3750 {
3751 g_autoptr(virJSONValue) props = NULL;
3752 const char *device = NULL;
3753 g_autofree char *uuidstr = NULL;
3754 virTristateBool unarmed = VIR_TRISTATE_BOOL_ABSENT;
3755 g_autofree char *memdev = NULL;
3756
3757 if (!mem->info.alias) {
3758 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3759 _("missing alias for memory device"));
3760 return NULL;
3761 }
3762
3763 memdev = g_strdup_printf("mem%s", mem->info.alias);
3764
3765 switch (mem->model) {
3766 case VIR_DOMAIN_MEMORY_MODEL_DIMM:
3767 device = "pc-dimm";
3768 break;
3769 case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
3770 device = "nvdimm";
3771 break;
3772
3773 case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
3774 device = "virtio-pmem-pci";
3775 break;
3776
3777 case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
3778 device = "virtio-mem-pci";
3779 break;
3780
3781 case VIR_DOMAIN_MEMORY_MODEL_NONE:
3782 case VIR_DOMAIN_MEMORY_MODEL_LAST:
3783 default:
3784 virReportEnumRangeError(virDomainMemoryModel, mem->model);
3785 return NULL;
3786 break;
3787 }
3788
3789 if (mem->readonly)
3790 unarmed = VIR_TRISTATE_BOOL_YES;
3791
3792 if (mem->uuid) {
3793 uuidstr = g_new0(char, VIR_UUID_STRING_BUFLEN);
3794 virUUIDFormat(mem->uuid, uuidstr);
3795 }
3796
3797 if (virJSONValueObjectAdd(&props,
3798 "s:driver", device,
3799 "k:node", mem->targetNode,
3800 "P:label-size", mem->labelsize * 1024,
3801 "P:block-size", mem->blocksize * 1024,
3802 "P:requested-size", mem->requestedsize * 1024,
3803 "S:uuid", uuidstr,
3804 "T:unarmed", unarmed,
3805 "s:memdev", memdev,
3806 "s:id", mem->info.alias,
3807 NULL) < 0)
3808 return NULL;
3809
3810 if (qemuBuildDeviceAddressProps(props, def, &mem->info) < 0)
3811 return NULL;
3812
3813 return g_steal_pointer(&props);
3814 }
3815
3816
3817 static char *
qemuBuildLegacyNicStr(virDomainNetDef * net)3818 qemuBuildLegacyNicStr(virDomainNetDef *net)
3819 {
3820 char macaddr[VIR_MAC_STRING_BUFLEN];
3821 const char *netmodel = virDomainNetGetModelString(net);
3822
3823 return g_strdup_printf("nic,macaddr=%s,netdev=host%s%s%s%s%s",
3824 virMacAddrFormat(&net->mac, macaddr),
3825 net->info.alias, netmodel ? ",model=" : "",
3826 NULLSTR_EMPTY(netmodel),
3827 (net->info.alias ? ",id=" : ""),
3828 NULLSTR_EMPTY(net->info.alias));
3829 }
3830
3831
3832 virJSONValue *
qemuBuildNicDevProps(virDomainDef * def,virDomainNetDef * net,size_t vhostfdSize,virQEMUCaps * qemuCaps)3833 qemuBuildNicDevProps(virDomainDef *def,
3834 virDomainNetDef *net,
3835 size_t vhostfdSize,
3836 virQEMUCaps *qemuCaps)
3837 {
3838 g_autoptr(virJSONValue) props = NULL;
3839 char macaddr[VIR_MAC_STRING_BUFLEN];
3840 g_autofree char *netdev = g_strdup_printf("host%s", net->info.alias);
3841
3842 if (virDomainNetIsVirtioModel(net)) {
3843 const char *tx = NULL;
3844 virTristateSwitch mq = VIR_TRISTATE_SWITCH_ABSENT;
3845 unsigned long long vectors = 0;
3846 virTristateSwitch failover = VIR_TRISTATE_SWITCH_ABSENT;
3847
3848 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_TX_ALG)) {
3849 switch (net->driver.virtio.txmode) {
3850 case VIR_DOMAIN_NET_VIRTIO_TX_MODE_IOTHREAD:
3851 tx = "bh";
3852 break;
3853
3854 case VIR_DOMAIN_NET_VIRTIO_TX_MODE_TIMER:
3855 tx = "timer";
3856 break;
3857
3858 case VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT:
3859 break;
3860
3861 case VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST:
3862 default:
3863 /* this should never happen, if it does, we need
3864 * to add another case to this switch.
3865 */
3866 virReportEnumRangeError(virDomainNetVirtioTxModeType,
3867 net->driver.virtio.txmode);
3868 return NULL;
3869 }
3870 }
3871
3872 if (vhostfdSize > 1) {
3873 if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
3874 /* ccw provides a one to one relation of fds to queues and
3875 * does not support the vectors option
3876 */
3877 mq = VIR_TRISTATE_SWITCH_ON;
3878 } else {
3879 /* As advised at https://www.linux-kvm.org/page/Multiqueue
3880 * we should add vectors=2*N+2 where N is the vhostfdSize
3881 */
3882 mq = VIR_TRISTATE_SWITCH_ON;
3883 vectors = 2 * vhostfdSize + 2;
3884 }
3885 }
3886
3887 if (net->teaming && net->teaming->type == VIR_DOMAIN_NET_TEAMING_TYPE_PERSISTENT)
3888 failover = VIR_TRISTATE_SWITCH_ON;
3889
3890 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_NET, net, qemuCaps)))
3891 return NULL;
3892
3893 if (virJSONValueObjectAdd(&props,
3894 "S:tx", tx,
3895 "T:ioeventfd", net->driver.virtio.ioeventfd,
3896 "T:event_idx", net->driver.virtio.event_idx,
3897 "T:csum", net->driver.virtio.host.csum,
3898 "T:gso", net->driver.virtio.host.gso,
3899 "T:host_tso4", net->driver.virtio.host.tso4,
3900 "T:host_tso6", net->driver.virtio.host.tso6,
3901 "T:host_ecn", net->driver.virtio.host.ecn,
3902 "T:host_ufo", net->driver.virtio.host.ufo,
3903 "T:mrg_rxbuf", net->driver.virtio.host.mrg_rxbuf,
3904 "T:guest_csum", net->driver.virtio.guest.csum,
3905 "T:guest_tso4", net->driver.virtio.guest.tso4,
3906 "T:guest_tso6", net->driver.virtio.guest.tso6,
3907 "T:guest_ecn", net->driver.virtio.guest.ecn,
3908 "T:guest_ufo", net->driver.virtio.guest.ufo,
3909 "T:mq", mq,
3910 "P:vectors", vectors,
3911 "p:rx_queue_size", net->driver.virtio.rx_queue_size,
3912 "p:tx_queue_size", net->driver.virtio.tx_queue_size,
3913 "p:host_mtu", net->mtu,
3914 "T:failover", failover,
3915 NULL) < 0)
3916 return NULL;
3917 } else {
3918 if (virJSONValueObjectAdd(&props,
3919 "s:driver", virDomainNetGetModelString(net),
3920 NULL) < 0)
3921 return NULL;
3922 }
3923
3924 virMacAddrFormat(&net->mac, macaddr);
3925
3926 if (virJSONValueObjectAdd(&props,
3927 "s:netdev", netdev,
3928 "s:id", net->info.alias,
3929 "s:mac", macaddr,
3930 "p:bootindex", net->info.effectiveBootIndex,
3931 NULL) < 0)
3932 return NULL;
3933
3934 if (qemuBuildDeviceAddressProps(props, def, &net->info) < 0)
3935 return NULL;
3936
3937 if (qemuBuildRomProps(props, &net->info) < 0)
3938 return NULL;
3939
3940 return g_steal_pointer(&props);
3941 }
3942
3943
3944 virJSONValue *
qemuBuildHostNetProps(virDomainNetDef * net,char ** tapfd,size_t tapfdSize,char ** vhostfd,size_t vhostfdSize,const char * slirpfd,const char * vdpadev)3945 qemuBuildHostNetProps(virDomainNetDef *net,
3946 char **tapfd,
3947 size_t tapfdSize,
3948 char **vhostfd,
3949 size_t vhostfdSize,
3950 const char *slirpfd,
3951 const char *vdpadev)
3952 {
3953 bool is_tap = false;
3954 virDomainNetType netType = virDomainNetGetActualType(net);
3955 size_t i;
3956
3957 g_autoptr(virJSONValue) netprops = NULL;
3958
3959 if (net->script && netType != VIR_DOMAIN_NET_TYPE_ETHERNET) {
3960 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3961 _("scripts are not supported on interfaces of type %s"),
3962 virDomainNetTypeToString(netType));
3963 return NULL;
3964 }
3965
3966 switch (netType) {
3967 /*
3968 * If type='bridge', and we're running as privileged user
3969 * or -netdev bridge is not supported then it will fall
3970 * through, -net tap,fd
3971 */
3972 case VIR_DOMAIN_NET_TYPE_BRIDGE:
3973 case VIR_DOMAIN_NET_TYPE_NETWORK:
3974 case VIR_DOMAIN_NET_TYPE_DIRECT:
3975 case VIR_DOMAIN_NET_TYPE_ETHERNET:
3976 if (virJSONValueObjectAdd(&netprops, "s:type", "tap", NULL) < 0)
3977 return NULL;
3978
3979 /* for one tapfd 'fd=' shall be used,
3980 * for more than one 'fds=' is the right choice */
3981 if (tapfdSize == 1) {
3982 if (virJSONValueObjectAdd(&netprops, "s:fd", tapfd[0], NULL) < 0)
3983 return NULL;
3984 } else {
3985 g_auto(virBuffer) fdsbuf = VIR_BUFFER_INITIALIZER;
3986
3987 for (i = 0; i < tapfdSize; i++)
3988 virBufferAsprintf(&fdsbuf, "%s:", tapfd[i]);
3989
3990 virBufferTrim(&fdsbuf, ":");
3991
3992 if (virJSONValueObjectAdd(&netprops,
3993 "s:fds", virBufferCurrentContent(&fdsbuf),
3994 NULL) < 0)
3995 return NULL;
3996 }
3997
3998 is_tap = true;
3999 break;
4000
4001 case VIR_DOMAIN_NET_TYPE_CLIENT:
4002 if (virJSONValueObjectAdd(&netprops, "s:type", "socket", NULL) < 0 ||
4003 virJSONValueObjectAppendStringPrintf(netprops, "connect", "%s:%d",
4004 net->data.socket.address,
4005 net->data.socket.port) < 0)
4006 return NULL;
4007 break;
4008
4009 case VIR_DOMAIN_NET_TYPE_SERVER:
4010 if (virJSONValueObjectAdd(&netprops, "s:type", "socket", NULL) < 0 ||
4011 virJSONValueObjectAppendStringPrintf(netprops, "listen", "%s:%d",
4012 NULLSTR_EMPTY(net->data.socket.address),
4013 net->data.socket.port) < 0)
4014 return NULL;
4015 break;
4016
4017 case VIR_DOMAIN_NET_TYPE_MCAST:
4018 if (virJSONValueObjectAdd(&netprops, "s:type", "socket", NULL) < 0 ||
4019 virJSONValueObjectAppendStringPrintf(netprops, "mcast", "%s:%d",
4020 net->data.socket.address,
4021 net->data.socket.port) < 0)
4022 return NULL;
4023 break;
4024
4025 case VIR_DOMAIN_NET_TYPE_UDP:
4026 if (virJSONValueObjectAdd(&netprops, "s:type", "socket", NULL) < 0 ||
4027 virJSONValueObjectAppendStringPrintf(netprops, "udp", "%s:%d",
4028 net->data.socket.address,
4029 net->data.socket.port) < 0 ||
4030 virJSONValueObjectAppendStringPrintf(netprops, "localaddr", "%s:%d",
4031 net->data.socket.localaddr,
4032 net->data.socket.localport) < 0)
4033 return NULL;
4034 break;
4035
4036 case VIR_DOMAIN_NET_TYPE_USER:
4037 if (slirpfd) {
4038 if (virJSONValueObjectAdd(&netprops, "s:type", "socket", NULL) < 0 ||
4039 virJSONValueObjectAppendString(netprops, "fd", slirpfd) < 0)
4040 return NULL;
4041 } else {
4042 if (virJSONValueObjectAdd(&netprops, "s:type", "user", NULL) < 0)
4043 return NULL;
4044
4045 for (i = 0; i < net->guestIP.nips; i++) {
4046 const virNetDevIPAddr *ip = net->guestIP.ips[i];
4047 g_autofree char *addr = NULL;
4048
4049 if (!(addr = virSocketAddrFormat(&ip->address)))
4050 return NULL;
4051
4052 if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET)) {
4053 g_autofree char *ipv4netaddr = NULL;
4054
4055 if (ip->prefix)
4056 ipv4netaddr = g_strdup_printf("%s/%u", addr, ip->prefix);
4057 else
4058 ipv4netaddr = g_strdup(addr);
4059
4060 if (virJSONValueObjectAppendString(netprops, "net", ipv4netaddr) < 0)
4061 return NULL;
4062 } else if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET6)) {
4063 if (virJSONValueObjectAppendString(netprops, "ipv6-prefix", addr) < 0)
4064 return NULL;
4065 if (ip->prefix &&
4066 virJSONValueObjectAppendNumberUlong(netprops, "ipv6-prefixlen",
4067 ip->prefix) < 0)
4068 return NULL;
4069 }
4070 }
4071 }
4072 break;
4073
4074 case VIR_DOMAIN_NET_TYPE_INTERNAL:
4075 if (virJSONValueObjectAdd(&netprops, "s:type", "user", NULL) < 0)
4076 return NULL;
4077 break;
4078
4079 case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
4080 if (virJSONValueObjectAdd(&netprops, "s:type", "vhost-user", NULL) < 0 ||
4081 virJSONValueObjectAppendStringPrintf(netprops, "chardev", "char%s", net->info.alias) < 0)
4082 return NULL;
4083
4084 if (net->driver.virtio.queues > 1 &&
4085 virJSONValueObjectAppendNumberUlong(netprops, "queues", net->driver.virtio.queues) < 0)
4086 return NULL;
4087 break;
4088
4089 case VIR_DOMAIN_NET_TYPE_VDPA:
4090 /* Caller will pass the fd to qemu with add-fd */
4091 if (virJSONValueObjectAdd(&netprops, "s:type", "vhost-vdpa", NULL) < 0 ||
4092 virJSONValueObjectAppendString(netprops, "vhostdev", vdpadev) < 0)
4093 return NULL;
4094 break;
4095
4096 case VIR_DOMAIN_NET_TYPE_HOSTDEV:
4097 /* Should have been handled earlier via PCI/USB hotplug code. */
4098 case VIR_DOMAIN_NET_TYPE_LAST:
4099 break;
4100 }
4101
4102 if (virJSONValueObjectAppendStringPrintf(netprops, "id", "host%s", net->info.alias) < 0)
4103 return NULL;
4104
4105 if (is_tap) {
4106 if (vhostfdSize) {
4107 if (virJSONValueObjectAppendBoolean(netprops, "vhost", true) < 0)
4108 return NULL;
4109
4110 if (vhostfdSize == 1) {
4111 if (virJSONValueObjectAdd(&netprops, "s:vhostfd", vhostfd[0], NULL) < 0)
4112 return NULL;
4113 } else {
4114 g_auto(virBuffer) fdsbuf = VIR_BUFFER_INITIALIZER;
4115
4116 for (i = 0; i < vhostfdSize; i++)
4117 virBufferAsprintf(&fdsbuf, "%s:", vhostfd[i]);
4118
4119 virBufferTrim(&fdsbuf, ":");
4120
4121 if (virJSONValueObjectAdd(&netprops,
4122 "s:vhostfds", virBufferCurrentContent(&fdsbuf),
4123 NULL) < 0)
4124 return NULL;
4125 }
4126 }
4127
4128 if (net->tune.sndbuf_specified &&
4129 virJSONValueObjectAppendNumberUlong(netprops, "sndbuf", net->tune.sndbuf) < 0)
4130 return NULL;
4131 }
4132
4133 return g_steal_pointer(&netprops);
4134 }
4135
4136
4137 virJSONValue *
qemuBuildWatchdogDevProps(const virDomainDef * def,virDomainWatchdogDef * dev)4138 qemuBuildWatchdogDevProps(const virDomainDef *def,
4139 virDomainWatchdogDef *dev)
4140 {
4141 g_autoptr(virJSONValue) props = NULL;
4142
4143 if (virJSONValueObjectAdd(&props,
4144 "s:driver", virDomainWatchdogModelTypeToString(dev->model),
4145 "s:id", dev->info.alias,
4146 NULL) < 0)
4147 return NULL;
4148
4149 if (qemuBuildDeviceAddressProps(props, def, &dev->info) < 0)
4150 return NULL;
4151
4152 return g_steal_pointer(&props);
4153 }
4154
4155
4156 static int
qemuBuildWatchdogCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)4157 qemuBuildWatchdogCommandLine(virCommand *cmd,
4158 const virDomainDef *def,
4159 virQEMUCaps *qemuCaps)
4160 {
4161 virDomainWatchdogDef *watchdog = def->watchdog;
4162 g_autoptr(virJSONValue) props = NULL;
4163 const char *action;
4164 int actualAction;
4165
4166 if (!def->watchdog)
4167 return 0;
4168
4169 if (qemuCommandAddExtDevice(cmd, &def->watchdog->info, qemuCaps) < 0)
4170 return -1;
4171
4172 if (!(props = qemuBuildWatchdogDevProps(def, watchdog)))
4173 return -1;
4174
4175 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps))
4176 return -1;
4177
4178 /* qemu doesn't have a 'dump' action; we tell qemu to 'pause', then
4179 libvirt listens for the watchdog event, and we perform the dump
4180 ourselves. so convert 'dump' to 'pause' for the qemu cli */
4181 actualAction = watchdog->action;
4182 if (watchdog->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP)
4183 actualAction = VIR_DOMAIN_WATCHDOG_ACTION_PAUSE;
4184
4185 action = virDomainWatchdogActionTypeToString(actualAction);
4186 if (!action) {
4187 virReportError(VIR_ERR_INTERNAL_ERROR,
4188 "%s", _("invalid watchdog action"));
4189 return -1;
4190 }
4191 virCommandAddArgList(cmd, "-watchdog-action", action, NULL);
4192
4193 return 0;
4194 }
4195
4196
4197 static int
qemuBuildMemballoonCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)4198 qemuBuildMemballoonCommandLine(virCommand *cmd,
4199 const virDomainDef *def,
4200 virQEMUCaps *qemuCaps)
4201 {
4202 g_autoptr(virJSONValue) props = NULL;
4203
4204 if (!virDomainDefHasMemballoon(def))
4205 return 0;
4206
4207 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_MEMBALLOON,
4208 def->memballoon, qemuCaps)))
4209 return -1;
4210
4211 if (virJSONValueObjectAdd(&props,
4212 "s:id", def->memballoon->info.alias,
4213 "T:deflate-on-oom", def->memballoon->autodeflate,
4214 "T:free-page-reporting", def->memballoon->free_page_reporting,
4215 NULL) < 0)
4216 return -1;
4217
4218 if (qemuBuildDeviceAddressProps(props, def, &def->memballoon->info) < 0)
4219 return -1;
4220
4221 if (qemuCommandAddExtDevice(cmd, &def->memballoon->info, qemuCaps) < 0)
4222 return -1;
4223
4224 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
4225 return -1;
4226
4227 return 0;
4228 }
4229
4230
4231 static char *
qemuBuildNVRAMDevStr(virDomainNVRAMDef * dev)4232 qemuBuildNVRAMDevStr(virDomainNVRAMDef *dev)
4233 {
4234 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4235
4236 virBufferAsprintf(&buf, "spapr-nvram.reg=0x%llx",
4237 dev->info.addr.spaprvio.reg);
4238
4239 return virBufferContentAndReset(&buf);
4240 }
4241
4242
4243 static int
qemuBuildNVRAMCommandLine(virCommand * cmd,const virDomainDef * def)4244 qemuBuildNVRAMCommandLine(virCommand *cmd,
4245 const virDomainDef *def)
4246 {
4247 g_autofree char *optstr = NULL;
4248
4249 if (!def->nvram)
4250 return 0;
4251
4252 virCommandAddArg(cmd, "-global");
4253 optstr = qemuBuildNVRAMDevStr(def->nvram);
4254 if (!optstr)
4255 return -1;
4256
4257 virCommandAddArg(cmd, optstr);
4258
4259 return 0;
4260 }
4261
4262
4263 virJSONValue *
qemuBuildInputVirtioDevProps(const virDomainDef * def,virDomainInputDef * dev,virQEMUCaps * qemuCaps)4264 qemuBuildInputVirtioDevProps(const virDomainDef *def,
4265 virDomainInputDef *dev,
4266 virQEMUCaps *qemuCaps)
4267 {
4268 g_autoptr(virJSONValue) props = NULL;
4269 const char *evdev = NULL;
4270
4271 switch ((virDomainInputType)dev->type) {
4272 case VIR_DOMAIN_INPUT_TYPE_MOUSE:
4273 case VIR_DOMAIN_INPUT_TYPE_TABLET:
4274 case VIR_DOMAIN_INPUT_TYPE_KBD:
4275 case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
4276 break;
4277 case VIR_DOMAIN_INPUT_TYPE_EVDEV:
4278 case VIR_DOMAIN_INPUT_TYPE_LAST:
4279 default:
4280 virReportEnumRangeError(virDomainInputType, dev->type);
4281 return NULL;
4282 }
4283
4284 if (dev->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH)
4285 evdev = dev->source.evdev;
4286
4287 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_INPUT, dev, qemuCaps)))
4288 return NULL;
4289
4290 if (virJSONValueObjectAdd(&props,
4291 "s:id", dev->info.alias,
4292 "S:evdev", evdev,
4293 NULL) < 0)
4294 return NULL;
4295
4296 if (qemuBuildDeviceAddressProps(props, def, &dev->info) < 0)
4297 return NULL;
4298
4299 return g_steal_pointer(&props);
4300 }
4301
4302
4303 virJSONValue *
qemuBuildInputUSBDevProps(const virDomainDef * def,virDomainInputDef * dev)4304 qemuBuildInputUSBDevProps(const virDomainDef *def,
4305 virDomainInputDef *dev)
4306 {
4307 g_autoptr(virJSONValue) props = NULL;
4308 const char *driver = NULL;
4309
4310 switch (dev->type) {
4311 case VIR_DOMAIN_INPUT_TYPE_MOUSE:
4312 driver = "usb-mouse";
4313 break;
4314 case VIR_DOMAIN_INPUT_TYPE_TABLET:
4315 driver = "usb-tablet";
4316 break;
4317 case VIR_DOMAIN_INPUT_TYPE_KBD:
4318 driver = "usb-kbd";
4319 break;
4320 }
4321
4322 if (virJSONValueObjectAdd(&props,
4323 "s:driver", driver,
4324 "s:id", dev->info.alias,
4325 NULL) < 0)
4326 return NULL;
4327
4328 if (qemuBuildDeviceAddressProps(props, def, &dev->info) < 0)
4329 return NULL;
4330
4331 return g_steal_pointer(&props);
4332 }
4333
4334
4335 static virJSONValue *
qemuBuildInputEvdevProps(virDomainInputDef * dev)4336 qemuBuildInputEvdevProps(virDomainInputDef *dev)
4337 {
4338 g_autoptr(virJSONValue) props = NULL;
4339
4340 if (qemuMonitorCreateObjectProps(&props, "input-linux", dev->info.alias,
4341 "s:evdev", dev->source.evdev,
4342 "T:repeat", dev->source.repeat,
4343 NULL) < 0)
4344 return NULL;
4345
4346 if (dev->source.grab == VIR_DOMAIN_INPUT_SOURCE_GRAB_ALL &&
4347 virJSONValueObjectAdd(&props, "b:grab_all", true, NULL) < 0)
4348 return NULL;
4349
4350 if (dev->source.grabToggle != VIR_DOMAIN_INPUT_SOURCE_GRAB_TOGGLE_DEFAULT &&
4351 virJSONValueObjectAdd(&props, "s:grab-toggle",
4352 virDomainInputSourceGrabToggleTypeToString(dev->source.grabToggle),
4353 NULL) < 0)
4354 return NULL;
4355
4356 return g_steal_pointer(&props);
4357 }
4358
4359
4360 static int
qemuBuildInputCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)4361 qemuBuildInputCommandLine(virCommand *cmd,
4362 const virDomainDef *def,
4363 virQEMUCaps *qemuCaps)
4364 {
4365 size_t i;
4366
4367 for (i = 0; i < def->ninputs; i++) {
4368 virDomainInputDef *input = def->inputs[i];
4369
4370 if (qemuCommandAddExtDevice(cmd, &input->info, qemuCaps) < 0)
4371 return -1;
4372
4373 if (input->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) {
4374 g_autoptr(virJSONValue) props = NULL;
4375
4376 if (!(props = qemuBuildInputEvdevProps(input)))
4377 return -1;
4378
4379 if (qemuBuildObjectCommandlineFromJSON(cmd, props, qemuCaps) < 0)
4380 return -1;
4381 } else {
4382 g_autoptr(virJSONValue) props = NULL;
4383
4384 switch ((virDomainInputBus) input->bus) {
4385 case VIR_DOMAIN_INPUT_BUS_USB:
4386 if (!(props = qemuBuildInputUSBDevProps(def, input)))
4387 return -1;
4388 break;
4389
4390 case VIR_DOMAIN_INPUT_BUS_VIRTIO:
4391 if (!(props = qemuBuildInputVirtioDevProps(def, input, qemuCaps)))
4392 return -1;
4393
4394 case VIR_DOMAIN_INPUT_BUS_PS2:
4395 case VIR_DOMAIN_INPUT_BUS_XEN:
4396 case VIR_DOMAIN_INPUT_BUS_PARALLELS:
4397 case VIR_DOMAIN_INPUT_BUS_NONE:
4398 case VIR_DOMAIN_INPUT_BUS_LAST:
4399 break;
4400 }
4401
4402 if (props &&
4403 qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
4404 return -1;
4405 }
4406 }
4407
4408 return 0;
4409 }
4410
4411 static char *
qemuGetAudioIDString(const virDomainDef * def,int id)4412 qemuGetAudioIDString(const virDomainDef *def, int id)
4413 {
4414 virDomainAudioDef *audio = virDomainDefFindAudioByID(def, id);
4415 if (!audio) {
4416 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4417 _("unable to find audio backend for sound device"));
4418 return NULL;
4419 }
4420 return g_strdup_printf("audio%d", audio->id);
4421 }
4422
4423 static int
qemuBuildSoundDevCmd(virCommand * cmd,const virDomainDef * def,virDomainSoundDef * sound,virQEMUCaps * qemuCaps)4424 qemuBuildSoundDevCmd(virCommand *cmd,
4425 const virDomainDef *def,
4426 virDomainSoundDef *sound,
4427 virQEMUCaps *qemuCaps)
4428 {
4429 g_autoptr(virJSONValue) props = NULL;
4430 const char *model = NULL;
4431 g_autofree char *audioid = NULL;
4432
4433 switch (sound->model) {
4434 case VIR_DOMAIN_SOUND_MODEL_ES1370:
4435 model = "ES1370";
4436 break;
4437 case VIR_DOMAIN_SOUND_MODEL_AC97:
4438 model = "AC97";
4439 break;
4440 case VIR_DOMAIN_SOUND_MODEL_ICH6:
4441 model = "intel-hda";
4442 break;
4443 case VIR_DOMAIN_SOUND_MODEL_USB:
4444 model = "usb-audio";
4445 break;
4446 case VIR_DOMAIN_SOUND_MODEL_ICH9:
4447 model = "ich9-intel-hda";
4448 break;
4449 case VIR_DOMAIN_SOUND_MODEL_SB16:
4450 model = "sb16";
4451 break;
4452 case VIR_DOMAIN_SOUND_MODEL_PCSPK: /* pc-speaker is handled separately */
4453 case VIR_DOMAIN_SOUND_MODEL_ICH7:
4454 case VIR_DOMAIN_SOUND_MODEL_LAST:
4455 return -1;
4456 }
4457
4458 if (!virDomainSoundModelSupportsCodecs(sound) &&
4459 virQEMUCapsGet(qemuCaps, QEMU_CAPS_AUDIODEV)) {
4460 if (!(audioid = qemuGetAudioIDString(def, sound->audioId)))
4461 return -1;
4462 }
4463
4464 if (virJSONValueObjectAdd(&props,
4465 "s:driver", model,
4466 "s:id", sound->info.alias,
4467 "S:audiodev", audioid,
4468 NULL) < 0)
4469 return -1;
4470
4471 if (qemuBuildDeviceAddressProps(props, def, &sound->info) < 0)
4472 return -1;
4473
4474 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
4475 return -1;
4476
4477 return 0;
4478 }
4479
4480
4481 static int
qemuBuildSoundCodecCmd(virCommand * cmd,const virDomainDef * def,virDomainSoundDef * sound,virDomainSoundCodecDef * codec,virQEMUCaps * qemuCaps)4482 qemuBuildSoundCodecCmd(virCommand *cmd,
4483 const virDomainDef *def,
4484 virDomainSoundDef *sound,
4485 virDomainSoundCodecDef *codec,
4486 virQEMUCaps *qemuCaps)
4487 {
4488 g_autoptr(virJSONValue) props = NULL;
4489 g_autofree char *audioid = NULL;
4490 g_autofree char *alias = g_strdup_printf("%s-codec%d", sound->info.alias, codec->cad);
4491 g_autofree char *bus = g_strdup_printf("%s.0", sound->info.alias);
4492
4493 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_AUDIODEV)) {
4494 if (!(audioid = qemuGetAudioIDString(def, sound->audioId)))
4495 return -1;
4496 }
4497
4498 if (virJSONValueObjectAdd(&props,
4499 "s:driver", qemuSoundCodecTypeToString(codec->type),
4500 "s:id", alias,
4501 "s:bus", bus,
4502 "i:cad", codec->cad,
4503 "S:audiodev", audioid,
4504 NULL) < 0)
4505 return -1;
4506
4507 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
4508 return -1;
4509
4510 return 0;
4511 }
4512
4513
4514 static int
qemuBuildSoundCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)4515 qemuBuildSoundCommandLine(virCommand *cmd,
4516 const virDomainDef *def,
4517 virQEMUCaps *qemuCaps)
4518 {
4519 size_t i, j;
4520
4521 for (i = 0; i < def->nsounds; i++) {
4522 virDomainSoundDef *sound = def->sounds[i];
4523
4524 /* Sadly pcspk device doesn't use -device syntax. Fortunately
4525 * we don't need to set any PCI address on it, so we don't
4526 * mind too much */
4527 if (sound->model == VIR_DOMAIN_SOUND_MODEL_PCSPK) {
4528 virCommandAddArgList(cmd, "-soundhw", "pcspk", NULL);
4529 } else {
4530 if (qemuCommandAddExtDevice(cmd, &sound->info, qemuCaps) < 0)
4531 return -1;
4532
4533 if (qemuBuildSoundDevCmd(cmd, def, sound, qemuCaps) < 0)
4534 return -1;
4535
4536 if (virDomainSoundModelSupportsCodecs(sound)) {
4537 for (j = 0; j < sound->ncodecs; j++) {
4538 if (qemuBuildSoundCodecCmd(cmd, def, sound, sound->codecs[j],
4539 qemuCaps) < 0)
4540 return -1;
4541 }
4542
4543 if (j == 0) {
4544 virDomainSoundCodecDef codec = { VIR_DOMAIN_SOUND_CODEC_TYPE_DUPLEX, 0 };
4545
4546 if (qemuBuildSoundCodecCmd(cmd, def, sound, &codec, qemuCaps) < 0)
4547 return -1;
4548 }
4549 }
4550 }
4551 }
4552 return 0;
4553 }
4554
4555
4556 static int
qemuBuildDeviceVideoCmd(virCommand * cmd,const virDomainDef * def,virDomainVideoDef * video,virQEMUCaps * qemuCaps)4557 qemuBuildDeviceVideoCmd(virCommand *cmd,
4558 const virDomainDef *def,
4559 virDomainVideoDef *video,
4560 virQEMUCaps *qemuCaps)
4561 {
4562 const char *model = NULL;
4563 virTristateSwitch virgl = VIR_TRISTATE_SWITCH_ABSENT;
4564 bool virtio = false;
4565 bool virtioBusSuffix = false;
4566 g_autoptr(virJSONValue) props = NULL;
4567
4568 if (!(model = qemuDeviceVideoGetModel(qemuCaps, video, &virtio, &virtioBusSuffix)))
4569 return -1;
4570
4571 if (virtio) {
4572 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_VIDEO, video, qemuCaps)))
4573 return -1;
4574 } else {
4575 if (virJSONValueObjectAdd(&props,
4576 "s:driver", model,
4577 NULL) < 0)
4578 return -1;
4579 }
4580
4581 if (video->backend != VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER &&
4582 video->type == VIR_DOMAIN_VIDEO_TYPE_VIRTIO) {
4583 if (video->accel &&
4584 virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_GPU_VIRGL)) {
4585 virgl = video->accel->accel3d;
4586 }
4587 }
4588
4589 if (virJSONValueObjectAdd(&props,
4590 "s:id", video->info.alias,
4591 "T:virgl", virgl,
4592 NULL) < 0)
4593 return -1;
4594
4595 if (video->type == VIR_DOMAIN_VIDEO_TYPE_QXL) {
4596 if (virJSONValueObjectAdd(&props,
4597 "p:ram_size", video->ram * 1024,
4598 "p:vram_size", video->vram * 1024,
4599 NULL) < 0)
4600 return -1;
4601
4602 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VRAM64)) {
4603 if (virJSONValueObjectAdd(&props,
4604 "u:vram64_size_mb", video->vram64 / 1024,
4605 NULL) < 0)
4606 return -1;
4607 }
4608
4609 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGAMEM)) {
4610 if (virJSONValueObjectAdd(&props,
4611 "u:vgamem_mb", video->vgamem / 1024,
4612 NULL) < 0)
4613 return -1;
4614 }
4615
4616 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_MAX_OUTPUTS)) {
4617 if (virJSONValueObjectAdd(&props,
4618 "p:max_outputs", video->heads,
4619 NULL) < 0)
4620 return -1;
4621 }
4622 } else if (video->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER) {
4623 g_autofree char *alias = qemuDomainGetVhostUserChrAlias(video->info.alias);
4624
4625 if (virJSONValueObjectAdd(&props,
4626 "p:max_outputs", video->heads,
4627 "s:chardev", alias,
4628 NULL) < 0)
4629 return -1;
4630 } else if (video->type == VIR_DOMAIN_VIDEO_TYPE_VIRTIO) {
4631 unsigned int heads = 0;
4632
4633 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_GPU_MAX_OUTPUTS))
4634 heads = video->heads;
4635
4636 if (virJSONValueObjectAdd(&props,
4637 "p:max_outputs", heads,
4638 NULL) < 0)
4639 return -1;
4640 } else if ((video->type == VIR_DOMAIN_VIDEO_TYPE_VGA &&
4641 virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_VGAMEM)) ||
4642 (video->type == VIR_DOMAIN_VIDEO_TYPE_VMVGA &&
4643 virQEMUCapsGet(qemuCaps, QEMU_CAPS_VMWARE_SVGA_VGAMEM))) {
4644 if (virJSONValueObjectAdd(&props,
4645 "p:vgamem_mb", video->vram / 1024,
4646 NULL) < 0)
4647 return -1;
4648 } else if (video->type == VIR_DOMAIN_VIDEO_TYPE_BOCHS) {
4649 if (virJSONValueObjectAdd(&props,
4650 "p:vgamem", video->vram * 1024,
4651 NULL) < 0)
4652 return -1;
4653 }
4654
4655 if (video->res) {
4656 if (virJSONValueObjectAdd(&props,
4657 "p:xres", video->res->x,
4658 "p:yres", video->res->y,
4659 NULL) < 0)
4660 return -1;
4661 }
4662
4663 if (qemuBuildDeviceAddressProps(props, def, &video->info) < 0)
4664 return -1;
4665
4666 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
4667 return -1;
4668
4669 return 0;
4670 }
4671
4672
4673 static char *
qemuBuildVhostUserChardevStr(const char * alias,int * fd,virCommand * cmd)4674 qemuBuildVhostUserChardevStr(const char *alias,
4675 int *fd,
4676 virCommand *cmd)
4677 {
4678 g_autofree char *chardev_alias = qemuDomainGetVhostUserChrAlias(alias);
4679 char *chardev = NULL;
4680
4681 if (*fd == -1) {
4682 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4683 _("Attempt to pass closed vhostuser FD"));
4684 return NULL;
4685 }
4686
4687 chardev = g_strdup_printf("socket,id=%s,fd=%d", chardev_alias, *fd);
4688
4689 virCommandPassFD(cmd, *fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
4690 *fd = -1;
4691
4692 return chardev;
4693 }
4694
4695
4696 static int
qemuBuildVideoCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)4697 qemuBuildVideoCommandLine(virCommand *cmd,
4698 const virDomainDef *def,
4699 virQEMUCaps *qemuCaps)
4700 {
4701 size_t i;
4702
4703 for (i = 0; i < def->nvideos; i++) {
4704 g_autofree char *chardev = NULL;
4705 virDomainVideoDef *video = def->videos[i];
4706
4707 if (video->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER) {
4708 if (!(chardev = qemuBuildVhostUserChardevStr(video->info.alias,
4709 &QEMU_DOMAIN_VIDEO_PRIVATE(video)->vhost_user_fd,
4710 cmd)))
4711 return -1;
4712
4713 virCommandAddArgList(cmd, "-chardev", chardev, NULL);
4714 }
4715 }
4716
4717 for (i = 0; i < def->nvideos; i++) {
4718 virDomainVideoDef *video = def->videos[i];
4719
4720 if (video->type == VIR_DOMAIN_VIDEO_TYPE_NONE)
4721 continue;
4722
4723 if (qemuCommandAddExtDevice(cmd, &def->videos[i]->info, qemuCaps) < 0)
4724 return -1;
4725
4726 if (qemuBuildDeviceVideoCmd(cmd, def, video, qemuCaps) < 0)
4727 return -1;
4728 }
4729
4730 return 0;
4731 }
4732
4733
4734 virJSONValue *
qemuBuildPCIHostdevDevProps(const virDomainDef * def,virDomainHostdevDef * dev)4735 qemuBuildPCIHostdevDevProps(const virDomainDef *def,
4736 virDomainHostdevDef *dev)
4737 {
4738 g_autoptr(virJSONValue) props = NULL;
4739 virDomainHostdevSubsysPCI *pcisrc = &dev->source.subsys.u.pci;
4740 virDomainNetTeamingInfo *teaming;
4741 g_autofree char *host = g_strdup_printf(VIR_PCI_DEVICE_ADDRESS_FMT,
4742 pcisrc->addr.domain,
4743 pcisrc->addr.bus,
4744 pcisrc->addr.slot,
4745 pcisrc->addr.function);
4746 const char *failover_pair_id = NULL;
4747
4748 /* caller has to assign proper passthrough backend type */
4749 switch ((virDomainHostdevSubsysPCIBackendType) pcisrc->backend) {
4750 case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
4751 break;
4752
4753 case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
4754 case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
4755 case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
4756 case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
4757 virReportError(VIR_ERR_INTERNAL_ERROR,
4758 _("invalid PCI passthrough type '%s'"),
4759 virDomainHostdevSubsysPCIBackendTypeToString(pcisrc->backend));
4760 return NULL;
4761 }
4762
4763 if (dev->parentnet)
4764 teaming = dev->parentnet->teaming;
4765 else
4766 teaming = dev->teaming;
4767
4768 if (teaming &&
4769 teaming->type == VIR_DOMAIN_NET_TEAMING_TYPE_TRANSIENT &&
4770 teaming->persistent)
4771 failover_pair_id = teaming->persistent;
4772
4773 if (virJSONValueObjectAdd(&props,
4774 "s:driver", "vfio-pci",
4775 "s:host", host,
4776 "s:id", dev->info->alias,
4777 "p:bootindex", dev->info->effectiveBootIndex,
4778 "S:failover_pair_id", failover_pair_id,
4779 NULL) < 0)
4780 return NULL;
4781
4782 if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0)
4783 return NULL;
4784
4785 if (qemuBuildRomProps(props, dev->info) < 0)
4786 return NULL;
4787
4788 return g_steal_pointer(&props);
4789 }
4790
4791
4792 virJSONValue *
qemuBuildUSBHostdevDevProps(const virDomainDef * def,virDomainHostdevDef * dev,virQEMUCaps * qemuCaps)4793 qemuBuildUSBHostdevDevProps(const virDomainDef *def,
4794 virDomainHostdevDef *dev,
4795 virQEMUCaps *qemuCaps)
4796 {
4797 g_autoptr(virJSONValue) props = NULL;
4798 virDomainHostdevSubsysUSB *usbsrc = &dev->source.subsys.u.usb;
4799 unsigned int hostbus = 0;
4800 unsigned int hostaddr = 0;
4801 g_autofree char *hostdevice = NULL;
4802
4803 if (!dev->missing) {
4804 if (usbsrc->bus == 0 && usbsrc->device == 0) {
4805 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4806 _("USB host device is missing bus/device information"));
4807 return NULL;
4808 }
4809
4810 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_HOST_HOSTDEVICE)) {
4811 hostdevice = g_strdup_printf("/dev/bus/usb/%03d/%03d",
4812 usbsrc->bus, usbsrc->device);
4813 } else {
4814 hostbus = usbsrc->bus;
4815 hostaddr = usbsrc->device;
4816 }
4817 }
4818
4819 if (virJSONValueObjectAdd(&props,
4820 "s:driver", "usb-host",
4821 "S:hostdevice", hostdevice,
4822 "p:hostbus", hostbus,
4823 "p:hostaddr", hostaddr,
4824 "s:id", dev->info->alias,
4825 "p:bootindex", dev->info->bootIndex,
4826 NULL) < 0)
4827 return NULL;
4828
4829 if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0)
4830 return NULL;
4831
4832 return g_steal_pointer(&props);
4833 }
4834
4835
4836 static int
qemuBuildHubDevCmd(virCommand * cmd,const virDomainDef * def,virDomainHubDef * dev,virQEMUCaps * qemuCaps)4837 qemuBuildHubDevCmd(virCommand *cmd,
4838 const virDomainDef *def,
4839 virDomainHubDef *dev,
4840 virQEMUCaps *qemuCaps)
4841 {
4842 g_autoptr(virJSONValue) props = NULL;
4843
4844 if (virJSONValueObjectAdd(&props,
4845 "s:driver", "usb-hub",
4846 "s:id", dev->info.alias,
4847 NULL) < 0)
4848 return -1;
4849
4850 if (qemuBuildDeviceAddressProps(props, def, &dev->info) < 0)
4851 return -1;
4852
4853 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
4854 return -1;
4855
4856 return 0;
4857 }
4858
4859
4860 static int
qemuBuildHubCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)4861 qemuBuildHubCommandLine(virCommand *cmd,
4862 const virDomainDef *def,
4863 virQEMUCaps *qemuCaps)
4864 {
4865 size_t i;
4866
4867 for (i = 0; i < def->nhubs; i++) {
4868 if (qemuBuildHubDevCmd(cmd, def, def->hubs[i], qemuCaps) < 0)
4869 return -1;
4870 }
4871
4872 return 0;
4873 }
4874
4875
4876 static char *
qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDef * dev)4877 qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDef *dev)
4878 {
4879 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4880 g_autoptr(virJSONValue) srcprops = NULL;
4881 virDomainHostdevSubsysSCSI *scsisrc = &dev->source.subsys.u.scsi;
4882 virDomainHostdevSubsysSCSIiSCSI *iscsisrc = &scsisrc->u.iscsi;
4883
4884 if (!(srcprops = qemuDiskSourceGetProps(iscsisrc->src)))
4885 return NULL;
4886
4887 if (virQEMUBuildCommandLineJSON(srcprops, &buf, NULL,
4888 virQEMUBuildCommandLineJSONArrayNumbered) < 0)
4889 return NULL;
4890
4891 virBufferAddLit(&buf, ",if=none,format=raw");
4892
4893 return virBufferContentAndReset(&buf);
4894 }
4895
4896
4897 virJSONValue *
qemuBuildSCSIVHostHostdevDevProps(const virDomainDef * def,virDomainHostdevDef * dev,virQEMUCaps * qemuCaps,char * vhostfdName)4898 qemuBuildSCSIVHostHostdevDevProps(const virDomainDef *def,
4899 virDomainHostdevDef *dev,
4900 virQEMUCaps *qemuCaps,
4901 char *vhostfdName)
4902 {
4903 g_autoptr(virJSONValue) props = NULL;
4904 virDomainHostdevSubsysSCSIVHost *hostsrc = &dev->source.subsys.u.scsi_host;
4905
4906 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_HOSTDEV, dev, qemuCaps)))
4907 return NULL;
4908
4909 if (virJSONValueObjectAdd(&props,
4910 "s:wwpn", hostsrc->wwpn,
4911 "s:vhostfd", vhostfdName,
4912 "s:id", dev->info->alias,
4913 NULL) < 0)
4914 return NULL;
4915
4916 if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0)
4917 return NULL;
4918
4919 return g_steal_pointer(&props);
4920 }
4921
4922
4923 static char *
qemuBuildSCSIHostdevDrvStr(virDomainHostdevDef * dev)4924 qemuBuildSCSIHostdevDrvStr(virDomainHostdevDef *dev)
4925 {
4926 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4927 g_autofree char *source = NULL;
4928 g_autofree char *drivealias = NULL;
4929 virDomainHostdevSubsysSCSI *scsisrc = &dev->source.subsys.u.scsi;
4930
4931 if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
4932 if (!(source = qemuBuildSCSIiSCSIHostdevDrvStr(dev)))
4933 return NULL;
4934 virBufferAdd(&buf, source, -1);
4935 } else {
4936 virBufferAsprintf(&buf, "file=%s,if=none,format=raw", scsisrc->u.host.src->path);
4937 }
4938
4939 if (!(drivealias = qemuAliasFromHostdev(dev)))
4940 return NULL;
4941 virBufferAsprintf(&buf, ",id=%s", drivealias);
4942
4943 if (dev->readonly)
4944 virBufferAddLit(&buf, ",readonly=on");
4945
4946 return virBufferContentAndReset(&buf);
4947 }
4948
4949 virJSONValue *
qemuBuildSCSIHostdevDevProps(const virDomainDef * def,virDomainHostdevDef * dev,const char * backendAlias)4950 qemuBuildSCSIHostdevDevProps(const virDomainDef *def,
4951 virDomainHostdevDef *dev,
4952 const char *backendAlias)
4953 {
4954 g_autoptr(virJSONValue) props = NULL;
4955
4956 if (virJSONValueObjectAdd(&props,
4957 "s:driver", "scsi-generic",
4958 "s:drive", backendAlias,
4959 "s:id", dev->info->alias,
4960 "p:bootindex", dev->info->bootIndex,
4961 NULL) < 0)
4962 return NULL;
4963
4964 if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0)
4965 return NULL;
4966
4967 return g_steal_pointer(&props);
4968 }
4969
4970 static int
qemuBuildChrChardevFileStr(virLogManager * logManager,virSecurityManager * secManager,virQEMUDriverConfig * cfg,virQEMUCaps * qemuCaps,const virDomainDef * def,virCommand * cmd,virBuffer * buf,const char * filearg,const char * fileval,const char * appendarg,int appendval)4971 qemuBuildChrChardevFileStr(virLogManager *logManager,
4972 virSecurityManager *secManager,
4973 virQEMUDriverConfig *cfg,
4974 virQEMUCaps *qemuCaps,
4975 const virDomainDef *def,
4976 virCommand *cmd,
4977 virBuffer *buf,
4978 const char *filearg, const char *fileval,
4979 const char *appendarg, int appendval)
4980 {
4981 /* Technically, to pass an FD via /dev/fdset we don't need
4982 * any capability check because X_QEMU_CAPS_ADD_FD is already
4983 * assumed. But keeping the old style is still handy when
4984 * building a standalone command line (e.g. for tests). */
4985 if (logManager ||
4986 virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS_COMMANDLINE)) {
4987 g_autofree char *fdset = NULL;
4988 int logfd;
4989 size_t idx;
4990
4991 if (logManager) {
4992 int flags = 0;
4993
4994 if (appendval == VIR_TRISTATE_SWITCH_ABSENT ||
4995 appendval == VIR_TRISTATE_SWITCH_OFF)
4996 flags |= VIR_LOG_MANAGER_PROTOCOL_DOMAIN_OPEN_LOG_FILE_TRUNCATE;
4997
4998 if ((logfd = virLogManagerDomainOpenLogFile(logManager,
4999 "qemu",
5000 def->uuid,
5001 def->name,
5002 fileval,
5003 flags,
5004 NULL, NULL)) < 0)
5005 return -1;
5006 } else {
5007 int oflags = O_CREAT | O_WRONLY;
5008
5009 switch (appendval) {
5010 case VIR_TRISTATE_SWITCH_ABSENT:
5011 case VIR_TRISTATE_SWITCH_OFF:
5012 oflags |= O_TRUNC;
5013 break;
5014 case VIR_TRISTATE_SWITCH_ON:
5015 oflags |= O_APPEND;
5016 break;
5017 case VIR_TRISTATE_SWITCH_LAST:
5018 break;
5019 }
5020
5021 if ((logfd = qemuDomainOpenFile(cfg, def, fileval, oflags, NULL)) < 0)
5022 return -1;
5023
5024 if (qemuSecuritySetImageFDLabel(secManager, (virDomainDef*)def, logfd) < 0) {
5025 VIR_FORCE_CLOSE(logfd);
5026 return -1;
5027 }
5028 }
5029
5030 virCommandPassFDIndex(cmd, logfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT, &idx);
5031 fdset = qemuBuildFDSet(logfd, idx);
5032
5033 virCommandAddArg(cmd, "-add-fd");
5034 virCommandAddArg(cmd, fdset);
5035
5036 virBufferAsprintf(buf, ",%s=/dev/fdset/%zu,%s=on", filearg, idx, appendarg);
5037 } else {
5038 virBufferAsprintf(buf, ",%s=", filearg);
5039 virQEMUBuildBufferEscapeComma(buf, fileval);
5040 if (appendval != VIR_TRISTATE_SWITCH_ABSENT) {
5041 virBufferAsprintf(buf, ",%s=%s", appendarg,
5042 virTristateSwitchTypeToString(appendval));
5043 }
5044 }
5045
5046 return 0;
5047 }
5048
5049
5050 static void
qemuBuildChrChardevReconnectStr(virBuffer * buf,const virDomainChrSourceReconnectDef * def)5051 qemuBuildChrChardevReconnectStr(virBuffer *buf,
5052 const virDomainChrSourceReconnectDef *def)
5053 {
5054 if (def->enabled == VIR_TRISTATE_BOOL_YES) {
5055 virBufferAsprintf(buf, ",reconnect=%u", def->timeout);
5056 } else if (def->enabled == VIR_TRISTATE_BOOL_NO) {
5057 virBufferAddLit(buf, ",reconnect=0");
5058 }
5059 }
5060
5061
5062 int
qemuOpenChrChardevUNIXSocket(const virDomainChrSourceDef * dev)5063 qemuOpenChrChardevUNIXSocket(const virDomainChrSourceDef *dev)
5064 {
5065 struct sockaddr_un addr;
5066 socklen_t addrlen = sizeof(addr);
5067 int fd;
5068
5069 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
5070 virReportSystemError(errno, "%s",
5071 _("Unable to create UNIX socket"));
5072 goto error;
5073 }
5074
5075 memset(&addr, 0, sizeof(addr));
5076 addr.sun_family = AF_UNIX;
5077 if (virStrcpyStatic(addr.sun_path, dev->data.nix.path) < 0) {
5078 virReportError(VIR_ERR_INTERNAL_ERROR,
5079 _("UNIX socket path '%s' too long"),
5080 dev->data.nix.path);
5081 goto error;
5082 }
5083
5084 if (unlink(dev->data.nix.path) < 0 && errno != ENOENT) {
5085 virReportSystemError(errno,
5086 _("Unable to unlink %s"),
5087 dev->data.nix.path);
5088 goto error;
5089 }
5090
5091 if (bind(fd, (struct sockaddr *)&addr, addrlen) < 0) {
5092 virReportSystemError(errno,
5093 _("Unable to bind to UNIX socket path '%s'"),
5094 dev->data.nix.path);
5095 goto error;
5096 }
5097
5098 if (listen(fd, 1) < 0) {
5099 virReportSystemError(errno,
5100 _("Unable to listen to UNIX socket path '%s'"),
5101 dev->data.nix.path);
5102 goto error;
5103 }
5104
5105 /* We run QEMU with umask 0002. Compensate for the umask
5106 * libvirtd might be running under to get the same permission
5107 * QEMU would have. */
5108 if (virFileUpdatePerm(dev->data.nix.path, 0002, 0664) < 0)
5109 goto error;
5110
5111 return fd;
5112
5113 error:
5114 VIR_FORCE_CLOSE(fd);
5115 return -1;
5116 }
5117
5118
5119 enum {
5120 QEMU_BUILD_CHARDEV_TCP_NOWAIT = (1 << 0),
5121 QEMU_BUILD_CHARDEV_FILE_LOGD = (1 << 1),
5122 QEMU_BUILD_CHARDEV_UNIX_FD_PASS = (1 << 2),
5123 };
5124
5125 /* This function outputs a -chardev command line option which describes only the
5126 * host side of the character device */
5127 static char *
qemuBuildChrChardevStr(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,const virDomainChrSourceDef * dev,const char * alias,virQEMUCaps * qemuCaps,unsigned int cdevflags)5128 qemuBuildChrChardevStr(virLogManager *logManager,
5129 virSecurityManager *secManager,
5130 virCommand *cmd,
5131 virQEMUDriverConfig *cfg,
5132 const virDomainDef *def,
5133 const virDomainChrSourceDef *dev,
5134 const char *alias,
5135 virQEMUCaps *qemuCaps,
5136 unsigned int cdevflags)
5137 {
5138 qemuDomainChrSourcePrivate *chrSourcePriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev);
5139 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5140 bool telnet;
5141 g_autofree char *charAlias = NULL;
5142
5143 if (!(charAlias = qemuAliasChardevFromDevAlias(alias)))
5144 return NULL;
5145
5146 switch ((virDomainChrType) dev->type) {
5147 case VIR_DOMAIN_CHR_TYPE_NULL:
5148 virBufferAsprintf(&buf, "null,id=%s", charAlias);
5149 break;
5150
5151 case VIR_DOMAIN_CHR_TYPE_VC:
5152 virBufferAsprintf(&buf, "vc,id=%s", charAlias);
5153 break;
5154
5155 case VIR_DOMAIN_CHR_TYPE_PTY:
5156 virBufferAsprintf(&buf, "pty,id=%s", charAlias);
5157 break;
5158
5159 case VIR_DOMAIN_CHR_TYPE_DEV:
5160 virBufferAsprintf(&buf, "%s,id=%s,path=",
5161 STRPREFIX(alias, "parallel") ? "parport" : "tty",
5162 charAlias);
5163 virQEMUBuildBufferEscapeComma(&buf, dev->data.file.path);
5164 break;
5165
5166 case VIR_DOMAIN_CHR_TYPE_FILE:
5167 virBufferAsprintf(&buf, "file,id=%s", charAlias);
5168
5169 if (qemuBuildChrChardevFileStr(cdevflags & QEMU_BUILD_CHARDEV_FILE_LOGD ?
5170 logManager : NULL,
5171 secManager, cfg, qemuCaps, def, cmd, &buf,
5172 "path", dev->data.file.path,
5173 "append", dev->data.file.append) < 0)
5174 return NULL;
5175 break;
5176
5177 case VIR_DOMAIN_CHR_TYPE_PIPE:
5178 virBufferAsprintf(&buf, "pipe,id=%s,path=", charAlias);
5179 virQEMUBuildBufferEscapeComma(&buf, dev->data.file.path);
5180 break;
5181
5182 case VIR_DOMAIN_CHR_TYPE_STDIO:
5183 virBufferAsprintf(&buf, "stdio,id=%s", charAlias);
5184 break;
5185
5186 case VIR_DOMAIN_CHR_TYPE_UDP: {
5187 const char *connectHost = dev->data.udp.connectHost;
5188 const char *bindHost = dev->data.udp.bindHost;
5189 const char *bindService = dev->data.udp.bindService;
5190
5191 if (connectHost == NULL)
5192 connectHost = "";
5193 if (bindHost == NULL)
5194 bindHost = "";
5195 if (bindService == NULL)
5196 bindService = "0";
5197
5198 virBufferAsprintf(&buf,
5199 "udp,id=%s,host=%s,port=%s,localaddr=%s,"
5200 "localport=%s",
5201 charAlias,
5202 connectHost,
5203 dev->data.udp.connectService,
5204 bindHost, bindService);
5205 break;
5206 }
5207 case VIR_DOMAIN_CHR_TYPE_TCP:
5208 telnet = dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
5209 virBufferAsprintf(&buf,
5210 "socket,id=%s,host=%s,port=%s%s",
5211 charAlias,
5212 dev->data.tcp.host,
5213 dev->data.tcp.service,
5214 telnet ? ",telnet=on" : "");
5215
5216 if (dev->data.tcp.listen) {
5217 virBufferAddLit(&buf, ",server=on");
5218 if (cdevflags & QEMU_BUILD_CHARDEV_TCP_NOWAIT)
5219 virBufferAddLit(&buf, ",wait=off");
5220 }
5221
5222 qemuBuildChrChardevReconnectStr(&buf, &dev->data.tcp.reconnect);
5223
5224 if (dev->data.tcp.haveTLS == VIR_TRISTATE_BOOL_YES) {
5225 g_autofree char *objalias = NULL;
5226 const char *tlsCertEncSecAlias = NULL;
5227
5228 /* Add the secret object first if necessary. The
5229 * secinfo is added only to a TCP serial device during
5230 * qemuDomainSecretChardevPrepare. Subsequently called
5231 * functions can just check the config fields */
5232 if (chrSourcePriv && chrSourcePriv->secinfo) {
5233 if (qemuBuildObjectSecretCommandLine(cmd,
5234 chrSourcePriv->secinfo,
5235 qemuCaps) < 0)
5236 return NULL;
5237
5238 tlsCertEncSecAlias = chrSourcePriv->secinfo->alias;
5239 }
5240
5241 if (!(objalias = qemuAliasTLSObjFromSrcAlias(charAlias)))
5242 return NULL;
5243
5244 if (qemuBuildTLSx509CommandLine(cmd, cfg->chardevTLSx509certdir,
5245 dev->data.tcp.listen,
5246 cfg->chardevTLSx509verify,
5247 tlsCertEncSecAlias,
5248 objalias, qemuCaps) < 0) {
5249 return NULL;
5250 }
5251
5252 virBufferAsprintf(&buf, ",tls-creds=%s", objalias);
5253 }
5254 break;
5255
5256 case VIR_DOMAIN_CHR_TYPE_UNIX:
5257 virBufferAsprintf(&buf, "socket,id=%s", charAlias);
5258 if (dev->data.nix.listen &&
5259 (cdevflags & QEMU_BUILD_CHARDEV_UNIX_FD_PASS) &&
5260 virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS_COMMANDLINE)) {
5261 int fd;
5262
5263 if (qemuSecuritySetSocketLabel(secManager, (virDomainDef *)def) < 0)
5264 return NULL;
5265 fd = qemuOpenChrChardevUNIXSocket(dev);
5266 if (qemuSecurityClearSocketLabel(secManager, (virDomainDef *)def) < 0) {
5267 VIR_FORCE_CLOSE(fd);
5268 return NULL;
5269 }
5270 if (fd < 0)
5271 return NULL;
5272
5273 virBufferAsprintf(&buf, ",fd=%d", fd);
5274
5275 virCommandPassFD(cmd, fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
5276 } else {
5277 virBufferAddLit(&buf, ",path=");
5278 virQEMUBuildBufferEscapeComma(&buf, dev->data.nix.path);
5279 }
5280 if (dev->data.nix.listen) {
5281 virBufferAddLit(&buf, ",server=on");
5282 if (cdevflags & QEMU_BUILD_CHARDEV_TCP_NOWAIT)
5283 virBufferAddLit(&buf, ",wait=off");
5284 }
5285
5286 qemuBuildChrChardevReconnectStr(&buf, &dev->data.nix.reconnect);
5287 break;
5288
5289 case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
5290 virBufferAsprintf(&buf, "spicevmc,id=%s,name=%s", charAlias,
5291 virDomainChrSpicevmcTypeToString(dev->data.spicevmc));
5292 break;
5293
5294 case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
5295 virBufferAsprintf(&buf, "spiceport,id=%s,name=%s", charAlias,
5296 dev->data.spiceport.channel);
5297 break;
5298
5299 case VIR_DOMAIN_CHR_TYPE_NMDM:
5300 case VIR_DOMAIN_CHR_TYPE_LAST:
5301 default:
5302 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5303 _("unsupported chardev '%s'"),
5304 virDomainChrTypeToString(dev->type));
5305 return NULL;
5306 }
5307
5308 if (dev->logfile) {
5309 if (qemuBuildChrChardevFileStr(logManager, secManager, cfg,
5310 qemuCaps, def, cmd, &buf,
5311 "logfile", dev->logfile,
5312 "logappend", dev->logappend) < 0)
5313 return NULL;
5314 }
5315
5316 return virBufferContentAndReset(&buf);
5317 }
5318
5319
5320 static const char *
qemuBuildHostdevMdevModelTypeString(virDomainHostdevSubsysMediatedDev * mdev)5321 qemuBuildHostdevMdevModelTypeString(virDomainHostdevSubsysMediatedDev *mdev)
5322 {
5323 /* when the 'ramfb' attribute is set, we must use the nohotplug variant
5324 * rather than 'vfio-pci' */
5325 if (mdev->model == VIR_MDEV_MODEL_TYPE_VFIO_PCI &&
5326 mdev->ramfb == VIR_TRISTATE_SWITCH_ON)
5327 return "vfio-pci-nohotplug";
5328
5329 return virMediatedDeviceModelTypeToString(mdev->model);
5330 }
5331
5332
5333 virJSONValue *
qemuBuildHostdevMediatedDevProps(const virDomainDef * def,virDomainHostdevDef * dev)5334 qemuBuildHostdevMediatedDevProps(const virDomainDef *def,
5335 virDomainHostdevDef *dev)
5336 {
5337 g_autoptr(virJSONValue) props = NULL;
5338 virDomainHostdevSubsysMediatedDev *mdevsrc = &dev->source.subsys.u.mdev;
5339 g_autofree char *mdevPath = NULL;
5340 /* 'ramfb' property must be omitted unless it's to be enabled */
5341 bool ramfb = mdevsrc->ramfb == VIR_TRISTATE_SWITCH_ON;
5342
5343 mdevPath = virMediatedDeviceGetSysfsPath(mdevsrc->uuidstr);
5344
5345 if (virJSONValueObjectAdd(&props,
5346 "s:driver", qemuBuildHostdevMdevModelTypeString(mdevsrc),
5347 "s:id", dev->info->alias,
5348 "s:sysfsdev", mdevPath,
5349 "S:display", qemuOnOffAuto(mdevsrc->display),
5350 "B:ramfb", ramfb,
5351 "p:bootindex", dev->info->bootIndex,
5352 NULL) < 0)
5353 return NULL;
5354
5355 if (qemuBuildDeviceAddressProps(props, def, dev->info) < 0)
5356 return NULL;
5357
5358 return g_steal_pointer(&props);
5359 }
5360
5361
5362 qemuBlockStorageSourceAttachData *
qemuBuildHostdevSCSIDetachPrepare(virDomainHostdevDef * hostdev,virQEMUCaps * qemuCaps)5363 qemuBuildHostdevSCSIDetachPrepare(virDomainHostdevDef *hostdev,
5364 virQEMUCaps *qemuCaps)
5365 {
5366 virDomainHostdevSubsysSCSI *scsisrc = &hostdev->source.subsys.u.scsi;
5367 g_autoptr(qemuBlockStorageSourceAttachData) ret = g_new0(qemuBlockStorageSourceAttachData, 1);
5368
5369 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV_HOSTDEV_SCSI)) {
5370 virStorageSource *src;
5371 qemuDomainStorageSourcePrivate *srcpriv;
5372
5373 switch ((virDomainHostdevSCSIProtocolType) scsisrc->protocol) {
5374 case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_NONE:
5375 src = scsisrc->u.host.src;
5376 break;
5377
5378 case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI:
5379 src = scsisrc->u.iscsi.src;
5380 break;
5381
5382 case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST:
5383 default:
5384 virReportEnumRangeError(virDomainHostdevSCSIProtocolType, scsisrc->protocol);
5385 return NULL;
5386 }
5387
5388 srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
5389 ret->storageNodeName = src->nodestorage;
5390 ret->storageAttached = true;
5391
5392 if (srcpriv && srcpriv->secinfo)
5393 ret->authsecretAlias = g_strdup(srcpriv->secinfo->alias);
5394
5395 } else {
5396 ret->driveAlias = qemuAliasFromHostdev(hostdev);
5397 ret->driveAdded = true;
5398 }
5399
5400 return g_steal_pointer(&ret);
5401 }
5402
5403
5404 qemuBlockStorageSourceAttachData *
qemuBuildHostdevSCSIAttachPrepare(virDomainHostdevDef * hostdev,const char ** backendAlias,virQEMUCaps * qemuCaps)5405 qemuBuildHostdevSCSIAttachPrepare(virDomainHostdevDef *hostdev,
5406 const char **backendAlias,
5407 virQEMUCaps *qemuCaps)
5408 {
5409 virDomainHostdevSubsysSCSI *scsisrc = &hostdev->source.subsys.u.scsi;
5410 g_autoptr(qemuBlockStorageSourceAttachData) ret = g_new0(qemuBlockStorageSourceAttachData, 1);
5411 virStorageSource *src = NULL;
5412
5413 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV_HOSTDEV_SCSI)) {
5414 switch ((virDomainHostdevSCSIProtocolType) scsisrc->protocol) {
5415 case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_NONE:
5416 src = scsisrc->u.host.src;
5417 break;
5418
5419 case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI:
5420 src = scsisrc->u.iscsi.src;
5421 break;
5422
5423 case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST:
5424 default:
5425 virReportEnumRangeError(virDomainHostdevSCSIProtocolType, scsisrc->protocol);
5426 return NULL;
5427 }
5428
5429 ret->storageNodeName = src->nodestorage;
5430 *backendAlias = src->nodestorage;
5431
5432 if (!(ret->storageProps = qemuBlockStorageSourceGetBackendProps(src,
5433 QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_SKIP_UNMAP)))
5434 return NULL;
5435
5436 } else {
5437 if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
5438 src = scsisrc->u.iscsi.src;
5439 ret->driveCmd = qemuBuildSCSIHostdevDrvStr(hostdev);
5440 ret->driveAlias = qemuAliasFromHostdev(hostdev);
5441 *backendAlias = ret->driveAlias;
5442 }
5443
5444 if (src &&
5445 qemuBuildStorageSourceAttachPrepareCommon(src, ret) < 0)
5446 return NULL;
5447
5448 return g_steal_pointer(&ret);
5449 }
5450
5451
5452 static int
qemuBuildHostdevSCSICommandLine(virCommand * cmd,const virDomainDef * def,virDomainHostdevDef * hostdev,virQEMUCaps * qemuCaps)5453 qemuBuildHostdevSCSICommandLine(virCommand *cmd,
5454 const virDomainDef *def,
5455 virDomainHostdevDef *hostdev,
5456 virQEMUCaps *qemuCaps)
5457 {
5458 g_autoptr(qemuBlockStorageSourceAttachData) data = NULL;
5459 g_autoptr(virJSONValue) devprops = NULL;
5460 const char *backendAlias = NULL;
5461
5462 if (!(data = qemuBuildHostdevSCSIAttachPrepare(hostdev, &backendAlias, qemuCaps)))
5463 return -1;
5464
5465 if (qemuBuildBlockStorageSourceAttachDataCommandline(cmd, data, qemuCaps) < 0)
5466 return -1;
5467
5468 if (!(devprops = qemuBuildSCSIHostdevDevProps(def, hostdev, backendAlias)))
5469 return -1;
5470
5471 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
5472 return -1;
5473
5474 return 0;
5475 }
5476
5477
5478 static int
qemuBuildHostdevCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)5479 qemuBuildHostdevCommandLine(virCommand *cmd,
5480 const virDomainDef *def,
5481 virQEMUCaps *qemuCaps)
5482 {
5483 size_t i;
5484
5485 for (i = 0; i < def->nhostdevs; i++) {
5486 virDomainHostdevDef *hostdev = def->hostdevs[i];
5487 virDomainHostdevSubsys *subsys = &hostdev->source.subsys;
5488 virDomainHostdevSubsysMediatedDev *mdevsrc = &subsys->u.mdev;
5489 g_autoptr(virJSONValue) devprops = NULL;
5490 g_autofree char *vhostfdName = NULL;
5491 int vhostfd = -1;
5492
5493 if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
5494 continue;
5495
5496 switch ((virDomainHostdevSubsysType) subsys->type) {
5497 /* USB */
5498 case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
5499 if (!(devprops = qemuBuildUSBHostdevDevProps(def, hostdev, qemuCaps)))
5500 return -1;
5501
5502 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
5503 return -1;
5504 break;
5505
5506 /* PCI */
5507 case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
5508 /* Ignore unassigned devices */
5509 if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED)
5510 continue;
5511
5512 if (qemuCommandAddExtDevice(cmd, hostdev->info, qemuCaps) < 0)
5513 return -1;
5514
5515 if (!(devprops = qemuBuildPCIHostdevDevProps(def, hostdev)))
5516 return -1;
5517
5518 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
5519 return -1;
5520 break;
5521
5522 /* SCSI */
5523 case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
5524 if (qemuBuildHostdevSCSICommandLine(cmd, def, hostdev, qemuCaps) < 0)
5525 return -1;
5526 break;
5527
5528 /* SCSI_host */
5529 case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
5530 if (hostdev->source.subsys.u.scsi_host.protocol ==
5531 VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST) {
5532
5533 if (virSCSIVHostOpenVhostSCSI(&vhostfd) < 0)
5534 return -1;
5535
5536 vhostfdName = g_strdup_printf("%d", vhostfd);
5537
5538 virCommandPassFD(cmd, vhostfd,
5539 VIR_COMMAND_PASS_FD_CLOSE_PARENT);
5540
5541 if (!(devprops = qemuBuildSCSIVHostHostdevDevProps(def,
5542 hostdev,
5543 qemuCaps,
5544 vhostfdName)))
5545 return -1;
5546
5547 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
5548 return -1;
5549 }
5550
5551 break;
5552
5553 /* MDEV */
5554 case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
5555 switch ((virMediatedDeviceModelType) mdevsrc->model) {
5556 case VIR_MDEV_MODEL_TYPE_VFIO_PCI:
5557 case VIR_MDEV_MODEL_TYPE_VFIO_CCW:
5558 case VIR_MDEV_MODEL_TYPE_VFIO_AP:
5559 break;
5560 case VIR_MDEV_MODEL_TYPE_LAST:
5561 default:
5562 virReportEnumRangeError(virMediatedDeviceModelType,
5563 subsys->u.mdev.model);
5564 return -1;
5565 }
5566
5567 if (!(devprops = qemuBuildHostdevMediatedDevProps(def, hostdev)))
5568 return -1;
5569
5570 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
5571 return -1;
5572 break;
5573
5574 case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
5575 break;
5576 }
5577 }
5578
5579 return 0;
5580 }
5581
5582
5583 static int
qemuBuildMonitorCommandLine(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,virDomainDef * def,qemuDomainObjPrivate * priv)5584 qemuBuildMonitorCommandLine(virLogManager *logManager,
5585 virSecurityManager *secManager,
5586 virCommand *cmd,
5587 virQEMUDriverConfig *cfg,
5588 virDomainDef *def,
5589 qemuDomainObjPrivate *priv)
5590 {
5591 g_autofree char *chrdev = NULL;
5592 unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
5593 QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
5594 if (priv->chardevStdioLogd)
5595 cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
5596
5597 if (!priv->monConfig)
5598 return 0;
5599
5600 if (!(chrdev = qemuBuildChrChardevStr(logManager, secManager,
5601 cmd, cfg, def,
5602 priv->monConfig, "monitor",
5603 priv->qemuCaps, cdevflags)))
5604 return -1;
5605 virCommandAddArg(cmd, "-chardev");
5606 virCommandAddArg(cmd, chrdev);
5607
5608 virCommandAddArg(cmd, "-mon");
5609 virCommandAddArg(cmd, "chardev=charmonitor,id=monitor,mode=control");
5610
5611 return 0;
5612 }
5613
5614
5615 static virJSONValue *
qemuBuildVirtioSerialPortDevProps(const virDomainDef * def,virDomainChrDef * dev)5616 qemuBuildVirtioSerialPortDevProps(const virDomainDef *def,
5617 virDomainChrDef *dev)
5618 {
5619 g_autoptr(virJSONValue) props = NULL;
5620 const char *driver;
5621 const char *targetname = NULL;
5622 g_autofree char *chardev = NULL;
5623
5624 switch (dev->deviceType) {
5625 case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
5626 driver = "virtconsole";
5627 break;
5628 case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
5629 driver = "virtserialport";
5630 break;
5631 default:
5632 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5633 _("Cannot use virtio serial for parallel/serial devices"));
5634 return NULL;
5635 }
5636
5637 if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
5638 dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
5639 /* Check it's a virtio-serial address */
5640 if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL) {
5641 virReportError(VIR_ERR_INTERNAL_ERROR,
5642 "%s", _("virtio serial device has invalid address type"));
5643 return NULL;
5644 }
5645
5646 }
5647
5648 if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
5649 dev->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC &&
5650 dev->target.name &&
5651 STRNEQ(dev->target.name, "com.redhat.spice.0")) {
5652 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5653 _("Unsupported spicevmc target name '%s'"),
5654 dev->target.name);
5655 return NULL;
5656 }
5657
5658 if (virJSONValueObjectAdd(&props,
5659 "s:driver", driver,
5660 NULL) < 0)
5661 return NULL;
5662
5663 if (qemuBuildDeviceAddressProps(props, def, &dev->info) < 0)
5664 return NULL;
5665
5666 chardev = g_strdup_printf("char%s", dev->info.alias);
5667
5668 if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
5669 (dev->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC ||
5670 dev->target.name)) {
5671 if (dev->target.name)
5672 targetname = dev->target.name;
5673 else
5674 targetname = "com.redhat.spice.0";
5675 }
5676
5677 if (virJSONValueObjectAdd(&props,
5678 "s:chardev", chardev,
5679 "s:id", dev->info.alias,
5680 "S:name", targetname,
5681 NULL) < 0)
5682 return NULL;
5683
5684 return g_steal_pointer(&props);
5685 }
5686
5687
5688 static virJSONValue *
qemuBuildSclpDevProps(virDomainChrDef * dev)5689 qemuBuildSclpDevProps(virDomainChrDef *dev)
5690 {
5691 g_autoptr(virJSONValue) props = NULL;
5692 g_autofree char *chardev = g_strdup_printf("char%s", dev->info.alias);
5693 const char *driver = NULL;
5694
5695 if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE) {
5696 switch (dev->targetType) {
5697 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLP:
5698 driver = "sclpconsole";
5699 break;
5700 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLPLM:
5701 driver = "sclplmconsole";
5702 break;
5703 }
5704 } else {
5705 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5706 _("Cannot use slcp with devices other than console"));
5707 return NULL;
5708 }
5709
5710 if (virJSONValueObjectAdd(&props,
5711 "s:driver", driver,
5712 "s:chardev", chardev,
5713 "s:id", dev->info.alias,
5714 NULL) < 0)
5715 return NULL;
5716
5717 return g_steal_pointer(&props);
5718 }
5719
5720
5721 static int
qemuBuildRNGBackendChrdevStr(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,virDomainRNGDef * rng,virQEMUCaps * qemuCaps,char ** chr,bool chardevStdioLogd)5722 qemuBuildRNGBackendChrdevStr(virLogManager *logManager,
5723 virSecurityManager *secManager,
5724 virCommand *cmd,
5725 virQEMUDriverConfig *cfg,
5726 const virDomainDef *def,
5727 virDomainRNGDef *rng,
5728 virQEMUCaps *qemuCaps,
5729 char **chr,
5730 bool chardevStdioLogd)
5731 {
5732 unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
5733 QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
5734
5735 *chr = NULL;
5736
5737 if (chardevStdioLogd)
5738 cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
5739
5740 switch ((virDomainRNGBackend) rng->backend) {
5741 case VIR_DOMAIN_RNG_BACKEND_RANDOM:
5742 case VIR_DOMAIN_RNG_BACKEND_BUILTIN:
5743 case VIR_DOMAIN_RNG_BACKEND_LAST:
5744 /* no chardev backend is needed */
5745 return 0;
5746
5747 case VIR_DOMAIN_RNG_BACKEND_EGD:
5748 if (!(*chr = qemuBuildChrChardevStr(logManager, secManager,
5749 cmd, cfg, def,
5750 rng->source.chardev,
5751 rng->info.alias, qemuCaps,
5752 cdevflags)))
5753 return -1;
5754 break;
5755 }
5756
5757 return 0;
5758 }
5759
5760
5761 int
qemuBuildRNGBackendProps(virDomainRNGDef * rng,virJSONValue ** props)5762 qemuBuildRNGBackendProps(virDomainRNGDef *rng,
5763 virJSONValue **props)
5764 {
5765 g_autofree char *objAlias = NULL;
5766 g_autofree char *charBackendAlias = NULL;
5767
5768 objAlias = g_strdup_printf("obj%s", rng->info.alias);
5769
5770 switch ((virDomainRNGBackend) rng->backend) {
5771 case VIR_DOMAIN_RNG_BACKEND_RANDOM:
5772 if (qemuMonitorCreateObjectProps(props, "rng-random", objAlias,
5773 "s:filename", rng->source.file,
5774 NULL) < 0)
5775 return -1;
5776
5777 break;
5778
5779 case VIR_DOMAIN_RNG_BACKEND_EGD:
5780 if (!(charBackendAlias = qemuAliasChardevFromDevAlias(rng->info.alias)))
5781 return -1;
5782
5783 if (qemuMonitorCreateObjectProps(props, "rng-egd", objAlias,
5784 "s:chardev", charBackendAlias,
5785 NULL) < 0)
5786 return -1;
5787
5788 break;
5789
5790 case VIR_DOMAIN_RNG_BACKEND_BUILTIN:
5791 if (qemuMonitorCreateObjectProps(props, "rng-builtin", objAlias,
5792 NULL) < 0)
5793 return -1;
5794
5795 break;
5796
5797 case VIR_DOMAIN_RNG_BACKEND_LAST:
5798 break;
5799 }
5800
5801 return 0;
5802 }
5803
5804
5805 virJSONValue *
qemuBuildRNGDevProps(const virDomainDef * def,virDomainRNGDef * dev,virQEMUCaps * qemuCaps)5806 qemuBuildRNGDevProps(const virDomainDef *def,
5807 virDomainRNGDef *dev,
5808 virQEMUCaps *qemuCaps)
5809 {
5810 g_autoptr(virJSONValue) props = NULL;
5811 g_autofree char *rng = g_strdup_printf("obj%s", dev->info.alias);
5812 unsigned int period = 0;
5813
5814 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_RNG, dev, qemuCaps)))
5815 return NULL;
5816
5817 if (dev->rate > 0) {
5818 period = dev->period;
5819
5820 if (period == 0)
5821 period = 1000;
5822 }
5823
5824 if (virJSONValueObjectAdd(&props,
5825 "s:rng", rng,
5826 "s:id", dev->info.alias,
5827 "p:max-bytes", dev->rate,
5828 "p:period", period,
5829 NULL) < 0)
5830 return NULL;
5831
5832 if (qemuBuildDeviceAddressProps(props, def, &dev->info) < 0)
5833 return NULL;
5834
5835 return g_steal_pointer(&props);
5836 }
5837
5838
5839 static int
qemuBuildRNGCommandLine(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,virQEMUCaps * qemuCaps,bool chardevStdioLogd)5840 qemuBuildRNGCommandLine(virLogManager *logManager,
5841 virSecurityManager *secManager,
5842 virCommand *cmd,
5843 virQEMUDriverConfig *cfg,
5844 const virDomainDef *def,
5845 virQEMUCaps *qemuCaps,
5846 bool chardevStdioLogd)
5847 {
5848 size_t i;
5849
5850 for (i = 0; i < def->nrngs; i++) {
5851 g_autoptr(virJSONValue) props = NULL;
5852 virDomainRNGDef *rng = def->rngs[i];
5853 g_autofree char *chardev = NULL;
5854 g_autoptr(virJSONValue) devprops = NULL;
5855
5856 if (!rng->info.alias) {
5857 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5858 _("RNG device is missing alias"));
5859 return -1;
5860 }
5861
5862 /* possibly add character device for backend */
5863 if (qemuBuildRNGBackendChrdevStr(logManager, secManager, cmd, cfg, def,
5864 rng, qemuCaps, &chardev,
5865 chardevStdioLogd) < 0)
5866 return -1;
5867
5868 if (chardev)
5869 virCommandAddArgList(cmd, "-chardev", chardev, NULL);
5870
5871 if (qemuBuildRNGBackendProps(rng, &props) < 0)
5872 return -1;
5873
5874 if (qemuBuildObjectCommandlineFromJSON(cmd, props, qemuCaps) < 0)
5875 return -1;
5876
5877 /* add the device */
5878 if (qemuCommandAddExtDevice(cmd, &rng->info, qemuCaps) < 0)
5879 return -1;
5880
5881 if (!(devprops = qemuBuildRNGDevProps(def, rng, qemuCaps)))
5882 return -1;
5883
5884 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
5885 return -1;
5886 }
5887
5888 return 0;
5889 }
5890
5891
5892 static char *
qemuBuildSmbiosBiosStr(virSysinfoBIOSDef * def)5893 qemuBuildSmbiosBiosStr(virSysinfoBIOSDef *def)
5894 {
5895 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5896
5897 if (!def)
5898 return NULL;
5899
5900 virBufferAddLit(&buf, "type=0");
5901
5902 /* 0:Vendor */
5903 if (def->vendor) {
5904 virBufferAddLit(&buf, ",vendor=");
5905 virQEMUBuildBufferEscapeComma(&buf, def->vendor);
5906 }
5907 /* 0:BIOS Version */
5908 if (def->version) {
5909 virBufferAddLit(&buf, ",version=");
5910 virQEMUBuildBufferEscapeComma(&buf, def->version);
5911 }
5912 /* 0:BIOS Release Date */
5913 if (def->date) {
5914 virBufferAddLit(&buf, ",date=");
5915 virQEMUBuildBufferEscapeComma(&buf, def->date);
5916 }
5917 /* 0:System BIOS Major Release and 0:System BIOS Minor Release */
5918 if (def->release) {
5919 virBufferAddLit(&buf, ",release=");
5920 virQEMUBuildBufferEscapeComma(&buf, def->release);
5921 }
5922
5923 return virBufferContentAndReset(&buf);
5924 }
5925
5926
5927 static char *
qemuBuildSmbiosSystemStr(virSysinfoSystemDef * def,bool skip_uuid)5928 qemuBuildSmbiosSystemStr(virSysinfoSystemDef *def,
5929 bool skip_uuid)
5930 {
5931 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5932
5933 if (!def ||
5934 (!def->manufacturer && !def->product && !def->version &&
5935 !def->serial && (!def->uuid || skip_uuid) &&
5936 def->sku && !def->family))
5937 return NULL;
5938
5939 virBufferAddLit(&buf, "type=1");
5940
5941 /* 1:Manufacturer */
5942 if (def->manufacturer) {
5943 virBufferAddLit(&buf, ",manufacturer=");
5944 virQEMUBuildBufferEscapeComma(&buf, def->manufacturer);
5945 }
5946 /* 1:Product Name */
5947 if (def->product) {
5948 virBufferAddLit(&buf, ",product=");
5949 virQEMUBuildBufferEscapeComma(&buf, def->product);
5950 }
5951 /* 1:Version */
5952 if (def->version) {
5953 virBufferAddLit(&buf, ",version=");
5954 virQEMUBuildBufferEscapeComma(&buf, def->version);
5955 }
5956 /* 1:Serial Number */
5957 if (def->serial) {
5958 virBufferAddLit(&buf, ",serial=");
5959 virQEMUBuildBufferEscapeComma(&buf, def->serial);
5960 }
5961 /* 1:UUID */
5962 if (def->uuid && !skip_uuid) {
5963 virBufferAddLit(&buf, ",uuid=");
5964 virQEMUBuildBufferEscapeComma(&buf, def->uuid);
5965 }
5966 /* 1:SKU Number */
5967 if (def->sku) {
5968 virBufferAddLit(&buf, ",sku=");
5969 virQEMUBuildBufferEscapeComma(&buf, def->sku);
5970 }
5971 /* 1:Family */
5972 if (def->family) {
5973 virBufferAddLit(&buf, ",family=");
5974 virQEMUBuildBufferEscapeComma(&buf, def->family);
5975 }
5976
5977 return virBufferContentAndReset(&buf);
5978 }
5979
5980
5981 static char *
qemuBuildSmbiosBaseBoardStr(virSysinfoBaseBoardDef * def)5982 qemuBuildSmbiosBaseBoardStr(virSysinfoBaseBoardDef *def)
5983 {
5984 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5985
5986 if (!def)
5987 return NULL;
5988
5989 virBufferAddLit(&buf, "type=2");
5990
5991 /* 2:Manufacturer */
5992 virBufferAddLit(&buf, ",manufacturer=");
5993 virQEMUBuildBufferEscapeComma(&buf, def->manufacturer);
5994 /* 2:Product Name */
5995 if (def->product) {
5996 virBufferAddLit(&buf, ",product=");
5997 virQEMUBuildBufferEscapeComma(&buf, def->product);
5998 }
5999 /* 2:Version */
6000 if (def->version) {
6001 virBufferAddLit(&buf, ",version=");
6002 virQEMUBuildBufferEscapeComma(&buf, def->version);
6003 }
6004 /* 2:Serial Number */
6005 if (def->serial) {
6006 virBufferAddLit(&buf, ",serial=");
6007 virQEMUBuildBufferEscapeComma(&buf, def->serial);
6008 }
6009 /* 2:Asset Tag */
6010 if (def->asset) {
6011 virBufferAddLit(&buf, ",asset=");
6012 virQEMUBuildBufferEscapeComma(&buf, def->asset);
6013 }
6014 /* 2:Location */
6015 if (def->location) {
6016 virBufferAddLit(&buf, ",location=");
6017 virQEMUBuildBufferEscapeComma(&buf, def->location);
6018 }
6019
6020 return virBufferContentAndReset(&buf);
6021 }
6022
6023
6024 static char *
qemuBuildSmbiosOEMStringsStr(virSysinfoOEMStringsDef * def)6025 qemuBuildSmbiosOEMStringsStr(virSysinfoOEMStringsDef *def)
6026 {
6027 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6028 size_t i;
6029
6030 if (!def)
6031 return NULL;
6032
6033 virBufferAddLit(&buf, "type=11");
6034
6035 for (i = 0; i < def->nvalues; i++) {
6036 virBufferAddLit(&buf, ",value=");
6037 virQEMUBuildBufferEscapeComma(&buf, def->values[i]);
6038 }
6039
6040 return virBufferContentAndReset(&buf);
6041 }
6042
6043
6044 static char *
qemuBuildSmbiosChassisStr(virSysinfoChassisDef * def)6045 qemuBuildSmbiosChassisStr(virSysinfoChassisDef *def)
6046 {
6047 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6048
6049 if (!def)
6050 return NULL;
6051
6052 virBufferAddLit(&buf, "type=3");
6053
6054 /* 3:Manufacturer */
6055 virBufferAddLit(&buf, ",manufacturer=");
6056 virQEMUBuildBufferEscapeComma(&buf, def->manufacturer);
6057 /* 3:Version */
6058 if (def->version) {
6059 virBufferAddLit(&buf, ",version=");
6060 virQEMUBuildBufferEscapeComma(&buf, def->version);
6061 }
6062 /* 3:Serial Number */
6063 if (def->serial) {
6064 virBufferAddLit(&buf, ",serial=");
6065 virQEMUBuildBufferEscapeComma(&buf, def->serial);
6066 }
6067 /* 3:Asset Tag */
6068 if (def->asset) {
6069 virBufferAddLit(&buf, ",asset=");
6070 virQEMUBuildBufferEscapeComma(&buf, def->asset);
6071 }
6072 /* 3:Sku */
6073 if (def->sku) {
6074 virBufferAddLit(&buf, ",sku=");
6075 virQEMUBuildBufferEscapeComma(&buf, def->sku);
6076 }
6077
6078 return virBufferContentAndReset(&buf);
6079 }
6080
6081
6082 static int
qemuBuildSmbiosCommandLine(virCommand * cmd,virQEMUDriver * driver,const virDomainDef * def)6083 qemuBuildSmbiosCommandLine(virCommand *cmd,
6084 virQEMUDriver *driver,
6085 const virDomainDef *def)
6086 {
6087 size_t i;
6088 virSysinfoDef *source = NULL;
6089 bool skip_uuid = false;
6090
6091 if (def->os.smbios_mode == VIR_DOMAIN_SMBIOS_NONE ||
6092 def->os.smbios_mode == VIR_DOMAIN_SMBIOS_EMULATE)
6093 return 0;
6094
6095 /* should we really error out or just warn in those cases ? */
6096 if (def->os.smbios_mode == VIR_DOMAIN_SMBIOS_HOST) {
6097 if (driver->hostsysinfo == NULL) {
6098 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6099 _("Host SMBIOS information is not available"));
6100 return -1;
6101 }
6102 source = driver->hostsysinfo;
6103 /* Host and guest uuid must differ, by definition of UUID. */
6104 skip_uuid = true;
6105 } else if (def->os.smbios_mode == VIR_DOMAIN_SMBIOS_SYSINFO) {
6106 for (i = 0; i < def->nsysinfo; i++) {
6107 if (def->sysinfo[i]->type == VIR_SYSINFO_SMBIOS) {
6108 source = def->sysinfo[i];
6109 break;
6110 }
6111 }
6112
6113 if (!source) {
6114 virReportError(VIR_ERR_XML_ERROR,
6115 _("Domain '%s' sysinfo are not available"),
6116 def->name);
6117 return -1;
6118 }
6119 /* domain_conf guaranteed that system_uuid matches guest uuid. */
6120 }
6121 if (source != NULL) {
6122 char *smbioscmd;
6123
6124 smbioscmd = qemuBuildSmbiosBiosStr(source->bios);
6125 if (smbioscmd != NULL) {
6126 virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
6127 VIR_FREE(smbioscmd);
6128 }
6129 smbioscmd = qemuBuildSmbiosSystemStr(source->system, skip_uuid);
6130 if (smbioscmd != NULL) {
6131 virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
6132 VIR_FREE(smbioscmd);
6133 }
6134
6135 if (source->nbaseBoard > 1) {
6136 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6137 _("qemu does not support more than "
6138 "one entry to Type 2 in SMBIOS table"));
6139 return -1;
6140 }
6141
6142 for (i = 0; i < source->nbaseBoard; i++) {
6143 if (!(smbioscmd =
6144 qemuBuildSmbiosBaseBoardStr(source->baseBoard + i)))
6145 return -1;
6146
6147 virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
6148 VIR_FREE(smbioscmd);
6149 }
6150
6151 smbioscmd = qemuBuildSmbiosChassisStr(source->chassis);
6152 if (smbioscmd != NULL) {
6153 virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
6154 VIR_FREE(smbioscmd);
6155 }
6156
6157 if (source->oemStrings) {
6158 if (!(smbioscmd = qemuBuildSmbiosOEMStringsStr(source->oemStrings)))
6159 return -1;
6160
6161 virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
6162 VIR_FREE(smbioscmd);
6163 }
6164 }
6165
6166 return 0;
6167 }
6168
6169
6170 static int
qemuBuildSysinfoCommandLine(virCommand * cmd,const virDomainDef * def)6171 qemuBuildSysinfoCommandLine(virCommand *cmd,
6172 const virDomainDef *def)
6173 {
6174 size_t i;
6175
6176 /* We need to handle VIR_SYSINFO_FWCFG here, because
6177 * VIR_SYSINFO_SMBIOS is handled in qemuBuildSmbiosCommandLine() */
6178 for (i = 0; i < def->nsysinfo; i++) {
6179 size_t j;
6180
6181 if (def->sysinfo[i]->type != VIR_SYSINFO_FWCFG)
6182 continue;
6183
6184 for (j = 0; j < def->sysinfo[i]->nfw_cfgs; j++) {
6185 const virSysinfoFWCfgDef *f = &def->sysinfo[i]->fw_cfgs[j];
6186 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6187
6188 virBufferAsprintf(&buf, "name=%s", f->name);
6189
6190 if (f->value)
6191 virBufferEscapeString(&buf, ",string=%s", f->value);
6192 else
6193 virBufferEscapeString(&buf, ",file=%s", f->file);
6194
6195 virCommandAddArg(cmd, "-fw_cfg");
6196 virCommandAddArgBuffer(cmd, &buf);
6197 }
6198 }
6199
6200 return 0;
6201 }
6202
6203
6204 static int
qemuBuildVMGenIDCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)6205 qemuBuildVMGenIDCommandLine(virCommand *cmd,
6206 const virDomainDef *def,
6207 virQEMUCaps *qemuCaps)
6208 {
6209 g_autoptr(virJSONValue) props = NULL;
6210 char guid[VIR_UUID_STRING_BUFLEN];
6211
6212 if (!def->genidRequested)
6213 return 0;
6214
6215 virUUIDFormat(def->genid, guid);
6216
6217 if (virJSONValueObjectAdd(&props,
6218 "s:driver", "vmgenid",
6219 "s:guid", guid,
6220 "s:id", "vmgenid0",
6221 NULL) < 0)
6222 return -1;
6223
6224 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
6225 return -1;
6226
6227 return 0;
6228 }
6229
6230
6231 static char *
qemuBuildClockArgStr(virDomainClockDef * def)6232 qemuBuildClockArgStr(virDomainClockDef *def)
6233 {
6234 size_t i;
6235 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6236
6237 switch (def->offset) {
6238 case VIR_DOMAIN_CLOCK_OFFSET_UTC:
6239 virBufferAddLit(&buf, "base=utc");
6240 break;
6241
6242 case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
6243 case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
6244 virBufferAddLit(&buf, "base=localtime");
6245 break;
6246
6247 case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: {
6248 g_autoptr(GDateTime) now = g_date_time_new_now_utc();
6249 g_autoptr(GDateTime) then = NULL;
6250 g_autofree char *thenstr = NULL;
6251
6252 if (def->data.variable.basis == VIR_DOMAIN_CLOCK_BASIS_LOCALTIME) {
6253 long localOffset;
6254
6255 /* in the case of basis='localtime', rather than trying to
6256 * keep that basis (and associated offset from UTC) in the
6257 * status and deal with adding in the difference each time
6258 * there is an RTC_CHANGE event, it is simpler and less
6259 * error prone to just convert the adjustment an offset
6260 * from UTC right now (and change the status to
6261 * "basis='utc' to reflect this). This eliminates
6262 * potential errors in both RTC_CHANGE events and in
6263 * migration (in the case that the status of DST, or the
6264 * timezone of the destination host, changed relative to
6265 * startup).
6266 */
6267 if (virTimeLocalOffsetFromUTC(&localOffset) < 0)
6268 return NULL;
6269 def->data.variable.adjustment += localOffset;
6270 def->data.variable.basis = VIR_DOMAIN_CLOCK_BASIS_UTC;
6271 }
6272
6273 then = g_date_time_add_seconds(now, def->data.variable.adjustment);
6274 thenstr = g_date_time_format(then, "%Y-%m-%dT%H:%M:%S");
6275
6276 /* when an RTC_CHANGE event is received from qemu, we need to
6277 * have the adjustment used at domain start time available to
6278 * compute the new offset from UTC. As this new value is
6279 * itself stored in def->data.variable.adjustment, we need to
6280 * save a copy of it now.
6281 */
6282 def->data.variable.adjustment0 = def->data.variable.adjustment;
6283
6284 virBufferAsprintf(&buf, "base=%s", thenstr);
6285 } break;
6286
6287 default:
6288 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6289 _("unsupported clock offset '%s'"),
6290 virDomainClockOffsetTypeToString(def->offset));
6291 return NULL;
6292 }
6293
6294 /* Look for an 'rtc' timer element, and add in appropriate
6295 * clock= and driftfix= */
6296 for (i = 0; i < def->ntimers; i++) {
6297 if (def->timers[i]->name == VIR_DOMAIN_TIMER_NAME_RTC) {
6298 switch (def->timers[i]->track) {
6299 case -1: /* unspecified - use hypervisor default */
6300 break;
6301 case VIR_DOMAIN_TIMER_TRACK_BOOT:
6302 return NULL;
6303 case VIR_DOMAIN_TIMER_TRACK_GUEST:
6304 virBufferAddLit(&buf, ",clock=vm");
6305 break;
6306 case VIR_DOMAIN_TIMER_TRACK_WALL:
6307 virBufferAddLit(&buf, ",clock=host");
6308 break;
6309 case VIR_DOMAIN_TIMER_TRACK_REALTIME:
6310 virBufferAddLit(&buf, ",clock=rt");
6311 break;
6312 }
6313
6314 switch (def->timers[i]->tickpolicy) {
6315 case -1:
6316 case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
6317 /* This is the default - missed ticks delivered when
6318 next scheduled, at normal rate */
6319 break;
6320 case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
6321 /* deliver ticks at a faster rate until caught up */
6322 virBufferAddLit(&buf, ",driftfix=slew");
6323 break;
6324 case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
6325 case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
6326 return NULL;
6327 }
6328 break; /* no need to check other timers - there is only one rtc */
6329 }
6330 }
6331
6332 return virBufferContentAndReset(&buf);
6333 }
6334
6335
6336 /* NOTE: Building of commands can change def->clock->data.* values, so
6337 * virDomainDef is not const here.
6338 */
6339 static int
qemuBuildClockCommandLine(virCommand * cmd,virDomainDef * def,virQEMUCaps * qemuCaps)6340 qemuBuildClockCommandLine(virCommand *cmd,
6341 virDomainDef *def,
6342 virQEMUCaps *qemuCaps)
6343 {
6344 size_t i;
6345 g_autofree char *rtcopt = NULL;
6346
6347 virCommandAddArg(cmd, "-rtc");
6348 if (!(rtcopt = qemuBuildClockArgStr(&def->clock)))
6349 return -1;
6350 virCommandAddArg(cmd, rtcopt);
6351
6352 if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE &&
6353 def->clock.data.timezone) {
6354 virCommandAddEnvPair(cmd, "TZ", def->clock.data.timezone);
6355 }
6356
6357 for (i = 0; i < def->clock.ntimers; i++) {
6358 switch ((virDomainTimerNameType)def->clock.timers[i]->name) {
6359 case VIR_DOMAIN_TIMER_NAME_PLATFORM:
6360 /* qemuDomainDefValidateClockTimers will handle this
6361 * error condition */
6362 return -1;
6363
6364 case VIR_DOMAIN_TIMER_NAME_TSC:
6365 case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
6366 case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
6367 case VIR_DOMAIN_TIMER_NAME_ARMVTIMER:
6368 /* Timers above are handled when building -cpu. */
6369 case VIR_DOMAIN_TIMER_NAME_LAST:
6370 break;
6371
6372 case VIR_DOMAIN_TIMER_NAME_RTC:
6373 /* Already handled in qemuDomainDefValidateClockTimers */
6374 break;
6375
6376 case VIR_DOMAIN_TIMER_NAME_PIT:
6377 switch (def->clock.timers[i]->tickpolicy) {
6378 case -1:
6379 case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
6380 /* delay is the default if we don't have kernel
6381 (kvm-pit), otherwise, the default is catchup. */
6382 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY))
6383 virCommandAddArgList(cmd, "-global",
6384 "kvm-pit.lost_tick_policy=delay", NULL);
6385 break;
6386 case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
6387 /* Do nothing - qemuDomainDefValidateClockTimers handled
6388 * the possible error condition here. */
6389 break;
6390 case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
6391 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY))
6392 virCommandAddArgList(cmd, "-global",
6393 "kvm-pit.lost_tick_policy=discard", NULL);
6394 break;
6395 case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
6396 /* no way to support this mode for pit in qemu */
6397 return -1;
6398 }
6399 break;
6400
6401 case VIR_DOMAIN_TIMER_NAME_HPET:
6402 /* the only meaningful attribute for hpet is "present". If
6403 * present is -1, that means it wasn't specified, and
6404 * should be left at the default for the
6405 * hypervisor. "default" when -no-hpet exists is "yes",
6406 * and when -no-hpet doesn't exist is "no". "confusing"?
6407 * "yes"! */
6408
6409 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_HPET)) {
6410 if (def->clock.timers[i]->present == 0)
6411 virCommandAddArg(cmd, "-no-hpet");
6412 }
6413 break;
6414 }
6415 }
6416
6417 return 0;
6418 }
6419
6420
6421 static int
qemuBuildPMCommandLine(virCommand * cmd,const virDomainDef * def,qemuDomainObjPrivate * priv)6422 qemuBuildPMCommandLine(virCommand *cmd,
6423 const virDomainDef *def,
6424 qemuDomainObjPrivate *priv)
6425 {
6426 virQEMUCaps *qemuCaps = priv->qemuCaps;
6427
6428 if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SET_ACTION)) {
6429 /* with new qemu we always want '-no-shutdown' on startup and we set
6430 * all the other behaviour later during startup */
6431 virCommandAddArg(cmd, "-no-shutdown");
6432 } else {
6433 if (priv->allowReboot == VIR_TRISTATE_BOOL_NO)
6434 virCommandAddArg(cmd, "-no-reboot");
6435 else
6436 virCommandAddArg(cmd, "-no-shutdown");
6437 }
6438
6439 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_ACPI)) {
6440 if (def->features[VIR_DOMAIN_FEATURE_ACPI] != VIR_TRISTATE_SWITCH_ON)
6441 virCommandAddArg(cmd, "-no-acpi");
6442 }
6443
6444 /* We fall back to PIIX4_PM even for q35, since it's what we did
6445 pre-q35-pm support. QEMU starts up fine (with a warning) if
6446 mixing PIIX PM and -M q35. Starting to reject things here
6447 could mean we refuse to start existing configs in the wild.*/
6448 if (def->pm.s3) {
6449 const char *pm_object = "PIIX4_PM";
6450
6451 if (qemuDomainIsQ35(def) &&
6452 virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S3))
6453 pm_object = "ICH9-LPC";
6454
6455 virCommandAddArg(cmd, "-global");
6456 virCommandAddArgFormat(cmd, "%s.disable_s3=%d",
6457 pm_object, def->pm.s3 == VIR_TRISTATE_BOOL_NO);
6458 }
6459
6460 if (def->pm.s4) {
6461 const char *pm_object = "PIIX4_PM";
6462
6463 if (qemuDomainIsQ35(def) &&
6464 virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S4))
6465 pm_object = "ICH9-LPC";
6466
6467 virCommandAddArg(cmd, "-global");
6468 virCommandAddArgFormat(cmd, "%s.disable_s4=%d",
6469 pm_object, def->pm.s4 == VIR_TRISTATE_BOOL_NO);
6470 }
6471
6472 return 0;
6473 }
6474
6475
6476 static int
qemuBuildBootCommandLine(virCommand * cmd,const virDomainDef * def)6477 qemuBuildBootCommandLine(virCommand *cmd,
6478 const virDomainDef *def)
6479 {
6480 g_auto(virBuffer) boot_buf = VIR_BUFFER_INITIALIZER;
6481 g_autofree char *boot_opts_str = NULL;
6482
6483 if (def->os.bootmenu) {
6484 if (def->os.bootmenu == VIR_TRISTATE_BOOL_YES)
6485 virBufferAddLit(&boot_buf, "menu=on,");
6486 else
6487 virBufferAddLit(&boot_buf, "menu=off,");
6488 }
6489
6490 if (def->os.bios.rt_set) {
6491 virBufferAsprintf(&boot_buf,
6492 "reboot-timeout=%d,",
6493 def->os.bios.rt_delay);
6494 }
6495
6496 if (def->os.bm_timeout_set)
6497 virBufferAsprintf(&boot_buf, "splash-time=%u,", def->os.bm_timeout);
6498
6499 virBufferAddLit(&boot_buf, "strict=on");
6500
6501 boot_opts_str = virBufferContentAndReset(&boot_buf);
6502 if (boot_opts_str) {
6503 virCommandAddArg(cmd, "-boot");
6504 virCommandAddArg(cmd, boot_opts_str);
6505 }
6506
6507 if (def->os.kernel)
6508 virCommandAddArgList(cmd, "-kernel", def->os.kernel, NULL);
6509 if (def->os.initrd)
6510 virCommandAddArgList(cmd, "-initrd", def->os.initrd, NULL);
6511 if (def->os.cmdline)
6512 virCommandAddArgList(cmd, "-append", def->os.cmdline, NULL);
6513 if (def->os.dtb)
6514 virCommandAddArgList(cmd, "-dtb", def->os.dtb, NULL);
6515 if (def->os.slic_table) {
6516 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6517 virCommandAddArg(cmd, "-acpitable");
6518 virBufferAddLit(&buf, "sig=SLIC,file=");
6519 virQEMUBuildBufferEscapeComma(&buf, def->os.slic_table);
6520 virCommandAddArgBuffer(cmd, &buf);
6521 }
6522
6523 return 0;
6524 }
6525
6526
6527 static int
qemuBuildIOMMUCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)6528 qemuBuildIOMMUCommandLine(virCommand *cmd,
6529 const virDomainDef *def,
6530 virQEMUCaps *qemuCaps)
6531 {
6532 const virDomainIOMMUDef *iommu = def->iommu;
6533
6534 if (!iommu)
6535 return 0;
6536
6537 switch (iommu->model) {
6538 case VIR_DOMAIN_IOMMU_MODEL_INTEL: {
6539 g_autoptr(virJSONValue) props = NULL;
6540
6541 if (virJSONValueObjectAdd(&props,
6542 "s:driver", "intel-iommu",
6543 "S:intremap", qemuOnOffAuto(iommu->intremap),
6544 "T:caching-mode", iommu->caching_mode,
6545 "S:eim", qemuOnOffAuto(iommu->eim),
6546 "T:device-iotlb", iommu->iotlb,
6547 "z:aw-bits", iommu->aw_bits,
6548 NULL) < 0)
6549 return -1;
6550
6551 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
6552 return -1;
6553
6554 return 0;
6555 }
6556
6557 case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
6558 /* There is no -device for SMMUv3, so nothing to be done here */
6559 return 0;
6560
6561 case VIR_DOMAIN_IOMMU_MODEL_LAST:
6562 default:
6563 virReportEnumRangeError(virDomainIOMMUModel, iommu->model);
6564 return -1;
6565 }
6566
6567 return 0;
6568 }
6569
6570
6571 static int
qemuBuildGlobalControllerCommandLine(virCommand * cmd,const virDomainDef * def)6572 qemuBuildGlobalControllerCommandLine(virCommand *cmd,
6573 const virDomainDef *def)
6574 {
6575 size_t i;
6576
6577 for (i = 0; i < def->ncontrollers; i++) {
6578 virDomainControllerDef *cont = def->controllers[i];
6579 if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
6580 cont->opts.pciopts.pcihole64) {
6581 const char *hoststr = NULL;
6582
6583 switch (cont->model) {
6584 case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
6585 hoststr = "i440FX-pcihost";
6586 break;
6587
6588 case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
6589 hoststr = "q35-pcihost";
6590 break;
6591
6592 default:
6593 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6594 _("64-bit PCI hole setting is only for root"
6595 " PCI controllers"));
6596 return -1;
6597 }
6598
6599 virCommandAddArg(cmd, "-global");
6600 virCommandAddArgFormat(cmd, "%s.pci-hole64-size=%luK", hoststr,
6601 cont->opts.pciopts.pcihole64size);
6602 }
6603 }
6604
6605 return 0;
6606 }
6607
6608
6609 static int
qemuBuildCpuModelArgStr(virQEMUDriver * driver,const virDomainDef * def,virBuffer * buf,virQEMUCaps * qemuCaps)6610 qemuBuildCpuModelArgStr(virQEMUDriver *driver,
6611 const virDomainDef *def,
6612 virBuffer *buf,
6613 virQEMUCaps *qemuCaps)
6614 {
6615 size_t i;
6616 virCPUDef *cpu = def->cpu;
6617
6618 switch ((virCPUMode) cpu->mode) {
6619 case VIR_CPU_MODE_HOST_PASSTHROUGH:
6620 case VIR_CPU_MODE_MAXIMUM:
6621 if (cpu->mode == VIR_CPU_MODE_MAXIMUM)
6622 virBufferAddLit(buf, "max");
6623 else
6624 virBufferAddLit(buf, "host");
6625
6626 if (def->os.arch == VIR_ARCH_ARMV7L &&
6627 driver->hostarch == VIR_ARCH_AARCH64) {
6628 virBufferAddLit(buf, ",aarch64=off");
6629 }
6630
6631 if (cpu->migratable) {
6632 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_MIGRATABLE)) {
6633 virBufferAsprintf(buf, ",migratable=%s",
6634 virTristateSwitchTypeToString(cpu->migratable));
6635 }
6636 }
6637 break;
6638
6639 case VIR_CPU_MODE_HOST_MODEL:
6640 /* HOST_MODEL is a valid CPU mode for domain XMLs of all archs, meaning
6641 * that we can't move this validation to parse time. By the time we reach
6642 * this point, all non-PPC64 archs must have translated the CPU model to
6643 * something else and set the CPU mode to MODE_CUSTOM.
6644 */
6645 if (ARCH_IS_PPC64(def->os.arch)) {
6646 virBufferAddLit(buf, "host");
6647 if (cpu->model &&
6648 !(qemuDomainIsPSeries(def) &&
6649 virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_MAX_CPU_COMPAT))) {
6650 virBufferAsprintf(buf, ",compat=%s", cpu->model);
6651 }
6652 } else {
6653 virReportError(VIR_ERR_INTERNAL_ERROR,
6654 _("unexpected host-model CPU for %s architecture"),
6655 virArchToString(def->os.arch));
6656 return -1;
6657 }
6658 break;
6659
6660 case VIR_CPU_MODE_CUSTOM:
6661 virBufferAdd(buf, cpu->model, -1);
6662 break;
6663
6664 case VIR_CPU_MODE_LAST:
6665 break;
6666 }
6667
6668 if ((ARCH_IS_S390(def->os.arch) || ARCH_IS_ARM(def->os.arch)) &&
6669 cpu->features &&
6670 !virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION)) {
6671 virReportError(VIR_ERR_INTERNAL_ERROR,
6672 _("CPU features not supported by hypervisor for %s "
6673 "architecture"), virArchToString(def->os.arch));
6674 return -1;
6675 }
6676
6677 if (cpu->vendor_id)
6678 virBufferAsprintf(buf, ",vendor=%s", cpu->vendor_id);
6679
6680 for (i = 0; i < cpu->nfeatures; i++) {
6681 const char *featname =
6682 virQEMUCapsCPUFeatureToQEMU(qemuCaps, cpu->features[i].name);
6683 switch ((virCPUFeaturePolicy) cpu->features[i].policy) {
6684 case VIR_CPU_FEATURE_FORCE:
6685 case VIR_CPU_FEATURE_REQUIRE:
6686 virBufferAsprintf(buf, ",%s=on", featname);
6687 break;
6688
6689 case VIR_CPU_FEATURE_DISABLE:
6690 case VIR_CPU_FEATURE_FORBID:
6691 virBufferAsprintf(buf, ",%s=off", featname);
6692 break;
6693
6694 case VIR_CPU_FEATURE_OPTIONAL:
6695 case VIR_CPU_FEATURE_LAST:
6696 break;
6697 }
6698 }
6699
6700 return 0;
6701 }
6702
6703 static int
qemuBuildCpuCommandLine(virCommand * cmd,virQEMUDriver * driver,const virDomainDef * def,virQEMUCaps * qemuCaps)6704 qemuBuildCpuCommandLine(virCommand *cmd,
6705 virQEMUDriver *driver,
6706 const virDomainDef *def,
6707 virQEMUCaps *qemuCaps)
6708 {
6709 virArch hostarch = virArchFromHost();
6710 g_autofree char *cpu = NULL;
6711 g_autofree char *cpu_flags = NULL;
6712 g_auto(virBuffer) cpu_buf = VIR_BUFFER_INITIALIZER;
6713 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6714 size_t i;
6715
6716 if (def->cpu &&
6717 (def->cpu->mode != VIR_CPU_MODE_CUSTOM || def->cpu->model)) {
6718 if (qemuBuildCpuModelArgStr(driver, def, &cpu_buf, qemuCaps) < 0)
6719 return -1;
6720 } else {
6721 /*
6722 * Need to force a 32-bit guest CPU type if
6723 *
6724 * 1. guest OS is i686
6725 * 2. host OS is x86_64
6726 * 3. emulator is qemu-kvm or kvm
6727 *
6728 * Or
6729 *
6730 * 1. guest OS is i686
6731 * 2. emulator is qemu-system-x86_64
6732 */
6733 if (def->os.arch == VIR_ARCH_I686 &&
6734 ((hostarch == VIR_ARCH_X86_64 &&
6735 strstr(def->emulator, "kvm")) ||
6736 strstr(def->emulator, "x86_64"))) {
6737 virBufferAddLit(&cpu_buf, "qemu32");
6738 }
6739 }
6740
6741 /* Handle paravirtual timers */
6742 for (i = 0; i < def->clock.ntimers; i++) {
6743 virDomainTimerDef *timer = def->clock.timers[i];
6744
6745 switch ((virDomainTimerNameType)timer->name) {
6746 case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
6747 if (timer->present != -1) {
6748 virBufferAsprintf(&buf, ",kvmclock=%s",
6749 timer->present ? "on" : "off");
6750 }
6751 break;
6752 case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
6753 if (timer->present == 1)
6754 virBufferAddLit(&buf, ",hv-time=on");
6755 break;
6756 case VIR_DOMAIN_TIMER_NAME_TSC:
6757 if (timer->frequency > 0)
6758 virBufferAsprintf(&buf, ",tsc-frequency=%llu", timer->frequency);
6759 break;
6760 case VIR_DOMAIN_TIMER_NAME_ARMVTIMER:
6761 switch (timer->tickpolicy) {
6762 case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
6763 virBufferAddLit(&buf, ",kvm-no-adjvtime=off");
6764 break;
6765 case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
6766 virBufferAddLit(&buf, ",kvm-no-adjvtime=on");
6767 break;
6768 case -1:
6769 case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
6770 case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
6771 break;
6772 }
6773 break;
6774 case VIR_DOMAIN_TIMER_NAME_PLATFORM:
6775 case VIR_DOMAIN_TIMER_NAME_PIT:
6776 case VIR_DOMAIN_TIMER_NAME_RTC:
6777 case VIR_DOMAIN_TIMER_NAME_HPET:
6778 break;
6779 case VIR_DOMAIN_TIMER_NAME_LAST:
6780 default:
6781 virReportEnumRangeError(virDomainTimerNameType, timer->name);
6782 return -1;
6783 }
6784 }
6785
6786 if (def->apic_eoi) {
6787 virBufferAsprintf(&buf, ",kvm-pv-eoi=%s", def->apic_eoi ==
6788 VIR_TRISTATE_SWITCH_ON ? "on" : "off");
6789 }
6790
6791 if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK]) {
6792 virBufferAsprintf(&buf, ",kvm-pv-unhalt=%s",
6793 def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] ==
6794 VIR_TRISTATE_SWITCH_ON ? "on" : "off");
6795 }
6796
6797 if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_TRISTATE_SWITCH_ON) {
6798 for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
6799 switch ((virDomainHyperv) i) {
6800 case VIR_DOMAIN_HYPERV_RELAXED:
6801 case VIR_DOMAIN_HYPERV_VAPIC:
6802 case VIR_DOMAIN_HYPERV_VPINDEX:
6803 case VIR_DOMAIN_HYPERV_RUNTIME:
6804 case VIR_DOMAIN_HYPERV_SYNIC:
6805 case VIR_DOMAIN_HYPERV_STIMER:
6806 case VIR_DOMAIN_HYPERV_RESET:
6807 case VIR_DOMAIN_HYPERV_FREQUENCIES:
6808 case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
6809 case VIR_DOMAIN_HYPERV_TLBFLUSH:
6810 case VIR_DOMAIN_HYPERV_IPI:
6811 case VIR_DOMAIN_HYPERV_EVMCS:
6812 if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON)
6813 virBufferAsprintf(&buf, ",hv-%s=on",
6814 virDomainHypervTypeToString(i));
6815 if ((i == VIR_DOMAIN_HYPERV_STIMER) &&
6816 (def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON))
6817 virBufferAsprintf(&buf, ",%s=on", VIR_CPU_x86_HV_STIMER_DIRECT);
6818 break;
6819
6820 case VIR_DOMAIN_HYPERV_SPINLOCKS:
6821 if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON)
6822 virBufferAsprintf(&buf, ",%s=0x%x",
6823 VIR_CPU_x86_HV_SPINLOCKS,
6824 def->hyperv_spinlocks);
6825 break;
6826
6827 case VIR_DOMAIN_HYPERV_VENDOR_ID:
6828 if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON)
6829 virBufferAsprintf(&buf, ",hv-vendor-id=%s",
6830 def->hyperv_vendor_id);
6831 break;
6832
6833 case VIR_DOMAIN_HYPERV_LAST:
6834 break;
6835 }
6836 }
6837 }
6838
6839 for (i = 0; i < def->npanics; i++) {
6840 if (def->panics[i]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) {
6841 virBufferAddLit(&buf, ",hv-crash");
6842 break;
6843 }
6844 }
6845
6846 if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
6847 for (i = 0; i < VIR_DOMAIN_KVM_LAST; i++) {
6848 switch ((virDomainKVM) i) {
6849 case VIR_DOMAIN_KVM_HIDDEN:
6850 if (def->kvm_features[i] == VIR_TRISTATE_SWITCH_ON)
6851 virBufferAddLit(&buf, ",kvm=off");
6852 break;
6853
6854 case VIR_DOMAIN_KVM_DEDICATED:
6855 if (def->kvm_features[i] == VIR_TRISTATE_SWITCH_ON)
6856 virBufferAddLit(&buf, ",kvm-hint-dedicated=on");
6857 break;
6858
6859 case VIR_DOMAIN_KVM_POLLCONTROL:
6860 if (def->kvm_features[i] == VIR_TRISTATE_SWITCH_ON)
6861 virBufferAddLit(&buf, ",kvm-poll-control=on");
6862 break;
6863
6864 case VIR_DOMAIN_KVM_PVIPI:
6865 if (def->kvm_features[i] == VIR_TRISTATE_SWITCH_OFF)
6866 virBufferAddLit(&buf, ",kvm-pv-ipi=off");
6867 break;
6868
6869 case VIR_DOMAIN_KVM_LAST:
6870 break;
6871 }
6872 }
6873 }
6874
6875 /* ppc64 guests always have PMU enabled, but the 'pmu' option
6876 * is not supported. */
6877 if (def->features[VIR_DOMAIN_FEATURE_PMU] && !ARCH_IS_PPC64(def->os.arch)) {
6878 virTristateSwitch pmu = def->features[VIR_DOMAIN_FEATURE_PMU];
6879 virBufferAsprintf(&buf, ",pmu=%s",
6880 virTristateSwitchTypeToString(pmu));
6881 }
6882
6883 if (def->cpu && def->cpu->cache) {
6884 virCPUCacheDef *cache = def->cpu->cache;
6885 bool hostOff = false;
6886 bool l3Off = false;
6887
6888 switch (cache->mode) {
6889 case VIR_CPU_CACHE_MODE_EMULATE:
6890 virBufferAddLit(&buf, ",l3-cache=on");
6891 hostOff = true;
6892 break;
6893
6894 case VIR_CPU_CACHE_MODE_PASSTHROUGH:
6895 virBufferAddLit(&buf, ",host-cache-info=on");
6896 l3Off = true;
6897 break;
6898
6899 case VIR_CPU_CACHE_MODE_DISABLE:
6900 hostOff = l3Off = true;
6901 break;
6902
6903 case VIR_CPU_CACHE_MODE_LAST:
6904 break;
6905 }
6906
6907 if (hostOff &&
6908 (def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH ||
6909 def->cpu->mode == VIR_CPU_MODE_MAXIMUM) &&
6910 virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_CACHE))
6911 virBufferAddLit(&buf, ",host-cache-info=off");
6912
6913 if (l3Off &&
6914 virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_CACHE))
6915 virBufferAddLit(&buf, ",l3-cache=off");
6916 }
6917
6918 cpu = virBufferContentAndReset(&cpu_buf);
6919 cpu_flags = virBufferContentAndReset(&buf);
6920
6921 if (cpu_flags && !cpu) {
6922 const char *default_model;
6923
6924 switch ((int)def->os.arch) {
6925 case VIR_ARCH_I686:
6926 default_model = "qemu32";
6927 break;
6928 case VIR_ARCH_X86_64:
6929 default_model = "qemu64";
6930 break;
6931 default:
6932 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6933 _("CPU flags requested but can't determine "
6934 "default CPU for arch %s"),
6935 virArchToString(def->os.arch));
6936 return -1;
6937 }
6938
6939 cpu = g_strdup(default_model);
6940 }
6941
6942 if (cpu) {
6943 virCommandAddArg(cmd, "-cpu");
6944 virCommandAddArgFormat(cmd, "%s%s", cpu, NULLSTR_EMPTY(cpu_flags));
6945 }
6946
6947 return 0;
6948 }
6949
6950
6951 static bool
qemuAppendKeyWrapMachineParm(virBuffer * buf,virQEMUCaps * qemuCaps,virQEMUCapsFlags flag,const char * pname,virTristateSwitch pstate)6952 qemuAppendKeyWrapMachineParm(virBuffer *buf, virQEMUCaps *qemuCaps,
6953 virQEMUCapsFlags flag, const char *pname,
6954 virTristateSwitch pstate)
6955 {
6956 if (pstate != VIR_TRISTATE_SWITCH_ABSENT) {
6957 if (!virQEMUCapsGet(qemuCaps, flag)) {
6958 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6959 _("%s is not available with this QEMU binary"), pname);
6960 return false;
6961 }
6962
6963 virBufferAsprintf(buf, ",%s=%s", pname,
6964 virTristateSwitchTypeToString(pstate));
6965 }
6966
6967 return true;
6968 }
6969
6970 static bool
qemuAppendKeyWrapMachineParms(virBuffer * buf,virQEMUCaps * qemuCaps,const virDomainKeyWrapDef * keywrap)6971 qemuAppendKeyWrapMachineParms(virBuffer *buf, virQEMUCaps *qemuCaps,
6972 const virDomainKeyWrapDef *keywrap)
6973 {
6974 if (!qemuAppendKeyWrapMachineParm(buf, qemuCaps, QEMU_CAPS_AES_KEY_WRAP,
6975 "aes-key-wrap", keywrap->aes))
6976 return false;
6977
6978 if (!qemuAppendKeyWrapMachineParm(buf, qemuCaps, QEMU_CAPS_DEA_KEY_WRAP,
6979 "dea-key-wrap", keywrap->dea))
6980 return false;
6981
6982 return true;
6983 }
6984
6985
6986 static void
qemuAppendLoadparmMachineParm(virBuffer * buf,const virDomainDef * def)6987 qemuAppendLoadparmMachineParm(virBuffer *buf,
6988 const virDomainDef *def)
6989 {
6990 size_t i = 0;
6991
6992 for (i = 0; i < def->ndisks; i++) {
6993 virDomainDiskDef *disk = def->disks[i];
6994
6995 if (disk->info.bootIndex == 1 && disk->info.loadparm) {
6996 virBufferAsprintf(buf, ",loadparm=%s", disk->info.loadparm);
6997 return;
6998 }
6999 }
7000
7001 /* Network boot device */
7002 for (i = 0; i < def->nnets; i++) {
7003 virDomainNetDef *net = def->nets[i];
7004
7005 if (net->info.bootIndex == 1 && net->info.loadparm) {
7006 virBufferAsprintf(buf, ",loadparm=%s", net->info.loadparm);
7007 return;
7008 }
7009 }
7010 }
7011
7012
7013 static int
qemuBuildNameCommandLine(virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def)7014 qemuBuildNameCommandLine(virCommand *cmd,
7015 virQEMUDriverConfig *cfg,
7016 const virDomainDef *def)
7017 {
7018 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7019
7020 virCommandAddArg(cmd, "-name");
7021
7022 /* The 'guest' option let's us handle a name with '=' embedded in it */
7023 virBufferAddLit(&buf, "guest=");
7024 virQEMUBuildBufferEscapeComma(&buf, def->name);
7025
7026 if (cfg->setProcessName)
7027 virBufferAsprintf(&buf, ",process=qemu:%s", def->name);
7028
7029 virBufferAddLit(&buf, ",debug-threads=on");
7030
7031 virCommandAddArgBuffer(cmd, &buf);
7032
7033 return 0;
7034 }
7035
7036 static int
qemuBuildMachineCommandLine(virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,virQEMUCaps * qemuCaps,qemuDomainObjPrivate * priv)7037 qemuBuildMachineCommandLine(virCommand *cmd,
7038 virQEMUDriverConfig *cfg,
7039 const virDomainDef *def,
7040 virQEMUCaps *qemuCaps,
7041 qemuDomainObjPrivate *priv)
7042 {
7043 virTristateSwitch vmport = def->features[VIR_DOMAIN_FEATURE_VMPORT];
7044 virTristateSwitch smm = def->features[VIR_DOMAIN_FEATURE_SMM];
7045 virCPUDef *cpu = def->cpu;
7046 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7047 size_t i;
7048
7049 virCommandAddArg(cmd, "-machine");
7050 virBufferAdd(&buf, def->os.machine, -1);
7051
7052 /* To avoid the collision of creating USB controllers when calling
7053 * machine->init in QEMU, it needs to set usb=off
7054 */
7055 virBufferAddLit(&buf, ",usb=off");
7056
7057 if (vmport != VIR_TRISTATE_SWITCH_ABSENT)
7058 virBufferAsprintf(&buf, ",vmport=%s",
7059 virTristateSwitchTypeToString(vmport));
7060
7061 if (smm)
7062 virBufferAsprintf(&buf, ",smm=%s", virTristateSwitchTypeToString(smm));
7063
7064 if (def->mem.dump_core) {
7065 virBufferAsprintf(&buf, ",dump-guest-core=%s",
7066 virTristateSwitchTypeToString(def->mem.dump_core));
7067 } else {
7068 virBufferAsprintf(&buf, ",dump-guest-core=%s",
7069 cfg->dumpGuestCore ? "on" : "off");
7070 }
7071
7072 if (def->mem.nosharepages)
7073 virBufferAddLit(&buf, ",mem-merge=off");
7074
7075 if (def->keywrap &&
7076 !qemuAppendKeyWrapMachineParms(&buf, qemuCaps, def->keywrap))
7077 return -1;
7078
7079 if (def->features[VIR_DOMAIN_FEATURE_GIC] == VIR_TRISTATE_SWITCH_ON) {
7080 bool hasGICVersionOption = virQEMUCapsGet(qemuCaps,
7081 QEMU_CAPS_MACH_VIRT_GIC_VERSION);
7082
7083 switch ((virGICVersion) def->gic_version) {
7084 case VIR_GIC_VERSION_2:
7085 if (!hasGICVersionOption) {
7086 /* If the gic-version option is not available, we can't
7087 * configure the GIC; however, we know that before the
7088 * option was introduced the guests would always get a
7089 * GICv2, so in order to maintain compatibility with
7090 * those old QEMU versions all we need to do is stop
7091 * early instead of erroring out */
7092 break;
7093 }
7094 G_GNUC_FALLTHROUGH;
7095
7096 case VIR_GIC_VERSION_3:
7097 case VIR_GIC_VERSION_HOST:
7098 if (!hasGICVersionOption) {
7099 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7100 _("gic-version option is not available "
7101 "with this QEMU binary"));
7102 return -1;
7103 }
7104
7105 virBufferAsprintf(&buf, ",gic-version=%s",
7106 virGICVersionTypeToString(def->gic_version));
7107 break;
7108
7109 case VIR_GIC_VERSION_NONE:
7110 case VIR_GIC_VERSION_LAST:
7111 default:
7112 break;
7113 }
7114 }
7115
7116 if (def->iommu) {
7117 switch (def->iommu->model) {
7118 case VIR_DOMAIN_IOMMU_MODEL_INTEL:
7119 /* The 'intel' IOMMu is formatted in qemuBuildIOMMUCommandLine */
7120 break;
7121
7122 case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
7123 virBufferAddLit(&buf, ",iommu=smmuv3");
7124 break;
7125
7126 case VIR_DOMAIN_IOMMU_MODEL_LAST:
7127 default:
7128 virReportEnumRangeError(virDomainIOMMUModel, def->iommu->model);
7129 return -1;
7130 }
7131 }
7132
7133 for (i = 0; i < def->nmems; i++) {
7134 if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM) {
7135 virBufferAddLit(&buf, ",nvdimm=on");
7136 break;
7137 }
7138 }
7139
7140 if (def->features[VIR_DOMAIN_FEATURE_IOAPIC] != VIR_DOMAIN_IOAPIC_NONE) {
7141 switch ((virDomainIOAPIC) def->features[VIR_DOMAIN_FEATURE_IOAPIC]) {
7142 case VIR_DOMAIN_IOAPIC_QEMU:
7143 virBufferAddLit(&buf, ",kernel_irqchip=split");
7144 break;
7145 case VIR_DOMAIN_IOAPIC_KVM:
7146 virBufferAddLit(&buf, ",kernel_irqchip=on");
7147 break;
7148 case VIR_DOMAIN_IOAPIC_NONE:
7149 case VIR_DOMAIN_IOAPIC_LAST:
7150 break;
7151 }
7152 }
7153
7154 if (def->features[VIR_DOMAIN_FEATURE_HPT] == VIR_TRISTATE_SWITCH_ON) {
7155
7156 if (def->hpt_resizing != VIR_DOMAIN_HPT_RESIZING_NONE) {
7157 virBufferAsprintf(&buf, ",resize-hpt=%s",
7158 virDomainHPTResizingTypeToString(def->hpt_resizing));
7159 }
7160
7161 if (def->hpt_maxpagesize > 0) {
7162 virBufferAsprintf(&buf, ",cap-hpt-max-page-size=%lluk",
7163 def->hpt_maxpagesize);
7164 }
7165 }
7166
7167 if (def->features[VIR_DOMAIN_FEATURE_HTM] != VIR_TRISTATE_SWITCH_ABSENT) {
7168 const char *str;
7169 str = virTristateSwitchTypeToString(def->features[VIR_DOMAIN_FEATURE_HTM]);
7170 virBufferAsprintf(&buf, ",cap-htm=%s", str);
7171 }
7172
7173 if (def->features[VIR_DOMAIN_FEATURE_NESTED_HV] != VIR_TRISTATE_SWITCH_ABSENT) {
7174 const char *str;
7175 str = virTristateSwitchTypeToString(def->features[VIR_DOMAIN_FEATURE_NESTED_HV]);
7176 virBufferAsprintf(&buf, ",cap-nested-hv=%s", str);
7177 }
7178
7179 if (def->features[VIR_DOMAIN_FEATURE_CCF_ASSIST] != VIR_TRISTATE_SWITCH_ABSENT) {
7180 const char *str;
7181 str = virTristateSwitchTypeToString(def->features[VIR_DOMAIN_FEATURE_CCF_ASSIST]);
7182 virBufferAsprintf(&buf, ",cap-ccf-assist=%s", str);
7183 }
7184
7185 if (def->features[VIR_DOMAIN_FEATURE_CFPC] != VIR_DOMAIN_CFPC_NONE) {
7186 const char *str = virDomainCFPCTypeToString(def->features[VIR_DOMAIN_FEATURE_CFPC]);
7187 virBufferAsprintf(&buf, ",cap-cfpc=%s", str);
7188 }
7189
7190 if (def->features[VIR_DOMAIN_FEATURE_SBBC] != VIR_DOMAIN_SBBC_NONE) {
7191 const char *str = virDomainSBBCTypeToString(def->features[VIR_DOMAIN_FEATURE_SBBC]);
7192 virBufferAsprintf(&buf, ",cap-sbbc=%s", str);
7193 }
7194
7195 if (def->features[VIR_DOMAIN_FEATURE_IBS] != VIR_DOMAIN_IBS_NONE) {
7196 const char *str = virDomainIBSTypeToString(def->features[VIR_DOMAIN_FEATURE_IBS]);
7197 virBufferAsprintf(&buf, ",cap-ibs=%s", str);
7198 }
7199
7200 if (cpu && cpu->model &&
7201 cpu->mode == VIR_CPU_MODE_HOST_MODEL &&
7202 qemuDomainIsPSeries(def) &&
7203 virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_MAX_CPU_COMPAT)) {
7204 virBufferAsprintf(&buf, ",max-cpu-compat=%s", cpu->model);
7205 }
7206
7207 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
7208 qemuAppendLoadparmMachineParm(&buf, def);
7209
7210 if (def->sec) {
7211 switch ((virDomainLaunchSecurity) def->sec->sectype) {
7212 case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
7213 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_CONFIDENTAL_GUEST_SUPPORT)) {
7214 virBufferAddLit(&buf, ",confidential-guest-support=lsec0");
7215 } else {
7216 virBufferAddLit(&buf, ",memory-encryption=lsec0");
7217 }
7218 break;
7219 case VIR_DOMAIN_LAUNCH_SECURITY_PV:
7220 virBufferAddLit(&buf, ",confidential-guest-support=lsec0");
7221 break;
7222 case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
7223 case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
7224 virReportEnumRangeError(virDomainLaunchSecurity, def->sec->sectype);
7225 return -1;
7226 }
7227 }
7228
7229 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) {
7230 if (priv->pflash0)
7231 virBufferAsprintf(&buf, ",pflash0=%s", priv->pflash0->nodeformat);
7232 if (priv->pflash1)
7233 virBufferAsprintf(&buf, ",pflash1=%s", priv->pflash1->nodeformat);
7234 }
7235
7236 if (virDomainNumaHasHMAT(def->numa))
7237 virBufferAddLit(&buf, ",hmat=on");
7238
7239 if (!virDomainNumaGetNodeCount(def->numa)) {
7240 const char *defaultRAMid = NULL;
7241
7242 /* QEMU is obsoleting -mem-path and -mem-prealloc. That means we have
7243 * to switch to memory-backend-* even for regular RAM and to keep
7244 * domain migratable we have to set the same ID as older QEMUs would.
7245 * If domain has no NUMA nodes and QEMU is new enough to expose ID of
7246 * the default RAM we want to use it for default RAM (construct
7247 * memory-backend-* with corresponding attributes instead of obsolete
7248 * -mem-path and -mem-prealloc).
7249 * This generates only reference for the memory-backend-* object added
7250 * later in qemuBuildMemCommandLine() */
7251 defaultRAMid = virQEMUCapsGetMachineDefaultRAMid(qemuCaps,
7252 def->virtType,
7253 def->os.machine);
7254 if (defaultRAMid)
7255 virBufferAsprintf(&buf, ",memory-backend=%s", defaultRAMid);
7256 }
7257
7258 /* On x86 targets, graphics=off activates the serial console
7259 * output mode in the firmware. On non-x86 targets it has
7260 * various other undesirable effects that we certainly do
7261 * not want to have. We rely on the validation code to have
7262 * blocked useserial=yes on non-x86
7263 */
7264 if (def->os.bios.useserial == VIR_TRISTATE_BOOL_YES) {
7265 virBufferAddLit(&buf, ",graphics=off");
7266 }
7267
7268 virCommandAddArgBuffer(cmd, &buf);
7269
7270 return 0;
7271 }
7272
7273
7274 static void
qemuBuildAccelCommandLine(virCommand * cmd,const virDomainDef * def)7275 qemuBuildAccelCommandLine(virCommand *cmd,
7276 const virDomainDef *def)
7277 {
7278 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7279
7280 virCommandAddArg(cmd, "-accel");
7281
7282 switch ((virDomainVirtType)def->virtType) {
7283 case VIR_DOMAIN_VIRT_QEMU:
7284 virBufferAddLit(&buf, "tcg");
7285 break;
7286
7287 case VIR_DOMAIN_VIRT_KVM:
7288 virBufferAddLit(&buf, "kvm");
7289 break;
7290
7291 case VIR_DOMAIN_VIRT_NVMM:
7292 virBufferAddLit(&buf, ",accel=nvmm");
7293 break;
7294
7295 case VIR_DOMAIN_VIRT_KQEMU:
7296 case VIR_DOMAIN_VIRT_XEN:
7297 case VIR_DOMAIN_VIRT_LXC:
7298 case VIR_DOMAIN_VIRT_UML:
7299 case VIR_DOMAIN_VIRT_OPENVZ:
7300 case VIR_DOMAIN_VIRT_TEST:
7301 case VIR_DOMAIN_VIRT_VMWARE:
7302 case VIR_DOMAIN_VIRT_HYPERV:
7303 case VIR_DOMAIN_VIRT_VBOX:
7304 case VIR_DOMAIN_VIRT_PHYP:
7305 case VIR_DOMAIN_VIRT_PARALLELS:
7306 case VIR_DOMAIN_VIRT_BHYVE:
7307 case VIR_DOMAIN_VIRT_VZ:
7308 case VIR_DOMAIN_VIRT_NONE:
7309 case VIR_DOMAIN_VIRT_LAST:
7310 break;
7311 }
7312
7313 virCommandAddArgBuffer(cmd, &buf);
7314 }
7315
7316
7317 static void
qemuBuildTSEGCommandLine(virCommand * cmd,const virDomainDef * def)7318 qemuBuildTSEGCommandLine(virCommand *cmd,
7319 const virDomainDef *def)
7320 {
7321 if (!def->tseg_specified)
7322 return;
7323
7324 virCommandAddArg(cmd, "-global");
7325
7326 /* PostParse callback guarantees that the size is divisible by 1 MiB */
7327 virCommandAddArgFormat(cmd, "mch.extended-tseg-mbytes=%llu",
7328 def->tseg_size >> 20);
7329 }
7330
7331
7332 static int
qemuBuildSmpCommandLine(virCommand * cmd,virDomainDef * def,virQEMUCaps * qemuCaps)7333 qemuBuildSmpCommandLine(virCommand *cmd,
7334 virDomainDef *def,
7335 virQEMUCaps *qemuCaps)
7336 {
7337 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7338 unsigned int maxvcpus = virDomainDefGetVcpusMax(def);
7339 unsigned int nvcpus = 0;
7340 virDomainVcpuDef *vcpu;
7341 size_t i;
7342
7343 /* count non-hotpluggable enabled vcpus. Hotpluggable ones will be added
7344 * in a different way */
7345 for (i = 0; i < maxvcpus; i++) {
7346 vcpu = virDomainDefGetVcpu(def, i);
7347 if (vcpu->online && vcpu->hotpluggable == VIR_TRISTATE_BOOL_NO)
7348 nvcpus++;
7349 }
7350
7351 virCommandAddArg(cmd, "-smp");
7352
7353 virBufferAsprintf(&buf, "%u", nvcpus);
7354
7355 if (nvcpus != maxvcpus)
7356 virBufferAsprintf(&buf, ",maxcpus=%u", maxvcpus);
7357 /* sockets, cores, and threads are either all zero
7358 * or all non-zero, thus checking one of them is enough */
7359 if (def->cpu && def->cpu->sockets) {
7360 if (def->cpu->dies != 1 && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SMP_DIES)) {
7361 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7362 _("Only 1 die per socket is supported"));
7363 return -1;
7364 }
7365 virBufferAsprintf(&buf, ",sockets=%u", def->cpu->sockets);
7366 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SMP_DIES))
7367 virBufferAsprintf(&buf, ",dies=%u", def->cpu->dies);
7368 virBufferAsprintf(&buf, ",cores=%u", def->cpu->cores);
7369 virBufferAsprintf(&buf, ",threads=%u", def->cpu->threads);
7370 } else {
7371 virBufferAsprintf(&buf, ",sockets=%u", virDomainDefGetVcpusMax(def));
7372 virBufferAsprintf(&buf, ",cores=%u", 1);
7373 virBufferAsprintf(&buf, ",threads=%u", 1);
7374 }
7375
7376 virCommandAddArgBuffer(cmd, &buf);
7377 return 0;
7378 }
7379
7380
7381 static int
qemuBuildMemPathStr(const virDomainDef * def,virCommand * cmd,qemuDomainObjPrivate * priv)7382 qemuBuildMemPathStr(const virDomainDef *def,
7383 virCommand *cmd,
7384 qemuDomainObjPrivate *priv)
7385 {
7386 g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver);
7387 const long system_page_size = virGetSystemPageSizeKB();
7388 g_autofree char *mem_path = NULL;
7389 bool prealloc = false;
7390
7391 /* There are two cases where we want to put -mem-path onto
7392 * the command line: First one is when there are no guest
7393 * NUMA nodes and hugepages are configured. The second one is
7394 * if user requested file allocation. */
7395 if (def->mem.nhugepages &&
7396 def->mem.hugepages[0].size != system_page_size) {
7397 unsigned long long pagesize = def->mem.hugepages[0].size;
7398 if (!pagesize &&
7399 qemuBuildMemoryGetDefaultPagesize(cfg, &pagesize) < 0)
7400 return -1;
7401 if (qemuGetDomainHupageMemPath(priv->driver, def, pagesize, &mem_path) < 0)
7402 return -1;
7403 prealloc = true;
7404 } else if (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) {
7405 if (qemuGetMemoryBackingPath(priv->driver, def, "ram", &mem_path) < 0)
7406 return -1;
7407 }
7408
7409 if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE)
7410 prealloc = true;
7411
7412 if (prealloc && !priv->memPrealloc) {
7413 virCommandAddArgList(cmd, "-mem-prealloc", NULL);
7414 priv->memPrealloc = true;
7415 }
7416
7417 if (mem_path)
7418 virCommandAddArgList(cmd, "-mem-path", mem_path, NULL);
7419
7420 return 0;
7421 }
7422
7423
7424 static int
qemuBuildMemCommandLineMemoryDefaultBackend(virCommand * cmd,const virDomainDef * def,qemuDomainObjPrivate * priv,const char * defaultRAMid)7425 qemuBuildMemCommandLineMemoryDefaultBackend(virCommand *cmd,
7426 const virDomainDef *def,
7427 qemuDomainObjPrivate *priv,
7428 const char *defaultRAMid)
7429 {
7430 g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver);
7431 g_autoptr(virJSONValue) props = NULL;
7432 virDomainMemoryDef mem = { 0 };
7433
7434 mem.size = virDomainDefGetMemoryInitial(def);
7435 mem.targetNode = -1;
7436 mem.info.alias = (char *) defaultRAMid;
7437
7438 if (qemuBuildMemoryBackendProps(&props, defaultRAMid, cfg,
7439 priv, def, &mem, false, true) < 0)
7440 return -1;
7441
7442 if (qemuBuildObjectCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0)
7443 return -1;
7444
7445 return 0;
7446 }
7447
7448
7449 static int
qemuBuildMemCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps,qemuDomainObjPrivate * priv)7450 qemuBuildMemCommandLine(virCommand *cmd,
7451 const virDomainDef *def,
7452 virQEMUCaps *qemuCaps,
7453 qemuDomainObjPrivate *priv)
7454 {
7455 const char *defaultRAMid = NULL;
7456
7457 virCommandAddArg(cmd, "-m");
7458
7459 if (virDomainDefHasMemoryHotplug(def)) {
7460 /* Use the 'k' suffix to let qemu handle the units */
7461 virCommandAddArgFormat(cmd, "size=%lluk,slots=%u,maxmem=%lluk",
7462 virDomainDefGetMemoryInitial(def),
7463 def->mem.memory_slots,
7464 def->mem.max_memory);
7465
7466 } else {
7467 virCommandAddArgFormat(cmd, "%llu",
7468 virDomainDefGetMemoryInitial(def) / 1024);
7469 }
7470
7471 defaultRAMid = virQEMUCapsGetMachineDefaultRAMid(qemuCaps,
7472 def->virtType,
7473 def->os.machine);
7474
7475 if (defaultRAMid) {
7476 /* As documented in qemuBuildMachineCommandLine() if QEMU is new enough
7477 * to expose default RAM ID we must use memory-backend-* even for
7478 * regular memory because -mem-path and -mem-prealloc are obsolete.
7479 * However, if domain has one or more NUMA nodes then there is no
7480 * default RAM and we mustn't generate the memory object. */
7481 if (!virDomainNumaGetNodeCount(def->numa))
7482 qemuBuildMemCommandLineMemoryDefaultBackend(cmd, def, priv, defaultRAMid);
7483 } else {
7484 /*
7485 * Add '-mem-path' (and '-mem-prealloc') parameter here if
7486 * the hugepages and no numa node is specified.
7487 */
7488 if (!virDomainNumaGetNodeCount(def->numa) &&
7489 qemuBuildMemPathStr(def, cmd, priv) < 0)
7490 return -1;
7491 }
7492
7493 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_OVERCOMMIT)) {
7494 virCommandAddArg(cmd, "-overcommit");
7495 virCommandAddArgFormat(cmd, "mem-lock=%s", def->mem.locked ? "on" : "off");
7496 } else {
7497 virCommandAddArg(cmd, "-realtime");
7498 virCommandAddArgFormat(cmd, "mlock=%s",
7499 def->mem.locked ? "on" : "off");
7500 }
7501
7502 return 0;
7503 }
7504
7505
7506 static int
qemuBuildIOThreadCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)7507 qemuBuildIOThreadCommandLine(virCommand *cmd,
7508 const virDomainDef *def,
7509 virQEMUCaps *qemuCaps)
7510 {
7511 size_t i;
7512
7513 if (def->niothreadids == 0)
7514 return 0;
7515
7516 for (i = 0; i < def->niothreadids; i++) {
7517 g_autoptr(virJSONValue) props = NULL;
7518 g_autofree char *alias = g_strdup_printf("iothread%u", def->iothreadids[i]->iothread_id);
7519
7520 if (qemuMonitorCreateObjectProps(&props, "iothread", alias, NULL) < 0)
7521 return -1;
7522
7523 if (qemuBuildObjectCommandlineFromJSON(cmd, props, qemuCaps) < 0)
7524 return -1;
7525 }
7526
7527 return 0;
7528 }
7529
7530
7531 static int
qemuBuildNumaCellCache(virCommand * cmd,const virDomainDef * def,size_t cell)7532 qemuBuildNumaCellCache(virCommand *cmd,
7533 const virDomainDef *def,
7534 size_t cell)
7535 {
7536 size_t ncaches = virDomainNumaGetNodeCacheCount(def->numa, cell);
7537 size_t i;
7538
7539 if (ncaches == 0)
7540 return 0;
7541
7542 for (i = 0; i < ncaches; i++) {
7543 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7544 unsigned int level;
7545 unsigned int size;
7546 unsigned int line;
7547 virNumaCacheAssociativity associativity;
7548 virNumaCachePolicy policy;
7549
7550 if (virDomainNumaGetNodeCache(def->numa, cell, i,
7551 &level, &size, &line,
7552 &associativity, &policy) < 0) {
7553 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7554 _("Unable to format NUMA node cache"));
7555 return -1;
7556 }
7557
7558 virBufferAsprintf(&buf,
7559 "hmat-cache,node-id=%zu,size=%uK,level=%u",
7560 cell, size, level);
7561
7562 switch (associativity) {
7563 case VIR_NUMA_CACHE_ASSOCIATIVITY_NONE:
7564 virBufferAddLit(&buf, ",associativity=none");
7565 break;
7566 case VIR_NUMA_CACHE_ASSOCIATIVITY_DIRECT:
7567 virBufferAddLit(&buf, ",associativity=direct");
7568 break;
7569 case VIR_NUMA_CACHE_ASSOCIATIVITY_FULL:
7570 virBufferAddLit(&buf, ",associativity=complex");
7571 break;
7572 case VIR_NUMA_CACHE_ASSOCIATIVITY_LAST:
7573 break;
7574 }
7575
7576 switch (policy) {
7577 case VIR_NUMA_CACHE_POLICY_NONE:
7578 virBufferAddLit(&buf, ",policy=none");
7579 break;
7580 case VIR_NUMA_CACHE_POLICY_WRITEBACK:
7581 virBufferAddLit(&buf, ",policy=write-back");
7582 break;
7583 case VIR_NUMA_CACHE_POLICY_WRITETHROUGH:
7584 virBufferAddLit(&buf, ",policy=write-through");
7585 break;
7586 case VIR_NUMA_CACHE_POLICY_LAST:
7587 break;
7588 }
7589
7590 if (line > 0)
7591 virBufferAsprintf(&buf, ",line=%u", line);
7592
7593 virCommandAddArg(cmd, "-numa");
7594 virCommandAddArgBuffer(cmd, &buf);
7595 }
7596
7597 return 0;
7598 }
7599
7600
7601 VIR_ENUM_DECL(qemuDomainMemoryHierarchy);
7602 VIR_ENUM_IMPL(qemuDomainMemoryHierarchy,
7603 4, /* Maximum level of cache */
7604 "memory", /* Special case, whole memory not specific cache */
7605 "first-level",
7606 "second-level",
7607 "third-level");
7608
7609 static int
qemuBuildNumaHMATCommandLine(virCommand * cmd,const virDomainDef * def)7610 qemuBuildNumaHMATCommandLine(virCommand *cmd,
7611 const virDomainDef *def)
7612 {
7613 size_t nlatencies;
7614 size_t i;
7615
7616 if (!def->numa)
7617 return 0;
7618
7619 nlatencies = virDomainNumaGetInterconnectsCount(def->numa);
7620 for (i = 0; i < nlatencies; i++) {
7621 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7622 virNumaInterconnectType type;
7623 unsigned int initiator;
7624 unsigned int target;
7625 unsigned int cache;
7626 virMemoryLatency accessType;
7627 unsigned long value;
7628 const char *hierarchyStr;
7629 const char *accessStr;
7630
7631 if (virDomainNumaGetInterconnect(def->numa, i,
7632 &type, &initiator, &target,
7633 &cache, &accessType, &value) < 0)
7634 return -1;
7635
7636 hierarchyStr = qemuDomainMemoryHierarchyTypeToString(cache);
7637 accessStr = virMemoryLatencyTypeToString(accessType);
7638 virBufferAsprintf(&buf,
7639 "hmat-lb,initiator=%u,target=%u,hierarchy=%s,data-type=%s-",
7640 initiator, target, hierarchyStr, accessStr);
7641
7642 switch (type) {
7643 case VIR_NUMA_INTERCONNECT_TYPE_LATENCY:
7644 virBufferAsprintf(&buf, "latency,latency=%lu", value);
7645 break;
7646 case VIR_NUMA_INTERCONNECT_TYPE_BANDWIDTH:
7647 virBufferAsprintf(&buf, "bandwidth,bandwidth=%luK", value);
7648 break;
7649 }
7650
7651 virCommandAddArg(cmd, "-numa");
7652 virCommandAddArgBuffer(cmd, &buf);
7653 }
7654
7655 return 0;
7656 }
7657
7658
7659 static int
qemuBuildNumaCPUs(virBuffer * buf,virBitmap * cpu)7660 qemuBuildNumaCPUs(virBuffer *buf,
7661 virBitmap *cpu)
7662 {
7663 g_autofree char *cpumask = NULL;
7664 char *tmpmask = NULL;
7665 char *next = NULL;
7666
7667 if (!cpu)
7668 return 0;
7669
7670 if (!(cpumask = virBitmapFormat(cpu)))
7671 return -1;
7672
7673 for (tmpmask = cpumask; tmpmask; tmpmask = next) {
7674 if ((next = strchr(tmpmask, ',')))
7675 *(next++) = '\0';
7676 virBufferAddLit(buf, ",cpus=");
7677 virBufferAdd(buf, tmpmask, -1);
7678 }
7679
7680 return 0;
7681 }
7682
7683
7684 static int
qemuBuildNumaCommandLine(virQEMUDriverConfig * cfg,virDomainDef * def,virCommand * cmd,qemuDomainObjPrivate * priv)7685 qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg,
7686 virDomainDef *def,
7687 virCommand *cmd,
7688 qemuDomainObjPrivate *priv)
7689 {
7690 size_t i, j;
7691 virQEMUCaps *qemuCaps = priv->qemuCaps;
7692 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7693 virJSONValue **nodeBackends = NULL;
7694 bool needBackend = false;
7695 bool hmat = false;
7696 int ret = -1;
7697 size_t ncells = virDomainNumaGetNodeCount(def->numa);
7698 ssize_t masterInitiator = -1;
7699
7700 if (!virDomainNumatuneNodesetIsAvailable(def->numa, priv->autoNodeset))
7701 goto cleanup;
7702
7703 if (!virQEMUCapsGetMachineNumaMemSupported(qemuCaps,
7704 def->virtType,
7705 def->os.machine))
7706 needBackend = true;
7707
7708 if (virDomainNumaHasHMAT(def->numa)) {
7709 needBackend = true;
7710 hmat = true;
7711 }
7712
7713 nodeBackends = g_new0(virJSONValue *, ncells);
7714
7715 /* using of -numa memdev= cannot be combined with -numa mem=, thus we
7716 * need to check which approach to use */
7717 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) ||
7718 virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE) ||
7719 virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD)) {
7720 int rc;
7721
7722 for (i = 0; i < ncells; i++) {
7723 if ((rc = qemuBuildMemoryCellBackendProps(def, cfg, i, priv,
7724 &nodeBackends[i])) < 0)
7725 goto cleanup;
7726
7727 if (rc == 0)
7728 needBackend = true;
7729 }
7730 }
7731
7732 if (!needBackend &&
7733 qemuBuildMemPathStr(def, cmd, priv) < 0)
7734 goto cleanup;
7735
7736 for (i = 0; i < ncells; i++) {
7737 if (virDomainNumaGetNodeCpumask(def->numa, i)) {
7738 masterInitiator = i;
7739 break;
7740 }
7741 }
7742
7743 if (masterInitiator < 0) {
7744 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7745 _("At least one NUMA node has to have CPUs"));
7746 goto cleanup;
7747 }
7748
7749 for (i = 0; i < ncells; i++) {
7750 ssize_t initiator = virDomainNumaGetNodeInitiator(def->numa, i);
7751
7752 if (needBackend) {
7753 if (qemuBuildObjectCommandlineFromJSON(cmd, nodeBackends[i],
7754 priv->qemuCaps) < 0)
7755 goto cleanup;
7756 }
7757
7758 virCommandAddArg(cmd, "-numa");
7759 virBufferAsprintf(&buf, "node,nodeid=%zu", i);
7760
7761 if (qemuBuildNumaCPUs(&buf, virDomainNumaGetNodeCpumask(def->numa, i)) < 0)
7762 goto cleanup;
7763
7764 if (hmat) {
7765 if (initiator < 0)
7766 initiator = masterInitiator;
7767
7768 virBufferAsprintf(&buf, ",initiator=%zd", initiator);
7769 }
7770
7771 if (needBackend)
7772 virBufferAsprintf(&buf, ",memdev=ram-node%zu", i);
7773 else
7774 virBufferAsprintf(&buf, ",mem=%llu",
7775 virDomainNumaGetNodeMemorySize(def->numa, i) / 1024);
7776
7777 virCommandAddArgBuffer(cmd, &buf);
7778 }
7779
7780 /* If NUMA node distance is specified for at least one pair
7781 * of nodes, we have to specify all the distances. Even
7782 * though they might be the default ones. */
7783 if (virDomainNumaNodesDistancesAreBeingSet(def->numa)) {
7784 for (i = 0; i < ncells; i++) {
7785 for (j = 0; j < ncells; j++) {
7786 size_t distance = virDomainNumaGetNodeDistance(def->numa, i, j);
7787
7788 virCommandAddArg(cmd, "-numa");
7789 virBufferAsprintf(&buf, "dist,src=%zu,dst=%zu,val=%zu", i, j, distance);
7790
7791 virCommandAddArgBuffer(cmd, &buf);
7792 }
7793 }
7794 }
7795
7796 if (hmat) {
7797 if (qemuBuildNumaHMATCommandLine(cmd, def) < 0)
7798 goto cleanup;
7799
7800 /* This can't be moved into any of the loops above,
7801 * because hmat-cache can be specified only after hmat-lb. */
7802 for (i = 0; i < ncells; i++) {
7803 if (qemuBuildNumaCellCache(cmd, def, i) < 0)
7804 goto cleanup;
7805 }
7806 }
7807
7808 ret = 0;
7809
7810 cleanup:
7811 if (nodeBackends) {
7812 for (i = 0; i < ncells; i++)
7813 virJSONValueFree(nodeBackends[i]);
7814
7815 VIR_FREE(nodeBackends);
7816 }
7817
7818 return ret;
7819 }
7820
7821
7822 static int
qemuBuildMemoryDeviceCommandLine(virCommand * cmd,virQEMUDriverConfig * cfg,virDomainDef * def,qemuDomainObjPrivate * priv)7823 qemuBuildMemoryDeviceCommandLine(virCommand *cmd,
7824 virQEMUDriverConfig *cfg,
7825 virDomainDef *def,
7826 qemuDomainObjPrivate *priv)
7827 {
7828 size_t i;
7829
7830 /* memory hotplug requires NUMA to be enabled - we already checked
7831 * that memory devices are present only when NUMA is */
7832 for (i = 0; i < def->nmems; i++) {
7833 g_autoptr(virJSONValue) props = NULL;
7834
7835 if (qemuBuildMemoryDimmBackendStr(cmd, def->mems[i], def, cfg, priv) < 0)
7836 return -1;
7837
7838 if (!(props = qemuBuildMemoryDeviceProps(def, def->mems[i])))
7839 return -1;
7840
7841 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0)
7842 return -1;
7843 }
7844
7845 return 0;
7846 }
7847
7848
7849 static int
qemuBuildAudioCommonProps(virDomainAudioIOCommon * def,virJSONValue ** props)7850 qemuBuildAudioCommonProps(virDomainAudioIOCommon *def,
7851 virJSONValue **props)
7852 {
7853 unsigned int frequency = 0;
7854 unsigned int channels = 0;
7855 const char *format = NULL;
7856
7857 if (def->fixedSettings == VIR_TRISTATE_BOOL_YES) {
7858 frequency = def->frequency;
7859 channels = def->channels;
7860 if (def->format != VIR_DOMAIN_AUDIO_FORMAT_DEFAULT)
7861 format = virDomainAudioFormatTypeToString(def->format);
7862 }
7863
7864 return virJSONValueObjectAdd(props,
7865 "T:mixing-engine", def->mixingEngine,
7866 "T:fixed-settings", def->fixedSettings,
7867 "p:voices", def->voices,
7868 "p:buffer-length", def->bufferLength,
7869 "p:frequency", frequency,
7870 "p:channels", channels,
7871 "S:format", format,
7872 NULL);
7873 }
7874
7875
7876 static int
qemuBuildAudioALSAProps(virDomainAudioIOALSA * def,virJSONValue ** props)7877 qemuBuildAudioALSAProps(virDomainAudioIOALSA *def,
7878 virJSONValue **props)
7879 {
7880 return virJSONValueObjectAdd(props,
7881 "S:dev", def->dev,
7882 NULL);
7883 }
7884
7885
7886 static int
qemuBuildAudioCoreAudioProps(virDomainAudioIOCoreAudio * def,virJSONValue ** props)7887 qemuBuildAudioCoreAudioProps(virDomainAudioIOCoreAudio *def,
7888 virJSONValue **props)
7889 {
7890 return virJSONValueObjectAdd(props,
7891 "p:buffer-count", def->bufferCount,
7892 NULL);
7893 }
7894
7895
7896 static int
qemuBuildAudioJackProps(virDomainAudioIOJack * def,virJSONValue ** props)7897 qemuBuildAudioJackProps(virDomainAudioIOJack *def,
7898 virJSONValue **props)
7899 {
7900 return virJSONValueObjectAdd(props,
7901 "S:server-name", def->serverName,
7902 "S:client-name", def->clientName,
7903 "S:connect-ports", def->connectPorts,
7904 "T:exact-name", def->exactName,
7905 NULL);
7906 }
7907
7908
7909 static int
qemuBuildAudioOSSProps(virDomainAudioIOOSS * def,virJSONValue ** props)7910 qemuBuildAudioOSSProps(virDomainAudioIOOSS *def,
7911 virJSONValue **props)
7912 {
7913 return virJSONValueObjectAdd(props,
7914 "S:dev", def->dev,
7915 "p:buffer-count", def->bufferCount,
7916 "T:try-poll", def->tryPoll,
7917 NULL);
7918 }
7919
7920
7921 static int
qemuBuildAudioPulseAudioProps(virDomainAudioIOPulseAudio * def,virJSONValue ** props)7922 qemuBuildAudioPulseAudioProps(virDomainAudioIOPulseAudio *def,
7923 virJSONValue **props)
7924 {
7925 return virJSONValueObjectAdd(props,
7926 "S:name", def->name,
7927 "S:stream-name", def->streamName,
7928 "p:latency", def->latency,
7929 NULL);
7930 }
7931
7932
7933 static int
qemuBuildAudioSDLProps(virDomainAudioIOSDL * def,virJSONValue ** props)7934 qemuBuildAudioSDLProps(virDomainAudioIOSDL *def,
7935 virJSONValue **props)
7936 {
7937 return virJSONValueObjectAdd(props,
7938 "p:buffer-count", def->bufferCount,
7939 NULL);
7940 }
7941
7942
7943 static int
qemuBuildAudioCommandLineArg(virCommand * cmd,virDomainAudioDef * def)7944 qemuBuildAudioCommandLineArg(virCommand *cmd,
7945 virDomainAudioDef *def)
7946 {
7947 g_autoptr(virJSONValue) props = NULL;
7948 g_autoptr(virJSONValue) in = NULL;
7949 g_autoptr(virJSONValue) out = NULL;
7950 g_autofree char *propsstr = NULL;
7951 g_autofree char *alias = g_strdup_printf("audio%d", def->id);
7952
7953 if (virJSONValueObjectAdd(&props,
7954 "s:id", alias,
7955 "s:driver", qemuAudioDriverTypeToString(def->type),
7956 "p:timer-period", def->timerPeriod,
7957 NULL) < 0)
7958 return -1;
7959
7960 if (qemuBuildAudioCommonProps(&def->input, &in) < 0 ||
7961 qemuBuildAudioCommonProps(&def->output, &out) < 0)
7962 return -1;
7963
7964 switch (def->type) {
7965 case VIR_DOMAIN_AUDIO_TYPE_NONE:
7966 break;
7967
7968 case VIR_DOMAIN_AUDIO_TYPE_ALSA:
7969 if (qemuBuildAudioALSAProps(&def->backend.alsa.input, &in) < 0 ||
7970 qemuBuildAudioALSAProps(&def->backend.alsa.output, &out) < 0)
7971 return -1;
7972 break;
7973
7974 case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
7975 if (qemuBuildAudioCoreAudioProps(&def->backend.coreaudio.input, &in) < 0 ||
7976 qemuBuildAudioCoreAudioProps(&def->backend.coreaudio.output, &out) < 0)
7977 return -1;
7978 break;
7979
7980 case VIR_DOMAIN_AUDIO_TYPE_JACK:
7981 if (qemuBuildAudioJackProps(&def->backend.jack.input, &in) < 0 ||
7982 qemuBuildAudioJackProps(&def->backend.jack.output, &out) < 0)
7983 return -1;
7984 break;
7985
7986 case VIR_DOMAIN_AUDIO_TYPE_OSS: {
7987 g_autoptr(virJSONValue) dspPolicy = NULL;
7988
7989 if (def->backend.oss.dspPolicySet)
7990 dspPolicy = virJSONValueNewNumberInt(def->backend.oss.dspPolicy);
7991
7992 if (qemuBuildAudioOSSProps(&def->backend.oss.input, &in) < 0 ||
7993 qemuBuildAudioOSSProps(&def->backend.oss.output, &out) < 0)
7994 return -1;
7995
7996 if (virJSONValueObjectAdd(&props,
7997 "T:try-mmap", def->backend.oss.tryMMap,
7998 "T:exclusive", def->backend.oss.exclusive,
7999 "A:dsp-policy", &dspPolicy,
8000 NULL) < 0)
8001 return -1;
8002 break;
8003 }
8004
8005 case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
8006 if (qemuBuildAudioPulseAudioProps(&def->backend.pulseaudio.input, &in) < 0 ||
8007 qemuBuildAudioPulseAudioProps(&def->backend.pulseaudio.output, &out) < 0)
8008 return -1;
8009
8010 if (virJSONValueObjectAdd(&props,
8011 "S:server", def->backend.pulseaudio.serverName,
8012 NULL) < 0)
8013 return -1;
8014 break;
8015
8016 case VIR_DOMAIN_AUDIO_TYPE_SDL:
8017 if (qemuBuildAudioSDLProps(&def->backend.sdl.input, &in) < 0 ||
8018 qemuBuildAudioSDLProps(&def->backend.sdl.output, &out) < 0)
8019 return -1;
8020
8021 if (def->backend.sdl.driver) {
8022 /*
8023 * Some SDL audio driver names are different on SDL 1.2
8024 * vs 2.0. Given how old SDL 1.2 is, we're not going
8025 * make any attempt to support it here as it is unlikely
8026 * to have an real world users. We can assume libvirt
8027 * driver name strings match SDL 2.0 names.
8028 */
8029 virCommandAddEnvPair(cmd, "SDL_AUDIODRIVER",
8030 virDomainAudioSDLDriverTypeToString(
8031 def->backend.sdl.driver));
8032 }
8033 break;
8034
8035 case VIR_DOMAIN_AUDIO_TYPE_SPICE:
8036 break;
8037
8038 case VIR_DOMAIN_AUDIO_TYPE_FILE:
8039 if (virJSONValueObjectAdd(&props,
8040 "S:path", def->backend.file.path,
8041 NULL) < 0)
8042 return -1;
8043 break;
8044
8045 case VIR_DOMAIN_AUDIO_TYPE_LAST:
8046 default:
8047 virReportEnumRangeError(virDomainAudioType, def->type);
8048 return -1;
8049 }
8050
8051 if (virJSONValueObjectAdd(&props,
8052 "A:in", &in,
8053 "A:out", &out,
8054 NULL) < 0)
8055 return -1;
8056
8057 if (!(propsstr = virJSONValueToString(props, false)))
8058 return -1;
8059
8060 virCommandAddArgList(cmd, "-audiodev", propsstr, NULL);
8061 return 0;
8062 }
8063
8064 static int
qemuBuildAudioCommandLineArgs(virCommand * cmd,virDomainDef * def)8065 qemuBuildAudioCommandLineArgs(virCommand *cmd,
8066 virDomainDef *def)
8067 {
8068 size_t i;
8069 for (i = 0; i < def->naudios; i++) {
8070 if (qemuBuildAudioCommandLineArg(cmd, def->audios[i]) < 0)
8071 return -1;
8072 }
8073 return 0;
8074 }
8075
8076 static void
qemuBuildAudioCommonEnv(virCommand * cmd,const char * prefix,virDomainAudioIOCommon * def)8077 qemuBuildAudioCommonEnv(virCommand *cmd,
8078 const char *prefix,
8079 virDomainAudioIOCommon *def)
8080 {
8081 if (def->fixedSettings)
8082 virCommandAddEnvFormat(cmd, "%sFIXED_SETTINGS=%s",
8083 prefix,
8084 virTristateSwitchTypeToString(def->fixedSettings));
8085
8086 if (def->voices)
8087 virCommandAddEnvFormat(cmd, "%sVOICES=%u",
8088 prefix, def->voices);
8089
8090 if (def->fixedSettings) {
8091 if (def->frequency)
8092 virCommandAddEnvFormat(cmd, "%sFIXED_FREQ=%u",
8093 prefix, def->frequency);
8094 if (def->channels)
8095 virCommandAddEnvFormat(cmd, "%sFIXED_CHANNELS=%u",
8096 prefix, def->channels);
8097 if (def->format)
8098 virCommandAddEnvFormat(cmd, "%sFIXED_FMT=%s",
8099 prefix,
8100 virDomainAudioFormatTypeToString(def->format));
8101 }
8102 }
8103
8104 static void
qemuBuildAudioALSAEnv(virCommand * cmd,const char * prefix,virDomainAudioIOALSA * def)8105 qemuBuildAudioALSAEnv(virCommand *cmd,
8106 const char *prefix,
8107 virDomainAudioIOALSA *def)
8108 {
8109 if (def->dev)
8110 virCommandAddEnvFormat(cmd, "%sDEV=%s",
8111 prefix, def->dev);
8112 }
8113
8114 static void
qemuBuildAudioCoreAudioEnv(virCommand * cmd,virDomainAudioDef * def)8115 qemuBuildAudioCoreAudioEnv(virCommand *cmd,
8116 virDomainAudioDef *def)
8117 {
8118 if (def->backend.coreaudio.output.bufferCount)
8119 virCommandAddEnvFormat(cmd, "QEMU_COREAUDIO_BUFFER_COUNT=%u",
8120 def->backend.coreaudio.output.bufferCount);
8121 if (def->output.bufferLength)
8122 virCommandAddEnvFormat(cmd, "QEMU_COREAUDIO_BUFFER_SIZE=%u",
8123 def->output.bufferLength);
8124 }
8125
8126 static void
qemuBuildAudioOSSEnv(virCommand * cmd,const char * prefix,const char * prefix2,virDomainAudioIOOSS * def)8127 qemuBuildAudioOSSEnv(virCommand *cmd,
8128 const char *prefix,
8129 const char *prefix2,
8130 virDomainAudioIOOSS *def)
8131 {
8132 if (def->dev)
8133 virCommandAddEnvFormat(cmd, "%sDEV=%s",
8134 prefix, def->dev);
8135 if (def->tryPoll)
8136 virCommandAddEnvFormat(cmd, "%sTRY_POLL=%s", prefix2,
8137 virTristateSwitchTypeToString(def->tryPoll));
8138 }
8139
8140 static void
qemuBuildAudioPulseAudioEnv(virCommand * cmd,virDomainAudioDef * def)8141 qemuBuildAudioPulseAudioEnv(virCommand *cmd,
8142 virDomainAudioDef *def)
8143 {
8144 if (def->backend.pulseaudio.input.name)
8145 virCommandAddEnvPair(cmd, "QEMU_PA_SOURCE",
8146 def->backend.pulseaudio.input.name);
8147 if (def->backend.pulseaudio.output.name)
8148 virCommandAddEnvPair(cmd, "QEMU_PA_SINK",
8149 def->backend.pulseaudio.output.name);
8150
8151 if (def->input.bufferLength)
8152 virCommandAddEnvFormat(cmd, "QEMU_PA_SAMPLES=%u",
8153 def->input.bufferLength);
8154
8155 if (def->backend.pulseaudio.serverName)
8156 virCommandAddEnvPair(cmd, "QEMU_PA_SERVER=%s",
8157 def->backend.pulseaudio.serverName);
8158 }
8159
8160
8161 static int
qemuBuildAudioCommandLineEnv(virCommand * cmd,virDomainDef * def)8162 qemuBuildAudioCommandLineEnv(virCommand *cmd,
8163 virDomainDef *def)
8164 {
8165 virDomainAudioDef *audio;
8166 if (def->naudios != 1)
8167 return 0;
8168
8169 audio = def->audios[0];
8170 virCommandAddEnvPair(cmd, "QEMU_AUDIO_DRV",
8171 qemuAudioDriverTypeToString(audio->type));
8172
8173 if (audio->timerPeriod)
8174 virCommandAddEnvFormat(cmd, "QEMU_AUDIO_TIMER_PERIOD=%u",
8175 audio->timerPeriod);
8176
8177 qemuBuildAudioCommonEnv(cmd, "QEMU_AUDIO_ADC_", &audio->input);
8178 qemuBuildAudioCommonEnv(cmd, "QEMU_AUDIO_DAC_", &audio->output);
8179
8180 switch (audio->type) {
8181 case VIR_DOMAIN_AUDIO_TYPE_NONE:
8182 break;
8183
8184 case VIR_DOMAIN_AUDIO_TYPE_ALSA:
8185 qemuBuildAudioALSAEnv(cmd, "QEMU_AUDIO_ADC_", &audio->backend.alsa.input);
8186 qemuBuildAudioALSAEnv(cmd, "QEMU_AUDIO_DAC_", &audio->backend.alsa.output);
8187 break;
8188
8189 case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
8190 qemuBuildAudioCoreAudioEnv(cmd, audio);
8191 break;
8192
8193 case VIR_DOMAIN_AUDIO_TYPE_JACK:
8194 break;
8195
8196 case VIR_DOMAIN_AUDIO_TYPE_OSS:
8197 qemuBuildAudioOSSEnv(cmd, "QEMU_OSS_ADC_", "QEMU_AUDIO_ADC_",
8198 &audio->backend.oss.input);
8199 qemuBuildAudioOSSEnv(cmd, "QEMU_OSS_DAC_", "QEMU_AUDIO_DAC_",
8200 &audio->backend.oss.output);
8201
8202 if (audio->backend.oss.input.bufferCount)
8203 virCommandAddEnvFormat(cmd, "QEMU_OSS_NFRAGS=%u",
8204 audio->backend.oss.input.bufferCount);
8205
8206 if (audio->backend.oss.tryMMap)
8207 virCommandAddEnvFormat(cmd, "QEMU_OSS_MMAP=%s",
8208 virTristateSwitchTypeToString(audio->backend.oss.tryMMap));
8209 if (audio->backend.oss.exclusive)
8210 virCommandAddEnvFormat(cmd, "QEMU_OSS_EXCLUSIVE=%s",
8211 virTristateSwitchTypeToString(audio->backend.oss.exclusive));
8212 if (audio->backend.oss.dspPolicySet)
8213 virCommandAddEnvFormat(cmd, "QEMU_OSS_POLICY=%d",
8214 audio->backend.oss.dspPolicy);
8215 break;
8216
8217 case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
8218 qemuBuildAudioPulseAudioEnv(cmd, audio);
8219 break;
8220
8221 case VIR_DOMAIN_AUDIO_TYPE_SDL:
8222 if (audio->output.bufferLength)
8223 virCommandAddEnvFormat(cmd, "QEMU_SDL_SAMPLES=%u",
8224 audio->output.bufferLength);
8225
8226 if (audio->backend.sdl.driver) {
8227 /*
8228 * Some SDL audio driver names are different on SDL 1.2
8229 * vs 2.0. Given how old SDL 1.2 is, we're not going
8230 * make any attempt to support it here as it is unlikely
8231 * to have an real world users. We can assume libvirt
8232 * driver name strings match SDL 2.0 names.
8233 */
8234 virCommandAddEnvPair(cmd, "SDL_AUDIODRIVER",
8235 virDomainAudioSDLDriverTypeToString(
8236 audio->backend.sdl.driver));
8237 }
8238 break;
8239
8240 case VIR_DOMAIN_AUDIO_TYPE_SPICE:
8241 break;
8242
8243 case VIR_DOMAIN_AUDIO_TYPE_FILE:
8244 if (audio->backend.file.path)
8245 virCommandAddEnvFormat(cmd, "QEMU_WAV_PATH=%s",
8246 audio->backend.file.path);
8247 break;
8248
8249 case VIR_DOMAIN_AUDIO_TYPE_LAST:
8250 default:
8251 virReportEnumRangeError(virDomainAudioType, audio->type);
8252 return -1;
8253 }
8254 return 0;
8255 }
8256
8257 static int
qemuBuildAudioCommandLine(virCommand * cmd,virDomainDef * def,virQEMUCaps * qemuCaps)8258 qemuBuildAudioCommandLine(virCommand *cmd,
8259 virDomainDef *def,
8260 virQEMUCaps *qemuCaps)
8261 {
8262 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_AUDIODEV))
8263 return qemuBuildAudioCommandLineArgs(cmd, def);
8264 else
8265 return qemuBuildAudioCommandLineEnv(cmd, def);
8266 }
8267
8268
8269 static int
qemuBuildGraphicsSDLCommandLine(virQEMUDriverConfig * cfg G_GNUC_UNUSED,virCommand * cmd,virQEMUCaps * qemuCaps G_GNUC_UNUSED,virDomainGraphicsDef * graphics)8270 qemuBuildGraphicsSDLCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED,
8271 virCommand *cmd,
8272 virQEMUCaps *qemuCaps G_GNUC_UNUSED,
8273 virDomainGraphicsDef *graphics)
8274 {
8275 g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
8276
8277 if (graphics->data.sdl.xauth)
8278 virCommandAddEnvPair(cmd, "XAUTHORITY", graphics->data.sdl.xauth);
8279 if (graphics->data.sdl.display)
8280 virCommandAddEnvPair(cmd, "DISPLAY", graphics->data.sdl.display);
8281 if (graphics->data.sdl.fullscreen)
8282 virCommandAddArg(cmd, "-full-screen");
8283
8284 virCommandAddArg(cmd, "-display");
8285 virBufferAddLit(&opt, "sdl");
8286
8287 if (graphics->data.sdl.gl != VIR_TRISTATE_BOOL_ABSENT)
8288 virBufferAsprintf(&opt, ",gl=%s",
8289 virTristateSwitchTypeToString(graphics->data.sdl.gl));
8290
8291 virCommandAddArgBuffer(cmd, &opt);
8292
8293 return 0;
8294 }
8295
8296
8297 static int
qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfig * cfg,const virDomainDef * def,virCommand * cmd,virQEMUCaps * qemuCaps,virDomainGraphicsDef * graphics)8298 qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfig *cfg,
8299 const virDomainDef *def,
8300 virCommand *cmd,
8301 virQEMUCaps *qemuCaps,
8302 virDomainGraphicsDef *graphics)
8303 {
8304 g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
8305 virDomainGraphicsListenDef *glisten = NULL;
8306 bool escapeAddr;
8307
8308 if (!(glisten = virDomainGraphicsGetListen(graphics, 0))) {
8309 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
8310 _("missing listen element"));
8311 return -1;
8312 }
8313
8314 switch (glisten->type) {
8315 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
8316 virBufferAddLit(&opt, "vnc=unix:");
8317 virQEMUBuildBufferEscapeComma(&opt, glisten->socket);
8318 break;
8319
8320 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
8321 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
8322 if (!graphics->data.vnc.autoport &&
8323 (graphics->data.vnc.port < 5900 ||
8324 graphics->data.vnc.port > 65535)) {
8325 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8326 _("vnc port must be in range [5900,65535]"));
8327 return -1;
8328 }
8329
8330 if (glisten->address) {
8331 escapeAddr = strchr(glisten->address, ':') != NULL;
8332 if (escapeAddr)
8333 virBufferAsprintf(&opt, "[%s]", glisten->address);
8334 else
8335 virBufferAdd(&opt, glisten->address, -1);
8336 }
8337 virBufferAsprintf(&opt, ":%d",
8338 graphics->data.vnc.port - 5900);
8339
8340 if (graphics->data.vnc.websocket)
8341 virBufferAsprintf(&opt, ",websocket=%d", graphics->data.vnc.websocket);
8342 break;
8343
8344 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
8345 virBufferAddLit(&opt, "none");
8346 break;
8347
8348 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
8349 break;
8350 }
8351
8352 if (graphics->data.vnc.sharePolicy) {
8353 virBufferAsprintf(&opt, ",share=%s",
8354 virDomainGraphicsVNCSharePolicyTypeToString(
8355 graphics->data.vnc.sharePolicy));
8356 }
8357
8358 if (graphics->data.vnc.auth.passwd || cfg->vncPassword) {
8359 virBufferAddLit(&opt, ",password=on");
8360 }
8361
8362 if (cfg->vncTLS) {
8363 qemuDomainGraphicsPrivate *gfxPriv = QEMU_DOMAIN_GRAPHICS_PRIVATE(graphics);
8364 const char *secretAlias = NULL;
8365
8366 if (gfxPriv->secinfo) {
8367 if (qemuBuildObjectSecretCommandLine(cmd,
8368 gfxPriv->secinfo,
8369 qemuCaps) < 0)
8370 return -1;
8371 secretAlias = gfxPriv->secinfo->alias;
8372 }
8373
8374 if (qemuBuildTLSx509CommandLine(cmd,
8375 cfg->vncTLSx509certdir,
8376 true,
8377 cfg->vncTLSx509verify,
8378 secretAlias,
8379 gfxPriv->tlsAlias,
8380 qemuCaps) < 0)
8381 return -1;
8382
8383 virBufferAsprintf(&opt, ",tls-creds=%s", gfxPriv->tlsAlias);
8384 }
8385
8386 if (cfg->vncSASL) {
8387 virBufferAddLit(&opt, ",sasl=on");
8388
8389 if (cfg->vncSASLdir)
8390 virCommandAddEnvPair(cmd, "SASL_CONF_PATH", cfg->vncSASLdir);
8391
8392 /* TODO: Support ACLs later */
8393 }
8394
8395 if (graphics->data.vnc.powerControl != VIR_TRISTATE_BOOL_ABSENT) {
8396 virBufferAsprintf(&opt, ",power-control=%s",
8397 graphics->data.vnc.powerControl == VIR_TRISTATE_BOOL_YES ?
8398 "on" : "off");
8399 }
8400
8401 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_AUDIODEV)) {
8402 g_autofree char *audioid = qemuGetAudioIDString(def, graphics->data.vnc.audioId);
8403 if (!audioid)
8404 return -1;
8405 virBufferAsprintf(&opt, ",audiodev=%s", audioid);
8406 }
8407
8408 virCommandAddArg(cmd, "-vnc");
8409 virCommandAddArgBuffer(cmd, &opt);
8410 if (graphics->data.vnc.keymap)
8411 virCommandAddArgList(cmd, "-k", graphics->data.vnc.keymap, NULL);
8412
8413 return 0;
8414 }
8415
8416
8417 static int
qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfig * cfg,virCommand * cmd,virDomainGraphicsDef * graphics)8418 qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfig *cfg,
8419 virCommand *cmd,
8420 virDomainGraphicsDef *graphics)
8421 {
8422 g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
8423 virDomainGraphicsListenDef *glisten = NULL;
8424 int port = graphics->data.spice.port;
8425 int tlsPort = graphics->data.spice.tlsPort;
8426 size_t i;
8427 bool hasSecure = false;
8428 bool hasInsecure = false;
8429
8430 if (!(glisten = virDomainGraphicsGetListen(graphics, 0))) {
8431 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
8432 _("missing listen element"));
8433 return -1;
8434 }
8435
8436 switch (glisten->type) {
8437 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
8438 virBufferAddLit(&opt, "unix,addr=");
8439 virQEMUBuildBufferEscapeComma(&opt, glisten->socket);
8440 virBufferAddLit(&opt, ",");
8441 hasInsecure = true;
8442 break;
8443
8444 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
8445 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
8446 if (port > 0) {
8447 virBufferAsprintf(&opt, "port=%u,", port);
8448 hasInsecure = true;
8449 }
8450
8451 if (tlsPort > 0) {
8452 virBufferAsprintf(&opt, "tls-port=%u,", tlsPort);
8453 hasSecure = true;
8454 }
8455
8456 if (port > 0 || tlsPort > 0) {
8457 if (glisten->address)
8458 virBufferAsprintf(&opt, "addr=%s,", glisten->address);
8459 }
8460
8461 break;
8462
8463 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
8464 /* QEMU requires either port or tls-port to be specified if there is no
8465 * other argument. Use a dummy port=0. */
8466 virBufferAddLit(&opt, "port=0,");
8467 hasInsecure = true;
8468 break;
8469 case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
8470 break;
8471 }
8472
8473 if (cfg->spiceSASL) {
8474 virBufferAddLit(&opt, "sasl=on,");
8475
8476 if (cfg->spiceSASLdir)
8477 virCommandAddEnvPair(cmd, "SASL_CONF_PATH",
8478 cfg->spiceSASLdir);
8479
8480 /* TODO: Support ACLs later */
8481 }
8482
8483 if (graphics->data.spice.mousemode) {
8484 switch (graphics->data.spice.mousemode) {
8485 case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER:
8486 virBufferAddLit(&opt, "agent-mouse=off,");
8487 break;
8488 case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT:
8489 virBufferAddLit(&opt, "agent-mouse=on,");
8490 break;
8491 case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT:
8492 break;
8493 case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST:
8494 default:
8495 virReportEnumRangeError(virDomainGraphicsSpiceMouseMode,
8496 graphics->data.spice.mousemode);
8497 return -1;
8498 }
8499 }
8500
8501 /* In the password case we set it via monitor command, to avoid
8502 * making it visible on CLI, so there's no use of password=XXX
8503 * in this bit of the code */
8504 if (!graphics->data.spice.auth.passwd &&
8505 !cfg->spicePassword)
8506 virBufferAddLit(&opt, "disable-ticketing=on,");
8507
8508 if (hasSecure) {
8509 virBufferAddLit(&opt, "x509-dir=");
8510 virQEMUBuildBufferEscapeComma(&opt, cfg->spiceTLSx509certdir);
8511 virBufferAddLit(&opt, ",");
8512 }
8513
8514 switch (graphics->data.spice.defaultMode) {
8515 case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
8516 if (!hasSecure) {
8517 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8518 _("spice defaultMode secure requested in XML "
8519 "configuration, but TLS connection is not "
8520 "available"));
8521 return -1;
8522 }
8523 virBufferAddLit(&opt, "tls-channel=default,");
8524 break;
8525 case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
8526 if (!hasInsecure) {
8527 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8528 _("spice defaultMode insecure requested in XML "
8529 "configuration, but plaintext connection is not "
8530 "available"));
8531 return -1;
8532 }
8533 virBufferAddLit(&opt, "plaintext-channel=default,");
8534 break;
8535 case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
8536 case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST:
8537 /* nothing */
8538 break;
8539 }
8540
8541 for (i = 0; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST; i++) {
8542 switch (graphics->data.spice.channels[i]) {
8543 case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
8544 if (!hasSecure) {
8545 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8546 _("spice secure channels set in XML "
8547 "configuration, but TLS connection is not "
8548 "available"));
8549 return -1;
8550 }
8551 virBufferAsprintf(&opt, "tls-channel=%s,",
8552 virDomainGraphicsSpiceChannelNameTypeToString(i));
8553 break;
8554
8555 case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
8556 if (!hasInsecure) {
8557 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8558 _("spice insecure channels set in XML "
8559 "configuration, but plaintext connection "
8560 "is not available"));
8561 return -1;
8562 }
8563 virBufferAsprintf(&opt, "plaintext-channel=%s,",
8564 virDomainGraphicsSpiceChannelNameTypeToString(i));
8565 break;
8566
8567 case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
8568 break;
8569 }
8570 }
8571
8572 if (graphics->data.spice.image)
8573 virBufferAsprintf(&opt, "image-compression=%s,",
8574 virDomainGraphicsSpiceImageCompressionTypeToString(graphics->data.spice.image));
8575 if (graphics->data.spice.jpeg)
8576 virBufferAsprintf(&opt, "jpeg-wan-compression=%s,",
8577 virDomainGraphicsSpiceJpegCompressionTypeToString(graphics->data.spice.jpeg));
8578 if (graphics->data.spice.zlib)
8579 virBufferAsprintf(&opt, "zlib-glz-wan-compression=%s,",
8580 virDomainGraphicsSpiceZlibCompressionTypeToString(graphics->data.spice.zlib));
8581 if (graphics->data.spice.playback)
8582 virBufferAsprintf(&opt, "playback-compression=%s,",
8583 virTristateSwitchTypeToString(graphics->data.spice.playback));
8584 if (graphics->data.spice.streaming)
8585 virBufferAsprintf(&opt, "streaming-video=%s,",
8586 virDomainGraphicsSpiceStreamingModeTypeToString(graphics->data.spice.streaming));
8587 if (graphics->data.spice.copypaste == VIR_TRISTATE_BOOL_NO)
8588 virBufferAddLit(&opt, "disable-copy-paste=on,");
8589
8590 if (graphics->data.spice.filetransfer == VIR_TRISTATE_BOOL_NO)
8591 virBufferAddLit(&opt, "disable-agent-file-xfer=on,");
8592
8593 if (graphics->data.spice.gl == VIR_TRISTATE_BOOL_YES) {
8594 /* spice.gl is a TristateBool, but qemu expects on/off: use
8595 * TristateSwitch helper */
8596 virBufferAsprintf(&opt, "gl=%s,",
8597 virTristateSwitchTypeToString(graphics->data.spice.gl));
8598
8599 if (graphics->data.spice.rendernode) {
8600 virBufferAddLit(&opt, "rendernode=");
8601 virQEMUBuildBufferEscapeComma(&opt, graphics->data.spice.rendernode);
8602 virBufferAddLit(&opt, ",");
8603 }
8604 }
8605
8606 /* Turn on seamless migration unconditionally. If migration destination
8607 * doesn't support it, it fallbacks to previous migration algorithm silently. */
8608 virBufferAddLit(&opt, "seamless-migration=on,");
8609
8610 virBufferTrim(&opt, ",");
8611
8612 virCommandAddArg(cmd, "-spice");
8613 virCommandAddArgBuffer(cmd, &opt);
8614 if (graphics->data.spice.keymap)
8615 virCommandAddArgList(cmd, "-k",
8616 graphics->data.spice.keymap, NULL);
8617
8618 return 0;
8619 }
8620
8621
8622 static int
qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfig * cfg G_GNUC_UNUSED,virCommand * cmd,virDomainGraphicsDef * graphics)8623 qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfig *cfg G_GNUC_UNUSED,
8624 virCommand *cmd,
8625 virDomainGraphicsDef *graphics)
8626 {
8627 g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER;
8628
8629 virBufferAddLit(&opt, "egl-headless");
8630
8631 if (graphics->data.egl_headless.rendernode) {
8632 virBufferAddLit(&opt, ",rendernode=");
8633 virQEMUBuildBufferEscapeComma(&opt,
8634 graphics->data.egl_headless.rendernode);
8635 }
8636
8637 virCommandAddArg(cmd, "-display");
8638 virCommandAddArgBuffer(cmd, &opt);
8639
8640 return 0;
8641 }
8642
8643
8644 static int
qemuBuildGraphicsCommandLine(virQEMUDriverConfig * cfg,virCommand * cmd,virDomainDef * def,virQEMUCaps * qemuCaps)8645 qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg,
8646 virCommand *cmd,
8647 virDomainDef *def,
8648 virQEMUCaps *qemuCaps)
8649 {
8650 size_t i;
8651
8652 for (i = 0; i < def->ngraphics; i++) {
8653 virDomainGraphicsDef *graphics = def->graphics[i];
8654
8655 switch (graphics->type) {
8656 case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
8657 if (qemuBuildGraphicsSDLCommandLine(cfg, cmd,
8658 qemuCaps, graphics) < 0)
8659 return -1;
8660
8661 break;
8662 case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
8663 if (qemuBuildGraphicsVNCCommandLine(cfg, def, cmd,
8664 qemuCaps, graphics) < 0)
8665 return -1;
8666
8667 break;
8668 case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
8669 if (qemuBuildGraphicsSPICECommandLine(cfg, cmd,
8670 graphics) < 0)
8671 return -1;
8672
8673 break;
8674 case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
8675 if (qemuBuildGraphicsEGLHeadlessCommandLine(cfg, cmd,
8676 graphics) < 0)
8677 return -1;
8678
8679 break;
8680 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
8681 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
8682 return -1;
8683 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
8684 default:
8685 virReportEnumRangeError(virDomainGraphicsType, graphics->type);
8686 return -1;
8687 }
8688 }
8689
8690 return 0;
8691 }
8692
8693 static int
qemuInterfaceVhostuserConnect(virQEMUDriver * driver,virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virDomainDef * def,virDomainNetDef * net,virQEMUCaps * qemuCaps,char ** chardev)8694 qemuInterfaceVhostuserConnect(virQEMUDriver *driver,
8695 virLogManager *logManager,
8696 virSecurityManager *secManager,
8697 virCommand *cmd,
8698 virDomainDef *def,
8699 virDomainNetDef *net,
8700 virQEMUCaps *qemuCaps,
8701 char **chardev)
8702 {
8703 g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
8704
8705 switch ((virDomainChrType)net->data.vhostuser->type) {
8706 case VIR_DOMAIN_CHR_TYPE_UNIX:
8707 if (!(*chardev = qemuBuildChrChardevStr(logManager, secManager,
8708 cmd, cfg, def,
8709 net->data.vhostuser,
8710 net->info.alias, qemuCaps, 0)))
8711 return -1;
8712 break;
8713
8714 case VIR_DOMAIN_CHR_TYPE_NULL:
8715 case VIR_DOMAIN_CHR_TYPE_VC:
8716 case VIR_DOMAIN_CHR_TYPE_PTY:
8717 case VIR_DOMAIN_CHR_TYPE_DEV:
8718 case VIR_DOMAIN_CHR_TYPE_FILE:
8719 case VIR_DOMAIN_CHR_TYPE_PIPE:
8720 case VIR_DOMAIN_CHR_TYPE_STDIO:
8721 case VIR_DOMAIN_CHR_TYPE_UDP:
8722 case VIR_DOMAIN_CHR_TYPE_TCP:
8723 case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
8724 case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
8725 case VIR_DOMAIN_CHR_TYPE_NMDM:
8726 case VIR_DOMAIN_CHR_TYPE_LAST:
8727 virReportError(VIR_ERR_INTERNAL_ERROR,
8728 _("vhost-user type '%s' not supported"),
8729 virDomainChrTypeToString(net->data.vhostuser->type));
8730 return -1;
8731 }
8732
8733 return 0;
8734 }
8735
8736 static int
qemuBuildInterfaceCommandLine(virQEMUDriver * driver,virDomainObj * vm,virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virDomainNetDef * net,virQEMUCaps * qemuCaps,virNetDevVPortProfileOp vmop,bool standalone,size_t * nnicindexes,int ** nicindexes)8737 qemuBuildInterfaceCommandLine(virQEMUDriver *driver,
8738 virDomainObj *vm,
8739 virLogManager *logManager,
8740 virSecurityManager *secManager,
8741 virCommand *cmd,
8742 virDomainNetDef *net,
8743 virQEMUCaps *qemuCaps,
8744 virNetDevVPortProfileOp vmop,
8745 bool standalone,
8746 size_t *nnicindexes,
8747 int **nicindexes)
8748 {
8749 virDomainDef *def = vm->def;
8750 int ret = -1;
8751 g_autoptr(virJSONValue) nicprops = NULL;
8752 g_autofree char *nic = NULL;
8753 g_autofree char *chardev = NULL;
8754 int *tapfd = NULL;
8755 size_t tapfdSize = 0;
8756 int *vhostfd = NULL;
8757 size_t vhostfdSize = 0;
8758 char **tapfdName = NULL;
8759 char **vhostfdName = NULL;
8760 g_autofree char *slirpfdName = NULL;
8761 g_autofree char *vdpafdName = NULL;
8762 int vdpafd = -1;
8763 virDomainNetType actualType = virDomainNetGetActualType(net);
8764 const virNetDevBandwidth *actualBandwidth;
8765 bool requireNicdev = false;
8766 qemuSlirp *slirp;
8767 size_t i;
8768 g_autoptr(virJSONValue) hostnetprops = NULL;
8769
8770 if (qemuDomainValidateActualNetDef(net, qemuCaps) < 0)
8771 return -1;
8772
8773 switch (actualType) {
8774 case VIR_DOMAIN_NET_TYPE_NETWORK:
8775 case VIR_DOMAIN_NET_TYPE_BRIDGE:
8776 tapfdSize = net->driver.virtio.queues;
8777 if (!tapfdSize)
8778 tapfdSize = 1;
8779
8780 tapfd = g_new0(int, tapfdSize);
8781 tapfdName = g_new0(char *, tapfdSize);
8782
8783 memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));
8784
8785 if (qemuInterfaceBridgeConnect(def, driver, net,
8786 tapfd, &tapfdSize) < 0)
8787 goto cleanup;
8788 break;
8789
8790 case VIR_DOMAIN_NET_TYPE_DIRECT:
8791 tapfdSize = net->driver.virtio.queues;
8792 if (!tapfdSize)
8793 tapfdSize = 1;
8794
8795 tapfd = g_new0(int, tapfdSize);
8796 tapfdName = g_new0(char *, tapfdSize);
8797
8798 memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));
8799
8800 if (qemuInterfaceDirectConnect(def, driver, net,
8801 tapfd, tapfdSize, vmop) < 0)
8802 goto cleanup;
8803 break;
8804
8805 case VIR_DOMAIN_NET_TYPE_ETHERNET:
8806 tapfdSize = net->driver.virtio.queues;
8807 if (!tapfdSize)
8808 tapfdSize = 1;
8809
8810 tapfd = g_new0(int, tapfdSize);
8811 tapfdName = g_new0(char *, tapfdSize);
8812
8813 memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));
8814
8815 if (qemuInterfaceEthernetConnect(def, driver, net,
8816 tapfd, tapfdSize) < 0)
8817 goto cleanup;
8818 break;
8819
8820 case VIR_DOMAIN_NET_TYPE_HOSTDEV:
8821 /* NET_TYPE_HOSTDEV devices are really hostdev devices, so
8822 * their commandlines are constructed with other hostdevs.
8823 */
8824 ret = 0;
8825 goto cleanup;
8826 break;
8827
8828 case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
8829 requireNicdev = true;
8830
8831 if (qemuInterfaceVhostuserConnect(driver, logManager, secManager,
8832 cmd, def, net, qemuCaps, &chardev) < 0)
8833 goto cleanup;
8834
8835 if (virNetDevOpenvswitchGetVhostuserIfname(net->data.vhostuser->data.nix.path,
8836 net->data.vhostuser->data.nix.listen,
8837 &net->ifname) < 0)
8838 goto cleanup;
8839
8840 break;
8841
8842 case VIR_DOMAIN_NET_TYPE_VDPA:
8843 if ((vdpafd = qemuInterfaceVDPAConnect(net)) < 0)
8844 goto cleanup;
8845 break;
8846
8847 case VIR_DOMAIN_NET_TYPE_USER:
8848 case VIR_DOMAIN_NET_TYPE_SERVER:
8849 case VIR_DOMAIN_NET_TYPE_CLIENT:
8850 case VIR_DOMAIN_NET_TYPE_MCAST:
8851 case VIR_DOMAIN_NET_TYPE_INTERNAL:
8852 case VIR_DOMAIN_NET_TYPE_UDP:
8853 case VIR_DOMAIN_NET_TYPE_LAST:
8854 /* nada */
8855 break;
8856 }
8857
8858 /* For types whose implementations use a netdev on the host, add
8859 * an entry to nicindexes for passing on to systemd.
8860 */
8861 switch ((virDomainNetType)actualType) {
8862 case VIR_DOMAIN_NET_TYPE_ETHERNET:
8863 case VIR_DOMAIN_NET_TYPE_NETWORK:
8864 case VIR_DOMAIN_NET_TYPE_BRIDGE:
8865 case VIR_DOMAIN_NET_TYPE_DIRECT:
8866 {
8867 int nicindex;
8868
8869 /* network and bridge use a tap device, and direct uses a
8870 * macvtap device
8871 */
8872 if (driver->privileged && nicindexes && nnicindexes &&
8873 net->ifname) {
8874 if (virNetDevGetIndex(net->ifname, &nicindex) < 0)
8875 goto cleanup;
8876
8877 VIR_APPEND_ELEMENT(*nicindexes, *nnicindexes, nicindex);
8878 }
8879 break;
8880 }
8881
8882 case VIR_DOMAIN_NET_TYPE_USER:
8883 case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
8884 case VIR_DOMAIN_NET_TYPE_SERVER:
8885 case VIR_DOMAIN_NET_TYPE_CLIENT:
8886 case VIR_DOMAIN_NET_TYPE_MCAST:
8887 case VIR_DOMAIN_NET_TYPE_UDP:
8888 case VIR_DOMAIN_NET_TYPE_INTERNAL:
8889 case VIR_DOMAIN_NET_TYPE_HOSTDEV:
8890 case VIR_DOMAIN_NET_TYPE_VDPA:
8891 case VIR_DOMAIN_NET_TYPE_LAST:
8892 /* These types don't use a network device on the host, but
8893 * instead use some other type of connection to the emulated
8894 * device in the qemu process.
8895 *
8896 * (Note that hostdev can't be considered as "using a network
8897 * device", because by the time it is being used, it has been
8898 * detached from the hostside network driver so it doesn't show
8899 * up in the list of interfaces on the host - it's just some
8900 * PCI device.)
8901 */
8902 break;
8903 }
8904
8905 qemuDomainInterfaceSetDefaultQDisc(driver, net);
8906
8907 /* Set bandwidth or warn if requested and not supported. */
8908 actualBandwidth = virDomainNetGetActualBandwidth(net);
8909 if (actualBandwidth) {
8910 if (virNetDevSupportsBandwidth(actualType)) {
8911 if (virDomainNetDefIsOvsport(net)) {
8912 if (virNetDevOpenvswitchInterfaceSetQos(net->ifname, actualBandwidth,
8913 def->uuid,
8914 !virDomainNetTypeSharesHostView(net)) < 0)
8915 goto cleanup;
8916 } else if (virNetDevBandwidthSet(net->ifname, actualBandwidth, false,
8917 !virDomainNetTypeSharesHostView(net)) < 0) {
8918 goto cleanup;
8919 }
8920 } else {
8921 VIR_WARN("setting bandwidth on interfaces of "
8922 "type '%s' is not implemented yet",
8923 virDomainNetTypeToString(actualType));
8924 }
8925 }
8926
8927 if (net->mtu && net->managed_tap != VIR_TRISTATE_BOOL_NO &&
8928 virNetDevSetMTU(net->ifname, net->mtu) < 0)
8929 goto cleanup;
8930
8931 if ((actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
8932 actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
8933 actualType == VIR_DOMAIN_NET_TYPE_ETHERNET ||
8934 actualType == VIR_DOMAIN_NET_TYPE_DIRECT) &&
8935 !standalone) {
8936 /* Attempt to use vhost-net mode for these types of
8937 network device */
8938 vhostfdSize = net->driver.virtio.queues;
8939 if (!vhostfdSize)
8940 vhostfdSize = 1;
8941
8942 vhostfd = g_new0(int, vhostfdSize);
8943 vhostfdName = g_new0(char *, vhostfdSize);
8944
8945 memset(vhostfd, -1, vhostfdSize * sizeof(vhostfd[0]));
8946
8947 if (qemuInterfaceOpenVhostNet(def, net, vhostfd, &vhostfdSize) < 0)
8948 goto cleanup;
8949 }
8950
8951 slirp = QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp;
8952 if (slirp && !standalone) {
8953 int slirpfd = qemuSlirpGetFD(slirp);
8954 virCommandPassFD(cmd, slirpfd,
8955 VIR_COMMAND_PASS_FD_CLOSE_PARENT);
8956 slirpfdName = g_strdup_printf("%d", slirpfd);
8957 }
8958
8959
8960 for (i = 0; i < tapfdSize; i++) {
8961 if (qemuSecuritySetTapFDLabel(driver->securityManager,
8962 def, tapfd[i]) < 0)
8963 goto cleanup;
8964 tapfdName[i] = g_strdup_printf("%d", tapfd[i]);
8965 virCommandPassFD(cmd, tapfd[i],
8966 VIR_COMMAND_PASS_FD_CLOSE_PARENT);
8967 tapfd[i] = -1;
8968 }
8969
8970 for (i = 0; i < vhostfdSize; i++) {
8971 vhostfdName[i] = g_strdup_printf("%d", vhostfd[i]);
8972 virCommandPassFD(cmd, vhostfd[i],
8973 VIR_COMMAND_PASS_FD_CLOSE_PARENT);
8974 vhostfd[i] = -1;
8975 }
8976
8977 if (vdpafd > 0) {
8978 g_autofree char *fdset = NULL;
8979 g_autofree char *addfdarg = NULL;
8980 size_t idx;
8981
8982 virCommandPassFDIndex(cmd, vdpafd, VIR_COMMAND_PASS_FD_CLOSE_PARENT, &idx);
8983 fdset = qemuBuildFDSet(vdpafd, idx);
8984 vdpafdName = g_strdup_printf("/dev/fdset/%zu", idx);
8985 /* set opaque to the devicepath so that we can look up the fdset later
8986 * if necessary */
8987 addfdarg = g_strdup_printf("%s,opaque=%s", fdset,
8988 net->data.vdpa.devicepath);
8989 virCommandAddArgList(cmd, "-add-fd", addfdarg, NULL);
8990 vdpafd = -1;
8991 }
8992
8993 if (chardev)
8994 virCommandAddArgList(cmd, "-chardev", chardev, NULL);
8995
8996 if (!(hostnetprops = qemuBuildHostNetProps(net,
8997 tapfdName, tapfdSize,
8998 vhostfdName, vhostfdSize,
8999 slirpfdName, vdpafdName)))
9000 goto cleanup;
9001
9002 if (qemuBuildNetdevCommandlineFromJSON(cmd, hostnetprops, qemuCaps) < 0)
9003 goto cleanup;
9004
9005 /* Possible combinations:
9006 *
9007 * Old way: -netdev type=tap,id=netdev1 \
9008 * -net nic,model=e1000,netdev=netdev1
9009 * New way: -netdev type=tap,id=netdev1 -device e1000,id=netdev1
9010 */
9011 if (qemuDomainSupportsNicdev(def, net)) {
9012 if (qemuCommandAddExtDevice(cmd, &net->info, qemuCaps) < 0)
9013 goto cleanup;
9014
9015 if (!(nicprops = qemuBuildNicDevProps(def, net, net->driver.virtio.queues, qemuCaps)))
9016 goto cleanup;
9017 if (qemuBuildDeviceCommandlineFromJSON(cmd, nicprops, qemuCaps) < 0)
9018 goto cleanup;
9019 } else if (!requireNicdev) {
9020 if (qemuCommandAddExtDevice(cmd, &net->info, qemuCaps) < 0)
9021 goto cleanup;
9022
9023 if (!(nic = qemuBuildLegacyNicStr(net)))
9024 goto cleanup;
9025 virCommandAddArgList(cmd, "-net", nic, NULL);
9026 } else {
9027 virReportError(VIR_ERR_INTERNAL_ERROR,
9028 "%s", _("Nicdev support unavailable"));
9029 goto cleanup;
9030 }
9031
9032 ret = 0;
9033 cleanup:
9034 if (ret < 0) {
9035 virErrorPtr saved_err;
9036
9037 virErrorPreserveLast(&saved_err);
9038 virDomainConfNWFilterTeardown(net);
9039 virErrorRestore(&saved_err);
9040 }
9041 for (i = 0; vhostfd && i < vhostfdSize; i++) {
9042 if (ret < 0)
9043 VIR_FORCE_CLOSE(vhostfd[i]);
9044 if (vhostfdName)
9045 VIR_FREE(vhostfdName[i]);
9046 }
9047 VIR_FREE(vhostfdName);
9048 for (i = 0; tapfd && i < tapfdSize; i++) {
9049 if (ret < 0)
9050 VIR_FORCE_CLOSE(tapfd[i]);
9051 if (tapfdName)
9052 VIR_FREE(tapfdName[i]);
9053 }
9054 VIR_FREE(tapfdName);
9055 VIR_FREE(vhostfd);
9056 VIR_FREE(tapfd);
9057 VIR_FORCE_CLOSE(vdpafd);
9058 return ret;
9059 }
9060
9061
9062 /* NOTE: Not using const virDomainDef here since eventually a call is made
9063 * into qemuSecuritySetTapFDLabel which calls it's driver
9064 * API domainSetSecurityTapFDLabel that doesn't use the const format.
9065 */
9066 static int
qemuBuildNetCommandLine(virQEMUDriver * driver,virDomainObj * vm,virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUCaps * qemuCaps,virNetDevVPortProfileOp vmop,bool standalone,size_t * nnicindexes,int ** nicindexes)9067 qemuBuildNetCommandLine(virQEMUDriver *driver,
9068 virDomainObj *vm,
9069 virLogManager *logManager,
9070 virSecurityManager *secManager,
9071 virCommand *cmd,
9072 virQEMUCaps *qemuCaps,
9073 virNetDevVPortProfileOp vmop,
9074 bool standalone,
9075 size_t *nnicindexes,
9076 int **nicindexes)
9077 {
9078 size_t i;
9079 int last_good_net = -1;
9080 virErrorPtr originalError = NULL;
9081 virDomainDef *def = vm->def;
9082
9083 for (i = 0; i < def->nnets; i++) {
9084 virDomainNetDef *net = def->nets[i];
9085
9086 if (qemuBuildInterfaceCommandLine(driver, vm, logManager, secManager, cmd, net,
9087 qemuCaps, vmop,
9088 standalone, nnicindexes,
9089 nicindexes) < 0)
9090 goto error;
9091
9092 last_good_net = i;
9093 }
9094 return 0;
9095
9096 error:
9097 /* free up any resources in the network driver
9098 * but don't overwrite the original error */
9099 virErrorPreserveLast(&originalError);
9100 for (i = 0; last_good_net != -1 && i <= last_good_net; i++)
9101 virDomainConfNWFilterTeardown(def->nets[i]);
9102 virErrorRestore(&originalError);
9103 return -1;
9104 }
9105
9106
9107 static int
qemuBuildSmartcardCommandLine(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,virQEMUCaps * qemuCaps,bool chardevStdioLogd)9108 qemuBuildSmartcardCommandLine(virLogManager *logManager,
9109 virSecurityManager *secManager,
9110 virCommand *cmd,
9111 virQEMUDriverConfig *cfg,
9112 const virDomainDef *def,
9113 virQEMUCaps *qemuCaps,
9114 bool chardevStdioLogd)
9115 {
9116 g_autoptr(virJSONValue) props = NULL;
9117 virDomainSmartcardDef *smartcard;
9118 const char *contAlias = NULL;
9119 g_autofree char *bus = NULL;
9120
9121 if (!def->nsmartcards)
9122 return 0;
9123
9124 smartcard = def->smartcards[0];
9125
9126 switch (smartcard->type) {
9127 case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
9128 if (virJSONValueObjectAdd(&props,
9129 "s:driver", "ccid-card-emulated",
9130 "s:backend", "nss-emulated",
9131 NULL) < 0)
9132 return -1;
9133
9134 break;
9135
9136 case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES: {
9137 const char *database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
9138
9139 if (smartcard->data.cert.database)
9140 database = smartcard->data.cert.database;
9141
9142 if (virJSONValueObjectAdd(&props,
9143 "s:driver", "ccid-card-emulated",
9144 "s:backend", "certificates",
9145 "s:cert1", smartcard->data.cert.file[0],
9146 "s:cert2", smartcard->data.cert.file[1],
9147 "s:cert3", smartcard->data.cert.file[2],
9148 "s:db", database,
9149 NULL) < 0)
9150 return -1;
9151 }
9152 break;
9153
9154 case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: {
9155 unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT | QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9156 g_autofree char *chardevstr = NULL;
9157 g_autofree char *chardevalias = g_strdup_printf("char%s", smartcard->info.alias);
9158
9159 if (chardevStdioLogd)
9160 cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9161
9162 if (!(chardevstr = qemuBuildChrChardevStr(logManager, secManager,
9163 cmd, cfg, def,
9164 smartcard->data.passthru,
9165 smartcard->info.alias,
9166 qemuCaps, cdevflags))) {
9167 return -1;
9168 }
9169
9170 virCommandAddArgList(cmd, "-chardev", chardevstr, NULL);
9171
9172 if (virJSONValueObjectAdd(&props,
9173 "s:driver", "ccid-card-passthru",
9174 "s:chardev", chardevalias,
9175 NULL) < 0)
9176 return -1;
9177 }
9178 break;
9179
9180 case VIR_DOMAIN_SMARTCARD_TYPE_LAST:
9181 default:
9182 virReportEnumRangeError(virDomainSmartcardType, smartcard->type);
9183 return -1;
9184 }
9185
9186 if (!(contAlias = virDomainControllerAliasFind(def,
9187 VIR_DOMAIN_CONTROLLER_TYPE_CCID,
9188 smartcard->info.addr.ccid.controller)))
9189 return -1;
9190
9191 bus = g_strdup_printf("%s.0", contAlias);
9192
9193 if (virJSONValueObjectAdd(&props,
9194 "s:id", smartcard->info.alias,
9195 "s:bus", bus,
9196 NULL) < 0)
9197 return -1;
9198
9199 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
9200 return -1;
9201
9202 return 0;
9203 }
9204
9205
9206 static virJSONValue *
qemuBuildShmemDevLegacyProps(virDomainDef * def,virDomainShmemDef * shmem)9207 qemuBuildShmemDevLegacyProps(virDomainDef *def,
9208 virDomainShmemDef *shmem)
9209 {
9210 g_autoptr(virJSONValue) props = NULL;
9211 g_autofree char *size = NULL;
9212 const char *shm = NULL;
9213 g_autofree char *chardev = NULL;
9214
9215 /* while this would result in a type error with newer qemus, the 'ivshmem'
9216 * device was removed in qemu-4.0, so for the sake of not changing the
9217 * commandline we do this hack */
9218 size = g_strdup_printf("%llum", shmem->size >> 20);
9219
9220 if (shmem->server.enabled)
9221 chardev = g_strdup_printf("char%s", shmem->info.alias);
9222 else
9223 shm = shmem->name;
9224
9225 if (virJSONValueObjectAdd(&props,
9226 "s:driver", "ivshmem",
9227 "s:id", shmem->info.alias,
9228 "s:size", size,
9229 "S:shm", shm,
9230 "S:chardev", chardev,
9231 "B:msi", shmem->msi.enabled,
9232 "p:vectors", shmem->msi.vectors,
9233 "T:ioeventfd", shmem->msi.ioeventfd,
9234 NULL) < 0)
9235 return NULL;
9236
9237 if (qemuBuildDeviceAddressProps(props, def, &shmem->info) < 0)
9238 return NULL;
9239
9240 return g_steal_pointer(&props);
9241 }
9242
9243
9244 virJSONValue *
qemuBuildShmemDevProps(virDomainDef * def,virDomainShmemDef * shmem)9245 qemuBuildShmemDevProps(virDomainDef *def,
9246 virDomainShmemDef *shmem)
9247 {
9248 g_autoptr(virJSONValue) props = NULL;
9249 g_autofree char *chardev = NULL;
9250 g_autofree char *memdev = NULL;
9251 virTristateSwitch master = VIR_TRISTATE_SWITCH_ABSENT;
9252
9253 if (shmem->server.enabled) {
9254 chardev = g_strdup_printf("char%s", shmem->info.alias);
9255 } else {
9256 memdev = g_strdup_printf("shmmem-%s", shmem->info.alias);
9257
9258 switch (shmem->role) {
9259 case VIR_DOMAIN_SHMEM_ROLE_MASTER:
9260 master = VIR_TRISTATE_SWITCH_ON;
9261 break;
9262 case VIR_DOMAIN_SHMEM_ROLE_PEER:
9263 master = VIR_TRISTATE_SWITCH_OFF;
9264 break;
9265 case VIR_DOMAIN_SHMEM_ROLE_DEFAULT:
9266 case VIR_DOMAIN_SHMEM_ROLE_LAST:
9267 break;
9268 }
9269 }
9270
9271 if (virJSONValueObjectAdd(&props,
9272 "s:driver", virDomainShmemModelTypeToString(shmem->model),
9273 "s:id", shmem->info.alias,
9274 "S:chardev", chardev,
9275 "S:memdev", memdev,
9276 "S:master", qemuOnOffAuto(master),
9277 "p:vectors", shmem->msi.vectors,
9278 "T:ioeventfd", shmem->msi.ioeventfd,
9279 NULL) < 0)
9280 return NULL;
9281
9282 if (qemuBuildDeviceAddressProps(props, def, &shmem->info) < 0)
9283 return NULL;
9284
9285 return g_steal_pointer(&props);
9286 }
9287
9288
9289 virJSONValue *
qemuBuildShmemBackendMemProps(virDomainShmemDef * shmem)9290 qemuBuildShmemBackendMemProps(virDomainShmemDef *shmem)
9291 {
9292 g_autofree char *mem_alias = NULL;
9293 g_autofree char *mem_path = NULL;
9294 virJSONValue *ret = NULL;
9295
9296 mem_path = g_strdup_printf("/dev/shm/%s", shmem->name);
9297
9298 mem_alias = g_strdup_printf("shmmem-%s", shmem->info.alias);
9299
9300 qemuMonitorCreateObjectProps(&ret, "memory-backend-file", mem_alias,
9301 "s:mem-path", mem_path,
9302 "U:size", shmem->size,
9303 "b:share", true,
9304 NULL);
9305
9306 return ret;
9307 }
9308
9309
9310 static int
qemuBuildShmemCommandLine(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,virDomainDef * def,virDomainShmemDef * shmem,virQEMUCaps * qemuCaps,bool chardevStdioLogd)9311 qemuBuildShmemCommandLine(virLogManager *logManager,
9312 virSecurityManager *secManager,
9313 virCommand *cmd,
9314 virQEMUDriverConfig *cfg,
9315 virDomainDef *def,
9316 virDomainShmemDef *shmem,
9317 virQEMUCaps *qemuCaps,
9318 bool chardevStdioLogd)
9319 {
9320 g_autoptr(virJSONValue) memProps = NULL;
9321 g_autoptr(virJSONValue) devProps = NULL;
9322 g_autofree char *chardev = NULL;
9323 unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
9324 QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9325 if (chardevStdioLogd)
9326 cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9327
9328 if (shmem->size) {
9329 /*
9330 * Thanks to our parsing code, we have a guarantee that the
9331 * size is power of two and is at least a mebibyte in size.
9332 * But because it may change in the future, the checks are
9333 * doubled in here.
9334 */
9335 if (shmem->size & (shmem->size - 1)) {
9336 virReportError(VIR_ERR_XML_ERROR, "%s",
9337 _("shmem size must be a power of two"));
9338 return -1;
9339 }
9340 if (shmem->size < 1024 * 1024) {
9341 virReportError(VIR_ERR_XML_ERROR, "%s",
9342 _("shmem size must be at least 1 MiB (1024 KiB)"));
9343 return -1;
9344 }
9345 }
9346
9347 if (shmem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
9348 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9349 _("only 'pci' addresses are supported for the "
9350 "shared memory device"));
9351 return -1;
9352 }
9353
9354 switch (shmem->model) {
9355 case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
9356 devProps = qemuBuildShmemDevLegacyProps(def, shmem);
9357 break;
9358
9359 case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
9360 if (!(memProps = qemuBuildShmemBackendMemProps(shmem)))
9361 return -1;
9362
9363 if (qemuBuildObjectCommandlineFromJSON(cmd, memProps, qemuCaps) < 0)
9364 return -1;
9365
9366 G_GNUC_FALLTHROUGH;
9367 case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL:
9368 devProps = qemuBuildShmemDevProps(def, shmem);
9369 break;
9370
9371 case VIR_DOMAIN_SHMEM_MODEL_LAST:
9372 break;
9373 }
9374
9375 if (!devProps)
9376 return -1;
9377
9378 if (qemuCommandAddExtDevice(cmd, &shmem->info, qemuCaps) < 0)
9379 return -1;
9380
9381 if (qemuBuildDeviceCommandlineFromJSON(cmd, devProps, qemuCaps) < 0)
9382 return -1;
9383
9384 if (shmem->server.enabled) {
9385 chardev = qemuBuildChrChardevStr(logManager, secManager,
9386 cmd, cfg, def,
9387 shmem->server.chr,
9388 shmem->info.alias, qemuCaps,
9389 cdevflags);
9390 if (!chardev)
9391 return -1;
9392
9393 virCommandAddArgList(cmd, "-chardev", chardev, NULL);
9394 }
9395
9396 return 0;
9397 }
9398
9399
9400 static virQEMUCapsFlags
qemuChrSerialTargetModelToCaps(virDomainChrSerialTargetModel targetModel)9401 qemuChrSerialTargetModelToCaps(virDomainChrSerialTargetModel targetModel)
9402 {
9403 switch (targetModel) {
9404 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
9405 return QEMU_CAPS_DEVICE_ISA_SERIAL;
9406 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_USB_SERIAL:
9407 return QEMU_CAPS_DEVICE_USB_SERIAL;
9408 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PCI_SERIAL:
9409 return QEMU_CAPS_DEVICE_PCI_SERIAL;
9410 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
9411 return QEMU_CAPS_DEVICE_SPAPR_VTY;
9412 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
9413 return QEMU_CAPS_DEVICE_SCLPCONSOLE;
9414 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
9415 return QEMU_CAPS_DEVICE_SCLPLMCONSOLE;
9416 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
9417 return QEMU_CAPS_DEVICE_PL011;
9418 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
9419 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
9420 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
9421 break;
9422 }
9423
9424 return 0;
9425 }
9426
9427
9428 static int
qemuBuildChrDeviceCommandLine(virCommand * cmd,const virDomainDef * def,virDomainChrDef * chr,virQEMUCaps * qemuCaps)9429 qemuBuildChrDeviceCommandLine(virCommand *cmd,
9430 const virDomainDef *def,
9431 virDomainChrDef *chr,
9432 virQEMUCaps *qemuCaps)
9433 {
9434 g_autoptr(virJSONValue) props = NULL;
9435
9436 if (!(props = qemuBuildChrDeviceProps(def, chr, qemuCaps)))
9437 return -1;
9438
9439 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
9440 return -1;
9441
9442 return 0;
9443 }
9444
9445
9446 static bool
qemuChrIsPlatformDevice(const virDomainDef * def,virDomainChrDef * chr)9447 qemuChrIsPlatformDevice(const virDomainDef *def,
9448 virDomainChrDef *chr)
9449 {
9450 if (def->os.arch == VIR_ARCH_ARMV6L ||
9451 def->os.arch == VIR_ARCH_ARMV7L ||
9452 def->os.arch == VIR_ARCH_AARCH64) {
9453
9454 /* pl011 (used on mach-virt) is a platform device */
9455 if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
9456 chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM &&
9457 chr->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011) {
9458 return true;
9459 }
9460 }
9461
9462 if (ARCH_IS_RISCV(def->os.arch)) {
9463
9464 /* 16550a (used by riscv/virt guests) is a platform device */
9465 if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
9466 chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM &&
9467 chr->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A) {
9468 return true;
9469 }
9470 }
9471
9472 /* If we got all the way here and we're still stuck with the default
9473 * target type for a serial device, it means we have no clue what kind of
9474 * device we're talking about and we must treat it as a platform device. */
9475 if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
9476 chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE) {
9477 return true;
9478 }
9479
9480 return false;
9481 }
9482
9483
9484 static int
qemuBuildSerialCommandLine(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,virQEMUCaps * qemuCaps,bool chardevStdioLogd)9485 qemuBuildSerialCommandLine(virLogManager *logManager,
9486 virSecurityManager *secManager,
9487 virCommand *cmd,
9488 virQEMUDriverConfig *cfg,
9489 const virDomainDef *def,
9490 virQEMUCaps *qemuCaps,
9491 bool chardevStdioLogd)
9492 {
9493 size_t i;
9494 bool havespice = false;
9495 unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
9496 QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9497 if (chardevStdioLogd)
9498 cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9499
9500 if (def->nserials) {
9501 for (i = 0; i < def->ngraphics && !havespice; i++) {
9502 if (def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
9503 havespice = true;
9504 }
9505 }
9506
9507 for (i = 0; i < def->nserials; i++) {
9508 virDomainChrDef *serial = def->serials[i];
9509 g_autofree char *devstr = NULL;
9510
9511 if (serial->source->type == VIR_DOMAIN_CHR_TYPE_SPICEPORT && !havespice)
9512 continue;
9513
9514 if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
9515 cmd, cfg, def,
9516 serial->source,
9517 serial->info.alias,
9518 qemuCaps, cdevflags)))
9519 return -1;
9520 virCommandAddArg(cmd, "-chardev");
9521 virCommandAddArg(cmd, devstr);
9522
9523 /* If the device is not a platform device, build the devstr */
9524 if (!qemuChrIsPlatformDevice(def, serial)) {
9525 if (qemuBuildChrDeviceCommandLine(cmd, def, serial, qemuCaps) < 0)
9526 return -1;
9527 } else {
9528 virQEMUCapsFlags caps;
9529
9530 caps = qemuChrSerialTargetModelToCaps(serial->targetModel);
9531
9532 if (caps && !virQEMUCapsGet(qemuCaps, caps)) {
9533 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9534 _("'%s' is not supported in this QEMU binary"),
9535 virDomainChrSerialTargetModelTypeToString(serial->targetModel));
9536 return -1;
9537 }
9538
9539 virCommandAddArg(cmd, "-serial");
9540 virCommandAddArgFormat(cmd, "chardev:char%s", serial->info.alias);
9541 }
9542 }
9543
9544 return 0;
9545 }
9546
9547
9548 static int
qemuBuildParallelsCommandLine(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,virQEMUCaps * qemuCaps,bool chardevStdioLogd)9549 qemuBuildParallelsCommandLine(virLogManager *logManager,
9550 virSecurityManager *secManager,
9551 virCommand *cmd,
9552 virQEMUDriverConfig *cfg,
9553 const virDomainDef *def,
9554 virQEMUCaps *qemuCaps,
9555 bool chardevStdioLogd)
9556 {
9557 size_t i;
9558 unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
9559 QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9560 if (chardevStdioLogd)
9561 cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9562
9563 for (i = 0; i < def->nparallels; i++) {
9564 virDomainChrDef *parallel = def->parallels[i];
9565 g_autofree char *devstr = NULL;
9566
9567 if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
9568 cmd, cfg, def,
9569 parallel->source,
9570 parallel->info.alias,
9571 qemuCaps, cdevflags)))
9572 return -1;
9573 virCommandAddArg(cmd, "-chardev");
9574 virCommandAddArg(cmd, devstr);
9575
9576 if (qemuBuildChrDeviceCommandLine(cmd, def, parallel,
9577 qemuCaps) < 0)
9578 return -1;
9579 }
9580
9581 return 0;
9582 }
9583
9584
9585 static int
qemuBuildChannelsCommandLine(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,virQEMUCaps * qemuCaps,bool chardevStdioLogd)9586 qemuBuildChannelsCommandLine(virLogManager *logManager,
9587 virSecurityManager *secManager,
9588 virCommand *cmd,
9589 virQEMUDriverConfig *cfg,
9590 const virDomainDef *def,
9591 virQEMUCaps *qemuCaps,
9592 bool chardevStdioLogd)
9593 {
9594 size_t i;
9595 unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
9596 QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9597 if (chardevStdioLogd)
9598 cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9599
9600 for (i = 0; i < def->nchannels; i++) {
9601 virDomainChrDef *channel = def->channels[i];
9602 g_autofree char *chardevstr = NULL;
9603 g_autoptr(virJSONValue) netdevprops = NULL;
9604
9605 if (!(chardevstr = qemuBuildChrChardevStr(logManager, secManager,
9606 cmd, cfg, def,
9607 channel->source,
9608 channel->info.alias,
9609 qemuCaps, cdevflags)))
9610 return -1;
9611
9612 virCommandAddArg(cmd, "-chardev");
9613 virCommandAddArg(cmd, chardevstr);
9614
9615 switch ((virDomainChrChannelTargetType) channel->targetType) {
9616 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
9617 if (!(netdevprops = qemuBuildChannelGuestfwdNetdevProps(channel)))
9618 return -1;
9619
9620 if (qemuBuildNetdevCommandlineFromJSON(cmd, netdevprops, qemuCaps) < 0)
9621 return -1;
9622 break;
9623
9624 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
9625 if (qemuBuildChrDeviceCommandLine(cmd, def, channel, qemuCaps) < 0)
9626 return -1;
9627 break;
9628
9629 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
9630 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE:
9631 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST:
9632 return -1;
9633 }
9634 }
9635
9636 return 0;
9637 }
9638
9639
9640 static int
qemuBuildConsoleCommandLine(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,virQEMUCaps * qemuCaps,bool chardevStdioLogd)9641 qemuBuildConsoleCommandLine(virLogManager *logManager,
9642 virSecurityManager *secManager,
9643 virCommand *cmd,
9644 virQEMUDriverConfig *cfg,
9645 const virDomainDef *def,
9646 virQEMUCaps *qemuCaps,
9647 bool chardevStdioLogd)
9648 {
9649 size_t i;
9650 unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
9651 QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9652 if (chardevStdioLogd)
9653 cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9654
9655 /* Explicit console devices */
9656 for (i = 0; i < def->nconsoles; i++) {
9657 virDomainChrDef *console = def->consoles[i];
9658 char *devstr;
9659
9660 switch (console->targetType) {
9661 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLP:
9662 if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
9663 cmd, cfg, def,
9664 console->source,
9665 console->info.alias,
9666 qemuCaps, cdevflags)))
9667 return -1;
9668 virCommandAddArg(cmd, "-chardev");
9669 virCommandAddArg(cmd, devstr);
9670 VIR_FREE(devstr);
9671
9672 if (qemuBuildChrDeviceCommandLine(cmd, def, console, qemuCaps) < 0)
9673 return -1;
9674 break;
9675
9676 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLPLM:
9677 if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
9678 cmd, cfg, def,
9679 console->source,
9680 console->info.alias,
9681 qemuCaps, cdevflags)))
9682 return -1;
9683 virCommandAddArg(cmd, "-chardev");
9684 virCommandAddArg(cmd, devstr);
9685 VIR_FREE(devstr);
9686
9687 if (qemuBuildChrDeviceCommandLine(cmd, def, console, qemuCaps) < 0)
9688 return -1;
9689 break;
9690
9691 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO:
9692 if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
9693 cmd, cfg, def,
9694 console->source,
9695 console->info.alias,
9696 qemuCaps, cdevflags)))
9697 return -1;
9698 virCommandAddArg(cmd, "-chardev");
9699 virCommandAddArg(cmd, devstr);
9700 VIR_FREE(devstr);
9701
9702 if (qemuBuildChrDeviceCommandLine(cmd, def, console, qemuCaps) < 0)
9703 return -1;
9704 break;
9705
9706 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
9707 break;
9708
9709 default:
9710 return -1;
9711 }
9712 }
9713
9714 return 0;
9715 }
9716
9717
9718 virJSONValue *
qemuBuildRedirdevDevProps(const virDomainDef * def,virDomainRedirdevDef * dev)9719 qemuBuildRedirdevDevProps(const virDomainDef *def,
9720 virDomainRedirdevDef *dev)
9721 {
9722 g_autoptr(virJSONValue) props = NULL;
9723 virDomainRedirFilterDef *redirfilter = def->redirfilter;
9724 g_autofree char *chardev = g_strdup_printf("char%s", dev->info.alias);
9725 g_autofree char *filter = NULL;
9726
9727 if (redirfilter) {
9728 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9729 size_t i;
9730
9731 for (i = 0; i < redirfilter->nusbdevs; i++) {
9732 virDomainRedirFilterUSBDevDef *usbdev = redirfilter->usbdevs[i];
9733 if (usbdev->usbClass >= 0)
9734 virBufferAsprintf(&buf, "0x%02X:", usbdev->usbClass);
9735 else
9736 virBufferAddLit(&buf, "-1:");
9737
9738 if (usbdev->vendor >= 0)
9739 virBufferAsprintf(&buf, "0x%04X:", usbdev->vendor);
9740 else
9741 virBufferAddLit(&buf, "-1:");
9742
9743 if (usbdev->product >= 0)
9744 virBufferAsprintf(&buf, "0x%04X:", usbdev->product);
9745 else
9746 virBufferAddLit(&buf, "-1:");
9747
9748 if (usbdev->version >= 0)
9749 virBufferAsprintf(&buf, "0x%04X:", usbdev->version);
9750 else
9751 virBufferAddLit(&buf, "-1:");
9752
9753 virBufferAsprintf(&buf, "%u|", usbdev->allow);
9754 }
9755 virBufferTrim(&buf, "|");
9756
9757 filter = virBufferContentAndReset(&buf);
9758 }
9759
9760 if (virJSONValueObjectAdd(&props,
9761 "s:driver", "usb-redir",
9762 "s:chardev", chardev,
9763 "s:id", dev->info.alias,
9764 "S:filter", filter,
9765 "p:bootindex", dev->info.bootIndex,
9766 NULL) < 0)
9767 return NULL;
9768
9769 if (qemuBuildDeviceAddressProps(props, def, &dev->info) < 0)
9770 return NULL;
9771
9772 return g_steal_pointer(&props);
9773 }
9774
9775
9776 static int
qemuBuildRedirdevCommandLine(virLogManager * logManager,virSecurityManager * secManager,virCommand * cmd,virQEMUDriverConfig * cfg,const virDomainDef * def,virQEMUCaps * qemuCaps,bool chardevStdioLogd)9777 qemuBuildRedirdevCommandLine(virLogManager *logManager,
9778 virSecurityManager *secManager,
9779 virCommand *cmd,
9780 virQEMUDriverConfig *cfg,
9781 const virDomainDef *def,
9782 virQEMUCaps *qemuCaps,
9783 bool chardevStdioLogd)
9784 {
9785 size_t i;
9786 unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
9787 QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9788 if (chardevStdioLogd)
9789 cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9790
9791 for (i = 0; i < def->nredirdevs; i++) {
9792 virDomainRedirdevDef *redirdev = def->redirdevs[i];
9793 g_autoptr(virJSONValue) devprops = NULL;
9794 char *devstr;
9795
9796 if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
9797 cmd, cfg, def,
9798 redirdev->source,
9799 redirdev->info.alias,
9800 qemuCaps, cdevflags))) {
9801 return -1;
9802 }
9803
9804 virCommandAddArg(cmd, "-chardev");
9805 virCommandAddArg(cmd, devstr);
9806 VIR_FREE(devstr);
9807
9808 if (!(devprops = qemuBuildRedirdevDevProps(def, redirdev)))
9809 return -1;
9810
9811 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
9812 return -1;
9813 }
9814
9815 return 0;
9816 }
9817
9818
9819 static void
qemuBuldDomainLoaderPflashCommandLine(virCommand * cmd,virDomainLoaderDef * loader,virQEMUCaps * qemuCaps)9820 qemuBuldDomainLoaderPflashCommandLine(virCommand *cmd,
9821 virDomainLoaderDef *loader,
9822 virQEMUCaps *qemuCaps)
9823 {
9824 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9825 int unit = 0;
9826
9827 if (loader->secure == VIR_TRISTATE_BOOL_YES) {
9828 virCommandAddArgList(cmd,
9829 "-global",
9830 "driver=cfi.pflash01,property=secure,value=on",
9831 NULL);
9832 }
9833
9834 /* with blockdev we instantiate the pflash when formatting -machine */
9835 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV))
9836 return;
9837
9838 virBufferAddLit(&buf, "file=");
9839 virQEMUBuildBufferEscapeComma(&buf, loader->path);
9840 virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit);
9841 unit++;
9842
9843 if (loader->readonly) {
9844 virBufferAsprintf(&buf, ",readonly=%s",
9845 virTristateSwitchTypeToString(loader->readonly));
9846 }
9847
9848 virCommandAddArg(cmd, "-drive");
9849 virCommandAddArgBuffer(cmd, &buf);
9850
9851 if (loader->nvram) {
9852 virBufferAddLit(&buf, "file=");
9853 virQEMUBuildBufferEscapeComma(&buf, loader->nvram);
9854 virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit);
9855
9856 virCommandAddArg(cmd, "-drive");
9857 virCommandAddArgBuffer(cmd, &buf);
9858 }
9859 }
9860
9861
9862 static void
qemuBuildDomainLoaderCommandLine(virCommand * cmd,virDomainDef * def,virQEMUCaps * qemuCaps)9863 qemuBuildDomainLoaderCommandLine(virCommand *cmd,
9864 virDomainDef *def,
9865 virQEMUCaps *qemuCaps)
9866 {
9867 virDomainLoaderDef *loader = def->os.loader;
9868
9869 if (!loader)
9870 return;
9871
9872 switch ((virDomainLoader) loader->type) {
9873 case VIR_DOMAIN_LOADER_TYPE_ROM:
9874 virCommandAddArg(cmd, "-bios");
9875 virCommandAddArg(cmd, loader->path);
9876 break;
9877
9878 case VIR_DOMAIN_LOADER_TYPE_PFLASH:
9879 qemuBuldDomainLoaderPflashCommandLine(cmd, loader, qemuCaps);
9880 break;
9881
9882 case VIR_DOMAIN_LOADER_TYPE_NONE:
9883 case VIR_DOMAIN_LOADER_TYPE_LAST:
9884 /* nada */
9885 break;
9886 }
9887 }
9888
9889
9890 static int
qemuBuildTPMDevCmd(virCommand * cmd,const virDomainDef * def,virDomainTPMDef * tpm,virQEMUCaps * qemuCaps)9891 qemuBuildTPMDevCmd(virCommand *cmd,
9892 const virDomainDef *def,
9893 virDomainTPMDef *tpm,
9894 virQEMUCaps *qemuCaps)
9895 {
9896 g_autoptr(virJSONValue) props = NULL;
9897 const char *model = virDomainTPMModelTypeToString(tpm->model);
9898 g_autofree char *tpmdev = g_strdup_printf("tpm-%s", tpm->info.alias);
9899
9900 if (tpm->model == VIR_DOMAIN_TPM_MODEL_TIS && def->os.arch == VIR_ARCH_AARCH64)
9901 model = "tpm-tis-device";
9902
9903 if (virJSONValueObjectAdd(&props,
9904 "s:driver", model,
9905 "s:tpmdev", tpmdev,
9906 "s:id", tpm->info.alias,
9907 NULL) < 0)
9908 return -1;
9909
9910 if (qemuBuildDeviceAddressProps(props, def, &tpm->info) < 0)
9911 return -1;
9912
9913 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
9914 return -1;
9915
9916 return 0;
9917 }
9918
9919
9920 /* this function is exported so that tests can mock the FDs */
9921 int
qemuBuildTPMOpenBackendFDs(const char * tpmdev,const char * cancel_path,int * tpmfd,int * cancelfd)9922 qemuBuildTPMOpenBackendFDs(const char *tpmdev,
9923 const char *cancel_path,
9924 int *tpmfd,
9925 int *cancelfd)
9926 {
9927 if ((*tpmfd = open(tpmdev, O_RDWR)) < 0) {
9928 virReportSystemError(errno, _("Could not open TPM device %s"),
9929 tpmdev);
9930 return -1;
9931 }
9932
9933 if ((*cancelfd = open(cancel_path, O_WRONLY)) < 0) {
9934 virReportSystemError(errno,
9935 _("Could not open TPM device's cancel "
9936 "path %s"), cancel_path);
9937 VIR_FORCE_CLOSE(*tpmfd);
9938 return -1;
9939 }
9940
9941 return 0;
9942 }
9943
9944
9945 static char *
qemuBuildTPMBackendStr(virCommand * cmd,virDomainTPMDef * tpm,int * tpmfd,int * cancelfd,char ** chardev)9946 qemuBuildTPMBackendStr(virCommand *cmd,
9947 virDomainTPMDef *tpm,
9948 int *tpmfd,
9949 int *cancelfd,
9950 char **chardev)
9951 {
9952 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9953 g_autofree char *cancel_path = NULL;
9954 g_autofree char *devset = NULL;
9955 g_autofree char *cancelset = NULL;
9956 const char *tpmdev;
9957
9958 *tpmfd = -1;
9959 *cancelfd = -1;
9960
9961 virBufferAsprintf(&buf, "%s", virDomainTPMBackendTypeToString(tpm->type));
9962 virBufferAsprintf(&buf, ",id=tpm-%s", tpm->info.alias);
9963
9964 switch (tpm->type) {
9965 case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
9966 tpmdev = tpm->data.passthrough.source->data.file.path;
9967 if (!(cancel_path = virTPMCreateCancelPath(tpmdev)))
9968 return NULL;
9969
9970 if (qemuBuildTPMOpenBackendFDs(tpmdev, cancel_path, tpmfd, cancelfd) < 0)
9971 return NULL;
9972
9973 virCommandPassFD(cmd, *tpmfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
9974 virCommandPassFD(cmd, *cancelfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
9975
9976 if (!(devset = qemuVirCommandGetDevSet(cmd, *tpmfd)) ||
9977 !(cancelset = qemuVirCommandGetDevSet(cmd, *cancelfd)))
9978 return NULL;
9979
9980 virBufferAddLit(&buf, ",path=");
9981 virQEMUBuildBufferEscapeComma(&buf, devset);
9982
9983 virBufferAddLit(&buf, ",cancel-path=");
9984 virQEMUBuildBufferEscapeComma(&buf, cancelset);
9985
9986 break;
9987 case VIR_DOMAIN_TPM_TYPE_EMULATOR:
9988 virBufferAddLit(&buf, ",chardev=chrtpm");
9989
9990 *chardev = g_strdup_printf("socket,id=chrtpm,path=%s",
9991 tpm->data.emulator.source->data.nix.path);
9992
9993 break;
9994 case VIR_DOMAIN_TPM_TYPE_LAST:
9995 return NULL;
9996 }
9997
9998 return virBufferContentAndReset(&buf);
9999 }
10000
10001
10002 static int
qemuBuildTPMCommandLine(virCommand * cmd,const virDomainDef * def,virDomainTPMDef * tpm,virQEMUCaps * qemuCaps)10003 qemuBuildTPMCommandLine(virCommand *cmd,
10004 const virDomainDef *def,
10005 virDomainTPMDef *tpm,
10006 virQEMUCaps *qemuCaps)
10007 {
10008 char *optstr;
10009 g_autofree char *chardev = NULL;
10010 int tpmfd = -1;
10011 int cancelfd = -1;
10012 char *fdset;
10013
10014 if (!(optstr = qemuBuildTPMBackendStr(cmd, tpm,
10015 &tpmfd, &cancelfd,
10016 &chardev)))
10017 return -1;
10018
10019 virCommandAddArgList(cmd, "-tpmdev", optstr, NULL);
10020 VIR_FREE(optstr);
10021
10022 if (chardev)
10023 virCommandAddArgList(cmd, "-chardev", chardev, NULL);
10024
10025 if (tpmfd >= 0) {
10026 fdset = qemuVirCommandGetFDSet(cmd, tpmfd);
10027 if (!fdset)
10028 return -1;
10029
10030 virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
10031 VIR_FREE(fdset);
10032 }
10033
10034 if (cancelfd >= 0) {
10035 fdset = qemuVirCommandGetFDSet(cmd, cancelfd);
10036 if (!fdset)
10037 return -1;
10038
10039 virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
10040 VIR_FREE(fdset);
10041 }
10042
10043 if (qemuBuildTPMDevCmd(cmd, def, tpm, qemuCaps) < 0)
10044 return -1;
10045
10046 return 0;
10047 }
10048
10049
10050 static int
qemuBuildTPMProxyCommandLine(virCommand * cmd,virDomainTPMDef * tpm,virQEMUCaps * qemuCaps)10051 qemuBuildTPMProxyCommandLine(virCommand *cmd,
10052 virDomainTPMDef *tpm,
10053 virQEMUCaps *qemuCaps)
10054 {
10055 g_autoptr(virJSONValue) props = NULL;
10056
10057 if (virJSONValueObjectAdd(&props,
10058 "s:driver", virDomainTPMModelTypeToString(tpm->model),
10059 "s:id", tpm->info.alias,
10060 "s:host-path", tpm->data.passthrough.source->data.file.path,
10061 NULL) < 0)
10062 return -1;
10063
10064 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
10065 return -1;
10066
10067 return 0;
10068 }
10069
10070
10071 static int
qemuBuildTPMsCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)10072 qemuBuildTPMsCommandLine(virCommand *cmd,
10073 const virDomainDef *def,
10074 virQEMUCaps *qemuCaps)
10075 {
10076 size_t i;
10077
10078 for (i = 0; i < def->ntpms; i++) {
10079 if (def->tpms[i]->model == VIR_DOMAIN_TPM_MODEL_SPAPR_PROXY) {
10080 if (qemuBuildTPMProxyCommandLine(cmd, def->tpms[i], qemuCaps) < 0)
10081 return -1;
10082 } else if (qemuBuildTPMCommandLine(cmd, def,
10083 def->tpms[i], qemuCaps) < 0) {
10084 return -1;
10085 }
10086 }
10087
10088 return 0;
10089 }
10090
10091
10092 static int
qemuBuildSEVCommandLine(virDomainObj * vm,virCommand * cmd,virDomainSEVDef * sev)10093 qemuBuildSEVCommandLine(virDomainObj *vm, virCommand *cmd,
10094 virDomainSEVDef *sev)
10095 {
10096 g_autoptr(virJSONValue) props = NULL;
10097 qemuDomainObjPrivate *priv = vm->privateData;
10098 g_autofree char *dhpath = NULL;
10099 g_autofree char *sessionpath = NULL;
10100
10101 VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
10102 sev->policy, sev->cbitpos, sev->reduced_phys_bits);
10103
10104 if (sev->dh_cert)
10105 dhpath = g_strdup_printf("%s/dh_cert.base64", priv->libDir);
10106
10107 if (sev->session)
10108 sessionpath = g_strdup_printf("%s/session.base64", priv->libDir);
10109
10110 if (qemuMonitorCreateObjectProps(&props, "sev-guest", "lsec0",
10111 "u:cbitpos", sev->cbitpos,
10112 "u:reduced-phys-bits", sev->reduced_phys_bits,
10113 "u:policy", sev->policy,
10114 "S:dh-cert-file", dhpath,
10115 "S:session-file", sessionpath,
10116 NULL) < 0)
10117 return -1;
10118
10119 if (qemuBuildObjectCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0)
10120 return -1;
10121
10122 return 0;
10123 }
10124
10125
10126 static int
qemuBuildPVCommandLine(virDomainObj * vm,virCommand * cmd)10127 qemuBuildPVCommandLine(virDomainObj *vm, virCommand *cmd)
10128 {
10129 g_autoptr(virJSONValue) props = NULL;
10130 qemuDomainObjPrivate *priv = vm->privateData;
10131
10132 if (qemuMonitorCreateObjectProps(&props, "s390-pv-guest", "lsec0",
10133 NULL) < 0)
10134 return -1;
10135
10136 if (qemuBuildObjectCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0)
10137 return -1;
10138
10139 return 0;
10140 }
10141
10142
10143 static int
qemuBuildSecCommandLine(virDomainObj * vm,virCommand * cmd,virDomainSecDef * sec)10144 qemuBuildSecCommandLine(virDomainObj *vm, virCommand *cmd,
10145 virDomainSecDef *sec)
10146 {
10147 if (!sec)
10148 return 0;
10149
10150 switch ((virDomainLaunchSecurity) sec->sectype) {
10151 case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
10152 return qemuBuildSEVCommandLine(vm, cmd, &sec->data.sev);
10153 break;
10154 case VIR_DOMAIN_LAUNCH_SECURITY_PV:
10155 return qemuBuildPVCommandLine(vm, cmd);
10156 break;
10157 case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
10158 case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
10159 virReportEnumRangeError(virDomainLaunchSecurity, sec->sectype);
10160 return -1;
10161 }
10162
10163 return 0;
10164 }
10165
10166
10167 static int
qemuBuildVMCoreInfoCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)10168 qemuBuildVMCoreInfoCommandLine(virCommand *cmd,
10169 const virDomainDef *def,
10170 virQEMUCaps *qemuCaps)
10171 {
10172 g_autoptr(virJSONValue) props = NULL;
10173
10174 if (def->features[VIR_DOMAIN_FEATURE_VMCOREINFO] != VIR_TRISTATE_SWITCH_ON)
10175 return 0;
10176
10177 if (virJSONValueObjectAdd(&props,
10178 "s:driver", "vmcoreinfo",
10179 NULL) < 0)
10180 return -1;
10181
10182 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
10183 return -1;
10184
10185 return 0;
10186 }
10187
10188
10189 static int
qemuBuildPanicCommandLine(virCommand * cmd,const virDomainDef * def,virQEMUCaps * qemuCaps)10190 qemuBuildPanicCommandLine(virCommand *cmd,
10191 const virDomainDef *def,
10192 virQEMUCaps *qemuCaps)
10193 {
10194 size_t i;
10195
10196 for (i = 0; i < def->npanics; i++) {
10197 switch ((virDomainPanicModel) def->panics[i]->model) {
10198 case VIR_DOMAIN_PANIC_MODEL_ISA: {
10199 g_autoptr(virJSONValue) props = NULL;
10200
10201 if (virJSONValueObjectAdd(&props,
10202 "s:driver", "pvpanic",
10203 NULL) < 0)
10204 return -1;
10205
10206 /* pvpanic uses 'ioport' instead of 'iobase' so
10207 * qemuBuildDeviceAddressProps can't be used */
10208 if (def->panics[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA) {
10209 if (virJSONValueObjectAdd(&props,
10210 "u:ioport", def->panics[i]->info.addr.isa.iobase,
10211 NULL) < 0)
10212 return -1;
10213 }
10214
10215 if (qemuBuildDeviceCommandlineFromJSON(cmd, props, qemuCaps) < 0)
10216 return -1;
10217
10218 break;
10219 }
10220
10221 case VIR_DOMAIN_PANIC_MODEL_S390:
10222 case VIR_DOMAIN_PANIC_MODEL_HYPERV:
10223 case VIR_DOMAIN_PANIC_MODEL_PSERIES:
10224 /* default model value was changed before in post parse */
10225 case VIR_DOMAIN_PANIC_MODEL_DEFAULT:
10226 case VIR_DOMAIN_PANIC_MODEL_LAST:
10227 break;
10228 }
10229 }
10230
10231 return 0;
10232 }
10233
10234
10235 static virJSONValue *
qemuBuildPRManagerInfoPropsInternal(const char * alias,const char * path)10236 qemuBuildPRManagerInfoPropsInternal(const char *alias,
10237 const char *path)
10238 {
10239 virJSONValue *ret = NULL;
10240
10241 if (qemuMonitorCreateObjectProps(&ret,
10242 "pr-manager-helper", alias,
10243 "s:path", path, NULL) < 0)
10244 return NULL;
10245
10246 return ret;
10247 }
10248
10249
10250 /**
10251 * qemuBuildPRManagedManagerInfoProps:
10252 *
10253 * Build the JSON properties for the pr-manager object corresponding to the PR
10254 * daemon managed by libvirt.
10255 */
10256 virJSONValue *
qemuBuildPRManagedManagerInfoProps(qemuDomainObjPrivate * priv)10257 qemuBuildPRManagedManagerInfoProps(qemuDomainObjPrivate *priv)
10258 {
10259 g_autofree char *path = NULL;
10260
10261 if (!(path = qemuDomainGetManagedPRSocketPath(priv)))
10262 return NULL;
10263
10264 return qemuBuildPRManagerInfoPropsInternal(qemuDomainGetManagedPRAlias(),
10265 path);
10266 }
10267
10268
10269 /**
10270 * qemuBuildPRManagerInfoProps:
10271 * @src: storage source
10272 *
10273 * Build the JSON properties for the pr-manager object.
10274 */
10275 virJSONValue *
qemuBuildPRManagerInfoProps(virStorageSource * src)10276 qemuBuildPRManagerInfoProps(virStorageSource *src)
10277 {
10278 return qemuBuildPRManagerInfoPropsInternal(src->pr->mgralias, src->pr->path);
10279 }
10280
10281
10282 static int
qemuBuildManagedPRCommandLine(virCommand * cmd,const virDomainDef * def,qemuDomainObjPrivate * priv)10283 qemuBuildManagedPRCommandLine(virCommand *cmd,
10284 const virDomainDef *def,
10285 qemuDomainObjPrivate *priv)
10286 {
10287 g_autoptr(virJSONValue) props = NULL;
10288
10289 if (!virDomainDefHasManagedPR(def))
10290 return 0;
10291
10292 if (!(props = qemuBuildPRManagedManagerInfoProps(priv)))
10293 return -1;
10294
10295 if (qemuBuildObjectCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0)
10296 return -1;
10297
10298 return 0;
10299 }
10300
10301
10302 static int
qemuBuildPflashBlockdevOne(virCommand * cmd,virStorageSource * src,virQEMUCaps * qemuCaps)10303 qemuBuildPflashBlockdevOne(virCommand *cmd,
10304 virStorageSource *src,
10305 virQEMUCaps *qemuCaps)
10306 {
10307 g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
10308 size_t i;
10309
10310 if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(src)))
10311 return -1;
10312
10313 for (i = data->nsrcdata; i > 0; i--) {
10314 if (qemuBuildBlockStorageSourceAttachDataCommandline(cmd,
10315 data->srcdata[i - 1],
10316 qemuCaps) < 0)
10317 return -1;
10318 }
10319
10320 return 0;
10321 }
10322
10323
10324 static int
qemuBuildPflashBlockdevCommandLine(virCommand * cmd,qemuDomainObjPrivate * priv)10325 qemuBuildPflashBlockdevCommandLine(virCommand *cmd,
10326 qemuDomainObjPrivate *priv)
10327 {
10328 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV))
10329 return 0;
10330
10331 if (priv->pflash0 &&
10332 qemuBuildPflashBlockdevOne(cmd, priv->pflash0, priv->qemuCaps) < 0)
10333 return -1;
10334
10335 if (priv->pflash1 &&
10336 qemuBuildPflashBlockdevOne(cmd, priv->pflash1, priv->qemuCaps) < 0)
10337 return -1;
10338
10339 return 0;
10340 }
10341
10342
10343 virJSONValue *
qemuBuildDBusVMStateInfoProps(virQEMUDriver * driver,virDomainObj * vm)10344 qemuBuildDBusVMStateInfoProps(virQEMUDriver *driver,
10345 virDomainObj *vm)
10346 {
10347 virJSONValue *ret = NULL;
10348 const char *alias = qemuDomainGetDBusVMStateAlias();
10349 g_autofree char *addr = qemuDBusGetAddress(driver, vm);
10350
10351 if (!addr)
10352 return NULL;
10353
10354 qemuMonitorCreateObjectProps(&ret,
10355 "dbus-vmstate", alias,
10356 "s:addr", addr, NULL);
10357 return ret;
10358 }
10359
10360
10361 static int
qemuBuildDBusVMStateCommandLine(virCommand * cmd,virQEMUDriver * driver,virDomainObj * vm)10362 qemuBuildDBusVMStateCommandLine(virCommand *cmd,
10363 virQEMUDriver *driver,
10364 virDomainObj *vm)
10365 {
10366 g_autoptr(virJSONValue) props = NULL;
10367 qemuDomainObjPrivate *priv = QEMU_DOMAIN_PRIVATE(vm);
10368
10369 if (!priv->dbusVMStateIds)
10370 return 0;
10371
10372 if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
10373 VIR_INFO("dbus-vmstate object is not supported by this QEMU binary");
10374 return 0;
10375 }
10376
10377 if (!(props = qemuBuildDBusVMStateInfoProps(driver, vm)))
10378 return -1;
10379
10380 if (qemuBuildObjectCommandlineFromJSON(cmd, props, priv->qemuCaps) < 0)
10381 return -1;
10382
10383 priv->dbusVMState = true;
10384
10385 return 0;
10386 }
10387
10388
10389 /**
10390 * qemuBuildCommandLineValidate:
10391 *
10392 * Prior to taking the plunge and building a long command line only
10393 * to find some configuration option isn't valid, let's do a couple
10394 * of checks and fail early.
10395 *
10396 * Returns 0 on success, returns -1 and messages what the issue is.
10397 */
10398 static int
qemuBuildCommandLineValidate(virQEMUDriver * driver,const virDomainDef * def)10399 qemuBuildCommandLineValidate(virQEMUDriver *driver,
10400 const virDomainDef *def)
10401 {
10402 size_t i;
10403 int sdl = 0;
10404 int vnc = 0;
10405 int spice = 0;
10406 int egl_headless = 0;
10407
10408 if (!driver->privileged) {
10409 /* If we have no cgroups then we can have no tunings that
10410 * require them */
10411
10412 if (virMemoryLimitIsSet(def->mem.hard_limit) ||
10413 virMemoryLimitIsSet(def->mem.soft_limit) ||
10414 virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
10415 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10416 _("Memory tuning is not available in session mode"));
10417 return -1;
10418 }
10419
10420 if (def->blkio.weight) {
10421 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10422 _("Block I/O tuning is not available in session mode"));
10423 return -1;
10424 }
10425
10426 if (def->cputune.sharesSpecified || def->cputune.period ||
10427 def->cputune.quota || def->cputune.global_period ||
10428 def->cputune.global_quota || def->cputune.emulator_period ||
10429 def->cputune.emulator_quota || def->cputune.iothread_period ||
10430 def->cputune.iothread_quota) {
10431 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10432 _("CPU tuning is not available in session mode"));
10433 return -1;
10434 }
10435 }
10436
10437 for (i = 0; i < def->ngraphics; ++i) {
10438 switch (def->graphics[i]->type) {
10439 case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
10440 ++sdl;
10441 break;
10442 case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
10443 ++vnc;
10444 break;
10445 case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
10446 ++spice;
10447 break;
10448 case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
10449 ++egl_headless;
10450 break;
10451 case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
10452 case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
10453 case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
10454 break;
10455 }
10456 }
10457
10458 if (sdl > 1 || vnc > 1 || spice > 1 || egl_headless > 1) {
10459 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10460 _("only 1 graphics device of each type "
10461 "(sdl, vnc, spice, headless) is supported"));
10462 return -1;
10463 }
10464
10465 if (def->virtType == VIR_DOMAIN_VIRT_XEN ||
10466 def->os.type == VIR_DOMAIN_OSTYPE_XEN ||
10467 def->os.type == VIR_DOMAIN_OSTYPE_LINUX) {
10468 virReportError(VIR_ERR_INTERNAL_ERROR,
10469 _("qemu emulator '%s' does not support xen"),
10470 def->emulator);
10471 return -1;
10472 }
10473
10474 return 0;
10475 }
10476
10477
10478 static int
qemuBuildSeccompSandboxCommandLine(virCommand * cmd,virQEMUDriverConfig * cfg,virQEMUCaps * qemuCaps G_GNUC_UNUSED)10479 qemuBuildSeccompSandboxCommandLine(virCommand *cmd,
10480 virQEMUDriverConfig *cfg,
10481 virQEMUCaps *qemuCaps G_GNUC_UNUSED)
10482 {
10483 if (cfg->seccompSandbox == 0) {
10484 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SECCOMP_SANDBOX))
10485 virCommandAddArgList(cmd, "-sandbox", "off", NULL);
10486 return 0;
10487 }
10488
10489 if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SECCOMP_SANDBOX)) {
10490 virCommandAddArgList(cmd, "-sandbox",
10491 "on,obsolete=deny,elevateprivileges=deny,"
10492 "spawn=deny,resourcecontrol=deny",
10493 NULL);
10494 return 0;
10495 }
10496
10497 return 0;
10498
10499 }
10500
10501
10502 virJSONValue *
qemuBuildVsockDevProps(virDomainDef * def,virDomainVsockDef * vsock,virQEMUCaps * qemuCaps,const char * fdprefix)10503 qemuBuildVsockDevProps(virDomainDef *def,
10504 virDomainVsockDef *vsock,
10505 virQEMUCaps *qemuCaps,
10506 const char *fdprefix)
10507 {
10508 qemuDomainVsockPrivate *priv = (qemuDomainVsockPrivate *)vsock->privateData;
10509 g_autoptr(virJSONValue) props = NULL;
10510 g_autofree char *vhostfd = g_strdup_printf("%s%u", fdprefix, priv->vhostfd);
10511
10512 if (!(props = qemuBuildVirtioDevProps(VIR_DOMAIN_DEVICE_VSOCK, vsock, qemuCaps)))
10513 return NULL;
10514
10515 if (virJSONValueObjectAdd(&props,
10516 "s:id", vsock->info.alias,
10517 "u:guest-cid", vsock->guest_cid,
10518 "s:vhostfd", vhostfd,
10519 NULL) < 0)
10520 return NULL;
10521
10522 if (qemuBuildDeviceAddressProps(props, def, &vsock->info) < 0)
10523 return NULL;
10524
10525 return g_steal_pointer(&props);
10526 }
10527
10528
10529 static int
qemuBuildVsockCommandLine(virCommand * cmd,virDomainDef * def,virDomainVsockDef * vsock,virQEMUCaps * qemuCaps)10530 qemuBuildVsockCommandLine(virCommand *cmd,
10531 virDomainDef *def,
10532 virDomainVsockDef *vsock,
10533 virQEMUCaps *qemuCaps)
10534 {
10535 qemuDomainVsockPrivate *priv = (qemuDomainVsockPrivate *)vsock->privateData;
10536 g_autoptr(virJSONValue) devprops = NULL;
10537
10538 if (!(devprops = qemuBuildVsockDevProps(def, vsock, qemuCaps, "")))
10539 return -1;
10540
10541 virCommandPassFD(cmd, priv->vhostfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
10542 priv->vhostfd = -1;
10543
10544 if (qemuCommandAddExtDevice(cmd, &vsock->info, qemuCaps) < 0)
10545 return -1;
10546
10547 if (qemuBuildDeviceCommandlineFromJSON(cmd, devprops, qemuCaps) < 0)
10548 return -1;
10549
10550 return 0;
10551 }
10552
10553
10554 typedef enum {
10555 QEMU_COMMAND_DEPRECATION_BEHAVIOR_NONE = 0,
10556 QEMU_COMMAND_DEPRECATION_BEHAVIOR_OMIT,
10557 QEMU_COMMAND_DEPRECATION_BEHAVIOR_REJECT,
10558 QEMU_COMMAND_DEPRECATION_BEHAVIOR_CRASH,
10559
10560 QEMU_COMMAND_DEPRECATION_BEHAVIOR_LAST
10561 } qemuCommnadDeprecationBehavior;
10562
10563
10564 VIR_ENUM_DECL(qemuCommnadDeprecationBehavior);
10565 VIR_ENUM_IMPL(qemuCommnadDeprecationBehavior,
10566 QEMU_COMMAND_DEPRECATION_BEHAVIOR_LAST,
10567 "none",
10568 "omit",
10569 "reject",
10570 "crash");
10571
10572 static void
qemuBuildCompatDeprecatedCommandLine(virCommand * cmd,virQEMUDriverConfig * cfg,virDomainDef * def,virQEMUCaps * qemuCaps)10573 qemuBuildCompatDeprecatedCommandLine(virCommand *cmd,
10574 virQEMUDriverConfig *cfg,
10575 virDomainDef *def,
10576 virQEMUCaps *qemuCaps)
10577 {
10578 g_autoptr(virJSONValue) props = NULL;
10579 g_autofree char *propsstr = NULL;
10580 qemuDomainXmlNsDef *nsdata = def->namespaceData;
10581 qemuCommnadDeprecationBehavior behavior = QEMU_COMMAND_DEPRECATION_BEHAVIOR_NONE;
10582 const char *behaviorStr = cfg->deprecationBehavior;
10583 int tmp;
10584 const char *deprecatedOutput = NULL;
10585 const char *deprecatedInput = NULL;
10586
10587 if (nsdata && nsdata->deprecationBehavior)
10588 behaviorStr = nsdata->deprecationBehavior;
10589
10590 if ((tmp = qemuCommnadDeprecationBehaviorTypeFromString(behaviorStr)) < 0) {
10591 VIR_WARN("Unsupported deprecation behavior '%s' for VM '%s'",
10592 behaviorStr, def->name);
10593 return;
10594 }
10595
10596 behavior = tmp;
10597
10598 if (behavior == QEMU_COMMAND_DEPRECATION_BEHAVIOR_NONE)
10599 return;
10600
10601 /* we don't try to enable this feature at all if qemu doesn't support it,
10602 * so that a downgrade of qemu version doesn't impact startup of the VM */
10603 if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_COMPAT_DEPRECATED)) {
10604 VIR_DEBUG("-compat not supported for VM '%s'", def->name);
10605 return;
10606 }
10607
10608 switch (behavior) {
10609 case QEMU_COMMAND_DEPRECATION_BEHAVIOR_OMIT:
10610 case QEMU_COMMAND_DEPRECATION_BEHAVIOR_NONE:
10611 case QEMU_COMMAND_DEPRECATION_BEHAVIOR_LAST:
10612 default:
10613 deprecatedOutput = "hide";
10614 break;
10615
10616 case QEMU_COMMAND_DEPRECATION_BEHAVIOR_REJECT:
10617 deprecatedOutput = "hide";
10618 deprecatedInput = "reject";
10619 break;
10620
10621 case QEMU_COMMAND_DEPRECATION_BEHAVIOR_CRASH:
10622 deprecatedOutput = "hide";
10623 deprecatedInput = "crash";
10624 break;
10625 }
10626
10627 if (virJSONValueObjectAdd(&props,
10628 "S:deprecated-output", deprecatedOutput,
10629 "S:deprecated-input", deprecatedInput,
10630 NULL) < 0)
10631 return;
10632
10633 if (!(propsstr = virJSONValueToString(props, false)))
10634 return;
10635
10636 virCommandAddArgList(cmd, "-compat", propsstr, NULL);
10637 }
10638
10639
10640 /*
10641 * Constructs a argv suitable for launching qemu with config defined
10642 * for a given virtual machine.
10643 */
10644 virCommand *
qemuBuildCommandLine(virQEMUDriver * driver,virLogManager * logManager,virSecurityManager * secManager,virDomainObj * vm,const char * migrateURI,virDomainMomentObj * snapshot,virNetDevVPortProfileOp vmop,bool standalone,bool enableFips,size_t * nnicindexes,int ** nicindexes,unsigned int flags)10645 qemuBuildCommandLine(virQEMUDriver *driver,
10646 virLogManager *logManager,
10647 virSecurityManager *secManager,
10648 virDomainObj *vm,
10649 const char *migrateURI,
10650 virDomainMomentObj *snapshot,
10651 virNetDevVPortProfileOp vmop,
10652 bool standalone,
10653 bool enableFips,
10654 size_t *nnicindexes,
10655 int **nicindexes,
10656 unsigned int flags)
10657 {
10658 size_t i;
10659 char uuid[VIR_UUID_STRING_BUFLEN];
10660 g_autoptr(virCommand) cmd = NULL;
10661 g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
10662 qemuDomainObjPrivate *priv = vm->privateData;
10663 virDomainDef *def = vm->def;
10664 virQEMUCaps *qemuCaps = priv->qemuCaps;
10665 bool chardevStdioLogd = priv->chardevStdioLogd;
10666
10667 VIR_DEBUG("driver=%p def=%p mon=%p "
10668 "qemuCaps=%p migrateURI=%s snapshot=%p vmop=%d flags=0x%x",
10669 driver, def, priv->monConfig,
10670 qemuCaps, migrateURI, snapshot, vmop, flags);
10671
10672 if (qemuBuildCommandLineValidate(driver, def) < 0)
10673 return NULL;
10674
10675 cmd = virCommandNew(def->emulator);
10676
10677 virCommandAddEnvPassCommon(cmd);
10678
10679 /* For system QEMU we want to set both HOME and all the XDG variables to
10680 * libDir/qemu otherwise apps QEMU links to might try to access the default
10681 * home dir '/' which would always result in a permission issue.
10682 *
10683 * For session QEMU, we only want to set XDG_CACHE_HOME as cache data
10684 * may be purged at any time and that should not affect any app. We
10685 * do want VMs to integrate with services in user's session so we're
10686 * not re-setting any other env variables
10687 */
10688 if (!driver->privileged) {
10689 virCommandAddEnvFormat(cmd, "XDG_CACHE_HOME=%s/%s",
10690 priv->libDir, ".cache");
10691 } else {
10692 virCommandAddEnvPair(cmd, "HOME", priv->libDir);
10693 virCommandAddEnvXDG(cmd, priv->libDir);
10694 }
10695
10696 if (qemuBuildNameCommandLine(cmd, cfg, def) < 0)
10697 return NULL;
10698
10699 qemuBuildCompatDeprecatedCommandLine(cmd, cfg, def, qemuCaps);
10700
10701 if (!standalone)
10702 virCommandAddArg(cmd, "-S"); /* freeze CPU */
10703
10704 if (qemuBuildMasterKeyCommandLine(cmd, priv) < 0)
10705 return NULL;
10706
10707 if (qemuBuildDBusVMStateCommandLine(cmd, driver, vm) < 0)
10708 return NULL;
10709
10710 if (qemuBuildManagedPRCommandLine(cmd, def, priv) < 0)
10711 return NULL;
10712
10713 if (qemuBuildPflashBlockdevCommandLine(cmd, priv) < 0)
10714 return NULL;
10715
10716 if (enableFips)
10717 virCommandAddArg(cmd, "-enable-fips");
10718
10719 if (qemuBuildMachineCommandLine(cmd, cfg, def, qemuCaps, priv) < 0)
10720 return NULL;
10721
10722 qemuBuildAccelCommandLine(cmd, def);
10723
10724 qemuBuildTSEGCommandLine(cmd, def);
10725
10726 if (qemuBuildCpuCommandLine(cmd, driver, def, qemuCaps) < 0)
10727 return NULL;
10728
10729 qemuBuildDomainLoaderCommandLine(cmd, def, qemuCaps);
10730
10731 if (qemuBuildMemCommandLine(cmd, def, qemuCaps, priv) < 0)
10732 return NULL;
10733
10734 if (qemuBuildSmpCommandLine(cmd, def, qemuCaps) < 0)
10735 return NULL;
10736
10737 if (qemuBuildIOThreadCommandLine(cmd, def, qemuCaps) < 0)
10738 return NULL;
10739
10740 if (virDomainNumaGetNodeCount(def->numa) &&
10741 qemuBuildNumaCommandLine(cfg, def, cmd, priv) < 0)
10742 return NULL;
10743
10744 if (qemuBuildMemoryDeviceCommandLine(cmd, cfg, def, priv) < 0)
10745 return NULL;
10746
10747 virUUIDFormat(def->uuid, uuid);
10748 virCommandAddArgList(cmd, "-uuid", uuid, NULL);
10749
10750 if (qemuBuildSmbiosCommandLine(cmd, driver, def) < 0)
10751 return NULL;
10752
10753 if (qemuBuildSysinfoCommandLine(cmd, def) < 0)
10754 return NULL;
10755
10756 if (qemuBuildVMGenIDCommandLine(cmd, def, qemuCaps) < 0)
10757 return NULL;
10758
10759 /*
10760 * NB, -nographic *MUST* come before any serial, or monitor
10761 * or parallel port flags due to QEMU craziness, where it
10762 * decides to change the serial port & monitor to be on stdout
10763 * if you ask for nographic. So we have to make sure we override
10764 * these defaults ourselves...
10765 */
10766 if (!def->ngraphics) {
10767 virCommandAddArg(cmd, "-display");
10768 virCommandAddArg(cmd, "none");
10769 }
10770
10771 /* Disable global config files and default devices */
10772 virCommandAddArg(cmd, "-no-user-config");
10773 virCommandAddArg(cmd, "-nodefaults");
10774
10775 if (qemuBuildMonitorCommandLine(logManager, secManager, cmd, cfg, def, priv) < 0)
10776 return NULL;
10777
10778 if (qemuBuildClockCommandLine(cmd, def, qemuCaps) < 0)
10779 return NULL;
10780
10781 if (qemuBuildPMCommandLine(cmd, def, priv) < 0)
10782 return NULL;
10783
10784 if (qemuBuildBootCommandLine(cmd, def) < 0)
10785 return NULL;
10786
10787 if (qemuBuildIOMMUCommandLine(cmd, def, qemuCaps) < 0)
10788 return NULL;
10789
10790 if (qemuBuildGlobalControllerCommandLine(cmd, def) < 0)
10791 return NULL;
10792
10793 if (qemuBuildControllersCommandLine(cmd, def, qemuCaps) < 0)
10794 return NULL;
10795
10796 if (qemuBuildHubCommandLine(cmd, def, qemuCaps) < 0)
10797 return NULL;
10798
10799 if (qemuBuildControllersByTypeCommandLine(cmd, def, qemuCaps,
10800 VIR_DOMAIN_CONTROLLER_TYPE_CCID) < 0)
10801 return NULL;
10802
10803 if (qemuBuildDisksCommandLine(cmd, def, qemuCaps) < 0)
10804 return NULL;
10805
10806 if (qemuBuildFilesystemCommandLine(cmd, def, qemuCaps, priv) < 0)
10807 return NULL;
10808
10809 if (qemuBuildNetCommandLine(driver, vm, logManager, secManager, cmd,
10810 qemuCaps, vmop, standalone,
10811 nnicindexes, nicindexes) < 0)
10812 return NULL;
10813
10814 if (qemuBuildSmartcardCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10815 chardevStdioLogd) < 0)
10816 return NULL;
10817
10818 if (qemuBuildSerialCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10819 chardevStdioLogd) < 0)
10820 return NULL;
10821
10822 if (qemuBuildParallelsCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10823 chardevStdioLogd) < 0)
10824 return NULL;
10825
10826 if (qemuBuildChannelsCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10827 chardevStdioLogd) < 0)
10828 return NULL;
10829
10830 if (qemuBuildConsoleCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10831 chardevStdioLogd) < 0)
10832 return NULL;
10833
10834 if (qemuBuildTPMsCommandLine(cmd, def, qemuCaps) < 0)
10835 return NULL;
10836
10837 if (qemuBuildInputCommandLine(cmd, def, qemuCaps) < 0)
10838 return NULL;
10839
10840 if (qemuBuildAudioCommandLine(cmd, def, qemuCaps) < 0)
10841 return NULL;
10842
10843 if (qemuBuildGraphicsCommandLine(cfg, cmd, def, qemuCaps) < 0)
10844 return NULL;
10845
10846 if (qemuBuildVideoCommandLine(cmd, def, qemuCaps) < 0)
10847 return NULL;
10848
10849 if (qemuBuildSoundCommandLine(cmd, def, qemuCaps) < 0)
10850 return NULL;
10851
10852 if (qemuBuildWatchdogCommandLine(cmd, def, qemuCaps) < 0)
10853 return NULL;
10854
10855 if (qemuBuildRedirdevCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10856 chardevStdioLogd) < 0)
10857 return NULL;
10858
10859 if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps) < 0)
10860 return NULL;
10861
10862 if (migrateURI)
10863 virCommandAddArgList(cmd, "-incoming", migrateURI, NULL);
10864
10865 if (qemuBuildMemballoonCommandLine(cmd, def, qemuCaps) < 0)
10866 return NULL;
10867
10868 if (qemuBuildRNGCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10869 chardevStdioLogd) < 0)
10870 return NULL;
10871
10872 if (qemuBuildNVRAMCommandLine(cmd, def) < 0)
10873 return NULL;
10874
10875 if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
10876 return NULL;
10877
10878 if (qemuBuildSecCommandLine(vm, cmd, def->sec) < 0)
10879 return NULL;
10880
10881 if (snapshot)
10882 virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
10883
10884 if (def->namespaceData) {
10885 qemuDomainXmlNsDef *qemuxmlns;
10886 GStrv n;
10887
10888 qemuxmlns = def->namespaceData;
10889 for (n = qemuxmlns->args; n && *n; n++)
10890 virCommandAddArg(cmd, *n);
10891 for (i = 0; i < qemuxmlns->num_env; i++)
10892 virCommandAddEnvPair(cmd, qemuxmlns->env[i].name,
10893 NULLSTR_EMPTY(qemuxmlns->env[i].value));
10894 }
10895
10896 if (qemuBuildSeccompSandboxCommandLine(cmd, cfg, qemuCaps) < 0)
10897 return NULL;
10898
10899 if (qemuBuildPanicCommandLine(cmd, def, qemuCaps) < 0)
10900 return NULL;
10901
10902 for (i = 0; i < def->nshmems; i++) {
10903 if (qemuBuildShmemCommandLine(logManager, secManager, cmd, cfg,
10904 def, def->shmems[i], qemuCaps,
10905 chardevStdioLogd) < 0)
10906 return NULL;
10907 }
10908
10909 if (def->vsock &&
10910 qemuBuildVsockCommandLine(cmd, def, def->vsock, qemuCaps) < 0)
10911 return NULL;
10912
10913 if (cfg->logTimestamp)
10914 virCommandAddArgList(cmd, "-msg", "timestamp=on", NULL);
10915
10916 return g_steal_pointer(&cmd);
10917 }
10918
10919
10920 static virJSONValue *
qemuBuildSerialChrDeviceProps(const virDomainDef * def,virDomainChrDef * serial,virQEMUCaps * qemuCaps)10921 qemuBuildSerialChrDeviceProps(const virDomainDef *def,
10922 virDomainChrDef *serial,
10923 virQEMUCaps *qemuCaps)
10924 {
10925 g_autoptr(virJSONValue) props = NULL;
10926 g_autofree char *chardev = g_strdup_printf("char%s", serial->info.alias);
10927 virQEMUCapsFlags caps;
10928
10929 switch ((virDomainChrSerialTargetModel) serial->targetModel) {
10930 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
10931 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_USB_SERIAL:
10932 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PCI_SERIAL:
10933 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
10934 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
10935 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
10936
10937 caps = qemuChrSerialTargetModelToCaps(serial->targetModel);
10938
10939 if (caps && !virQEMUCapsGet(qemuCaps, caps)) {
10940 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10941 _("'%s' is not supported in this QEMU binary"),
10942 virDomainChrSerialTargetModelTypeToString(serial->targetModel));
10943 return NULL;
10944 }
10945 break;
10946
10947 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
10948 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
10949 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
10950 case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
10951 /* Except from _LAST, which is just a guard value and will never
10952 * be used, all of the above are platform devices, which means
10953 * qemuBuildSerialCommandLine() will have taken the appropriate
10954 * branch and we will not have ended up here. */
10955 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10956 _("Invalid target model for serial device"));
10957 return NULL;
10958 }
10959
10960 if (virJSONValueObjectAdd(&props,
10961 "s:driver", virDomainChrSerialTargetModelTypeToString(serial->targetModel),
10962 "s:chardev", chardev,
10963 "s:id", serial->info.alias,
10964 NULL) < 0)
10965 return NULL;
10966
10967 if (qemuBuildDeviceAddressProps(props, def, &serial->info) < 0)
10968 return NULL;
10969
10970 return g_steal_pointer(&props);
10971 }
10972
10973
10974 static virJSONValue *
qemuBuildParallelChrDeviceProps(virDomainChrDef * chr)10975 qemuBuildParallelChrDeviceProps(virDomainChrDef *chr)
10976 {
10977 g_autoptr(virJSONValue) props = NULL;
10978 g_autofree char *chardev = g_strdup_printf("char%s", chr->info.alias);
10979
10980 if (virJSONValueObjectAdd(&props,
10981 "s:driver", "isa-parallel",
10982 "s:chardev", chardev,
10983 "s:id", chr->info.alias,
10984 NULL) < 0)
10985 return NULL;
10986
10987 return g_steal_pointer(&props);
10988 }
10989
10990
10991 virJSONValue *
qemuBuildChannelGuestfwdNetdevProps(virDomainChrDef * chr)10992 qemuBuildChannelGuestfwdNetdevProps(virDomainChrDef *chr)
10993 {
10994 g_autoptr(virJSONValue) guestfwdarr = virJSONValueNewArray();
10995 g_autoptr(virJSONValue) guestfwdstrobj = virJSONValueNewObject();
10996 g_autofree char *addr = NULL;
10997 virJSONValue *ret = NULL;
10998
10999 if (!(addr = virSocketAddrFormat(chr->target.addr)))
11000 return NULL;
11001
11002 /* this may seem weird, but qemu indeed decided that 'guestfwd' parameter
11003 * is an array of objects which have just one member named 'str' which
11004 * contains the description */
11005 if (virJSONValueObjectAppendStringPrintf(guestfwdstrobj, "str",
11006 "tcp:%s:%i-chardev:char%s",
11007 addr,
11008 virSocketAddrGetPort(chr->target.addr),
11009 chr->info.alias) < 0)
11010 return NULL;
11011
11012 if (virJSONValueArrayAppend(guestfwdarr, &guestfwdstrobj) < 0)
11013 return NULL;
11014
11015 if (virJSONValueObjectAdd(&ret,
11016 "s:type", "user",
11017 "a:guestfwd", &guestfwdarr,
11018 "s:id", chr->info.alias,
11019 NULL) < 0)
11020 return NULL;
11021
11022 return ret;
11023 }
11024
11025
11026 static virJSONValue *
qemuBuildChannelChrDeviceProps(const virDomainDef * def,virDomainChrDef * chr)11027 qemuBuildChannelChrDeviceProps(const virDomainDef *def,
11028 virDomainChrDef *chr)
11029 {
11030 switch ((virDomainChrChannelTargetType)chr->targetType) {
11031 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
11032 return qemuBuildVirtioSerialPortDevProps(def, chr);
11033
11034 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
11035 /* guestfwd is as a netdev handled separately */
11036 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
11037 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE:
11038 case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST:
11039 break;
11040 }
11041
11042 return NULL;
11043 }
11044
11045 static virJSONValue *
qemuBuildConsoleChrDeviceProps(const virDomainDef * def,virDomainChrDef * chr)11046 qemuBuildConsoleChrDeviceProps(const virDomainDef *def,
11047 virDomainChrDef *chr)
11048 {
11049 switch ((virDomainChrConsoleTargetType)chr->targetType) {
11050 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLP:
11051 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLPLM:
11052 return qemuBuildSclpDevProps(chr);
11053
11054 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO:
11055 return qemuBuildVirtioSerialPortDevProps(def, chr);
11056
11057 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
11058 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE:
11059 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN:
11060 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_UML:
11061 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LXC:
11062 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_OPENVZ:
11063 case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST:
11064 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11065 _("unsupported console target type %s"),
11066 NULLSTR(virDomainChrConsoleTargetTypeToString(chr->targetType)));
11067 break;
11068 }
11069
11070 return NULL;
11071 }
11072
11073
11074 virJSONValue *
qemuBuildChrDeviceProps(const virDomainDef * vmdef,virDomainChrDef * chr,virQEMUCaps * qemuCaps)11075 qemuBuildChrDeviceProps(const virDomainDef *vmdef,
11076 virDomainChrDef *chr,
11077 virQEMUCaps *qemuCaps)
11078 {
11079 switch ((virDomainChrDeviceType)chr->deviceType) {
11080 case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
11081 return qemuBuildSerialChrDeviceProps(vmdef, chr, qemuCaps);
11082
11083 case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
11084 return qemuBuildParallelChrDeviceProps(chr);
11085
11086 case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
11087 return qemuBuildChannelChrDeviceProps(vmdef, chr);
11088
11089 case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
11090 return qemuBuildConsoleChrDeviceProps(vmdef, chr);
11091
11092 case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
11093 break;
11094 }
11095
11096 return NULL;
11097 }
11098
11099
11100 virJSONValue *
qemuBuildHotpluggableCPUProps(const virDomainVcpuDef * vcpu)11101 qemuBuildHotpluggableCPUProps(const virDomainVcpuDef *vcpu)
11102 {
11103 qemuDomainVcpuPrivate *vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
11104 g_autoptr(virJSONValue) ret = NULL;
11105
11106 if (!(ret = virJSONValueCopy(vcpupriv->props)))
11107 return NULL;
11108
11109 if (virJSONValueObjectPrependString(ret, "id", vcpupriv->alias) < 0 ||
11110 virJSONValueObjectPrependString(ret, "driver", vcpupriv->type) < 0)
11111 return NULL;
11112
11113 return g_steal_pointer(&ret);
11114 }
11115
11116
11117 /**
11118 * qemuBuildStorageSourceAttachPrepareDrive:
11119 * @disk: disk object to prepare
11120 * @qemuCaps: qemu capabilities object
11121 *
11122 * Prepare qemuBlockStorageSourceAttachData *for use with the old approach
11123 * using -drive/drive_add. See qemuBlockStorageSourceAttachPrepareBlockdev.
11124 */
11125 static qemuBlockStorageSourceAttachData *
qemuBuildStorageSourceAttachPrepareDrive(virDomainDiskDef * disk,virQEMUCaps * qemuCaps)11126 qemuBuildStorageSourceAttachPrepareDrive(virDomainDiskDef *disk,
11127 virQEMUCaps *qemuCaps)
11128 {
11129 g_autoptr(qemuBlockStorageSourceAttachData) data = NULL;
11130
11131 data = g_new0(qemuBlockStorageSourceAttachData, 1);
11132
11133 if (!(data->driveCmd = qemuBuildDriveStr(disk, qemuCaps)) ||
11134 !(data->driveAlias = qemuAliasDiskDriveFromDisk(disk)))
11135 return NULL;
11136
11137 return g_steal_pointer(&data);
11138 }
11139
11140
11141 /**
11142 * qemuBuildStorageSourceAttachPrepareChardev:
11143 * @src: disk source to prepare
11144 *
11145 * Prepare qemuBlockStorageSourceAttachData *for vhost-user disk
11146 * to be used with -chardev.
11147 */
11148 static qemuBlockStorageSourceAttachData *
qemuBuildStorageSourceAttachPrepareChardev(virDomainDiskDef * disk)11149 qemuBuildStorageSourceAttachPrepareChardev(virDomainDiskDef *disk)
11150 {
11151 g_autoptr(qemuBlockStorageSourceAttachData) data = NULL;
11152 g_auto(virBuffer) chardev = VIR_BUFFER_INITIALIZER;
11153
11154 data = g_new0(qemuBlockStorageSourceAttachData, 1);
11155
11156 data->chardevDef = disk->src->vhostuser;
11157 data->chardevAlias = qemuDomainGetVhostUserChrAlias(disk->info.alias);
11158
11159 virBufferAddLit(&chardev, "socket");
11160 virBufferAsprintf(&chardev, ",id=%s", data->chardevAlias);
11161 virBufferAddLit(&chardev, ",path=");
11162 virQEMUBuildBufferEscapeComma(&chardev, disk->src->vhostuser->data.nix.path);
11163
11164 qemuBuildChrChardevReconnectStr(&chardev,
11165 &disk->src->vhostuser->data.nix.reconnect);
11166
11167 if (!(data->chardevCmd = virBufferContentAndReset(&chardev)))
11168 return NULL;
11169
11170 return g_steal_pointer(&data);
11171 }
11172
11173
11174 /**
11175 * qemuBuildStorageSourceAttachPrepareCommon:
11176 * @src: storage source
11177 * @data: already initialized data for disk source addition
11178 *
11179 * Prepare data for configuration associated with the disk source such as
11180 * secrets/TLS/pr objects etc ...
11181 */
11182 int
qemuBuildStorageSourceAttachPrepareCommon(virStorageSource * src,qemuBlockStorageSourceAttachData * data)11183 qemuBuildStorageSourceAttachPrepareCommon(virStorageSource *src,
11184 qemuBlockStorageSourceAttachData *data)
11185 {
11186 qemuDomainStorageSourcePrivate *srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
11187 const char *tlsKeySecretAlias = NULL;
11188
11189 if (src->pr &&
11190 !virStoragePRDefIsManaged(src->pr) &&
11191 !(data->prmgrProps = qemuBuildPRManagerInfoProps(src)))
11192 return -1;
11193
11194 if (srcpriv) {
11195 if (srcpriv->secinfo &&
11196 qemuBuildSecretInfoProps(srcpriv->secinfo, &data->authsecretProps) < 0)
11197 return -1;
11198
11199 if (srcpriv->encinfo &&
11200 qemuBuildSecretInfoProps(srcpriv->encinfo, &data->encryptsecretProps) < 0)
11201 return -1;
11202
11203 if (srcpriv->httpcookie &&
11204 qemuBuildSecretInfoProps(srcpriv->httpcookie, &data->httpcookiesecretProps) < 0)
11205 return -1;
11206
11207 if (srcpriv->tlsKeySecret) {
11208 if (qemuBuildSecretInfoProps(srcpriv->tlsKeySecret, &data->tlsKeySecretProps) < 0)
11209 return -1;
11210
11211 tlsKeySecretAlias = srcpriv->tlsKeySecret->alias;
11212 }
11213 }
11214
11215 if (src->haveTLS == VIR_TRISTATE_BOOL_YES &&
11216 qemuBuildTLSx509BackendProps(src->tlsCertdir, false, true, src->tlsAlias,
11217 tlsKeySecretAlias, &data->tlsProps) < 0)
11218 return -1;
11219
11220 return 0;
11221 }
11222
11223
11224 /**
11225 * qemuBuildStorageSourceChainAttachPrepareDrive:
11226 * @disk: disk definition
11227 * @qemuCaps: qemu capabilities object
11228 *
11229 * Prepares qemuBlockStorageSourceChainData *for attaching @disk via -drive.
11230 */
11231 qemuBlockStorageSourceChainData *
qemuBuildStorageSourceChainAttachPrepareDrive(virDomainDiskDef * disk,virQEMUCaps * qemuCaps)11232 qemuBuildStorageSourceChainAttachPrepareDrive(virDomainDiskDef *disk,
11233 virQEMUCaps *qemuCaps)
11234 {
11235 g_autoptr(qemuBlockStorageSourceAttachData) elem = NULL;
11236 g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
11237
11238 data = g_new0(qemuBlockStorageSourceChainData, 1);
11239
11240 if (!(elem = qemuBuildStorageSourceAttachPrepareDrive(disk, qemuCaps)))
11241 return NULL;
11242
11243 if (qemuBuildStorageSourceAttachPrepareCommon(disk->src, elem) < 0)
11244 return NULL;
11245
11246 VIR_APPEND_ELEMENT(data->srcdata, data->nsrcdata, elem);
11247
11248 return g_steal_pointer(&data);
11249 }
11250
11251
11252 /**
11253 * qemuBuildStorageSourceChainAttachPrepareChardev:
11254 * @src: disk definition
11255 *
11256 * Prepares qemuBlockStorageSourceChainData *for attaching a vhost-user
11257 * disk's backend via -chardev.
11258 */
11259 qemuBlockStorageSourceChainData *
qemuBuildStorageSourceChainAttachPrepareChardev(virDomainDiskDef * disk)11260 qemuBuildStorageSourceChainAttachPrepareChardev(virDomainDiskDef *disk)
11261 {
11262 g_autoptr(qemuBlockStorageSourceAttachData) elem = NULL;
11263 g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
11264
11265 data = g_new0(qemuBlockStorageSourceChainData, 1);
11266
11267 if (!(elem = qemuBuildStorageSourceAttachPrepareChardev(disk)))
11268 return NULL;
11269
11270 VIR_APPEND_ELEMENT(data->srcdata, data->nsrcdata, elem);
11271
11272 return g_steal_pointer(&data);
11273 }
11274
11275
11276 static int
qemuBuildStorageSourceChainAttachPrepareBlockdevOne(qemuBlockStorageSourceChainData * data,virStorageSource * src,virStorageSource * backingStore)11277 qemuBuildStorageSourceChainAttachPrepareBlockdevOne(qemuBlockStorageSourceChainData *data,
11278 virStorageSource *src,
11279 virStorageSource *backingStore)
11280 {
11281 g_autoptr(qemuBlockStorageSourceAttachData) elem = NULL;
11282
11283 if (!(elem = qemuBlockStorageSourceAttachPrepareBlockdev(src, backingStore, true)))
11284 return -1;
11285
11286 if (qemuBuildStorageSourceAttachPrepareCommon(src, elem) < 0)
11287 return -1;
11288
11289 VIR_APPEND_ELEMENT(data->srcdata, data->nsrcdata, elem);
11290
11291 return 0;
11292 }
11293
11294
11295 /**
11296 * qemuBuildStorageSourceChainAttachPrepareBlockdev:
11297 * @top: storage source chain
11298 *
11299 * Prepares qemuBlockStorageSourceChainData *for attaching the chain of images
11300 * starting at @top via -blockdev.
11301 */
11302 qemuBlockStorageSourceChainData *
qemuBuildStorageSourceChainAttachPrepareBlockdev(virStorageSource * top)11303 qemuBuildStorageSourceChainAttachPrepareBlockdev(virStorageSource *top)
11304 {
11305 g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
11306 virStorageSource *n;
11307
11308 data = g_new0(qemuBlockStorageSourceChainData, 1);
11309
11310 for (n = top; virStorageSourceIsBacking(n); n = n->backingStore) {
11311 if (qemuBuildStorageSourceChainAttachPrepareBlockdevOne(data, n,
11312 n->backingStore) < 0)
11313 return NULL;
11314 }
11315
11316 return g_steal_pointer(&data);
11317 }
11318
11319
11320 /**
11321 * qemuBuildStorageSourceChainAttachPrepareBlockdevTop:
11322 * @top: storage source chain
11323 * @backingStore: a storage source to use as backing of @top
11324 *
11325 * Prepares qemuBlockStorageSourceChainData *for attaching of @top image only
11326 * via -blockdev.
11327 */
11328 qemuBlockStorageSourceChainData *
qemuBuildStorageSourceChainAttachPrepareBlockdevTop(virStorageSource * top,virStorageSource * backingStore)11329 qemuBuildStorageSourceChainAttachPrepareBlockdevTop(virStorageSource *top,
11330 virStorageSource *backingStore)
11331 {
11332 g_autoptr(qemuBlockStorageSourceChainData) data = NULL;
11333
11334 data = g_new0(qemuBlockStorageSourceChainData, 1);
11335
11336 if (qemuBuildStorageSourceChainAttachPrepareBlockdevOne(data, top, backingStore) < 0)
11337 return NULL;
11338
11339 return g_steal_pointer(&data);
11340 }
11341