qemu_command.c 365.6 KB
Newer Older
1 2 3
/*
 * qemu_command.c: QEMU command generation
 *
4
 * Copyright (C) 2006-2016 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2006 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23 24
 */

#include <config.h>

#include "qemu_command.h"
25
#include "qemu_hostdev.h"
26
#include "qemu_capabilities.h"
27
#include "qemu_interface.h"
28
#include "qemu_alias.h"
29
#include "qemu_security.h"
30
#include "qemu_block.h"
31
#include "cpu/cpu.h"
32
#include "dirname.h"
33
#include "viralloc.h"
34
#include "virlog.h"
35
#include "virarch.h"
36
#include "virerror.h"
E
Eric Blake 已提交
37
#include "virfile.h"
38
#include "virnetdev.h"
39
#include "virnetdevbridge.h"
40
#include "virqemu.h"
41
#include "virstring.h"
42
#include "virtime.h"
43
#include "viruuid.h"
44
#include "domain_nwfilter.h"
45
#include "domain_addr.h"
46
#include "domain_audit.h"
M
Michal Novotny 已提交
47
#include "domain_conf.h"
48
#include "netdev_bandwidth_conf.h"
49
#include "snapshot_conf.h"
50
#include "storage_conf.h"
51
#include "secret_conf.h"
52
#include "virnetdevtap.h"
53
#include "virnetdevopenvswitch.h"
54
#include "device_conf.h"
55
#include "virstoragefile.h"
56
#include "virtpm.h"
57
#include "virscsi.h"
58
#include "virnuma.h"
59
#include "virgic.h"
60
#include "virmdev.h"
61 62 63
#if defined(__linux__)
# include <linux/capability.h>
#endif
64
#include "logging/log_manager.h"
65 66 67 68 69 70

#include <sys/stat.h>
#include <fcntl.h>

#define VIR_FROM_THIS VIR_FROM_QEMU

71 72
VIR_LOG_INIT("qemu.qemu_command");

73
VIR_ENUM_DECL(virDomainDiskQEMUBus);
74 75 76 77 78 79 80 81
VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
              "ide",
              "floppy",
              "scsi",
              "virtio",
              "xen",
              "usb",
              "uml",
82
              "sata",
83 84
              "sd",
);
85 86


87
VIR_ENUM_DECL(qemuDiskCacheV2);
88 89 90 91 92

VIR_ENUM_IMPL(qemuDiskCacheV2, VIR_DOMAIN_DISK_CACHE_LAST,
              "default",
              "none",
              "writethrough",
93
              "writeback",
94
              "directsync",
95 96
              "unsafe",
);
97 98

VIR_ENUM_IMPL(qemuVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
99
              "", /* default value, we shouldn't see this */
100 101 102
              "std",
              "cirrus",
              "vmware",
103
              "", /* don't support xen */
104
              "", /* don't support vbox */
105
              "qxl",
M
Marc-André Lureau 已提交
106
              "", /* don't support parallels */
F
Fabian Freyer 已提交
107
              "", /* no need for virtio */
108
              "" /* don't support gop */,
109 110
              "" /* 'none' doesn't make sense here */,
);
111

112
VIR_ENUM_DECL(qemuDeviceVideo);
113 114

VIR_ENUM_IMPL(qemuDeviceVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
115
              "", /* default value, we shouldn't see this */
116 117 118
              "VGA",
              "cirrus-vga",
              "vmware-svga",
119
              "", /* don't support xen */
120
              "", /* don't support vbox */
121
              "qxl-vga",
M
Marc-André Lureau 已提交
122
              "", /* don't support parallels */
F
Fabian Freyer 已提交
123
              "virtio-vga",
124
              "" /* don't support gop */,
125 126
              "" /* 'none' doesn't make sense here */,
);
127

128
VIR_ENUM_DECL(qemuDeviceVideoSecondary);
129 130

VIR_ENUM_IMPL(qemuDeviceVideoSecondary, VIR_DOMAIN_VIDEO_TYPE_LAST,
131
              "", /* default value, we shouldn't see this */
132 133 134 135 136 137 138
              "", /* no secondary device for VGA */
              "", /* no secondary device for cirrus-vga */
              "", /* no secondary device for vmware-svga */
              "", /* don't support xen */
              "", /* don't support vbox */
              "qxl",
              "", /* don't support parallels */
139
              "virtio-gpu",
140
              "" /* don't support gop */,
141 142
              "" /* 'none' doesn't make sense here */,
);
143

144
VIR_ENUM_DECL(qemuSoundCodec);
145 146 147

VIR_ENUM_IMPL(qemuSoundCodec, VIR_DOMAIN_SOUND_CODEC_TYPE_LAST,
              "hda-duplex",
F
Filip Alac 已提交
148
              "hda-micro",
149 150
              "hda-output",
);
151

152
VIR_ENUM_DECL(qemuControllerModelUSB);
153 154 155 156 157 158 159 160 161 162

VIR_ENUM_IMPL(qemuControllerModelUSB, VIR_DOMAIN_CONTROLLER_MODEL_USB_LAST,
              "piix3-usb-uhci",
              "piix4-usb-uhci",
              "usb-ehci",
              "ich9-usb-ehci1",
              "ich9-usb-uhci1",
              "ich9-usb-uhci2",
              "ich9-usb-uhci3",
              "vt82c686b-usb-uhci",
G
Gerd Hoffmann 已提交
163
              "pci-ohci",
164
              "nec-usb-xhci",
165 166
              "qusb1",
              "qusb2",
167
              "qemu-xhci",
168 169
              "none",
);
170

171
VIR_ENUM_DECL(qemuDomainFSDriver);
172 173 174
VIR_ENUM_IMPL(qemuDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST,
              "local",
              "local",
175
              "handle",
176
              NULL,
D
Dmitry Guryanov 已提交
177
              NULL,
178 179
              NULL,
);
180

181
VIR_ENUM_DECL(qemuNumaPolicy);
182 183 184
VIR_ENUM_IMPL(qemuNumaPolicy, VIR_DOMAIN_NUMATUNE_MEM_LAST,
              "bind",
              "preferred",
185 186
              "interleave",
);
187

188

189 190 191 192 193 194 195 196 197 198 199 200
/**
 * qemuBuildMasterKeyCommandLine:
 * @cmd: the command to modify
 * @qemuCaps qemu capabilities object
 * @domainLibDir: location to find the master key

 * Formats the command line for a master key if available
 *
 * Returns 0 on success, -1 w/ error message on failure
 */
static int
qemuBuildMasterKeyCommandLine(virCommandPtr cmd,
201
                              qemuDomainObjPrivatePtr priv)
202 203 204 205
{
    int ret = -1;
    char *alias = NULL;
    char *path = NULL;
206
    virBuffer buf = VIR_BUFFER_INITIALIZER;
207 208 209 210 211

    /* If the -object secret does not exist, then just return. This just
     * means the domain won't be able to use a secret master key and is
     * not a failure.
     */
212
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_SECRET)) {
213 214 215 216 217 218 219 220 221 222 223 224
        VIR_INFO("secret object is not supported by this QEMU binary");
        return 0;
    }

    if (!(alias = qemuDomainGetMasterKeyAlias()))
        return -1;

    /* Get the path. NB, the mocked test will not have the created
     * file so we cannot check for existence, which is no different
     * than other command line options which do not check for the
     * existence of socket files before using.
     */
225
    if (!(path = qemuDomainGetMasterKeyFilePath(priv->libDir)))
226 227 228
        goto cleanup;

    virCommandAddArg(cmd, "-object");
229
    virBufferAsprintf(&buf, "secret,id=%s,format=raw,file=", alias);
230
    virQEMUBuildBufferEscapeComma(&buf, path);
231
    virCommandAddArgBuffer(cmd, &buf);
232 233 234 235

    ret = 0;

 cleanup:
236
    virBufferFreeAndReset(&buf);
237 238 239 240 241 242
    VIR_FREE(alias);
    VIR_FREE(path);
    return ret;
}


243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
/**
 * qemuVirCommandGetFDSet:
 * @cmd: the command to modify
 * @fd: fd to reassign to the child
 *
 * Get the parameters for the QEMU -add-fd command line option
 * for the given file descriptor. The file descriptor must previously
 * have been 'transferred' in a virCommandPassFD() call.
 * This function for example returns "set=10,fd=20".
 */
static char *
qemuVirCommandGetFDSet(virCommandPtr cmd, int fd)
{
    char *result = NULL;
    int idx = virCommandPassFDGetFDIndex(cmd, fd);

    if (idx >= 0) {
        ignore_value(virAsprintf(&result, "set=%d,fd=%d", idx, fd));
    } else {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("file descriptor %d has not been transferred"), fd);
    }

    return result;
}


/**
 * qemuVirCommandGetDevSet:
 * @cmd: the command to modify
 * @fd: fd to reassign to the child
 *
 * Get the parameters for the QEMU path= parameter where a file
 * descriptor is accessed via a file descriptor set, for example
 * /dev/fdset/10. The file descriptor must previously have been
 * 'transferred' in a virCommandPassFD() call.
 */
static char *
qemuVirCommandGetDevSet(virCommandPtr cmd, int fd)
{
    char *result = NULL;
    int idx = virCommandPassFDGetFDIndex(cmd, fd);

    if (idx >= 0) {
        ignore_value(virAsprintf(&result, "/dev/fdset/%d", idx));
    } else {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("file descriptor %d has not been transferred"), fd);
    }
    return result;
}


296 297
static int
qemuBuildDeviceAddressStr(virBufferPtr buf,
298
                          const virDomainDef *domainDef,
299
                          virDomainDeviceInfoPtr info,
300
                          virQEMUCapsPtr qemuCaps)
301
{
302 303
    int ret = -1;
    char *devStr = NULL;
304
    const char *contAlias = NULL;
305 306
    bool contIsPHB = false;
    int contTargetIndex = 0;
307

308
    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
309 310
        size_t i;

311
        if (!(devStr = virPCIDeviceAddressAsString(&info->addr.pci)))
312 313 314 315 316 317
            goto cleanup;
        for (i = 0; i < domainDef->ncontrollers; i++) {
            virDomainControllerDefPtr cont = domainDef->controllers[i];

            if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
                cont->idx == info->addr.pci.bus) {
318
                contAlias = cont->info.alias;
319
                contIsPHB = virDomainControllerIsPSeriesPHB(cont);
320
                contTargetIndex = cont->opts.pciopts.targetIndex;
321

322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
                if (!contAlias) {
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Device alias was not set for PCI "
                                     "controller with index %u required "
                                     "for device at address %s"),
                                   info->addr.pci.bus, devStr);
                    goto cleanup;
                }

                if (virDomainDeviceAliasIsUserAlias(contAlias)) {
                    /* When domain has builtin pci-root controller we don't put it
                     * onto cmd line. Therefore we can't set its alias. In that
                     * case, use the default one. */
                    if (!qemuDomainIsPSeries(domainDef) &&
                        cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
                        if (virQEMUCapsHasPCIMultiBus(qemuCaps, domainDef))
                            contAlias = "pci.0";
                        else
                            contAlias = "pci";
                    } else if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) {
                        contAlias = "pcie.0";
343
                    }
344 345 346 347 348 349 350 351 352 353 354 355 356
                }
                break;
            }
        }
        if (!contAlias) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not find PCI "
                             "controller with index %u required "
                             "for device at address %s"),
                           info->addr.pci.bus, devStr);
            goto cleanup;
        }

357 358 359 360 361 362 363 364 365 366 367
        if (contIsPHB && contTargetIndex > 0) {
            /* The PCI bus created by a spapr-pci-host-bridge device with
             * alias 'x' will be called 'x.0' rather than 'x'; however,
             * this does not apply to the implicit PHB in a pSeries guest,
             * which always has the hardcoded name 'pci.0' */
            virBufferAsprintf(buf, ",bus=%s.0", contAlias);
        } else {
            /* For all other controllers, the bus name matches the alias
             * of the corresponding controller */
            virBufferAsprintf(buf, ",bus=%s", contAlias);
        }
368

J
Ján Tomko 已提交
369
        if (info->addr.pci.multi == VIR_TRISTATE_SWITCH_ON)
370
            virBufferAddLit(buf, ",multifunction=on");
J
Ján Tomko 已提交
371
        else if (info->addr.pci.multi == VIR_TRISTATE_SWITCH_OFF)
372 373 374 375
            virBufferAddLit(buf, ",multifunction=off");
        virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot);
        if (info->addr.pci.function != 0)
           virBufferAsprintf(buf, ".0x%x", info->addr.pci.function);
376
    } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
377 378 379 380
        if (!(contAlias = virDomainControllerAliasFind(domainDef,
                                                       VIR_DOMAIN_CONTROLLER_TYPE_USB,
                                                       info->addr.usb.bus)))
            goto cleanup;
J
Ján Tomko 已提交
381
        virBufferAsprintf(buf, ",bus=%s.0", contAlias);
382 383 384 385
        if (virDomainUSBAddressPortIsValid(info->addr.usb.port)) {
            virBufferAddLit(buf, ",port=");
            virDomainUSBAddressPortFormatBuf(buf, info->addr.usb.port);
        }
386 387 388
    } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) {
        if (info->addr.spaprvio.has_reg)
            virBufferAsprintf(buf, ",reg=0x%llx", info->addr.spaprvio.reg);
389 390 391 392 393 394
    } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
        if (info->addr.ccw.assigned)
            virBufferAsprintf(buf, ",devno=%x.%x.%04x",
                              info->addr.ccw.cssid,
                              info->addr.ccw.ssid,
                              info->addr.ccw.devno);
395 396 397 398
    } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA) {
        virBufferAsprintf(buf, ",iobase=0x%x,irq=0x%x",
                          info->addr.isa.iobase,
                          info->addr.isa.irq);
399
    }
400

401
    ret = 0;
402
 cleanup:
403 404
    VIR_FREE(devStr);
    return ret;
405 406
}

407

408 409 410 411
/**
 * qemuBuildVirtioDevStr
 * @buf: virBufferPtr to append the built string
 * @baseName: qemu virtio device basename string. Ex: virtio-rng for <rng>
412
 * @qemuCaps: virQEMUCapPtr
413 414 415 416 417 418 419 420 421 422
 * @devtype: virDomainDeviceType of the device. Ex: VIR_DOMAIN_DEVICE_TYPE_RNG
 * @devdata: *DefPtr of the device definition
 *
 * Build the qemu virtio -device name from the passed parameters. Currently
 * this is mostly about attaching the correct string prefix to @baseName for
 * the passed @type. So for @baseName "virtio-rng" and devdata->info.type
 * VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI, generate "virtio-rng-pci"
 *
 * Returns: -1 on failure, 0 on success
 */
423 424 425
static int
qemuBuildVirtioDevStr(virBufferPtr buf,
                      const char *baseName,
426
                      virQEMUCapsPtr qemuCaps,
427 428
                      virDomainDeviceType devtype,
                      void *devdata)
429 430
{
    const char *implName = NULL;
431 432
    virDomainDeviceDef device = { .type = devtype };
    virDomainDeviceInfoPtr info;
433
    bool has_tmodel, has_ntmodel;
434

435 436 437 438
    virDomainDeviceSetData(&device, devdata);
    info = virDomainDeviceGetInfo(&device);

    switch ((virDomainDeviceAddressType) info->type) {
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
        implName = "pci";
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
        implName = "device";
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
        implName = "ccw";
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390:
        implName = "s390";
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unexpected address type for '%s'"), baseName);
        return -1;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
    default:
469
        virReportEnumRangeError(virDomainDeviceAddressType, info->type);
470 471 472 473 474
        return -1;
    }

    virBufferAsprintf(buf, "%s-%s", baseName, implName);

475 476 477 478 479 480 481
    switch (devtype) {
        case VIR_DOMAIN_DEVICE_DISK:
            has_tmodel = device.data.disk->model == VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL;
            has_ntmodel = device.data.disk->model == VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL;
            break;

        case VIR_DOMAIN_DEVICE_NET:
482 483 484 485 486 487
            has_tmodel = STREQ_NULLABLE(device.data.net->model,
                                        "virtio-transitional");
            has_ntmodel = STREQ_NULLABLE(device.data.net->model,
                                         "virtio-non-transitional");
            break;

488 489 490 491 492 493 494
        case VIR_DOMAIN_DEVICE_HOSTDEV:
            if (device.data.hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST)
                return 0;
            has_tmodel = device.data.hostdev->source.subsys.u.scsi_host.model == VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_VHOST_MODEL_TYPE_VIRTIO_TRANSITIONAL;
            has_ntmodel = device.data.hostdev->source.subsys.u.scsi_host.model == VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_VHOST_MODEL_TYPE_VIRTIO_NON_TRANSITIONAL;
            break;

495 496 497 498 499
        case VIR_DOMAIN_DEVICE_RNG:
            has_tmodel = device.data.rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO_TRANSITIONAL;
            has_ntmodel = device.data.rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO_NON_TRANSITIONAL;
            break;

500
        case VIR_DOMAIN_DEVICE_FS:
501 502 503 504
            has_tmodel = device.data.fs->model == VIR_DOMAIN_FS_MODEL_VIRTIO_TRANSITIONAL;
            has_ntmodel = device.data.fs->model == VIR_DOMAIN_FS_MODEL_VIRTIO_NON_TRANSITIONAL;
            break;

505 506 507 508 509
        case VIR_DOMAIN_DEVICE_MEMBALLOON:
            has_tmodel = device.data.memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO_TRANSITIONAL;
            has_ntmodel = device.data.memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO_NON_TRANSITIONAL;
            break;

510 511 512 513 514
        case VIR_DOMAIN_DEVICE_VSOCK:
            has_tmodel = device.data.vsock->model == VIR_DOMAIN_VSOCK_MODEL_VIRTIO_TRANSITIONAL;
            has_ntmodel = device.data.vsock->model == VIR_DOMAIN_VSOCK_MODEL_VIRTIO_NON_TRANSITIONAL;
            break;

515
        case VIR_DOMAIN_DEVICE_INPUT:
516 517 518 519 520 521
            if (device.data.input->type != VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH)
                return 0;
            has_tmodel = device.data.input->model == VIR_DOMAIN_INPUT_MODEL_VIRTIO_TRANSITIONAL;
            has_ntmodel = device.data.input->model == VIR_DOMAIN_INPUT_MODEL_VIRTIO_NON_TRANSITIONAL;
            break;

522 523 524 525
        case VIR_DOMAIN_DEVICE_CONTROLLER:
            if (device.data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL) {
                has_tmodel = device.data.controller->model == VIR_DOMAIN_CONTROLLER_MODEL_VIRTIO_SERIAL_VIRTIO_TRANSITIONAL;
                has_ntmodel = device.data.controller->model == VIR_DOMAIN_CONTROLLER_MODEL_VIRTIO_SERIAL_VIRTIO_NON_TRANSITIONAL;
526 527 528
            } else if (device.data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
                has_tmodel = device.data.controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL;
                has_ntmodel = device.data.controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL;
529 530 531 532 533
            } else {
                return 0;
            }
            break;

534
        case VIR_DOMAIN_DEVICE_LEASE:
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
        case VIR_DOMAIN_DEVICE_SOUND:
        case VIR_DOMAIN_DEVICE_VIDEO:
        case VIR_DOMAIN_DEVICE_WATCHDOG:
        case VIR_DOMAIN_DEVICE_GRAPHICS:
        case VIR_DOMAIN_DEVICE_HUB:
        case VIR_DOMAIN_DEVICE_REDIRDEV:
        case VIR_DOMAIN_DEVICE_NONE:
        case VIR_DOMAIN_DEVICE_SMARTCARD:
        case VIR_DOMAIN_DEVICE_CHR:
        case VIR_DOMAIN_DEVICE_NVRAM:
        case VIR_DOMAIN_DEVICE_SHMEM:
        case VIR_DOMAIN_DEVICE_TPM:
        case VIR_DOMAIN_DEVICE_PANIC:
        case VIR_DOMAIN_DEVICE_MEMORY:
        case VIR_DOMAIN_DEVICE_IOMMU:
        case VIR_DOMAIN_DEVICE_LAST:
        default:
            return 0;
    }

    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
        (has_tmodel || has_ntmodel)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("virtio (non-)transitional models are not "
                         "supported for address type=%s"),
                       virDomainDeviceAddressTypeToString(info->type));
        return -1;
    }

    if (has_tmodel) {
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_PCI_TRANSITIONAL)) {
            virBufferAddLit(buf, "-transitional");
        } else if (virQEMUCapsGet(qemuCaps,
                                  QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY)) {
            virBufferAddLit(buf, ",disable-legacy=off,disable-modern=off");
        }
        /* No error if -transitional is not supported: our address
         * allocation will force the device into plain PCI bus, which
         * is functionally identical to standard 'virtio-XXX' behavior
         */
    } else if (has_ntmodel) {
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_PCI_TRANSITIONAL)) {
            virBufferAddLit(buf, "-non-transitional");
        } else if (virQEMUCapsGet(qemuCaps,
                                  QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY)) {
            /* Even if the QEMU binary doesn't support the non-transitional
             * device, we can still make it work by manually disabling legacy
             * VirtIO and enabling modern VirtIO */
            virBufferAddLit(buf, ",disable-legacy=on,disable-modern=off");
        } else {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("virtio non-transitional model not supported "
                             "for this qemu"));
            return -1;
        }
    }

592 593 594
    return 0;
}

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
static int
qemuBuildVirtioOptionsStr(virBufferPtr buf,
                          virDomainVirtioOptionsPtr virtio,
                          virQEMUCapsPtr qemuCaps)
{
    if (!virtio)
        return 0;

    if (virtio->iommu != VIR_TRISTATE_SWITCH_ABSENT) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_PCI_IOMMU_PLATFORM)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("the iommu setting is not supported "
                             "with this QEMU binary"));
            return -1;
        }
        virBufferAsprintf(buf, ",iommu_platform=%s",
                          virTristateSwitchTypeToString(virtio->iommu));
    }
    if (virtio->ats != VIR_TRISTATE_SWITCH_ABSENT) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_PCI_ATS)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("the ats setting is not supported with this "
                             "QEMU binary"));
            return -1;
        }
        virBufferAsprintf(buf, ",ats=%s",
                          virTristateSwitchTypeToString(virtio->ats));
    }

    return 0;
}

627 628
static int
qemuBuildRomStr(virBufferPtr buf,
629
                virDomainDeviceInfoPtr info)
630
{
631
    if (info->romenabled || info->rombar || info->romfile) {
632
        if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
633
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
634
                           "%s", _("ROM tuning is only supported for PCI devices"));
635 636 637
            return -1;
        }

638 639 640 641 642 643 644
        /* Passing an empty romfile= tells QEMU to disable ROM entirely for
         * this device, and makes other settings irrelevant */
        if (info->romenabled == VIR_TRISTATE_BOOL_NO) {
            virBufferAddLit(buf, ",romfile=");
            return 0;
        }

645
        switch (info->rombar) {
J
Ján Tomko 已提交
646
        case VIR_TRISTATE_SWITCH_OFF:
647 648
            virBufferAddLit(buf, ",rombar=0");
            break;
J
Ján Tomko 已提交
649
        case VIR_TRISTATE_SWITCH_ON:
650 651 652 653 654
            virBufferAddLit(buf, ",rombar=1");
            break;
        default:
            break;
        }
655 656 657 658
        if (info->romfile) {
           virBufferAddLit(buf, ",romfile=");
           virQEMUBuildBufferEscapeComma(buf, info->romfile);
        }
659
    }
660

661 662 663
    return 0;
}

664 665
static int
qemuBuildIoEventFdStr(virBufferPtr buf,
J
Ján Tomko 已提交
666
                      virTristateSwitch use,
667
                      virQEMUCapsPtr qemuCaps)
668
{
669
    if (use && virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_IOEVENTFD))
670
        virBufferAsprintf(buf, ",ioeventfd=%s",
J
Ján Tomko 已提交
671
                          virTristateSwitchTypeToString(use));
672 673
    return 0;
}
674 675

#define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \
676
  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ .+"
677 678 679 680

static int
qemuSafeSerialParamValue(const char *value)
{
681
    if (strspn(value, QEMU_SERIAL_PARAM_ACCEPTED_CHARS) != strlen(value)) {
682 683 684
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("driver serial '%s' contains unsafe characters"),
                       value);
685 686 687 688 689 690
        return -1;
    }

    return 0;
}

691

692 693 694 695 696 697 698 699 700 701
/**
 * qemuBuildSecretInfoProps:
 * @secinfo: pointer to the secret info object
 * @props: json properties to return
 *
 * Build the JSON properties for the secret info type.
 *
 * Returns 0 on success with the filled in JSON property; otherwise,
 * returns -1 on failure error message set.
 */
702
int
703 704 705 706 707 708 709 710 711
qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo,
                         virJSONValuePtr *propsret)
{
    int ret = -1;
    char *keyid = NULL;

    if (!(keyid = qemuDomainGetMasterKeyAlias()))
        return -1;

712 713 714 715 716 717
    ret = qemuMonitorCreateObjectProps(propsret,
                                       "secret", secinfo->s.aes.alias,
                                       "s:data", secinfo->s.aes.ciphertext,
                                       "s:keyid", keyid,
                                       "s:iv", secinfo->s.aes.iv,
                                       "s:format", "base64", NULL);
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739

    VIR_FREE(keyid);
    return ret;
}


/**
 * qemuBuildObjectSecretCommandLine:
 * @cmd: the command to modify
 * @secinfo: pointer to the secret info object
 *
 * If the secinfo is available and associated with an AES secret,
 * then format the command line for the secret object. This object
 * will be referenced by the device that needs/uses it, so it needs
 * to be in place first.
 *
 * Returns 0 on success, -1 w/ error message on failure
 */
static int
qemuBuildObjectSecretCommandLine(virCommandPtr cmd,
                                 qemuDomainSecretInfoPtr secinfo)
{
740
    virBuffer buf = VIR_BUFFER_INITIALIZER;
741 742 743
    int ret = -1;
    virJSONValuePtr props = NULL;

744
    if (qemuBuildSecretInfoProps(secinfo, &props) < 0)
745 746
        return -1;

747
    if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0)
748 749
        goto cleanup;

750 751 752 753
    virCommandAddArg(cmd, "-object");
    virCommandAddArgBuffer(cmd, &buf);

    ret  = 0;
754 755

 cleanup:
756
    virBufferFreeAndReset(&buf);
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
    virJSONValueFree(props);
    return ret;
}


/* qemuBuildDiskSecinfoCommandLine:
 * @cmd: Pointer to the command string
 * @secinfo: Pointer to a possible secinfo
 *
 * Add the secret object for the disks that will be using it to perform
 * their authentication.
 *
 * Returns 0 on success, -1 w/ error on some sort of failure.
 */
static int
qemuBuildDiskSecinfoCommandLine(virCommandPtr cmd,
                                qemuDomainSecretInfoPtr secinfo)
{
    /* Not necessary for non AES secrets */
    if (!secinfo || secinfo->type != VIR_DOMAIN_SECRET_INFO_TYPE_AES)
        return 0;

    return qemuBuildObjectSecretCommandLine(cmd, secinfo);
}


783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
/* qemuBuildGeneralSecinfoURI:
 * @uri: Pointer to the URI structure to add to
 * @secinfo: Pointer to the secret info data (if present)
 *
 * If we have a secinfo, then build the command line options for
 * the secret info for the "general" case (somewhat a misnomer since
 * an iscsi disk is the only one with a secinfo).
 *
 * Returns 0 on success or if no secinfo,
 * -1 and error message if fail to add secret information
 */
static int
qemuBuildGeneralSecinfoURI(virURIPtr uri,
                           qemuDomainSecretInfoPtr secinfo)
{
    if (!secinfo)
        return 0;

J
John Ferlan 已提交
801 802 803
    switch ((qemuDomainSecretInfoType) secinfo->type) {
    case VIR_DOMAIN_SECRET_INFO_TYPE_PLAIN:
        if (secinfo->s.plain.secret) {
804 805 806 807 808 809
            if (!virStringBufferIsPrintable(secinfo->s.plain.secret,
                                            secinfo->s.plain.secretlen)) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("found non printable characters in secret"));
                return -1;
            }
J
John Ferlan 已提交
810 811 812 813 814 815 816 817 818 819
            if (virAsprintf(&uri->user, "%s:%s",
                            secinfo->s.plain.username,
                            secinfo->s.plain.secret) < 0)
                return -1;
        } else {
            if (VIR_STRDUP(uri->user, secinfo->s.plain.username) < 0)
                return -1;
        }
        break;

820
    case VIR_DOMAIN_SECRET_INFO_TYPE_AES:
J
John Ferlan 已提交
821 822
    case VIR_DOMAIN_SECRET_INFO_TYPE_LAST:
        return -1;
823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
    }

    return 0;
}


/* qemuBuildRBDSecinfoURI:
 * @uri: Pointer to the URI structure to add to
 * @secinfo: Pointer to the secret info data (if present)
 *
 * If we have a secinfo, then build the command line options for
 * the secret info for the RBD network storage. Assumption for this
 * is both username and secret exist for plaintext
 *
 * Returns 0 on success or if no secinfo,
 * -1 and error message if fail to add secret information
 */
static int
qemuBuildRBDSecinfoURI(virBufferPtr buf,
                       qemuDomainSecretInfoPtr secinfo)
{
844 845
    char *base64secret = NULL;

846 847 848 849 850
    if (!secinfo) {
        virBufferAddLit(buf, ":auth_supported=none");
        return 0;
    }

J
John Ferlan 已提交
851 852
    switch ((qemuDomainSecretInfoType) secinfo->type) {
    case VIR_DOMAIN_SECRET_INFO_TYPE_PLAIN:
853 854 855 856
        if (!(base64secret = virStringEncodeBase64(secinfo->s.plain.secret,
                                                   secinfo->s.plain.secretlen)))
            return -1;
        virBufferEscape(buf, '\\', ":", ":id=%s", secinfo->s.plain.username);
J
John Ferlan 已提交
857 858
        virBufferEscape(buf, '\\', ":",
                        ":key=%s:auth_supported=cephx\\;none",
859 860
                        base64secret);
        VIR_DISPOSE_STRING(base64secret);
J
John Ferlan 已提交
861 862
        break;

863
    case VIR_DOMAIN_SECRET_INFO_TYPE_AES:
864 865 866 867
        virBufferEscape(buf, '\\', ":", ":id=%s:auth_supported=cephx\\;none",
                        secinfo->s.aes.username);
        break;

J
John Ferlan 已提交
868 869 870
    case VIR_DOMAIN_SECRET_INFO_TYPE_LAST:
        return -1;
    }
871 872 873 874 875

    return 0;
}


876 877 878 879
/* qemuBuildTLSx509BackendProps:
 * @tlspath: path to the TLS credentials
 * @listen: boolen listen for client or server setting
 * @verifypeer: boolean to enable peer verification (form of authorization)
880
 * @alias: alias for the TLS credentials object
881
 * @secalias: if one exists, the alias of the security object for passwordid
882 883 884 885 886 887 888
 * @qemuCaps: capabilities
 * @propsret: json properties to return
 *
 * Create a backend string for the tls-creds-x509 object.
 *
 * Returns 0 on success, -1 on failure with error set.
 */
889
int
890
qemuBuildTLSx509BackendProps(const char *tlspath,
891
                             bool isListen,
892
                             bool verifypeer,
893
                             const char *alias,
894
                             const char *secalias,
895 896 897 898 899 900 901 902 903
                             virQEMUCapsPtr qemuCaps,
                             virJSONValuePtr *propsret)
{
    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_X509)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("tls-creds-x509 not supported in this QEMU binary"));
        return -1;
    }

904 905 906 907 908 909
    if (qemuMonitorCreateObjectProps(propsret, "tls-creds-x509", alias,
                                     "s:dir", tlspath,
                                     "s:endpoint", (isListen ? "server": "client"),
                                     "b:verify-peer", (isListen ? verifypeer : true),
                                     "S:passwordid", secalias,
                                     NULL) < 0)
910
        return -1;
911

912
    return 0;
913 914 915 916 917 918 919 920
}


/* qemuBuildTLSx509CommandLine:
 * @cmd: Pointer to command
 * @tlspath: path to the TLS credentials
 * @listen: boolen listen for client or server setting
 * @verifypeer: boolean to enable peer verification (form of authorization)
921 922
 * @certEncSecretAlias: alias of a 'secret' object for decrypting TLS private key
 *                      (optional)
923
 * @alias: TLS object alias
924 925 926 927 928 929 930 931 932
 * @qemuCaps: capabilities
 *
 * Create the command line for a TLS object
 *
 * Returns 0 on success, -1 on failure with error set.
 */
static int
qemuBuildTLSx509CommandLine(virCommandPtr cmd,
                            const char *tlspath,
933
                            bool isListen,
934
                            bool verifypeer,
935
                            const char *certEncSecretAlias,
936
                            const char *alias,
937 938
                            virQEMUCapsPtr qemuCaps)
{
939
    virBuffer buf = VIR_BUFFER_INITIALIZER;
940 941 942
    int ret = -1;
    virJSONValuePtr props = NULL;

943 944
    if (qemuBuildTLSx509BackendProps(tlspath, isListen, verifypeer, alias,
                                     certEncSecretAlias, qemuCaps, &props) < 0)
945 946
        goto cleanup;

947
    if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0)
948 949
        goto cleanup;

950 951
    virCommandAddArg(cmd, "-object");
    virCommandAddArgBuffer(cmd, &buf);
952 953 954 955

    ret = 0;

 cleanup:
956
    virBufferFreeAndReset(&buf);
957 958 959 960 961
    virJSONValueFree(props);
    return ret;
}


962 963 964 965 966 967 968
static char *
qemuBuildNetworkDriveURI(virStorageSourcePtr src,
                         qemuDomainSecretInfoPtr secinfo)
{
    virURIPtr uri = NULL;
    char *ret = NULL;

969
    if (!(uri = qemuBlockStorageSourceGetURI(src)))
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
        goto cleanup;

    if (src->hosts->socket &&
        virAsprintf(&uri->query, "socket=%s", src->hosts->socket) < 0)
        goto cleanup;

    if (qemuBuildGeneralSecinfoURI(uri, secinfo) < 0)
        goto cleanup;

    ret = virURIFormat(uri);

 cleanup:
    virURIFree(uri);
    return ret;
}


987
static char *
988
qemuBuildNetworkDriveStr(virStorageSourcePtr src,
989
                         qemuDomainSecretInfoPtr secinfo)
990 991
{
    char *ret = NULL;
992
    virBuffer buf = VIR_BUFFER_INITIALIZER;
993
    size_t i;
994

995
    switch ((virStorageNetProtocol) src->protocol) {
996
        case VIR_STORAGE_NET_PROTOCOL_NBD:
997
            if (src->nhosts != 1) {
998 999
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("protocol '%s' accepts only one host"),
1000
                               virStorageNetProtocolTypeToString(src->protocol));
1001 1002 1003
                goto cleanup;
            }

1004 1005 1006 1007 1008 1009
            if (!((src->hosts->name && strchr(src->hosts->name, ':')) ||
                  (src->hosts->transport == VIR_STORAGE_NET_HOST_TRANS_TCP &&
                   !src->hosts->name) ||
                  (src->hosts->transport == VIR_STORAGE_NET_HOST_TRANS_UNIX &&
                   src->hosts->socket &&
                   src->hosts->socket[0] != '/'))) {
1010 1011 1012

                virBufferAddLit(&buf, "nbd:");

1013
                switch (src->hosts->transport) {
1014
                case VIR_STORAGE_NET_HOST_TRANS_TCP:
1015 1016
                    virBufferAsprintf(&buf, "%s:%u",
                                      src->hosts->name, src->hosts->port);
1017 1018
                    break;

1019
                case VIR_STORAGE_NET_HOST_TRANS_UNIX:
1020
                    if (!src->hosts->socket) {
1021 1022 1023 1024 1025 1026
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("socket attribute required for "
                                         "unix transport"));
                        goto cleanup;
                    }

1027
                    virBufferAsprintf(&buf, "unix:%s", src->hosts->socket);
1028 1029 1030 1031 1032
                    break;

                default:
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("nbd does not support transport '%s'"),
1033
                                   virStorageNetHostTransportTypeToString(src->hosts->transport));
1034 1035 1036
                    goto cleanup;
                }

1037 1038
                if (src->path)
                    virBufferAsprintf(&buf, ":exportname=%s", src->path);
1039

1040
                if (virBufferCheckError(&buf) < 0)
1041 1042 1043 1044 1045
                    goto cleanup;

                ret = virBufferContentAndReset(&buf);
                goto cleanup;
            }
1046 1047 1048
            /* NBD code uses URI formatting scheme as others in some cases */
            ret = qemuBuildNetworkDriveURI(src, secinfo);
            break;
1049

1050 1051 1052 1053 1054 1055 1056
        case VIR_STORAGE_NET_PROTOCOL_HTTP:
        case VIR_STORAGE_NET_PROTOCOL_HTTPS:
        case VIR_STORAGE_NET_PROTOCOL_FTP:
        case VIR_STORAGE_NET_PROTOCOL_FTPS:
        case VIR_STORAGE_NET_PROTOCOL_TFTP:
        case VIR_STORAGE_NET_PROTOCOL_ISCSI:
        case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
1057
            ret = qemuBuildNetworkDriveURI(src, secinfo);
1058 1059
            break;

1060
        case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
1061
            if (!src->path) {
1062 1063 1064 1065 1066
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("missing disk source for 'sheepdog' protocol"));
                goto cleanup;
            }

1067 1068
            if (src->nhosts == 0) {
                if (virAsprintf(&ret, "sheepdog:%s", src->path) < 0)
1069
                    goto cleanup;
1070
            } else if (src->nhosts == 1) {
1071
                if (virAsprintf(&ret, "sheepdog:%s:%u:%s",
1072
                                src->hosts->name, src->hosts->port,
1073
                                src->path) < 0)
1074 1075 1076 1077 1078 1079 1080 1081 1082
                    goto cleanup;
            } else {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("protocol 'sheepdog' accepts up to one host"));
                goto cleanup;
            }

            break;

1083
        case VIR_STORAGE_NET_PROTOCOL_RBD:
1084
            if (strchr(src->path, ':')) {
1085 1086
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("':' not allowed in RBD source volume name '%s'"),
1087
                               src->path);
1088 1089 1090
                goto cleanup;
            }

1091
            virBufferStrcat(&buf, "rbd:", src->volume, "/", src->path, NULL);
1092

1093 1094 1095
            if (src->snapshot)
                virBufferEscape(&buf, '\\', ":", "@%s", src->snapshot);

1096 1097
            if (qemuBuildRBDSecinfoURI(&buf, secinfo) < 0)
                goto cleanup;
1098

1099
            if (src->nhosts > 0) {
1100
                virBufferAddLit(&buf, ":mon_host=");
1101
                for (i = 0; i < src->nhosts; i++) {
1102 1103 1104 1105
                    if (i)
                        virBufferAddLit(&buf, "\\;");

                    /* assume host containing : is ipv6 */
1106 1107 1108
                    if (strchr(src->hosts[i].name, ':'))
                        virBufferEscape(&buf, '\\', ":", "[%s]",
                                        src->hosts[i].name);
1109
                    else
1110
                        virBufferAsprintf(&buf, "%s", src->hosts[i].name);
1111

1112
                    if (src->hosts[i].port)
1113
                        virBufferAsprintf(&buf, "\\:%u", src->hosts[i].port);
1114 1115 1116
                }
            }

1117 1118 1119
            if (src->configFile)
                virBufferEscape(&buf, '\\', ":", ":conf=%s", src->configFile);

1120
            if (virBufferCheckError(&buf) < 0)
1121 1122 1123 1124 1125
                goto cleanup;

            ret = virBufferContentAndReset(&buf);
            break;

1126 1127 1128 1129 1130
        case VIR_STORAGE_NET_PROTOCOL_VXHS:
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("VxHS protocol does not support URI syntax"));
            goto cleanup;

1131 1132 1133 1134
        case VIR_STORAGE_NET_PROTOCOL_SSH:
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("'ssh' protocol is not yet supported"));
            goto cleanup;
1135

1136
        case VIR_STORAGE_NET_PROTOCOL_LAST:
1137
        case VIR_STORAGE_NET_PROTOCOL_NONE:
1138 1139 1140
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unexpected network protocol '%s'"),
                           virStorageNetProtocolTypeToString(src->protocol));
1141 1142
            goto cleanup;
    }
1143

1144
 cleanup:
1145
    virBufferFreeAndReset(&buf);
1146 1147 1148 1149 1150

    return ret;
}


1151
int
1152
qemuGetDriveSourceString(virStorageSourcePtr src,
1153
                         qemuDomainSecretInfoPtr secinfo,
1154
                         char **source)
1155
{
1156 1157 1158 1159 1160
    int actualType = virStorageSourceGetActualType(src);
    int ret = -1;

    *source = NULL;

1161 1162 1163 1164
    /* return 1 for empty sources */
    if (virStorageSourceIsEmpty(src))
        return 1;

1165
    switch ((virStorageType)actualType) {
E
Eric Blake 已提交
1166 1167 1168
    case VIR_STORAGE_TYPE_BLOCK:
    case VIR_STORAGE_TYPE_FILE:
    case VIR_STORAGE_TYPE_DIR:
1169 1170
        if (VIR_STRDUP(*source, src->path) < 0)
            goto cleanup;
1171 1172 1173

        break;

E
Eric Blake 已提交
1174
    case VIR_STORAGE_TYPE_NETWORK:
1175
        if (!(*source = qemuBuildNetworkDriveStr(src, secinfo)))
1176
            goto cleanup;
1177 1178
        break;

E
Eric Blake 已提交
1179
    case VIR_STORAGE_TYPE_VOLUME:
1180
    case VIR_STORAGE_TYPE_NONE:
E
Eric Blake 已提交
1181
    case VIR_STORAGE_TYPE_LAST:
1182 1183 1184
        break;
    }

1185
    ret = 0;
1186

1187
 cleanup:
1188 1189 1190
    return ret;
}

P
Paolo Bonzini 已提交
1191

1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228
static bool
qemuDiskConfigBlkdeviotuneHasBasic(virDomainDiskDefPtr disk)
{
    return disk->blkdeviotune.total_bytes_sec ||
           disk->blkdeviotune.read_bytes_sec ||
           disk->blkdeviotune.write_bytes_sec ||
           disk->blkdeviotune.total_iops_sec ||
           disk->blkdeviotune.read_iops_sec ||
           disk->blkdeviotune.write_iops_sec;
}


static bool
qemuDiskConfigBlkdeviotuneHasMax(virDomainDiskDefPtr disk)
{
    return disk->blkdeviotune.total_bytes_sec_max ||
           disk->blkdeviotune.read_bytes_sec_max ||
           disk->blkdeviotune.write_bytes_sec_max ||
           disk->blkdeviotune.total_iops_sec_max ||
           disk->blkdeviotune.read_iops_sec_max ||
           disk->blkdeviotune.write_iops_sec_max ||
           disk->blkdeviotune.size_iops_sec;
}


static bool
qemuDiskConfigBlkdeviotuneHasMaxLength(virDomainDiskDefPtr disk)
{
    return disk->blkdeviotune.total_bytes_sec_max_length ||
           disk->blkdeviotune.read_bytes_sec_max_length ||
           disk->blkdeviotune.write_bytes_sec_max_length ||
           disk->blkdeviotune.total_iops_sec_max_length ||
           disk->blkdeviotune.read_iops_sec_max_length ||
           disk->blkdeviotune.write_iops_sec_max_length;
}


1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
bool
qemuDiskConfigBlkdeviotuneEnabled(virDomainDiskDefPtr disk)
{
    return !!disk->blkdeviotune.group_name ||
           qemuDiskConfigBlkdeviotuneHasBasic(disk) ||
           qemuDiskConfigBlkdeviotuneHasMax(disk) ||
           qemuDiskConfigBlkdeviotuneHasMaxLength(disk);
}


1239 1240 1241 1242 1243 1244 1245 1246
/**
 * qemuCheckDiskConfigBlkdeviotune:
 * @disk: disk configuration
 * @qemuCaps: qemu capabilities, NULL if checking cold-configuration
 *
 * Checks whether block io tuning settings make sense. Returns -1 on error and
 * reports a proper libvirt error.
 */
1247 1248 1249 1250
static int
qemuCheckDiskConfigBlkdeviotune(virDomainDiskDefPtr disk,
                                virQEMUCapsPtr qemuCaps)
{
1251 1252 1253 1254 1255
    /* group_name by itself is ignored by qemu */
    if (disk->blkdeviotune.group_name &&
        !qemuDiskConfigBlkdeviotuneHasBasic(disk) &&
        !qemuDiskConfigBlkdeviotuneHasMax(disk) &&
        !qemuDiskConfigBlkdeviotuneHasMaxLength(disk)) {
1256
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1257 1258
                       _("group_name can be configured only together with "
                         "settings"));
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280
        return -1;
    }

    if (disk->blkdeviotune.total_bytes_sec > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.read_bytes_sec > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.write_bytes_sec > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.total_iops_sec > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.read_iops_sec > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.write_iops_sec > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.total_bytes_sec_max > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.read_bytes_sec_max > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.write_bytes_sec_max > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.total_iops_sec_max > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.read_iops_sec_max > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.write_iops_sec_max > QEMU_BLOCK_IOTUNE_MAX ||
        disk->blkdeviotune.size_iops_sec > QEMU_BLOCK_IOTUNE_MAX) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
                      _("block I/O throttle limit must "
                        "be no more than %llu using QEMU"), QEMU_BLOCK_IOTUNE_MAX);
        return -1;
    }

1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309
    if (qemuCaps) {
        /* block I/O throttling 1.7 */
        if (qemuDiskConfigBlkdeviotuneHasMax(disk) &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("there are some block I/O throttling parameters "
                             "that are not supported with this QEMU binary"));
            return -1;
        }

        /* block I/O group 2.4 */
        if (disk->blkdeviotune.group_name &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_GROUP)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("the block I/O throttling group parameter is "
                             "not supported with this QEMU binary"));
            return -1;
        }

        /* block I/O throttling length 2.6 */
        if (qemuDiskConfigBlkdeviotuneHasMaxLength(disk) &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("there are some block I/O throttling length parameters "
                             "that are not supported with this QEMU binary"));
            return -1;
        }
    }

1310 1311 1312 1313
    return 0;
}


1314 1315 1316 1317 1318 1319 1320 1321
/**
 * qemuCheckDiskConfig:
 * @disk: disk definition
 * @qemuCaps: qemu capabilities, may be NULL for cold-plug check
 *
 * Perform disk definition config validity checks. Returns -1 on error with
 * error reported.
 */
1322
int
1323 1324
qemuCheckDiskConfig(virDomainDiskDefPtr disk,
                    virQEMUCapsPtr qemuCaps)
1325
{
1326 1327 1328
    if (qemuCheckDiskConfigBlkdeviotune(disk, qemuCaps) < 0)
        return -1;

1329 1330 1331
    if (virDiskNameToIndex(disk->dst) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported disk type '%s'"), disk->dst);
1332
        return -1;
1333 1334 1335 1336 1337 1338 1339
    }

    if (disk->wwn) {
        if ((disk->bus != VIR_DOMAIN_DISK_BUS_IDE) &&
            (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Only ide and scsi disk support wwn"));
1340
            return -1;
1341 1342 1343 1344 1345 1346 1347
        }
    }

    if ((disk->vendor || disk->product) &&
        disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Only scsi disk supports vendor and product"));
1348
            return -1;
1349 1350 1351 1352 1353 1354 1355 1356 1357
    }

    if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
        /* make sure that both the bus supports type='lun' (SG_IO). */
        if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO &&
            disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk device='lun' is not supported for bus='%s'"),
                           virDomainDiskQEMUBusTypeToString(disk->bus));
1358
            return -1;
1359
        }
1360

1361 1362 1363 1364 1365 1366 1367 1368
        if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
            disk->src->format != VIR_STORAGE_FILE_RAW) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("disk device 'lun' using target 'scsi' must use "
                             "'raw' format"));
            return -1;
        }

1369
        if (qemuDomainDefValidateDiskLunSource(disk->src) < 0)
1370
            return -1;
1371

1372 1373 1374
        if (disk->wwn) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting wwn is not supported for lun device"));
1375
            return -1;
1376 1377 1378 1379 1380
        }
        if (disk->vendor || disk->product) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting vendor or product is not supported "
                             "for lun device"));
1381
            return -1;
1382 1383
        }
    }
1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480

    switch (disk->bus) {
    case VIR_DOMAIN_DISK_BUS_SCSI:
        if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unexpected address type for scsi disk"));
            return -1;
        }

        /* Setting bus= attr for SCSI drives, causes a controller
         * to be created. Yes this is slightly odd. It is not possible
         * to have > 1 bus on a SCSI controller (yet). */
        if (disk->info.addr.drive.bus != 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("SCSI controller only supports 1 bus"));
            return -1;
        }
        break;

    case VIR_DOMAIN_DISK_BUS_IDE:
        if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unexpected address type for ide disk"));
            return -1;
        }
        /* We can only have 1 IDE controller (currently) */
        if (disk->info.addr.drive.controller != 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Only 1 IDE controller is supported"));
            return -1;
        }
        break;

    case VIR_DOMAIN_DISK_BUS_FDC:
        if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unexpected address type for fdc disk"));
            return -1;
        }
        /* We can only have 1 FDC controller (currently) */
        if (disk->info.addr.drive.controller != 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Only 1 fdc controller is supported"));
            return -1;
        }
        /* We can only have 1 FDC bus (currently) */
        if (disk->info.addr.drive.bus != 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Only 1 fdc bus is supported"));
            return -1;
        }
        if (disk->info.addr.drive.target != 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("target must be 0 for controller fdc"));
            return -1;
        }
        break;

    case VIR_DOMAIN_DISK_BUS_VIRTIO:
    case VIR_DOMAIN_DISK_BUS_XEN:
    case VIR_DOMAIN_DISK_BUS_SD:
        break;
    }

    if (disk->src->readonly &&
        disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
        if (disk->bus == VIR_DOMAIN_DISK_BUS_IDE) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("readonly ide disks are not supported"));
            return -1;
        }

        if (disk->bus == VIR_DOMAIN_DISK_BUS_SATA) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("readonly sata disks are not supported"));
            return -1;
        }
    }

    if (disk->transient) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("transient disks not supported yet"));
        return -1;
    }

    if (disk->iomode == VIR_DOMAIN_DISK_IO_NATIVE &&
        disk->cachemode != VIR_DOMAIN_DISK_CACHE_DIRECTSYNC &&
        disk->cachemode != VIR_DOMAIN_DISK_CACHE_DISABLE) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("native I/O needs either no disk cache "
                         "or directsync cache mode, QEMU will fallback "
                         "to aio=threads"));
        return -1;
    }

    if (qemuCaps) {
        if (disk->serial &&
1481 1482 1483 1484 1485 1486
            disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
            disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("scsi-block 'lun' devices do not support the "
                             "serial property"));
            return -1;
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503
        }

        if (disk->discard &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_DISCARD)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("discard is not supported by this QEMU binary"));
            return -1;
        }

        if (disk->detect_zeroes &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_DETECT_ZEROES)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("detect_zeroes is not supported by this QEMU binary"));
            return -1;
        }
    }

1504 1505 1506 1507
    if (disk->serial &&
        qemuSafeSerialParamValue(disk->serial) < 0)
        return -1;

1508 1509 1510 1511
    return 0;
}


P
Philipp Hahn 已提交
1512
/* QEMU 1.2 and later have a binary flag -enable-fips that must be
1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
 * used for VNC auth to obey FIPS settings; but the flag only
 * exists on Linux, and with no way to probe for it via QMP.  Our
 * solution: if FIPS mode is required, then unconditionally use
 * the flag, regardless of qemu version, for the following matrix:
 *
 *                          old QEMU            new QEMU
 * FIPS enabled             doesn't start       VNC auth disabled
 * FIPS disabled/missing    VNC auth enabled    VNC auth enabled
 */
bool
qemuCheckFips(void)
{
    bool ret = false;

    if (virFileExists("/proc/sys/crypto/fips_enabled")) {
        char *buf = NULL;

        if (virFileReadAll("/proc/sys/crypto/fips_enabled", 10, &buf) < 0)
            return ret;
        if (STREQ(buf, "1\n"))
            ret = true;
        VIR_FREE(buf);
    }

    return ret;
}


1541 1542 1543 1544 1545 1546 1547 1548 1549 1550
/**
 * qemuDiskBusNeedsDriveArg:
 * @bus: disk bus
 *
 * Unfortunately it is not possible to use -device for SD devices.
 * Fortunately, those don't need static PCI addresses, so we can use -drive
 * without -device.
 */
bool
qemuDiskBusNeedsDriveArg(int bus)
J
Ján Tomko 已提交
1551
{
1552
    return bus == VIR_DOMAIN_DISK_BUS_SD;
J
Ján Tomko 已提交
1553 1554 1555
}


1556 1557 1558 1559 1560 1561 1562 1563 1564
/**
 * qemuDiskSourceNeedsProps:
 * @src: disk source
 *
 * Returns true, if the disk source needs to be generated from the JSON
 * representation. Otherwise, the disk source should be represented using
 * the legacy representation.
 */
static bool
1565 1566
qemuDiskSourceNeedsProps(virStorageSourcePtr src,
                         virQEMUCapsPtr qemuCaps)
1567 1568 1569 1570 1571 1572 1573 1574
{
    int actualType = virStorageSourceGetActualType(src);

    if (actualType == VIR_STORAGE_TYPE_NETWORK &&
        src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER &&
        src->nhosts > 1)
        return true;

1575 1576 1577 1578
    if (actualType == VIR_STORAGE_TYPE_NETWORK &&
        src->protocol == VIR_STORAGE_NET_PROTOCOL_VXHS)
        return true;

1579 1580 1581 1582 1583
    if (actualType == VIR_STORAGE_TYPE_NETWORK &&
        src->protocol == VIR_STORAGE_NET_PROTOCOL_ISCSI &&
        virQEMUCapsGet(qemuCaps, QEMU_CAPS_ISCSI_PASSWORD_SECRET))
        return true;

1584 1585 1586 1587 1588
    if (actualType == VIR_STORAGE_TYPE_NETWORK &&
        src->protocol == VIR_STORAGE_NET_PROTOCOL_NBD &&
        src->haveTLS == VIR_TRISTATE_BOOL_YES)
        return true;

1589 1590 1591 1592
    return false;
}


1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
/**
 * qemuDiskSourceGetProps:
 * @src: disk source struct
 *
 * Returns the disk source struct wrapped so that it can be used as disk source
 * directly by converting it from json.
 */
static virJSONValuePtr
qemuDiskSourceGetProps(virStorageSourcePtr src)
{
    virJSONValuePtr props;
    virJSONValuePtr ret;

1606
    if (!(props = qemuBlockStorageSourceGetBackendProps(src, true)))
1607 1608
        return NULL;

1609
    if (virJSONValueObjectCreate(&ret, "a:file", &props, NULL) < 0) {
1610 1611 1612 1613 1614 1615 1616 1617
        virJSONValueFree(props);
        return NULL;
    }

    return ret;
}


1618 1619 1620 1621 1622 1623 1624
static int
qemuBuildDriveSourcePR(virBufferPtr buf,
                       virDomainDiskDefPtr disk)
{
    char *alias = NULL;
    const char *defaultAlias = NULL;

1625
    if (!disk->src->pr)
1626 1627 1628 1629
        return 0;

    if (virStoragePRDefIsManaged(disk->src->pr))
        defaultAlias = qemuDomainGetManagedPRAlias();
1630
    else if (!(alias = qemuDomainGetUnmanagedPRAlias(disk->info.alias)))
1631 1632 1633 1634 1635 1636 1637 1638 1639
        return -1;


    virBufferAsprintf(buf, ",file.pr-manager=%s", alias ? alias : defaultAlias);
    VIR_FREE(alias);
    return 0;
}


1640 1641
static int
qemuBuildDriveSourceStr(virDomainDiskDefPtr disk,
1642
                        virQEMUCapsPtr qemuCaps,
1643
                        virBufferPtr buf)
1644 1645
{
    int actualType = virStorageSourceGetActualType(disk->src);
1646
    qemuDomainStorageSourcePrivatePtr srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(disk->src);
1647 1648
    qemuDomainSecretInfoPtr secinfo = NULL;
    qemuDomainSecretInfoPtr encinfo = NULL;
1649
    virJSONValuePtr srcprops = NULL;
1650
    char *source = NULL;
1651
    bool rawluks = false;
1652 1653
    int ret = -1;

1654 1655 1656 1657 1658
    if (srcpriv) {
        secinfo = srcpriv->secinfo;
        encinfo = srcpriv->encinfo;
    }

1659
    if (qemuDiskSourceNeedsProps(disk->src, qemuCaps) &&
1660
        !(srcprops = qemuDiskSourceGetProps(disk->src)))
1661 1662 1663 1664
        goto cleanup;

    if (!srcprops &&
        qemuGetDriveSourceString(disk->src, secinfo, &source) < 0)
1665 1666
        goto cleanup;

1667
    /* nothing to format if the drive is empty */
1668
    if (!(source || srcprops) ||
1669 1670 1671 1672 1673 1674
        ((disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY ||
          disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
         disk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN)) {
        ret = 0;
        goto cleanup;
    }
1675

1676 1677 1678 1679 1680 1681 1682 1683
    if (actualType == VIR_STORAGE_TYPE_BLOCK &&
        disk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       disk->src->type == VIR_STORAGE_TYPE_VOLUME ?
                       _("tray status 'open' is invalid for block type volume") :
                       _("tray status 'open' is invalid for block type disk"));
        goto cleanup;
    }
1684

1685 1686
    if (source) {
        virBufferAddLit(buf, "file=");
1687

1688 1689 1690 1691 1692 1693
        /* for now the DIR based storage is handled by the magic FAT format */
        if (actualType == VIR_STORAGE_TYPE_DIR) {
            virBufferAddLit(buf, "fat:");

            if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
                virBufferAddLit(buf, "floppy:");
1694 1695
        }

1696
        virQEMUBuildBufferEscapeComma(buf, source);
1697 1698 1699

        if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES)
            virBufferAsprintf(buf, ",file.password-secret=%s", secinfo->s.aes.alias);
1700 1701 1702

        if (disk->src->debug)
            virBufferAsprintf(buf, ",file.debug=%d", disk->src->debugLevel);
1703 1704 1705

        if (qemuBuildDriveSourcePR(buf, disk) < 0)
            goto cleanup;
1706 1707 1708
    } else {
        if (!(source = virQEMUBuildDriveCommandlineFromJSON(srcprops)))
            goto cleanup;
1709

1710
        virBufferAdd(buf, source, -1);
1711 1712
    }
    virBufferAddLit(buf, ",");
1713

1714 1715 1716 1717 1718 1719 1720 1721 1722 1723
    if (encinfo) {
        if (disk->src->format == VIR_STORAGE_FILE_RAW) {
            virBufferAsprintf(buf, "key-secret=%s,", encinfo->s.aes.alias);
            rawluks = true;
        } else if (disk->src->format == VIR_STORAGE_FILE_QCOW2 &&
                   disk->src->encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
            virBufferAddLit(buf, "encrypt.format=luks,");
            virBufferAsprintf(buf, "encrypt.key-secret=%s,", encinfo->s.aes.alias);
        }
    }
1724 1725

    if (disk->src->format > 0 &&
1726 1727
        disk->src->type != VIR_STORAGE_TYPE_DIR) {
        const char *qemuformat = virStorageFileFormatTypeToString(disk->src->format);
1728
        if (rawluks)
1729 1730 1731
            qemuformat = "luks";
        virBufferAsprintf(buf, "format=%s,", qemuformat);
    }
1732

1733 1734 1735 1736
    ret = 0;

 cleanup:
    VIR_FREE(source);
1737
    virJSONValueFree(srcprops);
1738 1739 1740 1741
    return ret;
}


1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767
static void
qemuBuildDiskThrottling(virDomainDiskDefPtr disk,
                        virBufferPtr buf)
{
#define IOTUNE_ADD(_field, _label) \
    if (disk->blkdeviotune._field) { \
        virBufferAsprintf(buf, ",throttling." _label "=%llu", \
                          disk->blkdeviotune._field); \
    }

    IOTUNE_ADD(total_bytes_sec, "bps-total");
    IOTUNE_ADD(read_bytes_sec, "bps-read");
    IOTUNE_ADD(write_bytes_sec, "bps-write");
    IOTUNE_ADD(total_iops_sec, "iops-total");
    IOTUNE_ADD(read_iops_sec, "iops-read");
    IOTUNE_ADD(write_iops_sec, "iops-write");

    IOTUNE_ADD(total_bytes_sec_max, "bps-total-max");
    IOTUNE_ADD(read_bytes_sec_max, "bps-read-max");
    IOTUNE_ADD(write_bytes_sec_max, "bps-write-max");
    IOTUNE_ADD(total_iops_sec_max, "iops-total-max");
    IOTUNE_ADD(read_iops_sec_max, "iops-read-max");
    IOTUNE_ADD(write_iops_sec_max, "iops-write-max");

    IOTUNE_ADD(size_iops_sec, "iops-size");
    if (disk->blkdeviotune.group_name) {
1768 1769
        virBufferAddLit(buf, ",throttling.group=");
        virQEMUBuildBufferEscapeComma(buf, disk->blkdeviotune.group_name);
1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781
    }

    IOTUNE_ADD(total_bytes_sec_max_length, "bps-total-max-length");
    IOTUNE_ADD(read_bytes_sec_max_length, "bps-read-max-length");
    IOTUNE_ADD(write_bytes_sec_max_length, "bps-write-max-length");
    IOTUNE_ADD(total_iops_sec_max_length, "iops-total-max-length");
    IOTUNE_ADD(read_iops_sec_max_length, "iops-read-max-length");
    IOTUNE_ADD(write_iops_sec_max_length, "iops-write-max-length");
#undef IOTUNE_ADD
}


1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812
static void
qemuBuildDiskFrontendAttributeErrorPolicy(virDomainDiskDefPtr disk,
                                          virBufferPtr buf)
{
    const char *wpolicy = NULL;
    const char *rpolicy = NULL;

    if (disk->error_policy)
        wpolicy = virDomainDiskErrorPolicyTypeToString(disk->error_policy);

    if (disk->rerror_policy)
        rpolicy = virDomainDiskErrorPolicyTypeToString(disk->rerror_policy);

    if (disk->error_policy == VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE) {
        /* in the case of enospace, the option is spelled
         * differently in qemu, and it's only valid for werror,
         * not for rerror, so leave rerror NULL.
         */
        wpolicy = "enospc";
    } else if (!rpolicy) {
        /* for other policies, rpolicy can match wpolicy */
        rpolicy = wpolicy;
    }

    if (wpolicy)
        virBufferAsprintf(buf, ",werror=%s", wpolicy);
    if (rpolicy)
        virBufferAsprintf(buf, ",rerror=%s", rpolicy);
}


1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826
static void
qemuBuildDiskFrontendAttributes(virDomainDiskDefPtr disk,
                                virBufferPtr buf)
{
    /* generate geometry command string */
    if (disk->geometry.cylinders > 0 &&
        disk->geometry.heads > 0 &&
        disk->geometry.sectors > 0) {
        virBufferAsprintf(buf, ",cyls=%u,heads=%u,secs=%u",
                          disk->geometry.cylinders,
                          disk->geometry.heads,
                          disk->geometry.sectors);

        if (disk->geometry.trans != VIR_DOMAIN_DISK_TRANS_DEFAULT)
1827
            virBufferAsprintf(buf, ",bios-chs-trans=%s",
1828 1829
                              virDomainDiskGeometryTransTypeToString(disk->geometry.trans));
    }
1830

1831
    if (disk->serial) {
1832 1833 1834
        virBufferAddLit(buf, ",serial=");
        virBufferEscape(buf, '\\', " ", "%s", disk->serial);
    }
1835 1836 1837
}


1838
static char *
1839 1840 1841 1842
qemuBuildDriveStr(virDomainDiskDefPtr disk,
                  virQEMUCapsPtr qemuCaps)
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;
1843 1844
    int detect_zeroes = virDomainDiskGetDetectZeroesMode(disk->discard,
                                                         disk->detect_zeroes);
1845

1846
    if (qemuBuildDriveSourceStr(disk, qemuCaps, &opt) < 0)
1847 1848
        goto error;

1849
    if (!qemuDiskBusNeedsDriveArg(disk->bus)) {
1850
        char *drivealias = qemuAliasDiskDriveFromDisk(disk);
1851 1852
        if (!drivealias)
            goto error;
1853 1854

        virBufferAddLit(&opt, "if=none");
1855 1856
        virBufferAsprintf(&opt, ",id=%s", drivealias);
        VIR_FREE(drivealias);
1857
    } else {
1858 1859 1860 1861 1862 1863 1864
        int idx = virDiskNameToIndex(disk->dst);

        if (idx < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unsupported disk type '%s'"), disk->dst);
            goto error;
        }
1865 1866 1867 1868 1869 1870 1871

        /* if we are using -device this will be checked elsewhere */
        if (qemuCheckDiskConfig(disk, qemuCaps) < 0)
            goto error;

        virBufferAsprintf(&opt, "if=%s",
                          virDomainDiskQEMUBusTypeToString(disk->bus));
1872
        virBufferAsprintf(&opt, ",index=%d", idx);
1873
    }
1874

1875 1876
    /* werror/rerror are really frontend attributes, but older
     * qemu requires them on -drive instead of -device */
1877 1878
    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_STORAGE_WERROR))
        qemuBuildDiskFrontendAttributeErrorPolicy(disk, &opt);
1879

1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890
    if (disk->src->readonly)
        virBufferAddLit(&opt, ",readonly=on");

    /* qemu rejects some parameters for an empty -drive, so we need to skip
     * them in that case:
     * cache: modifies properties of the format driver which is not present
     * copy_on_read: really only works for floppies
     * discard: modifies properties of format driver
     * detect_zeroes: works but really depends on discard so it's useless
     * iomode: setting it to 'native' requires a specific cache mode
     */
1891 1892 1893 1894 1895
    if (!virStorageSourceIsEmpty(disk->src)) {
        if (disk->cachemode) {
            virBufferAsprintf(&opt, ",cache=%s",
                              qemuDiskCacheV2TypeToString(disk->cachemode));
        }
1896

1897 1898 1899 1900
        if (disk->copy_on_read) {
            virBufferAsprintf(&opt, ",copy-on-read=%s",
                              virTristateSwitchTypeToString(disk->copy_on_read));
        }
1901

1902 1903 1904 1905
        if (disk->discard) {
            virBufferAsprintf(&opt, ",discard=%s",
                              virDomainDiskDiscardTypeToString(disk->discard));
        }
O
Osier Yang 已提交
1906

1907 1908 1909 1910
        if (detect_zeroes) {
            virBufferAsprintf(&opt, ",detect-zeroes=%s",
                              virDomainDiskDetectZeroesTypeToString(detect_zeroes));
        }
O
Osier Yang 已提交
1911

1912 1913 1914 1915
        if (disk->iomode) {
            virBufferAsprintf(&opt, ",aio=%s",
                              virDomainDiskIoTypeToString(disk->iomode));
        }
E
Eric Blake 已提交
1916 1917
    }

1918 1919
    qemuBuildDiskThrottling(disk, &opt);

1920
    if (virBufferCheckError(&opt) < 0)
1921 1922 1923 1924
        goto error;

    return virBufferContentAndReset(&opt);

1925
 error:
1926 1927 1928 1929
    virBufferFreeAndReset(&opt);
    return NULL;
}

1930

1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973
static bool
qemuCheckIOThreads(const virDomainDef *def,
                   virDomainDiskDefPtr disk)
{
    /* Right "type" of disk" */
    switch ((virDomainDiskBus)disk->bus) {
    case VIR_DOMAIN_DISK_BUS_VIRTIO:
        if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
            disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("IOThreads only available for virtio pci and "
                              "virtio ccw disk"));
            return false;
        }
        break;

    case VIR_DOMAIN_DISK_BUS_IDE:
    case VIR_DOMAIN_DISK_BUS_FDC:
    case VIR_DOMAIN_DISK_BUS_SCSI:
    case VIR_DOMAIN_DISK_BUS_XEN:
    case VIR_DOMAIN_DISK_BUS_USB:
    case VIR_DOMAIN_DISK_BUS_UML:
    case VIR_DOMAIN_DISK_BUS_SATA:
    case VIR_DOMAIN_DISK_BUS_SD:
    case VIR_DOMAIN_DISK_BUS_LAST:
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("IOThreads not available for bus %s target %s"),
                       virDomainDiskBusTypeToString(disk->bus), disk->dst);
        return false;
    }

    /* Can we find the disk iothread in the iothreadid list? */
    if (!virDomainIOThreadIDFind(def, disk->iothread)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Disk iothread '%u' not defined in iothreadid"),
                       disk->iothread);
        return false;
    }

    return true;
}


1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
static int
qemuBuildDriveDevCacheStr(virDomainDiskDefPtr disk,
                          virBufferPtr buf,
                          virQEMUCapsPtr qemuCaps)
{
    bool wb;

    if (disk->cachemode == VIR_DOMAIN_DISK_CACHE_DEFAULT)
        return 0;

1984 1985 1986 1987 1988
    /* VIR_DOMAIN_DISK_DEVICE_LUN translates into 'scsi-block'
     * where any caching setting makes no sense. */
    if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN)
        return 0;

1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_WRITE_CACHE))
        return 0;

    if (qemuDomainDiskCachemodeFlags(disk->cachemode, &wb, NULL, NULL) < 0)
        return -1;

    virBufferStrcat(buf, ",write-cache=",
                    virTristateSwitchTypeToString(virTristateSwitchFromBool(wb)),
                    NULL);

    return 0;
}


2003
char *
2004 2005 2006 2007
qemuBuildDiskDeviceStr(const virDomainDef *def,
                       virDomainDiskDefPtr disk,
                       unsigned int bootindex,
                       virQEMUCapsPtr qemuCaps)
2008 2009 2010
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;
    const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
2011
    const char *contAlias;
2012
    char *backendAlias = NULL;
2013
    VIR_AUTOFREE(char *) scsiVPDDeviceId = NULL;
2014
    int controllerModel;
2015

2016
    if (qemuCheckDiskConfig(disk, qemuCaps) < 0)
2017
        goto error;
2018

2019
    if (!qemuDomainCheckCCWS390AddressSupport(def, &disk->info, qemuCaps, disk->dst))
2020 2021
        goto error;

2022 2023 2024
    if (disk->iothread && !qemuCheckIOThreads(def, disk))
        goto error;

2025
    switch ((virDomainDiskBus) disk->bus) {
2026
    case VIR_DOMAIN_DISK_BUS_IDE:
2027
        if (disk->info.addr.drive.target != 0) {
2028 2029
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("target must be 0 for ide controller"));
2030 2031
            goto error;
        }
2032

2033
        if (disk->wwn &&
2034
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_IDE_DRIVE_WWN)) {
2035 2036 2037 2038 2039 2040
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting wwn for ide disk is not supported "
                             "by this QEMU"));
            goto error;
        }

2041 2042 2043 2044
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
            virBufferAddLit(&opt, "ide-cd");
        else
            virBufferAddLit(&opt, "ide-hd");
2045

2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056
        /* When domain has builtin IDE controller we don't put it onto cmd
         * line. Therefore we can't set its alias. In that case, use the
         * default one. */
        if (qemuDomainHasBuiltinIDE(def)) {
            contAlias = "ide";
        } else {
            if (!(contAlias = virDomainControllerAliasFind(def,
                                                           VIR_DOMAIN_CONTROLLER_TYPE_IDE,
                                                           disk->info.addr.drive.controller)))
                goto error;
        }
2057 2058
        virBufferAsprintf(&opt, ",bus=%s.%d,unit=%d",
                          contAlias,
2059 2060 2061
                          disk->info.addr.drive.bus,
                          disk->info.addr.drive.unit);
        break;
2062

2063
    case VIR_DOMAIN_DISK_BUS_SCSI:
2064
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
2065
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_BLOCK)) {
2066 2067 2068
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("This QEMU doesn't support scsi-block for "
                                 "lun passthrough"));
2069 2070 2071 2072
                goto error;
            }
        }

2073
        if (disk->wwn &&
2074
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_DISK_WWN)) {
2075 2076 2077 2078 2079 2080
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting wwn for scsi disk is not supported "
                             "by this QEMU"));
            goto error;
        }

2081 2082 2083 2084
        /* Properties wwn, vendor and product were introduced in the
         * same QEMU release (1.2.0).
         */
        if ((disk->vendor || disk->product) &&
2085
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_DISK_WWN)) {
2086 2087 2088 2089 2090 2091
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting vendor or product for scsi disk is not "
                             "supported by this QEMU"));
            goto error;
        }

2092
        controllerModel = qemuDomainFindSCSIControllerModel(def, &disk->info);
2093
        if (controllerModel < 0)
2094
            goto error;
2095

2096 2097 2098
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
            virBufferAddLit(&opt, "scsi-block");
        } else {
2099 2100 2101 2102
            if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
                virBufferAddLit(&opt, "scsi-cd");
            else
                virBufferAddLit(&opt, "scsi-hd");
2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117

            /* qemu historically used the name of -drive as one of the device
             * ids in the Vital Product Data Device Identification page if
             * disk serial was not set and the disk serial otherwise.
             * To avoid a guest-visible regression we need to provide it
             * ourselves especially for cases when -blockdev will be used */
            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_DISK_DEVICE_ID)) {
                if (disk->serial) {
                    if (VIR_STRDUP(scsiVPDDeviceId, disk->serial) < 0)
                        goto error;
                } else {
                    if (!(scsiVPDDeviceId = qemuAliasDiskDriveFromDisk(disk)))
                        goto error;
                }
            }
2118 2119
        }

2120 2121 2122 2123
        if (!(contAlias = virDomainControllerAliasFind(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
                                                       disk->info.addr.drive.controller)))
           goto error;

2124 2125
        if (controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) {
            if (disk->info.addr.drive.target != 0) {
2126 2127 2128
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("target must be 0 for controller "
                                 "model 'lsilogic'"));
2129 2130 2131
                goto error;
            }

2132 2133
            virBufferAsprintf(&opt, ",bus=%s.%d,scsi-id=%d",
                              contAlias,
2134 2135 2136
                              disk->info.addr.drive.bus,
                              disk->info.addr.drive.unit);
        } else {
2137
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_DISK_CHANNEL)) {
2138
                if (disk->info.addr.drive.target > 7) {
2139 2140 2141
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                   _("This QEMU doesn't support target "
                                     "greater than 7"));
2142 2143 2144
                    goto error;
                }

2145 2146
                if (disk->info.addr.drive.bus != 0 &&
                    disk->info.addr.drive.unit != 0) {
2147 2148 2149
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                   _("This QEMU only supports both bus and "
                                     "unit equal to 0"));
2150 2151 2152 2153
                    goto error;
                }
            }

2154 2155
            virBufferAsprintf(&opt, ",bus=%s.0,channel=%d,scsi-id=%d,lun=%d",
                              contAlias,
2156 2157 2158 2159
                              disk->info.addr.drive.bus,
                              disk->info.addr.drive.target,
                              disk->info.addr.drive.unit);
        }
2160 2161 2162 2163

        if (scsiVPDDeviceId)
            virBufferStrcat(&opt, ",device_id=", scsiVPDDeviceId, NULL);

2164
        break;
2165

J
Jim Fehlig 已提交
2166
    case VIR_DOMAIN_DISK_BUS_SATA:
2167
        if (disk->info.addr.drive.bus != 0) {
2168 2169
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("bus must be 0 for ide controller"));
2170 2171 2172
            goto error;
        }
        if (disk->info.addr.drive.target != 0) {
2173 2174
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("target must be 0 for ide controller"));
2175 2176
            goto error;
        }
2177

2178 2179 2180 2181
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
            virBufferAddLit(&opt, "ide-cd");
        else
            virBufferAddLit(&opt, "ide-hd");
2182

2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194
        /* When domain has builtin SATA controller we don't put it onto cmd
         * line. Therefore we can't set its alias. In that case, use the
         * default one. */
        if (qemuDomainIsQ35(def) &&
            disk->info.addr.drive.controller == 0) {
            contAlias = "ide";
        } else {
            if (!(contAlias = virDomainControllerAliasFind(def,
                                                           VIR_DOMAIN_CONTROLLER_TYPE_SATA,
                                                           disk->info.addr.drive.controller)))
                goto error;
        }
2195 2196 2197
        virBufferAsprintf(&opt, ",bus=%s.%d",
                          contAlias,
                          disk->info.addr.drive.unit);
J
Jim Fehlig 已提交
2198
        break;
2199

2200
    case VIR_DOMAIN_DISK_BUS_VIRTIO:
2201
        if (qemuBuildVirtioDevStr(&opt, "virtio-blk", qemuCaps,
2202
                                  VIR_DOMAIN_DEVICE_DISK, disk) < 0) {
2203
            goto error;
2204
        }
2205

2206
        if (disk->iothread)
2207 2208
            virBufferAsprintf(&opt, ",iothread=iothread%u", disk->iothread);

2209
        qemuBuildIoEventFdStr(&opt, disk->ioeventfd, qemuCaps);
2210
        if (disk->event_idx &&
2211
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_EVENT_IDX)) {
2212
            virBufferAsprintf(&opt, ",event_idx=%s",
J
Ján Tomko 已提交
2213
                              virTristateSwitchTypeToString(disk->event_idx));
2214
        }
2215
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SCSI)) {
2216 2217 2218 2219 2220 2221 2222
            /* if sg_io is true but the scsi option isn't supported,
             * that means it's just always on in this version of qemu.
             */
            virBufferAsprintf(&opt, ",scsi=%s",
                              (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN)
                              ? "on" : "off");
        }
2223

L
Lin Ma 已提交
2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234
        if (disk->queues) {
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_NUM_QUEUES)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("num-queues property isn't supported by this "
                                 "QEMU binary"));
                goto error;
            }

            virBufferAsprintf(&opt, ",num-queues=%u", disk->queues);
        }

2235 2236 2237
        if (qemuBuildVirtioOptionsStr(&opt, disk->virtio, qemuCaps) < 0)
            goto error;

2238
        if (qemuBuildDeviceAddressStr(&opt, def, &disk->info, qemuCaps) < 0)
A
Alex Jia 已提交
2239
            goto error;
2240
        break;
2241

2242
    case VIR_DOMAIN_DISK_BUS_USB:
2243 2244 2245 2246 2247 2248
        if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
            disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unexpected address type for usb disk"));
            goto error;
        }
2249 2250 2251 2252 2253 2254 2255
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("This QEMU doesn't support '-device "
                             "usb-storage'"));
            goto error;

        }
2256
        virBufferAddLit(&opt, "usb-storage");
2257

2258
        if (qemuBuildDeviceAddressStr(&opt, def, &disk->info, qemuCaps) < 0)
2259
            goto error;
2260
        break;
2261

2262 2263 2264 2265
    case VIR_DOMAIN_DISK_BUS_FDC:
        virBufferAsprintf(&opt, "floppy,unit=%d", disk->info.addr.drive.unit);
        break;

2266 2267 2268 2269
    case VIR_DOMAIN_DISK_BUS_XEN:
    case VIR_DOMAIN_DISK_BUS_UML:
    case VIR_DOMAIN_DISK_BUS_SD:
    case VIR_DOMAIN_DISK_BUS_LAST:
2270
    default:
2271 2272
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported disk bus '%s' with device setup"), bus);
2273 2274
        goto error;
    }
2275

2276 2277 2278 2279
    if (disk->src->shared &&
        virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_SHARE_RW))
        virBufferAddLit(&opt, ",share-rw=on");

2280
    if (qemuDomainDiskGetBackendAlias(disk, qemuCaps, &backendAlias) < 0)
2281
        goto error;
2282 2283 2284 2285 2286 2287

    if (backendAlias)
        virBufferAsprintf(&opt, ",drive=%s", backendAlias);
    VIR_FREE(backendAlias);

    virBufferAsprintf(&opt, ",id=%s", disk->info.alias);
2288
    if (bootindex)
2289
        virBufferAsprintf(&opt, ",bootindex=%u", bootindex);
2290
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKIO)) {
V
Viktor Mihajlovski 已提交
2291
        if (disk->blockio.logical_block_size > 0)
2292
            virBufferAsprintf(&opt, ",logical_block_size=%u",
V
Viktor Mihajlovski 已提交
2293 2294
                              disk->blockio.logical_block_size);
        if (disk->blockio.physical_block_size > 0)
2295
            virBufferAsprintf(&opt, ",physical_block_size=%u",
V
Viktor Mihajlovski 已提交
2296
                              disk->blockio.physical_block_size);
2297
    }
2298

2299 2300 2301 2302 2303 2304
    if (disk->wwn) {
        if (STRPREFIX(disk->wwn, "0x"))
            virBufferAsprintf(&opt, ",wwn=%s", disk->wwn);
        else
            virBufferAsprintf(&opt, ",wwn=0x%s", disk->wwn);
    }
2305

2306 2307 2308 2309
    if (disk->vendor) {
        virBufferAddLit(&opt, ",vendor=");
        virQEMUBuildBufferEscapeComma(&opt, disk->vendor);
    }
2310

2311 2312 2313 2314
    if (disk->product) {
        virBufferAddLit(&opt, ",product=");
        virQEMUBuildBufferEscapeComma(&opt, disk->product);
    }
2315

2316 2317
    if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_STORAGE_REMOVABLE)) {
J
Ján Tomko 已提交
2318
            if (disk->removable == VIR_TRISTATE_SWITCH_ON)
2319 2320 2321 2322
                virBufferAddLit(&opt, ",removable=on");
            else
                virBufferAddLit(&opt, ",removable=off");
        } else {
J
Ján Tomko 已提交
2323
            if (disk->removable != VIR_TRISTATE_SWITCH_ABSENT) {
2324 2325 2326 2327 2328 2329 2330 2331
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("This QEMU doesn't support setting the "
                                 "removable flag of USB storage devices"));
                goto error;
            }
        }
    }

2332 2333 2334
    if (qemuBuildDriveDevCacheStr(disk, &opt, qemuCaps) < 0)
        goto error;

2335 2336
    qemuBuildDiskFrontendAttributes(disk, &opt);

2337 2338 2339
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_STORAGE_WERROR))
        qemuBuildDiskFrontendAttributeErrorPolicy(disk, &opt);

2340
    if (virBufferCheckError(&opt) < 0)
2341 2342 2343 2344
        goto error;

    return virBufferContentAndReset(&opt);

2345
 error:
2346
    VIR_FREE(backendAlias);
2347 2348 2349 2350
    virBufferFreeAndReset(&opt);
    return NULL;
}

2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401
char *
qemuBuildZPCIDevStr(virDomainDeviceInfoPtr dev)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virBufferAsprintf(&buf,
                      "zpci,uid=%u,fid=%u,target=%s,id=zpci%u",
                      dev->addr.pci.zpci.uid,
                      dev->addr.pci.zpci.fid,
                      dev->alias,
                      dev->addr.pci.zpci.uid);

    if (virBufferCheckError(&buf) < 0) {
        virBufferFreeAndReset(&buf);
        return NULL;
    }

    return virBufferContentAndReset(&buf);
}

static int
qemuCommandAddZPCIDevice(virCommandPtr cmd,
                         virDomainDeviceInfoPtr dev)
{
    char *devstr = NULL;

    virCommandAddArg(cmd, "-device");

    if (!(devstr = qemuBuildZPCIDevStr(dev)))
        return -1;

    virCommandAddArg(cmd, devstr);

    VIR_FREE(devstr);
    return 0;
}

static int
qemuCommandAddExtDevice(virCommandPtr cmd,
                        virDomainDeviceInfoPtr dev)
{
    if (dev->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
        dev->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
        return 0;
    }

    if (dev->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
        return qemuCommandAddZPCIDevice(cmd, dev);

    return 0;
}
2402

2403
static int
2404 2405 2406 2407
qemuBuildFloppyCommandLineControllerOptions(virCommandPtr cmd,
                                            const virDomainDef *def,
                                            virQEMUCapsPtr qemuCaps,
                                            unsigned int bootFloppy)
2408 2409
{
    virBuffer fdc_opts = VIR_BUFFER_INITIALIZER;
2410 2411 2412
    bool explicitfdc = qemuDomainNeedsFDC(def);
    bool hasfloppy = false;
    unsigned int bootindex;
2413
    char driveLetter;
2414
    char *backendAlias = NULL;
2415 2416
    char *backendStr = NULL;
    char *bootindexStr = NULL;
2417
    size_t i;
2418
    int ret = -1;
2419

2420
    virBufferAddLit(&fdc_opts, "isa-fdc,");
2421

2422 2423
    for (i = 0; i < def->ndisks; i++) {
        virDomainDiskDefPtr disk = def->disks[i];
2424

2425 2426
        if (disk->bus != VIR_DOMAIN_DISK_BUS_FDC)
            continue;
2427

2428
        hasfloppy = true;
2429

2430 2431 2432 2433 2434
        if (disk->info.bootIndex) {
            bootindex = disk->info.bootIndex;
        } else {
            bootindex = bootFloppy;
            bootFloppy = 0;
2435 2436
        }

2437 2438 2439 2440 2441 2442 2443 2444 2445
        if (disk->info.addr.drive.unit)
            driveLetter = 'B';
        else
            driveLetter = 'A';

        if (bootindex &&
            virAsprintf(&bootindexStr, "bootindex%c=%u", driveLetter, bootindex) < 0)
            goto cleanup;

2446 2447 2448 2449 2450 2451 2452 2453 2454 2455
        /* with -blockdev we setup the floppy device and it's backend with -device */
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) {
            if (qemuDomainDiskGetBackendAlias(disk, qemuCaps, &backendAlias) < 0)
                goto cleanup;

            if (backendAlias &&
                virAsprintf(&backendStr, "drive%c=%s", driveLetter, backendAlias) < 0)
                goto cleanup;
        }

2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468
        if (!explicitfdc) {
            if (backendStr) {
                virCommandAddArg(cmd, "-global");
                virCommandAddArgFormat(cmd, "isa-fdc.%s", backendStr);
            }

            if (bootindexStr) {
                virCommandAddArg(cmd, "-global");
                virCommandAddArgFormat(cmd, "isa-fdc.%s", bootindexStr);
            }
        } else {
            virBufferStrcat(&fdc_opts, backendStr, ",", NULL);
            virBufferStrcat(&fdc_opts, bootindexStr, ",", NULL);
2469
        }
2470 2471 2472 2473 2474 2475 2476

        VIR_FREE(backendAlias);
        VIR_FREE(backendStr);
        VIR_FREE(bootindexStr);
    }

    if (explicitfdc && hasfloppy) {
2477 2478
        /* Newer Q35 machine types require an explicit FDC controller */
        virBufferTrim(&fdc_opts, ",", -1);
2479
        virCommandAddArg(cmd, "-device");
2480
        virCommandAddArgBuffer(cmd, &fdc_opts);
2481 2482
    }

2483 2484 2485 2486
    ret = 0;

 cleanup:
    VIR_FREE(backendAlias);
2487 2488
    VIR_FREE(backendStr);
    VIR_FREE(bootindexStr);
2489
    virBufferFreeAndReset(&fdc_opts);
2490
    return ret;
2491 2492 2493
}


2494
static int
2495 2496
qemuBuildObjectCommandline(virCommandPtr cmd,
                           virJSONValuePtr objProps)
2497 2498 2499
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

2500
    if (!objProps)
2501 2502
        return 0;

2503 2504
    if (virQEMUBuildObjectCommandlineFromJSON(&buf, objProps) < 0) {
        virBufferFreeAndReset(&buf);
2505
        return -1;
2506
    }
2507 2508 2509 2510

    virCommandAddArg(cmd, "-object");
    virCommandAddArgBuffer(cmd, &buf);

2511 2512 2513 2514 2515 2516 2517 2518
    return 0;
}


static int
qemuBuildBlockStorageSourceAttachDataCommandline(virCommandPtr cmd,
                                                 qemuBlockStorageSourceAttachDataPtr data)
{
2519 2520
    char *tmp;

2521 2522 2523 2524 2525 2526 2527 2528 2529
    if (qemuBuildObjectCommandline(cmd, data->prmgrProps) < 0 ||
        qemuBuildObjectCommandline(cmd, data->authsecretProps) < 0 ||
        qemuBuildObjectCommandline(cmd, data->encryptsecretProps) < 0 ||
        qemuBuildObjectCommandline(cmd, data->tlsProps) < 0)
        return -1;

    if (data->driveCmd)
        virCommandAddArgList(cmd, "-drive", data->driveCmd, NULL);

2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545
    if (data->storageProps) {
        if (!(tmp = virJSONValueToString(data->storageProps, false)))
            return -1;

        virCommandAddArgList(cmd, "-blockdev", tmp, NULL);
        VIR_FREE(tmp);
    }

    if (data->formatProps) {
        if (!(tmp = virJSONValueToString(data->formatProps, false)))
            return -1;

        virCommandAddArgList(cmd, "-blockdev", tmp, NULL);
        VIR_FREE(tmp);
    }

2546
    return 0;
2547 2548 2549
}


2550
static int
2551 2552
qemuBuildDiskSourceCommandLine(virCommandPtr cmd,
                               virDomainDiskDefPtr disk,
2553
                               virQEMUCapsPtr qemuCaps)
2554
{
2555 2556 2557 2558 2559 2560 2561
    qemuBlockStorageSourceAttachDataPtr *data = NULL;
    size_t ndata = 0;
    qemuBlockStorageSourceAttachDataPtr tmp = NULL;
    virJSONValuePtr copyOnReadProps = NULL;
    virStorageSourcePtr n;
    char *str = NULL;
    size_t i;
2562
    int ret = -1;
2563

2564 2565 2566 2567 2568
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) {
        if (virStorageSourceIsEmpty(disk->src)) {
            ret = 0;
            goto cleanup;
        }
2569

2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608
        for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) {
            if (!(tmp = qemuBlockStorageSourceAttachPrepareBlockdev(n)))
                goto cleanup;

            if (qemuBuildStorageSourceAttachPrepareCommon(n, tmp, qemuCaps) < 0)
                goto cleanup;

            if (VIR_APPEND_ELEMENT(data, ndata, tmp) < 0)
                goto cleanup;
        }

        if (disk->copy_on_read == VIR_TRISTATE_SWITCH_ON &&
            !(copyOnReadProps = qemuBlockStorageGetCopyOnReadProps(disk)))
            goto cleanup;
    } else {
        if (!(tmp = qemuBuildStorageSourceAttachPrepareDrive(disk, qemuCaps)))
            goto cleanup;

        if (qemuBuildStorageSourceAttachPrepareCommon(disk->src, tmp,
                                                      qemuCaps) < 0)
            goto cleanup;

        if (VIR_APPEND_ELEMENT(data, ndata, tmp) < 0)
            goto cleanup;
    }

    for (i = ndata; i > 0; i--) {
        if (qemuBuildBlockStorageSourceAttachDataCommandline(cmd,
                                                             data[i - 1]) < 0)
            goto cleanup;
    }

    if (copyOnReadProps) {
        if (!(str = virJSONValueToString(copyOnReadProps, false)))
            goto cleanup;

        virCommandAddArgList(cmd, "-blockdev", str, NULL);
        VIR_FREE(str);
    }
2609

2610 2611 2612
    ret = 0;

 cleanup:
2613 2614 2615 2616 2617 2618
    for (i = 0; i < ndata; i++)
        qemuBlockStorageSourceAttachDataFree(data[i]);
    VIR_FREE(data);
    qemuBlockStorageSourceAttachDataFree(tmp);
    virJSONValueFree(copyOnReadProps);
    VIR_FREE(str);
2619 2620 2621 2622 2623 2624 2625 2626 2627
    return ret;
}


static int
qemuBuildDiskCommandLine(virCommandPtr cmd,
                         const virDomainDef *def,
                         virDomainDiskDefPtr disk,
                         virQEMUCapsPtr qemuCaps,
2628
                         unsigned int bootindex)
2629 2630 2631
{
    char *optstr;

2632
    if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps) < 0)
2633
        return -1;
2634

2635
    if (!qemuDiskBusNeedsDriveArg(disk->bus)) {
2636 2637
        if (disk->bus != VIR_DOMAIN_DISK_BUS_FDC ||
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) {
2638 2639 2640
            if (qemuCommandAddExtDevice(cmd, &disk->info) < 0)
                return -1;

2641 2642
            virCommandAddArg(cmd, "-device");

2643 2644
            if (!(optstr = qemuBuildDiskDeviceStr(def, disk, bootindex,
                                                  qemuCaps)))
2645 2646 2647 2648 2649 2650 2651 2652 2653 2654
                return -1;
            virCommandAddArg(cmd, optstr);
            VIR_FREE(optstr);
        }
    }

    return 0;
}


2655
static int
2656 2657 2658
qemuBuildDisksCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
2659 2660
{
    size_t i;
2661 2662 2663
    unsigned int bootCD = 0;
    unsigned int bootFloppy = 0;
    unsigned int bootDisk = 0;
2664
    bool blockdev = virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV);
2665

2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676
    for (i = 0; i < def->os.nBootDevs; i++) {
        switch (def->os.bootDevs[i]) {
        case VIR_DOMAIN_BOOT_CDROM:
            bootCD = i + 1;
            break;
        case VIR_DOMAIN_BOOT_FLOPPY:
            bootFloppy = i + 1;
            break;
        case VIR_DOMAIN_BOOT_DISK:
            bootDisk = i + 1;
            break;
2677 2678 2679
        }
    }

2680 2681 2682 2683 2684 2685
    /* If we want to express the floppy drives via -device, the controller needs
     * to be instantiated prior to that */
    if (blockdev &&
        qemuBuildFloppyCommandLineControllerOptions(cmd, def, qemuCaps, bootFloppy) < 0)
        return -1;

2686
    for (i = 0; i < def->ndisks; i++) {
2687
        virDomainDiskDefPtr disk = def->disks[i];
2688
        unsigned int bootindex = 0;
2689

2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703
        if (disk->info.bootIndex) {
            bootindex = disk->info.bootIndex;
        } else {
            switch (disk->device) {
            case VIR_DOMAIN_DISK_DEVICE_CDROM:
                bootindex = bootCD;
                bootCD = 0;
                break;
            case VIR_DOMAIN_DISK_DEVICE_DISK:
            case VIR_DOMAIN_DISK_DEVICE_LUN:
                bootindex = bootDisk;
                bootDisk = 0;
                break;
            }
2704 2705
        }

2706 2707 2708 2709 2710 2711
        /* The floppy device itself does not support the bootindex property
         * so we need to set it up for the controller */
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
            bootindex = 0;

        if (qemuBuildDiskCommandLine(cmd, def, disk, qemuCaps, bootindex) < 0)
2712
            return -1;
2713
    }
2714

2715 2716
    if (!blockdev &&
        qemuBuildFloppyCommandLineControllerOptions(cmd, def, qemuCaps, bootFloppy) < 0)
2717 2718
        return -1;

2719 2720 2721 2722
    return 0;
}


2723
static char *
2724
qemuBuildFSStr(virDomainFSDefPtr fs)
2725 2726
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;
2727
    const char *driver = qemuDomainFSDriverTypeToString(fs->fsdriver);
2728
    const char *wrpolicy = virDomainFSWrpolicyTypeToString(fs->wrpolicy);
2729 2730

    if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) {
2731 2732
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("only supports mount filesystem type"));
2733 2734 2735
        goto error;
    }

2736
    if (!driver) {
2737 2738
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Filesystem driver type not supported"));
2739 2740 2741 2742
        goto error;
    }
    virBufferAdd(&opt, driver, -1);

2743 2744 2745 2746
    if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_PATH ||
        fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_DEFAULT) {
        if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_MAPPED) {
            virBufferAddLit(&opt, ",security_model=mapped");
2747
        } else if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
2748
            virBufferAddLit(&opt, ",security_model=passthrough");
2749
        } else if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_SQUASH) {
2750 2751 2752 2753 2754 2755
            virBufferAddLit(&opt, ",security_model=none");
        }
    } else {
        /* For other fs drivers, default(passthru) should always
         * be supported */
        if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
2756 2757
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("only supports passthrough accessmode"));
2758 2759
            goto error;
        }
2760
    }
2761

2762 2763
    if (fs->wrpolicy)
        virBufferAsprintf(&opt, ",writeout=%s", wrpolicy);
2764

2765
    virBufferAsprintf(&opt, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
2766 2767
    virBufferAddLit(&opt, ",path=");
    virQEMUBuildBufferEscapeComma(&opt, fs->src->path);
2768

2769 2770
    if (fs->readonly)
        virBufferAddLit(&opt, ",readonly");
2771

2772
    if (virBufferCheckError(&opt) < 0)
2773 2774 2775 2776
        goto error;

    return virBufferContentAndReset(&opt);

2777
 error:
2778 2779 2780 2781 2782
    virBufferFreeAndReset(&opt);
    return NULL;
}


2783 2784
static char *
qemuBuildFSDevStr(const virDomainDef *def,
2785
                  virDomainFSDefPtr fs,
2786
                  virQEMUCapsPtr qemuCaps)
2787 2788 2789 2790
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;

    if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) {
2791 2792
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("can only passthrough directories"));
2793 2794 2795
        goto error;
    }

2796
    if (qemuBuildVirtioDevStr(&opt, "virtio-9p", qemuCaps,
2797
                              VIR_DOMAIN_DEVICE_FS, fs) < 0) {
2798
        goto error;
2799
    }
2800

2801
    virBufferAsprintf(&opt, ",id=%s", fs->info.alias);
2802 2803
    virBufferAsprintf(&opt, ",fsdev=%s%s",
                      QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
2804 2805
    virBufferAddLit(&opt, ",mount_tag=");
    virQEMUBuildBufferEscapeComma(&opt, fs->dst);
A
Alex Jia 已提交
2806

2807 2808
    if (qemuBuildVirtioOptionsStr(&opt, fs->virtio, qemuCaps) < 0)
        goto error;
2809

2810
    if (qemuBuildDeviceAddressStr(&opt, def, &fs->info, qemuCaps) < 0)
A
Alex Jia 已提交
2811
        goto error;
2812

2813
    if (virBufferCheckError(&opt) < 0)
2814 2815 2816 2817
        goto error;

    return virBufferContentAndReset(&opt);

2818
 error:
2819 2820 2821 2822 2823
    virBufferFreeAndReset(&opt);
    return NULL;
}


2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835
static int
qemuBuildFSDevCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
    size_t i;

    for (i = 0; i < def->nfss; i++) {
        char *optstr;
        virDomainFSDefPtr fs = def->fss[i];

        virCommandAddArg(cmd, "-fsdev");
2836
        if (!(optstr = qemuBuildFSStr(fs)))
2837 2838 2839 2840
            return -1;
        virCommandAddArg(cmd, optstr);
        VIR_FREE(optstr);

2841 2842 2843
        if (qemuCommandAddExtDevice(cmd, &fs->info) < 0)
            return -1;

2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854
        virCommandAddArg(cmd, "-device");
        if (!(optstr = qemuBuildFSDevStr(def, fs, qemuCaps)))
            return -1;
        virCommandAddArg(cmd, optstr);
        VIR_FREE(optstr);
    }

    return 0;
}


2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873
static int
qemuControllerModelUSBToCaps(int model)
{
    switch (model) {
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI:
        return QEMU_CAPS_PIIX3_USB_UHCI;
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI:
        return QEMU_CAPS_PIIX4_USB_UHCI;
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI:
        return QEMU_CAPS_USB_EHCI;
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
        return QEMU_CAPS_ICH9_USB_EHCI1;
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI:
        return QEMU_CAPS_VT82C686B_USB_UHCI;
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI:
        return QEMU_CAPS_PCI_OHCI;
G
Gerd Hoffmann 已提交
2874 2875
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI:
        return QEMU_CAPS_NEC_USB_XHCI;
2876 2877
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_QEMU_XHCI:
        return QEMU_CAPS_DEVICE_QEMU_XHCI;
2878 2879 2880 2881 2882 2883
    default:
        return -1;
    }
}


2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908
static const char *
qemuBuildUSBControllerFindMasterAlias(const virDomainDef *domainDef,
                                      const virDomainControllerDef *def)
{
    size_t i;

    for (i = 0; i < domainDef->ncontrollers; i++) {
        const virDomainControllerDef *tmp = domainDef->controllers[i];

        if (tmp->type != VIR_DOMAIN_CONTROLLER_TYPE_USB)
            continue;

        if (tmp->idx != def->idx)
            continue;

        if (tmp->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB)
            continue;

        return tmp->info.alias;
    }

    return NULL;
}


2909
static int
2910 2911
qemuBuildUSBControllerDevStr(const virDomainDef *domainDef,
                             virDomainControllerDefPtr def,
2912
                             virQEMUCapsPtr qemuCaps,
2913 2914 2915
                             virBuffer *buf)
{
    const char *smodel;
2916
    int model, flags;
2917 2918

    model = def->model;
2919

2920
    if (model == VIR_DOMAIN_CONTROLLER_MODEL_USB_DEFAULT) {
2921 2922 2923
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       "%s", _("no model provided for USB controller"));
        return -1;
2924
    }
2925 2926

    smodel = qemuControllerModelUSBTypeToString(model);
2927
    flags = qemuControllerModelUSBToCaps(model);
2928

2929
    if (flags == -1 || !virQEMUCapsGet(qemuCaps, flags)) {
2930 2931
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("%s not supported in this QEMU binary"), smodel);
2932 2933 2934
        return -1;
    }

2935 2936
    virBufferAsprintf(buf, "%s", smodel);

2937
    if (def->opts.usbopts.ports != -1) {
2938 2939 2940
        if ((model != VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI ||
             !virQEMUCapsGet(qemuCaps, QEMU_CAPS_NEC_USB_XHCI_PORTS)) &&
            model != VIR_DOMAIN_CONTROLLER_MODEL_USB_QEMU_XHCI) {
2941 2942 2943 2944 2945 2946 2947 2948 2949 2950
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("usb controller type %s doesn't support 'ports' "
                             "with this QEMU binary"), smodel);
            return -1;
        }

        virBufferAsprintf(buf, ",p2=%d,p3=%d",
                          def->opts.usbopts.ports, def->opts.usbopts.ports);
    }

2951 2952 2953 2954 2955 2956 2957 2958
    if (def->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
        const char *masterbus;

        if (!(masterbus = qemuBuildUSBControllerFindMasterAlias(domainDef, def))) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("masterbus not found"));
            return -1;
        }
2959
        virBufferAsprintf(buf, ",masterbus=%s.0,firstport=%d",
2960 2961
                          masterbus, def->info.master.usb.startport);
    } else {
2962
        virBufferAsprintf(buf, ",id=%s", def->info.alias);
2963
    }
2964

2965 2966 2967
    return 0;
}

2968

2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989
/**
 * qemuBuildControllerDevStr:
 * @domainDef: domain definition
 * @def: controller definition
 * @qemuCaps: QEMU binary capabilities
 * @devstr: device string
 * @nusbcontroller: number of USB controllers
 *
 * Turn @def into a description of the controller that QEMU will understand,
 * to be used either on the command line or through the monitor.
 *
 * The description will be returned in @devstr and can be NULL, eg. when
 * passing in one of the built-in controllers. The returned string must be
 * freed by the caller.
 *
 * The number pointed to by @nusbcontroller will be increased by one every
 * time the description for a USB controller has been generated successfully.
 *
 * Returns: 0 on success, <0 on failure
 */
int
2990
qemuBuildControllerDevStr(const virDomainDef *domainDef,
2991
                          virDomainControllerDefPtr def,
2992
                          virQEMUCapsPtr qemuCaps,
2993
                          char **devstr)
2994 2995
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
2996

2997 2998
    *devstr = NULL;

2999
    switch ((virDomainControllerType)def->type) {
3000
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
3001
        switch ((virDomainControllerModelSCSI) def->model) {
3002
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI:
3003 3004
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL:
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL:
3005
            if (qemuBuildVirtioDevStr(&buf, "virtio-scsi", qemuCaps,
3006
                                      VIR_DOMAIN_DEVICE_CONTROLLER, def) < 0) {
3007
                goto error;
3008
            }
3009 3010 3011 3012 3013 3014

            if (def->iothread) {
                virBufferAsprintf(&buf, ",iothread=iothread%u",
                                  def->iothread);
            }

3015 3016
            if (qemuBuildVirtioOptionsStr(&buf, def->virtio, qemuCaps) < 0)
                goto error;
3017
            break;
3018
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC:
3019
            virBufferAddLit(&buf, "lsi");
3020 3021 3022 3023
            break;
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
            virBufferAddLit(&buf, "spapr-vscsi");
            break;
3024 3025 3026
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068:
            virBufferAddLit(&buf, "mptsas1068");
            break;
3027 3028 3029
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078:
            virBufferAddLit(&buf, "megasas");
            break;
3030 3031 3032
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO:
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC:
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI:
3033 3034 3035
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unsupported controller model: %s"),
                           virDomainControllerModelSCSITypeToString(def->model));
3036 3037 3038 3039 3040 3041 3042
            goto error;
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT:
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST:
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unexpected SCSI controller model %d"),
                           def->model);
            goto error;
3043
        }
3044
        virBufferAsprintf(&buf, ",id=%s", def->info.alias);
3045 3046 3047
        break;

    case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
3048
        if (qemuBuildVirtioDevStr(&buf, "virtio-serial", qemuCaps,
3049
                                  VIR_DOMAIN_DEVICE_CONTROLLER, def) < 0) {
3050
            goto error;
3051
        }
3052

3053
        virBufferAsprintf(&buf, ",id=%s", def->info.alias);
3054
        if (def->opts.vioserial.ports != -1) {
3055
            virBufferAsprintf(&buf, ",max_ports=%d",
3056 3057 3058
                              def->opts.vioserial.ports);
        }
        if (def->opts.vioserial.vectors != -1) {
3059
            virBufferAsprintf(&buf, ",vectors=%d",
3060 3061
                              def->opts.vioserial.vectors);
        }
3062 3063
        if (qemuBuildVirtioOptionsStr(&buf, def->virtio, qemuCaps) < 0)
            goto error;
3064 3065
        break;

E
Eric Blake 已提交
3066
    case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
3067
        virBufferAsprintf(&buf, "usb-ccid,id=%s", def->info.alias);
E
Eric Blake 已提交
3068 3069
        break;

J
Jim Fehlig 已提交
3070
    case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
3071
        virBufferAsprintf(&buf, "ahci,id=%s", def->info.alias);
J
Jim Fehlig 已提交
3072 3073
        break;

3074
    case VIR_DOMAIN_CONTROLLER_TYPE_USB:
3075
        if (qemuBuildUSBControllerDevStr(domainDef, def, qemuCaps, &buf) == -1)
3076 3077 3078 3079
            goto error;

        break;

3080 3081 3082
    case VIR_DOMAIN_CONTROLLER_TYPE_PCI: {
        const virDomainPCIControllerOpts *pciopts = &def->opts.pciopts;
        const char *modelName = virDomainControllerPCIModelNameTypeToString(pciopts->modelName);
3083

3084 3085 3086 3087 3088 3089 3090
        /* Skip the implicit PHB for pSeries guests */
        if (def->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT &&
            pciopts->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE &&
            pciopts->targetIndex == 0) {
            goto done;
        }

3091 3092 3093 3094 3095 3096 3097
        if (!modelName) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unknown virDomainControllerPCIModelName value: %d"),
                           pciopts->modelName);
            return -1;
        }

3098
        switch ((virDomainControllerModelPCI) def->model) {
3099
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
3100
            virBufferAsprintf(&buf, "%s,chassis_nr=%d,id=%s",
3101
                              modelName, pciopts->chassisNr,
3102
                              def->info.alias);
3103
            break;
3104
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS:
3105
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS:
3106
            virBufferAsprintf(&buf, "%s,bus_nr=%d,id=%s",
3107
                              modelName, pciopts->busNr,
3108
                              def->info.alias);
3109 3110 3111 3112
            if (pciopts->numaNode != -1) {
                virBufferAsprintf(&buf, ",numa_node=%d",
                                  pciopts->numaNode);
            }
3113
            break;
3114
        case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
3115
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
3116
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE:
3117 3118
            virBufferAsprintf(&buf, "%s,id=%s", modelName, def->info.alias);
            break;
3119
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
3120 3121
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
            virBufferAsprintf(&buf, "%s,port=0x%x,chassis=%d,id=%s",
3122 3123
                              modelName, pciopts->port,
                              pciopts->chassis, def->info.alias);
3124
            break;
3125
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
3126
            virBufferAsprintf(&buf, "%s,index=%d,id=%s",
3127
                              modelName, pciopts->targetIndex,
3128
                              def->info.alias);
3129

3130
            if (pciopts->numaNode != -1)
3131
                virBufferAsprintf(&buf, ",numa_node=%d", pciopts->numaNode);
3132
            break;
3133
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
3134 3135 3136 3137
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Unsupported PCI Express root controller"));
            goto error;
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT:
3138
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
3139 3140 3141
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unexpected PCI controller model %d"),
                           def->model);
3142 3143
            goto error;
        }
3144
        break;
3145
    }
3146

3147
    case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
3148 3149
    case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
    case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
3150
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3151
                       _("Unsupported controller type: %s"),
3152
                       virDomainControllerTypeToString(def->type));
3153 3154 3155
        goto error;
    }

3156 3157
    if (def->queues)
        virBufferAsprintf(&buf, ",num_queues=%u", def->queues);
3158

3159 3160 3161 3162 3163 3164
    if (def->cmd_per_lun)
        virBufferAsprintf(&buf, ",cmd_per_lun=%u", def->cmd_per_lun);

    if (def->max_sectors)
        virBufferAsprintf(&buf, ",max_sectors=%u", def->max_sectors);

3165 3166
    qemuBuildIoEventFdStr(&buf, def->ioeventfd, qemuCaps);

3167
    if (qemuBuildDeviceAddressStr(&buf, domainDef, &def->info, qemuCaps) < 0)
3168 3169
        goto error;

3170
 done:
3171
    if (virBufferCheckError(&buf) < 0)
3172 3173
        goto error;

3174 3175
    *devstr = virBufferContentAndReset(&buf);
    return 0;
3176

3177
 error:
3178
    virBufferFreeAndReset(&buf);
3179
    return -1;
3180 3181 3182
}


3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194
static bool
qemuBuildDomainForbidLegacyUSBController(const virDomainDef *def)
{
    if (qemuDomainIsQ35(def) ||
        qemuDomainIsARMVirt(def) ||
        qemuDomainIsRISCVVirt(def))
        return true;

    return false;
}


3195 3196
static int
qemuBuildLegacyUSBControllerCommandLine(virCommandPtr cmd,
3197
                                        const virDomainDef *def)
3198
{
3199
    size_t i;
3200
    size_t nlegacy = 0;
3201
    size_t nusb = 0;
3202 3203 3204 3205 3206 3207 3208 3209 3210 3211

    for (i = 0; i < def->ncontrollers; i++) {
        virDomainControllerDefPtr cont = def->controllers[i];

        if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_USB)
            continue;

        /* If we have mode='none', there are no other USB controllers */
        if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE)
            return 0;
3212 3213 3214

        if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_DEFAULT)
            nlegacy++;
3215 3216
        else
            nusb++;
3217 3218 3219 3220 3221 3222 3223
    }

    if (nlegacy > 1) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Multiple legacy USB controllers are "
                         "not supported"));
        return -1;
3224 3225
    }

3226
    if (nusb == 0 &&
3227
        !qemuBuildDomainForbidLegacyUSBController(def) &&
3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238
        !ARCH_IS_S390(def->os.arch)) {
        /* We haven't added any USB controller yet, but we haven't been asked
         * not to add one either. Add a legacy USB controller, unless we're
         * creating a kind of guest we want to keep legacy-free */
        virCommandAddArg(cmd, "-usb");
    }

    return 0;
}


3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276
/**
 * qemuBuildSkipController:
 * @controller: Controller to check
 * @def: Domain definition
 *
 * Returns true if this controller can be skipped for command line
 * generation or device validation.
 */
static bool
qemuBuildSkipController(const virDomainControllerDef *controller,
                        const virDomainDef *def)
{
    /* skip pcie-root */
    if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
        controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)
        return true;

    /* Skip pci-root, except for pSeries guests (which actually
     * support more than one PCI Host Bridge per guest) */
    if (!qemuDomainIsPSeries(def) &&
        controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
        controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT)
        return true;

    /* first SATA controller on Q35 machines is implicit */
    if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA &&
        controller->idx == 0 && qemuDomainIsQ35(def))
        return true;

    /* first IDE controller is implicit on various machines */
    if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
        controller->idx == 0 && qemuDomainHasBuiltinIDE(def))
        return true;

    return false;
}


3277 3278 3279 3280 3281 3282
static int
qemuBuildControllersByTypeCommandLine(virCommandPtr cmd,
                                      const virDomainDef *def,
                                      virQEMUCapsPtr qemuCaps,
                                      virDomainControllerType type)
{
3283
    char *devstr = NULL;
3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320
    int ret = -1;
    size_t i;

    for (i = 0; i < def->ncontrollers; i++) {
        virDomainControllerDefPtr cont = def->controllers[i];

        if (cont->type != type)
            continue;

        if (qemuBuildSkipController(cont, def))
            continue;

        /* skip USB controllers with type none.*/
        if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
            cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE) {
            continue;
        }

        if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
            cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_DEFAULT &&
            !qemuBuildDomainForbidLegacyUSBController(def)) {

            /* An appropriate default USB controller model should already
             * have been selected in qemuDomainDeviceDefPostParse(); if
             * we still have no model by now, we have to fall back to the
             * legacy USB controller.
             *
             * Note that we *don't* want to end up with the legacy USB
             * controller for q35 and virt machines, so we go ahead and
             * fail in qemuBuildControllerDevStr(); on the other hand,
             * for s390 machines we want to ignore any USB controller
             * (see 548ba43028 for the full story), so we skip
             * qemuBuildControllerDevStr() but we don't ultimately end
             * up adding the legacy USB controller */
            continue;
        }

3321
        VIR_FREE(devstr);
3322 3323 3324 3325
        if (qemuBuildControllerDevStr(def, cont, qemuCaps, &devstr) < 0)
            goto cleanup;

        if (devstr) {
3326
            if (qemuCommandAddExtDevice(cmd, &cont->info) < 0)
3327 3328 3329 3330 3331 3332 3333 3334 3335
                goto cleanup;

            virCommandAddArg(cmd, "-device");
            virCommandAddArg(cmd, devstr);
        }
    }

    ret = 0;
 cleanup:
3336
    VIR_FREE(devstr);
3337 3338 3339 3340
    return ret;
}


3341
static int
3342 3343 3344
qemuBuildControllersCommandLine(virCommandPtr cmd,
                                const virDomainDef *def,
                                virQEMUCapsPtr qemuCaps)
3345
{
3346
    size_t i;
3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361
    int contOrder[] = {
        /*
         * List of controller types that we add commandline args for,
         * *in the order we want to add them*.
         *
         * The floppy controller is implicit on PIIX4 and older Q35
         * machines. For newer Q35 machines it is added out of the
         * controllers loop, after the floppy drives.
         *
         * We don't add PCI/PCIe root controller either, because it's
         * implicit, but we do add PCI bridges and other PCI
         * controllers, so we leave that in to check each
         * one. Likewise, we don't do anything for the primary IDE
         * controller on an i440fx machine or primary SATA on q35, but
         * we do add those beyond these two exceptions.
3362 3363 3364
         *
         * CCID controllers are formatted separately after USB hubs,
         * because they go on the USB bus.
3365 3366 3367 3368 3369 3370 3371 3372
         */
        VIR_DOMAIN_CONTROLLER_TYPE_PCI,
        VIR_DOMAIN_CONTROLLER_TYPE_USB,
        VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
        VIR_DOMAIN_CONTROLLER_TYPE_IDE,
        VIR_DOMAIN_CONTROLLER_TYPE_SATA,
        VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL,
    };
3373
    int ret = -1;
3374

3375 3376
    for (i = 0; i < ARRAY_CARDINALITY(contOrder); i++) {
        if (qemuBuildControllersByTypeCommandLine(cmd, def, qemuCaps, contOrder[i]) < 0)
3377
            goto cleanup;
3378 3379
    }

3380
    if (qemuBuildLegacyUSBControllerCommandLine(cmd, def) < 0)
3381
        goto cleanup;
3382

3383 3384 3385 3386
    ret = 0;

 cleanup:
    return ret;
3387 3388 3389
}


M
Marc-André Lureau 已提交
3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409
static int
qemuBuildMemoryBackendPropsShare(virJSONValuePtr props,
                                 virDomainMemoryAccess memAccess)
{
    switch (memAccess) {
    case VIR_DOMAIN_MEMORY_ACCESS_SHARED:
        return virJSONValueObjectAdd(props, "b:share", true, NULL);

    case VIR_DOMAIN_MEMORY_ACCESS_PRIVATE:
        return virJSONValueObjectAdd(props, "b:share", false, NULL);

    case VIR_DOMAIN_MEMORY_ACCESS_DEFAULT:
    case VIR_DOMAIN_MEMORY_ACCESS_LAST:
        break;
    }

    return 0;
}


3410
/**
3411
 * qemuBuildMemoryBackendProps:
3412
 * @backendProps: [out] constructed object
3413
 * @alias: alias of the device
3414
 * @cfg: qemu driver config object
3415
 * @priv: pointer to domain private object
3416 3417 3418 3419 3420
 * @def: domain definition object
 * @mem: memory definition object
 * @force: forcibly use one of the backends
 *
 * Creates a configuration object that represents memory backend of given guest
3421
 * NUMA node (domain @def and @mem). Use @priv->autoNodeset to fine tune the
3422 3423 3424 3425 3426
 * placement of the memory on the host NUMA nodes.
 *
 * By default, if no memory-backend-* object is necessary to fulfil the guest
 * configuration value of 1 is returned. This behaviour can be suppressed by
 * setting @force to true in which case 0 would be returned.
3427
 *
3428 3429
 * Then, if one of the three memory-backend-* should be used, the @priv->qemuCaps
 * is consulted to check if qemu does support it.
3430
 *
3431 3432 3433
 * Returns: 0 on success,
 *          1 on success and if there's no need to use memory-backend-*
 *         -1 on error.
3434
 */
3435
int
3436
qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
3437
                            const char *alias,
3438
                            virQEMUDriverConfigPtr cfg,
3439
                            qemuDomainObjPrivatePtr priv,
3440 3441 3442
                            virDomainDefPtr def,
                            virDomainMemoryDefPtr mem,
                            bool force)
3443
{
3444
    const char *backendType = "memory-backend-file";
3445
    virDomainNumatuneMemMode mode;
3446
    const long system_page_size = virGetSystemPageSizeKB();
3447
    virDomainMemoryAccess memAccess = mem->access;
3448
    size_t i;
M
Michal Privoznik 已提交
3449 3450
    char *memPath = NULL;
    bool prealloc = false;
3451
    virBitmapPtr nodemask = NULL;
3452
    int ret = -1;
3453
    virJSONValuePtr props = NULL;
3454 3455
    bool nodeSpecified = virDomainNumatuneNodeSpecified(def->numa, mem->targetNode);
    unsigned long long pagesize = mem->pagesize;
3456
    bool needHugepage = !!pagesize;
3457
    bool useHugepage = !!pagesize;
3458
    int discard = mem->discard;
3459 3460 3461 3462 3463 3464

    /* The difference between @needHugepage and @useHugepage is that the latter
     * is true whenever huge page is defined for the current memory cell.
     * Either directly, or transitively via global domain huge pages. The
     * former is true whenever "memory-backend-file" must be used to satisfy
     * @useHugepage. */
3465

3466 3467
    *backendProps = NULL;

3468
    if (mem->targetNode >= 0) {
3469
        /* memory devices could provide a invalid guest node */
3470
        if (mem->targetNode >= virDomainNumaGetNodeCount(def->numa)) {
3471 3472 3473
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("can't add memory backend for guest node '%d' as "
                             "the guest has only '%zu' NUMA nodes configured"),
3474
                           mem->targetNode, virDomainNumaGetNodeCount(def->numa));
3475 3476
            return -1;
        }
3477

3478 3479 3480 3481 3482
        if (memAccess == VIR_DOMAIN_MEMORY_ACCESS_DEFAULT)
            memAccess = virDomainNumaGetNodeMemoryAccessMode(def->numa, mem->targetNode);

        if (discard == VIR_TRISTATE_BOOL_ABSENT)
            discard = virDomainNumaGetNodeDiscard(def->numa, mem->targetNode);
3483
    }
3484

3485 3486 3487
    if (memAccess == VIR_DOMAIN_MEMORY_ACCESS_DEFAULT)
        memAccess = def->mem.access;

3488 3489 3490
    if (discard == VIR_TRISTATE_BOOL_ABSENT)
        discard = def->mem.discard;

3491
    if (virDomainNumatuneGetMode(def->numa, mem->targetNode, &mode) < 0 &&
3492 3493
        virDomainNumatuneGetMode(def->numa, -1, &mode) < 0)
        mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
3494

3495
    if (pagesize == 0) {
3496 3497
        virDomainHugePagePtr master_hugepage = NULL;
        virDomainHugePagePtr hugepage = NULL;
3498 3499
        bool thisHugepage = false;

3500 3501 3502 3503 3504 3505 3506 3507 3508
        /* Find the huge page size we want to use */
        for (i = 0; i < def->mem.nhugepages; i++) {
            hugepage = &def->mem.hugepages[i];

            if (!hugepage->nodemask) {
                master_hugepage = hugepage;
                continue;
            }

3509
            /* just find the master hugepage in case we don't use NUMA */
3510
            if (mem->targetNode < 0)
3511 3512
                continue;

3513
            if (virBitmapGetBit(hugepage->nodemask, mem->targetNode,
3514 3515 3516 3517 3518 3519 3520 3521 3522
                                &thisHugepage) < 0) {
                /* Ignore this error. It's not an error after all. Well,
                 * the nodemask for this <page/> can contain lower NUMA
                 * nodes than we are querying in here. */
                continue;
            }

            if (thisHugepage) {
                /* Hooray, we've found the page size */
3523
                needHugepage = true;
3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534
                break;
            }
        }

        if (i == def->mem.nhugepages) {
            /* We have not found specific huge page to be used with this
             * NUMA node. Use the generic setting then (<page/> without any
             * @nodemask) if possible. */
            hugepage = master_hugepage;
        }

3535
        if (hugepage) {
3536
            pagesize = hugepage->size;
3537 3538
            useHugepage = true;
        }
3539
    }
3540

3541 3542 3543 3544 3545
    if (pagesize == system_page_size) {
        /* However, if user specified to use "huge" page
         * of regular system page size, it's as if they
         * hasn't specified any huge pages at all. */
        pagesize = 0;
3546 3547
        needHugepage = false;
        useHugepage = false;
3548 3549
    }

3550 3551 3552
    if (!(props = virJSONValueNewObject()))
        return -1;

M
Marc-André Lureau 已提交
3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565
    if (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_MEMFD) {
        backendType = "memory-backend-memfd";

        if (useHugepage &&
            (virJSONValueObjectAdd(props, "b:hugetlb", useHugepage, NULL) < 0 ||
             virJSONValueObjectAdd(props, "U:hugetlbsize", pagesize << 10, NULL) < 0)) {
            goto cleanup;
        }

        if (qemuBuildMemoryBackendPropsShare(props, memAccess) < 0)
            goto cleanup;

    } else if (useHugepage || mem->nvdimmPath || memAccess ||
M
Michal Privoznik 已提交
3566
        def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) {
3567

3568 3569
        if (mem->nvdimmPath) {
            if (VIR_STRDUP(memPath, mem->nvdimmPath) < 0)
3570
                goto cleanup;
3571 3572
            if (!priv->memPrealloc)
                prealloc = true;
3573 3574
        } else if (useHugepage) {
            if (qemuGetDomainHupageMemPath(def, cfg, pagesize, &memPath) < 0)
3575
                goto cleanup;
3576 3577
            if (!priv->memPrealloc)
                prealloc = true;
3578
        } else {
3579 3580
            /* We can have both pagesize and mem source. If that's the case,
             * prefer hugepages as those are more specific. */
3581
            if (qemuGetMemoryBackingPath(def, cfg, mem->info.alias, &memPath) < 0)
3582 3583
                goto cleanup;
        }
3584

M
Michal Privoznik 已提交
3585 3586 3587 3588 3589 3590
        if (virJSONValueObjectAdd(props,
                                  "B:prealloc", prealloc,
                                  "s:mem-path", memPath,
                                  NULL) < 0)
            goto cleanup;

3591 3592
        if (!mem->nvdimmPath &&
            discard == VIR_TRISTATE_BOOL_YES) {
3593
            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE_DISCARD)) {
3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("this QEMU doesn't support memory discard"));
                goto cleanup;
            }

            if (virJSONValueObjectAdd(props,
                                      "B:discard-data", true,
                                      NULL) < 0)
                goto cleanup;
        }

M
Marc-André Lureau 已提交
3605 3606
        if (qemuBuildMemoryBackendPropsShare(props, memAccess) < 0)
            goto cleanup;
3607
    } else {
3608
        backendType = "memory-backend-ram";
3609 3610
    }

3611
    if (virJSONValueObjectAdd(props, "U:size", mem->size * 1024, NULL) < 0)
3612
        goto cleanup;
3613

3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624
    if (mem->alignsize) {
        if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE_ALIGN)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("nvdimm align property is not available "
                             "with this QEMU binary"));
            goto cleanup;
        }
        if (virJSONValueObjectAdd(props, "U:align", mem->alignsize * 1024, NULL) < 0)
            goto cleanup;
    }

3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635
    if (mem->nvdimmPmem) {
        if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE_PMEM)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("nvdimm pmem property is not available "
                             "with this QEMU binary"));
            goto cleanup;
        }
        if (virJSONValueObjectAdd(props, "s:pmem", "on", NULL) < 0)
            goto cleanup;
    }

3636 3637
    if (mem->sourceNodes) {
        nodemask = mem->sourceNodes;
3638
    } else {
3639
        if (virDomainNumatuneMaybeGetNodeset(def->numa, priv->autoNodeset,
3640
                                             &nodemask, mem->targetNode) < 0)
3641 3642 3643 3644
            goto cleanup;
    }

    if (nodemask) {
3645 3646
        if (!virNumaNodesetIsAvailable(nodemask))
            goto cleanup;
3647 3648 3649 3650
        if (virJSONValueObjectAdd(props,
                                  "m:host-nodes", nodemask,
                                  "S:policy", qemuNumaPolicyTypeToString(mode),
                                  NULL) < 0)
3651 3652 3653
            goto cleanup;
    }

3654
    /* If none of the following is requested... */
3655
    if (!needHugepage && !mem->sourceNodes && !nodeSpecified &&
M
Michal Privoznik 已提交
3656
        !mem->nvdimmPath &&
3657
        memAccess == VIR_DOMAIN_MEMORY_ACCESS_DEFAULT &&
M
Marc-André Lureau 已提交
3658 3659 3660
        def->mem.source != VIR_DOMAIN_MEMORY_SOURCE_FILE &&
        def->mem.source != VIR_DOMAIN_MEMORY_SOURCE_MEMFD &&
        !force) {
3661 3662 3663 3664 3665
        /* report back that using the new backend is not necessary
         * to achieve the desired configuration */
        ret = 1;
    } else {
        /* otherwise check the required capability */
3666
        if (STREQ(backendType, "memory-backend-file") &&
3667
            !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) {
3668 3669 3670 3671
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this qemu doesn't support the "
                             "memory-backend-file object"));
            goto cleanup;
3672
        } else if (STREQ(backendType, "memory-backend-ram") &&
3673
                   !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM)) {
3674 3675 3676
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this qemu doesn't support the "
                             "memory-backend-ram object"));
3677
            goto cleanup;
M
Marc-André Lureau 已提交
3678
        } else if (STREQ(backendType, "memory-backend-memory") &&
3679
                   !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD)) {
M
Marc-André Lureau 已提交
3680 3681 3682 3683
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this qemu doesn't support the "
                             "memory-backend-memfd object"));
            goto cleanup;
3684 3685
        }

3686
        ret = 0;
3687 3688
    }

3689 3690 3691
    if (!(*backendProps = qemuMonitorCreateObjectPropsWrap(backendType, alias,
                                                           &props)))
        ret = -1;
3692 3693

 cleanup:
3694
    virJSONValueFree(props);
M
Michal Privoznik 已提交
3695
    VIR_FREE(memPath);
3696 3697 3698 3699 3700 3701 3702 3703
    return ret;
}


static int
qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
                              virQEMUDriverConfigPtr cfg,
                              size_t cell,
3704
                              qemuDomainObjPrivatePtr priv,
3705
                              virBufferPtr buf)
3706
{
3707 3708 3709 3710
    virJSONValuePtr props = NULL;
    char *alias = NULL;
    int ret = -1;
    int rc;
3711
    virDomainMemoryDef mem = { 0 };
3712 3713
    unsigned long long memsize = virDomainNumaGetNodeMemorySize(def->numa,
                                                                cell);
3714

3715 3716 3717
    if (virAsprintf(&alias, "ram-node%zu", cell) < 0)
        goto cleanup;

3718 3719
    mem.size = memsize;
    mem.targetNode = cell;
3720
    mem.info.alias = alias;
3721

3722 3723
    if ((rc = qemuBuildMemoryBackendProps(&props, alias, cfg,
                                          priv, def, &mem, false)) < 0)
3724 3725
        goto cleanup;

3726
    if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
3727 3728
        goto cleanup;

3729
    ret = rc;
3730 3731 3732 3733 3734

 cleanup:
    VIR_FREE(alias);
    virJSONValueFree(props);

3735 3736 3737 3738
    return ret;
}


3739 3740 3741
static int
qemuBuildMemoryDimmBackendStr(virBufferPtr buf,
                              virDomainMemoryDefPtr mem,
3742
                              virDomainDefPtr def,
3743
                              virQEMUDriverConfigPtr cfg,
3744
                              qemuDomainObjPrivatePtr priv)
3745 3746 3747
{
    virJSONValuePtr props = NULL;
    char *alias = NULL;
3748
    int ret = -1;
3749 3750 3751 3752

    if (!mem->info.alias) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("memory device alias is not assigned"));
3753
        return -1;
3754 3755 3756 3757 3758
    }

    if (virAsprintf(&alias, "mem%s", mem->info.alias) < 0)
        goto cleanup;

3759 3760
    if (qemuBuildMemoryBackendProps(&props, alias, cfg,
                                    priv, def, mem, true) < 0)
3761 3762
        goto cleanup;

3763 3764 3765 3766
    if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
        goto cleanup;

    ret = 0;
3767 3768 3769 3770 3771 3772 3773 3774 3775

 cleanup:
    VIR_FREE(alias);
    virJSONValueFree(props);

    return ret;
}


3776
char *
3777 3778
qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
                         qemuDomainObjPrivatePtr priv)
3779 3780
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
M
Michal Privoznik 已提交
3781
    const char *device;
3782 3783 3784 3785 3786 3787 3788 3789

    if (!mem->info.alias) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("missing alias for memory device"));
        return NULL;
    }

    switch ((virDomainMemoryModel) mem->model) {
M
Michal Privoznik 已提交
3790
    case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
3791
    case VIR_DOMAIN_MEMORY_MODEL_DIMM:
M
Michal Privoznik 已提交
3792 3793 3794 3795 3796 3797 3798

        if (mem->model == VIR_DOMAIN_MEMORY_MODEL_DIMM)
            device = "pc-dimm";
        else
            device = "nvdimm";

        virBufferAsprintf(&buf, "%s,", device);
3799 3800 3801 3802

        if (mem->targetNode >= 0)
            virBufferAsprintf(&buf, "node=%d,", mem->targetNode);

3803 3804 3805
        if (mem->labelsize)
            virBufferAsprintf(&buf, "label-size=%llu,", mem->labelsize * 1024);

3806 3807 3808 3809 3810 3811 3812 3813 3814 3815
        if (mem->readonly) {
            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_NVDIMM_UNARMED)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("nvdimm readonly property is not available "
                                 "with this QEMU binary"));
                return NULL;
            }
            virBufferAddLit(&buf, "unarmed=on,");
        }

3816 3817
        virBufferAsprintf(&buf, "memdev=mem%s,id=%s",
                          mem->info.alias, mem->info.alias);
3818 3819 3820

        if (mem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM) {
            virBufferAsprintf(&buf, ",slot=%d", mem->info.addr.dimm.slot);
3821 3822
            if (mem->info.addr.dimm.base)
                virBufferAsprintf(&buf, ",addr=%llu", mem->info.addr.dimm.base);
3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839
        }

        break;

    case VIR_DOMAIN_MEMORY_MODEL_NONE:
    case VIR_DOMAIN_MEMORY_MODEL_LAST:
        break;

    }

    if (virBufferCheckError(&buf) < 0)
        return NULL;

    return virBufferContentAndReset(&buf);
}


3840
static char *
3841
qemuBuildLegacyNicStr(virDomainNetDefPtr net)
3842 3843
{
    char *str;
3844 3845
    char macaddr[VIR_MAC_STRING_BUFLEN];

3846
    ignore_value(virAsprintf(&str,
3847
                             "nic,macaddr=%s,netdev=host%s%s%s%s%s",
3848
                             virMacAddrFormat(&net->mac, macaddr),
3849
                             net->info.alias,
3850
                             (net->model ? ",model=" : ""),
J
Ján Tomko 已提交
3851
                             NULLSTR_EMPTY(net->model),
3852
                             (net->info.alias ? ",id=" : ""),
J
Ján Tomko 已提交
3853
                             NULLSTR_EMPTY(net->info.alias)));
3854 3855 3856 3857 3858
    return str;
}


char *
3859
qemuBuildNicDevStr(virDomainDefPtr def,
3860
                   virDomainNetDefPtr net,
3861
                   unsigned int bootindex,
3862
                   size_t vhostfdSize,
3863
                   virQEMUCapsPtr qemuCaps)
3864 3865
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
3866
    bool usingVirtio = false;
3867
    char macaddr[VIR_MAC_STRING_BUFLEN];
3868

3869
    if (virDomainNetIsVirtioModel(net)) {
3870
        if (qemuBuildVirtioDevStr(&buf, "virtio-net", qemuCaps,
3871
                                  VIR_DOMAIN_DEVICE_NET, net) < 0) {
3872
            goto error;
3873
        }
3874

3875
        usingVirtio = true;
3876 3877
    } else {
        virBufferAddStr(&buf, net->model);
3878 3879
    }

3880
    if (usingVirtio && net->driver.virtio.txmode) {
3881
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_TX_ALG)) {
3882 3883 3884 3885 3886 3887 3888 3889 3890
            virBufferAddLit(&buf, ",tx=");
            switch (net->driver.virtio.txmode) {
                case VIR_DOMAIN_NET_VIRTIO_TX_MODE_IOTHREAD:
                    virBufferAddLit(&buf, "bh");
                    break;

                case VIR_DOMAIN_NET_VIRTIO_TX_MODE_TIMER:
                    virBufferAddLit(&buf, "timer");
                    break;
3891 3892 3893 3894 3895

                case VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT:
                    break;

                case VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST:
3896 3897 3898 3899
                default:
                    /* this should never happen, if it does, we need
                     * to add another case to this switch.
                     */
3900 3901
                    virReportEnumRangeError(virDomainNetVirtioTxModeType,
                                            net->driver.virtio.txmode);
3902 3903 3904
                    goto error;
            }
        } else {
3905 3906
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("virtio-net-pci 'tx' option not supported in this QEMU binary"));
3907 3908 3909
            goto error;
        }
    }
3910
    if (usingVirtio) {
3911
        qemuBuildIoEventFdStr(&buf, net->driver.virtio.ioeventfd, qemuCaps);
3912
        if (net->driver.virtio.event_idx &&
3913
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_EVENT_IDX)) {
3914
            virBufferAsprintf(&buf, ",event_idx=%s",
J
Ján Tomko 已提交
3915
                              virTristateSwitchTypeToString(net->driver.virtio.event_idx));
3916
        }
3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940
        if (net->driver.virtio.host.csum) {
            virBufferAsprintf(&buf, ",csum=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.host.csum));
        }
        if (net->driver.virtio.host.gso) {
            virBufferAsprintf(&buf, ",gso=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.host.gso));
        }
        if (net->driver.virtio.host.tso4) {
            virBufferAsprintf(&buf, ",host_tso4=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.host.tso4));
        }
        if (net->driver.virtio.host.tso6) {
            virBufferAsprintf(&buf, ",host_tso6=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.host.tso6));
        }
        if (net->driver.virtio.host.ecn) {
            virBufferAsprintf(&buf, ",host_ecn=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.host.ecn));
        }
        if (net->driver.virtio.host.ufo) {
            virBufferAsprintf(&buf, ",host_ufo=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.host.ufo));
        }
J
Ján Tomko 已提交
3941 3942 3943 3944
        if (net->driver.virtio.host.mrg_rxbuf) {
            virBufferAsprintf(&buf, ",mrg_rxbuf=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.host.mrg_rxbuf));
        }
3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964
        if (net->driver.virtio.guest.csum) {
            virBufferAsprintf(&buf, ",guest_csum=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.guest.csum));
        }
        if (net->driver.virtio.guest.tso4) {
            virBufferAsprintf(&buf, ",guest_tso4=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.guest.tso4));
        }
        if (net->driver.virtio.guest.tso6) {
            virBufferAsprintf(&buf, ",guest_tso6=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.guest.tso6));
        }
        if (net->driver.virtio.guest.ecn) {
            virBufferAsprintf(&buf, ",guest_ecn=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.guest.ecn));
        }
        if (net->driver.virtio.guest.ufo) {
            virBufferAsprintf(&buf, ",guest_ufo=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.guest.ufo));
        }
3965
    }
3966
    if (usingVirtio && vhostfdSize > 1) {
3967 3968 3969 3970 3971 3972
        if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
            /* ccw provides a one to one relation of fds to queues and
             * does not support the vectors option
             */
            virBufferAddLit(&buf, ",mq=on");
        } else {
3973
            /* As advised at https://www.linux-kvm.org/page/Multiqueue
3974 3975 3976 3977
             * we should add vectors=2*N+2 where N is the vhostfdSize
             */
            virBufferAsprintf(&buf, ",mq=on,vectors=%zu", 2 * vhostfdSize + 2);
        }
3978
    }
3979 3980 3981 3982 3983
    if (usingVirtio && net->driver.virtio.rx_queue_size) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_RX_QUEUE_SIZE)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("virtio rx_queue_size option is not supported with this QEMU binary"));
            goto error;
3984
        }
3985
        virBufferAsprintf(&buf, ",rx_queue_size=%u", net->driver.virtio.rx_queue_size);
3986
    }
3987 3988 3989 3990 3991
    if (usingVirtio && net->driver.virtio.tx_queue_size) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_TX_QUEUE_SIZE)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("virtio tx_queue_size option is not supported with this QEMU binary"));
            goto error;
3992
        }
3993
        virBufferAsprintf(&buf, ",tx_queue_size=%u", net->driver.virtio.tx_queue_size);
3994
    }
3995

3996 3997 3998 3999 4000
    if (usingVirtio && net->mtu) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_HOST_MTU)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("setting MTU is not supported with this QEMU binary"));
            goto error;
4001
        }
4002
        virBufferAsprintf(&buf, ",host_mtu=%u", net->mtu);
4003 4004
    }

4005
    virBufferAsprintf(&buf, ",netdev=host%s", net->info.alias);
4006
    virBufferAsprintf(&buf, ",id=%s", net->info.alias);
4007 4008
    virBufferAsprintf(&buf, ",mac=%s",
                      virMacAddrFormat(&net->mac, macaddr));
4009

4010
    if (qemuBuildDeviceAddressStr(&buf, def, &net->info, qemuCaps) < 0)
4011
        goto error;
4012
    if (qemuBuildRomStr(&buf, &net->info) < 0)
4013
        goto error;
4014
    if (bootindex)
4015
        virBufferAsprintf(&buf, ",bootindex=%u", bootindex);
4016 4017 4018
    if (usingVirtio &&
        qemuBuildVirtioOptionsStr(&buf, net->virtio, qemuCaps) < 0)
        goto error;
4019

4020
    if (virBufferCheckError(&buf) < 0)
4021 4022 4023 4024
        goto error;

    return virBufferContentAndReset(&buf);

4025
 error:
4026 4027 4028 4029 4030 4031 4032
    virBufferFreeAndReset(&buf);
    return NULL;
}


char *
qemuBuildHostNetStr(virDomainNetDefPtr net,
4033
                    virQEMUDriverPtr driver,
4034
                    char **tapfd,
4035
                    size_t tapfdSize,
4036
                    char **vhostfd,
4037
                    size_t vhostfdSize)
4038
{
4039
    bool is_tap = false;
4040
    virBuffer buf = VIR_BUFFER_INITIALIZER;
4041
    virDomainNetType netType = virDomainNetGetActualType(net);
4042
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
4043
    size_t i;
4044
    char *addr = NULL;
4045
    char *ret = NULL;
4046

4047
    if (net->script && netType != VIR_DOMAIN_NET_TYPE_ETHERNET) {
4048 4049 4050
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("scripts are not supported on interfaces of type %s"),
                       virDomainNetTypeToString(netType));
4051
        goto cleanup;
4052 4053 4054
    }

    switch (netType) {
M
Michal Privoznik 已提交
4055 4056 4057 4058 4059
        /*
         * If type='bridge', and we're running as privileged user
         * or -netdev bridge is not supported then it will fall
         * through, -net tap,fd
         */
4060
    case VIR_DOMAIN_NET_TYPE_BRIDGE:
R
Richa Marwaha 已提交
4061
    case VIR_DOMAIN_NET_TYPE_NETWORK:
4062
    case VIR_DOMAIN_NET_TYPE_DIRECT:
4063
    case VIR_DOMAIN_NET_TYPE_ETHERNET:
4064
        virBufferAddLit(&buf, "tap,");
4065 4066 4067
        /* for one tapfd 'fd=' shall be used,
         * for more than one 'fds=' is the right choice */
        if (tapfdSize == 1) {
4068
            virBufferAsprintf(&buf, "fd=%s,", tapfd[0]);
4069 4070 4071 4072 4073 4074 4075
        } else {
            virBufferAddLit(&buf, "fds=");
            for (i = 0; i < tapfdSize; i++) {
                if (i)
                    virBufferAddChar(&buf, ':');
                virBufferAdd(&buf, tapfd[i], -1);
            }
4076
            virBufferAddChar(&buf, ',');
4077
        }
4078
        is_tap = true;
4079 4080 4081
        break;

    case VIR_DOMAIN_NET_TYPE_CLIENT:
4082
        virBufferAsprintf(&buf, "socket,connect=%s:%d,",
M
Michal Privoznik 已提交
4083 4084 4085
                          net->data.socket.address,
                          net->data.socket.port);
        break;
4086

4087
    case VIR_DOMAIN_NET_TYPE_SERVER:
4088
        virBufferAsprintf(&buf, "socket,listen=%s:%d,",
J
Ján Tomko 已提交
4089
                          NULLSTR_EMPTY(net->data.socket.address),
M
Michal Privoznik 已提交
4090 4091
                          net->data.socket.port);
        break;
4092

4093
    case VIR_DOMAIN_NET_TYPE_MCAST:
4094
        virBufferAsprintf(&buf, "socket,mcast=%s:%d,",
M
Michal Privoznik 已提交
4095 4096 4097
                          net->data.socket.address,
                          net->data.socket.port);
        break;
4098

4099
    case VIR_DOMAIN_NET_TYPE_UDP:
4100
        virBufferAsprintf(&buf, "socket,udp=%s:%d,localaddr=%s:%d,",
M
Michal Privoznik 已提交
4101 4102 4103 4104 4105
                          net->data.socket.address,
                          net->data.socket.port,
                          net->data.socket.localaddr,
                          net->data.socket.localport);
        break;
4106

4107
    case VIR_DOMAIN_NET_TYPE_USER:
4108
        virBufferAddLit(&buf, "user,");
4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124
        for (i = 0; i < net->guestIP.nips; i++) {
            const virNetDevIPAddr *ip = net->guestIP.ips[i];
            const char *prefix = "";

            if (!(addr = virSocketAddrFormat(&ip->address)))
                goto cleanup;

            if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET))
                prefix = "net=";
            if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET6))
                prefix = "ipv6-net=";

            virBufferAsprintf(&buf, "%s%s", prefix, addr);
            if (ip->prefix)
                virBufferAsprintf(&buf, "/%u", ip->prefix);
            virBufferAddChar(&buf, ',');
4125
            VIR_FREE(addr);
4126 4127 4128
        }
        break;

4129
    case VIR_DOMAIN_NET_TYPE_INTERNAL:
4130
        virBufferAddLit(&buf, "user,");
4131
        break;
4132 4133

    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
4134
        virBufferAsprintf(&buf, "vhost-user,chardev=char%s,",
4135 4136
                          net->info.alias);
        if (net->driver.virtio.queues > 1)
4137
            virBufferAsprintf(&buf, "queues=%u,",
4138
                              net->driver.virtio.queues);
4139 4140
        break;

J
Ján Tomko 已提交
4141 4142
    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
        /* Should have been handled earlier via PCI/USB hotplug code. */
4143 4144
    case VIR_DOMAIN_NET_TYPE_LAST:
        break;
4145 4146
    }

4147
    virBufferAsprintf(&buf, "id=host%s,", net->info.alias);
4148

4149
    if (is_tap) {
4150
        if (vhostfdSize) {
4151
            virBufferAddLit(&buf, "vhost=on,");
4152
            if (vhostfdSize == 1) {
4153
                virBufferAsprintf(&buf, "vhostfd=%s,", vhostfd[0]);
4154 4155 4156 4157 4158 4159 4160
            } else {
                virBufferAddLit(&buf, "vhostfds=");
                for (i = 0; i < vhostfdSize; i++) {
                    if (i)
                        virBufferAddChar(&buf, ':');
                    virBufferAdd(&buf, vhostfd[i], -1);
                }
4161
                virBufferAddChar(&buf, ',');
4162 4163
            }
        }
4164
        if (net->tune.sndbuf_specified)
4165
            virBufferAsprintf(&buf, "sndbuf=%lu,", net->tune.sndbuf);
4166 4167
    }

4168

4169
    virBufferTrim(&buf, ",", -1);
4170
    if (virBufferCheckError(&buf) < 0)
4171
        goto cleanup;
4172

4173 4174 4175 4176
    ret = virBufferContentAndReset(&buf);
 cleanup:
    virBufferFreeAndReset(&buf);
    virObjectUnref(cfg);
4177
    VIR_FREE(addr);
4178
    return ret;
4179 4180 4181
}


M
Michal Privoznik 已提交
4182
char *
4183
qemuBuildWatchdogDevStr(const virDomainDef *def,
4184
                        virDomainWatchdogDefPtr dev,
4185
                        virQEMUCapsPtr qemuCaps)
4186 4187 4188 4189 4190
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    const char *model = virDomainWatchdogModelTypeToString(dev->model);
    if (!model) {
4191 4192
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing watchdog model"));
4193 4194 4195
        goto error;
    }

4196
    virBufferAsprintf(&buf, "%s,id=%s", model, dev->info.alias);
4197
    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
4198 4199
        goto error;

4200
    if (virBufferCheckError(&buf) < 0)
4201 4202 4203 4204
        goto error;

    return virBufferContentAndReset(&buf);

4205
 error:
4206 4207 4208 4209 4210
    virBufferFreeAndReset(&buf);
    return NULL;
}


4211 4212 4213 4214 4215 4216 4217 4218
static int
qemuBuildWatchdogCommandLine(virCommandPtr cmd,
                             const virDomainDef *def,
                             virQEMUCapsPtr qemuCaps)
{
    virDomainWatchdogDefPtr watchdog = def->watchdog;
    char *optstr;
    const char *action;
4219
    int actualAction;
4220 4221 4222 4223

    if (!def->watchdog)
        return 0;

4224 4225 4226
    if (qemuCommandAddExtDevice(cmd, &def->watchdog->info) < 0)
        return -1;

4227
    virCommandAddArg(cmd, "-device");
4228

4229 4230 4231
    optstr = qemuBuildWatchdogDevStr(def, watchdog, qemuCaps);
    if (!optstr)
        return -1;
4232 4233 4234 4235

    virCommandAddArg(cmd, optstr);
    VIR_FREE(optstr);

4236 4237 4238 4239
    /* qemu doesn't have a 'dump' action; we tell qemu to 'pause', then
       libvirt listens for the watchdog event, and we perform the dump
       ourselves. so convert 'dump' to 'pause' for the qemu cli */
    actualAction = watchdog->action;
4240
    if (watchdog->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP)
4241
        actualAction = VIR_DOMAIN_WATCHDOG_ACTION_PAUSE;
4242

4243
    action = virDomainWatchdogActionTypeToString(actualAction);
4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254
    if (!action) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("invalid watchdog action"));
        return -1;
    }
    virCommandAddArgList(cmd, "-watchdog-action", action, NULL);

    return 0;
}


4255 4256 4257 4258
static int
qemuBuildMemballoonCommandLine(virCommandPtr cmd,
                               const virDomainDef *def,
                               virQEMUCapsPtr qemuCaps)
4259 4260 4261
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

4262
    if (!virDomainDefHasMemballoon(def))
4263 4264
        return 0;

4265
    if (qemuBuildVirtioDevStr(&buf, "virtio-balloon", qemuCaps,
4266 4267
                              VIR_DOMAIN_DEVICE_MEMBALLOON,
                              def->memballoon) < 0) {
4268
        goto error;
4269 4270
    }

4271 4272
    virBufferAsprintf(&buf, ",id=%s", def->memballoon->info.alias);
    if (qemuBuildDeviceAddressStr(&buf, def, &def->memballoon->info, qemuCaps) < 0)
4273 4274
        goto error;

4275
    if (def->memballoon->autodeflate != VIR_TRISTATE_SWITCH_ABSENT) {
4276
        virBufferAsprintf(&buf, ",deflate-on-oom=%s",
4277
                          virTristateSwitchTypeToString(def->memballoon->autodeflate));
4278 4279
    }

4280 4281 4282
    if (qemuBuildVirtioOptionsStr(&buf, def->memballoon->virtio, qemuCaps) < 0)
        goto error;

4283 4284 4285
    if (qemuCommandAddExtDevice(cmd, &def->memballoon->info) < 0)
        goto error;

4286 4287 4288
    virCommandAddArg(cmd, "-device");
    virCommandAddArgBuffer(cmd, &buf);
    return 0;
4289

4290
 error:
4291
    virBufferFreeAndReset(&buf);
4292
    return -1;
4293 4294 4295
}


4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310
static char *
qemuBuildNVRAMDevStr(virDomainNVRAMDefPtr dev)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (dev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO &&
        dev->info.addr.spaprvio.has_reg) {
        virBufferAsprintf(&buf, "spapr-nvram.reg=0x%llx",
                          dev->info.addr.spaprvio.reg);
    } else {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("nvram address type must be spaprvio"));
        goto error;
    }

4311
    if (virBufferCheckError(&buf) < 0)
4312 4313 4314 4315
        goto error;

    return virBufferContentAndReset(&buf);

4316
 error:
4317 4318 4319
    virBufferFreeAndReset(&buf);
    return NULL;
}
4320

4321 4322 4323 4324 4325 4326 4327 4328 4329

static int
qemuBuildNVRAMCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
    if (!def->nvram)
        return 0;

4330
    if (qemuDomainIsPSeries(def)) {
4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_NVRAM)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("nvram device is not supported by "
                             "this QEMU binary"));
            return -1;
        }

        char *optstr;
        virCommandAddArg(cmd, "-global");
        optstr = qemuBuildNVRAMDevStr(def->nvram);
        if (!optstr)
            return -1;
4343
        virCommandAddArg(cmd, optstr);
4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354
        VIR_FREE(optstr);
    } else {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                      _("nvram device is only supported for PPC64"));
        return -1;
    }

    return 0;
}


4355
static char *
4356
qemuBuildVirtioInputDevStr(const virDomainDef *def,
4357 4358 4359 4360 4361
                           virDomainInputDefPtr dev,
                           virQEMUCapsPtr qemuCaps)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

4362
    switch ((virDomainInputType)dev->type) {
4363
    case VIR_DOMAIN_INPUT_TYPE_MOUSE:
4364
        if (qemuBuildVirtioDevStr(&buf, "virtio-mouse", qemuCaps,
4365
                                  VIR_DOMAIN_DEVICE_INPUT, dev) < 0) {
4366
            goto error;
4367
        }
4368 4369
        break;
    case VIR_DOMAIN_INPUT_TYPE_TABLET:
4370
        if (qemuBuildVirtioDevStr(&buf, "virtio-tablet", qemuCaps,
4371
                                  VIR_DOMAIN_DEVICE_INPUT, dev) < 0) {
4372
            goto error;
4373
        }
4374 4375
        break;
    case VIR_DOMAIN_INPUT_TYPE_KBD:
4376
        if (qemuBuildVirtioDevStr(&buf, "virtio-keyboard", qemuCaps,
4377
                                  VIR_DOMAIN_DEVICE_INPUT, dev) < 0) {
4378
            goto error;
4379
        }
4380
        break;
4381
    case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
4382
        if (qemuBuildVirtioDevStr(&buf, "virtio-input-host", qemuCaps,
4383
                                  VIR_DOMAIN_DEVICE_INPUT, dev) < 0) {
4384
            goto error;
4385
        }
4386
        break;
4387
    case VIR_DOMAIN_INPUT_TYPE_LAST:
4388 4389 4390
    default:
        virReportEnumRangeError(virDomainInputType, dev->type);
        goto error;
4391 4392
    }

4393 4394 4395 4396 4397 4398 4399
    virBufferAsprintf(&buf, ",id=%s", dev->info.alias);

    if (dev->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH) {
        virBufferAddLit(&buf, ",evdev=");
        virQEMUBuildBufferEscapeComma(&buf, dev->source.evdev);
    }

4400 4401 4402
    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
        goto error;

4403 4404 4405
    if (qemuBuildVirtioOptionsStr(&buf, dev->virtio, qemuCaps) < 0)
        goto error;

4406 4407 4408 4409 4410 4411 4412 4413 4414 4415
    if (virBufferCheckError(&buf) < 0)
        goto error;

    return virBufferContentAndReset(&buf);

 error:
    virBufferFreeAndReset(&buf);
    return NULL;
}

4416 4417
static char *
qemuBuildUSBInputDevStr(const virDomainDef *def,
4418
                        virDomainInputDefPtr dev,
4419
                        virQEMUCapsPtr qemuCaps)
4420 4421 4422
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

4423 4424 4425 4426 4427 4428 4429 4430
    switch (dev->type) {
    case VIR_DOMAIN_INPUT_TYPE_MOUSE:
        virBufferAsprintf(&buf, "usb-mouse,id=%s", dev->info.alias);
        break;
    case VIR_DOMAIN_INPUT_TYPE_TABLET:
        virBufferAsprintf(&buf, "usb-tablet,id=%s", dev->info.alias);
        break;
    case VIR_DOMAIN_INPUT_TYPE_KBD:
4431 4432 4433 4434
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_KBD)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("usb keyboard is not supported by this "
                             "QEMU binary"));
4435
            goto error;
4436
        }
4437 4438 4439
        virBufferAsprintf(&buf, "usb-kbd,id=%s", dev->info.alias);
        break;
    }
4440

4441
    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
4442 4443
        goto error;

4444
    if (virBufferCheckError(&buf) < 0)
4445 4446 4447 4448
        goto error;

    return virBufferContentAndReset(&buf);

4449
 error:
4450 4451 4452 4453 4454
    virBufferFreeAndReset(&buf);
    return NULL;
}


J
Ján Tomko 已提交
4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475
int
qemuBuildInputDevStr(char **devstr,
                     const virDomainDef *def,
                     virDomainInputDefPtr input,
                     virQEMUCapsPtr qemuCaps)
{
    switch (input->bus) {
    case VIR_DOMAIN_INPUT_BUS_USB:
        if (!(*devstr = qemuBuildUSBInputDevStr(def, input, qemuCaps)))
            return -1;
        break;

    case VIR_DOMAIN_INPUT_BUS_VIRTIO:
        if (!(*devstr = qemuBuildVirtioInputDevStr(def, input, qemuCaps)))
            return -1;
        break;
    }
    return 0;
}


4476 4477 4478 4479 4480 4481 4482 4483 4484
static int
qemuBuildInputCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
    size_t i;

    for (i = 0; i < def->ninputs; i++) {
        virDomainInputDefPtr input = def->inputs[i];
J
Ján Tomko 已提交
4485
        char *devstr = NULL;
4486

4487 4488 4489
        if (qemuCommandAddExtDevice(cmd, &input->info) < 0)
            return -1;

J
Ján Tomko 已提交
4490 4491 4492 4493
        if (qemuBuildInputDevStr(&devstr, def, input, qemuCaps) < 0)
            return -1;

        if (devstr) {
4494
            virCommandAddArg(cmd, "-device");
J
Ján Tomko 已提交
4495
            virCommandAddArg(cmd, devstr);
4496
        }
J
Ján Tomko 已提交
4497 4498

        VIR_FREE(devstr);
4499 4500 4501 4502 4503 4504
    }

    return 0;
}


4505 4506
static char *
qemuBuildSoundDevStr(const virDomainDef *def,
4507
                     virDomainSoundDefPtr sound,
4508
                     virQEMUCapsPtr qemuCaps)
4509 4510
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
4511
    const char *model = NULL;
4512

4513
    /* Hack for devices with different names in QEMU and libvirt */
4514
    switch ((virDomainSoundModel) sound->model) {
4515
    case VIR_DOMAIN_SOUND_MODEL_ES1370:
4516
        model = "ES1370";
4517 4518
        break;
    case VIR_DOMAIN_SOUND_MODEL_AC97:
4519
        model = "AC97";
4520 4521
        break;
    case VIR_DOMAIN_SOUND_MODEL_ICH6:
4522
        model = "intel-hda";
4523
        break;
4524 4525 4526 4527 4528 4529 4530 4531 4532
    case VIR_DOMAIN_SOUND_MODEL_USB:
        model = "usb-audio";
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_USB_AUDIO)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("usb-audio controller is not supported "
                             "by this QEMU binary"));
            goto error;
        }
        break;
4533 4534 4535 4536 4537 4538 4539 4540 4541
    case VIR_DOMAIN_SOUND_MODEL_ICH9:
        model = "ich9-intel-hda";
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ICH9_INTEL_HDA)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("The ich9-intel-hda audio controller "
                             "is not supported in this QEMU binary"));
            goto error;
        }
        break;
4542 4543 4544 4545 4546 4547 4548 4549 4550
    case VIR_DOMAIN_SOUND_MODEL_SB16:
        model = "sb16";
        break;
    case VIR_DOMAIN_SOUND_MODEL_PCSPK: /* pc-speaker is handled separately */
    case VIR_DOMAIN_SOUND_MODEL_LAST:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("sound card model '%s' is not supported by qemu"),
                       virDomainSoundModelTypeToString(sound->model));
        goto error;
4551
    }
4552

4553
    virBufferAsprintf(&buf, "%s,id=%s", model, sound->info.alias);
4554
    if (qemuBuildDeviceAddressStr(&buf, def, &sound->info, qemuCaps) < 0)
4555 4556
        goto error;

4557
    if (virBufferCheckError(&buf) < 0)
4558 4559 4560 4561
        goto error;

    return virBufferContentAndReset(&buf);

4562
 error:
4563 4564 4565 4566
    virBufferFreeAndReset(&buf);
    return NULL;
}

4567 4568 4569 4570 4571 4572 4573 4574 4575

static int
qemuSoundCodecTypeToCaps(int type)
{
    switch (type) {
    case VIR_DOMAIN_SOUND_CODEC_TYPE_DUPLEX:
        return QEMU_CAPS_HDA_DUPLEX;
    case VIR_DOMAIN_SOUND_CODEC_TYPE_MICRO:
        return QEMU_CAPS_HDA_MICRO;
4576 4577
    case VIR_DOMAIN_SOUND_CODEC_TYPE_OUTPUT:
        return QEMU_CAPS_HDA_OUTPUT;
4578 4579 4580 4581 4582 4583
    default:
        return -1;
    }
}


4584 4585
static char *
qemuBuildSoundCodecStr(virDomainSoundDefPtr sound,
4586
                       virDomainSoundCodecDefPtr codec,
4587
                       virQEMUCapsPtr qemuCaps)
4588 4589
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
4590
    const char *stype;
4591
    int type, flags;
4592

4593 4594
    type = codec->type;
    stype = qemuSoundCodecTypeToString(type);
4595
    flags = qemuSoundCodecTypeToCaps(type);
4596

4597
    if (flags == -1 || !virQEMUCapsGet(qemuCaps, flags)) {
4598 4599
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("%s not supported in this QEMU binary"), stype);
4600 4601 4602
        goto error;
    }

4603 4604 4605
    virBufferAsprintf(&buf, "%s,id=%s-codec%d,bus=%s.0,cad=%d",
                      stype, sound->info.alias, codec->cad, sound->info.alias, codec->cad);

4606 4607
    return virBufferContentAndReset(&buf);

4608
 error:
4609 4610 4611
    virBufferFreeAndReset(&buf);
    return NULL;
}
4612

4613 4614 4615 4616 4617 4618 4619 4620

static int
qemuBuildSoundCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
    size_t i, j;

4621 4622 4623
    for (i = 0; i < def->nsounds; i++) {
        virDomainSoundDefPtr sound = def->sounds[i];
        char *str = NULL;
4624

4625 4626 4627 4628 4629 4630
        /* Sadly pcspk device doesn't use -device syntax. Fortunately
         * we don't need to set any PCI address on it, so we don't
         * mind too much */
        if (sound->model == VIR_DOMAIN_SOUND_MODEL_PCSPK) {
            virCommandAddArgList(cmd, "-soundhw", "pcspk", NULL);
        } else {
4631 4632 4633
            if (qemuCommandAddExtDevice(cmd, &sound->info) < 0)
                return -1;

4634 4635 4636
            virCommandAddArg(cmd, "-device");
            if (!(str = qemuBuildSoundDevStr(def, sound, qemuCaps)))
                return -1;
4637

4638 4639 4640 4641 4642
            virCommandAddArg(cmd, str);
            VIR_FREE(str);
            if (sound->model == VIR_DOMAIN_SOUND_MODEL_ICH6 ||
                sound->model == VIR_DOMAIN_SOUND_MODEL_ICH9) {
                char *codecstr = NULL;
4643

4644 4645 4646 4647 4648 4649
                for (j = 0; j < sound->ncodecs; j++) {
                    virCommandAddArg(cmd, "-device");
                    if (!(codecstr =
                          qemuBuildSoundCodecStr(sound, sound->codecs[j],
                                                 qemuCaps))) {
                        return -1;
4650 4651

                    }
4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664
                    virCommandAddArg(cmd, codecstr);
                    VIR_FREE(codecstr);
                }
                if (j == 0) {
                    virDomainSoundCodecDef codec = {
                        VIR_DOMAIN_SOUND_CODEC_TYPE_DUPLEX,
                        0
                    };
                    virCommandAddArg(cmd, "-device");
                    if (!(codecstr =
                          qemuBuildSoundCodecStr(sound, &codec,
                                                 qemuCaps))) {
                        return -1;
4665 4666

                    }
4667 4668
                    virCommandAddArg(cmd, codecstr);
                    VIR_FREE(codecstr);
4669 4670 4671 4672 4673 4674 4675 4676 4677
                }
            }
        }
    }
    return 0;
}



4678
static char *
4679
qemuBuildDeviceVideoStr(const virDomainDef *def,
4680
                        virDomainVideoDefPtr video,
4681
                        virQEMUCapsPtr qemuCaps)
4682 4683
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
4684
    const char *model;
4685

4686 4687 4688 4689 4690
    /* We try to chose the best model for primary video device by preferring
     * model with VGA compatibility mode.  For some video devices on some
     * architectures there might not be such model so fallback to one
     * without VGA compatibility mode. */
    if (video->primary && qemuDomainSupportsVideoVga(video, qemuCaps))
4691
        model = qemuDeviceVideoTypeToString(video->type);
4692 4693 4694 4695 4696 4697 4698 4699
    else
        model = qemuDeviceVideoSecondaryTypeToString(video->type);

    if (!model || STREQ(model, "")) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("invalid model for video type '%s'"),
                       virDomainVideoTypeToString(video->type));
        goto error;
4700 4701
    }

4702
    if (STREQ(model, "virtio-gpu")) {
4703
        if (qemuBuildVirtioDevStr(&buf, "virtio-gpu", qemuCaps,
4704
                                  VIR_DOMAIN_DEVICE_VIDEO, video) < 0) {
4705
            goto error;
4706
        }
4707 4708 4709 4710 4711
    } else {
        virBufferAsprintf(&buf, "%s", model);
    }

    virBufferAsprintf(&buf, ",id=%s", video->info.alias);
4712

4713 4714 4715 4716 4717 4718
    if (video->accel && video->accel->accel3d == VIR_TRISTATE_SWITCH_ON) {
        virBufferAsprintf(&buf, ",virgl=%s",
                          virTristateSwitchTypeToString(video->accel->accel3d));
    }

    if (video->type == VIR_DOMAIN_VIDEO_TYPE_QXL) {
4719 4720 4721 4722
        if (video->ram) {
            /* QEMU accepts bytes for ram_size. */
            virBufferAsprintf(&buf, ",ram_size=%u", video->ram * 1024);
        }
4723

4724 4725 4726 4727
        if (video->vram) {
            /* QEMU accepts bytes for vram_size. */
            virBufferAsprintf(&buf, ",vram_size=%u", video->vram * 1024);
        }
4728

4729
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VRAM64)) {
4730 4731 4732 4733
            /* QEMU accepts mebibytes for vram64_size_mb. */
            virBufferAsprintf(&buf, ",vram64_size_mb=%u", video->vram64 / 1024);
        }

4734
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGAMEM)) {
4735 4736 4737
            /* QEMU accepts mebibytes for vgamem_mb. */
            virBufferAsprintf(&buf, ",vgamem_mb=%u", video->vgamem / 1024);
        }
4738

4739
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_MAX_OUTPUTS)) {
4740 4741 4742
            if (video->heads)
                virBufferAsprintf(&buf, ",max_outputs=%u", video->heads);
        }
4743 4744 4745 4746 4747
    } else if (video->type == VIR_DOMAIN_VIDEO_TYPE_VIRTIO) {
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_GPU_MAX_OUTPUTS)) {
            if (video->heads)
                virBufferAsprintf(&buf, ",max_outputs=%u", video->heads);
        }
4748 4749 4750 4751 4752 4753 4754
    } else if (video->vram &&
        ((video->type == VIR_DOMAIN_VIDEO_TYPE_VGA &&
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_VGAMEM)) ||
         (video->type == VIR_DOMAIN_VIDEO_TYPE_VMVGA &&
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_VMWARE_SVGA_VGAMEM)))) {

        virBufferAsprintf(&buf, ",vgamem_mb=%u", video->vram / 1024);
4755 4756
    }

4757
    if (qemuBuildDeviceAddressStr(&buf, def, &video->info, qemuCaps) < 0)
4758 4759
        goto error;

4760 4761 4762
    if (qemuBuildVirtioOptionsStr(&buf, video->virtio, qemuCaps) < 0)
        goto error;

4763
    if (virBufferCheckError(&buf) < 0)
4764 4765 4766 4767
        goto error;

    return virBufferContentAndReset(&buf);

4768
 error:
4769 4770 4771 4772 4773
    virBufferFreeAndReset(&buf);
    return NULL;
}


4774 4775
static int
qemuBuildVgaVideoCommand(virCommandPtr cmd,
4776
                         virDomainVideoDefPtr video,
4777 4778
                         virQEMUCapsPtr qemuCaps)
{
4779
    const char *vgastr = qemuVideoTypeToString(video->type);
4780 4781 4782
    if (!vgastr || STREQ(vgastr, "")) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("invalid model for video type '%s'"),
4783
                       virDomainVideoTypeToString(video->type));
4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799
        return -1;
    }

    virCommandAddArgList(cmd, "-vga", vgastr, NULL);

    /* If we cannot use --device option to specify the video device
     * in QEMU we will fallback to the old --vga option. To get the
     * correct device name for the --vga option the 'qemuVideo' is
     * used, but to set some device attributes we need to use the
     * --global option and for that we need to specify the device
     * name the same as for --device option and for that we need to
     * use 'qemuDeviceVideo'.
     *
     * See 'Graphics Devices' section in docs/qdev-device-use.txt in
     * QEMU repository.
     */
4800
    const char *dev = qemuDeviceVideoTypeToString(video->type);
4801

4802 4803 4804 4805 4806 4807
    if (video->type == VIR_DOMAIN_VIDEO_TYPE_QXL &&
        (video->vram || video->ram)) {
        unsigned int ram = video->ram;
        unsigned int vram = video->vram;
        unsigned int vram64 = video->vram64;
        unsigned int vgamem = video->vgamem;
4808
        unsigned int heads = video->heads;
4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831

        if (ram) {
            virCommandAddArg(cmd, "-global");
            virCommandAddArgFormat(cmd, "%s.ram_size=%u",
                                   dev, ram * 1024);
        }
        if (vram) {
            virCommandAddArg(cmd, "-global");
            virCommandAddArgFormat(cmd, "%s.vram_size=%u",
                                   dev, vram * 1024);
        }
        if (vram64 &&
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VRAM64)) {
            virCommandAddArg(cmd, "-global");
            virCommandAddArgFormat(cmd, "%s.vram64_size_mb=%u",
                                   dev, vram64 / 1024);
        }
        if (vgamem &&
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGAMEM)) {
            virCommandAddArg(cmd, "-global");
            virCommandAddArgFormat(cmd, "%s.vgamem_mb=%u",
                                   dev, vgamem / 1024);
        }
4832 4833 4834 4835 4836 4837
        if (heads &&
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_MAX_OUTPUTS)) {
            virCommandAddArg(cmd, "-global");
            virCommandAddArgFormat(cmd, "%s.max_outputs=%u",
                                   dev, heads);
        }
4838 4839
    }

4840 4841
    if (video->vram &&
        ((video->type == VIR_DOMAIN_VIDEO_TYPE_VGA &&
4842
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_VGAMEM)) ||
4843
         (video->type == VIR_DOMAIN_VIDEO_TYPE_VMVGA &&
4844
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_VMWARE_SVGA_VGAMEM)))) {
4845
        unsigned int vram = video->vram;
4846 4847 4848 4849 4850 4851 4852 4853 4854 4855

        virCommandAddArg(cmd, "-global");
        virCommandAddArgFormat(cmd, "%s.vgamem_mb=%u",
                               dev, vram / 1024);
    }

    return 0;
}


4856 4857 4858 4859 4860 4861 4862
static int
qemuBuildVideoCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
    size_t i;

4863 4864 4865
    for (i = 0; i < def->nvideos; i++) {
        char *str = NULL;
        virDomainVideoDefPtr video = def->videos[i];
4866

4867 4868 4869
        if (video->type == VIR_DOMAIN_VIDEO_TYPE_NONE)
            continue;

4870 4871
        if (video->primary) {
            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY)) {
4872

4873 4874 4875 4876
                if (qemuCommandAddExtDevice(cmd,
                                            &def->videos[i]->info) < 0)
                    return -1;

4877
                virCommandAddArg(cmd, "-device");
4878

4879 4880
                if (!(str = qemuBuildDeviceVideoStr(def, video, qemuCaps)))
                    return -1;
4881

4882 4883 4884 4885 4886 4887 4888
                virCommandAddArg(cmd, str);
                VIR_FREE(str);
            } else {
                if (qemuBuildVgaVideoCommand(cmd, video, qemuCaps) < 0)
                    return -1;
            }
        } else {
4889 4890 4891
            if (qemuCommandAddExtDevice(cmd, &def->videos[i]->info) < 0)
                return -1;

4892
            virCommandAddArg(cmd, "-device");
4893

4894
            if (!(str = qemuBuildDeviceVideoStr(def, video, qemuCaps)))
4895
                return -1;
4896 4897 4898

            virCommandAddArg(cmd, str);
            VIR_FREE(str);
4899 4900 4901 4902 4903 4904 4905
        }
    }

    return 0;
}


4906 4907 4908
int
qemuOpenPCIConfig(virDomainHostdevDefPtr dev)
{
4909
    virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
4910 4911 4912 4913
    char *path = NULL;
    int configfd = -1;

    if (virAsprintf(&path, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/config",
4914 4915
                    pcisrc->addr.domain, pcisrc->addr.bus,
                    pcisrc->addr.slot, pcisrc->addr.function) < 0)
4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928
        return -1;

    configfd = open(path, O_RDWR, 0);

    if (configfd < 0)
        virReportSystemError(errno, _("Failed opening %s"), path);

    VIR_FREE(path);

    return configfd;
}

char *
4929
qemuBuildPCIHostdevDevStr(const virDomainDef *def,
4930
                          virDomainHostdevDefPtr dev,
4931
                          unsigned int bootIndex, /* used iff dev->info->bootIndex == 0 */
4932
                          const char *configfd,
4933
                          virQEMUCapsPtr qemuCaps)
4934 4935
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
4936 4937
    virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
    int backend = pcisrc->backend;
4938

4939
    /* caller has to assign proper passthrough backend type */
4940
    switch ((virDomainHostdevSubsysPCIBackendType)backend) {
4941
    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
4942 4943 4944
        virBufferAddLit(&buf, "pci-assign");
        if (configfd && *configfd)
            virBufferAsprintf(&buf, ",configfd=%s", configfd);
4945 4946 4947 4948 4949 4950
        break;

    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
        virBufferAddLit(&buf, "vfio-pci");
        break;

4951 4952 4953
    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
4954 4955
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("invalid PCI passthrough type '%s'"),
4956
                       virDomainHostdevSubsysPCIBackendTypeToString(backend));
4957
        goto error;
4958
    }
4959

4960
    virBufferAddLit(&buf, ",host=");
4961
    if (pcisrc->addr.domain)
4962
        virBufferAsprintf(&buf, "%.4x:", pcisrc->addr.domain);
4963
    virBufferAsprintf(&buf, "%.2x:%.2x.%.1x",
4964 4965
                      pcisrc->addr.bus, pcisrc->addr.slot,
                      pcisrc->addr.function);
4966 4967
    virBufferAsprintf(&buf, ",id=%s", dev->info->alias);
    if (dev->info->bootIndex)
4968 4969
        bootIndex = dev->info->bootIndex;
    if (bootIndex)
4970
        virBufferAsprintf(&buf, ",bootindex=%u", bootIndex);
4971
    if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
4972
        goto error;
4973
    if (qemuBuildRomStr(&buf, dev->info) < 0)
4974
        goto error;
4975

4976
    if (virBufferCheckError(&buf) < 0)
4977 4978 4979 4980
        goto error;

    return virBufferContentAndReset(&buf);

4981
 error:
4982 4983 4984 4985 4986 4987
    virBufferFreeAndReset(&buf);
    return NULL;
}


char *
4988
qemuBuildUSBHostdevDevStr(const virDomainDef *def,
4989
                          virDomainHostdevDefPtr dev,
4990
                          virQEMUCapsPtr qemuCaps)
4991
{
4992
    virBuffer buf = VIR_BUFFER_INITIALIZER;
4993
    virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
4994

4995
    if (!dev->missing && !usbsrc->bus && !usbsrc->device) {
4996 4997
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("USB host device is missing bus/device information"));
4998 4999 5000
        return NULL;
    }

5001 5002 5003
    virBufferAddLit(&buf, "usb-host");
    if (!dev->missing) {
        virBufferAsprintf(&buf, ",hostbus=%d,hostaddr=%d",
5004
                          usbsrc->bus, usbsrc->device);
5005 5006
    }
    virBufferAsprintf(&buf, ",id=%s", dev->info->alias);
5007
    if (dev->info->bootIndex)
5008
        virBufferAsprintf(&buf, ",bootindex=%u", dev->info->bootIndex);
5009

5010
    if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
5011 5012
        goto error;

5013
    if (virBufferCheckError(&buf) < 0)
5014
        goto error;
5015

5016 5017
    return virBufferContentAndReset(&buf);

5018
 error:
5019 5020
    virBufferFreeAndReset(&buf);
    return NULL;
5021 5022 5023
}


5024 5025
static char *
qemuBuildHubDevStr(const virDomainDef *def,
5026
                   virDomainHubDefPtr dev,
5027
                   virQEMUCapsPtr qemuCaps)
M
Marc-André Lureau 已提交
5028 5029 5030 5031
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (dev->type != VIR_DOMAIN_HUB_TYPE_USB) {
5032 5033 5034
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hub type %s not supported"),
                       virDomainHubTypeToString(dev->type));
M
Marc-André Lureau 已提交
5035 5036 5037
        goto error;
    }

5038
    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_HUB)) {
5039
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5040
                       _("usb-hub not supported by QEMU binary"));
M
Marc-André Lureau 已提交
5041 5042 5043 5044 5045
        goto error;
    }

    virBufferAddLit(&buf, "usb-hub");
    virBufferAsprintf(&buf, ",id=%s", dev->info.alias);
5046
    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
M
Marc-André Lureau 已提交
5047 5048
        goto error;

5049
    if (virBufferCheckError(&buf) < 0)
M
Marc-André Lureau 已提交
5050 5051 5052 5053
        goto error;

    return virBufferContentAndReset(&buf);

5054
 error:
M
Marc-André Lureau 已提交
5055 5056 5057 5058 5059
    virBufferFreeAndReset(&buf);
    return NULL;
}


5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081
static int
qemuBuildHubCommandLine(virCommandPtr cmd,
                        const virDomainDef *def,
                        virQEMUCapsPtr qemuCaps)
{
    size_t i;

    for (i = 0; i < def->nhubs; i++) {
        virDomainHubDefPtr hub = def->hubs[i];
        char *optstr;

        virCommandAddArg(cmd, "-device");
        if (!(optstr = qemuBuildHubDevStr(def, hub, qemuCaps)))
            return -1;
        virCommandAddArg(cmd, optstr);
        VIR_FREE(optstr);
    }

    return 0;
}


5082
static char *
J
Ján Tomko 已提交
5083
qemuBuildSCSIHostHostdevDrvStr(virDomainHostdevDefPtr dev)
5084
{
5085
    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
5086
    virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
J
Ján Tomko 已提交
5087 5088 5089 5090 5091 5092

    return virSCSIDeviceGetSgName(NULL,
                                  scsihostsrc->adapter,
                                  scsihostsrc->bus,
                                  scsihostsrc->target,
                                  scsihostsrc->unit);
5093 5094 5095
}

static char *
5096 5097
qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev,
                                virQEMUCapsPtr qemuCaps)
5098
{
5099
    char *ret = NULL;
5100
    virBuffer buf = VIR_BUFFER_INITIALIZER;
5101
    char *netsource = NULL;
5102
    virJSONValuePtr srcprops = NULL;
5103 5104
    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
    virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
5105 5106
    qemuDomainStorageSourcePrivatePtr srcPriv =
        QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(iscsisrc->src);
5107

5108 5109 5110 5111 5112
    if (qemuDiskSourceNeedsProps(iscsisrc->src, qemuCaps)) {
        if (!(srcprops = qemuDiskSourceGetProps(iscsisrc->src)))
            goto cleanup;
        if (!(netsource = virQEMUBuildDriveCommandlineFromJSON(srcprops)))
            goto cleanup;
5113
        virBufferAsprintf(&buf, "%s,if=none,format=raw", netsource);
5114 5115 5116 5117 5118
    } else {
        /* Rather than pull what we think we want - use the network disk code */
        if (!(netsource = qemuBuildNetworkDriveStr(iscsisrc->src, srcPriv ?
                                                   srcPriv->secinfo : NULL)))
            goto cleanup;
5119 5120 5121
        virBufferAddLit(&buf, "file=");
        virQEMUBuildBufferEscapeComma(&buf, netsource);
        virBufferAddLit(&buf, ",if=none,format=raw");
5122
    }
5123

5124 5125 5126
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;

5127
    ret = virBufferContentAndReset(&buf);
5128

5129 5130
 cleanup:
    VIR_FREE(netsource);
5131
    virJSONValueFree(srcprops);
5132
    virBufferFreeAndReset(&buf);
5133
    return ret;
5134 5135
}

5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150
char *
qemuBuildSCSIVHostHostdevDevStr(const virDomainDef *def,
                           virDomainHostdevDefPtr dev,
                           virQEMUCapsPtr qemuCaps,
                           char *vhostfdName)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host;

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VHOST_SCSI)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("This QEMU doesn't support vhost-scsi devices"));
        goto cleanup;
    }

5151
    if (qemuBuildVirtioDevStr(&buf, "vhost-scsi", qemuCaps,
5152
                              VIR_DOMAIN_DEVICE_HOSTDEV, dev) < 0) {
5153
        goto cleanup;
5154
    }
5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173

    virBufferAsprintf(&buf, ",wwpn=%s,vhostfd=%s,id=%s",
                      hostsrc->wwpn,
                      vhostfdName,
                      dev->info->alias);

    if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
        goto cleanup;

    if (virBufferCheckError(&buf) < 0)
        goto cleanup;

    return virBufferContentAndReset(&buf);

 cleanup:
    virBufferFreeAndReset(&buf);
    return NULL;
}

5174
char *
5175 5176
qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev,
                           virQEMUCapsPtr qemuCaps)
5177 5178 5179
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *source = NULL;
J
John Ferlan 已提交
5180
    char *drivealias = NULL;
5181 5182 5183
    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;

    if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
5184
        if (!(source = qemuBuildSCSIiSCSIHostdevDrvStr(dev, qemuCaps)))
5185
            goto error;
5186
        virBufferAdd(&buf, source, -1);
5187
    } else {
J
Ján Tomko 已提交
5188
        if (!(source = qemuBuildSCSIHostHostdevDrvStr(dev)))
5189
            goto error;
5190
        virBufferAsprintf(&buf, "file=/dev/%s,if=none,format=raw", source);
5191
    }
J
John Ferlan 已提交
5192 5193 5194 5195 5196 5197
    VIR_FREE(source);

    if (!(drivealias = qemuAliasFromHostdev(dev)))
        goto error;
    virBufferAsprintf(&buf, ",id=%s", drivealias);
    VIR_FREE(drivealias);
5198

5199 5200
    if (dev->readonly)
        virBufferAddLit(&buf, ",readonly=on");
O
Osier Yang 已提交
5201

5202
    if (virBufferCheckError(&buf) < 0)
5203 5204 5205
        goto error;

    return virBufferContentAndReset(&buf);
5206
 error:
5207 5208 5209 5210 5211
    virBufferFreeAndReset(&buf);
    return NULL;
}

char *
5212
qemuBuildSCSIHostdevDevStr(const virDomainDef *def,
5213
                           virDomainHostdevDefPtr dev)
5214 5215 5216
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    int model = -1;
J
John Ferlan 已提交
5217
    char *driveAlias;
5218
    const char *contAlias;
5219

5220
    model = qemuDomainFindSCSIControllerModel(def, dev->info);
5221
    if (model < 0)
5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241
        goto error;

    if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) {
        if (dev->info->addr.drive.target != 0) {
           virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("target must be 0 for scsi host device "
                             "if its controller model is 'lsilogic'"));
            goto error;
        }

        if (dev->info->addr.drive.unit > 7) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("unit must be not more than 7 for scsi host "
                             "device if its controller model is 'lsilogic'"));
            goto error;
        }
    }

    virBufferAddLit(&buf, "scsi-generic");

5242 5243 5244 5245
    if (!(contAlias = virDomainControllerAliasFind(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
                                                   dev->info->addr.drive.controller)))
        goto error;

5246
    if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) {
5247 5248
        virBufferAsprintf(&buf, ",bus=%s.%d,scsi-id=%d",
                          contAlias,
5249 5250 5251
                          dev->info->addr.drive.bus,
                          dev->info->addr.drive.unit);
    } else {
5252 5253
        virBufferAsprintf(&buf, ",bus=%s.0,channel=%d,scsi-id=%d,lun=%d",
                          contAlias,
5254 5255 5256 5257
                          dev->info->addr.drive.bus,
                          dev->info->addr.drive.target,
                          dev->info->addr.drive.unit);
    }
5258

J
John Ferlan 已提交
5259 5260 5261 5262
    if (!(driveAlias = qemuAliasFromHostdev(dev)))
        goto error;
    virBufferAsprintf(&buf, ",drive=%s,id=%s", driveAlias, dev->info->alias);
    VIR_FREE(driveAlias);
5263

5264
    if (dev->info->bootIndex)
5265
        virBufferAsprintf(&buf, ",bootindex=%u", dev->info->bootIndex);
5266

5267
    if (virBufferCheckError(&buf) < 0)
5268 5269 5270
        goto error;

    return virBufferContentAndReset(&buf);
5271
 error:
5272 5273 5274
    virBufferFreeAndReset(&buf);
    return NULL;
}
5275

5276 5277 5278
static int
qemuBuildChrChardevFileStr(virLogManagerPtr logManager,
                           virCommandPtr cmd,
5279
                           const virDomainDef *def,
5280 5281 5282 5283 5284 5285 5286 5287 5288
                           virBufferPtr buf,
                           const char *filearg, const char *fileval,
                           const char *appendarg, int appendval)
{
    if (logManager) {
        char *fdset, *fdpath;
        int flags = 0;
        int logfd;

5289 5290
        if (appendval == VIR_TRISTATE_SWITCH_ABSENT ||
            appendval == VIR_TRISTATE_SWITCH_OFF)
5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315
            flags |= VIR_LOG_MANAGER_PROTOCOL_DOMAIN_OPEN_LOG_FILE_TRUNCATE;

        if ((logfd = virLogManagerDomainOpenLogFile(logManager,
                                                    "qemu",
                                                    def->uuid,
                                                    def->name,
                                                    fileval,
                                                    flags,
                                                    NULL, NULL)) < 0)
            return -1;

        virCommandPassFD(cmd, logfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
        if (!(fdset = qemuVirCommandGetFDSet(cmd, logfd)))
            return -1;

        virCommandAddArg(cmd, "-add-fd");
        virCommandAddArg(cmd, fdset);
        VIR_FREE(fdset);

        if (!(fdpath = qemuVirCommandGetDevSet(cmd, logfd)))
            return -1;

        virBufferAsprintf(buf, ",%s=%s,%s=on", filearg, fdpath, appendarg);
        VIR_FREE(fdpath);
    } else {
5316 5317
        virBufferAsprintf(buf, ",%s=", filearg);
        virQEMUBuildBufferEscapeComma(buf, fileval);
5318 5319 5320 5321 5322 5323 5324 5325 5326
        if (appendval != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(buf, ",%s=%s", appendarg,
                              virTristateSwitchTypeToString(appendval));
        }
    }

    return 0;
}

5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339

static void
qemuBuildChrChardevReconnectStr(virBufferPtr buf,
                                const virDomainChrSourceReconnectDef *def)
{
    if (def->enabled == VIR_TRISTATE_BOOL_YES) {
        virBufferAsprintf(buf, ",reconnect=%u", def->timeout);
    } else if (def->enabled == VIR_TRISTATE_BOOL_NO) {
        virBufferAddLit(buf, ",reconnect=0");
    }
}


5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354
int
qemuOpenChrChardevUNIXSocket(const virDomainChrSourceDef *dev)
{
    struct sockaddr_un addr;
    socklen_t addrlen = sizeof(addr);
    int fd;

    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to create UNIX socket"));
        goto error;
    }

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
5355
    if (virStrcpyStatic(addr.sun_path, dev->data.nix.path) < 0) {
5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("UNIX socket path '%s' too long"),
                       dev->data.nix.path);
        goto error;
    }

    if (unlink(dev->data.nix.path) < 0 && errno != ENOENT) {
        virReportSystemError(errno,
                             _("Unable to unlink %s"),
                             dev->data.nix.path);
        goto error;
    }

    if (bind(fd, (struct sockaddr *)&addr, addrlen) < 0) {
        virReportSystemError(errno,
                             _("Unable to bind to UNIX socket path '%s'"),
                             dev->data.nix.path);
        goto error;
    }

    if (listen(fd, 1) < 0) {
        virReportSystemError(errno,
                             _("Unable to listen to UNIX socket path '%s'"),
                             dev->data.nix.path);
        goto error;
    }

5383 5384 5385 5386 5387 5388
    /* We run QEMU with umask 0002. Compensate for the umask
     * libvirtd might be running under to get the same permission
     * QEMU would have. */
    if (virFileUpdatePerm(dev->data.nix.path, 0002, 0664) < 0)
        goto error;

5389 5390 5391 5392 5393 5394 5395
    return fd;

 error:
    VIR_FORCE_CLOSE(fd);
    return -1;
}

5396 5397 5398 5399

enum {
    QEMU_BUILD_CHARDEV_TCP_NOWAIT = (1 << 0),
    QEMU_BUILD_CHARDEV_FILE_LOGD  = (1 << 1),
5400
    QEMU_BUILD_CHARDEV_UNIX_FD_PASS = (1 << 2),
5401 5402
};

5403 5404
/* This function outputs a -chardev command line option which describes only the
 * host side of the character device */
5405
static char *
5406
qemuBuildChrChardevStr(virLogManagerPtr logManager,
5407
                       virSecurityManagerPtr secManager,
5408
                       virCommandPtr cmd,
5409
                       virQEMUDriverConfigPtr cfg,
5410
                       const virDomainDef *def,
5411
                       const virDomainChrSourceDef *dev,
5412
                       const char *alias,
5413
                       virQEMUCapsPtr qemuCaps,
5414
                       unsigned int flags)
5415
{
5416
    qemuDomainChrSourcePrivatePtr chrSourcePriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev);
5417 5418
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    bool telnet;
5419
    char *charAlias = NULL;
5420
    char *ret = NULL;
5421 5422

    if (!(charAlias = qemuAliasChardevFromDevAlias(alias)))
5423
        goto cleanup;
5424

5425
    switch (dev->type) {
5426
    case VIR_DOMAIN_CHR_TYPE_NULL:
5427
        virBufferAsprintf(&buf, "null,id=%s", charAlias);
5428 5429 5430
        break;

    case VIR_DOMAIN_CHR_TYPE_VC:
5431
        virBufferAsprintf(&buf, "vc,id=%s", charAlias);
5432 5433 5434
        break;

    case VIR_DOMAIN_CHR_TYPE_PTY:
5435
        virBufferAsprintf(&buf, "pty,id=%s", charAlias);
5436 5437 5438
        break;

    case VIR_DOMAIN_CHR_TYPE_DEV:
5439
        virBufferAsprintf(&buf, "%s,id=%s,path=",
5440
                          STRPREFIX(alias, "parallel") ? "parport" : "tty",
5441 5442
                          charAlias);
        virQEMUBuildBufferEscapeComma(&buf, dev->data.file.path);
5443 5444 5445
        break;

    case VIR_DOMAIN_CHR_TYPE_FILE:
5446
        virBufferAsprintf(&buf, "file,id=%s", charAlias);
5447

5448 5449 5450 5451
        if (dev->data.file.append != VIR_TRISTATE_SWITCH_ABSENT &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FILE_APPEND)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("append not supported in this QEMU binary"));
5452
            goto cleanup;
5453
        }
5454 5455
        if (qemuBuildChrChardevFileStr(flags & QEMU_BUILD_CHARDEV_FILE_LOGD ?
                                       logManager : NULL,
5456
                                       cmd, def, &buf,
5457 5458
                                       "path", dev->data.file.path,
                                       "append", dev->data.file.append) < 0)
5459
            goto cleanup;
5460 5461 5462
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
5463 5464
        virBufferAsprintf(&buf, "pipe,id=%s,path=", charAlias);
        virQEMUBuildBufferEscapeComma(&buf, dev->data.file.path);
5465 5466 5467
        break;

    case VIR_DOMAIN_CHR_TYPE_STDIO:
5468
        virBufferAsprintf(&buf, "stdio,id=%s", charAlias);
5469 5470
        break;

5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482
    case VIR_DOMAIN_CHR_TYPE_UDP: {
        const char *connectHost = dev->data.udp.connectHost;
        const char *bindHost = dev->data.udp.bindHost;
        const char *bindService = dev->data.udp.bindService;

        if (connectHost == NULL)
            connectHost = "";
        if (bindHost == NULL)
            bindHost = "";
        if (bindService == NULL)
            bindService = "0";

5483
        virBufferAsprintf(&buf,
5484
                          "udp,id=%s,host=%s,port=%s,localaddr=%s,"
5485
                          "localport=%s",
5486
                          charAlias,
5487
                          connectHost,
5488
                          dev->data.udp.connectService,
5489
                          bindHost, bindService);
5490
        break;
5491
    }
5492 5493
    case VIR_DOMAIN_CHR_TYPE_TCP:
        telnet = dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
5494
        virBufferAsprintf(&buf,
5495 5496
                          "socket,id=%s,host=%s,port=%s%s",
                          charAlias,
5497 5498
                          dev->data.tcp.host,
                          dev->data.tcp.service,
5499 5500
                          telnet ? ",telnet" : "");

5501 5502 5503 5504 5505
        if (dev->data.tcp.listen) {
            virBufferAddLit(&buf, ",server");
            if (flags & QEMU_BUILD_CHARDEV_TCP_NOWAIT)
                virBufferAddLit(&buf, ",nowait");
        }
5506

5507 5508
        qemuBuildChrChardevReconnectStr(&buf, &dev->data.tcp.reconnect);

5509
        if (dev->data.tcp.haveTLS == VIR_TRISTATE_BOOL_YES) {
J
John Ferlan 已提交
5510
            char *objalias = NULL;
5511
            const char *tlsCertEncSecAlias = NULL;
5512

5513 5514 5515 5516
            /* Add the secret object first if necessary. The
             * secinfo is added only to a TCP serial device during
             * qemuDomainSecretChardevPrepare. Subsequently called
             * functions can just check the config fields */
5517 5518 5519 5520 5521 5522 5523
            if (chrSourcePriv && chrSourcePriv->secinfo) {
                if (qemuBuildObjectSecretCommandLine(cmd,
                                                     chrSourcePriv->secinfo) < 0)
                    goto cleanup;

                tlsCertEncSecAlias = chrSourcePriv->secinfo->s.aes.alias;
            }
5524

5525 5526 5527
            if (!(objalias = qemuAliasTLSObjFromSrcAlias(charAlias)))
                goto cleanup;

J
John Ferlan 已提交
5528 5529 5530
            if (qemuBuildTLSx509CommandLine(cmd, cfg->chardevTLSx509certdir,
                                            dev->data.tcp.listen,
                                            cfg->chardevTLSx509verify,
5531
                                            tlsCertEncSecAlias,
5532 5533
                                            objalias, qemuCaps) < 0) {
                VIR_FREE(objalias);
5534
                goto cleanup;
5535
            }
5536

J
John Ferlan 已提交
5537 5538 5539
            virBufferAsprintf(&buf, ",tls-creds=%s", objalias);
            VIR_FREE(objalias);
        }
5540 5541 5542
        break;

    case VIR_DOMAIN_CHR_TYPE_UNIX:
5543
        virBufferAsprintf(&buf, "socket,id=%s", charAlias);
5544 5545
        if (dev->data.nix.listen &&
            (flags & QEMU_BUILD_CHARDEV_UNIX_FD_PASS) &&
5546
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS)) {
5547 5548
            if (qemuSecuritySetSocketLabel(secManager, (virDomainDefPtr)def) < 0)
                goto cleanup;
5549
            int fd = qemuOpenChrChardevUNIXSocket(dev);
5550 5551 5552 5553
            if (qemuSecurityClearSocketLabel(secManager, (virDomainDefPtr)def) < 0) {
                VIR_FORCE_CLOSE(fd);
                goto cleanup;
            }
5554 5555 5556
            if (fd < 0)
                goto cleanup;

5557
            virBufferAsprintf(&buf, ",fd=%d", fd);
5558 5559 5560

            virCommandPassFD(cmd, fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
        } else {
5561
            virBufferAddLit(&buf, ",path=");
5562 5563
            virQEMUBuildBufferEscapeComma(&buf, dev->data.nix.path);
        }
5564 5565 5566 5567 5568
        if (dev->data.nix.listen) {
            virBufferAddLit(&buf, ",server");
            if (flags & QEMU_BUILD_CHARDEV_TCP_NOWAIT)
                virBufferAddLit(&buf, ",nowait");
        }
5569 5570

        qemuBuildChrChardevReconnectStr(&buf, &dev->data.nix.reconnect);
5571
        break;
5572 5573

    case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
5574
        virBufferAsprintf(&buf, "spicevmc,id=%s,name=%s", charAlias,
E
Eric Blake 已提交
5575
                          virDomainChrSpicevmcTypeToString(dev->data.spicevmc));
5576 5577
        break;

5578
    case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
5579
        virBufferAsprintf(&buf, "spiceport,id=%s,name=%s", charAlias,
5580 5581 5582
                          dev->data.spiceport.channel);
        break;

5583
    default:
5584 5585 5586
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unsupported chardev '%s'"),
                       virDomainChrTypeToString(dev->type));
5587
        goto cleanup;
5588 5589
    }

5590 5591 5592 5593
    if (dev->logfile) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_LOGFILE)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("logfile not supported in this QEMU binary"));
5594
            goto cleanup;
5595
        }
5596 5597 5598
        if (qemuBuildChrChardevFileStr(logManager, cmd, def, &buf,
                                       "logfile", dev->logfile,
                                       "logappend", dev->logappend) < 0)
5599
            goto cleanup;
5600 5601
    }

5602
    if (virBufferCheckError(&buf) < 0)
5603
        goto cleanup;
5604

5605 5606
    ret = virBufferContentAndReset(&buf);
 cleanup:
5607
    VIR_FREE(charAlias);
5608
    virBufferFreeAndReset(&buf);
5609
    return ret;
5610 5611
}

5612 5613 5614 5615 5616 5617 5618 5619
char *
qemuBuildHostdevMediatedDevStr(const virDomainDef *def,
                               virDomainHostdevDefPtr dev,
                               virQEMUCapsPtr qemuCaps)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virDomainHostdevSubsysMediatedDevPtr mdevsrc = &dev->source.subsys.u.mdev;
    char *ret = NULL;
5620
    char *mdevPath = NULL;
5621
    const char *dev_str = NULL;
5622 5623 5624

    if (!(mdevPath = virMediatedDeviceGetSysfsPath(mdevsrc->uuidstr)))
        goto cleanup;
5625

5626 5627 5628 5629 5630 5631
    dev_str = virMediatedDeviceModelTypeToString(mdevsrc->model);

    if (!dev_str)
        goto cleanup;

    virBufferAdd(&buf, dev_str, -1);
5632
    virBufferAsprintf(&buf, ",id=%s,sysfsdev=%s", dev->info->alias, mdevPath);
5633

5634 5635 5636 5637
    if (mdevsrc->display != VIR_TRISTATE_SWITCH_ABSENT)
        virBufferAsprintf(&buf, ",display=%s",
                          virTristateSwitchTypeToString(mdevsrc->display));

5638 5639 5640 5641 5642 5643 5644 5645 5646
    if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
        goto cleanup;

    if (virBufferCheckError(&buf) < 0)
        goto cleanup;

    ret = virBufferContentAndReset(&buf);

 cleanup:
5647
    VIR_FREE(mdevPath);
5648 5649 5650
    virBufferFreeAndReset(&buf);
    return ret;
}
5651

5652 5653 5654 5655
static int
qemuBuildHostdevCommandLine(virCommandPtr cmd,
                            const virDomainDef *def,
                            virQEMUCapsPtr qemuCaps,
5656
                            unsigned int *bootHostdevNet)
5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680
{
    size_t i;

    for (i = 0; i < def->nhostdevs; i++) {
        virDomainHostdevDefPtr hostdev = def->hostdevs[i];
        virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
        char *devstr;

        if (hostdev->info->bootIndex) {
            if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
                (subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
                 subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
                 subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("booting from assigned devices is only "
                                 "supported for PCI, USB and SCSI devices"));
                return -1;
            }
        }

        /* USB */
        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            subsys->type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {

5681 5682 5683 5684 5685 5686
            virCommandAddArg(cmd, "-device");
            if (!(devstr =
                  qemuBuildUSBHostdevDevStr(def, hostdev, qemuCaps)))
                return -1;
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702
        }

        /* PCI */
        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            subsys->type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
            int backend = subsys->u.pci.backend;

            if (backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
                if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                   _("VFIO PCI device assignment is not "
                                     "supported by this version of qemu"));
                    return -1;
                }
            }

5703 5704
            char *configfd_name = NULL;
            unsigned int bootIndex = hostdev->info->bootIndex;
5705

5706 5707 5708 5709 5710 5711 5712 5713
            /* bootNet will be non-0 if boot order was set and no other
             * net devices were encountered
             */
            if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
                bootIndex == 0) {
                bootIndex = *bootHostdevNet;
                *bootHostdevNet = 0;
            }
5714
            if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
5715
                int configfd = qemuOpenPCIConfig(hostdev);
5716

5717 5718 5719 5720
                if (configfd >= 0) {
                    if (virAsprintf(&configfd_name, "%d", configfd) < 0) {
                        VIR_FORCE_CLOSE(configfd);
                        return -1;
5721
                    }
5722 5723 5724

                    virCommandPassFD(cmd, configfd,
                                     VIR_COMMAND_PASS_FD_CLOSE_PARENT);
5725 5726
                }
            }
5727 5728 5729 5730

            if (qemuCommandAddExtDevice(cmd, hostdev->info) < 0)
                return -1;

5731 5732 5733 5734 5735 5736 5737 5738
            virCommandAddArg(cmd, "-device");
            devstr = qemuBuildPCIHostdevDevStr(def, hostdev, bootIndex,
                                               configfd_name, qemuCaps);
            VIR_FREE(configfd_name);
            if (!devstr)
                return -1;
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
5739 5740 5741
        }

        /* SCSI */
5742
        if (virHostdevIsSCSIDevice(hostdev)) {
5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755
            virDomainHostdevSubsysSCSIPtr scsisrc =
                &hostdev->source.subsys.u.scsi;
            char *drvstr;

            if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
                virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc =
                    &scsisrc->u.iscsi;
                qemuDomainStorageSourcePrivatePtr srcPriv =
                    QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(iscsisrc->src);

                if (qemuBuildDiskSecinfoCommandLine(cmd, srcPriv ?
                                                    srcPriv->secinfo :
                                                    NULL) < 0)
5756
                    return -1;
5757
            }
5758

5759 5760
            virCommandAddArg(cmd, "-drive");
            if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, qemuCaps)))
5761
                return -1;
5762 5763 5764 5765 5766 5767 5768 5769
            virCommandAddArg(cmd, drvstr);
            VIR_FREE(drvstr);

            virCommandAddArg(cmd, "-device");
            if (!(devstr = qemuBuildSCSIHostdevDevStr(def, hostdev)))
                return -1;
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
5770
        }
5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805

        /* SCSI_host */
        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            subsys->type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
            if (hostdev->source.subsys.u.scsi_host.protocol ==
                VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST) {
                char *vhostfdName = NULL;
                int vhostfd = -1;

                if (virSCSIVHostOpenVhostSCSI(&vhostfd) < 0)
                    return -1;

                if (virAsprintf(&vhostfdName, "%d", vhostfd) < 0) {
                    VIR_FORCE_CLOSE(vhostfd);
                    return -1;
                }

                virCommandPassFD(cmd, vhostfd,
                                 VIR_COMMAND_PASS_FD_CLOSE_PARENT);

                virCommandAddArg(cmd, "-device");
                if (!(devstr = qemuBuildSCSIVHostHostdevDevStr(def,
                                                               hostdev,
                                                               qemuCaps,
                                                               vhostfdName))) {
                    VIR_FREE(vhostfdName);
                    VIR_FORCE_CLOSE(vhostfd);
                    return -1;
                }
                virCommandAddArg(cmd, devstr);

                VIR_FREE(vhostfdName);
                VIR_FREE(devstr);
            }
        }
5806 5807

        /* MDEV */
5808
        if (virHostdevIsMdevDevice(hostdev)) {
5809 5810 5811
            virDomainHostdevSubsysMediatedDevPtr mdevsrc = &subsys->u.mdev;

            switch ((virMediatedDeviceModelType) mdevsrc->model) {
5812 5813 5814 5815 5816 5817 5818
            case VIR_MDEV_MODEL_TYPE_VFIO_PCI:
                if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                   _("VFIO PCI device assignment is not "
                                     "supported by this version of QEMU"));
                    return -1;
                }
5819

5820 5821 5822 5823 5824 5825 5826 5827 5828
                break;
            case VIR_MDEV_MODEL_TYPE_VFIO_CCW:
                if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW)) {
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                   _("VFIO CCW device assignment is not "
                                     "supported by this version of QEMU"));
                    return -1;
                }
                break;
B
Boris Fiuczynski 已提交
5829 5830 5831 5832 5833 5834 5835 5836
            case VIR_MDEV_MODEL_TYPE_VFIO_AP:
                if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_AP)) {
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                   _("VFIO AP device assignment is not "
                                     "supported by this version of QEMU"));
                    return -1;
                }
                break;
5837
            case VIR_MDEV_MODEL_TYPE_LAST:
5838 5839 5840
            default:
                virReportEnumRangeError(virMediatedDeviceModelType,
                                        subsys->u.mdev.model);
5841 5842 5843 5844 5845 5846 5847 5848 5849 5850
                return -1;
            }

            virCommandAddArg(cmd, "-device");
            if (!(devstr =
                  qemuBuildHostdevMediatedDevStr(def, hostdev, qemuCaps)))
                return -1;
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
        }
5851 5852 5853 5854 5855
    }

    return 0;
}

5856

5857
static int
5858
qemuBuildMonitorCommandLine(virLogManagerPtr logManager,
5859
                            virSecurityManagerPtr secManager,
5860
                            virCommandPtr cmd,
5861
                            virQEMUDriverConfigPtr cfg,
5862
                            virDomainDefPtr def,
5863
                            qemuDomainObjPrivatePtr priv)
5864 5865
{
    char *chrdev;
5866 5867
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
5868 5869
    if (priv->chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
5870

5871
    if (!priv->monConfig)
5872 5873
        return 0;

5874 5875
    if (!(chrdev = qemuBuildChrChardevStr(logManager, secManager,
                                          cmd, cfg, def,
5876
                                          priv->monConfig, "monitor",
5877
                                          priv->qemuCaps, cdevflags)))
5878 5879 5880 5881 5882 5883 5884 5885
        return -1;
    virCommandAddArg(cmd, "-chardev");
    virCommandAddArg(cmd, chrdev);
    VIR_FREE(chrdev);

    virCommandAddArg(cmd, "-mon");
    virCommandAddArgFormat(cmd,
                           "chardev=charmonitor,id=monitor,mode=%s",
5886
                           priv->monJSON ? "control" : "readline");
5887 5888 5889 5890 5891

    return 0;
}


5892
static char *
5893
qemuBuildVirtioSerialPortDevStr(const virDomainDef *def,
5894
                                virDomainChrDefPtr dev)
5895 5896
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
5897 5898
    const char *contAlias;

5899 5900
    switch (dev->deviceType) {
    case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
5901
        virBufferAddLit(&buf, "virtconsole");
5902 5903
        break;
    case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
5904
        virBufferAddLit(&buf, "virtserialport");
5905 5906
        break;
    default:
5907 5908
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Cannot use virtio serial for parallel/serial devices"));
5909 5910
        return NULL;
    }
5911

5912
    if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
5913
        dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
5914
        dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) {
5915
        /* Check it's a virtio-serial address */
5916
        if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL) {
5917 5918
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("virtio serial device has invalid address type"));
5919 5920 5921
            goto error;
        }

5922 5923 5924 5925 5926 5927 5928
        contAlias = virDomainControllerAliasFind(def, VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL,
                                                 dev->info.addr.vioserial.controller);
        if (!contAlias)
            goto error;

        virBufferAsprintf(&buf, ",bus=%s.%d,nr=%d", contAlias,
                          dev->info.addr.vioserial.bus,
5929 5930 5931
                          dev->info.addr.vioserial.port);
    }

5932
    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
5933
        dev->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC &&
5934 5935
        dev->target.name &&
        STRNEQ(dev->target.name, "com.redhat.spice.0")) {
5936 5937 5938
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Unsupported spicevmc target name '%s'"),
                       dev->target.name);
5939 5940
        goto error;
    }
5941

5942 5943 5944 5945 5946 5947 5948
    virBufferAsprintf(&buf, ",chardev=char%s,id=%s",
                      dev->info.alias, dev->info.alias);
    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
        (dev->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC ||
         dev->target.name)) {
        virBufferAsprintf(&buf, ",name=%s", dev->target.name
                          ? dev->target.name : "com.redhat.spice.0");
5949
    }
5950
    if (virBufferCheckError(&buf) < 0)
5951 5952 5953 5954
        goto error;

    return virBufferContentAndReset(&buf);

5955
 error:
5956 5957 5958 5959
    virBufferFreeAndReset(&buf);
    return NULL;
}

5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979
static char *
qemuBuildSclpDevStr(virDomainChrDefPtr dev)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE) {
        switch (dev->targetType) {
        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLP:
            virBufferAddLit(&buf, "sclpconsole");
            break;
        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLPLM:
            virBufferAddLit(&buf, "sclplmconsole");
            break;
        }
    } else {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Cannot use slcp with devices other than console"));
        goto error;
    }
    virBufferAsprintf(&buf, ",chardev=char%s,id=%s",
                      dev->info.alias, dev->info.alias);
5980
    if (virBufferCheckError(&buf) < 0)
5981 5982 5983 5984
        goto error;

    return virBufferContentAndReset(&buf);

5985
 error:
5986 5987 5988 5989
    virBufferFreeAndReset(&buf);
    return NULL;
}

5990 5991

static int
5992
qemuBuildRNGBackendChrdevStr(virLogManagerPtr logManager,
5993
                             virSecurityManagerPtr secManager,
5994
                             virCommandPtr cmd,
5995
                             virQEMUDriverConfigPtr cfg,
5996
                             const virDomainDef *def,
5997
                             virDomainRNGDefPtr rng,
5998
                             virQEMUCapsPtr qemuCaps,
5999 6000
                             char **chr,
                             bool chardevStdioLogd)
6001
{
6002 6003
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
6004 6005 6006

    *chr = NULL;

6007 6008
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
6009 6010 6011 6012 6013 6014 6015 6016

    switch ((virDomainRNGBackend) rng->backend) {
    case VIR_DOMAIN_RNG_BACKEND_RANDOM:
    case VIR_DOMAIN_RNG_BACKEND_LAST:
        /* no chardev backend is needed */
        return 0;

    case VIR_DOMAIN_RNG_BACKEND_EGD:
6017 6018
        if (!(*chr = qemuBuildChrChardevStr(logManager, secManager,
                                            cmd, cfg, def,
6019
                                            rng->source.chardev,
6020 6021
                                            rng->info.alias, qemuCaps,
                                            cdevflags)))
6022 6023 6024 6025 6026 6027 6028
            return -1;
    }

    return 0;
}


6029
int
6030 6031 6032 6033
qemuBuildRNGBackendProps(virDomainRNGDefPtr rng,
                         virQEMUCapsPtr qemuCaps,
                         virJSONValuePtr *props)
{
6034
    char *objAlias = NULL;
6035
    char *charBackendAlias = NULL;
6036 6037
    int ret = -1;

6038 6039 6040
    if (virAsprintf(&objAlias, "obj%s", rng->info.alias) < 0)
        goto cleanup;

6041
    switch ((virDomainRNGBackend) rng->backend) {
6042 6043 6044 6045
    case VIR_DOMAIN_RNG_BACKEND_RANDOM:
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_RNG_RANDOM)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this qemu doesn't support the rng-random "
6046
                             "backend"));
6047 6048 6049
            goto cleanup;
        }

6050 6051 6052
        if (qemuMonitorCreateObjectProps(props, "rng-random", objAlias,
                                         "s:filename", rng->source.file,
                                         NULL) < 0)
6053
            goto cleanup;
6054

6055 6056 6057
        break;

    case VIR_DOMAIN_RNG_BACKEND_EGD:
6058 6059 6060 6061 6062 6063 6064
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_RNG_EGD)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this qemu doesn't support the rng-egd "
                             "backend"));
            goto cleanup;
        }

6065
        if (!(charBackendAlias = qemuAliasChardevFromDevAlias(rng->info.alias)))
6066 6067
            goto cleanup;

6068 6069 6070
        if (qemuMonitorCreateObjectProps(props, "rng-egd", objAlias,
                                         "s:chardev", charBackendAlias,
                                         NULL) < 0)
6071
            goto cleanup;
6072

6073 6074 6075
        break;

    case VIR_DOMAIN_RNG_BACKEND_LAST:
6076 6077 6078
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("unknown rng-random backend"));
        goto cleanup;
6079 6080 6081 6082
    }

    ret = 0;

6083
 cleanup:
6084
    VIR_FREE(objAlias);
6085 6086 6087 6088 6089
    VIR_FREE(charBackendAlias);
    return ret;
}


6090
char *
6091
qemuBuildRNGDevStr(const virDomainDef *def,
6092 6093
                   virDomainRNGDefPtr dev,
                   virQEMUCapsPtr qemuCaps)
6094 6095 6096
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

6097
    if (!qemuDomainCheckCCWS390AddressSupport(def, &dev->info, qemuCaps,
6098
                                              dev->source.file))
6099 6100
        goto error;

6101
    if (qemuBuildVirtioDevStr(&buf, "virtio-rng", qemuCaps,
6102
                              VIR_DOMAIN_DEVICE_RNG, dev) < 0) {
6103
        goto error;
6104
    }
6105 6106 6107

    virBufferAsprintf(&buf, ",rng=obj%s,id=%s",
                      dev->info.alias, dev->info.alias);
6108

6109 6110 6111 6112 6113 6114 6115 6116
    if (dev->rate > 0) {
        virBufferAsprintf(&buf, ",max-bytes=%u", dev->rate);
        if (dev->period)
            virBufferAsprintf(&buf, ",period=%u", dev->period);
        else
            virBufferAddLit(&buf, ",period=1000");
    }

6117 6118 6119
    if (qemuBuildVirtioOptionsStr(&buf, dev->virtio, qemuCaps) < 0)
        goto error;

6120
    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
6121 6122 6123
        goto error;
    if (virBufferCheckError(&buf) < 0)
        goto error;
6124

6125
    return virBufferContentAndReset(&buf);
6126

6127
 error:
6128
    virBufferFreeAndReset(&buf);
6129
    return NULL;
6130 6131 6132
}


6133 6134
static int
qemuBuildRNGCommandLine(virLogManagerPtr logManager,
6135
                        virSecurityManagerPtr secManager,
6136
                        virCommandPtr cmd,
6137
                        virQEMUDriverConfigPtr cfg,
6138
                        const virDomainDef *def,
6139 6140
                        virQEMUCapsPtr qemuCaps,
                        bool chardevStdioLogd)
6141 6142 6143 6144
{
    size_t i;

    for (i = 0; i < def->nrngs; i++) {
6145 6146
        virJSONValuePtr props;
        virBuffer buf = VIR_BUFFER_INITIALIZER;
6147 6148
        virDomainRNGDefPtr rng = def->rngs[i];
        char *tmp;
6149
        int rc;
6150 6151 6152 6153 6154 6155 6156 6157

        if (!rng->info.alias) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("RNG device is missing alias"));
            return -1;
        }

        /* possibly add character device for backend */
6158
        if (qemuBuildRNGBackendChrdevStr(logManager, secManager, cmd, cfg, def,
6159 6160
                                         rng, qemuCaps, &tmp,
                                         chardevStdioLogd) < 0)
6161 6162 6163 6164 6165 6166 6167
            return -1;

        if (tmp) {
            virCommandAddArgList(cmd, "-chardev", tmp, NULL);
            VIR_FREE(tmp);
        }

6168
        if (qemuBuildRNGBackendProps(rng, qemuCaps, &props) < 0)
6169 6170
            return -1;

6171 6172 6173 6174 6175 6176 6177 6178
        rc = virQEMUBuildObjectCommandlineFromJSON(&buf, props);
        virJSONValueFree(props);

        if (rc < 0)
            return -1;

        virCommandAddArg(cmd, "-object");
        virCommandAddArgBuffer(cmd, &buf);
6179 6180

        /* add the device */
6181 6182 6183
        if (qemuCommandAddExtDevice(cmd, &rng->info) < 0)
            return -1;

6184 6185 6186 6187 6188 6189 6190 6191 6192 6193
        if (!(tmp = qemuBuildRNGDevStr(def, rng, qemuCaps)))
            return -1;
        virCommandAddArgList(cmd, "-device", tmp, NULL);
        VIR_FREE(tmp);
    }

    return 0;
}


6194 6195
static char *
qemuBuildSmbiosBiosStr(virSysinfoBIOSDefPtr def)
6196 6197 6198
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

6199
    if (!def)
6200
        return NULL;
6201 6202 6203 6204

    virBufferAddLit(&buf, "type=0");

    /* 0:Vendor */
6205 6206 6207 6208
    if (def->vendor) {
        virBufferAddLit(&buf, ",vendor=");
        virQEMUBuildBufferEscapeComma(&buf, def->vendor);
    }
6209
    /* 0:BIOS Version */
6210 6211 6212 6213
    if (def->version) {
        virBufferAddLit(&buf, ",version=");
        virQEMUBuildBufferEscapeComma(&buf, def->version);
    }
6214
    /* 0:BIOS Release Date */
6215 6216 6217 6218
    if (def->date) {
        virBufferAddLit(&buf, ",date=");
        virQEMUBuildBufferEscapeComma(&buf, def->date);
    }
6219
    /* 0:System BIOS Major Release and 0:System BIOS Minor Release */
6220 6221 6222 6223
    if (def->release) {
        virBufferAddLit(&buf, ",release=");
        virQEMUBuildBufferEscapeComma(&buf, def->release);
    }
6224 6225 6226 6227

    return virBufferContentAndReset(&buf);
}

6228 6229 6230 6231

static char *
qemuBuildSmbiosSystemStr(virSysinfoSystemDefPtr def,
                         bool skip_uuid)
6232 6233 6234
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

6235 6236 6237 6238
    if (!def ||
        (!def->manufacturer && !def->product && !def->version &&
         !def->serial && (!def->uuid || skip_uuid) &&
         def->sku && !def->family))
6239 6240 6241 6242 6243
        return NULL;

    virBufferAddLit(&buf, "type=1");

    /* 1:Manufacturer */
6244 6245 6246 6247
    if (def->manufacturer) {
        virBufferAddLit(&buf, ",manufacturer=");
        virQEMUBuildBufferEscapeComma(&buf, def->manufacturer);
    }
6248
     /* 1:Product Name */
6249 6250 6251 6252
    if (def->product) {
        virBufferAddLit(&buf, ",product=");
        virQEMUBuildBufferEscapeComma(&buf, def->product);
    }
6253
    /* 1:Version */
6254 6255 6256 6257
    if (def->version) {
        virBufferAddLit(&buf, ",version=");
        virQEMUBuildBufferEscapeComma(&buf, def->version);
    }
6258
    /* 1:Serial Number */
6259 6260 6261 6262
    if (def->serial) {
        virBufferAddLit(&buf, ",serial=");
        virQEMUBuildBufferEscapeComma(&buf, def->serial);
    }
6263
    /* 1:UUID */
6264 6265 6266 6267
    if (def->uuid && !skip_uuid) {
        virBufferAddLit(&buf, ",uuid=");
        virQEMUBuildBufferEscapeComma(&buf, def->uuid);
    }
6268
    /* 1:SKU Number */
6269 6270 6271 6272
    if (def->sku) {
        virBufferAddLit(&buf, ",sku=");
        virQEMUBuildBufferEscapeComma(&buf, def->sku);
    }
6273
    /* 1:Family */
6274 6275 6276 6277
    if (def->family) {
        virBufferAddLit(&buf, ",family=");
        virQEMUBuildBufferEscapeComma(&buf, def->family);
    }
6278 6279 6280 6281

    return virBufferContentAndReset(&buf);
}

6282 6283 6284

static char *
qemuBuildSmbiosBaseBoardStr(virSysinfoBaseBoardDefPtr def)
6285 6286 6287 6288 6289 6290 6291 6292 6293
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (!def)
        return NULL;

    virBufferAddLit(&buf, "type=2");

    /* 2:Manufacturer */
6294 6295
    virBufferAddLit(&buf, ",manufacturer=");
    virQEMUBuildBufferEscapeComma(&buf, def->manufacturer);
6296
    /* 2:Product Name */
6297 6298 6299 6300
    if (def->product) {
        virBufferAddLit(&buf, ",product=");
        virQEMUBuildBufferEscapeComma(&buf, def->product);
    }
6301
    /* 2:Version */
6302 6303 6304 6305
    if (def->version) {
        virBufferAddLit(&buf, ",version=");
        virQEMUBuildBufferEscapeComma(&buf, def->version);
    }
6306
    /* 2:Serial Number */
6307 6308 6309 6310
    if (def->serial) {
        virBufferAddLit(&buf, ",serial=");
        virQEMUBuildBufferEscapeComma(&buf, def->serial);
    }
6311
    /* 2:Asset Tag */
6312 6313 6314 6315
    if (def->asset) {
        virBufferAddLit(&buf, ",asset=");
        virQEMUBuildBufferEscapeComma(&buf, def->asset);
    }
6316
    /* 2:Location */
6317 6318 6319 6320
    if (def->location) {
        virBufferAddLit(&buf, ",location=");
        virQEMUBuildBufferEscapeComma(&buf, def->location);
    }
6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331

    if (virBufferCheckError(&buf) < 0)
        goto error;

    return virBufferContentAndReset(&buf);

 error:
    virBufferFreeAndReset(&buf);
    return NULL;
}

6332

6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352
static char *
qemuBuildSmbiosOEMStringsStr(virSysinfoOEMStringsDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    size_t i;

    if (!def)
        return NULL;

    virBufferAddLit(&buf, "type=11");

    for (i = 0; i < def->nvalues; i++) {
        virBufferAddLit(&buf, ",value=");
        virQEMUBuildBufferEscapeComma(&buf, def->values[i]);
    }

    return virBufferContentAndReset(&buf);
}


6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397
static char *
qemuBuildSmbiosChassisStr(virSysinfoChassisDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (!def)
        return NULL;

    virBufferAddLit(&buf, "type=3");

    /* 3:Manufacturer */
    virBufferAddLit(&buf, ",manufacturer=");
    virQEMUBuildBufferEscapeComma(&buf, def->manufacturer);
    /* 3:Version */
    if (def->version) {
        virBufferAddLit(&buf, ",version=");
        virQEMUBuildBufferEscapeComma(&buf, def->version);
    }
    /* 3:Serial Number */
    if (def->serial) {
        virBufferAddLit(&buf, ",serial=");
        virQEMUBuildBufferEscapeComma(&buf, def->serial);
    }
    /* 3:Asset Tag */
    if (def->asset) {
        virBufferAddLit(&buf, ",asset=");
        virQEMUBuildBufferEscapeComma(&buf, def->asset);
    }
    /* 3:Sku */
    if (def->sku) {
        virBufferAddLit(&buf, ",sku=");
        virQEMUBuildBufferEscapeComma(&buf, def->sku);
    }

    if (virBufferCheckError(&buf) < 0)
        goto error;

    return virBufferContentAndReset(&buf);

 error:
    virBufferFreeAndReset(&buf);
    return NULL;
}


6398 6399 6400
static int
qemuBuildSmbiosCommandLine(virCommandPtr cmd,
                           virQEMUDriverPtr driver,
6401
                           const virDomainDef *def)
6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459
{
    size_t i;
    virSysinfoDefPtr source = NULL;
    bool skip_uuid = false;

    if (def->os.smbios_mode == VIR_DOMAIN_SMBIOS_NONE ||
        def->os.smbios_mode == VIR_DOMAIN_SMBIOS_EMULATE)
        return 0;

    /* should we really error out or just warn in those cases ? */
    if (def->os.smbios_mode == VIR_DOMAIN_SMBIOS_HOST) {
        if (driver->hostsysinfo == NULL) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Host SMBIOS information is not available"));
            return -1;
        }
        source = driver->hostsysinfo;
        /* Host and guest uuid must differ, by definition of UUID. */
        skip_uuid = true;
    } else if (def->os.smbios_mode == VIR_DOMAIN_SMBIOS_SYSINFO) {
        if (def->sysinfo == NULL) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("Domain '%s' sysinfo are not available"),
                           def->name);
            return -1;
        }
        source = def->sysinfo;
        /* domain_conf guaranteed that system_uuid matches guest uuid. */
    }
    if (source != NULL) {
        char *smbioscmd;

        smbioscmd = qemuBuildSmbiosBiosStr(source->bios);
        if (smbioscmd != NULL) {
            virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
            VIR_FREE(smbioscmd);
        }
        smbioscmd = qemuBuildSmbiosSystemStr(source->system, skip_uuid);
        if (smbioscmd != NULL) {
            virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
            VIR_FREE(smbioscmd);
        }

        if (source->nbaseBoard > 1) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("qemu does not support more than "
                             "one entry to Type 2 in SMBIOS table"));
            return -1;
        }

        for (i = 0; i < source->nbaseBoard; i++) {
            if (!(smbioscmd =
                  qemuBuildSmbiosBaseBoardStr(source->baseBoard + i)))
                return -1;

            virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
            VIR_FREE(smbioscmd);
        }
6460

6461 6462 6463 6464 6465 6466
        smbioscmd = qemuBuildSmbiosChassisStr(source->chassis);
        if (smbioscmd != NULL) {
            virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
            VIR_FREE(smbioscmd);
        }

6467 6468 6469 6470 6471 6472 6473
        if (source->oemStrings) {
            if (!(smbioscmd = qemuBuildSmbiosOEMStringsStr(source->oemStrings)))
                return -1;

            virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
            VIR_FREE(smbioscmd);
        }
6474 6475 6476 6477 6478 6479
    }

    return 0;
}


6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507
static int
qemuBuildVMGenIDCommandLine(virCommandPtr cmd,
                            const virDomainDef *def,
                            virQEMUCapsPtr qemuCaps)
{
    virBuffer opts = VIR_BUFFER_INITIALIZER;
    char guid[VIR_UUID_STRING_BUFLEN];

    if (!def->genidRequested)
        return 0;

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VMGENID)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                      _("this QEMU does not support the 'genid' capability"));
        return -1;
    }

    virUUIDFormat(def->genid, guid);
    virBufferAsprintf(&opts, "vmgenid,guid=%s,id=vmgenid0", guid);

    virCommandAddArg(cmd, "-device");
    virCommandAddArgBuffer(cmd, &opts);

    virBufferFreeAndReset(&opts);
    return 0;
}


6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531
static int
qemuBuildSgaCommandLine(virCommandPtr cmd,
                        const virDomainDef *def,
                        virQEMUCapsPtr qemuCaps)
{
    /* Serial graphics adapter */
    if (def->os.bios.useserial == VIR_TRISTATE_BOOL_YES) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SGA)) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("qemu does not support SGA"));
            return -1;
        }
        if (!def->nserials) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("need at least one serial port to use SGA"));
            return -1;
        }
        virCommandAddArgList(cmd, "-device", "sga", NULL);
    }

    return 0;
}


6532 6533 6534
static char *
qemuBuildClockArgStr(virDomainClockDefPtr def)
{
6535
    size_t i;
6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    switch (def->offset) {
    case VIR_DOMAIN_CLOCK_OFFSET_UTC:
        virBufferAddLit(&buf, "base=utc");
        break;

    case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
    case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
        virBufferAddLit(&buf, "base=localtime");
        break;

    case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: {
        time_t now = time(NULL);
        struct tm nowbits;

6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570
        if (def->data.variable.basis == VIR_DOMAIN_CLOCK_BASIS_LOCALTIME) {
            long localOffset;

            /* in the case of basis='localtime', rather than trying to
             * keep that basis (and associated offset from UTC) in the
             * status and deal with adding in the difference each time
             * there is an RTC_CHANGE event, it is simpler and less
             * error prone to just convert the adjustment an offset
             * from UTC right now (and change the status to
             * "basis='utc' to reflect this). This eliminates
             * potential errors in both RTC_CHANGE events and in
             * migration (in the case that the status of DST, or the
             * timezone of the destination host, changed relative to
             * startup).
             */
            if (virTimeLocalOffsetFromUTC(&localOffset) < 0)
               goto error;
            def->data.variable.adjustment += localOffset;
            def->data.variable.basis = VIR_DOMAIN_CLOCK_BASIS_UTC;
6571
        }
6572

6573 6574 6575
        now += def->data.variable.adjustment;
        gmtime_r(&now, &nowbits);

6576 6577 6578 6579 6580 6581 6582 6583
        /* when an RTC_CHANGE event is received from qemu, we need to
         * have the adjustment used at domain start time available to
         * compute the new offset from UTC. As this new value is
         * itself stored in def->data.variable.adjustment, we need to
         * save a copy of it now.
        */
        def->data.variable.adjustment0 = def->data.variable.adjustment;

6584
        virBufferAsprintf(&buf, "base=%d-%02d-%02dT%02d:%02d:%02d",
6585 6586 6587 6588 6589 6590 6591 6592 6593
                          nowbits.tm_year + 1900,
                          nowbits.tm_mon + 1,
                          nowbits.tm_mday,
                          nowbits.tm_hour,
                          nowbits.tm_min,
                          nowbits.tm_sec);
    }   break;

    default:
6594 6595 6596
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unsupported clock offset '%s'"),
                       virDomainClockOffsetTypeToString(def->offset));
6597 6598 6599
        goto error;
    }

6600 6601
    /* Look for an 'rtc' timer element, and add in appropriate
     * clock= and driftfix= */
6602 6603 6604 6605 6606 6607
    for (i = 0; i < def->ntimers; i++) {
        if (def->timers[i]->name == VIR_DOMAIN_TIMER_NAME_RTC) {
            switch (def->timers[i]->track) {
            case -1: /* unspecified - use hypervisor default */
                break;
            case VIR_DOMAIN_TIMER_TRACK_BOOT:
6608 6609 6610
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unsupported rtc timer track '%s'"),
                               virDomainTimerTrackTypeToString(def->timers[i]->track));
6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631
                goto error;
            case VIR_DOMAIN_TIMER_TRACK_GUEST:
                virBufferAddLit(&buf, ",clock=vm");
                break;
            case VIR_DOMAIN_TIMER_TRACK_WALL:
                virBufferAddLit(&buf, ",clock=host");
                break;
            }

            switch (def->timers[i]->tickpolicy) {
            case -1:
            case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
                /* This is the default - missed ticks delivered when
                   next scheduled, at normal rate */
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
                /* deliver ticks at a faster rate until caught up */
                virBufferAddLit(&buf, ",driftfix=slew");
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
            case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
6632 6633 6634
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unsupported rtc timer tickpolicy '%s'"),
                               virDomainTimerTickpolicyTypeToString(def->timers[i]->tickpolicy));
6635 6636 6637 6638 6639 6640
                goto error;
            }
            break; /* no need to check other timers - there is only one rtc */
        }
    }

6641
    if (virBufferCheckError(&buf) < 0)
6642 6643 6644 6645
        goto error;

    return virBufferContentAndReset(&buf);

6646
 error:
6647 6648 6649 6650
    virBufferFreeAndReset(&buf);
    return NULL;
}

6651 6652 6653 6654 6655 6656 6657 6658 6659 6660

/* NOTE: Building of commands can change def->clock->data.* values, so
 *       virDomainDef is not const here.
 */
static int
qemuBuildClockCommandLine(virCommandPtr cmd,
                          virDomainDefPtr def,
                          virQEMUCapsPtr qemuCaps)
{
    size_t i;
J
Ján Tomko 已提交
6661
    char *rtcopt;
6662

J
Ján Tomko 已提交
6663 6664 6665 6666 6667
    virCommandAddArg(cmd, "-rtc");
    if (!(rtcopt = qemuBuildClockArgStr(&def->clock)))
        return -1;
    virCommandAddArg(cmd, rtcopt);
    VIR_FREE(rtcopt);
6668 6669 6670 6671 6672 6673 6674

    if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE &&
        def->clock.data.timezone) {
        virCommandAddEnvPair(cmd, "TZ", def->clock.data.timezone);
    }

    for (i = 0; i < def->clock.ntimers; i++) {
6675
        switch ((virDomainTimerNameType)def->clock.timers[i]->name) {
6676 6677 6678 6679 6680 6681
        case VIR_DOMAIN_TIMER_NAME_PLATFORM:
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("unsupported timer type (name) '%s'"),
                           virDomainTimerNameTypeToString(def->clock.timers[i]->name));
            return -1;

6682
        case VIR_DOMAIN_TIMER_NAME_TSC:
6683 6684 6685 6686 6687 6688 6689
        case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
        case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
            /* Timers above are handled when building -cpu.  */
        case VIR_DOMAIN_TIMER_NAME_LAST:
            break;

        case VIR_DOMAIN_TIMER_NAME_RTC:
6690
            /* Already handled in qemuBuildClockArgStr */
6691 6692 6693 6694 6695 6696 6697
            break;

        case VIR_DOMAIN_TIMER_NAME_PIT:
            switch (def->clock.timers[i]->tickpolicy) {
            case -1:
            case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
                /* delay is the default if we don't have kernel
J
Ján Tomko 已提交
6698
                   (kvm-pit), otherwise, the default is catchup. */
6699 6700
                if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY))
                    virCommandAddArgList(cmd, "-global",
6701
                                         "kvm-pit.lost_tick_policy=delay", NULL);
6702 6703
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
J
Ján Tomko 已提交
6704
                if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) {
6705 6706
                    /* do nothing - this is default for kvm-pit */
                } else {
J
Ján Tomko 已提交
6707
                    /* can't catchup if we don't have kvm-pit */
6708 6709 6710 6711 6712 6713 6714
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   _("unsupported pit tickpolicy '%s'"),
                                   virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
                    return -1;
                }
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
6715 6716 6717 6718 6719 6720
                if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY))
                    virCommandAddArgList(cmd, "-global",
                                         "kvm-pit.lost_tick_policy=discard", NULL);
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
                /* no way to support this mode for pit in qemu */
6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unsupported pit tickpolicy '%s'"),
                               virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
                return -1;
            }
            break;

        case VIR_DOMAIN_TIMER_NAME_HPET:
            /* the only meaningful attribute for hpet is "present". If
             * present is -1, that means it wasn't specified, and
             * should be left at the default for the
             * hypervisor. "default" when -no-hpet exists is "yes",
             * and when -no-hpet doesn't exist is "no". "confusing"?
             * "yes"! */

            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_HPET)) {
                if (def->clock.timers[i]->present == 0)
                    virCommandAddArg(cmd, "-no-hpet");
            } else {
                /* no hpet timer available. The only possible action
                   is to raise an error if present="yes" */
                if (def->clock.timers[i]->present == 1) {
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   "%s", _("hpet timer is not supported"));
                    return -1;
                }
            }
            break;
        }
    }

    return 0;
}


6756 6757 6758
static int
qemuBuildPMCommandLine(virCommandPtr cmd,
                       const virDomainDef *def,
6759
                       qemuDomainObjPrivatePtr priv)
6760
{
6761
    virQEMUCapsPtr qemuCaps = priv->qemuCaps;
6762 6763

    /* Only add -no-reboot option if each event destroys domain */
6764
    if (priv->allowReboot == VIR_TRISTATE_BOOL_NO)
6765 6766
        virCommandAddArg(cmd, "-no-reboot");

J
John Ferlan 已提交
6767
    if (qemuDomainIsUsingNoShutdown(priv))
6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781
        virCommandAddArg(cmd, "-no-shutdown");

    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_ACPI)) {
        if (def->features[VIR_DOMAIN_FEATURE_ACPI] != VIR_TRISTATE_SWITCH_ON)
            virCommandAddArg(cmd, "-no-acpi");
    }

    /* We fall back to PIIX4_PM even for q35, since it's what we did
       pre-q35-pm support. QEMU starts up fine (with a warning) if
       mixing PIIX PM and -M q35. Starting to reject things here
       could mean we refuse to start existing configs in the wild.*/
    if (def->pm.s3) {
        const char *pm_object = "PIIX4_PM";

6782
        if (qemuDomainIsQ35(def) &&
6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S3)) {
            pm_object = "ICH9-LPC";
        } else if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S3)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           "%s", _("setting ACPI S3 not supported"));
            return -1;
        }

        virCommandAddArg(cmd, "-global");
        virCommandAddArgFormat(cmd, "%s.disable_s3=%d",
                               pm_object, def->pm.s3 == VIR_TRISTATE_BOOL_NO);
    }

    if (def->pm.s4) {
        const char *pm_object = "PIIX4_PM";

6799
        if (qemuDomainIsQ35(def) &&
6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S4)) {
            pm_object = "ICH9-LPC";
        } else if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S4)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           "%s", _("setting ACPI S4 not supported"));
            return -1;
        }

        virCommandAddArg(cmd, "-global");
        virCommandAddArgFormat(cmd, "%s.disable_s4=%d",
                               pm_object, def->pm.s4 == VIR_TRISTATE_BOOL_NO);
    }

    return 0;
}


6817 6818 6819
static int
qemuBuildBootCommandLine(virCommandPtr cmd,
                         const virDomainDef *def,
6820
                         virQEMUCapsPtr qemuCaps)
6821 6822
{
    virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
6823
    char *boot_opts_str = NULL;
6824 6825

    if (def->os.bootmenu) {
J
Ján Tomko 已提交
6826 6827 6828 6829
        if (def->os.bootmenu == VIR_TRISTATE_BOOL_YES)
            virBufferAddLit(&boot_buf, "menu=on,");
        else
            virBufferAddLit(&boot_buf, "menu=off,");
6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864
    }

    if (def->os.bios.rt_set) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_REBOOT_TIMEOUT)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("reboot timeout is not supported "
                             "by this QEMU binary"));
            goto error;
        }

        virBufferAsprintf(&boot_buf,
                          "reboot-timeout=%d,",
                          def->os.bios.rt_delay);
    }

    if (def->os.bm_timeout_set) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPLASH_TIMEOUT)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("splash timeout is not supported "
                             "by this QEMU binary"));
            goto error;
        }

        virBufferAsprintf(&boot_buf, "splash-time=%u,", def->os.bm_timeout);
    }

    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BOOT_STRICT))
        virBufferAddLit(&boot_buf, "strict=on,");

    virBufferTrim(&boot_buf, ",", -1);

    if (virBufferCheckError(&boot_buf) < 0)
        goto error;

    boot_opts_str = virBufferContentAndReset(&boot_buf);
6865
    if (boot_opts_str) {
6866
        virCommandAddArg(cmd, "-boot");
6867
        virCommandAddArg(cmd, boot_opts_str);
6868 6869 6870 6871 6872 6873 6874 6875 6876
    }
    VIR_FREE(boot_opts_str);

    if (def->os.kernel)
        virCommandAddArgList(cmd, "-kernel", def->os.kernel, NULL);
    if (def->os.initrd)
        virCommandAddArgList(cmd, "-initrd", def->os.initrd, NULL);
    if (def->os.cmdline)
        virCommandAddArgList(cmd, "-append", def->os.cmdline, NULL);
J
Ján Tomko 已提交
6877 6878
    if (def->os.dtb)
        virCommandAddArgList(cmd, "-dtb", def->os.dtb, NULL);
6879 6880 6881 6882
    if (def->os.slic_table) {
        virBuffer buf = VIR_BUFFER_INITIALIZER;
        virCommandAddArg(cmd, "-acpitable");
        virBufferAddLit(&buf, "sig=SLIC,file=");
6883
        virQEMUBuildBufferEscapeComma(&buf, def->os.slic_table);
6884 6885
        virCommandAddArgBuffer(cmd, &buf);
    }
6886 6887 6888 6889 6890 6891 6892 6893 6894 6895

    return 0;

 error:
    VIR_FREE(boot_opts_str);
    virBufferFreeAndReset(&boot_buf);
    return -1;
}


6896 6897 6898 6899 6900
static int
qemuBuildIOMMUCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
6901 6902 6903 6904 6905
    virBuffer opts = VIR_BUFFER_INITIALIZER;
    const virDomainIOMMUDef *iommu = def->iommu;
    int ret = -1;

    if (!iommu)
6906 6907
        return 0;

6908 6909 6910 6911 6912 6913 6914 6915 6916
    switch (iommu->model) {
    case VIR_DOMAIN_IOMMU_MODEL_INTEL:
        if (iommu->intremap != VIR_TRISTATE_SWITCH_ABSENT &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_INTREMAP)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("iommu: interrupt remapping is not supported "
                             "with this QEMU binary"));
            return -1;
        }
6917 6918 6919 6920 6921 6922 6923
        if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_CACHING_MODE))  {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("iommu: caching mode is not supported "
                             "with this QEMU binary"));
            return -1;
        }
6924 6925 6926 6927 6928 6929 6930
        if (iommu->eim != VIR_TRISTATE_SWITCH_ABSENT &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_EIM))  {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("iommu: eim is not supported "
                             "with this QEMU binary"));
            return -1;
        }
6931 6932 6933 6934 6935 6936 6937
        if (iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_DEVICE_IOTLB)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("iommu: device IOTLB is not supported "
                             "with this QEMU binary"));
            return -1;
        }
6938 6939 6940 6941 6942
        break;
    case VIR_DOMAIN_IOMMU_MODEL_LAST:
        break;
    }

6943 6944 6945
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_IOMMU))
        return 0; /* Already handled via -machine */

6946
    switch (iommu->model) {
6947 6948 6949 6950 6951
    case VIR_DOMAIN_IOMMU_MODEL_INTEL:
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_INTEL_IOMMU)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("IOMMU device: '%s' is not supported with "
                             "this QEMU binary"),
6952
                           virDomainIOMMUModelTypeToString(iommu->model));
6953 6954
            return -1;
        }
6955
        if (!qemuDomainIsQ35(def)) {
6956 6957 6958
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("IOMMU device: '%s' is only supported with "
                             "Q35 machines"),
6959
                           virDomainIOMMUModelTypeToString(iommu->model));
6960 6961
            return -1;
        }
6962
        virBufferAddLit(&opts, "intel-iommu");
6963 6964 6965 6966
        if (iommu->intremap != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&opts, ",intremap=%s",
                              virTristateSwitchTypeToString(iommu->intremap));
        }
6967 6968 6969 6970
        if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&opts, ",caching-mode=%s",
                              virTristateSwitchTypeToString(iommu->caching_mode));
        }
6971 6972 6973 6974
        if (iommu->eim != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&opts, ",eim=%s",
                              virTristateSwitchTypeToString(iommu->eim));
        }
6975 6976 6977 6978
        if (iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&opts, ",device-iotlb=%s",
                              virTristateSwitchTypeToString(iommu->iotlb));
        }
6979 6980 6981
    case VIR_DOMAIN_IOMMU_MODEL_LAST:
        break;
    }
6982 6983 6984 6985 6986 6987
    virCommandAddArg(cmd, "-device");
    virCommandAddArgBuffer(cmd, &opts);

    ret = 0;
    virBufferFreeAndReset(&opts);
    return ret;
6988 6989 6990
}


6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005
static int
qemuBuildGlobalControllerCommandLine(virCommandPtr cmd,
                                     const virDomainDef *def,
                                     virQEMUCapsPtr qemuCaps)
{
    size_t i;

    for (i = 0; i < def->ncontrollers; i++) {
        virDomainControllerDefPtr cont = def->controllers[i];
        if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
            cont->opts.pciopts.pcihole64) {
            const char *hoststr = NULL;
            bool cap = false;
            bool machine = false;

7006
            switch (cont->model) {
7007 7008 7009
            case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
                hoststr = "i440FX-pcihost";
                cap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_I440FX_PCI_HOLE64_SIZE);
7010
                machine = qemuDomainIsI440FX(def);
7011 7012 7013 7014 7015
                break;

            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
                hoststr = "q35-pcihost";
                cap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_Q35_PCI_HOLE64_SIZE);
7016
                machine = qemuDomainIsQ35(def);
7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048
                break;

            default:
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("64-bit PCI hole setting is only for root"
                                 " PCI controllers"));
                return -1;
            }

            if (!machine) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                             _("Setting the 64-bit PCI hole size is not "
                             "supported for machine '%s'"), def->os.machine);
                return -1;
            }
            if (!cap) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("64-bit PCI hole size setting is not supported "
                                 "with this QEMU binary"));
                return -1;
            }

            virCommandAddArg(cmd, "-global");
            virCommandAddArgFormat(cmd, "%s.pci-hole64-size=%luK", hoststr,
                                   cont->opts.pciopts.pcihole64size);
        }
    }

    return 0;
}


7049
static int
7050 7051 7052
qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
                        const virDomainDef *def,
                        virBufferPtr buf,
7053
                        virQEMUCapsPtr qemuCaps)
7054
{
7055 7056
    int ret = -1;
    size_t i;
7057
    virCapsPtr caps = NULL;
7058
    virCPUDefPtr cpu = def->cpu;
7059

7060 7061 7062
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

7063 7064
    switch ((virCPUMode) cpu->mode) {
    case VIR_CPU_MODE_HOST_PASSTHROUGH:
7065
        virBufferAddLit(buf, "host");
7066

7067
        if (def->os.arch == VIR_ARCH_ARMV7L &&
7068
            caps->host.arch == VIR_ARCH_AARCH64) {
7069 7070 7071 7072 7073 7074 7075 7076 7077
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_AARCH64_OFF)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("QEMU binary does not support CPU "
                                 "host-passthrough for armv7l on "
                                 "aarch64 host"));
                goto cleanup;
            }
            virBufferAddLit(buf, ",aarch64=off");
        }
7078
        break;
7079

7080 7081 7082
    case VIR_CPU_MODE_HOST_MODEL:
        if (ARCH_IS_PPC64(def->os.arch)) {
            virBufferAddLit(buf, "host");
7083 7084 7085
            if (cpu->model &&
                !(qemuDomainIsPSeries(def) &&
                  virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_MAX_CPU_COMPAT))) {
7086
                virBufferAsprintf(buf, ",compat=%s", cpu->model);
7087
            }
7088
        } else {
7089 7090 7091
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected host-model CPU for %s architecture"),
                           virArchToString(def->os.arch));
7092
            goto cleanup;
7093 7094
        }
        break;
7095

7096 7097 7098
    case VIR_CPU_MODE_CUSTOM:
        virBufferAdd(buf, cpu->model, -1);
        break;
7099

7100 7101 7102
    case VIR_CPU_MODE_LAST:
        break;
    }
7103

7104 7105 7106 7107 7108 7109 7110 7111
    if (ARCH_IS_S390(def->os.arch) && cpu->features &&
        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("CPU features not supported by hypervisor for %s "
                         "architecture"), virArchToString(def->os.arch));
        goto cleanup;
    }

7112 7113
    if (cpu->vendor_id)
        virBufferAsprintf(buf, ",vendor=%s", cpu->vendor_id);
7114

7115 7116 7117 7118
    for (i = 0; i < cpu->nfeatures; i++) {
        switch ((virCPUFeaturePolicy) cpu->features[i].policy) {
        case VIR_CPU_FEATURE_FORCE:
        case VIR_CPU_FEATURE_REQUIRE:
7119 7120 7121 7122
            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
                virBufferAsprintf(buf, ",%s=on", cpu->features[i].name);
            else
                virBufferAsprintf(buf, ",+%s", cpu->features[i].name);
7123
            break;
7124

7125 7126
        case VIR_CPU_FEATURE_DISABLE:
        case VIR_CPU_FEATURE_FORBID:
7127 7128 7129 7130
            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
                virBufferAsprintf(buf, ",%s=off", cpu->features[i].name);
            else
                virBufferAsprintf(buf, ",-%s", cpu->features[i].name);
7131
            break;
7132

7133 7134 7135
        case VIR_CPU_FEATURE_OPTIONAL:
        case VIR_CPU_FEATURE_LAST:
            break;
7136
        }
7137
    }
7138

7139
    ret = 0;
7140
 cleanup:
7141 7142 7143
    virObjectUnref(caps);
    return ret;
}
7144

7145
static int
7146 7147 7148
qemuBuildCpuCommandLine(virCommandPtr cmd,
                        virQEMUDriverPtr driver,
                        const virDomainDef *def,
7149
                        virQEMUCapsPtr qemuCaps)
7150
{
7151
    virArch hostarch = virArchFromHost();
7152
    char *cpu = NULL, *cpu_flags = NULL;
7153
    int ret = -1;
7154
    virBuffer cpu_buf = VIR_BUFFER_INITIALIZER;
7155 7156
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    size_t i;
7157

7158 7159
    if (def->cpu &&
        (def->cpu->mode != VIR_CPU_MODE_CUSTOM || def->cpu->model)) {
7160
        if (qemuBuildCpuModelArgStr(driver, def, &cpu_buf, qemuCaps) < 0)
7161
            goto cleanup;
7162
    } else {
7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174
        /*
         * Need to force a 32-bit guest CPU type if
         *
         *  1. guest OS is i686
         *  2. host OS is x86_64
         *  3. emulator is qemu-kvm or kvm
         *
         * Or
         *
         *  1. guest OS is i686
         *  2. emulator is qemu-system-x86_64
         */
7175
        if (def->os.arch == VIR_ARCH_I686 &&
7176
            ((hostarch == VIR_ARCH_X86_64 &&
J
John Ferlan 已提交
7177 7178
              strstr(def->emulator, "kvm")) ||
             strstr(def->emulator, "x86_64"))) {
7179
            virBufferAddLit(&cpu_buf, "qemu32");
7180 7181 7182
        }
    }

7183
    /* Handle paravirtual timers  */
7184
    for (i = 0; i < def->clock.ntimers; i++) {
7185 7186
        virDomainTimerDefPtr timer = def->clock.timers[i];

7187 7188
        if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK &&
            timer->present != -1) {
7189
            virBufferAsprintf(&buf, ",%ckvmclock",
7190 7191
                              timer->present ? '+' : '-');
        } else if (timer->name == VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK &&
7192
                   timer->present == 1) {
7193
            virBufferAddLit(&buf, ",hv_time");
7194 7195
        } else if (timer->name == VIR_DOMAIN_TIMER_NAME_TSC &&
                   timer->frequency > 0) {
7196
            virBufferAsprintf(&buf, ",tsc-frequency=%lu", timer->frequency);
7197
        }
7198 7199
    }

7200 7201
    if (def->apic_eoi) {
        char sign;
J
Ján Tomko 已提交
7202
        if (def->apic_eoi == VIR_TRISTATE_SWITCH_ON)
7203 7204 7205 7206
            sign = '+';
        else
            sign = '-';

7207
        virBufferAsprintf(&buf, ",%ckvm_pv_eoi", sign);
7208 7209
    }

7210 7211
    if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK]) {
        char sign;
7212 7213
        if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] ==
            VIR_TRISTATE_SWITCH_ON)
7214 7215 7216 7217
            sign = '+';
        else
            sign = '-';

7218
        virBufferAsprintf(&buf, ",%ckvm_pv_unhalt", sign);
7219 7220
    }

J
Ján Tomko 已提交
7221
    if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_TRISTATE_SWITCH_ON) {
7222
        for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
7223
            switch ((virDomainHyperv) i) {
7224
            case VIR_DOMAIN_HYPERV_RELAXED:
7225
            case VIR_DOMAIN_HYPERV_VAPIC:
7226 7227 7228 7229 7230
            case VIR_DOMAIN_HYPERV_VPINDEX:
            case VIR_DOMAIN_HYPERV_RUNTIME:
            case VIR_DOMAIN_HYPERV_SYNIC:
            case VIR_DOMAIN_HYPERV_STIMER:
            case VIR_DOMAIN_HYPERV_RESET:
7231
            case VIR_DOMAIN_HYPERV_FREQUENCIES:
7232
            case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
7233
            case VIR_DOMAIN_HYPERV_TLBFLUSH:
7234
            case VIR_DOMAIN_HYPERV_IPI:
7235
            case VIR_DOMAIN_HYPERV_EVMCS:
J
Ján Tomko 已提交
7236
                if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON)
7237 7238 7239 7240
                    virBufferAsprintf(&buf, ",hv_%s",
                                      virDomainHypervTypeToString(i));
                break;

7241
            case VIR_DOMAIN_HYPERV_SPINLOCKS:
J
Ján Tomko 已提交
7242
                if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON)
7243 7244
                    virBufferAsprintf(&buf, ",hv_spinlocks=0x%x",
                                      def->hyperv_spinlocks);
7245 7246
                break;

7247 7248 7249 7250 7251 7252
            case VIR_DOMAIN_HYPERV_VENDOR_ID:
                if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON)
                    virBufferAsprintf(&buf, ",hv_vendor_id=%s",
                                      def->hyperv_vendor_id);
                break;

7253
            /* coverity[dead_error_begin] */
7254 7255 7256 7257 7258 7259
            case VIR_DOMAIN_HYPERV_LAST:
                break;
            }
        }
    }

D
Dmitry Andreev 已提交
7260 7261 7262 7263 7264
    for (i = 0; i < def->npanics; i++) {
        if (def->panics[i]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) {
            virBufferAddLit(&buf, ",hv_crash");
            break;
        }
7265 7266
    }

7267 7268 7269 7270 7271 7272 7273 7274
    if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
        for (i = 0; i < VIR_DOMAIN_KVM_LAST; i++) {
            switch ((virDomainKVM) i) {
            case VIR_DOMAIN_KVM_HIDDEN:
                if (def->kvm_features[i] == VIR_TRISTATE_SWITCH_ON)
                    virBufferAddLit(&buf, ",kvm=off");
                break;

J
John Ferlan 已提交
7275
            /* coverity[dead_error_begin] */
7276 7277 7278 7279 7280 7281
            case VIR_DOMAIN_KVM_LAST:
                break;
            }
        }
    }

7282 7283 7284 7285 7286 7287
    if (def->features[VIR_DOMAIN_FEATURE_PMU]) {
        virTristateSwitch pmu = def->features[VIR_DOMAIN_FEATURE_PMU];
        virBufferAsprintf(&buf, ",pmu=%s",
                          virTristateSwitchTypeToString(pmu));
    }

7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321
    if (def->cpu && def->cpu->cache) {
        virCPUCacheDefPtr cache = def->cpu->cache;
        bool hostOff = false;
        bool l3Off = false;

        switch (cache->mode) {
        case VIR_CPU_CACHE_MODE_EMULATE:
            virBufferAddLit(&buf, ",l3-cache=on");
            hostOff = true;
            break;

        case VIR_CPU_CACHE_MODE_PASSTHROUGH:
            virBufferAddLit(&buf, ",host-cache-info=on");
            l3Off = true;
            break;

        case VIR_CPU_CACHE_MODE_DISABLE:
            hostOff = l3Off = true;
            break;

        case VIR_CPU_CACHE_MODE_LAST:
            break;
        }

        if (hostOff &&
            def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH &&
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_CACHE))
            virBufferAddLit(&buf, ",host-cache-info=off");

        if (l3Off &&
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_CACHE))
            virBufferAddLit(&buf, ",l3-cache=off");
    }

7322 7323
    if (virBufferCheckError(&cpu_buf) < 0)
        goto cleanup;
7324
    if (virBufferCheckError(&buf) < 0)
7325
        goto cleanup;
7326

7327 7328 7329 7330
    cpu = virBufferContentAndReset(&cpu_buf);
    cpu_flags = virBufferContentAndReset(&buf);

    if (cpu_flags && !cpu) {
7331 7332
        const char *default_model;

7333
        switch ((int)def->os.arch) {
7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347
        case VIR_ARCH_I686:
            default_model = "qemu32";
            break;
        case VIR_ARCH_X86_64:
            default_model = "qemu64";
            break;
        default:
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("CPU flags requested but can't determine "
                             "default CPU for arch %s"),
                           virArchToString(def->os.arch));
            goto cleanup;
        }

7348 7349 7350
        if (VIR_STRDUP(cpu, default_model) < 0)
            goto cleanup;
    }
7351 7352

    if (cpu) {
7353
        virCommandAddArg(cmd, "-cpu");
J
Ján Tomko 已提交
7354
        virCommandAddArgFormat(cmd, "%s%s", cpu, NULLSTR_EMPTY(cpu_flags));
7355
    }
7356 7357 7358

    ret = 0;

7359
 cleanup:
7360
    VIR_FREE(cpu);
7361
    VIR_FREE(cpu_flags);
7362
    virBufferFreeAndReset(&buf);
7363
    virBufferFreeAndReset(&cpu_buf);
7364 7365 7366
    return ret;
}

7367

7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400
static bool
qemuAppendKeyWrapMachineParm(virBuffer *buf, virQEMUCapsPtr qemuCaps,
                             int flag, const char *pname, int pstate)
{
    if (pstate != VIR_TRISTATE_SWITCH_ABSENT) {
        if (!virQEMUCapsGet(qemuCaps, flag)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("%s is not available with this QEMU binary"), pname);
            return false;
        }

        virBufferAsprintf(buf, ",%s=%s", pname,
                          virTristateSwitchTypeToString(pstate));
    }

    return true;
}

static bool
qemuAppendKeyWrapMachineParms(virBuffer *buf, virQEMUCapsPtr qemuCaps,
                              const virDomainKeyWrapDef *keywrap)
{
    if (!qemuAppendKeyWrapMachineParm(buf, qemuCaps, QEMU_CAPS_AES_KEY_WRAP,
                                      "aes-key-wrap", keywrap->aes))
        return false;

    if (!qemuAppendKeyWrapMachineParm(buf, qemuCaps, QEMU_CAPS_DEA_KEY_WRAP,
                                      "dea-key-wrap", keywrap->dea))
        return false;

    return true;
}

7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428

static void
qemuAppendLoadparmMachineParm(virBuffer *buf,
                              const virDomainDef *def)
{
    size_t i = 0;

    for (i = 0; i < def->ndisks; i++) {
        virDomainDiskDefPtr disk = def->disks[i];

        if (disk->info.bootIndex == 1 && disk->info.loadparm) {
            virBufferAsprintf(buf, ",loadparm=%s", disk->info.loadparm);
            return;
        }
    }

    /* Network boot device */
    for (i = 0; i < def->nnets; i++) {
        virDomainNetDefPtr net = def->nets[i];

        if (net->info.bootIndex == 1 && net->info.loadparm) {
            virBufferAsprintf(buf, ",loadparm=%s", net->info.loadparm);
            return;
        }
    }
}


M
Marc-André Lureau 已提交
7429 7430 7431 7432 7433 7434 7435 7436 7437 7438
static int
qemuBuildNameCommandLine(virCommandPtr cmd,
                         virQEMUDriverConfigPtr cfg,
                         const virDomainDef *def,
                         virQEMUCapsPtr qemuCaps)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virCommandAddArg(cmd, "-name");

7439 7440 7441 7442
    /* The 'guest' option let's us handle a name with '=' embedded in it */
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NAME_GUEST))
        virBufferAddLit(&buf, "guest=");

7443
    virQEMUBuildBufferEscapeComma(&buf, def->name);
M
Marc-André Lureau 已提交
7444

7445
    if (cfg->setProcessName)
M
Marc-André Lureau 已提交
7446 7447 7448 7449 7450 7451 7452 7453 7454 7455
        virBufferAsprintf(&buf, ",process=qemu:%s", def->name);

    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NAME_DEBUG_THREADS))
        virBufferAddLit(&buf, ",debug-threads=on");

    virCommandAddArgBuffer(cmd, &buf);

    return 0;
}

7456
static int
7457
qemuBuildMachineCommandLine(virCommandPtr cmd,
7458
                            virQEMUDriverConfigPtr cfg,
7459 7460
                            const virDomainDef *def,
                            virQEMUCapsPtr qemuCaps)
7461
{
7462 7463 7464
    virTristateSwitch vmport = def->features[VIR_DOMAIN_FEATURE_VMPORT];
    virTristateSwitch smm = def->features[VIR_DOMAIN_FEATURE_SMM];
    virCPUDefPtr cpu = def->cpu;
7465
    virBuffer buf = VIR_BUFFER_INITIALIZER;
M
Michal Privoznik 已提交
7466
    size_t i;
7467
    int ret = -1;
7468

7469 7470 7471 7472 7473 7474 7475
    /* This should *never* be NULL, since we always provide
     * a machine in the capabilities data for QEMU. So this
     * check is just here as a safety in case the unexpected
     * happens */
    if (!def->os.machine)
        return 0;

7476 7477 7478
    virCommandAddArg(cmd, "-machine");
    virBufferAdd(&buf, def->os.machine, -1);

7479
    switch ((virDomainVirtType)def->virtType) {
7480
    case VIR_DOMAIN_VIRT_QEMU:
7481
        virBufferAddLit(&buf, ",accel=tcg");
7482 7483 7484
        break;

    case VIR_DOMAIN_VIRT_KVM:
7485
        virBufferAddLit(&buf, ",accel=kvm");
7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501
        break;

    case VIR_DOMAIN_VIRT_KQEMU:
    case VIR_DOMAIN_VIRT_XEN:
    case VIR_DOMAIN_VIRT_LXC:
    case VIR_DOMAIN_VIRT_UML:
    case VIR_DOMAIN_VIRT_OPENVZ:
    case VIR_DOMAIN_VIRT_TEST:
    case VIR_DOMAIN_VIRT_VMWARE:
    case VIR_DOMAIN_VIRT_HYPERV:
    case VIR_DOMAIN_VIRT_VBOX:
    case VIR_DOMAIN_VIRT_PHYP:
    case VIR_DOMAIN_VIRT_PARALLELS:
    case VIR_DOMAIN_VIRT_BHYVE:
    case VIR_DOMAIN_VIRT_VZ:
    case VIR_DOMAIN_VIRT_NONE:
7502 7503 7504 7505
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("the QEMU binary does not support %s"),
                       virDomainVirtTypeToString(def->virtType));
        return -1;
7506 7507 7508 7509 7510

    case VIR_DOMAIN_VIRT_LAST:
    default:
        virReportEnumRangeError(virDomainVirtType, def->virtType);
        return -1;
7511
    }
7512 7513 7514 7515

    /* To avoid the collision of creating USB controllers when calling
     * machine->init in QEMU, it needs to set usb=off
     */
7516
    virBufferAddLit(&buf, ",usb=off");
7517 7518 7519

    if (vmport) {
        if (!virQEMUCapsSupportsVmport(qemuCaps, def)) {
7520
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7521
                           _("vmport is not available "
7522
                             "with this QEMU binary"));
7523
            goto cleanup;
7524
        }
7525

7526 7527 7528 7529
        virBufferAsprintf(&buf, ",vmport=%s",
                          virTristateSwitchTypeToString(vmport));
    }

7530 7531
    if (smm)
        virBufferAsprintf(&buf, ",smm=%s", virTristateSwitchTypeToString(smm));
7532

7533 7534 7535
    if (def->mem.dump_core) {
        virBufferAsprintf(&buf, ",dump-guest-core=%s",
                          virTristateSwitchTypeToString(def->mem.dump_core));
7536
    } else {
7537 7538
        virBufferAsprintf(&buf, ",dump-guest-core=%s",
                          cfg->dumpGuestCore ? "on" : "off");
7539
    }
M
Michal Privoznik 已提交
7540

7541 7542 7543 7544 7545 7546
    if (def->mem.nosharepages) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MEM_MERGE)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("disable shared memory is not available "
                             "with this QEMU binary"));
            goto cleanup;
M
Michal Privoznik 已提交
7547
        }
7548

7549 7550
        virBufferAddLit(&buf, ",mem-merge=off");
    }
7551

7552 7553 7554
    if (def->keywrap &&
        !qemuAppendKeyWrapMachineParms(&buf, qemuCaps, def->keywrap))
        goto cleanup;
7555

7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571
    if (def->features[VIR_DOMAIN_FEATURE_GIC] == VIR_TRISTATE_SWITCH_ON) {
        bool hasGICVersionOption = virQEMUCapsGet(qemuCaps,
                                                  QEMU_CAPS_MACH_VIRT_GIC_VERSION);

        switch ((virGICVersion) def->gic_version) {
        case VIR_GIC_VERSION_2:
            if (!hasGICVersionOption) {
                /* If the gic-version option is not available, we can't
                 * configure the GIC; however, we know that before the
                 * option was introduced the guests would always get a
                 * GICv2, so in order to maintain compatibility with
                 * those old QEMU versions all we need to do is stop
                 * early instead of erroring out */
                break;
            }
            ATTRIBUTE_FALLTHROUGH;
L
Li Zhang 已提交
7572

7573 7574 7575
        case VIR_GIC_VERSION_3:
        case VIR_GIC_VERSION_HOST:
            if (!hasGICVersionOption) {
7576
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7577
                               _("gic-version option is not available "
7578
                                 "with this QEMU binary"));
7579
                goto cleanup;
7580 7581
            }

7582 7583 7584
            virBufferAsprintf(&buf, ",gic-version=%s",
                              virGICVersionTypeToString(def->gic_version));
            break;
M
Michal Privoznik 已提交
7585

7586 7587 7588 7589
        case VIR_GIC_VERSION_NONE:
        case VIR_GIC_VERSION_LAST:
        default:
            break;
M
Michal Privoznik 已提交
7590
        }
7591
    }
M
Michal Privoznik 已提交
7592

7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603
    /* We don't report errors on missing cap here - -device code will do that */
    if (def->iommu &&
        virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_IOMMU)) {
        switch (def->iommu->model) {
        case VIR_DOMAIN_IOMMU_MODEL_INTEL:
            if (!qemuDomainIsQ35(def)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("IOMMU device: '%s' is only supported with "
                                 "Q35 machines"),
                               virDomainIOMMUModelTypeToString(def->iommu->model));
                return -1;
7604
            }
7605 7606 7607 7608
            virBufferAddLit(&buf, ",iommu=on");
            break;
        case VIR_DOMAIN_IOMMU_MODEL_LAST:
            break;
7609
        }
7610
    }
7611

7612 7613 7614
    for (i = 0; i < def->nmems; i++) {
        if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM) {
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_NVDIMM)) {
7615
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7616
                               _("nvdimm isn't supported by this QEMU binary"));
7617
                goto cleanup;
7618
            }
7619 7620
            virBufferAddLit(&buf, ",nvdimm=on");
            break;
7621
        }
7622
    }
7623

7624 7625 7626 7627 7628
    if (def->features[VIR_DOMAIN_FEATURE_IOAPIC] != VIR_DOMAIN_IOAPIC_NONE) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_KERNEL_IRQCHIP)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("I/O APIC tuning is not supported by this "
                             "QEMU binary"));
7629
            goto cleanup;
M
Michal Privoznik 已提交
7630
        }
7631 7632 7633
        switch ((virDomainIOAPIC) def->features[VIR_DOMAIN_FEATURE_IOAPIC]) {
        case VIR_DOMAIN_IOAPIC_QEMU:
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_KERNEL_IRQCHIP_SPLIT)) {
7634
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7635
                               _("split I/O APIC is not supported by this "
7636 7637 7638
                                 "QEMU binary"));
                goto cleanup;
            }
7639 7640 7641 7642 7643 7644 7645 7646
            virBufferAddLit(&buf, ",kernel_irqchip=split");
            break;
        case VIR_DOMAIN_IOAPIC_KVM:
            virBufferAddLit(&buf, ",kernel_irqchip=on");
            break;
        case VIR_DOMAIN_IOAPIC_NONE:
        case VIR_DOMAIN_IOAPIC_LAST:
            break;
7647
        }
7648
    }
7649

7650
    if (def->features[VIR_DOMAIN_FEATURE_HPT] == VIR_TRISTATE_SWITCH_ON) {
7651

7652 7653
        if (def->hpt_resizing != VIR_DOMAIN_HPT_RESIZING_NONE) {
            const char *str;
7654

7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("HTP resizing is not supported by this "
                                 "QEMU binary"));
                goto cleanup;
            }

            str = virDomainHPTResizingTypeToString(def->hpt_resizing);
            if (!str) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("Invalid setting for HPT resizing"));
                goto cleanup;
            }
7668

7669 7670
            virBufferAsprintf(&buf, ",resize-hpt=%s", str);
        }
7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682

        if (def->hpt_maxpagesize > 0) {
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_CAP_HPT_MAX_PAGE_SIZE)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("Configuring the page size for HPT guests "
                                 "is not supported by this QEMU binary"));
                goto cleanup;
            }

            virBufferAsprintf(&buf, ",cap-hpt-max-page-size=%lluk",
                              def->hpt_maxpagesize);
        }
7683
    }
7684

7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704
    if (def->features[VIR_DOMAIN_FEATURE_HTM] != VIR_TRISTATE_SWITCH_ABSENT) {
        const char *str;

        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_CAP_HTM)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("HTM configuration is not supported by this "
                             "QEMU binary"));
            goto cleanup;
        }

        str = virTristateSwitchTypeToString(def->features[VIR_DOMAIN_FEATURE_HTM]);
        if (!str) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Invalid setting for HTM state"));
            goto cleanup;
        }

        virBufferAsprintf(&buf, ",cap-htm=%s", str);
    }

7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724
    if (def->features[VIR_DOMAIN_FEATURE_NESTED_HV] != VIR_TRISTATE_SWITCH_ABSENT) {
        const char *str;

        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_CAP_NESTED_HV)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Nested HV configuration is not supported by "
                             "this QEMU binary"));
            goto cleanup;
        }

        str = virTristateSwitchTypeToString(def->features[VIR_DOMAIN_FEATURE_NESTED_HV]);
        if (!str) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Invalid setting for nested HV state"));
            goto cleanup;
        }

        virBufferAsprintf(&buf, ",cap-nested-hv=%s", str);
    }

7725 7726 7727 7728 7729
    if (cpu && cpu->model &&
        cpu->mode == VIR_CPU_MODE_HOST_MODEL &&
        qemuDomainIsPSeries(def) &&
        virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_MAX_CPU_COMPAT)) {
        virBufferAsprintf(&buf, ",max-cpu-compat=%s", cpu->model);
7730 7731
    }

7732
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
7733 7734
        qemuAppendLoadparmMachineParm(&buf, def);

7735 7736 7737
    if (def->sev)
        virBufferAddLit(&buf, ",memory-encryption=sev0");

7738 7739
    virCommandAddArgBuffer(cmd, &buf);

7740 7741 7742 7743
    ret = 0;
 cleanup:
    virBufferFreeAndReset(&buf);
    return ret;
7744 7745
}

7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761

static void
qemuBuildTSEGCommandLine(virCommandPtr cmd,
                         const virDomainDef *def)
{
    if (!def->tseg_specified)
        return;

    virCommandAddArg(cmd, "-global");

    /* PostParse callback guarantees that the size is divisible by 1 MiB */
    virCommandAddArgFormat(cmd, "mch.extended-tseg-mbytes=%llu",
                           def->tseg_size >> 20);
}


7762 7763
static int
qemuBuildSmpCommandLine(virCommandPtr cmd,
7764
                        virDomainDefPtr def)
7765
{
7766
    char *smp;
7767
    virBuffer buf = VIR_BUFFER_INITIALIZER;
7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779
    unsigned int maxvcpus = virDomainDefGetVcpusMax(def);
    unsigned int nvcpus = 0;
    virDomainVcpuDefPtr vcpu;
    size_t i;

    /* count non-hotpluggable enabled vcpus. Hotpluggable ones will be added
     * in a different way */
    for (i = 0; i < maxvcpus; i++) {
        vcpu = virDomainDefGetVcpu(def, i);
        if (vcpu->online && vcpu->hotpluggable == VIR_TRISTATE_BOOL_NO)
            nvcpus++;
    }
7780

7781 7782
    virCommandAddArg(cmd, "-smp");

7783
    virBufferAsprintf(&buf, "%u", nvcpus);
7784

7785 7786
    if (nvcpus != maxvcpus)
        virBufferAsprintf(&buf, ",maxcpus=%u", maxvcpus);
7787 7788 7789 7790 7791 7792 7793 7794 7795 7796
    /* sockets, cores, and threads are either all zero
     * or all non-zero, thus checking one of them is enough */
    if (def->cpu && def->cpu->sockets) {
        virBufferAsprintf(&buf, ",sockets=%u", def->cpu->sockets);
        virBufferAsprintf(&buf, ",cores=%u", def->cpu->cores);
        virBufferAsprintf(&buf, ",threads=%u", def->cpu->threads);
    } else {
        virBufferAsprintf(&buf, ",sockets=%u", virDomainDefGetVcpusMax(def));
        virBufferAsprintf(&buf, ",cores=%u", 1);
        virBufferAsprintf(&buf, ",threads=%u", 1);
7797 7798
    }

7799
    if (virBufferCheckError(&buf) < 0)
7800
        return -1;
7801

7802 7803 7804 7805 7806
    smp = virBufferContentAndReset(&buf);
    virCommandAddArg(cmd, smp);
    VIR_FREE(smp);

    return 0;
7807 7808
}

7809

7810 7811
static int
qemuBuildMemPathStr(virQEMUDriverConfigPtr cfg,
7812
                    const virDomainDef *def,
7813 7814
                    virCommandPtr cmd,
                    qemuDomainObjPrivatePtr priv)
7815 7816 7817 7818
{
    const long system_page_size = virGetSystemPageSizeKB();
    char *mem_path = NULL;

7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832
    /* There are two cases where we want to put -mem-path onto
     * the command line: First one is when there are no guest
     * NUMA nodes and hugepages are configured. The second one is
     * if user requested file allocation. */
    if (def->mem.nhugepages &&
        def->mem.hugepages[0].size != system_page_size) {
        if (qemuGetDomainHupageMemPath(def, cfg,
                                       def->mem.hugepages[0].size,
                                       &mem_path) < 0)
            return -1;
    } else if (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) {
        if (qemuGetMemoryBackingPath(def, cfg, "ram", &mem_path) < 0)
            return -1;
    } else {
7833
        return 0;
7834
    }
7835

7836
    if (def->mem.allocation != VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) {
7837
        virCommandAddArgList(cmd, "-mem-prealloc", NULL);
7838 7839
        priv->memPrealloc = true;
    }
7840 7841

    virCommandAddArgList(cmd, "-mem-path", mem_path, NULL);
7842 7843 7844 7845 7846
    VIR_FREE(mem_path);

    return 0;
}

7847 7848 7849 7850 7851

static int
qemuBuildMemCommandLine(virCommandPtr cmd,
                        virQEMUDriverConfigPtr cfg,
                        const virDomainDef *def,
7852 7853
                        virQEMUCapsPtr qemuCaps,
                        qemuDomainObjPrivatePtr priv)
7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871
{
    if (qemuDomainDefValidateMemoryHotplug(def, qemuCaps, NULL) < 0)
        return -1;

    virCommandAddArg(cmd, "-m");

    if (virDomainDefHasMemoryHotplug(def)) {
        /* Use the 'k' suffix to let qemu handle the units */
        virCommandAddArgFormat(cmd, "size=%lluk,slots=%u,maxmem=%lluk",
                               virDomainDefGetMemoryInitial(def),
                               def->mem.memory_slots,
                               def->mem.max_memory);

    } else {
       virCommandAddArgFormat(cmd, "%llu",
                              virDomainDefGetMemoryInitial(def) / 1024);
    }

7872
    if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) {
7873
        virCommandAddArgList(cmd, "-mem-prealloc", NULL);
7874 7875
        priv->memPrealloc = true;
    }
7876

7877
    /*
7878 7879
     * Add '-mem-path' (and '-mem-prealloc') parameter here if
     * the hugepages and no numa node is specified.
7880 7881
     */
    if (!virDomainNumaGetNodeCount(def->numa) &&
7882
        qemuBuildMemPathStr(cfg, def, cmd, priv) < 0)
7883 7884
        return -1;

7885
    if (def->mem.locked && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_REALTIME_MLOCK)) {
7886 7887 7888 7889
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("memory locking not supported by QEMU binary"));
        return -1;
    }
7890
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_REALTIME_MLOCK)) {
7891 7892 7893 7894 7895 7896 7897 7898 7899
        virCommandAddArg(cmd, "-realtime");
        virCommandAddArgFormat(cmd, "mlock=%s",
                               def->mem.locked ? "on" : "off");
    }

    return 0;
}


7900 7901
static int
qemuBuildIOThreadCommandLine(virCommandPtr cmd,
7902
                             const virDomainDef *def)
7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923
{
    size_t i;

    if (def->niothreadids == 0)
        return 0;

    /* Create iothread objects using the defined iothreadids list
     * and the defined id and name from the list. These may be used
     * by a disk definition which will associate to an iothread by
     * supplying a value of an id from the list
     */
    for (i = 0; i < def->niothreadids; i++) {
        virCommandAddArg(cmd, "-object");
        virCommandAddArgFormat(cmd, "iothread,id=iothread%u",
                               def->iothreadids[i]->iothread_id);
    }

    return 0;
}


B
Bharata B Rao 已提交
7924
static int
7925
qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
7926
                    virDomainDefPtr def,
7927
                    virCommandPtr cmd,
7928
                    qemuDomainObjPrivatePtr priv)
B
Bharata B Rao 已提交
7929
{
7930
    size_t i, j;
7931
    virQEMUCapsPtr qemuCaps = priv->qemuCaps;
B
Bharata B Rao 已提交
7932
    virBuffer buf = VIR_BUFFER_INITIALIZER;
7933
    char *cpumask = NULL, *tmpmask = NULL, *next = NULL;
7934
    virBufferPtr nodeBackends = NULL;
7935 7936
    bool needBackend = false;
    int rc;
7937
    int ret = -1;
7938
    size_t ncells = virDomainNumaGetNodeCount(def->numa);
7939
    const long system_page_size = virGetSystemPageSizeKB();
7940
    bool numa_distances = false;
B
Bharata B Rao 已提交
7941

7942
    if (virDomainNumatuneHasPerNodeBinding(def->numa) &&
7943
        !(virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) ||
M
Marc-André Lureau 已提交
7944 7945
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE) ||
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD))) {
7946 7947 7948 7949 7950 7951
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Per-node memory binding is not supported "
                         "with this QEMU"));
        goto cleanup;
    }

7952 7953
    if (def->mem.nhugepages &&
        def->mem.hugepages[0].size != system_page_size &&
7954 7955 7956 7957 7958 7959 7960
        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("huge pages per NUMA node are not "
                         "supported with this QEMU"));
        goto cleanup;
    }

7961
    if (!virDomainNumatuneNodesetIsAvailable(def->numa, priv->autoNodeset))
7962 7963
        goto cleanup;

7964
    if (VIR_ALLOC_N(nodeBackends, ncells) < 0)
7965 7966 7967 7968
        goto cleanup;

    /* using of -numa memdev= cannot be combined with -numa mem=, thus we
     * need to check which approach to use */
7969
    for (i = 0; i < ncells; i++) {
7970
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) ||
M
Marc-André Lureau 已提交
7971 7972
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE) ||
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD)) {
7973

7974
            if ((rc = qemuBuildMemoryCellBackendStr(def, cfg, i, priv,
7975
                                                    &nodeBackends[i])) < 0)
7976 7977
                goto cleanup;

7978 7979
            if (rc == 0)
                needBackend = true;
7980
        } else {
7981
            if (virDomainNumaGetNodeMemoryAccessMode(def->numa, i)) {
7982 7983 7984 7985 7986
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("Shared memory mapping is not supported "
                                 "with this QEMU"));
                goto cleanup;
            }
7987
        }
7988 7989
    }

7990
    if (!needBackend &&
7991
        qemuBuildMemPathStr(cfg, def, cmd, priv) < 0)
7992 7993
        goto cleanup;

7994
    for (i = 0; i < ncells; i++) {
7995
        VIR_FREE(cpumask);
7996
        if (!(cpumask = virBitmapFormat(virDomainNumaGetNodeCpumask(def->numa, i))))
7997 7998 7999 8000 8001 8002 8003 8004 8005 8006
            goto cleanup;

        if (strchr(cpumask, ',') &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("disjoint NUMA cpu ranges are not supported "
                             "with this QEMU"));
            goto cleanup;
        }

8007 8008
        if (needBackend) {
            virCommandAddArg(cmd, "-object");
8009
            virCommandAddArgBuffer(cmd, &nodeBackends[i]);
8010
        }
8011

B
Bharata B Rao 已提交
8012
        virCommandAddArg(cmd, "-numa");
8013
        virBufferAsprintf(&buf, "node,nodeid=%zu", i);
8014

8015 8016 8017 8018 8019 8020 8021
        for (tmpmask = cpumask; tmpmask; tmpmask = next) {
            if ((next = strchr(tmpmask, ',')))
                *(next++) = '\0';
            virBufferAddLit(&buf, ",cpus=");
            virBufferAdd(&buf, tmpmask, -1);
        }

8022
        if (needBackend)
8023
            virBufferAsprintf(&buf, ",memdev=ram-node%zu", i);
8024
        else
8025
            virBufferAsprintf(&buf, ",mem=%llu",
8026
                              virDomainNumaGetNodeMemorySize(def->numa, i) / 1024);
B
Bharata B Rao 已提交
8027 8028 8029

        virCommandAddArgBuffer(cmd, &buf);
    }
8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065

    /* If NUMA node distance is specified for at least one pair
     * of nodes, we have to specify all the distances. Even
     * though they might be the default ones. */
    for (i = 0; i < ncells; i++) {
        for (j = 0; j < ncells; j++) {
            if (virDomainNumaNodeDistanceIsUsingDefaults(def->numa, i, j))
                continue;

            numa_distances = true;
            break;
        }
        if (numa_distances)
            break;
    }

    if (numa_distances) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA_DIST)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("setting NUMA distances is not "
                             "supported with this qemu"));
            goto cleanup;
        }

        for (i = 0; i < ncells; i++) {
            for (j = 0; j < ncells; j++) {
                size_t distance = virDomainNumaGetNodeDistance(def->numa, i, j);

                virCommandAddArg(cmd, "-numa");
                virBufferAsprintf(&buf, "dist,src=%zu,dst=%zu,val=%zu", i, j, distance);

                virCommandAddArgBuffer(cmd, &buf);
            }
        }
    }

8066
    ret = 0;
B
Bharata B Rao 已提交
8067

8068
 cleanup:
8069
    VIR_FREE(cpumask);
8070 8071

    if (nodeBackends) {
8072
        for (i = 0; i < ncells; i++)
8073
            virBufferFreeAndReset(&nodeBackends[i]);
8074 8075 8076 8077

        VIR_FREE(nodeBackends);
    }

B
Bharata B Rao 已提交
8078
    virBufferFreeAndReset(&buf);
8079
    return ret;
B
Bharata B Rao 已提交
8080
}
8081

8082

8083
static int
8084 8085 8086
qemuBuildMemoryDeviceCommandLine(virCommandPtr cmd,
                                 virQEMUDriverConfigPtr cfg,
                                 virDomainDefPtr def,
8087
                                 qemuDomainObjPrivatePtr priv)
8088 8089 8090 8091 8092 8093
{
    size_t i;

    /* memory hotplug requires NUMA to be enabled - we already checked
     * that memory devices are present only when NUMA is */
    for (i = 0; i < def->nmems; i++) {
8094
        virBuffer buf = VIR_BUFFER_INITIALIZER;
8095 8096
        char *dimmStr;

8097
        if (qemuBuildMemoryDimmBackendStr(&buf, def->mems[i], def, cfg, priv) < 0)
8098 8099
            return -1;

8100 8101 8102
        virCommandAddArg(cmd, "-object");
        virCommandAddArgBuffer(cmd, &buf);

8103
        if (!(dimmStr = qemuBuildMemoryDeviceStr(def->mems[i], priv)))
8104 8105
            return -1;

8106
        virCommandAddArgList(cmd, "-device", dimmStr, NULL);
8107 8108 8109 8110 8111 8112 8113 8114

        VIR_FREE(dimmStr);
    }

    return 0;
}


8115 8116 8117 8118 8119 8120
static int
qemuBuildGraphicsSDLCommandLine(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
                                virCommandPtr cmd,
                                virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED,
                                virDomainGraphicsDefPtr graphics)
{
8121 8122 8123
    int ret = -1;
    virBuffer opt = VIR_BUFFER_INITIALIZER;

8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137
    if (graphics->data.sdl.xauth)
        virCommandAddEnvPair(cmd, "XAUTHORITY", graphics->data.sdl.xauth);
    if (graphics->data.sdl.display)
        virCommandAddEnvPair(cmd, "DISPLAY", graphics->data.sdl.display);
    if (graphics->data.sdl.fullscreen)
        virCommandAddArg(cmd, "-full-screen");

    /* If using SDL for video, then we should just let it
     * use QEMU's host audio drivers, possibly SDL too
     * User can set these two before starting libvirtd
     */
    virCommandAddEnvPassBlockSUID(cmd, "QEMU_AUDIO_DRV", NULL);
    virCommandAddEnvPassBlockSUID(cmd, "SDL_AUDIODRIVER", NULL);

8138 8139
    virCommandAddArg(cmd, "-display");
    virBufferAddLit(&opt, "sdl");
8140

8141
    if (graphics->data.sdl.gl != VIR_TRISTATE_BOOL_ABSENT) {
8142 8143
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SDL_GL)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8144 8145
                           _("OpenGL for SDL is not supported with this QEMU "
                             "binary"));
8146 8147 8148
            goto cleanup;
        }

8149
        virBufferAsprintf(&opt, ",gl=%s",
8150
                          virTristateSwitchTypeToString(graphics->data.sdl.gl));
8151

8152 8153
    }

8154 8155 8156 8157
    if (virBufferCheckError(&opt) < 0)
        goto cleanup;

    virCommandAddArgBuffer(cmd, &opt);
8158 8159 8160 8161 8162

    ret = 0;
 cleanup:
    virBufferFreeAndReset(&opt);
    return ret;
8163 8164 8165
}


8166 8167 8168 8169
static int
qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg,
                                virCommandPtr cmd,
                                virQEMUCapsPtr qemuCaps,
8170
                                virDomainGraphicsDefPtr graphics)
8171 8172
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;
8173
    virDomainGraphicsListenDefPtr glisten = NULL;
8174 8175 8176 8177 8178 8179 8180 8181
    bool escapeAddr;

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VNC)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("vnc graphics are not supported with this QEMU"));
        goto error;
    }

8182 8183 8184 8185 8186
    if (!(glisten = virDomainGraphicsGetListen(graphics, 0))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("missing listen element"));
        goto error;
    }
8187

8188 8189
    switch (glisten->type) {
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
8190 8191 8192 8193
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VNC_MULTI_SERVERS))
            virBufferAddLit(&opt, "vnc=unix:");
        else
            virBufferAddLit(&opt, "unix:");
8194
        virQEMUBuildBufferEscapeComma(&opt, glisten->socket);
8195
        break;
8196

8197 8198
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
8199 8200 8201 8202 8203 8204 8205
        if (!graphics->data.vnc.autoport &&
            (graphics->data.vnc.port < 5900 ||
             graphics->data.vnc.port > 65535)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("vnc port must be in range [5900,65535]"));
            goto error;
        }
8206

8207
        if (glisten->address) {
8208 8209 8210 8211 8212
            escapeAddr = strchr(glisten->address, ':') != NULL;
            if (escapeAddr)
                virBufferAsprintf(&opt, "[%s]", glisten->address);
            else
                virBufferAdd(&opt, glisten->address, -1);
8213 8214 8215
        }
        virBufferAsprintf(&opt, ":%d",
                          graphics->data.vnc.port - 5900);
8216

8217
        if (graphics->data.vnc.websocket)
8218
            virBufferAsprintf(&opt, ",websocket=%d", graphics->data.vnc.websocket);
8219 8220 8221
        break;

    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
8222 8223 8224
        virBufferAddLit(&opt, "none");
        break;

8225 8226
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
        break;
8227
    }
8228

8229 8230 8231
    if (graphics->data.vnc.sharePolicy) {
        virBufferAsprintf(&opt, ",share=%s",
                          virDomainGraphicsVNCSharePolicyTypeToString(
8232
                              graphics->data.vnc.sharePolicy));
8233
    }
8234

8235 8236
    if (graphics->data.vnc.auth.passwd || cfg->vncPassword)
        virBufferAddLit(&opt, ",password");
8237

8238
    if (cfg->vncTLS) {
8239 8240
        qemuDomainGraphicsPrivatePtr gfxPriv = QEMU_DOMAIN_GRAPHICS_PRIVATE(graphics);
        if (gfxPriv->tlsAlias) {
8241 8242 8243 8244 8245 8246 8247 8248 8249
            const char *secretAlias = NULL;

            if (gfxPriv->secinfo) {
                if (qemuBuildObjectSecretCommandLine(cmd,
                                                     gfxPriv->secinfo) < 0)
                    goto error;
                secretAlias = gfxPriv->secinfo->s.aes.alias;
            }

J
Ján Tomko 已提交
8250 8251 8252 8253
            if (qemuBuildTLSx509CommandLine(cmd,
                                            cfg->vncTLSx509certdir,
                                            true,
                                            cfg->vncTLSx509verify,
8254
                                            secretAlias,
8255
                                            gfxPriv->tlsAlias,
J
Ján Tomko 已提交
8256 8257 8258
                                            qemuCaps) < 0)
                goto error;

8259
            virBufferAsprintf(&opt, ",tls-creds=%s", gfxPriv->tlsAlias);
8260
        } else {
J
Ján Tomko 已提交
8261 8262 8263 8264 8265 8266 8267 8268
            virBufferAddLit(&opt, ",tls");
            if (cfg->vncTLSx509verify) {
                virBufferAddLit(&opt, ",x509verify=");
                virQEMUBuildBufferEscapeComma(&opt, cfg->vncTLSx509certdir);
            } else {
                virBufferAddLit(&opt, ",x509=");
                virQEMUBuildBufferEscapeComma(&opt, cfg->vncTLSx509certdir);
            }
8269
        }
8270
    }
8271

8272 8273
    if (cfg->vncSASL) {
        virBufferAddLit(&opt, ",sasl");
8274

8275 8276
        if (cfg->vncSASLdir)
            virCommandAddEnvPair(cmd, "SASL_CONF_PATH", cfg->vncSASLdir);
8277

8278
        /* TODO: Support ACLs later */
8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290
    }

    virCommandAddArg(cmd, "-vnc");
    virCommandAddArgBuffer(cmd, &opt);
    if (graphics->data.vnc.keymap)
        virCommandAddArgList(cmd, "-k", graphics->data.vnc.keymap, NULL);

    /* Unless user requested it, set the audio backend to none, to
     * prevent it opening the host OS audio devices, since that causes
     * security issues and might not work when using VNC.
     */
    if (cfg->vncAllowHostAudio)
8291
        virCommandAddEnvPassBlockSUID(cmd, "QEMU_AUDIO_DRV", NULL);
8292 8293 8294 8295 8296
    else
        virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");

    return 0;

8297
 error:
8298 8299 8300 8301 8302
    virBufferFreeAndReset(&opt);
    return -1;
}


8303 8304 8305 8306 8307 8308 8309
static int
qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfigPtr cfg,
                                  virCommandPtr cmd,
                                  virQEMUCapsPtr qemuCaps,
                                  virDomainGraphicsDefPtr graphics)
{
    virBuffer opt = VIR_BUFFER_INITIALIZER;
8310
    virDomainGraphicsListenDefPtr glisten = NULL;
8311 8312
    int port = graphics->data.spice.port;
    int tlsPort = graphics->data.spice.tlsPort;
8313
    size_t i;
8314 8315
    bool hasSecure = false;
    bool hasInsecure = false;
8316 8317 8318 8319 8320 8321 8322

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("spice graphics are not supported with this QEMU"));
        goto error;
    }

8323 8324 8325 8326
    if (!(glisten = virDomainGraphicsGetListen(graphics, 0))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("missing listen element"));
        goto error;
8327
    }
8328

8329 8330 8331
    switch (glisten->type) {
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_UNIX)) {
8332
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8333 8334
                           _("unix socket for spice graphics are not supported "
                             "with this QEMU"));
8335 8336 8337
            goto error;
        }

8338
        virBufferAddLit(&opt, "unix,addr=");
8339
        virQEMUBuildBufferEscapeComma(&opt, glisten->socket);
8340
        virBufferAddLit(&opt, ",");
8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369
        hasInsecure = true;
        break;

    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
        if (port > 0) {
            virBufferAsprintf(&opt, "port=%u,", port);
            hasInsecure = true;
        }

        if (tlsPort > 0) {
            if (!cfg->spiceTLS) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("spice TLS port set in XML configuration, "
                                 "but TLS is disabled in qemu.conf"));
                goto error;
            }
            virBufferAsprintf(&opt, "tls-port=%u,", tlsPort);
            hasSecure = true;
        }

        if (port > 0 || tlsPort > 0) {
            if (glisten->address)
                virBufferAsprintf(&opt, "addr=%s,", glisten->address);
        }

        break;

    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
P
Pavel Hrdina 已提交
8370 8371 8372 8373 8374
        /* QEMU requires either port or tls-port to be specified if there is no
         * other argument. Use a dummy port=0. */
        virBufferAddLit(&opt, "port=0,");
        hasInsecure = true;
        break;
8375 8376
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
        break;
8377
    }
8378

8379 8380 8381 8382 8383 8384 8385 8386 8387 8388
    if (cfg->spiceSASL) {
        virBufferAddLit(&opt, "sasl,");

        if (cfg->spiceSASLdir)
            virCommandAddEnvPair(cmd, "SASL_CONF_PATH",
                                 cfg->spiceSASLdir);

        /* TODO: Support ACLs later */
    }

8389 8390 8391
    if (graphics->data.spice.mousemode) {
        switch (graphics->data.spice.mousemode) {
        case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER:
8392
            virBufferAddLit(&opt, "agent-mouse=off,");
8393 8394
            break;
        case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT:
8395
            virBufferAddLit(&opt, "agent-mouse=on,");
8396
            break;
8397
        case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT:
8398
            break;
8399 8400 8401 8402 8403
        case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST:
        default:
            virReportEnumRangeError(virDomainGraphicsSpiceMouseMode,
                                    graphics->data.spice.mousemode);
            goto error;
8404 8405 8406 8407 8408 8409 8410 8411
        }
    }

    /* In the password case we set it via monitor command, to avoid
     * making it visible on CLI, so there's no use of password=XXX
     * in this bit of the code */
    if (!graphics->data.spice.auth.passwd &&
        !cfg->spicePassword)
8412
        virBufferAddLit(&opt, "disable-ticketing,");
8413

8414 8415 8416 8417 8418
    if (hasSecure) {
        virBufferAddLit(&opt, "x509-dir=");
        virQEMUBuildBufferEscapeComma(&opt, cfg->spiceTLSx509certdir);
        virBufferAddLit(&opt, ",");
    }
8419

8420
    switch (graphics->data.spice.defaultMode) {
8421
    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
8422 8423 8424 8425 8426 8427 8428
        if (!hasSecure) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("spice defaultMode secure requested in XML "
                             "configuration, but TLS connection is not "
                             "available"));
            goto error;
        }
8429
        virBufferAddLit(&opt, "tls-channel=default,");
8430 8431
        break;
    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
8432 8433 8434 8435 8436 8437 8438
        if (!hasInsecure) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("spice defaultMode insecure requested in XML "
                             "configuration, but plaintext connection is not "
                             "available"));
            goto error;
        }
8439
        virBufferAddLit(&opt, "plaintext-channel=default,");
8440 8441
        break;
    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
8442
    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST:
8443 8444 8445 8446
        /* nothing */
        break;
    }

8447
    for (i = 0; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST; i++) {
8448
        switch (graphics->data.spice.channels[i]) {
8449
        case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
8450
            if (!hasSecure) {
8451
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8452 8453 8454
                               _("spice secure channels set in XML "
                                 "configuration, but TLS connection is not "
                                 "available"));
8455 8456
                goto error;
            }
8457
            virBufferAsprintf(&opt, "tls-channel=%s,",
8458 8459
                              virDomainGraphicsSpiceChannelNameTypeToString(i));
            break;
8460

8461
        case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
8462
            if (!hasInsecure) {
8463 8464
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("spice insecure channels set in XML "
8465 8466
                                 "configuration, but plaintext connection "
                                 "is not available"));
8467 8468
                goto error;
            }
8469
            virBufferAsprintf(&opt, "plaintext-channel=%s,",
8470 8471
                              virDomainGraphicsSpiceChannelNameTypeToString(i));
            break;
8472 8473 8474

        case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
            break;
8475 8476
        }
    }
8477

8478
    if (graphics->data.spice.image)
8479
        virBufferAsprintf(&opt, "image-compression=%s,",
8480 8481
                          virDomainGraphicsSpiceImageCompressionTypeToString(graphics->data.spice.image));
    if (graphics->data.spice.jpeg)
8482
        virBufferAsprintf(&opt, "jpeg-wan-compression=%s,",
8483 8484
                          virDomainGraphicsSpiceJpegCompressionTypeToString(graphics->data.spice.jpeg));
    if (graphics->data.spice.zlib)
8485
        virBufferAsprintf(&opt, "zlib-glz-wan-compression=%s,",
8486 8487
                          virDomainGraphicsSpiceZlibCompressionTypeToString(graphics->data.spice.zlib));
    if (graphics->data.spice.playback)
8488
        virBufferAsprintf(&opt, "playback-compression=%s,",
J
Ján Tomko 已提交
8489
                          virTristateSwitchTypeToString(graphics->data.spice.playback));
8490
    if (graphics->data.spice.streaming)
8491
        virBufferAsprintf(&opt, "streaming-video=%s,",
8492
                          virDomainGraphicsSpiceStreamingModeTypeToString(graphics->data.spice.streaming));
J
Ján Tomko 已提交
8493
    if (graphics->data.spice.copypaste == VIR_TRISTATE_BOOL_NO)
8494 8495
        virBufferAddLit(&opt, "disable-copy-paste,");

J
Ján Tomko 已提交
8496
    if (graphics->data.spice.filetransfer == VIR_TRISTATE_BOOL_NO) {
8497 8498 8499 8500 8501
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_FILE_XFER_DISABLE)) {
           virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                          _("This QEMU can't disable file transfers through spice"));
            goto error;
        } else {
8502
            virBufferAddLit(&opt, "disable-agent-file-xfer,");
8503 8504
        }
    }
8505

8506
    if (graphics->data.spice.gl == VIR_TRISTATE_BOOL_YES) {
8507 8508 8509 8510 8511 8512 8513 8514
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_GL)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("This QEMU doesn't support spice OpenGL"));
            goto error;
        }

        /* spice.gl is a TristateBool, but qemu expects on/off: use
         * TristateSwitch helper */
8515
        virBufferAsprintf(&opt, "gl=%s,",
8516
                          virTristateSwitchTypeToString(graphics->data.spice.gl));
8517 8518 8519 8520 8521 8522 8523 8524

        if (graphics->data.spice.rendernode) {
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_RENDERNODE)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("This QEMU doesn't support spice OpenGL rendernode"));
                goto error;
            }

8525 8526 8527
            virBufferAddLit(&opt, "rendernode=");
            virQEMUBuildBufferEscapeComma(&opt, graphics->data.spice.rendernode);
            virBufferAddLit(&opt, ",");
8528
        }
8529 8530
    }

8531 8532 8533
    /* Turn on seamless migration unconditionally. If migration destination
     * doesn't support it, it fallbacks to previous migration algorithm silently. */
    virBufferAddLit(&opt, "seamless-migration=on,");
8534

8535 8536
    virBufferTrim(&opt, ",", -1);

8537
    virCommandAddArg(cmd, "-spice");
P
Pavel Hrdina 已提交
8538
    virCommandAddArgBuffer(cmd, &opt);
8539 8540 8541 8542 8543 8544 8545 8546 8547 8548
    if (graphics->data.spice.keymap)
        virCommandAddArgList(cmd, "-k",
                             graphics->data.spice.keymap, NULL);
    /* SPICE includes native support for tunnelling audio, so we
     * set the audio backend to point at SPICE's own driver
     */
    virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=spice");

    return 0;

8549
 error:
8550 8551 8552 8553
    virBufferFreeAndReset(&opt);
    return -1;
}

8554

8555 8556 8557
static int
qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
                                        virCommandPtr cmd,
8558 8559
                                        virQEMUCapsPtr qemuCaps,
                                        virDomainGraphicsDefPtr graphics)
8560
{
8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581
    int ret = -1;
    virBuffer opt = VIR_BUFFER_INITIALIZER;

    virBufferAddLit(&opt, "egl-headless");

    if (graphics->data.egl_headless.rendernode) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_EGL_HEADLESS_RENDERNODE)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("This QEMU doesn't support OpenGL rendernode "
                             "with egl-headless graphics type"));
            goto cleanup;
        }

        virBufferAddLit(&opt, ",rendernode=");
        virQEMUBuildBufferEscapeComma(&opt,
                                      graphics->data.egl_headless.rendernode);
    }

    if (virBufferCheckError(&opt) < 0)
        goto cleanup;

8582
    virCommandAddArg(cmd, "-display");
8583
    virCommandAddArgBuffer(cmd, &opt);
8584

8585 8586 8587 8588
    ret = 0;
 cleanup:
    virBufferFreeAndReset(&opt);
    return ret;
8589 8590 8591
}


8592
static int
8593
qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg,
8594
                             virCommandPtr cmd,
8595 8596
                             virDomainDefPtr def,
                             virQEMUCapsPtr qemuCaps)
8597
{
8598
    size_t i;
8599

8600 8601
    for (i = 0; i < def->ngraphics; i++) {
        virDomainGraphicsDefPtr graphics = def->graphics[i];
8602

8603 8604 8605 8606 8607
        switch (graphics->type) {
        case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
            if (qemuBuildGraphicsSDLCommandLine(cfg, cmd,
                                                qemuCaps, graphics) < 0)
                return -1;
8608

8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620
            break;
        case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
            if (qemuBuildGraphicsVNCCommandLine(cfg, cmd,
                                                qemuCaps, graphics) < 0)
                return -1;

            break;
        case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
            if (qemuBuildGraphicsSPICECommandLine(cfg, cmd,
                                                  qemuCaps, graphics) < 0)
                return -1;

8621 8622
            break;
        case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
8623 8624 8625
            if (qemuBuildGraphicsEGLHeadlessCommandLine(cfg, cmd,
                                                        qemuCaps, graphics) < 0)
                return -1;
8626

8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638
            break;
        case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
        case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("unsupported graphics type '%s'"),
                           virDomainGraphicsTypeToString(graphics->type));
            return -1;
        case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
        default:
            virReportEnumRangeError(virDomainGraphicsType, graphics->type);
            return -1;
        }
8639
    }
8640

8641 8642
    return 0;
}
8643

M
Michele Paolino 已提交
8644
static int
8645
qemuInterfaceVhostuserConnect(virQEMUDriverPtr driver,
8646
                              virLogManagerPtr logManager,
8647
                              virSecurityManagerPtr secManager,
8648
                              virCommandPtr cmd,
M
Michele Paolino 已提交
8649 8650
                              virDomainDefPtr def,
                              virDomainNetDefPtr net,
8651
                              virQEMUCapsPtr qemuCaps,
8652
                              char **chardev)
M
Michele Paolino 已提交
8653
{
8654
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
8655
    int ret = -1;
M
Michele Paolino 已提交
8656

8657
    switch ((virDomainChrType)net->data.vhostuser->type) {
M
Michele Paolino 已提交
8658
    case VIR_DOMAIN_CHR_TYPE_UNIX:
8659 8660 8661 8662
        if (!(*chardev = qemuBuildChrChardevStr(logManager, secManager,
                                                cmd, cfg, def,
                                                net->data.vhostuser,
                                                net->info.alias, qemuCaps, 0)))
8663
            goto cleanup;
M
Michele Paolino 已提交
8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680
        break;

    case VIR_DOMAIN_CHR_TYPE_NULL:
    case VIR_DOMAIN_CHR_TYPE_VC:
    case VIR_DOMAIN_CHR_TYPE_PTY:
    case VIR_DOMAIN_CHR_TYPE_DEV:
    case VIR_DOMAIN_CHR_TYPE_FILE:
    case VIR_DOMAIN_CHR_TYPE_PIPE:
    case VIR_DOMAIN_CHR_TYPE_STDIO:
    case VIR_DOMAIN_CHR_TYPE_UDP:
    case VIR_DOMAIN_CHR_TYPE_TCP:
    case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
    case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
    case VIR_DOMAIN_CHR_TYPE_NMDM:
    case VIR_DOMAIN_CHR_TYPE_LAST:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("vhost-user type '%s' not supported"),
8681
                       virDomainChrTypeToString(net->data.vhostuser->type));
8682
        goto cleanup;
M
Michele Paolino 已提交
8683 8684
    }

8685 8686
    ret = 0;
 cleanup:
8687
    virObjectUnref(cfg);
8688
    return ret;
M
Michele Paolino 已提交
8689 8690
}

8691
static int
8692 8693
qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
                              virLogManagerPtr logManager,
8694
                              virSecurityManagerPtr secManager,
8695
                              virCommandPtr cmd,
8696 8697 8698
                              virDomainDefPtr def,
                              virDomainNetDefPtr net,
                              virQEMUCapsPtr qemuCaps,
8699
                              unsigned int bootindex,
8700
                              virNetDevVPortProfileOp vmop,
8701
                              bool standalone,
8702
                              size_t *nnicindexes,
8703
                              int **nicindexes)
8704 8705
{
    int ret = -1;
8706 8707
    char *nic = NULL;
    char *host = NULL;
8708
    char *chardev = NULL;
8709
    int *tapfd = NULL;
8710
    size_t tapfdSize = 0;
8711
    int *vhostfd = NULL;
8712
    size_t vhostfdSize = 0;
8713 8714
    char **tapfdName = NULL;
    char **vhostfdName = NULL;
8715
    virDomainNetType actualType = virDomainNetGetActualType(net);
8716
    virNetDevBandwidthPtr actualBandwidth;
8717
    bool requireNicdev = false;
8718
    size_t i;
8719

8720 8721 8722 8723

    if (!bootindex)
        bootindex = net->info.bootIndex;

8724 8725 8726
    /* Currently nothing besides TAP devices supports multiqueue. */
    if (net->driver.virtio.queues > 0 &&
        !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
8727
          actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
8728
          actualType == VIR_DOMAIN_NET_TYPE_DIRECT ||
8729 8730
          actualType == VIR_DOMAIN_NET_TYPE_ETHERNET ||
          actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER)) {
8731 8732 8733 8734 8735 8736
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Multiqueue network is not supported for: %s"),
                       virDomainNetTypeToString(actualType));
        return -1;
    }

8737
    /* and only TAP devices support nwfilter rules */
8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756
    if (net->filter) {
        virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(net);
        if (!(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
              actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
              actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("filterref is not supported for "
                             "network interfaces of type %s"),
                           virDomainNetTypeToString(actualType));
            return -1;
        }
        if (vport && vport->virtPortType != VIR_NETDEV_VPORT_PROFILE_NONE) {
            /* currently none of the defined virtualport types support iptables */
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("filterref is not supported for "
                             "network interfaces with virtualport type %s"),
                           virNetDevVPortTypeToString(vport->virtPortType));
            return -1;
        }
8757 8758
    }

8759 8760
    if (net->backend.tap &&
        !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
8761 8762
          actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
          actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
8763 8764 8765 8766 8767 8768
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Custom tap device path is not supported for: %s"),
                       virDomainNetTypeToString(actualType));
        return -1;
    }

8769 8770 8771
    switch (actualType) {
    case VIR_DOMAIN_NET_TYPE_NETWORK:
    case VIR_DOMAIN_NET_TYPE_BRIDGE:
8772 8773 8774 8775 8776
        tapfdSize = net->driver.virtio.queues;
        if (!tapfdSize)
            tapfdSize = 1;

        if (VIR_ALLOC_N(tapfd, tapfdSize) < 0 ||
8777
            VIR_ALLOC_N(tapfdName, tapfdSize) < 0)
8778 8779
            goto cleanup;

8780 8781
        memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));

8782
        if (qemuInterfaceBridgeConnect(def, driver, net,
8783
                                       tapfd, &tapfdSize) < 0)
8784
            goto cleanup;
8785 8786 8787
        break;

    case VIR_DOMAIN_NET_TYPE_DIRECT:
8788 8789 8790 8791 8792 8793
        tapfdSize = net->driver.virtio.queues;
        if (!tapfdSize)
            tapfdSize = 1;

        if (VIR_ALLOC_N(tapfd, tapfdSize) < 0 ||
            VIR_ALLOC_N(tapfdName, tapfdSize) < 0)
8794
            goto cleanup;
8795 8796 8797

        memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));

8798 8799
        if (qemuInterfaceDirectConnect(def, driver, net,
                                       tapfd, tapfdSize, vmop) < 0)
8800
            goto cleanup;
8801 8802 8803
        break;

    case VIR_DOMAIN_NET_TYPE_ETHERNET:
8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814
        tapfdSize = net->driver.virtio.queues;
        if (!tapfdSize)
            tapfdSize = 1;

        if (VIR_ALLOC_N(tapfd, tapfdSize) < 0 ||
            VIR_ALLOC_N(tapfdName, tapfdSize) < 0)
            goto cleanup;

        memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));

        if (qemuInterfaceEthernetConnect(def, driver, net,
8815
                                         tapfd, tapfdSize) < 0)
8816
            goto cleanup;
8817 8818 8819
        break;

    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
8820 8821 8822 8823 8824
        /* NET_TYPE_HOSTDEV devices are really hostdev devices, so
         * their commandlines are constructed with other hostdevs.
         */
        ret = 0;
        goto cleanup;
8825 8826 8827
        break;

    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845
        requireNicdev = true;

        if (net->driver.virtio.queues > 1 &&
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_VHOSTUSER_MULTIQUEUE)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("multi-queue is not supported for vhost-user "
                             "with this QEMU binary"));
            goto cleanup;
        }

        if (qemuInterfaceVhostuserConnect(driver, logManager, secManager,
                                          cmd, def, net, qemuCaps, &chardev) < 0)
            goto cleanup;

        if (virNetDevOpenvswitchGetVhostuserIfname(net->data.vhostuser->data.nix.path,
                                                   &net->ifname) < 0)
            goto cleanup;

8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856
        break;

    case VIR_DOMAIN_NET_TYPE_USER:
    case VIR_DOMAIN_NET_TYPE_SERVER:
    case VIR_DOMAIN_NET_TYPE_CLIENT:
    case VIR_DOMAIN_NET_TYPE_MCAST:
    case VIR_DOMAIN_NET_TYPE_INTERNAL:
    case VIR_DOMAIN_NET_TYPE_UDP:
    case VIR_DOMAIN_NET_TYPE_LAST:
        /* nada */
        break;
8857 8858
    }

8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872
    /* For types whose implementations use a netdev on the host, add
     * an entry to nicindexes for passing on to systemd.
    */
    switch ((virDomainNetType)actualType) {
    case VIR_DOMAIN_NET_TYPE_ETHERNET:
    case VIR_DOMAIN_NET_TYPE_NETWORK:
    case VIR_DOMAIN_NET_TYPE_BRIDGE:
    case VIR_DOMAIN_NET_TYPE_DIRECT:
    {
        int nicindex;

        /* network and bridge use a tap device, and direct uses a
         * macvtap device
         */
8873 8874
        if (virQEMUDriverIsPrivileged(driver) && nicindexes && nnicindexes &&
            net->ifname) {
8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886
            if (virNetDevGetIndex(net->ifname, &nicindex) < 0 ||
                VIR_APPEND_ELEMENT(*nicindexes, *nnicindexes, nicindex) < 0)
                goto cleanup;
        }
        break;
    }

    case VIR_DOMAIN_NET_TYPE_USER:
    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
    case VIR_DOMAIN_NET_TYPE_SERVER:
    case VIR_DOMAIN_NET_TYPE_CLIENT:
    case VIR_DOMAIN_NET_TYPE_MCAST:
8887
    case VIR_DOMAIN_NET_TYPE_UDP:
8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903
    case VIR_DOMAIN_NET_TYPE_INTERNAL:
    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
    case VIR_DOMAIN_NET_TYPE_LAST:
       /* These types don't use a network device on the host, but
        * instead use some other type of connection to the emulated
        * device in the qemu process.
        *
        * (Note that hostdev can't be considered as "using a network
        * device", because by the time it is being used, it has been
        * detached from the hostside network driver so it doesn't show
        * up in the list of interfaces on the host - it's just some
        * PCI device.)
        */
       break;
    }

8904 8905 8906 8907
    /* Set bandwidth or warn if requested and not supported. */
    actualBandwidth = virDomainNetGetActualBandwidth(net);
    if (actualBandwidth) {
        if (virNetDevSupportBandwidth(actualType)) {
8908 8909
            if (virNetDevBandwidthSet(net->ifname, actualBandwidth, false,
                                      !virDomainNetTypeSharesHostView(net)) < 0)
8910 8911 8912 8913 8914 8915 8916
                goto cleanup;
        } else {
            VIR_WARN("setting bandwidth on interfaces of "
                     "type '%s' is not implemented yet",
                     virDomainNetTypeToString(actualType));
        }
    }
8917

8918 8919 8920 8921
    if (net->mtu &&
        virNetDevSetMTU(net->ifname, net->mtu) < 0)
        goto cleanup;

8922 8923 8924 8925 8926
    if ((actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
         actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
         actualType == VIR_DOMAIN_NET_TYPE_ETHERNET ||
         actualType == VIR_DOMAIN_NET_TYPE_DIRECT) &&
        !standalone) {
8927 8928
        /* Attempt to use vhost-net mode for these types of
           network device */
8929 8930 8931 8932 8933
        vhostfdSize = net->driver.virtio.queues;
        if (!vhostfdSize)
            vhostfdSize = 1;

        if (VIR_ALLOC_N(vhostfd, vhostfdSize) < 0 ||
8934
            VIR_ALLOC_N(vhostfdName, vhostfdSize))
8935 8936
            goto cleanup;

8937 8938
        memset(vhostfd, -1, vhostfdSize * sizeof(vhostfd[0]));

J
Ján Tomko 已提交
8939
        if (qemuInterfaceOpenVhostNet(def, net, vhostfd, &vhostfdSize) < 0)
8940 8941 8942
            goto cleanup;
    }

8943
    for (i = 0; i < tapfdSize; i++) {
8944 8945
        if (qemuSecuritySetTapFDLabel(driver->securityManager,
                                      def, tapfd[i]) < 0)
M
Michal Privoznik 已提交
8946
            goto cleanup;
8947 8948
        virCommandPassFD(cmd, tapfd[i],
                         VIR_COMMAND_PASS_FD_CLOSE_PARENT);
8949
        if (virAsprintf(&tapfdName[i], "%d", tapfd[i]) < 0)
8950 8951 8952
            goto cleanup;
    }

8953
    for (i = 0; i < vhostfdSize; i++) {
8954 8955
        virCommandPassFD(cmd, vhostfd[i],
                         VIR_COMMAND_PASS_FD_CLOSE_PARENT);
8956
        if (virAsprintf(&vhostfdName[i], "%d", vhostfd[i]) < 0)
8957
            goto cleanup;
8958 8959
    }

8960 8961 8962
    if (chardev)
        virCommandAddArgList(cmd, "-chardev", chardev, NULL);

8963 8964 8965 8966 8967 8968
    if (!(host = qemuBuildHostNetStr(net, driver,
                                     tapfdName, tapfdSize,
                                     vhostfdName, vhostfdSize)))
        goto cleanup;
    virCommandAddArgList(cmd, "-netdev", host, NULL);

8969 8970
    /* Possible combinations:
     *
8971 8972 8973
     *   Old way: -netdev type=tap,id=netdev1 \
     *              -net nic,model=e1000,netdev=netdev1
     *   New way: -netdev type=tap,id=netdev1 -device e1000,id=netdev1
8974
     */
8975
    if (qemuDomainSupportsNicdev(def, net)) {
8976 8977 8978
        if (qemuCommandAddExtDevice(cmd, &net->info) < 0)
            goto cleanup;

8979
        if (!(nic = qemuBuildNicDevStr(def, net, bootindex,
8980
                                       net->driver.virtio.queues, qemuCaps)))
8981 8982
            goto cleanup;
        virCommandAddArgList(cmd, "-device", nic, NULL);
8983
    } else if (!requireNicdev) {
8984 8985 8986
        if (qemuCommandAddExtDevice(cmd, &net->info) < 0)
            goto cleanup;

8987
        if (!(nic = qemuBuildLegacyNicStr(net)))
8988 8989
            goto cleanup;
        virCommandAddArgList(cmd, "-net", nic, NULL);
8990 8991 8992 8993
    } else {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Nicdev support unavailable"));
        goto cleanup;
8994 8995 8996
    }

    ret = 0;
8997
 cleanup:
8998 8999
    if (ret < 0) {
        virErrorPtr saved_err = virSaveLastError();
9000
        virDomainConfNWFilterTeardown(net);
9001 9002 9003
        virSetError(saved_err);
        virFreeError(saved_err);
    }
9004
    for (i = 0; vhostfd && i < vhostfdSize && vhostfd[i] >= 0; i++) {
9005 9006
        if (ret < 0)
            VIR_FORCE_CLOSE(vhostfd[i]);
9007 9008
        if (vhostfdName)
            VIR_FREE(vhostfdName[i]);
9009
    }
9010 9011 9012 9013 9014 9015 9016 9017
    VIR_FREE(vhostfdName);
    for (i = 0; tapfd && i < tapfdSize && tapfd[i] >= 0; i++) {
        if (ret < 0)
            VIR_FORCE_CLOSE(tapfd[i]);
        if (tapfdName)
            VIR_FREE(tapfdName[i]);
    }
    VIR_FREE(tapfdName);
9018
    VIR_FREE(vhostfd);
9019
    VIR_FREE(tapfd);
9020
    VIR_FREE(chardev);
9021
    VIR_FREE(host);
9022
    VIR_FREE(nic);
9023 9024 9025
    return ret;
}

9026 9027

/* NOTE: Not using const virDomainDef here since eventually a call is made
9028
 *       into qemuSecuritySetTapFDLabel which calls it's driver
9029 9030 9031
 *       API domainSetSecurityTapFDLabel that doesn't use the const format.
 */
static int
9032 9033
qemuBuildNetCommandLine(virQEMUDriverPtr driver,
                        virLogManagerPtr logManager,
9034
                        virSecurityManagerPtr secManager,
9035
                        virCommandPtr cmd,
9036 9037 9038 9039 9040 9041
                        virDomainDefPtr def,
                        virQEMUCapsPtr qemuCaps,
                        virNetDevVPortProfileOp vmop,
                        bool standalone,
                        size_t *nnicindexes,
                        int **nicindexes,
9042
                        unsigned int *bootHostdevNet)
9043 9044 9045
{
    size_t i;
    int last_good_net = -1;
9046
    virErrorPtr originalError = NULL;
9047

J
Ján Tomko 已提交
9048
    if (def->nnets) {
9049
        unsigned int bootNet = 0;
9050

9051 9052 9053 9054 9055
        /* convert <boot dev='network'/> to bootindex since we didn't emit -boot n */
        for (i = 0; i < def->os.nBootDevs; i++) {
            if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) {
                bootNet = i + 1;
                break;
9056 9057 9058 9059 9060 9061
            }
        }

        for (i = 0; i < def->nnets; i++) {
            virDomainNetDefPtr net = def->nets[i];

9062
            if (qemuBuildInterfaceCommandLine(driver, logManager, secManager, cmd, def, net,
9063
                                              qemuCaps, bootNet, vmop,
9064
                                              standalone, nnicindexes,
9065
                                              nicindexes) < 0)
9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084
                goto error;

            last_good_net = i;
            /* if this interface is a type='hostdev' interface and we
             * haven't yet added a "bootindex" parameter to an
             * emulated network device, save the bootindex - hostdev
             * interface commandlines will be built later on when we
             * cycle through all the hostdevs, and we'll use it then.
             */
            if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
                *bootHostdevNet == 0) {
                *bootHostdevNet = bootNet;
            }
            bootNet = 0;
        }
    }
    return 0;

 error:
9085 9086 9087
    /* free up any resources in the network driver
     * but don't overwrite the original error */
    originalError = virSaveLastError();
9088 9089
    for (i = 0; last_good_net != -1 && i <= last_good_net; i++)
        virDomainConfNWFilterTeardown(def->nets[i]);
9090 9091
    virSetError(originalError);
    virFreeError(originalError);
9092 9093 9094 9095
    return -1;
}


9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121
static const char *
qemuBuildSmartcardFindCCIDController(const virDomainDef *def,
                                     const virDomainSmartcardDef *smartcard)
{
    size_t i;

    /* Should never happen. But doesn't hurt to check. */
    if (smartcard->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID)
        return NULL;

    for (i = 0; i < def->ncontrollers; i++) {
        const virDomainControllerDef *tmp = def->controllers[i];

        if (tmp->type != VIR_DOMAIN_CONTROLLER_TYPE_CCID)
            continue;

        if (tmp->idx != smartcard->info.addr.ccid.controller)
            continue;

        return tmp->info.alias;
    }

    return NULL;
}


9122 9123
static int
qemuBuildSmartcardCommandLine(virLogManagerPtr logManager,
9124
                              virSecurityManagerPtr secManager,
9125
                              virCommandPtr cmd,
9126
                              virQEMUDriverConfigPtr cfg,
9127
                              const virDomainDef *def,
9128 9129
                              virQEMUCapsPtr qemuCaps,
                              bool chardevStdioLogd)
9130 9131 9132 9133 9134 9135
{
    size_t i;
    virDomainSmartcardDefPtr smartcard;
    char *devstr;
    virBuffer opt = VIR_BUFFER_INITIALIZER;
    const char *database;
9136
    const char *contAlias = NULL;
9137 9138
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9139 9140
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161

    if (!def->nsmartcards)
        return 0;

    smartcard = def->smartcards[0];

    /* -device usb-ccid was already emitted along with other
     * controllers.  For now, qemu handles only one smartcard.  */
    if (def->nsmartcards > 1 ||
        smartcard->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID ||
        smartcard->info.addr.ccid.controller != 0 ||
        smartcard->info.addr.ccid.slot != 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("this QEMU binary lacks multiple smartcard "
                         "support"));
        virBufferFreeAndReset(&opt);
        return -1;
    }

    switch (smartcard->type) {
    case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
9162
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_EMULATED)) {
9163 9164 9165 9166 9167 9168 9169 9170 9171 9172
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this QEMU binary lacks smartcard host "
                             "mode support"));
            return -1;
        }

        virBufferAddLit(&opt, "ccid-card-emulated,backend=nss-emulated");
        break;

    case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
9173
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_EMULATED)) {
9174 9175 9176 9177 9178 9179 9180 9181
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this QEMU binary lacks smartcard host "
                             "mode support"));
            return -1;
        }

        virBufferAddLit(&opt, "ccid-card-emulated,backend=certificates");
        for (i = 0; i < VIR_DOMAIN_SMARTCARD_NUM_CERTIFICATES; i++) {
9182 9183
            virBufferAsprintf(&opt, ",cert%zu=", i + 1);
            virQEMUBuildBufferEscapeComma(&opt, smartcard->data.cert.file[i]);
9184 9185 9186 9187 9188 9189
        }
        if (smartcard->data.cert.database) {
            database = smartcard->data.cert.database;
        } else {
            database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
        }
9190 9191
        virBufferAddLit(&opt, ",db=");
        virQEMUBuildBufferEscapeComma(&opt, database);
9192 9193 9194
        break;

    case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
9195
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_PASSTHRU)) {
9196 9197 9198 9199 9200 9201
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this QEMU binary lacks smartcard "
                             "passthrough mode support"));
            return -1;
        }

9202 9203
        if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                              cmd, cfg, def,
9204
                                              smartcard->data.passthru,
9205
                                              smartcard->info.alias,
9206
                                              qemuCaps, cdevflags))) {
9207 9208 9209
            virBufferFreeAndReset(&opt);
            return -1;
        }
9210
        virCommandAddArg(cmd, "-chardev");
9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224
        virCommandAddArg(cmd, devstr);
        VIR_FREE(devstr);

        virBufferAsprintf(&opt, "ccid-card-passthru,chardev=char%s",
                          smartcard->info.alias);
        break;

    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected smartcard type %d"),
                       smartcard->type);
        virBufferFreeAndReset(&opt);
        return -1;
    }
9225 9226 9227 9228 9229 9230 9231 9232 9233

    if (!(contAlias = qemuBuildSmartcardFindCCIDController(def,
                                                           smartcard))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unable to find controller for %s"),
                       smartcard->info.alias);
        return -1;
    }

9234
    virCommandAddArg(cmd, "-device");
9235
    virBufferAsprintf(&opt, ",id=%s,bus=%s.0", smartcard->info.alias, contAlias);
9236 9237 9238 9239 9240 9241
    virCommandAddArgBuffer(cmd, &opt);

    return 0;
}


9242
static char *
9243 9244 9245
qemuBuildShmemDevLegacyStr(virDomainDefPtr def,
                           virDomainShmemDefPtr shmem,
                           virQEMUCapsPtr qemuCaps)
9246 9247 9248 9249 9250 9251 9252
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("ivshmem device is not supported "
                         "with this QEMU binary"));
9253
        return NULL;
9254 9255 9256
    }

    virBufferAddLit(&buf, "ivshmem");
9257 9258
    virBufferAsprintf(&buf, ",id=%s", shmem->info.alias);

9259
    if (shmem->size)
M
Martin Kletzander 已提交
9260
        virBufferAsprintf(&buf, ",size=%llum", shmem->size >> 20);
9261 9262

    if (!shmem->server.enabled) {
9263
        virBufferAsprintf(&buf, ",shm=%s", shmem->name);
9264
    } else {
9265
        virBufferAsprintf(&buf, ",chardev=char%s", shmem->info.alias);
9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281
        if (shmem->msi.enabled) {
            virBufferAddLit(&buf, ",msi=on");
            if (shmem->msi.vectors)
                virBufferAsprintf(&buf, ",vectors=%u", shmem->msi.vectors);
            if (shmem->msi.ioeventfd)
                virBufferAsprintf(&buf, ",ioeventfd=%s",
                                  virTristateSwitchTypeToString(shmem->msi.ioeventfd));
        }
    }

    if (qemuBuildDeviceAddressStr(&buf, def, &shmem->info, qemuCaps) < 0)
        goto error;

    if (virBufferCheckError(&buf) < 0)
        goto error;

9282
    return virBufferContentAndReset(&buf);
9283 9284 9285

 error:
    virBufferFreeAndReset(&buf);
9286 9287 9288
    return NULL;
}

9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336
char *
qemuBuildShmemDevStr(virDomainDefPtr def,
                     virDomainShmemDefPtr shmem,
                     virQEMUCapsPtr qemuCaps)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if ((shmem->model == VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN &&
         !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM_PLAIN)) ||
        (shmem->model == VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL &&
         !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL))) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("shmem model '%s' is not supported "
                             "by this QEMU binary"),
                           virDomainShmemModelTypeToString(shmem->model));
        return NULL;
    }

    virBufferAdd(&buf, virDomainShmemModelTypeToString(shmem->model), -1);
    virBufferAsprintf(&buf, ",id=%s", shmem->info.alias);

    if (shmem->server.enabled)
        virBufferAsprintf(&buf, ",chardev=char%s", shmem->info.alias);
    else
        virBufferAsprintf(&buf, ",memdev=shmmem-%s", shmem->info.alias);

    if (shmem->msi.vectors)
        virBufferAsprintf(&buf, ",vectors=%u", shmem->msi.vectors);
    if (shmem->msi.ioeventfd) {
        virBufferAsprintf(&buf, ",ioeventfd=%s",
                          virTristateSwitchTypeToString(shmem->msi.ioeventfd));
    }

    if (qemuBuildDeviceAddressStr(&buf, def, &shmem->info, qemuCaps) < 0) {
        virBufferFreeAndReset(&buf);
        return NULL;
    }

    if (virBufferCheckError(&buf) < 0)
        return NULL;

    return virBufferContentAndReset(&buf);
}


virJSONValuePtr
qemuBuildShmemBackendMemProps(virDomainShmemDefPtr shmem)
{
9337
    char *mem_alias = NULL;
9338 9339 9340 9341 9342 9343
    char *mem_path = NULL;
    virJSONValuePtr ret = NULL;

    if (virAsprintf(&mem_path, "/dev/shm/%s", shmem->name) < 0)
        return NULL;

9344
    if (virAsprintf(&mem_alias, "shmmem-%s", shmem->info.alias) < 0)
9345 9346
        goto cleanup;

9347 9348 9349 9350 9351
    qemuMonitorCreateObjectProps(&ret, "memory-backend-file", mem_alias,
                                 "s:mem-path", mem_path,
                                 "U:size", shmem->size,
                                 "b:share", true,
                                 NULL);
9352

9353 9354 9355
 cleanup:
    VIR_FREE(mem_alias);
    VIR_FREE(mem_path);
9356 9357 9358 9359
    return ret;
}


9360
static int
9361
qemuBuildShmemCommandLine(virLogManagerPtr logManager,
9362
                          virSecurityManagerPtr secManager,
9363
                          virCommandPtr cmd,
9364
                          virQEMUDriverConfigPtr cfg,
9365 9366
                          virDomainDefPtr def,
                          virDomainShmemDefPtr shmem,
9367 9368
                          virQEMUCapsPtr qemuCaps,
                          bool chardevStdioLogd)
9369
{
9370 9371
    virJSONValuePtr memProps = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
9372
    char *devstr = NULL;
9373
    int rc;
9374 9375
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9376 9377
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9378

9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404
    if (shmem->size) {
        /*
         * Thanks to our parsing code, we have a guarantee that the
         * size is power of two and is at least a mebibyte in size.
         * But because it may change in the future, the checks are
         * doubled in here.
         */
        if (shmem->size & (shmem->size - 1)) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("shmem size must be a power of two"));
            return -1;
        }
        if (shmem->size < 1024 * 1024) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("shmem size must be at least 1 MiB (1024 KiB)"));
            return -1;
        }
    }

    if (shmem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("only 'pci' addresses are supported for the "
                         "shared memory device"));
        return -1;
    }

9405 9406 9407 9408 9409
    switch ((virDomainShmemModel)shmem->model) {
    case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
        devstr = qemuBuildShmemDevLegacyStr(def, shmem, qemuCaps);
        break;

9410
    case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
9411
        if (!(memProps = qemuBuildShmemBackendMemProps(shmem)))
9412 9413
            return -1;

9414 9415 9416 9417 9418 9419 9420 9421
        rc = virQEMUBuildObjectCommandlineFromJSON(&buf, memProps);
        virJSONValueFree(memProps);

        if (rc < 0)
            return -1;

        virCommandAddArg(cmd, "-object");
        virCommandAddArgBuffer(cmd, &buf);
9422

M
Marc Hartmayer 已提交
9423
        ATTRIBUTE_FALLTHROUGH;
9424
    case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL:
9425
        devstr = qemuBuildShmemDevStr(def, shmem, qemuCaps);
9426 9427
        break;

9428 9429 9430 9431 9432
    case VIR_DOMAIN_SHMEM_MODEL_LAST:
        break;
    }

    if (!devstr)
9433
        return -1;
9434 9435 9436 9437 9438 9439

    if (qemuCommandAddExtDevice(cmd, &shmem->info) < 0) {
        VIR_FREE(devstr);
        return -1;
    }

9440 9441
    virCommandAddArgList(cmd, "-device", devstr, NULL);
    VIR_FREE(devstr);
9442 9443

    if (shmem->server.enabled) {
9444 9445
        devstr = qemuBuildChrChardevStr(logManager, secManager,
                                        cmd, cfg, def,
9446
                                        &shmem->server.chr,
9447 9448
                                        shmem->info.alias, qemuCaps,
                                        cdevflags);
9449
        if (!devstr)
9450 9451
            return -1;

9452
        virCommandAddArgList(cmd, "-chardev", devstr, NULL);
9453 9454 9455 9456 9457 9458
        VIR_FREE(devstr);
    }

    return 0;
}

9459 9460 9461 9462 9463

static virQEMUCapsFlags
qemuChrSerialTargetModelToCaps(virDomainChrSerialTargetModel targetModel)
{
    switch (targetModel) {
9464 9465
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
        return QEMU_CAPS_DEVICE_ISA_SERIAL;
9466 9467 9468 9469
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_USB_SERIAL:
        return QEMU_CAPS_DEVICE_USB_SERIAL;
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PCI_SERIAL:
        return QEMU_CAPS_DEVICE_PCI_SERIAL;
9470 9471
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
        return QEMU_CAPS_DEVICE_SPAPR_VTY;
9472 9473 9474 9475
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
        return QEMU_CAPS_DEVICE_SCLPCONSOLE;
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
        return QEMU_CAPS_DEVICE_SCLPLMCONSOLE;
9476
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
9477
        return QEMU_CAPS_DEVICE_PL011;
9478
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
9479 9480 9481 9482 9483 9484 9485 9486 9487
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
        break;
    }

    return 0;
}


9488 9489
static int
qemuBuildChrDeviceCommandLine(virCommandPtr cmd,
9490
                              const virDomainDef *def,
9491 9492 9493 9494 9495 9496 9497 9498 9499
                              virDomainChrDefPtr chr,
                              virQEMUCapsPtr qemuCaps)
{
    char *devstr = NULL;

    if (qemuBuildChrDeviceStr(&devstr, def, chr, qemuCaps) < 0)
        return -1;

    virCommandAddArgList(cmd, "-device", devstr, NULL);
9500
    VIR_FREE(devstr);
9501 9502 9503
    return 0;
}

9504

9505 9506 9507 9508
static bool
qemuChrIsPlatformDevice(const virDomainDef *def,
                        virDomainChrDefPtr chr)
{
S
Stefan Schallenberg 已提交
9509 9510 9511
    if (def->os.arch == VIR_ARCH_ARMV6L ||
        def->os.arch == VIR_ARCH_ARMV7L ||
        def->os.arch == VIR_ARCH_AARCH64) {
9512 9513

        /* pl011 (used on mach-virt) is a platform device */
9514
        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
9515 9516
            chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM &&
            chr->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011) {
9517
            return true;
9518
        }
9519 9520
    }

9521 9522 9523 9524 9525 9526 9527 9528 9529 9530
    if (ARCH_IS_RISCV(def->os.arch)) {

        /* 16550a (used by riscv/virt guests) is a platform device */
        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
            chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM &&
            chr->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A) {
            return true;
        }
    }

9531 9532 9533 9534 9535 9536 9537 9538
    /* If we got all the way here and we're still stuck with the default
     * target type for a serial device, it means we have no clue what kind of
     * device we're talking about and we must treat it as a platform device. */
    if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
        chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE) {
        return true;
    }

9539 9540 9541 9542
    return false;
}


9543 9544
static int
qemuBuildSerialCommandLine(virLogManagerPtr logManager,
9545
                           virSecurityManagerPtr secManager,
9546
                           virCommandPtr cmd,
9547
                           virQEMUDriverConfigPtr cfg,
9548
                           const virDomainDef *def,
9549 9550
                           virQEMUCapsPtr qemuCaps,
                           bool chardevStdioLogd)
9551 9552 9553
{
    size_t i;
    bool havespice = false;
9554 9555
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9556 9557
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569

    if (def->nserials) {
        for (i = 0; i < def->ngraphics && !havespice; i++) {
            if (def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
                havespice = true;
        }
    }

    for (i = 0; i < def->nserials; i++) {
        virDomainChrDefPtr serial = def->serials[i];
        char *devstr;

9570
        if (serial->source->type == VIR_DOMAIN_CHR_TYPE_SPICEPORT && !havespice)
9571 9572
            continue;

9573 9574
        if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                              cmd, cfg, def,
9575 9576
                                              serial->source,
                                              serial->info.alias,
9577
                                              qemuCaps, cdevflags)))
9578 9579 9580 9581 9582
            return -1;
        virCommandAddArg(cmd, "-chardev");
        virCommandAddArg(cmd, devstr);
        VIR_FREE(devstr);

9583 9584
        /* If the device is not a platform device, build the devstr */
        if (!qemuChrIsPlatformDevice(def, serial)) {
9585 9586 9587
            if (qemuBuildChrDeviceCommandLine(cmd, def, serial, qemuCaps) < 0)
                return -1;
        } else {
9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598
            virQEMUCapsFlags caps;

            caps = qemuChrSerialTargetModelToCaps(serial->targetModel);

            if (caps && !virQEMUCapsGet(qemuCaps, caps)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("'%s' is not supported in this QEMU binary"),
                               virDomainChrSerialTargetModelTypeToString(serial->targetModel));
                return -1;
            }

9599
            virCommandAddArg(cmd, "-serial");
9600
            virCommandAddArgFormat(cmd, "chardev:char%s", serial->info.alias);
9601 9602 9603 9604 9605 9606 9607
        }
    }

    return 0;
}


9608 9609
static int
qemuBuildParallelsCommandLine(virLogManagerPtr logManager,
9610
                              virSecurityManagerPtr secManager,
9611
                              virCommandPtr cmd,
9612
                              virQEMUDriverConfigPtr cfg,
9613
                              const virDomainDef *def,
9614 9615
                              virQEMUCapsPtr qemuCaps,
                              bool chardevStdioLogd)
9616 9617
{
    size_t i;
9618 9619
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9620 9621
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9622 9623 9624 9625 9626

    for (i = 0; i < def->nparallels; i++) {
        virDomainChrDefPtr parallel = def->parallels[i];
        char *devstr;

9627 9628
        if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                              cmd, cfg, def,
9629 9630
                                              parallel->source,
                                              parallel->info.alias,
9631
                                              qemuCaps, cdevflags)))
9632 9633 9634 9635
            return -1;
        virCommandAddArg(cmd, "-chardev");
        virCommandAddArg(cmd, devstr);
        VIR_FREE(devstr);
9636

9637 9638 9639
        if (qemuBuildChrDeviceCommandLine(cmd, def, parallel,
                                          qemuCaps) < 0)
            return -1;
9640 9641 9642 9643 9644 9645
    }

    return 0;
}


9646 9647
static int
qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
9648
                             virSecurityManagerPtr secManager,
9649
                             virCommandPtr cmd,
9650
                             virQEMUDriverConfigPtr cfg,
9651
                             const virDomainDef *def,
9652 9653
                             virQEMUCapsPtr qemuCaps,
                             bool chardevStdioLogd)
9654 9655
{
    size_t i;
9656 9657
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9658 9659
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9660 9661 9662 9663 9664 9665 9666

    for (i = 0; i < def->nchannels; i++) {
        virDomainChrDefPtr channel = def->channels[i];
        char *devstr;

        switch (channel->targetType) {
        case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
9667 9668
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9669
                                                  channel->source,
9670
                                                  channel->info.alias,
9671
                                                  qemuCaps, cdevflags)))
9672
                return -1;
9673
            virCommandAddArg(cmd, "-chardev");
9674 9675 9676 9677 9678 9679 9680 9681 9682 9683
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);

            if (qemuBuildChrDeviceStr(&devstr, def, channel, qemuCaps) < 0)
                return -1;
            virCommandAddArgList(cmd, "-netdev", devstr, NULL);
            VIR_FREE(devstr);
            break;

        case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
9684 9685
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9686 9687
                                                  channel->source,
                                                  channel->info.alias,
9688
                                                  qemuCaps, cdevflags)))
9689 9690 9691 9692
                return -1;
            virCommandAddArg(cmd, "-chardev");
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703

            if (qemuBuildChrDeviceCommandLine(cmd, def, channel, qemuCaps) < 0)
                return -1;
            break;
        }
    }

    return 0;
}


9704 9705
static int
qemuBuildConsoleCommandLine(virLogManagerPtr logManager,
9706
                            virSecurityManagerPtr secManager,
9707
                            virCommandPtr cmd,
9708
                            virQEMUDriverConfigPtr cfg,
9709
                            const virDomainDef *def,
9710 9711
                            virQEMUCapsPtr qemuCaps,
                            bool chardevStdioLogd)
9712 9713
{
    size_t i;
9714 9715
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9716 9717
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9718 9719 9720 9721 9722 9723 9724 9725

    /* Explicit console devices */
    for (i = 0; i < def->nconsoles; i++) {
        virDomainChrDefPtr console = def->consoles[i];
        char *devstr;

        switch (console->targetType) {
        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLP:
9726
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCLPCONSOLE)) {
9727
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9728
                               _("sclpconsole is not supported in this QEMU binary"));
9729 9730 9731
                return -1;
            }

9732 9733
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9734 9735
                                                  console->source,
                                                  console->info.alias,
9736
                                                  qemuCaps, cdevflags)))
9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752
                return -1;
            virCommandAddArg(cmd, "-chardev");
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);

            if (qemuBuildChrDeviceCommandLine(cmd, def, console, qemuCaps) < 0)
                return -1;
            break;

        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLPLM:
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCLPLMCONSOLE)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("sclplmconsole is not supported in this QEMU binary"));
                return -1;
            }

9753 9754
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9755
                                                  console->source,
9756
                                                  console->info.alias,
9757
                                                  qemuCaps, cdevflags)))
9758
                return -1;
9759
            virCommandAddArg(cmd, "-chardev");
9760 9761 9762 9763 9764 9765 9766 9767
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);

            if (qemuBuildChrDeviceCommandLine(cmd, def, console, qemuCaps) < 0)
                return -1;
            break;

        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO:
9768 9769
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9770
                                                  console->source,
9771
                                                  console->info.alias,
9772
                                                  qemuCaps, cdevflags)))
9773
                return -1;
9774
            virCommandAddArg(cmd, "-chardev");
9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);

            if (qemuBuildChrDeviceCommandLine(cmd, def, console, qemuCaps) < 0)
                return -1;
            break;

        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
            break;

        default:
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("unsupported console target type %s"),
                           NULLSTR(virDomainChrConsoleTargetTypeToString(console->targetType)));
            return -1;
        }
    }

    return 0;
}


9797 9798 9799 9800 9801 9802 9803 9804 9805 9806 9807 9808 9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842 9843 9844 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860
char *
qemuBuildRedirdevDevStr(const virDomainDef *def,
                        virDomainRedirdevDefPtr dev,
                        virQEMUCapsPtr qemuCaps)
{
    size_t i;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virDomainRedirFilterDefPtr redirfilter = def->redirfilter;

    if (dev->bus != VIR_DOMAIN_REDIRDEV_BUS_USB) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Redirection bus %s is not supported by QEMU"),
                       virDomainRedirdevBusTypeToString(dev->bus));
        goto error;
    }

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_REDIR)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("USB redirection is not supported "
                         "by this version of QEMU"));
        goto error;
    }

    virBufferAsprintf(&buf, "usb-redir,chardev=char%s,id=%s",
                      dev->info.alias, dev->info.alias);

    if (redirfilter && redirfilter->nusbdevs) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_REDIR_FILTER)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("USB redirection filter is not "
                             "supported by this version of QEMU"));
            goto error;
        }

        virBufferAddLit(&buf, ",filter=");

        for (i = 0; i < redirfilter->nusbdevs; i++) {
            virDomainRedirFilterUSBDevDefPtr usbdev = redirfilter->usbdevs[i];
            if (usbdev->usbClass >= 0)
                virBufferAsprintf(&buf, "0x%02X:", usbdev->usbClass);
            else
                virBufferAddLit(&buf, "-1:");

            if (usbdev->vendor >= 0)
                virBufferAsprintf(&buf, "0x%04X:", usbdev->vendor);
            else
                virBufferAddLit(&buf, "-1:");

            if (usbdev->product >= 0)
                virBufferAsprintf(&buf, "0x%04X:", usbdev->product);
            else
                virBufferAddLit(&buf, "-1:");

            if (usbdev->version >= 0)
                virBufferAsprintf(&buf, "0x%04X:", usbdev->version);
            else
                virBufferAddLit(&buf, "-1:");

            virBufferAsprintf(&buf, "%u", usbdev->allow);
            if (i < redirfilter->nusbdevs -1)
                virBufferAddLit(&buf, "|");
        }
    }

9861
    if (dev->info.bootIndex)
9862
        virBufferAsprintf(&buf, ",bootindex=%u", dev->info.bootIndex);
9863 9864 9865 9866 9867 9868 9869 9870 9871 9872 9873 9874 9875 9876 9877 9878 9879

    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
        goto error;

    if (virBufferCheckError(&buf) < 0)
        goto error;

    return virBufferContentAndReset(&buf);

 error:
    virBufferFreeAndReset(&buf);
    return NULL;
}


static int
qemuBuildRedirdevCommandLine(virLogManagerPtr logManager,
9880
                             virSecurityManagerPtr secManager,
9881
                             virCommandPtr cmd,
9882
                             virQEMUDriverConfigPtr cfg,
9883
                             const virDomainDef *def,
9884 9885
                             virQEMUCapsPtr qemuCaps,
                             bool chardevStdioLogd)
9886 9887
{
    size_t i;
9888 9889
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9890 9891
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9892 9893 9894 9895 9896

    for (i = 0; i < def->nredirdevs; i++) {
        virDomainRedirdevDefPtr redirdev = def->redirdevs[i];
        char *devstr;

9897 9898
        if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                              cmd, cfg, def,
9899
                                              redirdev->source,
9900
                                              redirdev->info.alias,
9901
                                              qemuCaps, cdevflags))) {
9902 9903 9904
            return -1;
        }

9905
        virCommandAddArg(cmd, "-chardev");
9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919
        virCommandAddArg(cmd, devstr);
        VIR_FREE(devstr);

        virCommandAddArg(cmd, "-device");
        if (!(devstr = qemuBuildRedirdevDevStr(def, redirdev, qemuCaps)))
            return -1;
        virCommandAddArg(cmd, devstr);
        VIR_FREE(devstr);
    }

    return 0;
}


9920
static void
9921
qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
9922
                                 virDomainDefPtr def)
9923 9924 9925 9926 9927 9928
{
    virDomainLoaderDefPtr loader = def->os.loader;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    int unit = 0;

    if (!loader)
9929
        return;
9930 9931 9932 9933 9934 9935 9936 9937 9938

    switch ((virDomainLoader) loader->type) {
    case VIR_DOMAIN_LOADER_TYPE_ROM:
        virCommandAddArg(cmd, "-bios");
        virCommandAddArg(cmd, loader->path);
        break;

    case VIR_DOMAIN_LOADER_TYPE_PFLASH:

M
Michal Privoznik 已提交
9939 9940 9941 9942 9943 9944 9945
        if (loader->secure == VIR_TRISTATE_BOOL_YES) {
            virCommandAddArgList(cmd,
                                 "-global",
                                 "driver=cfi.pflash01,property=secure,value=on",
                                 NULL);
        }

9946 9947 9948
        virBufferAddLit(&buf, "file=");
        virQEMUBuildBufferEscapeComma(&buf, loader->path);
        virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit);
9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960
        unit++;

        if (loader->readonly) {
            virBufferAsprintf(&buf, ",readonly=%s",
                              virTristateSwitchTypeToString(loader->readonly));
        }

        virCommandAddArg(cmd, "-drive");
        virCommandAddArgBuffer(cmd, &buf);

        if (loader->nvram) {
            virBufferFreeAndReset(&buf);
9961 9962 9963
            virBufferAddLit(&buf, "file=");
            virQEMUBuildBufferEscapeComma(&buf, loader->nvram);
            virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit);
9964 9965 9966 9967 9968 9969

            virCommandAddArg(cmd, "-drive");
            virCommandAddArgBuffer(cmd, &buf);
        }
        break;

9970
    case VIR_DOMAIN_LOADER_TYPE_NONE:
9971 9972 9973 9974 9975 9976 9977 9978
    case VIR_DOMAIN_LOADER_TYPE_LAST:
        /* nada */
        break;
    }

    virBufferFreeAndReset(&buf);
}

J
John Ferlan 已提交
9979

J
John Ferlan 已提交
9980 9981
static char *
qemuBuildTPMDevStr(const virDomainDef *def,
9982
                   virQEMUCapsPtr qemuCaps)
J
John Ferlan 已提交
9983 9984 9985 9986
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    const virDomainTPMDef *tpm = def->tpm;
    const char *model = virDomainTPMModelTypeToString(tpm->model);
9987
    virQEMUCapsFlags flag;
J
John Ferlan 已提交
9988

9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002
    switch (tpm->model) {
    case VIR_DOMAIN_TPM_MODEL_TIS:
        flag = QEMU_CAPS_DEVICE_TPM_TIS;
        break;
    case VIR_DOMAIN_TPM_MODEL_CRB:
        flag = QEMU_CAPS_DEVICE_TPM_CRB;
        break;
    case VIR_DOMAIN_TPM_MODEL_LAST:
    default:
        virReportEnumRangeError(virDomainTPMModel, tpm->model);
        goto error;
    }

    if (!virQEMUCapsGet(qemuCaps, flag)) {
J
John Ferlan 已提交
10003 10004 10005
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("The QEMU executable %s does not support TPM "
                       "model %s"),
10006
                       def->emulator, model);
J
John Ferlan 已提交
10007 10008 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023
        goto error;
    }

    virBufferAsprintf(&buf, "%s,tpmdev=tpm-%s,id=%s",
                      model, tpm->info.alias, tpm->info.alias);

    if (virBufferCheckError(&buf) < 0)
        goto error;

    return virBufferContentAndReset(&buf);

 error:
    virBufferFreeAndReset(&buf);
    return NULL;
}


10024 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048
/* this function is exported so that tests can mock the FDs */
int
qemuBuildTPMOpenBackendFDs(const char *tpmdev,
                           const char *cancel_path,
                           int *tpmfd,
                           int *cancelfd)
{
    if ((*tpmfd = open(tpmdev, O_RDWR)) < 0) {
        virReportSystemError(errno, _("Could not open TPM device %s"),
                             tpmdev);
        return -1;
    }

    if ((*cancelfd = open(cancel_path, O_WRONLY)) < 0) {
        virReportSystemError(errno,
                             _("Could not open TPM device's cancel "
                               "path %s"), cancel_path);
        VIR_FORCE_CLOSE(*tpmfd);
        return -1;
    }

    return 0;
}


J
John Ferlan 已提交
10049 10050 10051 10052 10053
static char *
qemuBuildTPMBackendStr(const virDomainDef *def,
                       virCommandPtr cmd,
                       virQEMUCapsPtr qemuCaps,
                       int *tpmfd,
10054 10055
                       int *cancelfd,
                       char **chardev)
J
John Ferlan 已提交
10056 10057 10058
{
    const virDomainTPMDef *tpm = def->tpm;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
10059
    const char *type = NULL;
10060 10061 10062
    char *cancel_path = NULL;
    char *devset = NULL;
    char *cancelset = NULL;
J
John Ferlan 已提交
10063 10064 10065 10066 10067
    const char *tpmdev;

    *tpmfd = -1;
    *cancelfd = -1;

10068 10069 10070 10071 10072 10073 10074 10075 10076
    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
    case VIR_DOMAIN_TPM_TYPE_EMULATOR:
        type = virDomainTPMBackendTypeToString(tpm->type);
        break;
    case VIR_DOMAIN_TPM_TYPE_LAST:
        goto error;
    }

J
John Ferlan 已提交
10077 10078 10079 10080 10081 10082 10083 10084 10085 10086 10087
    virBufferAsprintf(&buf, "%s,id=tpm-%s", type, tpm->info.alias);

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_PASSTHROUGH))
            goto no_support;

        tpmdev = tpm->data.passthrough.source.data.file.path;
        if (!(cancel_path = virTPMCreateCancelPath(tpmdev)))
            goto error;

10088 10089
        if (qemuBuildTPMOpenBackendFDs(tpmdev, cancel_path, tpmfd, cancelfd) < 0)
            goto error;
J
John Ferlan 已提交
10090

10091 10092 10093 10094 10095 10096
        virCommandPassFD(cmd, *tpmfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
        virCommandPassFD(cmd, *cancelfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);

        if (!(devset = qemuVirCommandGetDevSet(cmd, *tpmfd)) ||
            !(cancelset = qemuVirCommandGetDevSet(cmd, *cancelfd)))
            goto error;
J
John Ferlan 已提交
10097 10098

        virBufferAddLit(&buf, ",path=");
10099
        virQEMUBuildBufferEscapeComma(&buf, devset);
J
John Ferlan 已提交
10100 10101

        virBufferAddLit(&buf, ",cancel-path=");
10102
        virQEMUBuildBufferEscapeComma(&buf, cancelset);
J
John Ferlan 已提交
10103 10104

        VIR_FREE(devset);
10105
        VIR_FREE(cancelset);
J
John Ferlan 已提交
10106 10107 10108
        VIR_FREE(cancel_path);

        break;
10109
    case VIR_DOMAIN_TPM_TYPE_EMULATOR:
10110 10111 10112 10113 10114 10115 10116 10117 10118 10119
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_EMULATOR))
            goto no_support;

        virBufferAddLit(&buf, ",chardev=chrtpm");

        if (virAsprintf(chardev, "socket,id=chrtpm,path=%s",
                        tpm->data.emulator.source.data.nix.path) < 0)
            goto error;

        break;
J
John Ferlan 已提交
10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131 10132
    case VIR_DOMAIN_TPM_TYPE_LAST:
        goto error;
    }

    if (virBufferCheckError(&buf) < 0)
        goto error;

    return virBufferContentAndReset(&buf);

 no_support:
    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                   _("The QEMU executable %s does not support TPM "
                     "backend type %s"),
10133
                   def->emulator, type);
J
John Ferlan 已提交
10134 10135 10136 10137 10138 10139 10140 10141 10142 10143

 error:
    VIR_FREE(devset);
    VIR_FREE(cancel_path);

    virBufferFreeAndReset(&buf);
    return NULL;
}


10144
static int
10145 10146 10147
qemuBuildTPMCommandLine(virCommandPtr cmd,
                        const virDomainDef *def,
                        virQEMUCapsPtr qemuCaps)
10148 10149
{
    char *optstr;
10150
    char *chardev = NULL;
10151 10152 10153
    int tpmfd = -1;
    int cancelfd = -1;
    char *fdset;
10154

10155 10156 10157 10158
    if (!def->tpm)
        return 0;

    if (!(optstr = qemuBuildTPMBackendStr(def, cmd, qemuCaps,
10159 10160
                                          &tpmfd, &cancelfd,
                                          &chardev)))
10161 10162 10163 10164 10165
        return -1;

    virCommandAddArgList(cmd, "-tpmdev", optstr, NULL);
    VIR_FREE(optstr);

10166 10167 10168 10169 10170
    if (chardev) {
        virCommandAddArgList(cmd, "-chardev", chardev, NULL);
        VIR_FREE(chardev);
    }

10171 10172 10173 10174 10175 10176 10177 10178 10179 10180 10181 10182 10183 10184 10185 10186 10187 10188
    if (tpmfd >= 0) {
        fdset = qemuVirCommandGetFDSet(cmd, tpmfd);
        if (!fdset)
            return -1;

        virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
        VIR_FREE(fdset);
    }

    if (cancelfd >= 0) {
        fdset = qemuVirCommandGetFDSet(cmd, cancelfd);
        if (!fdset)
            return -1;

        virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
        VIR_FREE(fdset);
    }

10189
    if (!(optstr = qemuBuildTPMDevStr(def, qemuCaps)))
10190 10191 10192 10193 10194 10195 10196 10197
        return -1;

    virCommandAddArgList(cmd, "-device", optstr, NULL);
    VIR_FREE(optstr);

    return 0;
}

10198
static int
J
Ján Tomko 已提交
10199
qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
10200
                        virDomainSEVDefPtr sev)
10201
{
10202
    virBuffer buf = VIR_BUFFER_INITIALIZER;
10203 10204
    qemuDomainObjPrivatePtr priv = vm->privateData;
    char *path = NULL;
10205
    int ret = -1;
10206 10207 10208 10209 10210 10211 10212

    if (!sev)
        return 0;

    VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
              sev->policy, sev->cbitpos, sev->reduced_phys_bits);

10213 10214 10215
    virBufferAsprintf(&buf, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
    virBufferAsprintf(&buf, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
    virBufferAsprintf(&buf, ",policy=0x%x", sev->policy);
10216 10217 10218

    if (sev->dh_cert) {
        if (virAsprintf(&path, "%s/dh_cert.base64", priv->libDir) < 0)
10219
            goto cleanup;
10220
        virBufferAsprintf(&buf, ",dh-cert-file=%s", path);
10221 10222 10223 10224 10225
        VIR_FREE(path);
    }

    if (sev->session) {
        if (virAsprintf(&path, "%s/session.base64", priv->libDir) < 0)
10226
            goto cleanup;
10227
        virBufferAsprintf(&buf, ",session-file=%s", path);
10228 10229 10230
        VIR_FREE(path);
    }

10231 10232 10233 10234 10235 10236
    virCommandAddArg(cmd, "-object");
    virCommandAddArgBuffer(cmd, &buf);
    ret = 0;
 cleanup:
    virBufferFreeAndReset(&buf);
    return ret;
10237
}
10238

M
Marc-André Lureau 已提交
10239 10240 10241 10242 10243 10244 10245 10246 10247 10248 10249 10250 10251 10252 10253 10254 10255 10256 10257 10258 10259 10260
static int
qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
                               const virDomainDef *def,
                               virQEMUCapsPtr qemuCaps)
{
    virTristateSwitch vmci = def->features[VIR_DOMAIN_FEATURE_VMCOREINFO];

    if (vmci != VIR_TRISTATE_SWITCH_ON)
        return 0;

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VMCOREINFO)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("vmcoreinfo is not available "
                         "with this QEMU binary"));
        return -1;
    }

    virCommandAddArgList(cmd, "-device", "vmcoreinfo", NULL);
    return 0;
}


10261 10262 10263 10264 10265 10266 10267 10268 10269
static int
qemuBuildPanicCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
    size_t i;

    for (i = 0; i < def->npanics; i++) {
        switch ((virDomainPanicModel) def->panics[i]->model) {
10270 10271 10272 10273 10274 10275 10276 10277 10278 10279 10280 10281 10282 10283 10284 10285 10286 10287 10288
        case VIR_DOMAIN_PANIC_MODEL_S390:
            /* For s390 guests, the hardware provides the same
             * functionality as the pvpanic device. The address
             * cannot be configured by the user */
            if (!ARCH_IS_S390(def->os.arch)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("only S390 guests support "
                                 "panic device of model 's390'"));
                return -1;
            }
            if (def->panics[i]->info.type !=
                VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("setting the panic device address is not "
                                 "supported for model 's390'"));
                return -1;
            }
            break;

10289 10290 10291 10292 10293 10294 10295 10296 10297 10298 10299 10300 10301 10302 10303 10304 10305 10306 10307 10308 10309 10310 10311
        case VIR_DOMAIN_PANIC_MODEL_HYPERV:
            /* Panic with model 'hyperv' is not a device, it should
             * be configured in cpu commandline. The address
             * cannot be configured by the user */
            if (!ARCH_IS_X86(def->os.arch)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("only i686 and x86_64 guests support "
                                 "panic device of model 'hyperv'"));
                return -1;
            }
            if (def->panics[i]->info.type !=
                VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("setting the panic device address is not "
                                 "supported for model 'hyperv'"));
                return -1;
            }
            break;

        case VIR_DOMAIN_PANIC_MODEL_PSERIES:
            /* For pSeries guests, the firmware provides the same
             * functionality as the pvpanic device. The address
             * cannot be configured by the user */
10312
            if (!qemuDomainIsPSeries(def)) {
10313 10314 10315 10316 10317 10318 10319 10320 10321 10322 10323 10324 10325 10326 10327 10328 10329 10330
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("only pSeries guests support panic device "
                                 "of model 'pseries'"));
                return -1;
            }
            if (def->panics[i]->info.type !=
                VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("setting the panic device address is not "
                                 "supported for model 'pseries'"));
                return -1;
            }
            break;

        case VIR_DOMAIN_PANIC_MODEL_ISA:
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PANIC)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("the QEMU binary does not support the "
10331
                                 "ISA panic device"));
10332 10333 10334 10335 10336 10337 10338 10339 10340 10341 10342 10343 10344 10345 10346 10347 10348 10349 10350 10351 10352 10353 10354 10355 10356 10357 10358 10359 10360 10361 10362 10363
                return -1;
            }

            switch (def->panics[i]->info.type) {
            case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
                virCommandAddArg(cmd, "-device");
                virCommandAddArgFormat(cmd, "pvpanic,ioport=%d",
                                       def->panics[i]->info.addr.isa.iobase);
                break;

            case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
                virCommandAddArgList(cmd, "-device", "pvpanic", NULL);
                break;

            default:
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("panic is supported only "
                                 "with ISA address type"));
                return -1;
            }

        /* default model value was changed before in post parse */
        case VIR_DOMAIN_PANIC_MODEL_DEFAULT:
        case VIR_DOMAIN_PANIC_MODEL_LAST:
            break;
        }
    }

    return 0;
}


10364 10365 10366 10367 10368 10369 10370 10371 10372 10373 10374 10375 10376 10377 10378
static virJSONValuePtr
qemuBuildPRManagerInfoPropsInternal(const char *alias,
                                    const char *path)
{
    virJSONValuePtr ret = NULL;

    if (qemuMonitorCreateObjectProps(&ret,
                                     "pr-manager-helper", alias,
                                     "s:path", path, NULL) < 0)
        return NULL;

    return ret;
}


10379
/**
10380
 * qemuBuildPRManagedManagerInfoProps:
10381
 *
10382 10383
 * Build the JSON properties for the pr-manager object corresponding to the PR
 * daemon managed by libvirt.
10384
 */
10385
virJSONValuePtr
10386
qemuBuildPRManagedManagerInfoProps(qemuDomainObjPrivatePtr priv)
10387
{
10388
    char *path = NULL;
10389 10390
    virJSONValuePtr ret = NULL;

10391
    if (!(path = qemuDomainGetManagedPRSocketPath(priv)))
10392 10393
        return NULL;

10394 10395 10396 10397
    ret = qemuBuildPRManagerInfoPropsInternal(qemuDomainGetManagedPRAlias(),
                                              path);

    VIR_FREE(path);
10398
    return ret;
10399 10400 10401
}


10402 10403 10404 10405 10406 10407 10408 10409 10410 10411 10412 10413 10414
/**
 * qemuBuildPRManagerInfoProps:
 * @src: storage source
 *
 * Build the JSON properties for the pr-manager object.
 */
virJSONValuePtr
qemuBuildPRManagerInfoProps(virStorageSourcePtr src)
{
    return qemuBuildPRManagerInfoPropsInternal(src->pr->mgralias, src->pr->path);
}


10415
static int
10416 10417 10418
qemuBuildManagedPRCommandLine(virCommandPtr cmd,
                              const virDomainDef *def,
                              qemuDomainObjPrivatePtr priv)
10419
{
10420
    virBuffer buf = VIR_BUFFER_INITIALIZER;
10421 10422 10423
    virJSONValuePtr props = NULL;
    int ret = -1;

10424 10425
    if (!virDomainDefHasManagedPR(def))
        return 0;
10426

10427 10428
    if (!(props = qemuBuildPRManagedManagerInfoProps(priv)))
        return -1;
10429

10430 10431
    if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0)
        goto cleanup;
10432

10433 10434
    virCommandAddArg(cmd, "-object");
    virCommandAddArgBuffer(cmd, &buf);
10435 10436 10437

    ret = 0;
 cleanup:
10438
    virBufferFreeAndReset(&buf);
10439 10440 10441 10442 10443
    virJSONValueFree(props);
    return ret;
}


10444 10445 10446 10447 10448 10449 10450 10451 10452 10453 10454 10455 10456 10457 10458 10459 10460
/**
 * qemuBuildCommandLineValidate:
 *
 * Prior to taking the plunge and building a long command line only
 * to find some configuration option isn't valid, let's do a couple
 * of checks and fail early.
 *
 * Returns 0 on success, returns -1 and messages what the issue is.
 */
static int
qemuBuildCommandLineValidate(virQEMUDriverPtr driver,
                             const virDomainDef *def)
{
    size_t i;
    int sdl = 0;
    int vnc = 0;
    int spice = 0;
10461
    int egl_headless = 0;
10462 10463 10464 10465 10466 10467 10468 10469 10470 10471 10472 10473 10474 10475 10476 10477 10478 10479 10480 10481

    if (!virQEMUDriverIsPrivileged(driver)) {
        /* If we have no cgroups then we can have no tunings that
         * require them */

        if (virMemoryLimitIsSet(def->mem.hard_limit) ||
            virMemoryLimitIsSet(def->mem.soft_limit) ||
            virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Memory tuning is not available in session mode"));
            return -1;
        }

        if (def->blkio.weight) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Block I/O tuning is not available in session mode"));
            return -1;
        }

        if (def->cputune.sharesSpecified || def->cputune.period ||
10482 10483
            def->cputune.quota || def->cputune.global_period ||
            def->cputune.global_quota || def->cputune.emulator_period ||
10484 10485
            def->cputune.emulator_quota || def->cputune.iothread_period ||
            def->cputune.iothread_quota) {
10486 10487 10488 10489 10490 10491 10492 10493 10494 10495 10496 10497 10498 10499 10500 10501 10502
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("CPU tuning is not available in session mode"));
            return -1;
        }
    }

    for (i = 0; i < def->ngraphics; ++i) {
        switch (def->graphics[i]->type) {
        case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
            ++sdl;
            break;
        case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
            ++vnc;
            break;
        case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
            ++spice;
            break;
10503 10504 10505
        case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
            ++egl_headless;
            break;
10506 10507 10508 10509
        case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
        case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
        case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
            break;
10510 10511 10512
        }
    }

10513
    if (sdl > 1 || vnc > 1 || spice > 1 || egl_headless > 1) {
10514 10515
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("only 1 graphics device of each type "
10516
                         "(sdl, vnc, spice, headless) is supported"));
10517 10518 10519 10520 10521 10522 10523 10524 10525 10526 10527 10528 10529 10530 10531 10532
        return -1;
    }

    if (def->virtType == VIR_DOMAIN_VIRT_XEN ||
        def->os.type == VIR_DOMAIN_OSTYPE_XEN ||
        def->os.type == VIR_DOMAIN_OSTYPE_LINUX) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("qemu emulator '%s' does not support xen"),
                       def->emulator);
        return -1;
    }

    return 0;
}


10533 10534 10535 10536 10537
static int
qemuBuildSeccompSandboxCommandLine(virCommandPtr cmd,
                                   virQEMUDriverConfigPtr cfg,
                                   virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED)
{
10538
    if (cfg->seccompSandbox == 0) {
10539 10540
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SECCOMP_SANDBOX))
            virCommandAddArgList(cmd, "-sandbox", "off", NULL);
10541 10542 10543
        return 0;
    }

10544 10545 10546 10547 10548 10549 10550 10551 10552 10553
    /* Use blacklist by default if supported */
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SECCOMP_BLACKLIST)) {
        virCommandAddArgList(cmd, "-sandbox",
                             "on,obsolete=deny,elevateprivileges=deny,"
                             "spawn=deny,resourcecontrol=deny",
                             NULL);
        return 0;
    }

    /* Seccomp whitelist is opt-in */
10554
    if (cfg->seccompSandbox > 0)
10555 10556 10557 10558 10559 10560 10561
        virCommandAddArgList(cmd, "-sandbox", "on", NULL);

    return 0;

}


J
Ján Tomko 已提交
10562
char *
10563 10564
qemuBuildVsockDevStr(virDomainDefPtr def,
                     virDomainVsockDefPtr vsock,
J
Ján Tomko 已提交
10565 10566
                     virQEMUCapsPtr qemuCaps,
                     const char *fdprefix)
10567 10568 10569
{
    qemuDomainVsockPrivatePtr priv = (qemuDomainVsockPrivatePtr)vsock->privateData;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
10570
    char *ret = NULL;
10571

10572

10573
    if (qemuBuildVirtioDevStr(&buf, "vhost-vsock", qemuCaps,
10574
                              VIR_DOMAIN_DEVICE_VSOCK, vsock) < 0) {
10575
        goto cleanup;
10576
    }
10577

10578 10579
    virBufferAsprintf(&buf, ",id=%s", vsock->info.alias);
    virBufferAsprintf(&buf, ",guest-cid=%u", vsock->guest_cid);
J
Ján Tomko 已提交
10580
    virBufferAsprintf(&buf, ",vhostfd=%s%u", fdprefix, priv->vhostfd);
10581 10582 10583 10584 10585 10586
    if (qemuBuildDeviceAddressStr(&buf, def, &vsock->info, qemuCaps) < 0)
        goto cleanup;

    if (virBufferCheckError(&buf) < 0)
        goto cleanup;

10587 10588 10589 10590 10591 10592 10593 10594 10595 10596 10597 10598 10599 10600 10601 10602 10603 10604
    ret = virBufferContentAndReset(&buf);

 cleanup:
    virBufferFreeAndReset(&buf);
    return ret;
}


static int
qemuBuildVsockCommandLine(virCommandPtr cmd,
                          virDomainDefPtr def,
                          virDomainVsockDefPtr vsock,
                          virQEMUCapsPtr qemuCaps)
{
    qemuDomainVsockPrivatePtr priv = (qemuDomainVsockPrivatePtr)vsock->privateData;
    char *devstr = NULL;
    int ret = -1;

J
Ján Tomko 已提交
10605
    if (!(devstr = qemuBuildVsockDevStr(def, vsock, qemuCaps, "")))
10606
        goto cleanup;
10607 10608 10609

    virCommandPassFD(cmd, priv->vhostfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
    priv->vhostfd = -1;
10610 10611 10612 10613

    if (qemuCommandAddExtDevice(cmd, &vsock->info) < 0)
        goto cleanup;

10614 10615 10616 10617 10618 10619 10620 10621 10622
    virCommandAddArgList(cmd, "-device", devstr, NULL);

    ret = 0;
 cleanup:
    VIR_FREE(devstr);
    return ret;
}


10623 10624 10625 10626 10627
/*
 * Constructs a argv suitable for launching qemu with config defined
 * for a given virtual machine.
 */
virCommandPtr
10628
qemuBuildCommandLine(virQEMUDriverPtr driver,
10629
                     virLogManagerPtr logManager,
10630
                     virSecurityManagerPtr secManager,
10631
                     virDomainObjPtr vm,
10632
                     const char *migrateURI,
10633
                     virDomainSnapshotObjPtr snapshot,
10634
                     virNetDevVPortProfileOp vmop,
10635
                     bool standalone,
10636
                     bool enableFips,
10637
                     size_t *nnicindexes,
10638
                     int **nicindexes)
10639
{
10640
    size_t i;
10641 10642
    char uuid[VIR_UUID_STRING_BUFLEN];
    virCommandPtr cmd = NULL;
10643
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
10644
    unsigned int bootHostdevNet = 0;
10645 10646 10647 10648
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virDomainDefPtr def = vm->def;
    virQEMUCapsPtr qemuCaps = priv->qemuCaps;
    bool chardevStdioLogd = priv->chardevStdioLogd;
10649

10650
    VIR_DEBUG("driver=%p def=%p mon=%p json=%d "
10651
              "qemuCaps=%p migrateURI=%s snapshot=%p vmop=%d",
10652
              driver, def, priv->monConfig, priv->monJSON,
10653
              qemuCaps, migrateURI, snapshot, vmop);
10654

10655 10656
    if (qemuBuildCommandLineValidate(driver, def) < 0)
        goto error;
10657

J
John Ferlan 已提交
10658
    cmd = virCommandNew(def->emulator);
10659

10660
    virCommandAddEnvPassCommon(cmd);
10661

M
Marc-André Lureau 已提交
10662 10663
    if (qemuBuildNameCommandLine(cmd, cfg, def, qemuCaps) < 0)
        goto error;
C
Cole Robinson 已提交
10664 10665 10666 10667

    if (!standalone)
        virCommandAddArg(cmd, "-S"); /* freeze CPU */

10668
    if (qemuBuildMasterKeyCommandLine(cmd, priv) < 0)
10669 10670
        goto error;

10671
    if (qemuBuildManagedPRCommandLine(cmd, def, priv) < 0)
10672 10673
        goto error;

10674
    if (enableFips)
10675
        virCommandAddArg(cmd, "-enable-fips");
10676

10677
    if (qemuBuildMachineCommandLine(cmd, cfg, def, qemuCaps) < 0)
10678
        goto error;
10679

10680 10681
    qemuBuildTSEGCommandLine(cmd, def);

10682
    if (qemuBuildCpuCommandLine(cmd, driver, def, qemuCaps) < 0)
10683
        goto error;
10684

10685
    qemuBuildDomainLoaderCommandLine(cmd, def);
10686

10687
    if (!migrateURI && !snapshot && qemuDomainAlignMemorySizes(def) < 0)
10688
        goto error;
10689

10690
    if (qemuBuildMemCommandLine(cmd, cfg, def, qemuCaps, priv) < 0)
10691 10692
        goto error;

10693
    if (qemuBuildSmpCommandLine(cmd, def) < 0)
10694 10695
        goto error;

10696
    if (qemuBuildIOThreadCommandLine(cmd, def) < 0)
10697
        goto error;
J
John Ferlan 已提交
10698

10699
    if (virDomainNumaGetNodeCount(def->numa) &&
10700
        qemuBuildNumaArgStr(cfg, def, cmd, priv) < 0)
10701 10702
        goto error;

10703
    if (qemuBuildMemoryDeviceCommandLine(cmd, cfg, def, priv) < 0)
10704
        goto error;
10705

10706
    virUUIDFormat(def->uuid, uuid);
10707
    virCommandAddArgList(cmd, "-uuid", uuid, NULL);
10708

10709
    if (qemuBuildSmbiosCommandLine(cmd, driver, def) < 0)
10710 10711 10712
        goto error;

    if (qemuBuildVMGenIDCommandLine(cmd, def, qemuCaps) < 0)
10713
        goto error;
10714

10715 10716 10717 10718 10719 10720 10721
    /*
     * NB, -nographic *MUST* come before any serial, or monitor
     * or parallel port flags due to QEMU craziness, where it
     * decides to change the serial port & monitor to be on stdout
     * if you ask for nographic. So we have to make sure we override
     * these defaults ourselves...
     */
10722
    if (!def->ngraphics) {
J
Ján Tomko 已提交
10723 10724
        virCommandAddArg(cmd, "-display");
        virCommandAddArg(cmd, "none");
10725

10726
        if (cfg->nogfxAllowHostAudio)
10727
            virCommandAddEnvPassBlockSUID(cmd, "QEMU_AUDIO_DRV", NULL);
10728 10729 10730 10731
        else
            virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
    }

J
Ján Tomko 已提交
10732
    /* Disable global config files and default devices */
10733
    virCommandAddArg(cmd, "-no-user-config");
J
Ján Tomko 已提交
10734
    virCommandAddArg(cmd, "-nodefaults");
10735

10736 10737
    if (qemuBuildSgaCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10738

10739
    if (qemuBuildMonitorCommandLine(logManager, secManager, cmd, cfg, def, priv) < 0)
10740
        goto error;
10741

10742 10743
    if (qemuBuildClockCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10744

10745
    if (qemuBuildPMCommandLine(cmd, def, priv) < 0)
10746
        goto error;
10747

10748
    if (qemuBuildBootCommandLine(cmd, def, qemuCaps) < 0)
10749
        goto error;
J
Ján Tomko 已提交
10750

10751 10752 10753
    if (qemuBuildIOMMUCommandLine(cmd, def, qemuCaps) < 0)
        goto error;

10754 10755
    if (qemuBuildGlobalControllerCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10756

10757
    if (qemuBuildControllersCommandLine(cmd, def, qemuCaps) < 0)
10758
        goto error;
10759

10760 10761
    if (qemuBuildHubCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10762

10763 10764 10765 10766
    if (qemuBuildControllersByTypeCommandLine(cmd, def, qemuCaps,
                                              VIR_DOMAIN_CONTROLLER_TYPE_CCID) < 0)
        goto error;

10767
    if (qemuBuildDisksCommandLine(cmd, def, qemuCaps) < 0)
10768
        goto error;
E
Eric Blake 已提交
10769

10770 10771
    if (qemuBuildFSDevCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10772

10773
    if (qemuBuildNetCommandLine(driver, logManager, secManager, cmd, def,
10774
                                qemuCaps, vmop, standalone,
10775
                                nnicindexes, nicindexes, &bootHostdevNet) < 0)
10776
        goto error;
10777

10778
    if (qemuBuildSmartcardCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10779
                                      chardevStdioLogd) < 0)
10780
        goto error;
10781

10782
    if (qemuBuildSerialCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10783
                                   chardevStdioLogd) < 0)
10784
        goto error;
M
Martin Kletzander 已提交
10785

10786
    if (qemuBuildParallelsCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10787
                                      chardevStdioLogd) < 0)
10788
        goto error;
10789

10790
    if (qemuBuildChannelsCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10791
                                     chardevStdioLogd) < 0)
10792
        goto error;
10793

10794
    if (qemuBuildConsoleCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10795
                                    chardevStdioLogd) < 0)
10796
        goto error;
10797

10798 10799
    if (qemuBuildTPMCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10800

10801 10802
    if (qemuBuildInputCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10803

10804 10805
    if (qemuBuildGraphicsCommandLine(cfg, cmd, def, qemuCaps) < 0)
        goto error;
10806

10807 10808
    if (qemuBuildVideoCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10809

10810 10811
    if (qemuBuildSoundCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10812

10813 10814
    if (qemuBuildWatchdogCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10815

10816
    if (qemuBuildRedirdevCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10817
                                     chardevStdioLogd) < 0)
10818
        goto error;
10819

10820
    if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps, &bootHostdevNet) < 0)
10821
        goto error;
10822

10823
    if (migrateURI)
10824
        virCommandAddArgList(cmd, "-incoming", migrateURI, NULL);
10825

10826 10827
    if (qemuBuildMemballoonCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10828

10829
    if (qemuBuildRNGCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10830
                                chardevStdioLogd) < 0)
10831
        goto error;
10832

10833 10834
    if (qemuBuildNVRAMCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10835

M
Marc-André Lureau 已提交
10836 10837 10838
    if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
        goto error;

J
Ján Tomko 已提交
10839
    if (qemuBuildSEVCommandLine(vm, cmd, def->sev) < 0)
10840 10841
        goto error;

10842 10843
    if (snapshot)
        virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
10844 10845 10846 10847 10848 10849 10850 10851 10852

    if (def->namespaceData) {
        qemuDomainCmdlineDefPtr qemucmd;

        qemucmd = def->namespaceData;
        for (i = 0; i < qemucmd->num_args; i++)
            virCommandAddArg(cmd, qemucmd->args[i]);
        for (i = 0; i < qemucmd->num_env; i++)
            virCommandAddEnvPair(cmd, qemucmd->env_name[i],
J
Ján Tomko 已提交
10853
                                 NULLSTR_EMPTY(qemucmd->env_value[i]));
10854 10855
    }

10856 10857
    if (qemuBuildSeccompSandboxCommandLine(cmd, cfg, qemuCaps) < 0)
        goto error;
10858

10859 10860
    if (qemuBuildPanicCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
H
Hu Tao 已提交
10861

10862
    for (i = 0; i < def->nshmems; i++) {
10863
        if (qemuBuildShmemCommandLine(logManager, secManager, cmd, cfg,
10864 10865
                                      def, def->shmems[i], qemuCaps,
                                      chardevStdioLogd))
10866 10867 10868
            goto error;
    }

10869 10870 10871 10872
    if (def->vsock &&
        qemuBuildVsockCommandLine(cmd, def, def->vsock, qemuCaps) < 0)
        goto error;

10873 10874
    /* In some situations, eg. VFIO passthrough, QEMU might need to lock a
     * significant amount of memory, so we need to set the limit accordingly */
10875
    virCommandSetMaxMemLock(cmd, qemuDomainGetMemLockLimitBytes(def));
10876

10877 10878 10879 10880
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSG_TIMESTAMP) &&
        cfg->logTimestamp)
        virCommandAddArgList(cmd, "-msg", "timestamp=on", NULL);

10881
    virObjectUnref(cfg);
10882 10883
    return cmd;

10884
 error:
10885
    virObjectUnref(cfg);
10886 10887 10888 10889
    virCommandFree(cmd);
    return NULL;
}

10890

10891 10892 10893
/* This function generates the correct '-device' string for character
 * devices of each architecture.
 */
10894 10895
static int
qemuBuildSerialChrDeviceStr(char **deviceStr,
10896
                            const virDomainDef *def,
10897
                            virDomainChrDefPtr serial,
10898
                            virQEMUCapsPtr qemuCaps)
10899 10900
{
    virBuffer cmd = VIR_BUFFER_INITIALIZER;
10901
    virQEMUCapsFlags caps;
10902

10903
    switch ((virDomainChrSerialTargetModel) serial->targetModel) {
10904
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
10905 10906 10907
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_USB_SERIAL:
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PCI_SERIAL:
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
10908 10909
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
10910

10911
        caps = qemuChrSerialTargetModelToCaps(serial->targetModel);
M
Michal Privoznik 已提交
10912

10913 10914 10915 10916
        if (caps && !virQEMUCapsGet(qemuCaps, caps)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("'%s' is not supported in this QEMU binary"),
                           virDomainChrSerialTargetModelTypeToString(serial->targetModel));
10917
            goto error;
G
Guannan Ren 已提交
10918
        }
10919
        break;
10920

10921
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
10922
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
10923 10924 10925 10926 10927 10928 10929 10930 10931
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
        /* Except from _LAST, which is just a guard value and will never
         * be used, all of the above are platform devices, which means
         * qemuBuildSerialCommandLine() will have taken the appropriate
         * branch and we will not have ended up here. */
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Invalid target model for serial device"));
        goto error;
G
Guannan Ren 已提交
10932 10933
    }

10934 10935 10936 10937
    virBufferAsprintf(&cmd, "%s,chardev=char%s,id=%s",
                      virDomainChrSerialTargetModelTypeToString(serial->targetModel),
                      serial->info.alias, serial->info.alias);

10938 10939 10940
    if (qemuBuildDeviceAddressStr(&cmd, def, &serial->info, qemuCaps) < 0)
        goto error;

10941
    if (virBufferCheckError(&cmd) < 0)
10942 10943
        goto error;

10944 10945
    *deviceStr = virBufferContentAndReset(&cmd);
    return 0;
10946

10947
 error:
10948
    virBufferFreeAndReset(&cmd);
10949 10950 10951 10952 10953 10954 10955 10956
    return -1;
}

static int
qemuBuildParallelChrDeviceStr(char **deviceStr,
                              virDomainChrDefPtr chr)
{
    if (virAsprintf(deviceStr, "isa-parallel,chardev=char%s,id=%s",
J
Ján Tomko 已提交
10957
                    chr->info.alias, chr->info.alias) < 0)
10958 10959
        return -1;
    return 0;
10960
}
10961

10962 10963
static int
qemuBuildChannelChrDeviceStr(char **deviceStr,
10964
                             const virDomainDef *def,
10965
                             virDomainChrDefPtr chr)
10966 10967 10968 10969 10970
{
    int ret = -1;
    char *addr = NULL;
    int port;

10971
    switch ((virDomainChrChannelTargetType)chr->targetType) {
10972 10973 10974 10975 10976 10977 10978 10979
    case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:

        addr = virSocketAddrFormat(chr->target.addr);
        if (!addr)
            return ret;
        port = virSocketAddrGetPort(chr->target.addr);

        if (virAsprintf(deviceStr,
10980
                        "user,guestfwd=tcp:%s:%i-chardev:char%s,id=%s",
J
Ján Tomko 已提交
10981
                        addr, port, chr->info.alias, chr->info.alias) < 0)
10982 10983 10984 10985
            goto cleanup;
        break;

    case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
10986
        if (!(*deviceStr = qemuBuildVirtioSerialPortDevStr(def, chr)))
10987
            goto cleanup;
10988 10989
        break;

J
Joao Martins 已提交
10990
    case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
10991 10992 10993 10994 10995 10996
    case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE:
    case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST:
        return ret;
    }

    ret = 0;
10997
 cleanup:
10998 10999 11000 11001 11002 11003
    VIR_FREE(addr);
    return ret;
}

static int
qemuBuildConsoleChrDeviceStr(char **deviceStr,
11004
                             const virDomainDef *def,
11005
                             virDomainChrDefPtr chr)
11006 11007 11008
{
    int ret = -1;

11009
    switch ((virDomainChrConsoleTargetType)chr->targetType) {
11010 11011 11012 11013 11014 11015 11016
    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLP:
    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SCLPLM:
        if (!(*deviceStr = qemuBuildSclpDevStr(chr)))
            goto cleanup;
        break;

    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO:
11017
        if (!(*deviceStr = qemuBuildVirtioSerialPortDevStr(def, chr)))
11018 11019 11020 11021
            goto cleanup;
        break;

    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
11022 11023
        break;

11024 11025 11026 11027 11028 11029
    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE:
    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN:
    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_UML:
    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LXC:
    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_OPENVZ:
    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST:
11030 11031 11032 11033
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unsupported console target type %s"),
                       NULLSTR(virDomainChrConsoleTargetTypeToString(chr->targetType)));
        goto cleanup;
11034 11035 11036
    }

    ret = 0;
11037
 cleanup:
11038 11039 11040 11041 11042
    return ret;
}

int
qemuBuildChrDeviceStr(char **deviceStr,
11043
                      const virDomainDef *vmdef,
11044 11045 11046 11047 11048
                      virDomainChrDefPtr chr,
                      virQEMUCapsPtr qemuCaps)
{
    int ret = -1;

11049
    switch ((virDomainChrDeviceType)chr->deviceType) {
11050
    case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
11051
        ret = qemuBuildSerialChrDeviceStr(deviceStr, vmdef, chr, qemuCaps);
11052 11053 11054 11055 11056 11057 11058
        break;

    case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
        ret = qemuBuildParallelChrDeviceStr(deviceStr, chr);
        break;

    case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
11059
        ret = qemuBuildChannelChrDeviceStr(deviceStr, vmdef, chr);
11060 11061 11062
        break;

    case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
11063
        ret = qemuBuildConsoleChrDeviceStr(deviceStr, vmdef, chr);
11064 11065 11066 11067 11068 11069 11070 11071
        break;

    case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
        return ret;
    }

    return ret;
}
11072 11073 11074 11075 11076 11077 11078 11079 11080 11081 11082 11083 11084 11085 11086 11087 11088 11089 11090 11091 11092 11093 11094 11095


virJSONValuePtr
qemuBuildHotpluggableCPUProps(const virDomainVcpuDef *vcpu)
{
    qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
    virJSONValuePtr ret = NULL;

    if (virJSONValueObjectCreate(&ret, "s:driver", vcpupriv->type,
                                       "s:id", vcpupriv->alias, NULL) < 0)
        goto error;

    if (vcpupriv->socket_id != -1 &&
        virJSONValueObjectAdd(ret, "i:socket-id", vcpupriv->socket_id, NULL) < 0)
        goto error;

    if (vcpupriv->core_id != -1 &&
        virJSONValueObjectAdd(ret, "i:core-id", vcpupriv->core_id, NULL) < 0)
        goto error;

    if (vcpupriv->thread_id != -1 &&
        virJSONValueObjectAdd(ret, "i:thread-id", vcpupriv->thread_id, NULL) < 0)
        goto error;

11096 11097 11098 11099
    if (vcpupriv->node_id != -1 &&
        virJSONValueObjectAdd(ret, "i:node-id", vcpupriv->node_id, NULL) < 0)
        goto error;

11100 11101 11102 11103 11104 11105
    return ret;

 error:
    virJSONValueFree(ret);
    return NULL;
}
11106 11107 11108 11109 11110 11111


/**
 * qemuBuildStorageSourceAttachPrepareDrive:
 * @disk: disk object to prepare
 * @qemuCaps: qemu capabilities object
11112
 * @driveBoot: bootable flag for disks which don't have -device part
11113 11114 11115 11116 11117 11118
 *
 * Prepare qemuBlockStorageSourceAttachDataPtr for use with the old approach
 * using -drive/drive_add. See qemuBlockStorageSourceAttachPrepareBlockdev.
 */
qemuBlockStorageSourceAttachDataPtr
qemuBuildStorageSourceAttachPrepareDrive(virDomainDiskDefPtr disk,
11119
                                         virQEMUCapsPtr qemuCaps)
11120 11121 11122 11123 11124 11125
{
    qemuBlockStorageSourceAttachDataPtr data = NULL;

    if (VIR_ALLOC(data) < 0)
        return NULL;

11126
    if (!(data->driveCmd = qemuBuildDriveStr(disk, qemuCaps)) ||
11127 11128 11129 11130 11131 11132 11133
        !(data->driveAlias = qemuAliasDiskDriveFromDisk(disk))) {
        qemuBlockStorageSourceAttachDataFree(data);
        return NULL;
    }

    return data;
}
11134 11135 11136 11137 11138 11139


/**
 * qemuBuildStorageSourceAttachPrepareCommon:
 * @src: storage source
 * @data: already initialized data for disk source addition
11140
 * @qemuCaps: qemu capabilities object
11141 11142 11143 11144 11145 11146
 *
 * Prepare data for configuration associated with the disk source such as
 * secrets/TLS/pr objects etc ...
 */
int
qemuBuildStorageSourceAttachPrepareCommon(virStorageSourcePtr src,
11147 11148
                                          qemuBlockStorageSourceAttachDataPtr data,
                                          virQEMUCapsPtr qemuCaps)
11149
{
11150 11151
    qemuDomainStorageSourcePrivatePtr srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);

11152 11153 11154 11155 11156
    if (src->pr &&
        !virStoragePRDefIsManaged(src->pr) &&
        !(data->prmgrProps = qemuBuildPRManagerInfoProps(src)))
        return -1;

11157 11158 11159 11160 11161 11162 11163 11164 11165 11166 11167
    if (srcpriv) {
        if (srcpriv->secinfo &&
            srcpriv->secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES &&
            qemuBuildSecretInfoProps(srcpriv->secinfo, &data->authsecretProps) < 0)
            return -1;

        if (srcpriv->encinfo &&
            qemuBuildSecretInfoProps(srcpriv->encinfo, &data->encryptsecretProps) < 0)
            return -1;
    }

11168 11169 11170 11171 11172
    if (src->haveTLS == VIR_TRISTATE_BOOL_YES &&
        qemuBuildTLSx509BackendProps(src->tlsCertdir, false, true, src->tlsAlias,
                                     NULL, qemuCaps, &data->tlsProps) < 0)
        return -1;

11173 11174
    return 0;
}