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