qemu_command.c 363.5 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
#include "virdomainsnapshotobjlist.h"
62 63 64
#if defined(__linux__)
# include <linux/capability.h>
#endif
65
#include "logging/log_manager.h"
66 67 68 69 70 71

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

#define VIR_FROM_THIS VIR_FROM_QEMU

72 73
VIR_LOG_INIT("qemu.qemu_command");

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


89
VIR_ENUM_DECL(qemuDiskCacheV2);
90

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

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

117
VIR_ENUM_DECL(qemuDeviceVideo);
118

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

135
VIR_ENUM_DECL(qemuDeviceVideoSecondary);
136

137 138
VIR_ENUM_IMPL(qemuDeviceVideoSecondary,
              VIR_DOMAIN_VIDEO_TYPE_LAST,
139
              "", /* default value, we shouldn't see this */
140 141 142 143 144 145 146
              "", /* 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 */
147
              "virtio-gpu",
148
              "" /* don't support gop */,
149
              "" /* 'none' doesn't make sense here */,
150
              "" /* no secondary device for bochs */,
151
);
152

153
VIR_ENUM_DECL(qemuSoundCodec);
154

155 156
VIR_ENUM_IMPL(qemuSoundCodec,
              VIR_DOMAIN_SOUND_CODEC_TYPE_LAST,
157
              "hda-duplex",
F
Filip Alac 已提交
158
              "hda-micro",
159 160
              "hda-output",
);
161

162
VIR_ENUM_DECL(qemuControllerModelUSB);
163

164 165
VIR_ENUM_IMPL(qemuControllerModelUSB,
              VIR_DOMAIN_CONTROLLER_MODEL_USB_LAST,
166 167 168 169 170 171 172 173
              "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 已提交
174
              "pci-ohci",
175
              "nec-usb-xhci",
176 177
              "qusb1",
              "qusb2",
178
              "qemu-xhci",
179 180
              "none",
);
181

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

190

191 192 193 194 195 196 197 198 199 200 201 202
/**
 * 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,
203
                              qemuDomainObjPrivatePtr priv)
204 205
{
    int ret = -1;
206 207
    VIR_AUTOFREE(char *) alias = NULL;
    VIR_AUTOFREE(char *) path = NULL;
208
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
209 210 211 212 213

    /* 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.
     */
214
    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_SECRET)) {
215 216 217 218 219 220 221 222 223 224 225 226
        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.
     */
227
    if (!(path = qemuDomainGetMasterKeyFilePath(priv->libDir)))
228 229 230
        goto cleanup;

    virCommandAddArg(cmd, "-object");
231
    virBufferAsprintf(&buf, "secret,id=%s,format=raw,file=", alias);
232
    virQEMUBuildBufferEscapeComma(&buf, path);
233
    virCommandAddArgBuffer(cmd, &buf);
234 235 236 237 238 239 240 241

    ret = 0;

 cleanup:
    return ret;
}


242 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
/**
 * 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;
}


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

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

310
        if (!(devStr = virPCIDeviceAddressAsString(&info->addr.pci)))
311 312 313 314 315 316
            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) {
317
                contAlias = cont->info.alias;
318
                contIsPHB = virDomainControllerIsPSeriesPHB(cont);
319
                contTargetIndex = cont->opts.pciopts.targetIndex;
320

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
                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";
342
                    }
343 344 345 346 347 348 349 350 351 352 353 354 355
                }
                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;
        }

356 357 358 359 360 361 362 363 364 365 366
        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);
        }
367

J
Ján Tomko 已提交
368
        if (info->addr.pci.multi == VIR_TRISTATE_SWITCH_ON)
369
            virBufferAddLit(buf, ",multifunction=on");
J
Ján Tomko 已提交
370
        else if (info->addr.pci.multi == VIR_TRISTATE_SWITCH_OFF)
371 372 373 374
            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);
375
    } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
376 377 378 379
        if (!(contAlias = virDomainControllerAliasFind(domainDef,
                                                       VIR_DOMAIN_CONTROLLER_TYPE_USB,
                                                       info->addr.usb.bus)))
            goto cleanup;
J
Ján Tomko 已提交
380
        virBufferAsprintf(buf, ",bus=%s.0", contAlias);
381 382 383 384
        if (virDomainUSBAddressPortIsValid(info->addr.usb.port)) {
            virBufferAddLit(buf, ",port=");
            virDomainUSBAddressPortFormatBuf(buf, info->addr.usb.port);
        }
385 386
    } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) {
        if (info->addr.spaprvio.has_reg)
387
            virBufferAsprintf(buf, ",reg=0x%08llx", info->addr.spaprvio.reg);
388 389 390 391 392 393
    } 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);
394 395 396 397
    } 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);
398
    }
399

400
    ret = 0;
401
 cleanup:
402
    return ret;
403 404
}

405

406 407 408 409
/**
 * qemuBuildVirtioDevStr
 * @buf: virBufferPtr to append the built string
 * @baseName: qemu virtio device basename string. Ex: virtio-rng for <rng>
410
 * @qemuCaps: virQEMUCapPtr
411 412 413 414 415 416 417 418 419 420
 * @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
 */
421 422 423
static int
qemuBuildVirtioDevStr(virBufferPtr buf,
                      const char *baseName,
424
                      virQEMUCapsPtr qemuCaps,
425 426
                      virDomainDeviceType devtype,
                      void *devdata)
427 428
{
    const char *implName = NULL;
429 430
    virDomainDeviceDef device = { .type = devtype };
    virDomainDeviceInfoPtr info;
431
    bool has_tmodel, has_ntmodel;
432

433 434 435 436
    virDomainDeviceSetData(&device, devdata);
    info = virDomainDeviceGetInfo(&device);

    switch ((virDomainDeviceAddressType) info->type) {
437 438 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
    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:
467
        virReportEnumRangeError(virDomainDeviceAddressType, info->type);
468 469 470 471 472
        return -1;
    }

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

473 474 475 476 477 478 479
    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:
480 481
            has_tmodel = device.data.net->model == VIR_DOMAIN_NET_MODEL_VIRTIO_TRANSITIONAL;
            has_ntmodel = device.data.net->model == VIR_DOMAIN_NET_MODEL_VIRTIO_NON_TRANSITIONAL;
482 483
            break;

484 485 486 487 488 489 490
        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;

491 492 493 494 495
        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;

496
        case VIR_DOMAIN_DEVICE_FS:
497 498 499 500
            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;

501 502 503 504 505
        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;

506 507 508 509 510
        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;

511
        case VIR_DOMAIN_DEVICE_INPUT:
512 513 514 515 516 517
            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;

518 519 520 521
        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;
522 523 524
            } 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;
525 526 527 528 529
            } else {
                return 0;
            }
            break;

530
        case VIR_DOMAIN_DEVICE_LEASE:
531 532 533 534 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
        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;
        }
    }

588 589 590
    return 0;
}

591 592 593 594 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
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;
}

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

634 635 636 637 638 639 640
        /* 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;
        }

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

657 658 659
    return 0;
}

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

#define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \
672
  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ .+"
673 674 675 676

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

    return 0;
}

687

688 689 690 691 692 693 694 695 696 697
/**
 * 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.
 */
698
int
699 700 701 702
qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo,
                         virJSONValuePtr *propsret)
{
    int ret = -1;
703
    VIR_AUTOFREE(char *) keyid = NULL;
704 705 706 707

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

708 709 710 711 712 713
    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);
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734

    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)
{
735
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
736
    int ret = -1;
737
    VIR_AUTOPTR(virJSONValue) props = NULL;
738

739
    if (qemuBuildSecretInfoProps(secinfo, &props) < 0)
740 741
        return -1;

742
    if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0)
743 744
        goto cleanup;

745 746 747 748
    virCommandAddArg(cmd, "-object");
    virCommandAddArgBuffer(cmd, &buf);

    ret  = 0;
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775

 cleanup:
    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);
}


776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
/* 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 已提交
794 795 796
    switch ((qemuDomainSecretInfoType) secinfo->type) {
    case VIR_DOMAIN_SECRET_INFO_TYPE_PLAIN:
        if (secinfo->s.plain.secret) {
797 798 799 800 801 802
            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 已提交
803 804 805 806 807 808 809 810 811 812
            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;

813
    case VIR_DOMAIN_SECRET_INFO_TYPE_AES:
J
John Ferlan 已提交
814 815
    case VIR_DOMAIN_SECRET_INFO_TYPE_LAST:
        return -1;
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
    }

    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)
{
837
    VIR_AUTODISPOSE_STR base64secret = NULL;
838

839 840 841 842 843
    if (!secinfo) {
        virBufferAddLit(buf, ":auth_supported=none");
        return 0;
    }

J
John Ferlan 已提交
844 845
    switch ((qemuDomainSecretInfoType) secinfo->type) {
    case VIR_DOMAIN_SECRET_INFO_TYPE_PLAIN:
846 847 848 849
        if (!(base64secret = virStringEncodeBase64(secinfo->s.plain.secret,
                                                   secinfo->s.plain.secretlen)))
            return -1;
        virBufferEscape(buf, '\\', ":", ":id=%s", secinfo->s.plain.username);
J
John Ferlan 已提交
850 851
        virBufferEscape(buf, '\\', ":",
                        ":key=%s:auth_supported=cephx\\;none",
852
                        base64secret);
J
John Ferlan 已提交
853 854
        break;

855
    case VIR_DOMAIN_SECRET_INFO_TYPE_AES:
856 857 858 859
        virBufferEscape(buf, '\\', ":", ":id=%s:auth_supported=cephx\\;none",
                        secinfo->s.aes.username);
        break;

J
John Ferlan 已提交
860 861 862
    case VIR_DOMAIN_SECRET_INFO_TYPE_LAST:
        return -1;
    }
863 864 865 866 867

    return 0;
}


868 869 870 871
/* qemuBuildTLSx509BackendProps:
 * @tlspath: path to the TLS credentials
 * @listen: boolen listen for client or server setting
 * @verifypeer: boolean to enable peer verification (form of authorization)
872
 * @alias: alias for the TLS credentials object
873
 * @secalias: if one exists, the alias of the security object for passwordid
874 875 876 877 878 879 880
 * @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.
 */
881
int
882
qemuBuildTLSx509BackendProps(const char *tlspath,
883
                             bool isListen,
884
                             bool verifypeer,
885
                             const char *alias,
886
                             const char *secalias,
887 888 889 890 891 892 893 894 895
                             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;
    }

896 897 898 899 900 901
    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)
902
        return -1;
903

904
    return 0;
905 906 907 908 909 910 911 912
}


/* 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)
913 914
 * @certEncSecretAlias: alias of a 'secret' object for decrypting TLS private key
 *                      (optional)
915
 * @alias: TLS object alias
916 917 918 919 920 921 922 923 924
 * @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,
925
                            bool isListen,
926
                            bool verifypeer,
927
                            const char *certEncSecretAlias,
928
                            const char *alias,
929 930
                            virQEMUCapsPtr qemuCaps)
{
931
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
932
    int ret = -1;
933
    VIR_AUTOPTR(virJSONValue) props = NULL;
934

935 936
    if (qemuBuildTLSx509BackendProps(tlspath, isListen, verifypeer, alias,
                                     certEncSecretAlias, qemuCaps, &props) < 0)
937 938
        goto cleanup;

939
    if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0)
940 941
        goto cleanup;

942 943
    virCommandAddArg(cmd, "-object");
    virCommandAddArgBuffer(cmd, &buf);
944 945 946 947 948 949 950 951

    ret = 0;

 cleanup:
    return ret;
}


952 953 954 955
static char *
qemuBuildNetworkDriveURI(virStorageSourcePtr src,
                         qemuDomainSecretInfoPtr secinfo)
{
956
    VIR_AUTOPTR(virURI) uri = NULL;
957 958
    char *ret = NULL;

959
    if (!(uri = qemuBlockStorageSourceGetURI(src)))
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
        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:
    return ret;
}


976
static char *
977
qemuBuildNetworkDriveStr(virStorageSourcePtr src,
978
                         qemuDomainSecretInfoPtr secinfo)
979 980
{
    char *ret = NULL;
981
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
982
    size_t i;
983

984
    switch ((virStorageNetProtocol) src->protocol) {
985
        case VIR_STORAGE_NET_PROTOCOL_NBD:
986
            if (src->nhosts != 1) {
987 988
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("protocol '%s' accepts only one host"),
989
                               virStorageNetProtocolTypeToString(src->protocol));
990 991 992
                goto cleanup;
            }

993 994 995 996 997 998
            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] != '/'))) {
999 1000 1001

                virBufferAddLit(&buf, "nbd:");

1002
                switch (src->hosts->transport) {
1003
                case VIR_STORAGE_NET_HOST_TRANS_TCP:
1004 1005
                    virBufferAsprintf(&buf, "%s:%u",
                                      src->hosts->name, src->hosts->port);
1006 1007
                    break;

1008
                case VIR_STORAGE_NET_HOST_TRANS_UNIX:
1009
                    if (!src->hosts->socket) {
1010 1011 1012 1013 1014 1015
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("socket attribute required for "
                                         "unix transport"));
                        goto cleanup;
                    }

1016
                    virBufferAsprintf(&buf, "unix:%s", src->hosts->socket);
1017 1018 1019 1020 1021
                    break;

                default:
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("nbd does not support transport '%s'"),
1022
                                   virStorageNetHostTransportTypeToString(src->hosts->transport));
1023 1024 1025
                    goto cleanup;
                }

1026 1027
                if (src->path)
                    virBufferAsprintf(&buf, ":exportname=%s", src->path);
1028

1029
                if (virBufferCheckError(&buf) < 0)
1030 1031 1032 1033 1034
                    goto cleanup;

                ret = virBufferContentAndReset(&buf);
                goto cleanup;
            }
1035 1036 1037
            /* NBD code uses URI formatting scheme as others in some cases */
            ret = qemuBuildNetworkDriveURI(src, secinfo);
            break;
1038

1039 1040 1041 1042 1043 1044 1045
        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:
1046
            ret = qemuBuildNetworkDriveURI(src, secinfo);
1047 1048
            break;

1049
        case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
1050
            if (!src->path) {
1051 1052 1053 1054 1055
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("missing disk source for 'sheepdog' protocol"));
                goto cleanup;
            }

1056 1057
            if (src->nhosts == 0) {
                if (virAsprintf(&ret, "sheepdog:%s", src->path) < 0)
1058
                    goto cleanup;
1059
            } else if (src->nhosts == 1) {
1060
                if (virAsprintf(&ret, "sheepdog:%s:%u:%s",
1061
                                src->hosts->name, src->hosts->port,
1062
                                src->path) < 0)
1063 1064 1065 1066 1067 1068 1069 1070 1071
                    goto cleanup;
            } else {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("protocol 'sheepdog' accepts up to one host"));
                goto cleanup;
            }

            break;

1072
        case VIR_STORAGE_NET_PROTOCOL_RBD:
1073
            if (strchr(src->path, ':')) {
1074 1075
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("':' not allowed in RBD source volume name '%s'"),
1076
                               src->path);
1077 1078 1079
                goto cleanup;
            }

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

1082 1083 1084
            if (src->snapshot)
                virBufferEscape(&buf, '\\', ":", "@%s", src->snapshot);

1085 1086
            if (qemuBuildRBDSecinfoURI(&buf, secinfo) < 0)
                goto cleanup;
1087

1088
            if (src->nhosts > 0) {
1089
                virBufferAddLit(&buf, ":mon_host=");
1090
                for (i = 0; i < src->nhosts; i++) {
1091 1092 1093 1094
                    if (i)
                        virBufferAddLit(&buf, "\\;");

                    /* assume host containing : is ipv6 */
1095 1096 1097
                    if (strchr(src->hosts[i].name, ':'))
                        virBufferEscape(&buf, '\\', ":", "[%s]",
                                        src->hosts[i].name);
1098
                    else
1099
                        virBufferAsprintf(&buf, "%s", src->hosts[i].name);
1100

1101
                    if (src->hosts[i].port)
1102
                        virBufferAsprintf(&buf, "\\:%u", src->hosts[i].port);
1103 1104 1105
                }
            }

1106 1107 1108
            if (src->configFile)
                virBufferEscape(&buf, '\\', ":", ":conf=%s", src->configFile);

1109
            if (virBufferCheckError(&buf) < 0)
1110 1111 1112 1113 1114
                goto cleanup;

            ret = virBufferContentAndReset(&buf);
            break;

1115 1116 1117 1118 1119
        case VIR_STORAGE_NET_PROTOCOL_VXHS:
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("VxHS protocol does not support URI syntax"));
            goto cleanup;

1120 1121 1122 1123
        case VIR_STORAGE_NET_PROTOCOL_SSH:
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("'ssh' protocol is not yet supported"));
            goto cleanup;
1124

1125
        case VIR_STORAGE_NET_PROTOCOL_LAST:
1126
        case VIR_STORAGE_NET_PROTOCOL_NONE:
1127 1128 1129
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unexpected network protocol '%s'"),
                           virStorageNetProtocolTypeToString(src->protocol));
1130 1131
            goto cleanup;
    }
1132

1133
 cleanup:
1134 1135 1136 1137 1138

    return ret;
}


1139
int
1140
qemuGetDriveSourceString(virStorageSourcePtr src,
1141
                         qemuDomainSecretInfoPtr secinfo,
1142
                         char **source)
1143
{
1144 1145 1146 1147 1148
    int actualType = virStorageSourceGetActualType(src);
    int ret = -1;

    *source = NULL;

1149 1150 1151 1152
    /* return 1 for empty sources */
    if (virStorageSourceIsEmpty(src))
        return 1;

1153
    switch ((virStorageType)actualType) {
E
Eric Blake 已提交
1154 1155 1156
    case VIR_STORAGE_TYPE_BLOCK:
    case VIR_STORAGE_TYPE_FILE:
    case VIR_STORAGE_TYPE_DIR:
1157 1158
        if (VIR_STRDUP(*source, src->path) < 0)
            goto cleanup;
1159 1160 1161

        break;

E
Eric Blake 已提交
1162
    case VIR_STORAGE_TYPE_NETWORK:
1163
        if (!(*source = qemuBuildNetworkDriveStr(src, secinfo)))
1164
            goto cleanup;
1165 1166
        break;

E
Eric Blake 已提交
1167
    case VIR_STORAGE_TYPE_VOLUME:
1168
    case VIR_STORAGE_TYPE_NONE:
E
Eric Blake 已提交
1169
    case VIR_STORAGE_TYPE_LAST:
1170 1171 1172
        break;
    }

1173
    ret = 0;
1174

1175
 cleanup:
1176 1177 1178
    return ret;
}

P
Paolo Bonzini 已提交
1179

1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 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
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;
}


1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
bool
qemuDiskConfigBlkdeviotuneEnabled(virDomainDiskDefPtr disk)
{
    return !!disk->blkdeviotune.group_name ||
           qemuDiskConfigBlkdeviotuneHasBasic(disk) ||
           qemuDiskConfigBlkdeviotuneHasMax(disk) ||
           qemuDiskConfigBlkdeviotuneHasMaxLength(disk);
}


1227 1228 1229 1230 1231 1232 1233 1234
/**
 * 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.
 */
1235 1236 1237 1238
static int
qemuCheckDiskConfigBlkdeviotune(virDomainDiskDefPtr disk,
                                virQEMUCapsPtr qemuCaps)
{
1239 1240 1241 1242 1243
    /* group_name by itself is ignored by qemu */
    if (disk->blkdeviotune.group_name &&
        !qemuDiskConfigBlkdeviotuneHasBasic(disk) &&
        !qemuDiskConfigBlkdeviotuneHasMax(disk) &&
        !qemuDiskConfigBlkdeviotuneHasMaxLength(disk)) {
1244
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1245 1246
                       _("group_name can be configured only together with "
                         "settings"));
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
        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;
    }

1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297
    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;
        }
    }

1298 1299 1300 1301
    return 0;
}


1302 1303 1304 1305 1306 1307 1308 1309
/**
 * 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.
 */
1310
int
1311 1312
qemuCheckDiskConfig(virDomainDiskDefPtr disk,
                    virQEMUCapsPtr qemuCaps)
1313
{
1314 1315 1316
    if (qemuCheckDiskConfigBlkdeviotune(disk, qemuCaps) < 0)
        return -1;

1317 1318 1319
    if (virDiskNameToIndex(disk->dst) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported disk type '%s'"), disk->dst);
1320
        return -1;
1321 1322 1323 1324 1325 1326 1327
    }

    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"));
1328
            return -1;
1329 1330 1331 1332 1333 1334 1335
        }
    }

    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"));
1336
            return -1;
1337 1338 1339 1340 1341 1342 1343 1344 1345
    }

    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));
1346
            return -1;
1347
        }
1348

1349 1350 1351 1352 1353 1354 1355 1356
        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;
        }

1357
        if (qemuDomainDefValidateDiskLunSource(disk->src) < 0)
1358
            return -1;
1359

1360 1361 1362
        if (disk->wwn) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting wwn is not supported for lun device"));
1363
            return -1;
1364 1365 1366 1367 1368
        }
        if (disk->vendor || disk->product) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting vendor or product is not supported "
                             "for lun device"));
1369
            return -1;
1370 1371
        }
    }
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 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

    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 &&
1469 1470 1471 1472 1473 1474
            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;
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
        }

        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;
        }
    }

1492 1493 1494 1495
    if (disk->serial &&
        qemuSafeSerialParamValue(disk->serial) < 0)
        return -1;

1496 1497 1498 1499
    return 0;
}


P
Philipp Hahn 已提交
1500
/* QEMU 1.2 and later have a binary flag -enable-fips that must be
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
 * 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")) {
1516
        VIR_AUTOFREE(char *) buf = NULL;
1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527

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

    return ret;
}


1528 1529 1530 1531 1532 1533 1534 1535 1536 1537
/**
 * 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 已提交
1538
{
1539
    return bus == VIR_DOMAIN_DISK_BUS_SD;
J
Ján Tomko 已提交
1540 1541 1542
}


1543 1544 1545 1546 1547 1548 1549 1550 1551
/**
 * 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
1552 1553
qemuDiskSourceNeedsProps(virStorageSourcePtr src,
                         virQEMUCapsPtr qemuCaps)
1554 1555 1556 1557 1558 1559 1560 1561
{
    int actualType = virStorageSourceGetActualType(src);

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

1562 1563 1564 1565
    if (actualType == VIR_STORAGE_TYPE_NETWORK &&
        src->protocol == VIR_STORAGE_NET_PROTOCOL_VXHS)
        return true;

1566 1567 1568 1569 1570
    if (actualType == VIR_STORAGE_TYPE_NETWORK &&
        src->protocol == VIR_STORAGE_NET_PROTOCOL_ISCSI &&
        virQEMUCapsGet(qemuCaps, QEMU_CAPS_ISCSI_PASSWORD_SECRET))
        return true;

1571 1572 1573 1574 1575
    if (actualType == VIR_STORAGE_TYPE_NETWORK &&
        src->protocol == VIR_STORAGE_NET_PROTOCOL_NBD &&
        src->haveTLS == VIR_TRISTATE_BOOL_YES)
        return true;

1576 1577 1578 1579
    return false;
}


1580 1581 1582 1583 1584 1585 1586 1587 1588 1589
/**
 * 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)
{
1590
    VIR_AUTOPTR(virJSONValue) props = NULL;
1591 1592
    virJSONValuePtr ret;

1593
    if (!(props = qemuBlockStorageSourceGetBackendProps(src, true, false, false)))
1594 1595
        return NULL;

1596
    if (virJSONValueObjectCreate(&ret, "a:file", &props, NULL) < 0)
1597 1598 1599 1600 1601 1602
        return NULL;

    return ret;
}


1603 1604 1605 1606
static int
qemuBuildDriveSourcePR(virBufferPtr buf,
                       virDomainDiskDefPtr disk)
{
1607
    VIR_AUTOFREE(char *) alias = NULL;
1608 1609
    const char *defaultAlias = NULL;

1610
    if (!disk->src->pr)
1611 1612 1613 1614
        return 0;

    if (virStoragePRDefIsManaged(disk->src->pr))
        defaultAlias = qemuDomainGetManagedPRAlias();
1615
    else if (!(alias = qemuDomainGetUnmanagedPRAlias(disk->info.alias)))
1616 1617 1618 1619 1620 1621 1622 1623
        return -1;


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


1624 1625
static int
qemuBuildDriveSourceStr(virDomainDiskDefPtr disk,
1626
                        virQEMUCapsPtr qemuCaps,
1627
                        virBufferPtr buf)
1628 1629
{
    int actualType = virStorageSourceGetActualType(disk->src);
1630
    qemuDomainStorageSourcePrivatePtr srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(disk->src);
1631 1632
    qemuDomainSecretInfoPtr secinfo = NULL;
    qemuDomainSecretInfoPtr encinfo = NULL;
1633
    VIR_AUTOPTR(virJSONValue) srcprops = NULL;
1634
    VIR_AUTOFREE(char *) source = NULL;
1635
    bool rawluks = false;
1636 1637
    int ret = -1;

1638 1639 1640 1641 1642
    if (srcpriv) {
        secinfo = srcpriv->secinfo;
        encinfo = srcpriv->encinfo;
    }

1643
    if (qemuDiskSourceNeedsProps(disk->src, qemuCaps) &&
1644
        !(srcprops = qemuDiskSourceGetProps(disk->src)))
1645 1646 1647 1648
        goto cleanup;

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

1651
    /* nothing to format if the drive is empty */
1652
    if (!(source || srcprops) ||
1653 1654 1655 1656 1657 1658
        ((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;
    }
1659

1660 1661 1662 1663 1664 1665 1666 1667
    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;
    }
1668

1669 1670
    if (source) {
        virBufferAddLit(buf, "file=");
1671

1672 1673 1674 1675 1676 1677
        /* 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:");
1678 1679
        }

1680
        virQEMUBuildBufferEscapeComma(buf, source);
1681 1682 1683

        if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES)
            virBufferAsprintf(buf, ",file.password-secret=%s", secinfo->s.aes.alias);
1684 1685 1686

        if (disk->src->debug)
            virBufferAsprintf(buf, ",file.debug=%d", disk->src->debugLevel);
1687 1688 1689

        if (qemuBuildDriveSourcePR(buf, disk) < 0)
            goto cleanup;
1690 1691 1692
    } else {
        if (!(source = virQEMUBuildDriveCommandlineFromJSON(srcprops)))
            goto cleanup;
1693

1694
        virBufferAdd(buf, source, -1);
1695 1696
    }
    virBufferAddLit(buf, ",");
1697

1698 1699 1700 1701 1702 1703 1704 1705 1706 1707
    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);
        }
    }
1708 1709

    if (disk->src->format > 0 &&
1710
        actualType != VIR_STORAGE_TYPE_DIR) {
1711
        const char *qemuformat = virStorageFileFormatTypeToString(disk->src->format);
1712
        if (rawluks)
1713 1714 1715
            qemuformat = "luks";
        virBufferAsprintf(buf, "format=%s,", qemuformat);
    }
1716

1717 1718 1719 1720 1721 1722 1723
    ret = 0;

 cleanup:
    return ret;
}


1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749
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) {
1750 1751
        virBufferAddLit(buf, ",throttling.group=");
        virQEMUBuildBufferEscapeComma(buf, disk->blkdeviotune.group_name);
1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763
    }

    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
}


1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794
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);
}


1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808
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)
1809
            virBufferAsprintf(buf, ",bios-chs-trans=%s",
1810 1811
                              virDomainDiskGeometryTransTypeToString(disk->geometry.trans));
    }
1812

1813
    if (disk->serial) {
1814 1815 1816
        virBufferAddLit(buf, ",serial=");
        virBufferEscape(buf, '\\', " ", "%s", disk->serial);
    }
1817 1818 1819
}


1820
static char *
1821 1822 1823
qemuBuildDriveStr(virDomainDiskDefPtr disk,
                  virQEMUCapsPtr qemuCaps)
{
1824
    VIR_AUTOCLEAN(virBuffer) opt = VIR_BUFFER_INITIALIZER;
1825 1826
    int detect_zeroes = virDomainDiskGetDetectZeroesMode(disk->discard,
                                                         disk->detect_zeroes);
1827

1828
    if (qemuBuildDriveSourceStr(disk, qemuCaps, &opt) < 0)
1829 1830
        goto error;

1831
    if (!qemuDiskBusNeedsDriveArg(disk->bus)) {
1832
        VIR_AUTOFREE(char *) drivealias = qemuAliasDiskDriveFromDisk(disk);
1833 1834
        if (!drivealias)
            goto error;
1835 1836

        virBufferAddLit(&opt, "if=none");
1837
        virBufferAsprintf(&opt, ",id=%s", drivealias);
1838
    } else {
1839 1840 1841 1842 1843 1844 1845
        int idx = virDiskNameToIndex(disk->dst);

        if (idx < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unsupported disk type '%s'"), disk->dst);
            goto error;
        }
1846 1847 1848 1849 1850 1851 1852

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

        virBufferAsprintf(&opt, "if=%s",
                          virDomainDiskQEMUBusTypeToString(disk->bus));
1853
        virBufferAsprintf(&opt, ",index=%d", idx);
1854
    }
1855

1856 1857
    /* werror/rerror are really frontend attributes, but older
     * qemu requires them on -drive instead of -device */
1858 1859
    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_STORAGE_WERROR))
        qemuBuildDiskFrontendAttributeErrorPolicy(disk, &opt);
1860

1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871
    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
     */
1872 1873 1874 1875 1876
    if (!virStorageSourceIsEmpty(disk->src)) {
        if (disk->cachemode) {
            virBufferAsprintf(&opt, ",cache=%s",
                              qemuDiskCacheV2TypeToString(disk->cachemode));
        }
1877

1878 1879 1880 1881
        if (disk->copy_on_read) {
            virBufferAsprintf(&opt, ",copy-on-read=%s",
                              virTristateSwitchTypeToString(disk->copy_on_read));
        }
1882

1883 1884 1885 1886
        if (disk->discard) {
            virBufferAsprintf(&opt, ",discard=%s",
                              virDomainDiskDiscardTypeToString(disk->discard));
        }
O
Osier Yang 已提交
1887

1888 1889 1890 1891
        if (detect_zeroes) {
            virBufferAsprintf(&opt, ",detect-zeroes=%s",
                              virDomainDiskDetectZeroesTypeToString(detect_zeroes));
        }
O
Osier Yang 已提交
1892

1893 1894 1895 1896
        if (disk->iomode) {
            virBufferAsprintf(&opt, ",aio=%s",
                              virDomainDiskIoTypeToString(disk->iomode));
        }
E
Eric Blake 已提交
1897 1898
    }

1899 1900
    qemuBuildDiskThrottling(disk, &opt);

1901
    if (virBufferCheckError(&opt) < 0)
1902 1903 1904 1905
        goto error;

    return virBufferContentAndReset(&opt);

1906
 error:
1907 1908 1909
    return NULL;
}

1910

1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
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;
}


1954 1955 1956 1957 1958 1959 1960 1961 1962 1963
static int
qemuBuildDriveDevCacheStr(virDomainDiskDefPtr disk,
                          virBufferPtr buf,
                          virQEMUCapsPtr qemuCaps)
{
    bool wb;

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

1964 1965 1966 1967 1968
    /* 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;

1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982
    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;
}


1983
char *
1984 1985 1986 1987
qemuBuildDiskDeviceStr(const virDomainDef *def,
                       virDomainDiskDefPtr disk,
                       unsigned int bootindex,
                       virQEMUCapsPtr qemuCaps)
1988
{
1989
    VIR_AUTOCLEAN(virBuffer) opt = VIR_BUFFER_INITIALIZER;
1990
    const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
1991
    const char *contAlias;
1992
    VIR_AUTOFREE(char *) backendAlias = NULL;
1993
    VIR_AUTOFREE(char *) scsiVPDDeviceId = NULL;
1994
    int controllerModel;
1995

1996
    if (qemuCheckDiskConfig(disk, qemuCaps) < 0)
1997
        goto error;
1998

1999
    if (!qemuDomainCheckCCWS390AddressSupport(def, &disk->info, qemuCaps, disk->dst))
2000 2001
        goto error;

2002 2003 2004
    if (disk->iothread && !qemuCheckIOThreads(def, disk))
        goto error;

2005
    switch ((virDomainDiskBus) disk->bus) {
2006
    case VIR_DOMAIN_DISK_BUS_IDE:
2007
        if (disk->info.addr.drive.target != 0) {
2008 2009
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("target must be 0 for ide controller"));
2010 2011
            goto error;
        }
2012

2013
        if (disk->wwn &&
2014
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_IDE_DRIVE_WWN)) {
2015 2016 2017 2018 2019 2020
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting wwn for ide disk is not supported "
                             "by this QEMU"));
            goto error;
        }

2021 2022 2023 2024
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
            virBufferAddLit(&opt, "ide-cd");
        else
            virBufferAddLit(&opt, "ide-hd");
2025

2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
        /* 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;
        }
2037 2038
        virBufferAsprintf(&opt, ",bus=%s.%d,unit=%d",
                          contAlias,
2039 2040 2041
                          disk->info.addr.drive.bus,
                          disk->info.addr.drive.unit);
        break;
2042

2043
    case VIR_DOMAIN_DISK_BUS_SCSI:
2044
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
2045
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_BLOCK)) {
2046 2047 2048
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("This QEMU doesn't support scsi-block for "
                                 "lun passthrough"));
2049 2050 2051 2052
                goto error;
            }
        }

2053
        if (disk->wwn &&
2054
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_DISK_WWN)) {
2055 2056 2057 2058 2059 2060
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting wwn for scsi disk is not supported "
                             "by this QEMU"));
            goto error;
        }

2061 2062 2063 2064
        /* Properties wwn, vendor and product were introduced in the
         * same QEMU release (1.2.0).
         */
        if ((disk->vendor || disk->product) &&
2065
            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_DISK_WWN)) {
2066 2067 2068 2069 2070 2071
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Setting vendor or product for scsi disk is not "
                             "supported by this QEMU"));
            goto error;
        }

2072
        controllerModel = qemuDomainFindSCSIControllerModel(def, &disk->info);
2073
        if (controllerModel < 0)
2074
            goto error;
2075

2076 2077 2078
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
            virBufferAddLit(&opt, "scsi-block");
        } else {
2079 2080 2081 2082
            if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
                virBufferAddLit(&opt, "scsi-cd");
            else
                virBufferAddLit(&opt, "scsi-hd");
2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097

            /* 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;
                }
            }
2098 2099
        }

2100 2101 2102 2103
        if (!(contAlias = virDomainControllerAliasFind(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
                                                       disk->info.addr.drive.controller)))
           goto error;

2104 2105
        if (controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) {
            if (disk->info.addr.drive.target != 0) {
2106 2107 2108
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("target must be 0 for controller "
                                 "model 'lsilogic'"));
2109 2110 2111
                goto error;
            }

2112 2113
            virBufferAsprintf(&opt, ",bus=%s.%d,scsi-id=%d",
                              contAlias,
2114 2115 2116
                              disk->info.addr.drive.bus,
                              disk->info.addr.drive.unit);
        } else {
2117
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_DISK_CHANNEL)) {
2118
                if (disk->info.addr.drive.target > 7) {
2119 2120 2121
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                   _("This QEMU doesn't support target "
                                     "greater than 7"));
2122 2123 2124
                    goto error;
                }

2125 2126
                if (disk->info.addr.drive.bus != 0 &&
                    disk->info.addr.drive.unit != 0) {
2127 2128 2129
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                   _("This QEMU only supports both bus and "
                                     "unit equal to 0"));
2130 2131 2132 2133
                    goto error;
                }
            }

2134 2135
            virBufferAsprintf(&opt, ",bus=%s.0,channel=%d,scsi-id=%d,lun=%d",
                              contAlias,
2136 2137 2138 2139
                              disk->info.addr.drive.bus,
                              disk->info.addr.drive.target,
                              disk->info.addr.drive.unit);
        }
2140 2141 2142 2143

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

2144
        break;
2145

J
Jim Fehlig 已提交
2146
    case VIR_DOMAIN_DISK_BUS_SATA:
2147
        if (disk->info.addr.drive.bus != 0) {
2148 2149
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("bus must be 0 for ide controller"));
2150 2151 2152
            goto error;
        }
        if (disk->info.addr.drive.target != 0) {
2153 2154
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("target must be 0 for ide controller"));
2155 2156
            goto error;
        }
2157

2158 2159 2160 2161
        if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
            virBufferAddLit(&opt, "ide-cd");
        else
            virBufferAddLit(&opt, "ide-hd");
2162

2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174
        /* 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;
        }
2175 2176 2177
        virBufferAsprintf(&opt, ",bus=%s.%d",
                          contAlias,
                          disk->info.addr.drive.unit);
J
Jim Fehlig 已提交
2178
        break;
2179

2180
    case VIR_DOMAIN_DISK_BUS_VIRTIO:
2181
        if (qemuBuildVirtioDevStr(&opt, "virtio-blk", qemuCaps,
2182
                                  VIR_DOMAIN_DEVICE_DISK, disk) < 0) {
2183
            goto error;
2184
        }
2185

2186
        if (disk->iothread)
2187 2188
            virBufferAsprintf(&opt, ",iothread=iothread%u", disk->iothread);

2189
        qemuBuildIoEventFdStr(&opt, disk->ioeventfd, qemuCaps);
2190
        if (disk->event_idx &&
2191
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_EVENT_IDX)) {
2192
            virBufferAsprintf(&opt, ",event_idx=%s",
J
Ján Tomko 已提交
2193
                              virTristateSwitchTypeToString(disk->event_idx));
2194
        }
2195
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SCSI)) {
2196 2197 2198 2199 2200 2201 2202
            /* 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");
        }
2203

L
Lin Ma 已提交
2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214
        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);
        }

2215 2216 2217
        if (qemuBuildVirtioOptionsStr(&opt, disk->virtio, qemuCaps) < 0)
            goto error;

2218
        if (qemuBuildDeviceAddressStr(&opt, def, &disk->info, qemuCaps) < 0)
A
Alex Jia 已提交
2219
            goto error;
2220
        break;
2221

2222
    case VIR_DOMAIN_DISK_BUS_USB:
2223 2224 2225 2226 2227 2228
        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;
        }
2229 2230 2231 2232 2233 2234 2235
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("This QEMU doesn't support '-device "
                             "usb-storage'"));
            goto error;

        }
2236
        virBufferAddLit(&opt, "usb-storage");
2237

2238
        if (qemuBuildDeviceAddressStr(&opt, def, &disk->info, qemuCaps) < 0)
2239
            goto error;
2240
        break;
2241

2242 2243 2244 2245
    case VIR_DOMAIN_DISK_BUS_FDC:
        virBufferAsprintf(&opt, "floppy,unit=%d", disk->info.addr.drive.unit);
        break;

2246 2247 2248 2249
    case VIR_DOMAIN_DISK_BUS_XEN:
    case VIR_DOMAIN_DISK_BUS_UML:
    case VIR_DOMAIN_DISK_BUS_SD:
    case VIR_DOMAIN_DISK_BUS_LAST:
2250
    default:
2251 2252
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported disk bus '%s' with device setup"), bus);
2253 2254
        goto error;
    }
2255

2256 2257 2258 2259
    if (disk->src->shared &&
        virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_SHARE_RW))
        virBufferAddLit(&opt, ",share-rw=on");

2260
    if (qemuDomainDiskGetBackendAlias(disk, qemuCaps, &backendAlias) < 0)
2261
        goto error;
2262 2263 2264 2265 2266

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

    virBufferAsprintf(&opt, ",id=%s", disk->info.alias);
2267
    if (bootindex)
2268
        virBufferAsprintf(&opt, ",bootindex=%u", bootindex);
2269
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKIO)) {
V
Viktor Mihajlovski 已提交
2270
        if (disk->blockio.logical_block_size > 0)
2271
            virBufferAsprintf(&opt, ",logical_block_size=%u",
V
Viktor Mihajlovski 已提交
2272 2273
                              disk->blockio.logical_block_size);
        if (disk->blockio.physical_block_size > 0)
2274
            virBufferAsprintf(&opt, ",physical_block_size=%u",
V
Viktor Mihajlovski 已提交
2275
                              disk->blockio.physical_block_size);
2276
    }
2277

2278 2279 2280 2281 2282 2283
    if (disk->wwn) {
        if (STRPREFIX(disk->wwn, "0x"))
            virBufferAsprintf(&opt, ",wwn=%s", disk->wwn);
        else
            virBufferAsprintf(&opt, ",wwn=0x%s", disk->wwn);
    }
2284

2285 2286 2287 2288
    if (disk->vendor) {
        virBufferAddLit(&opt, ",vendor=");
        virQEMUBuildBufferEscapeComma(&opt, disk->vendor);
    }
2289

2290 2291 2292 2293
    if (disk->product) {
        virBufferAddLit(&opt, ",product=");
        virQEMUBuildBufferEscapeComma(&opt, disk->product);
    }
2294

2295 2296
    if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_STORAGE_REMOVABLE)) {
J
Ján Tomko 已提交
2297
            if (disk->removable == VIR_TRISTATE_SWITCH_ON)
2298 2299 2300 2301
                virBufferAddLit(&opt, ",removable=on");
            else
                virBufferAddLit(&opt, ",removable=off");
        } else {
J
Ján Tomko 已提交
2302
            if (disk->removable != VIR_TRISTATE_SWITCH_ABSENT) {
2303 2304 2305 2306 2307 2308 2309 2310
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("This QEMU doesn't support setting the "
                                 "removable flag of USB storage devices"));
                goto error;
            }
        }
    }

2311 2312 2313
    if (qemuBuildDriveDevCacheStr(disk, &opt, qemuCaps) < 0)
        goto error;

2314 2315
    qemuBuildDiskFrontendAttributes(disk, &opt);

2316 2317 2318
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_STORAGE_WERROR))
        qemuBuildDiskFrontendAttributeErrorPolicy(disk, &opt);

2319
    if (virBufferCheckError(&opt) < 0)
2320 2321 2322 2323
        goto error;

    return virBufferContentAndReset(&opt);

2324
 error:
2325 2326 2327
    return NULL;
}

2328 2329 2330
char *
qemuBuildZPCIDevStr(virDomainDeviceInfoPtr dev)
{
2331
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
2332 2333 2334 2335 2336 2337 2338 2339

    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);

2340
    if (virBufferCheckError(&buf) < 0)
2341 2342 2343 2344 2345 2346 2347 2348 2349
        return NULL;

    return virBufferContentAndReset(&buf);
}

static int
qemuCommandAddZPCIDevice(virCommandPtr cmd,
                         virDomainDeviceInfoPtr dev)
{
2350
    VIR_AUTOFREE(char *) devstr = 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

    virCommandAddArg(cmd, "-device");

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

    virCommandAddArg(cmd, 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;
}
2376

2377
static int
2378 2379 2380 2381
qemuBuildFloppyCommandLineControllerOptions(virCommandPtr cmd,
                                            const virDomainDef *def,
                                            virQEMUCapsPtr qemuCaps,
                                            unsigned int bootFloppy)
2382
{
2383
    VIR_AUTOCLEAN(virBuffer) fdc_opts = VIR_BUFFER_INITIALIZER;
2384 2385 2386
    bool explicitfdc = qemuDomainNeedsFDC(def);
    bool hasfloppy = false;
    unsigned int bootindex;
2387
    char driveLetter;
2388
    size_t i;
2389
    int ret = -1;
2390

2391
    virBufferAddLit(&fdc_opts, "isa-fdc,");
2392

2393
    for (i = 0; i < def->ndisks; i++) {
2394 2395 2396
        VIR_AUTOFREE(char *) backendAlias = NULL;
        VIR_AUTOFREE(char *) backendStr = NULL;
        VIR_AUTOFREE(char *) bootindexStr = NULL;
2397
        virDomainDiskDefPtr disk = def->disks[i];
2398

2399 2400
        if (disk->bus != VIR_DOMAIN_DISK_BUS_FDC)
            continue;
2401

2402
        hasfloppy = true;
2403

2404 2405 2406 2407 2408
        if (disk->info.bootIndex) {
            bootindex = disk->info.bootIndex;
        } else {
            bootindex = bootFloppy;
            bootFloppy = 0;
2409 2410
        }

2411 2412 2413 2414 2415 2416 2417 2418 2419
        if (disk->info.addr.drive.unit)
            driveLetter = 'B';
        else
            driveLetter = 'A';

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

2420 2421 2422 2423 2424 2425 2426 2427 2428 2429
        /* 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;
        }

2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442
        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);
2443
        }
2444 2445 2446
    }

    if (explicitfdc && hasfloppy) {
2447 2448
        /* Newer Q35 machine types require an explicit FDC controller */
        virBufferTrim(&fdc_opts, ",", -1);
2449
        virCommandAddArg(cmd, "-device");
2450
        virCommandAddArgBuffer(cmd, &fdc_opts);
2451 2452
    }

2453 2454 2455 2456
    ret = 0;

 cleanup:
    return ret;
2457 2458 2459
}


2460
static int
2461 2462
qemuBuildObjectCommandline(virCommandPtr cmd,
                           virJSONValuePtr objProps)
2463
{
2464
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
2465

2466
    if (!objProps)
2467 2468
        return 0;

2469
    if (virQEMUBuildObjectCommandlineFromJSON(&buf, objProps) < 0)
2470 2471 2472 2473 2474
        return -1;

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

2475 2476 2477 2478 2479 2480 2481 2482
    return 0;
}


static int
qemuBuildBlockStorageSourceAttachDataCommandline(virCommandPtr cmd,
                                                 qemuBlockStorageSourceAttachDataPtr data)
{
2483 2484
    char *tmp;

2485 2486 2487 2488 2489 2490 2491 2492 2493
    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);

2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509
    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);
    }

2510
    return 0;
2511 2512 2513
}


2514
static int
2515 2516
qemuBuildDiskSourceCommandLine(virCommandPtr cmd,
                               virDomainDiskDefPtr disk,
2517
                               virQEMUCapsPtr qemuCaps)
2518
{
2519
    VIR_AUTOPTR(qemuBlockStorageSourceChainData) data = NULL;
2520 2521
    VIR_AUTOPTR(virJSONValue) copyOnReadProps = NULL;
    VIR_AUTOFREE(char *) copyOnReadPropsStr = NULL;
2522
    size_t i;
2523

2524
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) {
2525 2526
        if (virStorageSourceIsEmpty(disk->src))
            return 0;
2527

2528 2529
        if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(disk->src,
                                                                      qemuCaps)))
2530
            return -1;
2531 2532 2533

        if (disk->copy_on_read == VIR_TRISTATE_SWITCH_ON &&
            !(copyOnReadProps = qemuBlockStorageGetCopyOnReadProps(disk)))
2534
            return -1;
2535
    } else {
2536
        if (!(data = qemuBuildStorageSourceChainAttachPrepareDrive(disk, qemuCaps)))
2537
            return -1;
2538 2539
    }

2540
    for (i = data->nsrcdata; i > 0; i--) {
2541
        if (qemuBuildBlockStorageSourceAttachDataCommandline(cmd,
2542
                                                             data->srcdata[i - 1]) < 0)
2543
            return -1;
2544 2545 2546
    }

    if (copyOnReadProps) {
2547
        if (!(copyOnReadPropsStr = virJSONValueToString(copyOnReadProps, false)))
2548
            return -1;
2549

2550
        virCommandAddArgList(cmd, "-blockdev", copyOnReadPropsStr, NULL);
2551
    }
2552

2553
    return 0;
2554 2555 2556 2557 2558 2559 2560 2561
}


static int
qemuBuildDiskCommandLine(virCommandPtr cmd,
                         const virDomainDef *def,
                         virDomainDiskDefPtr disk,
                         virQEMUCapsPtr qemuCaps,
2562
                         unsigned int bootindex)
2563
{
2564
    VIR_AUTOFREE(char *) optstr = NULL;
2565

2566
    if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps) < 0)
2567
        return -1;
2568

2569
    if (!qemuDiskBusNeedsDriveArg(disk->bus)) {
2570 2571
        if (disk->bus != VIR_DOMAIN_DISK_BUS_FDC ||
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) {
2572 2573 2574
            if (qemuCommandAddExtDevice(cmd, &disk->info) < 0)
                return -1;

2575 2576
            virCommandAddArg(cmd, "-device");

2577 2578
            if (!(optstr = qemuBuildDiskDeviceStr(def, disk, bootindex,
                                                  qemuCaps)))
2579 2580 2581 2582 2583 2584 2585 2586 2587
                return -1;
            virCommandAddArg(cmd, optstr);
        }
    }

    return 0;
}


2588
static int
2589 2590 2591
qemuBuildDisksCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
2592 2593
{
    size_t i;
2594 2595 2596
    unsigned int bootCD = 0;
    unsigned int bootFloppy = 0;
    unsigned int bootDisk = 0;
2597
    bool blockdev = virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV);
2598

2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609
    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;
2610 2611 2612
        }
    }

2613 2614 2615 2616 2617 2618
    /* 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;

2619
    for (i = 0; i < def->ndisks; i++) {
2620
        virDomainDiskDefPtr disk = def->disks[i];
2621
        unsigned int bootindex = 0;
2622

2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636
        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;
            }
2637 2638
        }

2639 2640 2641 2642 2643 2644
        /* 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)
2645
            return -1;
2646
    }
2647

2648 2649
    if (!blockdev &&
        qemuBuildFloppyCommandLineControllerOptions(cmd, def, qemuCaps, bootFloppy) < 0)
2650 2651
        return -1;

2652 2653 2654 2655
    return 0;
}


2656
static char *
2657
qemuBuildFSStr(virDomainFSDefPtr fs)
2658
{
2659
    VIR_AUTOCLEAN(virBuffer) opt = VIR_BUFFER_INITIALIZER;
2660
    const char *wrpolicy = virDomainFSWrpolicyTypeToString(fs->wrpolicy);
2661

2662 2663
    if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_PATH ||
        fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_DEFAULT) {
2664
        virBufferAddLit(&opt, "local");
2665 2666
        if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_MAPPED) {
            virBufferAddLit(&opt, ",security_model=mapped");
2667
        } else if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
2668
            virBufferAddLit(&opt, ",security_model=passthrough");
2669
        } else if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_SQUASH) {
2670 2671
            virBufferAddLit(&opt, ",security_model=none");
        }
2672 2673 2674
    } else if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE) {
        /* removed since qemu 4.0.0 see v3.1.0-29-g93aee84f57 */
        virBufferAddLit(&opt, "handle");
2675
    }
2676

2677 2678
    if (fs->wrpolicy)
        virBufferAsprintf(&opt, ",writeout=%s", wrpolicy);
2679

2680
    virBufferAsprintf(&opt, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
2681 2682
    virBufferAddLit(&opt, ",path=");
    virQEMUBuildBufferEscapeComma(&opt, fs->src->path);
2683

2684 2685
    if (fs->readonly)
        virBufferAddLit(&opt, ",readonly");
2686

2687
    if (virBufferCheckError(&opt) < 0)
2688
        return NULL;
2689 2690 2691 2692 2693

    return virBufferContentAndReset(&opt);
}


2694 2695
static char *
qemuBuildFSDevStr(const virDomainDef *def,
2696
                  virDomainFSDefPtr fs,
2697
                  virQEMUCapsPtr qemuCaps)
2698
{
2699
    VIR_AUTOCLEAN(virBuffer) opt = VIR_BUFFER_INITIALIZER;
2700

2701
    if (qemuBuildVirtioDevStr(&opt, "virtio-9p", qemuCaps,
2702 2703
                              VIR_DOMAIN_DEVICE_FS, fs) < 0)
        return NULL;
2704

2705
    virBufferAsprintf(&opt, ",id=%s", fs->info.alias);
2706 2707
    virBufferAsprintf(&opt, ",fsdev=%s%s",
                      QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
2708 2709
    virBufferAddLit(&opt, ",mount_tag=");
    virQEMUBuildBufferEscapeComma(&opt, fs->dst);
A
Alex Jia 已提交
2710

2711
    if (qemuBuildVirtioOptionsStr(&opt, fs->virtio, qemuCaps) < 0)
2712
        return NULL;
2713

2714
    if (qemuBuildDeviceAddressStr(&opt, def, &fs->info, qemuCaps) < 0)
2715
        return NULL;
2716

2717
    if (virBufferCheckError(&opt) < 0)
2718
        return NULL;
2719 2720 2721 2722 2723

    return virBufferContentAndReset(&opt);
}


2724 2725 2726 2727 2728 2729
static int
qemuBuildFSDevCommandLine(virCommandPtr cmd,
                          virDomainFSDefPtr fs,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
2730 2731
    VIR_AUTOFREE(char *) fsdevstr = NULL;
    VIR_AUTOFREE(char *) devicestr = NULL;
2732 2733

    virCommandAddArg(cmd, "-fsdev");
2734
    if (!(fsdevstr = qemuBuildFSStr(fs)))
2735
        return -1;
2736
    virCommandAddArg(cmd, fsdevstr);
2737 2738 2739 2740 2741

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

    virCommandAddArg(cmd, "-device");
2742
    if (!(devicestr = qemuBuildFSDevStr(def, fs, qemuCaps)))
2743
        return -1;
2744
    virCommandAddArg(cmd, devicestr);
2745 2746 2747 2748 2749

    return 0;
}


2750
static int
2751 2752 2753
qemuBuildFilesystemCommandLine(virCommandPtr cmd,
                               const virDomainDef *def,
                               virQEMUCapsPtr qemuCaps)
2754 2755 2756 2757
{
    size_t i;

    for (i = 0; i < def->nfss; i++) {
2758
        if (qemuBuildFSDevCommandLine(cmd, def->fss[i], def, qemuCaps) < 0)
2759 2760 2761 2762 2763 2764 2765
            return -1;
    }

    return 0;
}


2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784
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 已提交
2785 2786
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI:
        return QEMU_CAPS_NEC_USB_XHCI;
2787 2788
    case VIR_DOMAIN_CONTROLLER_MODEL_USB_QEMU_XHCI:
        return QEMU_CAPS_DEVICE_QEMU_XHCI;
2789 2790 2791 2792 2793 2794
    default:
        return -1;
    }
}


2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819
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;
}


2820
static int
2821 2822
qemuBuildUSBControllerDevStr(const virDomainDef *domainDef,
                             virDomainControllerDefPtr def,
2823
                             virQEMUCapsPtr qemuCaps,
2824 2825 2826
                             virBuffer *buf)
{
    const char *smodel;
2827
    int model, flags;
2828 2829

    model = def->model;
2830

2831
    if (model == VIR_DOMAIN_CONTROLLER_MODEL_USB_DEFAULT) {
2832 2833 2834
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       "%s", _("no model provided for USB controller"));
        return -1;
2835
    }
2836 2837

    smodel = qemuControllerModelUSBTypeToString(model);
2838
    flags = qemuControllerModelUSBToCaps(model);
2839

2840
    if (flags == -1 || !virQEMUCapsGet(qemuCaps, flags)) {
2841 2842
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("%s not supported in this QEMU binary"), smodel);
2843 2844 2845
        return -1;
    }

2846 2847
    virBufferAsprintf(buf, "%s", smodel);

2848
    if (def->opts.usbopts.ports != -1) {
2849 2850 2851
        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) {
2852 2853 2854 2855 2856 2857 2858 2859 2860 2861
            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);
    }

2862 2863 2864 2865 2866 2867 2868 2869
    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;
        }
2870
        virBufferAsprintf(buf, ",masterbus=%s.0,firstport=%d",
2871 2872
                          masterbus, def->info.master.usb.startport);
    } else {
2873
        virBufferAsprintf(buf, ",id=%s", def->info.alias);
2874
    }
2875

2876 2877 2878
    return 0;
}

2879

2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900
/**
 * 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
2901
qemuBuildControllerDevStr(const virDomainDef *domainDef,
2902
                          virDomainControllerDefPtr def,
2903
                          virQEMUCapsPtr qemuCaps,
2904
                          char **devstr)
2905
{
2906
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
2907

2908 2909
    *devstr = NULL;

2910
    switch ((virDomainControllerType)def->type) {
2911
    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
2912
        switch ((virDomainControllerModelSCSI) def->model) {
2913
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI:
2914 2915
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL:
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL:
2916
            if (qemuBuildVirtioDevStr(&buf, "virtio-scsi", qemuCaps,
2917
                                      VIR_DOMAIN_DEVICE_CONTROLLER, def) < 0) {
2918
                goto error;
2919
            }
2920 2921 2922 2923 2924 2925

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

2926 2927
            if (qemuBuildVirtioOptionsStr(&buf, def->virtio, qemuCaps) < 0)
                goto error;
2928
            break;
2929
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC:
2930
            virBufferAddLit(&buf, "lsi");
2931 2932 2933 2934
            break;
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
            virBufferAddLit(&buf, "spapr-vscsi");
            break;
2935 2936 2937
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068:
            virBufferAddLit(&buf, "mptsas1068");
            break;
2938 2939 2940
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078:
            virBufferAddLit(&buf, "megasas");
            break;
2941 2942 2943
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO:
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC:
        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI:
2944 2945 2946
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unsupported controller model: %s"),
                           virDomainControllerModelSCSITypeToString(def->model));
2947 2948 2949 2950 2951 2952 2953
            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;
2954
        }
2955
        virBufferAsprintf(&buf, ",id=%s", def->info.alias);
2956 2957 2958
        break;

    case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
2959
        if (qemuBuildVirtioDevStr(&buf, "virtio-serial", qemuCaps,
2960
                                  VIR_DOMAIN_DEVICE_CONTROLLER, def) < 0) {
2961
            goto error;
2962
        }
2963

2964
        virBufferAsprintf(&buf, ",id=%s", def->info.alias);
2965
        if (def->opts.vioserial.ports != -1) {
2966
            virBufferAsprintf(&buf, ",max_ports=%d",
2967 2968 2969
                              def->opts.vioserial.ports);
        }
        if (def->opts.vioserial.vectors != -1) {
2970
            virBufferAsprintf(&buf, ",vectors=%d",
2971 2972
                              def->opts.vioserial.vectors);
        }
2973 2974
        if (qemuBuildVirtioOptionsStr(&buf, def->virtio, qemuCaps) < 0)
            goto error;
2975 2976
        break;

E
Eric Blake 已提交
2977
    case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
2978
        virBufferAsprintf(&buf, "usb-ccid,id=%s", def->info.alias);
E
Eric Blake 已提交
2979 2980
        break;

J
Jim Fehlig 已提交
2981
    case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
2982
        virBufferAsprintf(&buf, "ahci,id=%s", def->info.alias);
J
Jim Fehlig 已提交
2983 2984
        break;

2985
    case VIR_DOMAIN_CONTROLLER_TYPE_USB:
2986
        if (qemuBuildUSBControllerDevStr(domainDef, def, qemuCaps, &buf) == -1)
2987 2988 2989 2990
            goto error;

        break;

2991 2992 2993
    case VIR_DOMAIN_CONTROLLER_TYPE_PCI: {
        const virDomainPCIControllerOpts *pciopts = &def->opts.pciopts;
        const char *modelName = virDomainControllerPCIModelNameTypeToString(pciopts->modelName);
2994

2995 2996 2997 2998 2999 3000 3001
        /* 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;
        }

3002 3003 3004 3005 3006 3007 3008
        if (!modelName) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unknown virDomainControllerPCIModelName value: %d"),
                           pciopts->modelName);
            return -1;
        }

3009
        switch ((virDomainControllerModelPCI) def->model) {
3010
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
3011
            virBufferAsprintf(&buf, "%s,chassis_nr=%d,id=%s",
3012
                              modelName, pciopts->chassisNr,
3013
                              def->info.alias);
3014
            break;
3015
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS:
3016
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS:
3017
            virBufferAsprintf(&buf, "%s,bus_nr=%d,id=%s",
3018
                              modelName, pciopts->busNr,
3019
                              def->info.alias);
3020 3021 3022 3023
            if (pciopts->numaNode != -1) {
                virBufferAsprintf(&buf, ",numa_node=%d",
                                  pciopts->numaNode);
            }
3024
            break;
3025
        case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
3026
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
3027
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE:
3028 3029
            virBufferAsprintf(&buf, "%s,id=%s", modelName, def->info.alias);
            break;
3030
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
3031 3032
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
            virBufferAsprintf(&buf, "%s,port=0x%x,chassis=%d,id=%s",
3033 3034
                              modelName, pciopts->port,
                              pciopts->chassis, def->info.alias);
3035
            break;
3036
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
3037
            virBufferAsprintf(&buf, "%s,index=%d,id=%s",
3038
                              modelName, pciopts->targetIndex,
3039
                              def->info.alias);
3040

3041
            if (pciopts->numaNode != -1)
3042
                virBufferAsprintf(&buf, ",numa_node=%d", pciopts->numaNode);
3043
            break;
3044
        case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
3045 3046 3047 3048
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Unsupported PCI Express root controller"));
            goto error;
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT:
3049
        case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
3050 3051 3052
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unexpected PCI controller model %d"),
                           def->model);
3053 3054
            goto error;
        }
3055
        break;
3056
    }
3057

3058
    case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
3059
    case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
3060
    case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
3061
    case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
3062
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3063
                       _("Unsupported controller type: %s"),
3064
                       virDomainControllerTypeToString(def->type));
3065 3066 3067
        goto error;
    }

3068 3069
    if (def->queues)
        virBufferAsprintf(&buf, ",num_queues=%u", def->queues);
3070

3071 3072 3073 3074 3075 3076
    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);

3077 3078
    qemuBuildIoEventFdStr(&buf, def->ioeventfd, qemuCaps);

3079
    if (qemuBuildDeviceAddressStr(&buf, domainDef, &def->info, qemuCaps) < 0)
3080 3081
        goto error;

3082
 done:
3083
    if (virBufferCheckError(&buf) < 0)
3084 3085
        goto error;

3086 3087
    *devstr = virBufferContentAndReset(&buf);
    return 0;
3088

3089
 error:
3090
    return -1;
3091 3092 3093
}


3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105
static bool
qemuBuildDomainForbidLegacyUSBController(const virDomainDef *def)
{
    if (qemuDomainIsQ35(def) ||
        qemuDomainIsARMVirt(def) ||
        qemuDomainIsRISCVVirt(def))
        return true;

    return false;
}


3106 3107
static int
qemuBuildLegacyUSBControllerCommandLine(virCommandPtr cmd,
3108
                                        const virDomainDef *def)
3109
{
3110
    size_t i;
3111
    size_t nlegacy = 0;
3112
    size_t nusb = 0;
3113 3114 3115 3116 3117 3118 3119 3120 3121 3122

    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;
3123 3124 3125

        if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_DEFAULT)
            nlegacy++;
3126 3127
        else
            nusb++;
3128 3129 3130 3131 3132 3133 3134
    }

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

3137
    if (nusb == 0 &&
3138
        !qemuBuildDomainForbidLegacyUSBController(def) &&
3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149
        !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;
}


3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187
/**
 * 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;
}


3188 3189 3190 3191 3192 3193
static int
qemuBuildControllersByTypeCommandLine(virCommandPtr cmd,
                                      const virDomainDef *def,
                                      virQEMUCapsPtr qemuCaps,
                                      virDomainControllerType type)
{
3194
    char *devstr = NULL;
3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231
    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;
        }

3232
        VIR_FREE(devstr);
3233 3234 3235 3236
        if (qemuBuildControllerDevStr(def, cont, qemuCaps, &devstr) < 0)
            goto cleanup;

        if (devstr) {
3237
            if (qemuCommandAddExtDevice(cmd, &cont->info) < 0)
3238 3239 3240 3241 3242 3243 3244 3245 3246
                goto cleanup;

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

    ret = 0;
 cleanup:
3247
    VIR_FREE(devstr);
3248 3249 3250 3251
    return ret;
}


3252
static int
3253 3254 3255
qemuBuildControllersCommandLine(virCommandPtr cmd,
                                const virDomainDef *def,
                                virQEMUCapsPtr qemuCaps)
3256
{
3257
    size_t i;
3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272
    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.
3273 3274 3275
         *
         * CCID controllers are formatted separately after USB hubs,
         * because they go on the USB bus.
3276 3277 3278 3279 3280 3281 3282 3283
         */
        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,
    };
3284
    int ret = -1;
3285

3286 3287
    for (i = 0; i < ARRAY_CARDINALITY(contOrder); i++) {
        if (qemuBuildControllersByTypeCommandLine(cmd, def, qemuCaps, contOrder[i]) < 0)
3288
            goto cleanup;
3289 3290
    }

3291
    if (qemuBuildLegacyUSBControllerCommandLine(cmd, def) < 0)
3292
        goto cleanup;
3293

3294 3295 3296 3297
    ret = 0;

 cleanup:
    return ret;
3298 3299 3300
}


M
Marc-André Lureau 已提交
3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320
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;
}


3321
static int
3322 3323
qemuBuildMemoryGetDefaultPagesize(virQEMUDriverConfigPtr cfg,
                                  unsigned long long *pagesize)
3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341
{
    virHugeTLBFSPtr p;

    if (!cfg->nhugetlbfs) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("hugetlbfs filesystem is not mounted "
                               "or disabled by administrator config"));
        return -1;
    }

    if (!(p = virFileGetDefaultHugepage(cfg->hugetlbfs, cfg->nhugetlbfs)))
        p = &cfg->hugetlbfs[0];

    *pagesize = p->size;
    return 0;
}


3342
/**
3343
 * qemuBuildMemoryBackendProps:
3344
 * @backendProps: [out] constructed object
3345
 * @alias: alias of the device
3346
 * @cfg: qemu driver config object
3347
 * @priv: pointer to domain private object
3348 3349 3350 3351 3352
 * @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
3353
 * NUMA node (domain @def and @mem). Use @priv->autoNodeset to fine tune the
3354 3355 3356 3357 3358
 * 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.
3359
 *
3360 3361
 * Then, if one of the three memory-backend-* should be used, the @priv->qemuCaps
 * is consulted to check if qemu does support it.
3362
 *
3363 3364 3365
 * Returns: 0 on success,
 *          1 on success and if there's no need to use memory-backend-*
 *         -1 on error.
3366
 */
3367
int
3368
qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
3369
                            const char *alias,
3370
                            virQEMUDriverConfigPtr cfg,
3371
                            qemuDomainObjPrivatePtr priv,
3372 3373 3374
                            virDomainDefPtr def,
                            virDomainMemoryDefPtr mem,
                            bool force)
3375
{
3376
    const char *backendType = "memory-backend-file";
3377
    virDomainNumatuneMemMode mode;
3378
    const long system_page_size = virGetSystemPageSizeKB();
3379
    virDomainMemoryAccess memAccess = mem->access;
3380
    size_t i;
3381
    VIR_AUTOFREE(char *) memPath = NULL;
M
Michal Privoznik 已提交
3382
    bool prealloc = false;
3383
    virBitmapPtr nodemask = NULL;
3384
    int ret = -1;
3385
    VIR_AUTOPTR(virJSONValue) props = NULL;
3386 3387
    bool nodeSpecified = virDomainNumatuneNodeSpecified(def->numa, mem->targetNode);
    unsigned long long pagesize = mem->pagesize;
3388
    bool needHugepage = !!pagesize;
3389
    bool useHugepage = !!pagesize;
3390
    int discard = mem->discard;
3391 3392 3393 3394 3395 3396

    /* 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. */
3397

3398 3399
    *backendProps = NULL;

3400
    if (mem->targetNode >= 0) {
3401
        /* memory devices could provide a invalid guest node */
3402
        if (mem->targetNode >= virDomainNumaGetNodeCount(def->numa)) {
3403 3404 3405
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("can't add memory backend for guest node '%d' as "
                             "the guest has only '%zu' NUMA nodes configured"),
3406
                           mem->targetNode, virDomainNumaGetNodeCount(def->numa));
3407 3408
            return -1;
        }
3409

3410 3411 3412 3413 3414
        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);
3415
    }
3416

3417 3418 3419
    if (memAccess == VIR_DOMAIN_MEMORY_ACCESS_DEFAULT)
        memAccess = def->mem.access;

3420 3421 3422
    if (discard == VIR_TRISTATE_BOOL_ABSENT)
        discard = def->mem.discard;

3423
    if (virDomainNumatuneGetMode(def->numa, mem->targetNode, &mode) < 0 &&
3424 3425
        virDomainNumatuneGetMode(def->numa, -1, &mode) < 0)
        mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
3426

3427
    if (pagesize == 0) {
3428 3429
        virDomainHugePagePtr master_hugepage = NULL;
        virDomainHugePagePtr hugepage = NULL;
3430 3431
        bool thisHugepage = false;

3432 3433 3434 3435 3436 3437 3438 3439 3440
        /* 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;
            }

3441
            /* just find the master hugepage in case we don't use NUMA */
3442
            if (mem->targetNode < 0)
3443 3444
                continue;

3445
            if (virBitmapGetBit(hugepage->nodemask, mem->targetNode,
3446 3447 3448 3449 3450 3451 3452 3453 3454
                                &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 */
3455
                needHugepage = true;
3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466
                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;
        }

3467
        if (hugepage) {
3468
            pagesize = hugepage->size;
3469 3470
            useHugepage = true;
        }
3471
    }
3472

3473 3474 3475 3476 3477
    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;
3478 3479
        needHugepage = false;
        useHugepage = false;
3480
    } else if (useHugepage && pagesize == 0) {
3481
        if (qemuBuildMemoryGetDefaultPagesize(cfg, &pagesize) < 0)
3482
            goto cleanup;
3483 3484
    }

3485 3486 3487
    if (!(props = virJSONValueNewObject()))
        return -1;

M
Marc-André Lureau 已提交
3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500
    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 已提交
3501
        def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) {
3502

3503 3504
        if (mem->nvdimmPath) {
            if (VIR_STRDUP(memPath, mem->nvdimmPath) < 0)
3505
                goto cleanup;
3506 3507
            if (!priv->memPrealloc)
                prealloc = true;
3508 3509
        } else if (useHugepage) {
            if (qemuGetDomainHupageMemPath(def, cfg, pagesize, &memPath) < 0)
3510
                goto cleanup;
3511 3512
            if (!priv->memPrealloc)
                prealloc = true;
3513
        } else {
3514 3515
            /* We can have both pagesize and mem source. If that's the case,
             * prefer hugepages as those are more specific. */
3516
            if (qemuGetMemoryBackingPath(def, cfg, mem->info.alias, &memPath) < 0)
3517 3518
                goto cleanup;
        }
3519

M
Michal Privoznik 已提交
3520 3521 3522 3523 3524 3525
        if (virJSONValueObjectAdd(props,
                                  "B:prealloc", prealloc,
                                  "s:mem-path", memPath,
                                  NULL) < 0)
            goto cleanup;

3526 3527
        if (!mem->nvdimmPath &&
            discard == VIR_TRISTATE_BOOL_YES) {
3528
            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE_DISCARD)) {
3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539
                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 已提交
3540 3541
        if (qemuBuildMemoryBackendPropsShare(props, memAccess) < 0)
            goto cleanup;
3542
    } else {
3543
        backendType = "memory-backend-ram";
3544 3545
    }

3546
    if (virJSONValueObjectAdd(props, "U:size", mem->size * 1024, NULL) < 0)
3547
        goto cleanup;
3548

3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559
    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;
    }

3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570
    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;
    }

3571 3572
    if (mem->sourceNodes) {
        nodemask = mem->sourceNodes;
3573
    } else {
3574
        if (virDomainNumatuneMaybeGetNodeset(def->numa, priv->autoNodeset,
3575
                                             &nodemask, mem->targetNode) < 0)
3576 3577 3578 3579
            goto cleanup;
    }

    if (nodemask) {
3580 3581
        if (!virNumaNodesetIsAvailable(nodemask))
            goto cleanup;
3582 3583 3584 3585
        if (virJSONValueObjectAdd(props,
                                  "m:host-nodes", nodemask,
                                  "S:policy", qemuNumaPolicyTypeToString(mode),
                                  NULL) < 0)
3586 3587 3588
            goto cleanup;
    }

3589
    /* If none of the following is requested... */
3590
    if (!needHugepage && !mem->sourceNodes && !nodeSpecified &&
M
Michal Privoznik 已提交
3591
        !mem->nvdimmPath &&
3592
        memAccess == VIR_DOMAIN_MEMORY_ACCESS_DEFAULT &&
M
Marc-André Lureau 已提交
3593 3594 3595
        def->mem.source != VIR_DOMAIN_MEMORY_SOURCE_FILE &&
        def->mem.source != VIR_DOMAIN_MEMORY_SOURCE_MEMFD &&
        !force) {
3596 3597 3598 3599 3600
        /* report back that using the new backend is not necessary
         * to achieve the desired configuration */
        ret = 1;
    } else {
        /* otherwise check the required capability */
3601
        if (STREQ(backendType, "memory-backend-file") &&
3602
            !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) {
3603 3604 3605 3606
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this qemu doesn't support the "
                             "memory-backend-file object"));
            goto cleanup;
3607
        } else if (STREQ(backendType, "memory-backend-ram") &&
3608
                   !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM)) {
3609 3610 3611
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this qemu doesn't support the "
                             "memory-backend-ram object"));
3612
            goto cleanup;
M
Marc-André Lureau 已提交
3613
        } else if (STREQ(backendType, "memory-backend-memory") &&
3614
                   !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD)) {
M
Marc-André Lureau 已提交
3615 3616 3617 3618
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this qemu doesn't support the "
                             "memory-backend-memfd object"));
            goto cleanup;
3619 3620
        }

3621
        ret = 0;
3622 3623
    }

3624 3625 3626
    if (!(*backendProps = qemuMonitorCreateObjectPropsWrap(backendType, alias,
                                                           &props)))
        ret = -1;
3627 3628 3629 3630 3631 3632 3633 3634 3635 3636

 cleanup:
    return ret;
}


static int
qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
                              virQEMUDriverConfigPtr cfg,
                              size_t cell,
3637
                              qemuDomainObjPrivatePtr priv,
3638
                              virBufferPtr buf)
3639
{
3640
    VIR_AUTOPTR(virJSONValue) props = NULL;
3641
    VIR_AUTOFREE(char *) alias = NULL;
3642 3643
    int ret = -1;
    int rc;
3644
    virDomainMemoryDef mem = { 0 };
3645 3646
    unsigned long long memsize = virDomainNumaGetNodeMemorySize(def->numa,
                                                                cell);
3647

3648 3649 3650
    if (virAsprintf(&alias, "ram-node%zu", cell) < 0)
        goto cleanup;

3651 3652
    mem.size = memsize;
    mem.targetNode = cell;
3653
    mem.info.alias = alias;
3654

3655 3656
    if ((rc = qemuBuildMemoryBackendProps(&props, alias, cfg,
                                          priv, def, &mem, false)) < 0)
3657 3658
        goto cleanup;

3659
    if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
3660 3661
        goto cleanup;

3662
    ret = rc;
3663 3664 3665

 cleanup:

3666 3667 3668 3669
    return ret;
}


3670 3671 3672
static int
qemuBuildMemoryDimmBackendStr(virBufferPtr buf,
                              virDomainMemoryDefPtr mem,
3673
                              virDomainDefPtr def,
3674
                              virQEMUDriverConfigPtr cfg,
3675
                              qemuDomainObjPrivatePtr priv)
3676
{
3677
    VIR_AUTOPTR(virJSONValue) props = NULL;
3678
    VIR_AUTOFREE(char *) alias = NULL;
3679
    int ret = -1;
3680 3681 3682 3683

    if (!mem->info.alias) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("memory device alias is not assigned"));
3684
        return -1;
3685 3686 3687 3688 3689
    }

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

3690 3691
    if (qemuBuildMemoryBackendProps(&props, alias, cfg,
                                    priv, def, mem, true) < 0)
3692 3693
        goto cleanup;

3694 3695 3696 3697
    if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
        goto cleanup;

    ret = 0;
3698 3699 3700 3701 3702 3703 3704

 cleanup:

    return ret;
}


3705
char *
3706 3707
qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
                         qemuDomainObjPrivatePtr priv)
3708
{
3709
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
M
Michal Privoznik 已提交
3710
    const char *device;
3711 3712 3713 3714 3715 3716 3717 3718

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

    switch ((virDomainMemoryModel) mem->model) {
M
Michal Privoznik 已提交
3719
    case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
3720
    case VIR_DOMAIN_MEMORY_MODEL_DIMM:
M
Michal Privoznik 已提交
3721 3722 3723 3724 3725 3726 3727

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

        virBufferAsprintf(&buf, "%s,", device);
3728 3729 3730 3731

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

3732 3733 3734
        if (mem->labelsize)
            virBufferAsprintf(&buf, "label-size=%llu,", mem->labelsize * 1024);

3735 3736 3737 3738 3739 3740 3741 3742 3743 3744
        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,");
        }

3745 3746
        virBufferAsprintf(&buf, "memdev=mem%s,id=%s",
                          mem->info.alias, mem->info.alias);
3747 3748 3749

        if (mem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM) {
            virBufferAsprintf(&buf, ",slot=%d", mem->info.addr.dimm.slot);
3750 3751
            if (mem->info.addr.dimm.base)
                virBufferAsprintf(&buf, ",addr=%llu", mem->info.addr.dimm.base);
3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768
        }

        break;

    case VIR_DOMAIN_MEMORY_MODEL_NONE:
    case VIR_DOMAIN_MEMORY_MODEL_LAST:
        break;

    }

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

    return virBufferContentAndReset(&buf);
}


3769
static char *
3770
qemuBuildLegacyNicStr(virDomainNetDefPtr net)
3771 3772
{
    char *str;
3773
    char macaddr[VIR_MAC_STRING_BUFLEN];
3774
    const char *netmodel = virDomainNetGetModelString(net);
3775

3776
    ignore_value(virAsprintf(&str,
3777
                             "nic,macaddr=%s,netdev=host%s%s%s%s%s",
3778
                             virMacAddrFormat(&net->mac, macaddr),
3779
                             net->info.alias,
3780 3781
                             netmodel ? ",model=" : "",
                             NULLSTR_EMPTY(netmodel),
3782
                             (net->info.alias ? ",id=" : ""),
J
Ján Tomko 已提交
3783
                             NULLSTR_EMPTY(net->info.alias)));
3784 3785 3786 3787 3788
    return str;
}


char *
3789
qemuBuildNicDevStr(virDomainDefPtr def,
3790
                   virDomainNetDefPtr net,
3791
                   unsigned int bootindex,
3792
                   size_t vhostfdSize,
3793
                   virQEMUCapsPtr qemuCaps)
3794
{
3795
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
3796
    bool usingVirtio = false;
3797
    char macaddr[VIR_MAC_STRING_BUFLEN];
3798

3799
    if (virDomainNetIsVirtioModel(net)) {
3800
        if (qemuBuildVirtioDevStr(&buf, "virtio-net", qemuCaps,
3801
                                  VIR_DOMAIN_DEVICE_NET, net) < 0) {
3802
            goto error;
3803
        }
3804

3805
        usingVirtio = true;
3806
    } else {
3807
        virBufferAddStr(&buf, virDomainNetGetModelString(net));
3808 3809
    }

3810
    if (usingVirtio && net->driver.virtio.txmode) {
3811
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_TX_ALG)) {
3812 3813 3814 3815 3816 3817 3818 3819 3820
            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;
3821 3822 3823 3824 3825

                case VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT:
                    break;

                case VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST:
3826 3827 3828 3829
                default:
                    /* this should never happen, if it does, we need
                     * to add another case to this switch.
                     */
3830 3831
                    virReportEnumRangeError(virDomainNetVirtioTxModeType,
                                            net->driver.virtio.txmode);
3832 3833 3834
                    goto error;
            }
        } else {
3835 3836
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("virtio-net-pci 'tx' option not supported in this QEMU binary"));
3837 3838 3839
            goto error;
        }
    }
3840
    if (usingVirtio) {
3841
        qemuBuildIoEventFdStr(&buf, net->driver.virtio.ioeventfd, qemuCaps);
3842
        if (net->driver.virtio.event_idx &&
3843
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_EVENT_IDX)) {
3844
            virBufferAsprintf(&buf, ",event_idx=%s",
J
Ján Tomko 已提交
3845
                              virTristateSwitchTypeToString(net->driver.virtio.event_idx));
3846
        }
3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870
        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 已提交
3871 3872 3873 3874
        if (net->driver.virtio.host.mrg_rxbuf) {
            virBufferAsprintf(&buf, ",mrg_rxbuf=%s",
                              virTristateSwitchTypeToString(net->driver.virtio.host.mrg_rxbuf));
        }
3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894
        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));
        }
3895
    }
3896
    if (usingVirtio && vhostfdSize > 1) {
3897 3898 3899 3900 3901 3902
        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 {
3903
            /* As advised at https://www.linux-kvm.org/page/Multiqueue
3904 3905 3906 3907
             * we should add vectors=2*N+2 where N is the vhostfdSize
             */
            virBufferAsprintf(&buf, ",mq=on,vectors=%zu", 2 * vhostfdSize + 2);
        }
3908
    }
3909 3910 3911 3912 3913
    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;
3914
        }
3915
        virBufferAsprintf(&buf, ",rx_queue_size=%u", net->driver.virtio.rx_queue_size);
3916
    }
3917 3918 3919 3920 3921
    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;
3922
        }
3923
        virBufferAsprintf(&buf, ",tx_queue_size=%u", net->driver.virtio.tx_queue_size);
3924
    }
3925

3926 3927 3928 3929 3930
    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;
3931
        }
3932
        virBufferAsprintf(&buf, ",host_mtu=%u", net->mtu);
3933 3934
    }

3935
    virBufferAsprintf(&buf, ",netdev=host%s", net->info.alias);
3936
    virBufferAsprintf(&buf, ",id=%s", net->info.alias);
3937 3938
    virBufferAsprintf(&buf, ",mac=%s",
                      virMacAddrFormat(&net->mac, macaddr));
3939

3940
    if (qemuBuildDeviceAddressStr(&buf, def, &net->info, qemuCaps) < 0)
3941
        goto error;
3942
    if (qemuBuildRomStr(&buf, &net->info) < 0)
3943
        goto error;
3944
    if (bootindex)
3945
        virBufferAsprintf(&buf, ",bootindex=%u", bootindex);
3946 3947 3948
    if (usingVirtio &&
        qemuBuildVirtioOptionsStr(&buf, net->virtio, qemuCaps) < 0)
        goto error;
3949

3950
    if (virBufferCheckError(&buf) < 0)
3951 3952 3953 3954
        goto error;

    return virBufferContentAndReset(&buf);

3955
 error:
3956 3957 3958 3959 3960 3961
    return NULL;
}


char *
qemuBuildHostNetStr(virDomainNetDefPtr net,
3962
                    virQEMUDriverPtr driver,
3963
                    char **tapfd,
3964
                    size_t tapfdSize,
3965
                    char **vhostfd,
3966
                    size_t vhostfdSize)
3967
{
3968
    bool is_tap = false;
3969
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
3970
    virDomainNetType netType = virDomainNetGetActualType(net);
3971
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
3972
    size_t i;
3973
    char *ret = NULL;
3974

3975
    if (net->script && netType != VIR_DOMAIN_NET_TYPE_ETHERNET) {
3976 3977 3978
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("scripts are not supported on interfaces of type %s"),
                       virDomainNetTypeToString(netType));
3979
        goto cleanup;
3980 3981 3982
    }

    switch (netType) {
M
Michal Privoznik 已提交
3983 3984 3985 3986 3987
        /*
         * If type='bridge', and we're running as privileged user
         * or -netdev bridge is not supported then it will fall
         * through, -net tap,fd
         */
3988
    case VIR_DOMAIN_NET_TYPE_BRIDGE:
R
Richa Marwaha 已提交
3989
    case VIR_DOMAIN_NET_TYPE_NETWORK:
3990
    case VIR_DOMAIN_NET_TYPE_DIRECT:
3991
    case VIR_DOMAIN_NET_TYPE_ETHERNET:
3992
        virBufferAddLit(&buf, "tap,");
3993 3994 3995
        /* for one tapfd 'fd=' shall be used,
         * for more than one 'fds=' is the right choice */
        if (tapfdSize == 1) {
3996
            virBufferAsprintf(&buf, "fd=%s,", tapfd[0]);
3997 3998 3999 4000 4001 4002 4003
        } else {
            virBufferAddLit(&buf, "fds=");
            for (i = 0; i < tapfdSize; i++) {
                if (i)
                    virBufferAddChar(&buf, ':');
                virBufferAdd(&buf, tapfd[i], -1);
            }
4004
            virBufferAddChar(&buf, ',');
4005
        }
4006
        is_tap = true;
4007 4008 4009
        break;

    case VIR_DOMAIN_NET_TYPE_CLIENT:
4010
        virBufferAsprintf(&buf, "socket,connect=%s:%d,",
M
Michal Privoznik 已提交
4011 4012 4013
                          net->data.socket.address,
                          net->data.socket.port);
        break;
4014

4015
    case VIR_DOMAIN_NET_TYPE_SERVER:
4016
        virBufferAsprintf(&buf, "socket,listen=%s:%d,",
J
Ján Tomko 已提交
4017
                          NULLSTR_EMPTY(net->data.socket.address),
M
Michal Privoznik 已提交
4018 4019
                          net->data.socket.port);
        break;
4020

4021
    case VIR_DOMAIN_NET_TYPE_MCAST:
4022
        virBufferAsprintf(&buf, "socket,mcast=%s:%d,",
M
Michal Privoznik 已提交
4023 4024 4025
                          net->data.socket.address,
                          net->data.socket.port);
        break;
4026

4027
    case VIR_DOMAIN_NET_TYPE_UDP:
4028
        virBufferAsprintf(&buf, "socket,udp=%s:%d,localaddr=%s:%d,",
M
Michal Privoznik 已提交
4029 4030 4031 4032 4033
                          net->data.socket.address,
                          net->data.socket.port,
                          net->data.socket.localaddr,
                          net->data.socket.localport);
        break;
4034

4035
    case VIR_DOMAIN_NET_TYPE_USER:
4036
        virBufferAddLit(&buf, "user,");
4037 4038
        for (i = 0; i < net->guestIP.nips; i++) {
            const virNetDevIPAddr *ip = net->guestIP.ips[i];
4039
            VIR_AUTOFREE(char *) addr = NULL;
4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056
            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, ',');
        }
        break;

4057
    case VIR_DOMAIN_NET_TYPE_INTERNAL:
4058
        virBufferAddLit(&buf, "user,");
4059
        break;
4060 4061

    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
4062
        virBufferAsprintf(&buf, "vhost-user,chardev=char%s,",
4063 4064
                          net->info.alias);
        if (net->driver.virtio.queues > 1)
4065
            virBufferAsprintf(&buf, "queues=%u,",
4066
                              net->driver.virtio.queues);
4067 4068
        break;

J
Ján Tomko 已提交
4069 4070
    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
        /* Should have been handled earlier via PCI/USB hotplug code. */
4071 4072
    case VIR_DOMAIN_NET_TYPE_LAST:
        break;
4073 4074
    }

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

4077
    if (is_tap) {
4078
        if (vhostfdSize) {
4079
            virBufferAddLit(&buf, "vhost=on,");
4080
            if (vhostfdSize == 1) {
4081
                virBufferAsprintf(&buf, "vhostfd=%s,", vhostfd[0]);
4082 4083 4084 4085 4086 4087 4088
            } else {
                virBufferAddLit(&buf, "vhostfds=");
                for (i = 0; i < vhostfdSize; i++) {
                    if (i)
                        virBufferAddChar(&buf, ':');
                    virBufferAdd(&buf, vhostfd[i], -1);
                }
4089
                virBufferAddChar(&buf, ',');
4090 4091
            }
        }
4092
        if (net->tune.sndbuf_specified)
4093
            virBufferAsprintf(&buf, "sndbuf=%lu,", net->tune.sndbuf);
4094 4095
    }

4096

4097
    virBufferTrim(&buf, ",", -1);
4098
    if (virBufferCheckError(&buf) < 0)
4099
        goto cleanup;
4100

4101 4102 4103 4104
    ret = virBufferContentAndReset(&buf);
 cleanup:
    virObjectUnref(cfg);
    return ret;
4105 4106 4107
}


M
Michal Privoznik 已提交
4108
char *
4109
qemuBuildWatchdogDevStr(const virDomainDef *def,
4110
                        virDomainWatchdogDefPtr dev,
4111
                        virQEMUCapsPtr qemuCaps)
4112
{
4113
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4114 4115 4116

    const char *model = virDomainWatchdogModelTypeToString(dev->model);
    if (!model) {
4117 4118
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing watchdog model"));
4119 4120 4121
        goto error;
    }

4122
    virBufferAsprintf(&buf, "%s,id=%s", model, dev->info.alias);
4123
    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
4124 4125
        goto error;

4126
    if (virBufferCheckError(&buf) < 0)
4127 4128 4129 4130
        goto error;

    return virBufferContentAndReset(&buf);

4131
 error:
4132 4133 4134 4135
    return NULL;
}


4136 4137 4138 4139 4140 4141
static int
qemuBuildWatchdogCommandLine(virCommandPtr cmd,
                             const virDomainDef *def,
                             virQEMUCapsPtr qemuCaps)
{
    virDomainWatchdogDefPtr watchdog = def->watchdog;
4142
    VIR_AUTOFREE(char *) optstr = NULL;
4143
    const char *action;
4144
    int actualAction;
4145 4146 4147 4148

    if (!def->watchdog)
        return 0;

4149 4150 4151
    if (qemuCommandAddExtDevice(cmd, &def->watchdog->info) < 0)
        return -1;

4152
    virCommandAddArg(cmd, "-device");
4153

4154 4155 4156
    optstr = qemuBuildWatchdogDevStr(def, watchdog, qemuCaps);
    if (!optstr)
        return -1;
4157 4158 4159

    virCommandAddArg(cmd, optstr);

4160 4161 4162 4163
    /* 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;
4164
    if (watchdog->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP)
4165
        actualAction = VIR_DOMAIN_WATCHDOG_ACTION_PAUSE;
4166

4167
    action = virDomainWatchdogActionTypeToString(actualAction);
4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178
    if (!action) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("invalid watchdog action"));
        return -1;
    }
    virCommandAddArgList(cmd, "-watchdog-action", action, NULL);

    return 0;
}


4179 4180 4181 4182
static int
qemuBuildMemballoonCommandLine(virCommandPtr cmd,
                               const virDomainDef *def,
                               virQEMUCapsPtr qemuCaps)
4183
{
4184
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4185

4186
    if (!virDomainDefHasMemballoon(def))
4187 4188
        return 0;

4189
    if (qemuBuildVirtioDevStr(&buf, "virtio-balloon", qemuCaps,
4190 4191
                              VIR_DOMAIN_DEVICE_MEMBALLOON,
                              def->memballoon) < 0) {
4192
        goto error;
4193 4194
    }

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

4199
    if (def->memballoon->autodeflate != VIR_TRISTATE_SWITCH_ABSENT) {
4200
        virBufferAsprintf(&buf, ",deflate-on-oom=%s",
4201
                          virTristateSwitchTypeToString(def->memballoon->autodeflate));
4202 4203
    }

4204 4205 4206
    if (qemuBuildVirtioOptionsStr(&buf, def->memballoon->virtio, qemuCaps) < 0)
        goto error;

4207 4208 4209
    if (qemuCommandAddExtDevice(cmd, &def->memballoon->info) < 0)
        goto error;

4210 4211 4212
    virCommandAddArg(cmd, "-device");
    virCommandAddArgBuffer(cmd, &buf);
    return 0;
4213

4214
 error:
4215
    return -1;
4216 4217 4218
}


4219 4220 4221
static char *
qemuBuildNVRAMDevStr(virDomainNVRAMDefPtr dev)
{
4222
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233

    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;
    }

4234
    if (virBufferCheckError(&buf) < 0)
4235 4236 4237 4238
        goto error;

    return virBufferContentAndReset(&buf);

4239
 error:
4240 4241
    return NULL;
}
4242

4243 4244 4245 4246 4247 4248 4249 4250 4251

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

4252
    if (qemuDomainIsPSeries(def)) {
4253 4254 4255 4256 4257 4258 4259
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_NVRAM)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("nvram device is not supported by "
                             "this QEMU binary"));
            return -1;
        }

4260
        VIR_AUTOFREE(char *) optstr = NULL;
4261 4262 4263 4264
        virCommandAddArg(cmd, "-global");
        optstr = qemuBuildNVRAMDevStr(def->nvram);
        if (!optstr)
            return -1;
4265
        virCommandAddArg(cmd, optstr);
4266 4267 4268 4269 4270 4271 4272 4273 4274 4275
    } else {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                      _("nvram device is only supported for PPC64"));
        return -1;
    }

    return 0;
}


4276
static char *
4277
qemuBuildVirtioInputDevStr(const virDomainDef *def,
4278 4279 4280
                           virDomainInputDefPtr dev,
                           virQEMUCapsPtr qemuCaps)
{
4281
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4282

4283
    switch ((virDomainInputType)dev->type) {
4284
    case VIR_DOMAIN_INPUT_TYPE_MOUSE:
4285
        if (qemuBuildVirtioDevStr(&buf, "virtio-mouse", qemuCaps,
4286
                                  VIR_DOMAIN_DEVICE_INPUT, dev) < 0) {
4287
            goto error;
4288
        }
4289 4290
        break;
    case VIR_DOMAIN_INPUT_TYPE_TABLET:
4291
        if (qemuBuildVirtioDevStr(&buf, "virtio-tablet", qemuCaps,
4292
                                  VIR_DOMAIN_DEVICE_INPUT, dev) < 0) {
4293
            goto error;
4294
        }
4295 4296
        break;
    case VIR_DOMAIN_INPUT_TYPE_KBD:
4297
        if (qemuBuildVirtioDevStr(&buf, "virtio-keyboard", qemuCaps,
4298
                                  VIR_DOMAIN_DEVICE_INPUT, dev) < 0) {
4299
            goto error;
4300
        }
4301
        break;
4302
    case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
4303
        if (qemuBuildVirtioDevStr(&buf, "virtio-input-host", qemuCaps,
4304
                                  VIR_DOMAIN_DEVICE_INPUT, dev) < 0) {
4305
            goto error;
4306
        }
4307
        break;
4308
    case VIR_DOMAIN_INPUT_TYPE_LAST:
4309 4310 4311
    default:
        virReportEnumRangeError(virDomainInputType, dev->type);
        goto error;
4312 4313
    }

4314 4315 4316 4317 4318 4319 4320
    virBufferAsprintf(&buf, ",id=%s", dev->info.alias);

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

4321 4322 4323
    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
        goto error;

4324 4325 4326
    if (qemuBuildVirtioOptionsStr(&buf, dev->virtio, qemuCaps) < 0)
        goto error;

4327 4328 4329 4330 4331 4332 4333 4334 4335
    if (virBufferCheckError(&buf) < 0)
        goto error;

    return virBufferContentAndReset(&buf);

 error:
    return NULL;
}

4336 4337
static char *
qemuBuildUSBInputDevStr(const virDomainDef *def,
4338
                        virDomainInputDefPtr dev,
4339
                        virQEMUCapsPtr qemuCaps)
4340
{
4341
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4342

4343 4344 4345 4346 4347 4348 4349 4350
    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:
4351 4352 4353 4354
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_KBD)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("usb keyboard is not supported by this "
                             "QEMU binary"));
4355
            goto error;
4356
        }
4357 4358 4359
        virBufferAsprintf(&buf, "usb-kbd,id=%s", dev->info.alias);
        break;
    }
4360

4361
    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
4362 4363
        goto error;

4364
    if (virBufferCheckError(&buf) < 0)
4365 4366 4367 4368
        goto error;

    return virBufferContentAndReset(&buf);

4369
 error:
4370 4371 4372 4373
    return NULL;
}


J
Ján Tomko 已提交
4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394
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;
}


4395 4396 4397 4398 4399 4400 4401 4402 4403
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];
4404
        VIR_AUTOFREE(char *) devstr = NULL;
4405

4406 4407 4408
        if (qemuCommandAddExtDevice(cmd, &input->info) < 0)
            return -1;

J
Ján Tomko 已提交
4409 4410 4411 4412
        if (qemuBuildInputDevStr(&devstr, def, input, qemuCaps) < 0)
            return -1;

        if (devstr) {
4413
            virCommandAddArg(cmd, "-device");
J
Ján Tomko 已提交
4414
            virCommandAddArg(cmd, devstr);
4415 4416 4417 4418 4419 4420 4421
        }
    }

    return 0;
}


4422 4423
static char *
qemuBuildSoundDevStr(const virDomainDef *def,
4424
                     virDomainSoundDefPtr sound,
4425
                     virQEMUCapsPtr qemuCaps)
4426
{
4427
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4428
    const char *model = NULL;
4429

4430
    /* Hack for devices with different names in QEMU and libvirt */
4431
    switch ((virDomainSoundModel) sound->model) {
4432
    case VIR_DOMAIN_SOUND_MODEL_ES1370:
4433
        model = "ES1370";
4434 4435
        break;
    case VIR_DOMAIN_SOUND_MODEL_AC97:
4436
        model = "AC97";
4437 4438
        break;
    case VIR_DOMAIN_SOUND_MODEL_ICH6:
4439
        model = "intel-hda";
4440
        break;
4441 4442 4443 4444 4445 4446 4447 4448 4449
    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;
4450 4451 4452 4453 4454 4455 4456 4457 4458
    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;
4459 4460 4461 4462 4463 4464 4465 4466 4467
    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;
4468
    }
4469

4470
    virBufferAsprintf(&buf, "%s,id=%s", model, sound->info.alias);
4471
    if (qemuBuildDeviceAddressStr(&buf, def, &sound->info, qemuCaps) < 0)
4472 4473
        goto error;

4474
    if (virBufferCheckError(&buf) < 0)
4475 4476 4477 4478
        goto error;

    return virBufferContentAndReset(&buf);

4479
 error:
4480 4481 4482
    return NULL;
}

4483 4484 4485 4486 4487 4488 4489 4490 4491

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;
4492 4493
    case VIR_DOMAIN_SOUND_CODEC_TYPE_OUTPUT:
        return QEMU_CAPS_HDA_OUTPUT;
4494 4495 4496 4497 4498 4499
    default:
        return -1;
    }
}


4500 4501
static char *
qemuBuildSoundCodecStr(virDomainSoundDefPtr sound,
4502
                       virDomainSoundCodecDefPtr codec,
4503
                       virQEMUCapsPtr qemuCaps)
4504
{
4505
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4506
    const char *stype;
4507
    int type, flags;
4508

4509 4510
    type = codec->type;
    stype = qemuSoundCodecTypeToString(type);
4511
    flags = qemuSoundCodecTypeToCaps(type);
4512

4513
    if (flags == -1 || !virQEMUCapsGet(qemuCaps, flags)) {
4514 4515
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("%s not supported in this QEMU binary"), stype);
4516 4517 4518
        goto error;
    }

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

4522 4523
    return virBufferContentAndReset(&buf);

4524
 error:
4525 4526
    return NULL;
}
4527

4528 4529 4530 4531 4532 4533 4534 4535

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

4536 4537
    for (i = 0; i < def->nsounds; i++) {
        virDomainSoundDefPtr sound = def->sounds[i];
4538
        VIR_AUTOFREE(char *) str = NULL;
4539

4540 4541 4542 4543 4544 4545
        /* 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 {
4546 4547 4548
            if (qemuCommandAddExtDevice(cmd, &sound->info) < 0)
                return -1;

4549 4550 4551
            virCommandAddArg(cmd, "-device");
            if (!(str = qemuBuildSoundDevStr(def, sound, qemuCaps)))
                return -1;
4552

4553 4554 4555 4556
            virCommandAddArg(cmd, str);
            if (sound->model == VIR_DOMAIN_SOUND_MODEL_ICH6 ||
                sound->model == VIR_DOMAIN_SOUND_MODEL_ICH9) {
                char *codecstr = NULL;
4557

4558 4559 4560 4561 4562 4563
                for (j = 0; j < sound->ncodecs; j++) {
                    virCommandAddArg(cmd, "-device");
                    if (!(codecstr =
                          qemuBuildSoundCodecStr(sound, sound->codecs[j],
                                                 qemuCaps))) {
                        return -1;
4564 4565

                    }
4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578
                    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;
4579 4580

                    }
4581 4582
                    virCommandAddArg(cmd, codecstr);
                    VIR_FREE(codecstr);
4583 4584 4585 4586 4587 4588 4589 4590 4591
                }
            }
        }
    }
    return 0;
}



4592
static char *
4593
qemuBuildDeviceVideoStr(const virDomainDef *def,
4594
                        virDomainVideoDefPtr video,
4595
                        virQEMUCapsPtr qemuCaps)
4596
{
4597
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4598
    const char *model;
4599

4600 4601 4602 4603 4604
    /* 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))
4605
        model = qemuDeviceVideoTypeToString(video->type);
4606 4607 4608 4609 4610 4611 4612 4613
    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;
4614 4615
    }

4616
    if (STREQ(model, "virtio-gpu")) {
4617
        if (qemuBuildVirtioDevStr(&buf, "virtio-gpu", qemuCaps,
4618
                                  VIR_DOMAIN_DEVICE_VIDEO, video) < 0) {
4619
            goto error;
4620
        }
4621 4622 4623 4624 4625
    } else {
        virBufferAsprintf(&buf, "%s", model);
    }

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

4627 4628 4629 4630 4631 4632
    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) {
4633 4634 4635 4636
        if (video->ram) {
            /* QEMU accepts bytes for ram_size. */
            virBufferAsprintf(&buf, ",ram_size=%u", video->ram * 1024);
        }
4637

4638 4639 4640 4641
        if (video->vram) {
            /* QEMU accepts bytes for vram_size. */
            virBufferAsprintf(&buf, ",vram_size=%u", video->vram * 1024);
        }
4642

4643
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VRAM64)) {
4644 4645 4646 4647
            /* QEMU accepts mebibytes for vram64_size_mb. */
            virBufferAsprintf(&buf, ",vram64_size_mb=%u", video->vram64 / 1024);
        }

4648
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_VGAMEM)) {
4649 4650 4651
            /* QEMU accepts mebibytes for vgamem_mb. */
            virBufferAsprintf(&buf, ",vgamem_mb=%u", video->vgamem / 1024);
        }
4652

4653
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_MAX_OUTPUTS)) {
4654 4655 4656
            if (video->heads)
                virBufferAsprintf(&buf, ",max_outputs=%u", video->heads);
        }
4657 4658 4659 4660 4661
    } 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);
        }
4662 4663 4664 4665 4666 4667
    } else if ((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))) {
        if (video->vram)
            virBufferAsprintf(&buf, ",vgamem_mb=%u", video->vram / 1024);
4668 4669 4670
    } else if (video->type == VIR_DOMAIN_VIDEO_TYPE_BOCHS) {
        if (video->vram)
            virBufferAsprintf(&buf, ",vgamem=%uk", video->vram);
4671 4672
    }

4673
    if (qemuBuildDeviceAddressStr(&buf, def, &video->info, qemuCaps) < 0)
4674 4675
        goto error;

4676 4677 4678
    if (qemuBuildVirtioOptionsStr(&buf, video->virtio, qemuCaps) < 0)
        goto error;

4679
    if (virBufferCheckError(&buf) < 0)
4680 4681 4682 4683
        goto error;

    return virBufferContentAndReset(&buf);

4684
 error:
4685 4686 4687 4688
    return NULL;
}


4689 4690
static int
qemuBuildVgaVideoCommand(virCommandPtr cmd,
4691
                         virDomainVideoDefPtr video,
4692 4693
                         virQEMUCapsPtr qemuCaps)
{
4694
    const char *vgastr = qemuVideoTypeToString(video->type);
4695 4696 4697
    if (!vgastr || STREQ(vgastr, "")) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("invalid model for video type '%s'"),
4698
                       virDomainVideoTypeToString(video->type));
4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714
        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.
     */
4715
    const char *dev = qemuDeviceVideoTypeToString(video->type);
4716

4717 4718 4719 4720 4721 4722
    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;
4723
        unsigned int heads = video->heads;
4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746

        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);
        }
4747 4748 4749 4750 4751 4752
        if (heads &&
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_QXL_MAX_OUTPUTS)) {
            virCommandAddArg(cmd, "-global");
            virCommandAddArgFormat(cmd, "%s.max_outputs=%u",
                                   dev, heads);
        }
4753 4754
    }

4755 4756
    if (video->vram &&
        ((video->type == VIR_DOMAIN_VIDEO_TYPE_VGA &&
4757
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_VGA_VGAMEM)) ||
4758
         (video->type == VIR_DOMAIN_VIDEO_TYPE_VMVGA &&
4759
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_VMWARE_SVGA_VGAMEM)))) {
4760
        unsigned int vram = video->vram;
4761 4762 4763 4764 4765 4766 4767 4768 4769 4770

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

    return 0;
}


4771 4772 4773 4774 4775 4776 4777
static int
qemuBuildVideoCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
    size_t i;

4778
    for (i = 0; i < def->nvideos; i++) {
4779
        VIR_AUTOFREE(char *) str = NULL;
4780
        virDomainVideoDefPtr video = def->videos[i];
4781

4782 4783 4784
        if (video->type == VIR_DOMAIN_VIDEO_TYPE_NONE)
            continue;

4785 4786
        if (video->primary) {
            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY)) {
4787

4788 4789 4790 4791
                if (qemuCommandAddExtDevice(cmd,
                                            &def->videos[i]->info) < 0)
                    return -1;

4792
                virCommandAddArg(cmd, "-device");
4793

4794 4795
                if (!(str = qemuBuildDeviceVideoStr(def, video, qemuCaps)))
                    return -1;
4796

4797 4798 4799 4800 4801 4802
                virCommandAddArg(cmd, str);
            } else {
                if (qemuBuildVgaVideoCommand(cmd, video, qemuCaps) < 0)
                    return -1;
            }
        } else {
4803 4804 4805
            if (qemuCommandAddExtDevice(cmd, &def->videos[i]->info) < 0)
                return -1;

4806
            virCommandAddArg(cmd, "-device");
4807

4808
            if (!(str = qemuBuildDeviceVideoStr(def, video, qemuCaps)))
4809
                return -1;
4810 4811

            virCommandAddArg(cmd, str);
4812 4813 4814 4815 4816 4817 4818
        }
    }

    return 0;
}


4819
char *
4820
qemuBuildPCIHostdevDevStr(const virDomainDef *def,
4821
                          virDomainHostdevDefPtr dev,
4822
                          unsigned int bootIndex, /* used iff dev->info->bootIndex == 0 */
4823
                          virQEMUCapsPtr qemuCaps)
4824
{
4825
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4826 4827
    virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
    int backend = pcisrc->backend;
4828

4829
    /* caller has to assign proper passthrough backend type */
4830
    switch ((virDomainHostdevSubsysPCIBackendType)backend) {
4831 4832 4833 4834
    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
        virBufferAddLit(&buf, "vfio-pci");
        break;

M
Michal Privoznik 已提交
4835
    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
4836 4837 4838
    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
    case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
4839 4840
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("invalid PCI passthrough type '%s'"),
4841
                       virDomainHostdevSubsysPCIBackendTypeToString(backend));
4842
        goto error;
4843
    }
4844

4845
    virBufferAddLit(&buf, ",host=");
4846 4847
    virBufferAsprintf(&buf,
                      VIR_PCI_DEVICE_ADDRESS_FMT,
4848 4849 4850
                      pcisrc->addr.domain,
                      pcisrc->addr.bus,
                      pcisrc->addr.slot,
4851
                      pcisrc->addr.function);
4852 4853
    virBufferAsprintf(&buf, ",id=%s", dev->info->alias);
    if (dev->info->bootIndex)
4854 4855
        bootIndex = dev->info->bootIndex;
    if (bootIndex)
4856
        virBufferAsprintf(&buf, ",bootindex=%u", bootIndex);
4857
    if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
4858
        goto error;
4859
    if (qemuBuildRomStr(&buf, dev->info) < 0)
4860
        goto error;
4861

4862
    if (virBufferCheckError(&buf) < 0)
4863 4864 4865 4866
        goto error;

    return virBufferContentAndReset(&buf);

4867
 error:
4868 4869 4870 4871 4872
    return NULL;
}


char *
4873
qemuBuildUSBHostdevDevStr(const virDomainDef *def,
4874
                          virDomainHostdevDefPtr dev,
4875
                          virQEMUCapsPtr qemuCaps)
4876
{
4877
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4878
    virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
4879

4880
    if (!dev->missing && !usbsrc->bus && !usbsrc->device) {
4881 4882
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("USB host device is missing bus/device information"));
4883 4884 4885
        return NULL;
    }

4886 4887 4888
    virBufferAddLit(&buf, "usb-host");
    if (!dev->missing) {
        virBufferAsprintf(&buf, ",hostbus=%d,hostaddr=%d",
4889
                          usbsrc->bus, usbsrc->device);
4890 4891
    }
    virBufferAsprintf(&buf, ",id=%s", dev->info->alias);
4892
    if (dev->info->bootIndex)
4893
        virBufferAsprintf(&buf, ",bootindex=%u", dev->info->bootIndex);
4894

4895
    if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
4896 4897
        goto error;

4898
    if (virBufferCheckError(&buf) < 0)
4899
        goto error;
4900

4901 4902
    return virBufferContentAndReset(&buf);

4903
 error:
4904
    return NULL;
4905 4906 4907
}


4908 4909
static char *
qemuBuildHubDevStr(const virDomainDef *def,
4910
                   virDomainHubDefPtr dev,
4911
                   virQEMUCapsPtr qemuCaps)
M
Marc-André Lureau 已提交
4912
{
4913
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
M
Marc-André Lureau 已提交
4914 4915

    if (dev->type != VIR_DOMAIN_HUB_TYPE_USB) {
4916 4917 4918
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hub type %s not supported"),
                       virDomainHubTypeToString(dev->type));
M
Marc-André Lureau 已提交
4919 4920 4921
        goto error;
    }

4922
    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_USB_HUB)) {
4923
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
4924
                       _("usb-hub not supported by QEMU binary"));
M
Marc-André Lureau 已提交
4925 4926 4927 4928 4929
        goto error;
    }

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

4933
    if (virBufferCheckError(&buf) < 0)
M
Marc-André Lureau 已提交
4934 4935 4936 4937
        goto error;

    return virBufferContentAndReset(&buf);

4938
 error:
M
Marc-André Lureau 已提交
4939 4940 4941 4942
    return NULL;
}


4943 4944 4945 4946 4947 4948 4949 4950 4951
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];
4952
        VIR_AUTOFREE(char *) optstr = NULL;
4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963

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

    return 0;
}


4964
static char *
J
Ján Tomko 已提交
4965
qemuBuildSCSIHostHostdevDrvStr(virDomainHostdevDefPtr dev)
4966
{
4967
    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
4968
    virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
J
Ján Tomko 已提交
4969 4970 4971 4972 4973 4974

    return virSCSIDeviceGetSgName(NULL,
                                  scsihostsrc->adapter,
                                  scsihostsrc->bus,
                                  scsihostsrc->target,
                                  scsihostsrc->unit);
4975 4976 4977
}

static char *
4978 4979
qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev,
                                virQEMUCapsPtr qemuCaps)
4980
{
4981
    char *ret = NULL;
4982
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4983
    VIR_AUTOFREE(char *) netsource = NULL;
4984
    VIR_AUTOPTR(virJSONValue) srcprops = NULL;
4985 4986
    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
    virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
4987 4988
    qemuDomainStorageSourcePrivatePtr srcPriv =
        QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(iscsisrc->src);
4989

4990 4991 4992 4993 4994
    if (qemuDiskSourceNeedsProps(iscsisrc->src, qemuCaps)) {
        if (!(srcprops = qemuDiskSourceGetProps(iscsisrc->src)))
            goto cleanup;
        if (!(netsource = virQEMUBuildDriveCommandlineFromJSON(srcprops)))
            goto cleanup;
4995
        virBufferAsprintf(&buf, "%s,if=none,format=raw", netsource);
4996 4997 4998 4999 5000
    } 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;
5001 5002 5003
        virBufferAddLit(&buf, "file=");
        virQEMUBuildBufferEscapeComma(&buf, netsource);
        virBufferAddLit(&buf, ",if=none,format=raw");
5004
    }
5005

5006 5007 5008
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;

5009
    ret = virBufferContentAndReset(&buf);
5010

5011
 cleanup:
5012
    return ret;
5013 5014
}

5015 5016 5017 5018 5019 5020
char *
qemuBuildSCSIVHostHostdevDevStr(const virDomainDef *def,
                           virDomainHostdevDefPtr dev,
                           virQEMUCapsPtr qemuCaps,
                           char *vhostfdName)
{
5021
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5022 5023 5024 5025 5026 5027 5028 5029
    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;
    }

5030
    if (qemuBuildVirtioDevStr(&buf, "vhost-scsi", qemuCaps,
5031
                              VIR_DOMAIN_DEVICE_HOSTDEV, dev) < 0) {
5032
        goto cleanup;
5033
    }
5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051

    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:
    return NULL;
}

5052
char *
5053 5054
qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev,
                           virQEMUCapsPtr qemuCaps)
5055
{
5056
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5057 5058
    VIR_AUTOFREE(char *) source = NULL;
    VIR_AUTOFREE(char *) drivealias = NULL;
5059 5060 5061
    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;

    if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
5062
        if (!(source = qemuBuildSCSIiSCSIHostdevDrvStr(dev, qemuCaps)))
5063
            goto error;
5064
        virBufferAdd(&buf, source, -1);
5065
    } else {
J
Ján Tomko 已提交
5066
        if (!(source = qemuBuildSCSIHostHostdevDrvStr(dev)))
5067
            goto error;
5068
        virBufferAsprintf(&buf, "file=/dev/%s,if=none,format=raw", source);
5069
    }
J
John Ferlan 已提交
5070 5071 5072 5073

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

5075 5076
    if (dev->readonly)
        virBufferAddLit(&buf, ",readonly=on");
O
Osier Yang 已提交
5077

5078
    if (virBufferCheckError(&buf) < 0)
5079 5080 5081
        goto error;

    return virBufferContentAndReset(&buf);
5082
 error:
5083 5084 5085 5086
    return NULL;
}

char *
5087
qemuBuildSCSIHostdevDevStr(const virDomainDef *def,
5088
                           virDomainHostdevDefPtr dev)
5089
{
5090
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5091
    int model = -1;
5092
    VIR_AUTOFREE(char *) driveAlias = NULL;
5093
    const char *contAlias;
5094

5095
    model = qemuDomainFindSCSIControllerModel(def, dev->info);
5096
    if (model < 0)
5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116
        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");

5117 5118 5119 5120
    if (!(contAlias = virDomainControllerAliasFind(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
                                                   dev->info->addr.drive.controller)))
        goto error;

5121
    if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) {
5122 5123
        virBufferAsprintf(&buf, ",bus=%s.%d,scsi-id=%d",
                          contAlias,
5124 5125 5126
                          dev->info->addr.drive.bus,
                          dev->info->addr.drive.unit);
    } else {
5127 5128
        virBufferAsprintf(&buf, ",bus=%s.0,channel=%d,scsi-id=%d,lun=%d",
                          contAlias,
5129 5130 5131 5132
                          dev->info->addr.drive.bus,
                          dev->info->addr.drive.target,
                          dev->info->addr.drive.unit);
    }
5133

J
John Ferlan 已提交
5134 5135 5136
    if (!(driveAlias = qemuAliasFromHostdev(dev)))
        goto error;
    virBufferAsprintf(&buf, ",drive=%s,id=%s", driveAlias, dev->info->alias);
5137

5138
    if (dev->info->bootIndex)
5139
        virBufferAsprintf(&buf, ",bootindex=%u", dev->info->bootIndex);
5140

5141
    if (virBufferCheckError(&buf) < 0)
5142 5143 5144
        goto error;

    return virBufferContentAndReset(&buf);
5145
 error:
5146 5147
    return NULL;
}
5148

5149 5150 5151
static int
qemuBuildChrChardevFileStr(virLogManagerPtr logManager,
                           virCommandPtr cmd,
5152
                           const virDomainDef *def,
5153 5154 5155 5156 5157
                           virBufferPtr buf,
                           const char *filearg, const char *fileval,
                           const char *appendarg, int appendval)
{
    if (logManager) {
5158 5159
        VIR_AUTOFREE(char *) fdset = NULL;
        VIR_AUTOFREE(char *) fdpath = NULL;
5160 5161 5162
        int flags = 0;
        int logfd;

5163 5164
        if (appendval == VIR_TRISTATE_SWITCH_ABSENT ||
            appendval == VIR_TRISTATE_SWITCH_OFF)
5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187
            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);

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

        virBufferAsprintf(buf, ",%s=%s,%s=on", filearg, fdpath, appendarg);
    } else {
5188 5189
        virBufferAsprintf(buf, ",%s=", filearg);
        virQEMUBuildBufferEscapeComma(buf, fileval);
5190 5191 5192 5193 5194 5195 5196 5197 5198
        if (appendval != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(buf, ",%s=%s", appendarg,
                              virTristateSwitchTypeToString(appendval));
        }
    }

    return 0;
}

5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211

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");
    }
}


5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226
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;
5227
    if (virStrcpyStatic(addr.sun_path, dev->data.nix.path) < 0) {
5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254
        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;
    }

5255 5256 5257 5258 5259 5260
    /* 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;

5261 5262 5263 5264 5265 5266 5267
    return fd;

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

5268 5269 5270 5271

enum {
    QEMU_BUILD_CHARDEV_TCP_NOWAIT = (1 << 0),
    QEMU_BUILD_CHARDEV_FILE_LOGD  = (1 << 1),
5272
    QEMU_BUILD_CHARDEV_UNIX_FD_PASS = (1 << 2),
5273 5274
};

5275 5276
/* This function outputs a -chardev command line option which describes only the
 * host side of the character device */
5277
static char *
5278
qemuBuildChrChardevStr(virLogManagerPtr logManager,
5279
                       virSecurityManagerPtr secManager,
5280
                       virCommandPtr cmd,
5281
                       virQEMUDriverConfigPtr cfg,
5282
                       const virDomainDef *def,
5283
                       const virDomainChrSourceDef *dev,
5284
                       const char *alias,
5285
                       virQEMUCapsPtr qemuCaps,
5286
                       unsigned int flags)
5287
{
5288
    qemuDomainChrSourcePrivatePtr chrSourcePriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev);
5289
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5290
    bool telnet;
5291
    VIR_AUTOFREE(char *) charAlias = NULL;
5292
    char *ret = NULL;
5293 5294

    if (!(charAlias = qemuAliasChardevFromDevAlias(alias)))
5295
        goto cleanup;
5296

5297
    switch (dev->type) {
5298
    case VIR_DOMAIN_CHR_TYPE_NULL:
5299
        virBufferAsprintf(&buf, "null,id=%s", charAlias);
5300 5301 5302
        break;

    case VIR_DOMAIN_CHR_TYPE_VC:
5303
        virBufferAsprintf(&buf, "vc,id=%s", charAlias);
5304 5305 5306
        break;

    case VIR_DOMAIN_CHR_TYPE_PTY:
5307
        virBufferAsprintf(&buf, "pty,id=%s", charAlias);
5308 5309 5310
        break;

    case VIR_DOMAIN_CHR_TYPE_DEV:
5311
        virBufferAsprintf(&buf, "%s,id=%s,path=",
5312
                          STRPREFIX(alias, "parallel") ? "parport" : "tty",
5313 5314
                          charAlias);
        virQEMUBuildBufferEscapeComma(&buf, dev->data.file.path);
5315 5316 5317
        break;

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

5320 5321 5322 5323
        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"));
5324
            goto cleanup;
5325
        }
5326 5327
        if (qemuBuildChrChardevFileStr(flags & QEMU_BUILD_CHARDEV_FILE_LOGD ?
                                       logManager : NULL,
5328
                                       cmd, def, &buf,
5329 5330
                                       "path", dev->data.file.path,
                                       "append", dev->data.file.append) < 0)
5331
            goto cleanup;
5332 5333 5334
        break;

    case VIR_DOMAIN_CHR_TYPE_PIPE:
5335 5336
        virBufferAsprintf(&buf, "pipe,id=%s,path=", charAlias);
        virQEMUBuildBufferEscapeComma(&buf, dev->data.file.path);
5337 5338 5339
        break;

    case VIR_DOMAIN_CHR_TYPE_STDIO:
5340
        virBufferAsprintf(&buf, "stdio,id=%s", charAlias);
5341 5342
        break;

5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354
    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";

5355
        virBufferAsprintf(&buf,
5356
                          "udp,id=%s,host=%s,port=%s,localaddr=%s,"
5357
                          "localport=%s",
5358
                          charAlias,
5359
                          connectHost,
5360
                          dev->data.udp.connectService,
5361
                          bindHost, bindService);
5362
        break;
5363
    }
5364 5365
    case VIR_DOMAIN_CHR_TYPE_TCP:
        telnet = dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
5366
        virBufferAsprintf(&buf,
5367 5368
                          "socket,id=%s,host=%s,port=%s%s",
                          charAlias,
5369 5370
                          dev->data.tcp.host,
                          dev->data.tcp.service,
5371 5372
                          telnet ? ",telnet" : "");

5373 5374 5375 5376 5377
        if (dev->data.tcp.listen) {
            virBufferAddLit(&buf, ",server");
            if (flags & QEMU_BUILD_CHARDEV_TCP_NOWAIT)
                virBufferAddLit(&buf, ",nowait");
        }
5378

5379 5380
        qemuBuildChrChardevReconnectStr(&buf, &dev->data.tcp.reconnect);

5381
        if (dev->data.tcp.haveTLS == VIR_TRISTATE_BOOL_YES) {
5382
            VIR_AUTOFREE(char *) objalias = NULL;
5383
            const char *tlsCertEncSecAlias = NULL;
5384

5385 5386 5387 5388
            /* 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 */
5389 5390 5391 5392 5393 5394 5395
            if (chrSourcePriv && chrSourcePriv->secinfo) {
                if (qemuBuildObjectSecretCommandLine(cmd,
                                                     chrSourcePriv->secinfo) < 0)
                    goto cleanup;

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

5397 5398 5399
            if (!(objalias = qemuAliasTLSObjFromSrcAlias(charAlias)))
                goto cleanup;

J
John Ferlan 已提交
5400 5401 5402
            if (qemuBuildTLSx509CommandLine(cmd, cfg->chardevTLSx509certdir,
                                            dev->data.tcp.listen,
                                            cfg->chardevTLSx509verify,
5403
                                            tlsCertEncSecAlias,
5404
                                            objalias, qemuCaps) < 0) {
5405
                goto cleanup;
5406
            }
5407

J
John Ferlan 已提交
5408 5409
            virBufferAsprintf(&buf, ",tls-creds=%s", objalias);
        }
5410 5411 5412
        break;

    case VIR_DOMAIN_CHR_TYPE_UNIX:
5413
        virBufferAsprintf(&buf, "socket,id=%s", charAlias);
5414 5415
        if (dev->data.nix.listen &&
            (flags & QEMU_BUILD_CHARDEV_UNIX_FD_PASS) &&
5416
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS)) {
5417 5418
            if (qemuSecuritySetSocketLabel(secManager, (virDomainDefPtr)def) < 0)
                goto cleanup;
5419
            int fd = qemuOpenChrChardevUNIXSocket(dev);
5420 5421 5422 5423
            if (qemuSecurityClearSocketLabel(secManager, (virDomainDefPtr)def) < 0) {
                VIR_FORCE_CLOSE(fd);
                goto cleanup;
            }
5424 5425 5426
            if (fd < 0)
                goto cleanup;

5427
            virBufferAsprintf(&buf, ",fd=%d", fd);
5428 5429 5430

            virCommandPassFD(cmd, fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
        } else {
5431
            virBufferAddLit(&buf, ",path=");
5432 5433
            virQEMUBuildBufferEscapeComma(&buf, dev->data.nix.path);
        }
5434 5435 5436 5437 5438
        if (dev->data.nix.listen) {
            virBufferAddLit(&buf, ",server");
            if (flags & QEMU_BUILD_CHARDEV_TCP_NOWAIT)
                virBufferAddLit(&buf, ",nowait");
        }
5439 5440

        qemuBuildChrChardevReconnectStr(&buf, &dev->data.nix.reconnect);
5441
        break;
5442 5443

    case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
5444
        virBufferAsprintf(&buf, "spicevmc,id=%s,name=%s", charAlias,
E
Eric Blake 已提交
5445
                          virDomainChrSpicevmcTypeToString(dev->data.spicevmc));
5446 5447
        break;

5448
    case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
5449
        virBufferAsprintf(&buf, "spiceport,id=%s,name=%s", charAlias,
5450 5451 5452
                          dev->data.spiceport.channel);
        break;

5453
    default:
5454 5455 5456
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unsupported chardev '%s'"),
                       virDomainChrTypeToString(dev->type));
5457
        goto cleanup;
5458 5459
    }

5460 5461 5462 5463
    if (dev->logfile) {
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_LOGFILE)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("logfile not supported in this QEMU binary"));
5464
            goto cleanup;
5465
        }
5466 5467 5468
        if (qemuBuildChrChardevFileStr(logManager, cmd, def, &buf,
                                       "logfile", dev->logfile,
                                       "logappend", dev->logappend) < 0)
5469
            goto cleanup;
5470 5471
    }

5472
    if (virBufferCheckError(&buf) < 0)
5473
        goto cleanup;
5474

5475 5476 5477
    ret = virBufferContentAndReset(&buf);
 cleanup:
    return ret;
5478 5479
}

5480 5481 5482 5483 5484
char *
qemuBuildHostdevMediatedDevStr(const virDomainDef *def,
                               virDomainHostdevDefPtr dev,
                               virQEMUCapsPtr qemuCaps)
{
5485
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5486 5487
    virDomainHostdevSubsysMediatedDevPtr mdevsrc = &dev->source.subsys.u.mdev;
    char *ret = NULL;
5488
    VIR_AUTOFREE(char *) mdevPath = NULL;
5489
    const char *dev_str = NULL;
5490 5491 5492

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

5494 5495 5496 5497 5498 5499
    dev_str = virMediatedDeviceModelTypeToString(mdevsrc->model);

    if (!dev_str)
        goto cleanup;

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

5502 5503 5504 5505
    if (mdevsrc->display != VIR_TRISTATE_SWITCH_ABSENT)
        virBufferAsprintf(&buf, ",display=%s",
                          virTristateSwitchTypeToString(mdevsrc->display));

5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516
    if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
        goto cleanup;

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

    ret = virBufferContentAndReset(&buf);

 cleanup:
    return ret;
}
5517

5518 5519 5520 5521
static int
qemuBuildHostdevCommandLine(virCommandPtr cmd,
                            const virDomainDef *def,
                            virQEMUCapsPtr qemuCaps,
5522
                            unsigned int *bootHostdevNet)
5523 5524 5525 5526 5527 5528
{
    size_t i;

    for (i = 0; i < def->nhostdevs; i++) {
        virDomainHostdevDefPtr hostdev = def->hostdevs[i];
        virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
5529
        VIR_AUTOFREE(char *) devstr = NULL;
5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546

        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) {

5547 5548 5549 5550 5551
            virCommandAddArg(cmd, "-device");
            if (!(devstr =
                  qemuBuildUSBHostdevDevStr(def, hostdev, qemuCaps)))
                return -1;
            virCommandAddArg(cmd, devstr);
5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567
        }

        /* 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;
                }
            }

5568
            unsigned int bootIndex = hostdev->info->bootIndex;
5569

5570 5571 5572
            /* bootNet will be non-0 if boot order was set and no other
             * net devices were encountered
             */
5573
            if (hostdev->parentnet && bootIndex == 0) {
5574 5575 5576
                bootIndex = *bootHostdevNet;
                *bootHostdevNet = 0;
            }
5577 5578 5579 5580

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

5581
            virCommandAddArg(cmd, "-device");
M
Michal Privoznik 已提交
5582
            devstr = qemuBuildPCIHostdevDevStr(def, hostdev, bootIndex, qemuCaps);
5583 5584 5585
            if (!devstr)
                return -1;
            virCommandAddArg(cmd, devstr);
5586 5587 5588
        }

        /* SCSI */
5589
        if (virHostdevIsSCSIDevice(hostdev)) {
5590 5591
            virDomainHostdevSubsysSCSIPtr scsisrc =
                &hostdev->source.subsys.u.scsi;
5592
            VIR_AUTOFREE(char *) drvstr = NULL;
5593 5594 5595 5596 5597 5598 5599 5600 5601 5602

            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)
5603
                    return -1;
5604
            }
5605

5606 5607
            virCommandAddArg(cmd, "-drive");
            if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, qemuCaps)))
5608
                return -1;
5609 5610 5611 5612 5613 5614
            virCommandAddArg(cmd, drvstr);

            virCommandAddArg(cmd, "-device");
            if (!(devstr = qemuBuildSCSIHostdevDevStr(def, hostdev)))
                return -1;
            virCommandAddArg(cmd, devstr);
5615
        }
5616 5617 5618 5619 5620 5621

        /* 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) {
5622
                VIR_AUTOFREE(char *) vhostfdName = NULL;
5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639
                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,
5640
                                                               vhostfdName)))
5641 5642
                    return -1;

5643
                virCommandAddArg(cmd, devstr);
5644 5645
            }
        }
5646 5647

        /* MDEV */
5648
        if (virHostdevIsMdevDevice(hostdev)) {
5649 5650 5651
            virDomainHostdevSubsysMediatedDevPtr mdevsrc = &subsys->u.mdev;

            switch ((virMediatedDeviceModelType) mdevsrc->model) {
5652 5653 5654 5655 5656 5657 5658
            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;
                }
5659

5660 5661 5662 5663 5664 5665 5666 5667 5668
                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 已提交
5669 5670 5671 5672 5673 5674 5675 5676
            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;
5677
            case VIR_MDEV_MODEL_TYPE_LAST:
5678 5679 5680
            default:
                virReportEnumRangeError(virMediatedDeviceModelType,
                                        subsys->u.mdev.model);
5681 5682 5683 5684 5685 5686 5687 5688 5689
                return -1;
            }

            virCommandAddArg(cmd, "-device");
            if (!(devstr =
                  qemuBuildHostdevMediatedDevStr(def, hostdev, qemuCaps)))
                return -1;
            virCommandAddArg(cmd, devstr);
        }
5690 5691 5692 5693 5694
    }

    return 0;
}

5695

5696
static int
5697
qemuBuildMonitorCommandLine(virLogManagerPtr logManager,
5698
                            virSecurityManagerPtr secManager,
5699
                            virCommandPtr cmd,
5700
                            virQEMUDriverConfigPtr cfg,
5701
                            virDomainDefPtr def,
5702
                            qemuDomainObjPrivatePtr priv)
5703
{
5704
    VIR_AUTOFREE(char *) chrdev = NULL;
5705 5706
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
5707 5708
    if (priv->chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
5709

5710
    if (!priv->monConfig)
5711 5712
        return 0;

5713 5714
    if (!(chrdev = qemuBuildChrChardevStr(logManager, secManager,
                                          cmd, cfg, def,
5715
                                          priv->monConfig, "monitor",
5716
                                          priv->qemuCaps, cdevflags)))
5717 5718 5719 5720 5721
        return -1;
    virCommandAddArg(cmd, "-chardev");
    virCommandAddArg(cmd, chrdev);

    virCommandAddArg(cmd, "-mon");
J
Ján Tomko 已提交
5722
    virCommandAddArg(cmd, "chardev=charmonitor,id=monitor,mode=control");
5723 5724 5725 5726 5727

    return 0;
}


5728
static char *
5729
qemuBuildVirtioSerialPortDevStr(const virDomainDef *def,
5730
                                virDomainChrDefPtr dev)
5731
{
5732
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5733 5734
    const char *contAlias;

5735 5736
    switch (dev->deviceType) {
    case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
5737
        virBufferAddLit(&buf, "virtconsole");
5738 5739
        break;
    case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
5740
        virBufferAddLit(&buf, "virtserialport");
5741 5742
        break;
    default:
5743 5744
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Cannot use virtio serial for parallel/serial devices"));
5745 5746
        return NULL;
    }
5747

5748
    if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
5749
        dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
5750
        dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) {
5751
        /* Check it's a virtio-serial address */
5752
        if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL) {
5753 5754
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("virtio serial device has invalid address type"));
5755 5756 5757
            goto error;
        }

5758 5759 5760 5761 5762 5763 5764
        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,
5765 5766 5767
                          dev->info.addr.vioserial.port);
    }

5768
    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
5769
        dev->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC &&
5770 5771
        dev->target.name &&
        STRNEQ(dev->target.name, "com.redhat.spice.0")) {
5772 5773 5774
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Unsupported spicevmc target name '%s'"),
                       dev->target.name);
5775 5776
        goto error;
    }
5777

5778 5779 5780 5781 5782 5783 5784
    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");
5785
    }
5786
    if (virBufferCheckError(&buf) < 0)
5787 5788 5789 5790
        goto error;

    return virBufferContentAndReset(&buf);

5791
 error:
5792 5793 5794
    return NULL;
}

5795 5796 5797
static char *
qemuBuildSclpDevStr(virDomainChrDefPtr dev)
{
5798
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814
    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);
5815
    if (virBufferCheckError(&buf) < 0)
5816 5817 5818 5819
        goto error;

    return virBufferContentAndReset(&buf);

5820
 error:
5821 5822 5823
    return NULL;
}

5824 5825

static int
5826
qemuBuildRNGBackendChrdevStr(virLogManagerPtr logManager,
5827
                             virSecurityManagerPtr secManager,
5828
                             virCommandPtr cmd,
5829
                             virQEMUDriverConfigPtr cfg,
5830
                             const virDomainDef *def,
5831
                             virDomainRNGDefPtr rng,
5832
                             virQEMUCapsPtr qemuCaps,
5833 5834
                             char **chr,
                             bool chardevStdioLogd)
5835
{
5836 5837
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
5838 5839 5840

    *chr = NULL;

5841 5842
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
5843 5844 5845 5846 5847 5848 5849 5850

    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:
5851 5852
        if (!(*chr = qemuBuildChrChardevStr(logManager, secManager,
                                            cmd, cfg, def,
5853
                                            rng->source.chardev,
5854 5855
                                            rng->info.alias, qemuCaps,
                                            cdevflags)))
5856 5857 5858 5859 5860 5861 5862
            return -1;
    }

    return 0;
}


5863
int
5864 5865 5866 5867
qemuBuildRNGBackendProps(virDomainRNGDefPtr rng,
                         virQEMUCapsPtr qemuCaps,
                         virJSONValuePtr *props)
{
5868 5869
    VIR_AUTOFREE(char *) objAlias = NULL;
    VIR_AUTOFREE(char *) charBackendAlias = NULL;
5870 5871
    int ret = -1;

5872 5873 5874
    if (virAsprintf(&objAlias, "obj%s", rng->info.alias) < 0)
        goto cleanup;

5875
    switch ((virDomainRNGBackend) rng->backend) {
5876 5877 5878 5879
    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 "
5880
                             "backend"));
5881 5882 5883
            goto cleanup;
        }

5884 5885 5886
        if (qemuMonitorCreateObjectProps(props, "rng-random", objAlias,
                                         "s:filename", rng->source.file,
                                         NULL) < 0)
5887
            goto cleanup;
5888

5889 5890 5891
        break;

    case VIR_DOMAIN_RNG_BACKEND_EGD:
5892 5893 5894 5895 5896 5897 5898
        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;
        }

5899
        if (!(charBackendAlias = qemuAliasChardevFromDevAlias(rng->info.alias)))
5900 5901
            goto cleanup;

5902 5903 5904
        if (qemuMonitorCreateObjectProps(props, "rng-egd", objAlias,
                                         "s:chardev", charBackendAlias,
                                         NULL) < 0)
5905
            goto cleanup;
5906

5907 5908 5909
        break;

    case VIR_DOMAIN_RNG_BACKEND_LAST:
5910 5911 5912
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("unknown rng-random backend"));
        goto cleanup;
5913 5914 5915 5916
    }

    ret = 0;

5917
 cleanup:
5918 5919 5920 5921
    return ret;
}


5922
char *
5923
qemuBuildRNGDevStr(const virDomainDef *def,
5924 5925
                   virDomainRNGDefPtr dev,
                   virQEMUCapsPtr qemuCaps)
5926
{
5927
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
5928

5929
    if (!qemuDomainCheckCCWS390AddressSupport(def, &dev->info, qemuCaps,
5930
                                              dev->source.file))
5931 5932
        goto error;

5933
    if (qemuBuildVirtioDevStr(&buf, "virtio-rng", qemuCaps,
5934
                              VIR_DOMAIN_DEVICE_RNG, dev) < 0) {
5935
        goto error;
5936
    }
5937 5938 5939

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

5941 5942 5943 5944 5945 5946 5947 5948
    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");
    }

5949 5950 5951
    if (qemuBuildVirtioOptionsStr(&buf, dev->virtio, qemuCaps) < 0)
        goto error;

5952
    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
5953 5954 5955
        goto error;
    if (virBufferCheckError(&buf) < 0)
        goto error;
5956

5957
    return virBufferContentAndReset(&buf);
5958

5959 5960
 error:
    return NULL;
5961 5962 5963
}


5964 5965
static int
qemuBuildRNGCommandLine(virLogManagerPtr logManager,
5966
                        virSecurityManagerPtr secManager,
5967
                        virCommandPtr cmd,
5968
                        virQEMUDriverConfigPtr cfg,
5969
                        const virDomainDef *def,
5970 5971
                        virQEMUCapsPtr qemuCaps,
                        bool chardevStdioLogd)
5972 5973 5974 5975
{
    size_t i;

    for (i = 0; i < def->nrngs; i++) {
5976
        VIR_AUTOPTR(virJSONValue) props = NULL;
5977
        virBuffer buf = VIR_BUFFER_INITIALIZER;
5978 5979
        virDomainRNGDefPtr rng = def->rngs[i];
        char *tmp;
5980
        int rc;
5981 5982 5983 5984 5985 5986 5987 5988

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

        /* possibly add character device for backend */
5989
        if (qemuBuildRNGBackendChrdevStr(logManager, secManager, cmd, cfg, def,
5990 5991
                                         rng, qemuCaps, &tmp,
                                         chardevStdioLogd) < 0)
5992 5993 5994 5995 5996 5997 5998
            return -1;

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

5999
        if (qemuBuildRNGBackendProps(rng, qemuCaps, &props) < 0)
6000 6001
            return -1;

6002 6003 6004 6005 6006 6007 6008
        rc = virQEMUBuildObjectCommandlineFromJSON(&buf, props);

        if (rc < 0)
            return -1;

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

        /* add the device */
6011 6012 6013
        if (qemuCommandAddExtDevice(cmd, &rng->info) < 0)
            return -1;

6014 6015 6016 6017 6018 6019 6020 6021 6022 6023
        if (!(tmp = qemuBuildRNGDevStr(def, rng, qemuCaps)))
            return -1;
        virCommandAddArgList(cmd, "-device", tmp, NULL);
        VIR_FREE(tmp);
    }

    return 0;
}


6024 6025
static char *
qemuBuildSmbiosBiosStr(virSysinfoBIOSDefPtr def)
6026
{
6027
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6028

6029
    if (!def)
6030
        return NULL;
6031 6032 6033 6034

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

    /* 0:Vendor */
6035 6036 6037 6038
    if (def->vendor) {
        virBufferAddLit(&buf, ",vendor=");
        virQEMUBuildBufferEscapeComma(&buf, def->vendor);
    }
6039
    /* 0:BIOS Version */
6040 6041 6042 6043
    if (def->version) {
        virBufferAddLit(&buf, ",version=");
        virQEMUBuildBufferEscapeComma(&buf, def->version);
    }
6044
    /* 0:BIOS Release Date */
6045 6046 6047 6048
    if (def->date) {
        virBufferAddLit(&buf, ",date=");
        virQEMUBuildBufferEscapeComma(&buf, def->date);
    }
6049
    /* 0:System BIOS Major Release and 0:System BIOS Minor Release */
6050 6051 6052 6053
    if (def->release) {
        virBufferAddLit(&buf, ",release=");
        virQEMUBuildBufferEscapeComma(&buf, def->release);
    }
6054 6055 6056 6057

    return virBufferContentAndReset(&buf);
}

6058 6059 6060 6061

static char *
qemuBuildSmbiosSystemStr(virSysinfoSystemDefPtr def,
                         bool skip_uuid)
6062
{
6063
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6064

6065 6066 6067 6068
    if (!def ||
        (!def->manufacturer && !def->product && !def->version &&
         !def->serial && (!def->uuid || skip_uuid) &&
         def->sku && !def->family))
6069 6070 6071 6072 6073
        return NULL;

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

    /* 1:Manufacturer */
6074 6075 6076 6077
    if (def->manufacturer) {
        virBufferAddLit(&buf, ",manufacturer=");
        virQEMUBuildBufferEscapeComma(&buf, def->manufacturer);
    }
6078
     /* 1:Product Name */
6079 6080 6081 6082
    if (def->product) {
        virBufferAddLit(&buf, ",product=");
        virQEMUBuildBufferEscapeComma(&buf, def->product);
    }
6083
    /* 1:Version */
6084 6085 6086 6087
    if (def->version) {
        virBufferAddLit(&buf, ",version=");
        virQEMUBuildBufferEscapeComma(&buf, def->version);
    }
6088
    /* 1:Serial Number */
6089 6090 6091 6092
    if (def->serial) {
        virBufferAddLit(&buf, ",serial=");
        virQEMUBuildBufferEscapeComma(&buf, def->serial);
    }
6093
    /* 1:UUID */
6094 6095 6096 6097
    if (def->uuid && !skip_uuid) {
        virBufferAddLit(&buf, ",uuid=");
        virQEMUBuildBufferEscapeComma(&buf, def->uuid);
    }
6098
    /* 1:SKU Number */
6099 6100 6101 6102
    if (def->sku) {
        virBufferAddLit(&buf, ",sku=");
        virQEMUBuildBufferEscapeComma(&buf, def->sku);
    }
6103
    /* 1:Family */
6104 6105 6106 6107
    if (def->family) {
        virBufferAddLit(&buf, ",family=");
        virQEMUBuildBufferEscapeComma(&buf, def->family);
    }
6108 6109 6110 6111

    return virBufferContentAndReset(&buf);
}

6112 6113 6114

static char *
qemuBuildSmbiosBaseBoardStr(virSysinfoBaseBoardDefPtr def)
6115
{
6116
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6117 6118 6119 6120 6121 6122 6123

    if (!def)
        return NULL;

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

    /* 2:Manufacturer */
6124 6125
    virBufferAddLit(&buf, ",manufacturer=");
    virQEMUBuildBufferEscapeComma(&buf, def->manufacturer);
6126
    /* 2:Product Name */
6127 6128 6129 6130
    if (def->product) {
        virBufferAddLit(&buf, ",product=");
        virQEMUBuildBufferEscapeComma(&buf, def->product);
    }
6131
    /* 2:Version */
6132 6133 6134 6135
    if (def->version) {
        virBufferAddLit(&buf, ",version=");
        virQEMUBuildBufferEscapeComma(&buf, def->version);
    }
6136
    /* 2:Serial Number */
6137 6138 6139 6140
    if (def->serial) {
        virBufferAddLit(&buf, ",serial=");
        virQEMUBuildBufferEscapeComma(&buf, def->serial);
    }
6141
    /* 2:Asset Tag */
6142 6143 6144 6145
    if (def->asset) {
        virBufferAddLit(&buf, ",asset=");
        virQEMUBuildBufferEscapeComma(&buf, def->asset);
    }
6146
    /* 2:Location */
6147 6148 6149 6150
    if (def->location) {
        virBufferAddLit(&buf, ",location=");
        virQEMUBuildBufferEscapeComma(&buf, def->location);
    }
6151 6152 6153 6154 6155 6156 6157 6158 6159 6160

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

    return virBufferContentAndReset(&buf);

 error:
    return NULL;
}

6161

6162 6163 6164
static char *
qemuBuildSmbiosOEMStringsStr(virSysinfoOEMStringsDefPtr def)
{
6165
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181
    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);
}


6182 6183 6184
static char *
qemuBuildSmbiosChassisStr(virSysinfoChassisDefPtr def)
{
6185
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225

    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:
    return NULL;
}


6226 6227 6228
static int
qemuBuildSmbiosCommandLine(virCommandPtr cmd,
                           virQEMUDriverPtr driver,
6229
                           const virDomainDef *def)
6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287
{
    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);
        }
6288

6289 6290 6291 6292 6293 6294
        smbioscmd = qemuBuildSmbiosChassisStr(source->chassis);
        if (smbioscmd != NULL) {
            virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
            VIR_FREE(smbioscmd);
        }

6295 6296 6297 6298 6299 6300 6301
        if (source->oemStrings) {
            if (!(smbioscmd = qemuBuildSmbiosOEMStringsStr(source->oemStrings)))
                return -1;

            virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
            VIR_FREE(smbioscmd);
        }
6302 6303 6304 6305 6306 6307
    }

    return 0;
}


6308 6309 6310 6311 6312
static int
qemuBuildVMGenIDCommandLine(virCommandPtr cmd,
                            const virDomainDef *def,
                            virQEMUCapsPtr qemuCaps)
{
6313
    VIR_AUTOCLEAN(virBuffer) opts = VIR_BUFFER_INITIALIZER;
6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334
    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);

    return 0;
}


6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358
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;
}


6359 6360 6361
static char *
qemuBuildClockArgStr(virDomainClockDefPtr def)
{
6362
    size_t i;
6363
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378

    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;

6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397
        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;
6398
        }
6399

6400 6401 6402
        now += def->data.variable.adjustment;
        gmtime_r(&now, &nowbits);

6403 6404 6405 6406 6407 6408 6409 6410
        /* 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;

6411
        virBufferAsprintf(&buf, "base=%d-%02d-%02dT%02d:%02d:%02d",
6412 6413 6414 6415 6416 6417 6418 6419 6420
                          nowbits.tm_year + 1900,
                          nowbits.tm_mon + 1,
                          nowbits.tm_mday,
                          nowbits.tm_hour,
                          nowbits.tm_min,
                          nowbits.tm_sec);
    }   break;

    default:
6421 6422 6423
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unsupported clock offset '%s'"),
                       virDomainClockOffsetTypeToString(def->offset));
6424 6425 6426
        goto error;
    }

6427 6428
    /* Look for an 'rtc' timer element, and add in appropriate
     * clock= and driftfix= */
6429 6430 6431 6432 6433 6434
    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:
6435 6436 6437
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unsupported rtc timer track '%s'"),
                               virDomainTimerTrackTypeToString(def->timers[i]->track));
6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458
                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:
6459 6460 6461
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unsupported rtc timer tickpolicy '%s'"),
                               virDomainTimerTickpolicyTypeToString(def->timers[i]->tickpolicy));
6462 6463 6464 6465 6466 6467
                goto error;
            }
            break; /* no need to check other timers - there is only one rtc */
        }
    }

6468
    if (virBufferCheckError(&buf) < 0)
6469 6470 6471 6472
        goto error;

    return virBufferContentAndReset(&buf);

6473
 error:
6474 6475 6476
    return NULL;
}

6477 6478 6479 6480 6481 6482 6483 6484 6485 6486

/* 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;
6487
    VIR_AUTOFREE(char *) rtcopt = NULL;
6488

J
Ján Tomko 已提交
6489 6490 6491 6492
    virCommandAddArg(cmd, "-rtc");
    if (!(rtcopt = qemuBuildClockArgStr(&def->clock)))
        return -1;
    virCommandAddArg(cmd, rtcopt);
6493 6494 6495 6496 6497 6498 6499

    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++) {
6500
        switch ((virDomainTimerNameType)def->clock.timers[i]->name) {
6501 6502 6503 6504 6505 6506
        case VIR_DOMAIN_TIMER_NAME_PLATFORM:
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("unsupported timer type (name) '%s'"),
                           virDomainTimerNameTypeToString(def->clock.timers[i]->name));
            return -1;

6507
        case VIR_DOMAIN_TIMER_NAME_TSC:
6508 6509 6510 6511 6512 6513 6514
        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:
6515
            /* Already handled in qemuBuildClockArgStr */
6516 6517 6518 6519 6520 6521 6522
            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 已提交
6523
                   (kvm-pit), otherwise, the default is catchup. */
6524 6525
                if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY))
                    virCommandAddArgList(cmd, "-global",
6526
                                         "kvm-pit.lost_tick_policy=delay", NULL);
6527 6528
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
J
Ján Tomko 已提交
6529
                if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) {
6530 6531
                    /* do nothing - this is default for kvm-pit */
                } else {
J
Ján Tomko 已提交
6532
                    /* can't catchup if we don't have kvm-pit */
6533 6534 6535 6536 6537 6538 6539
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   _("unsupported pit tickpolicy '%s'"),
                                   virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
                    return -1;
                }
                break;
            case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
6540 6541 6542 6543 6544 6545
                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 */
6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580
                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;
}


6581 6582 6583
static int
qemuBuildPMCommandLine(virCommandPtr cmd,
                       const virDomainDef *def,
6584
                       qemuDomainObjPrivatePtr priv)
6585
{
6586
    virQEMUCapsPtr qemuCaps = priv->qemuCaps;
6587 6588

    /* Only add -no-reboot option if each event destroys domain */
6589
    if (priv->allowReboot == VIR_TRISTATE_BOOL_NO)
6590 6591
        virCommandAddArg(cmd, "-no-reboot");

J
John Ferlan 已提交
6592
    if (qemuDomainIsUsingNoShutdown(priv))
6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606
        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";

6607
        if (qemuDomainIsQ35(def) &&
6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623
            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";

6624
        if (qemuDomainIsQ35(def) &&
6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641
            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;
}


6642 6643 6644
static int
qemuBuildBootCommandLine(virCommandPtr cmd,
                         const virDomainDef *def,
6645
                         virQEMUCapsPtr qemuCaps)
6646
{
6647
    VIR_AUTOCLEAN(virBuffer) boot_buf = VIR_BUFFER_INITIALIZER;
6648
    VIR_AUTOFREE(char *) boot_opts_str = NULL;
6649 6650

    if (def->os.bootmenu) {
J
Ján Tomko 已提交
6651 6652 6653 6654
        if (def->os.bootmenu == VIR_TRISTATE_BOOL_YES)
            virBufferAddLit(&boot_buf, "menu=on,");
        else
            virBufferAddLit(&boot_buf, "menu=off,");
6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689
    }

    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);
6690
    if (boot_opts_str) {
6691
        virCommandAddArg(cmd, "-boot");
6692
        virCommandAddArg(cmd, boot_opts_str);
6693 6694 6695 6696 6697 6698 6699 6700
    }

    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 已提交
6701 6702
    if (def->os.dtb)
        virCommandAddArgList(cmd, "-dtb", def->os.dtb, NULL);
6703 6704 6705 6706
    if (def->os.slic_table) {
        virBuffer buf = VIR_BUFFER_INITIALIZER;
        virCommandAddArg(cmd, "-acpitable");
        virBufferAddLit(&buf, "sig=SLIC,file=");
6707
        virQEMUBuildBufferEscapeComma(&buf, def->os.slic_table);
6708 6709
        virCommandAddArgBuffer(cmd, &buf);
    }
6710 6711 6712 6713 6714 6715 6716 6717

    return 0;

 error:
    return -1;
}


6718 6719 6720 6721 6722
static int
qemuBuildIOMMUCommandLine(virCommandPtr cmd,
                          const virDomainDef *def,
                          virQEMUCapsPtr qemuCaps)
{
6723 6724 6725
    const virDomainIOMMUDef *iommu = def->iommu;

    if (!iommu)
6726 6727
        return 0;

6728
    switch (iommu->model) {
6729 6730 6731
    case VIR_DOMAIN_IOMMU_MODEL_INTEL: {
        VIR_AUTOCLEAN(virBuffer) opts = VIR_BUFFER_INITIALIZER;

6732 6733 6734 6735 6736 6737 6738
        /* qemuDomainDeviceDefValidateIOMMU() already made sure we have
         * one of QEMU_CAPS_DEVICE_INTEL_IOMMU or QEMU_CAPS_MACHINE_IOMMU:
         * here we handle the former case, while the latter is taken care
         * of in qemuBuildMachineCommandLine() */
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_INTEL_IOMMU))
            return 0;

6739
        virBufferAddLit(&opts, "intel-iommu");
6740 6741 6742 6743
        if (iommu->intremap != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&opts, ",intremap=%s",
                              virTristateSwitchTypeToString(iommu->intremap));
        }
6744 6745 6746 6747
        if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&opts, ",caching-mode=%s",
                              virTristateSwitchTypeToString(iommu->caching_mode));
        }
6748 6749 6750 6751
        if (iommu->eim != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&opts, ",eim=%s",
                              virTristateSwitchTypeToString(iommu->eim));
        }
6752 6753 6754 6755
        if (iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT) {
            virBufferAsprintf(&opts, ",device-iotlb=%s",
                              virTristateSwitchTypeToString(iommu->iotlb));
        }
6756 6757 6758

        virCommandAddArg(cmd, "-device");
        virCommandAddArgBuffer(cmd, &opts);
6759
        break;
6760
    }
6761

6762
    case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
A
Andrea Bolognani 已提交
6763 6764
        /* There is no -device for SMMUv3, so nothing to be done here */
        return 0;
6765

6766 6767 6768 6769
    case VIR_DOMAIN_IOMMU_MODEL_LAST:
    default:
        virReportEnumRangeError(virDomainIOMMUModel, iommu->model);
        return -1;
6770
    }
6771

6772
    return 0;
6773 6774 6775
}


6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790
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;

6791
            switch (cont->model) {
6792 6793 6794
            case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
                hoststr = "i440FX-pcihost";
                cap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_I440FX_PCI_HOLE64_SIZE);
6795
                machine = qemuDomainIsI440FX(def);
6796 6797 6798 6799 6800
                break;

            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
                hoststr = "q35-pcihost";
                cap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_Q35_PCI_HOLE64_SIZE);
6801
                machine = qemuDomainIsQ35(def);
6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833
                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;
}


6834 6835 6836 6837 6838 6839
static void
qemuBuildCpuFeature(virQEMUCapsPtr qemuCaps,
                    virBufferPtr buf,
                    const char *name,
                    bool state)
{
6840 6841
    name = virQEMUCapsCPUFeatureToQEMU(qemuCaps, name);

6842 6843 6844 6845 6846 6847 6848
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
        virBufferAsprintf(buf, ",%s=%s", name, state ? "on" : "off");
    else
        virBufferAsprintf(buf, ",%c%s", state ? '+' : '-', name);
}


6849
static int
6850 6851 6852
qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
                        const virDomainDef *def,
                        virBufferPtr buf,
6853
                        virQEMUCapsPtr qemuCaps)
6854
{
6855 6856
    int ret = -1;
    size_t i;
6857
    virCapsPtr caps = NULL;
6858
    virCPUDefPtr cpu = def->cpu;
6859

6860 6861 6862
    if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
        goto cleanup;

6863 6864
    switch ((virCPUMode) cpu->mode) {
    case VIR_CPU_MODE_HOST_PASSTHROUGH:
6865
        virBufferAddLit(buf, "host");
6866

6867
        if (def->os.arch == VIR_ARCH_ARMV7L &&
6868
            caps->host.arch == VIR_ARCH_AARCH64) {
6869 6870 6871 6872 6873 6874 6875 6876 6877
            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");
        }
6878
        break;
6879

6880 6881 6882
    case VIR_CPU_MODE_HOST_MODEL:
        if (ARCH_IS_PPC64(def->os.arch)) {
            virBufferAddLit(buf, "host");
6883 6884 6885
            if (cpu->model &&
                !(qemuDomainIsPSeries(def) &&
                  virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_MAX_CPU_COMPAT))) {
6886
                virBufferAsprintf(buf, ",compat=%s", cpu->model);
6887
            }
6888
        } else {
6889 6890 6891
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected host-model CPU for %s architecture"),
                           virArchToString(def->os.arch));
6892
            goto cleanup;
6893 6894
        }
        break;
6895

6896 6897 6898
    case VIR_CPU_MODE_CUSTOM:
        virBufferAdd(buf, cpu->model, -1);
        break;
6899

6900 6901 6902
    case VIR_CPU_MODE_LAST:
        break;
    }
6903

6904 6905 6906 6907 6908 6909 6910 6911
    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;
    }

6912 6913
    if (cpu->vendor_id)
        virBufferAsprintf(buf, ",vendor=%s", cpu->vendor_id);
6914

6915 6916 6917 6918
    for (i = 0; i < cpu->nfeatures; i++) {
        switch ((virCPUFeaturePolicy) cpu->features[i].policy) {
        case VIR_CPU_FEATURE_FORCE:
        case VIR_CPU_FEATURE_REQUIRE:
6919
            qemuBuildCpuFeature(qemuCaps, buf, cpu->features[i].name, true);
6920
            break;
6921

6922 6923
        case VIR_CPU_FEATURE_DISABLE:
        case VIR_CPU_FEATURE_FORBID:
6924
            qemuBuildCpuFeature(qemuCaps, buf, cpu->features[i].name, false);
6925
            break;
6926

6927 6928 6929
        case VIR_CPU_FEATURE_OPTIONAL:
        case VIR_CPU_FEATURE_LAST:
            break;
6930
        }
6931
    }
6932

6933
    ret = 0;
6934
 cleanup:
6935 6936 6937
    virObjectUnref(caps);
    return ret;
}
6938

6939
static int
6940 6941 6942
qemuBuildCpuCommandLine(virCommandPtr cmd,
                        virQEMUDriverPtr driver,
                        const virDomainDef *def,
6943
                        virQEMUCapsPtr qemuCaps)
6944
{
6945
    virArch hostarch = virArchFromHost();
6946 6947
    VIR_AUTOFREE(char *) cpu = NULL;
    VIR_AUTOFREE(char *) cpu_flags = NULL;
6948
    int ret = -1;
6949 6950
    VIR_AUTOCLEAN(virBuffer) cpu_buf = VIR_BUFFER_INITIALIZER;
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
6951
    size_t i;
6952

6953 6954
    if (def->cpu &&
        (def->cpu->mode != VIR_CPU_MODE_CUSTOM || def->cpu->model)) {
6955
        if (qemuBuildCpuModelArgStr(driver, def, &cpu_buf, qemuCaps) < 0)
6956
            goto cleanup;
6957
    } else {
6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969
        /*
         * 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
         */
6970
        if (def->os.arch == VIR_ARCH_I686 &&
6971
            ((hostarch == VIR_ARCH_X86_64 &&
J
John Ferlan 已提交
6972 6973
              strstr(def->emulator, "kvm")) ||
             strstr(def->emulator, "x86_64"))) {
6974
            virBufferAddLit(&cpu_buf, "qemu32");
6975 6976 6977
        }
    }

6978
    /* Handle paravirtual timers  */
6979
    for (i = 0; i < def->clock.ntimers; i++) {
6980 6981
        virDomainTimerDefPtr timer = def->clock.timers[i];

6982 6983
        if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK &&
            timer->present != -1) {
6984 6985
            qemuBuildCpuFeature(qemuCaps, &buf, "kvmclock",
                                !!timer->present);
6986
        } else if (timer->name == VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK &&
6987
                   timer->present == 1) {
6988
            virBufferAddLit(&buf, ",hv-time");
6989 6990
        } else if (timer->name == VIR_DOMAIN_TIMER_NAME_TSC &&
                   timer->frequency > 0) {
6991
            virBufferAsprintf(&buf, ",tsc-frequency=%lu", timer->frequency);
6992
        }
6993 6994
    }

6995
    if (def->apic_eoi) {
6996 6997
        qemuBuildCpuFeature(qemuCaps, &buf, "kvm_pv_eoi",
                            def->apic_eoi == VIR_TRISTATE_SWITCH_ON);
6998 6999
    }

7000
    if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK]) {
7001
        qemuBuildCpuFeature(qemuCaps, &buf, VIR_CPU_x86_KVM_PV_UNHALT,
7002
                            def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] == VIR_TRISTATE_SWITCH_ON);
7003 7004
    }

J
Ján Tomko 已提交
7005
    if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_TRISTATE_SWITCH_ON) {
7006 7007 7008 7009 7010
        const char *hvPrefix = "hv-";

        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CANONICAL_CPU_FEATURES))
            hvPrefix = "hv_";

7011
        for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
7012
            switch ((virDomainHyperv) i) {
7013
            case VIR_DOMAIN_HYPERV_RELAXED:
7014
            case VIR_DOMAIN_HYPERV_VAPIC:
7015 7016 7017 7018 7019
            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:
7020
            case VIR_DOMAIN_HYPERV_FREQUENCIES:
7021
            case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
7022
            case VIR_DOMAIN_HYPERV_TLBFLUSH:
7023
            case VIR_DOMAIN_HYPERV_IPI:
7024
            case VIR_DOMAIN_HYPERV_EVMCS:
J
Ján Tomko 已提交
7025
                if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON)
7026 7027
                    virBufferAsprintf(&buf, ",%s%s",
                                      hvPrefix,
7028
                                      virDomainHypervTypeToString(i));
7029 7030 7031
                if ((i == VIR_DOMAIN_HYPERV_STIMER) &&
                    (def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON))
                    virBufferAsprintf(&buf, ",%s", VIR_CPU_x86_HV_STIMER_DIRECT);
7032 7033
                break;

7034
            case VIR_DOMAIN_HYPERV_SPINLOCKS:
J
Ján Tomko 已提交
7035
                if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON)
7036
                    virBufferAsprintf(&buf, ",%s=0x%x",
7037
                                      VIR_CPU_x86_HV_SPINLOCKS,
7038
                                      def->hyperv_spinlocks);
7039 7040
                break;

7041 7042
            case VIR_DOMAIN_HYPERV_VENDOR_ID:
                if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON)
7043
                    virBufferAsprintf(&buf, ",hv-vendor-id=%s",
7044 7045 7046
                                      def->hyperv_vendor_id);
                break;

7047
            /* coverity[dead_error_begin] */
7048 7049 7050 7051 7052 7053
            case VIR_DOMAIN_HYPERV_LAST:
                break;
            }
        }
    }

D
Dmitry Andreev 已提交
7054 7055
    for (i = 0; i < def->npanics; i++) {
        if (def->panics[i]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) {
7056
            virBufferAddLit(&buf, ",hv-crash");
D
Dmitry Andreev 已提交
7057 7058
            break;
        }
7059 7060
    }

7061 7062 7063 7064 7065 7066 7067 7068
    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;

7069 7070 7071 7072 7073
            case VIR_DOMAIN_KVM_DEDICATED:
                if (def->kvm_features[i] == VIR_TRISTATE_SWITCH_ON)
                    virBufferAddLit(&buf, ",kvm-hint-dedicated=on");
                break;

J
John Ferlan 已提交
7074
            /* coverity[dead_error_begin] */
7075 7076 7077 7078 7079 7080
            case VIR_DOMAIN_KVM_LAST:
                break;
            }
        }
    }

7081 7082 7083 7084 7085 7086
    if (def->features[VIR_DOMAIN_FEATURE_PMU]) {
        virTristateSwitch pmu = def->features[VIR_DOMAIN_FEATURE_PMU];
        virBufferAsprintf(&buf, ",pmu=%s",
                          virTristateSwitchTypeToString(pmu));
    }

7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120
    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");
    }

7121 7122
    if (virBufferCheckError(&cpu_buf) < 0)
        goto cleanup;
7123
    if (virBufferCheckError(&buf) < 0)
7124
        goto cleanup;
7125

7126 7127 7128 7129
    cpu = virBufferContentAndReset(&cpu_buf);
    cpu_flags = virBufferContentAndReset(&buf);

    if (cpu_flags && !cpu) {
7130 7131
        const char *default_model;

7132
        switch ((int)def->os.arch) {
7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146
        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;
        }

7147 7148 7149
        if (VIR_STRDUP(cpu, default_model) < 0)
            goto cleanup;
    }
7150 7151

    if (cpu) {
7152
        virCommandAddArg(cmd, "-cpu");
J
Ján Tomko 已提交
7153
        virCommandAddArgFormat(cmd, "%s%s", cpu, NULLSTR_EMPTY(cpu_flags));
7154
    }
7155 7156 7157

    ret = 0;

7158
 cleanup:
7159 7160 7161
    return ret;
}

7162

7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195
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;
}

7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223

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 已提交
7224 7225 7226 7227 7228 7229
static int
qemuBuildNameCommandLine(virCommandPtr cmd,
                         virQEMUDriverConfigPtr cfg,
                         const virDomainDef *def,
                         virQEMUCapsPtr qemuCaps)
{
7230
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
M
Marc-André Lureau 已提交
7231 7232 7233

    virCommandAddArg(cmd, "-name");

7234 7235 7236 7237
    /* The 'guest' option let's us handle a name with '=' embedded in it */
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NAME_GUEST))
        virBufferAddLit(&buf, "guest=");

7238
    virQEMUBuildBufferEscapeComma(&buf, def->name);
M
Marc-André Lureau 已提交
7239

7240
    if (cfg->setProcessName)
M
Marc-André Lureau 已提交
7241 7242 7243 7244 7245 7246 7247 7248 7249 7250
        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;
}

7251
static int
7252
qemuBuildMachineCommandLine(virCommandPtr cmd,
7253
                            virQEMUDriverConfigPtr cfg,
7254 7255
                            const virDomainDef *def,
                            virQEMUCapsPtr qemuCaps)
7256
{
7257 7258 7259
    virTristateSwitch vmport = def->features[VIR_DOMAIN_FEATURE_VMPORT];
    virTristateSwitch smm = def->features[VIR_DOMAIN_FEATURE_SMM];
    virCPUDefPtr cpu = def->cpu;
7260
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
M
Michal Privoznik 已提交
7261
    size_t i;
7262
    int ret = -1;
7263

7264 7265 7266 7267 7268 7269 7270
    /* 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;

7271 7272 7273
    virCommandAddArg(cmd, "-machine");
    virBufferAdd(&buf, def->os.machine, -1);

7274
    switch ((virDomainVirtType)def->virtType) {
7275
    case VIR_DOMAIN_VIRT_QEMU:
7276
        virBufferAddLit(&buf, ",accel=tcg");
7277 7278 7279
        break;

    case VIR_DOMAIN_VIRT_KVM:
7280
        virBufferAddLit(&buf, ",accel=kvm");
7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296
        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:
7297 7298 7299 7300
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("the QEMU binary does not support %s"),
                       virDomainVirtTypeToString(def->virtType));
        return -1;
7301 7302 7303 7304 7305

    case VIR_DOMAIN_VIRT_LAST:
    default:
        virReportEnumRangeError(virDomainVirtType, def->virtType);
        return -1;
7306
    }
7307 7308 7309 7310

    /* To avoid the collision of creating USB controllers when calling
     * machine->init in QEMU, it needs to set usb=off
     */
7311
    virBufferAddLit(&buf, ",usb=off");
7312 7313 7314

    if (vmport) {
        if (!virQEMUCapsSupportsVmport(qemuCaps, def)) {
7315
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7316
                           _("vmport is not available "
7317
                             "with this QEMU binary"));
7318
            goto cleanup;
7319
        }
7320

7321 7322 7323 7324
        virBufferAsprintf(&buf, ",vmport=%s",
                          virTristateSwitchTypeToString(vmport));
    }

7325 7326
    if (smm)
        virBufferAsprintf(&buf, ",smm=%s", virTristateSwitchTypeToString(smm));
7327

7328 7329 7330
    if (def->mem.dump_core) {
        virBufferAsprintf(&buf, ",dump-guest-core=%s",
                          virTristateSwitchTypeToString(def->mem.dump_core));
7331
    } else {
7332 7333
        virBufferAsprintf(&buf, ",dump-guest-core=%s",
                          cfg->dumpGuestCore ? "on" : "off");
7334
    }
M
Michal Privoznik 已提交
7335

7336 7337 7338 7339 7340 7341
    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 已提交
7342
        }
7343

7344 7345
        virBufferAddLit(&buf, ",mem-merge=off");
    }
7346

7347 7348 7349
    if (def->keywrap &&
        !qemuAppendKeyWrapMachineParms(&buf, qemuCaps, def->keywrap))
        goto cleanup;
7350

7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366
    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 已提交
7367

7368 7369 7370
        case VIR_GIC_VERSION_3:
        case VIR_GIC_VERSION_HOST:
            if (!hasGICVersionOption) {
7371
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7372
                               _("gic-version option is not available "
7373
                                 "with this QEMU binary"));
7374
                goto cleanup;
7375 7376
            }

7377 7378 7379
            virBufferAsprintf(&buf, ",gic-version=%s",
                              virGICVersionTypeToString(def->gic_version));
            break;
M
Michal Privoznik 已提交
7380

7381 7382 7383 7384
        case VIR_GIC_VERSION_NONE:
        case VIR_GIC_VERSION_LAST:
        default:
            break;
M
Michal Privoznik 已提交
7385
        }
7386
    }
M
Michal Privoznik 已提交
7387

7388
    if (def->iommu) {
7389 7390
        switch (def->iommu->model) {
        case VIR_DOMAIN_IOMMU_MODEL_INTEL:
7391 7392 7393 7394 7395 7396
            /* qemuDomainDeviceDefValidateIOMMU() already made sure we have
             * one of QEMU_CAPS_DEVICE_INTEL_IOMMU or QEMU_CAPS_MACHINE_IOMMU:
             * here we handle the latter case, while the former is taken care
             * of in qemuBuildIOMMUCommandLine() */
            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_IOMMU))
                virBufferAddLit(&buf, ",iommu=on");
7397
            break;
7398 7399

        case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
A
Andrea Bolognani 已提交
7400
            virBufferAddLit(&buf, ",iommu=smmuv3");
7401 7402
            break;

7403
        case VIR_DOMAIN_IOMMU_MODEL_LAST:
7404 7405 7406
        default:
            virReportEnumRangeError(virDomainIOMMUModel, def->iommu->model);
            return -1;
7407
        }
7408
    }
7409

7410 7411 7412
    for (i = 0; i < def->nmems; i++) {
        if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM) {
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_NVDIMM)) {
7413
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7414
                               _("nvdimm isn't supported by this QEMU binary"));
7415
                goto cleanup;
7416
            }
7417 7418
            virBufferAddLit(&buf, ",nvdimm=on");
            break;
7419
        }
7420
    }
7421

7422 7423 7424 7425 7426
    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"));
7427
            goto cleanup;
M
Michal Privoznik 已提交
7428
        }
7429 7430 7431
        switch ((virDomainIOAPIC) def->features[VIR_DOMAIN_FEATURE_IOAPIC]) {
        case VIR_DOMAIN_IOAPIC_QEMU:
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_KERNEL_IRQCHIP_SPLIT)) {
7432
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7433
                               _("split I/O APIC is not supported by this "
7434 7435 7436
                                 "QEMU binary"));
                goto cleanup;
            }
7437 7438 7439 7440 7441 7442 7443 7444
            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;
7445
        }
7446
    }
7447

7448
    if (def->features[VIR_DOMAIN_FEATURE_HPT] == VIR_TRISTATE_SWITCH_ON) {
7449

7450 7451
        if (def->hpt_resizing != VIR_DOMAIN_HPT_RESIZING_NONE) {
            const char *str;
7452

7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465
            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;
            }
7466

7467 7468
            virBufferAsprintf(&buf, ",resize-hpt=%s", str);
        }
7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480

        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);
        }
7481
    }
7482

7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502
    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);
    }

7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522
    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);
    }

7523 7524 7525 7526 7527
    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);
7528 7529
    }

7530
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
7531 7532
        qemuAppendLoadparmMachineParm(&buf, def);

7533 7534 7535
    if (def->sev)
        virBufferAddLit(&buf, ",memory-encryption=sev0");

7536 7537
    virCommandAddArgBuffer(cmd, &buf);

7538 7539 7540
    ret = 0;
 cleanup:
    return ret;
7541 7542
}

7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558

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);
}


7559 7560
static int
qemuBuildSmpCommandLine(virCommandPtr cmd,
7561
                        virDomainDefPtr def)
7562
{
7563
    char *smp = NULL;
7564
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576
    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++;
    }
7577

7578 7579
    virCommandAddArg(cmd, "-smp");

7580
    virBufferAsprintf(&buf, "%u", nvcpus);
7581

7582 7583
    if (nvcpus != maxvcpus)
        virBufferAsprintf(&buf, ",maxcpus=%u", maxvcpus);
7584 7585 7586 7587 7588 7589 7590 7591 7592 7593
    /* 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);
7594 7595
    }

7596
    if (virBufferCheckError(&buf) < 0)
7597
        return -1;
7598

7599 7600 7601 7602 7603
    smp = virBufferContentAndReset(&buf);
    virCommandAddArg(cmd, smp);
    VIR_FREE(smp);

    return 0;
7604 7605
}

7606

7607 7608
static int
qemuBuildMemPathStr(virQEMUDriverConfigPtr cfg,
7609
                    const virDomainDef *def,
7610 7611
                    virCommandPtr cmd,
                    qemuDomainObjPrivatePtr priv)
7612 7613
{
    const long system_page_size = virGetSystemPageSizeKB();
7614
    VIR_AUTOFREE(char *) mem_path = NULL;
7615

7616 7617 7618 7619 7620 7621
    /* 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) {
7622 7623 7624 7625 7626
        unsigned long long pagesize = def->mem.hugepages[0].size;
        if (!pagesize &&
            qemuBuildMemoryGetDefaultPagesize(cfg, &pagesize) < 0)
            return -1;
        if (qemuGetDomainHupageMemPath(def, cfg, pagesize, &mem_path) < 0)
7627 7628 7629 7630 7631
            return -1;
    } else if (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) {
        if (qemuGetMemoryBackingPath(def, cfg, "ram", &mem_path) < 0)
            return -1;
    } else {
7632
        return 0;
7633
    }
7634

7635
    if (def->mem.allocation != VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) {
7636
        virCommandAddArgList(cmd, "-mem-prealloc", NULL);
7637 7638
        priv->memPrealloc = true;
    }
7639 7640

    virCommandAddArgList(cmd, "-mem-path", mem_path, NULL);
7641 7642 7643 7644

    return 0;
}

7645 7646 7647 7648 7649

static int
qemuBuildMemCommandLine(virCommandPtr cmd,
                        virQEMUDriverConfigPtr cfg,
                        const virDomainDef *def,
7650 7651
                        virQEMUCapsPtr qemuCaps,
                        qemuDomainObjPrivatePtr priv)
7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669
{
    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);
    }

7670
    if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) {
7671
        virCommandAddArgList(cmd, "-mem-prealloc", NULL);
7672 7673
        priv->memPrealloc = true;
    }
7674

7675
    /*
7676 7677
     * Add '-mem-path' (and '-mem-prealloc') parameter here if
     * the hugepages and no numa node is specified.
7678 7679
     */
    if (!virDomainNumaGetNodeCount(def->numa) &&
7680
        qemuBuildMemPathStr(cfg, def, cmd, priv) < 0)
7681 7682
        return -1;

7683 7684 7685 7686 7687 7688 7689 7690
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_OVERCOMMIT)) {
        virCommandAddArg(cmd, "-overcommit");
        virCommandAddArgFormat(cmd, "mem-lock=%s", def->mem.locked ? "on" : "off");
    } else {
        virCommandAddArg(cmd, "-realtime");
        virCommandAddArgFormat(cmd, "mlock=%s",
                               def->mem.locked ? "on" : "off");
    }
7691 7692 7693 7694 7695

    return 0;
}


7696 7697
static int
qemuBuildIOThreadCommandLine(virCommandPtr cmd,
7698
                             const virDomainDef *def)
7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719
{
    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 已提交
7720
static int
7721
qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
7722
                    virDomainDefPtr def,
7723
                    virCommandPtr cmd,
7724
                    qemuDomainObjPrivatePtr priv)
B
Bharata B Rao 已提交
7725
{
7726
    size_t i, j;
7727
    virQEMUCapsPtr qemuCaps = priv->qemuCaps;
7728
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7729 7730 7731
    char *cpumask = NULL;
    char *tmpmask = NULL;
    char *next = NULL;
7732
    virBufferPtr nodeBackends = NULL;
7733 7734
    bool needBackend = false;
    int rc;
7735
    int ret = -1;
7736
    size_t ncells = virDomainNumaGetNodeCount(def->numa);
7737
    const long system_page_size = virGetSystemPageSizeKB();
7738
    bool numa_distances = false;
B
Bharata B Rao 已提交
7739

7740
    if (virDomainNumatuneHasPerNodeBinding(def->numa) &&
7741
        !(virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) ||
M
Marc-André Lureau 已提交
7742 7743
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE) ||
          virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD))) {
7744 7745 7746 7747 7748 7749
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Per-node memory binding is not supported "
                         "with this QEMU"));
        goto cleanup;
    }

7750 7751
    if (def->mem.nhugepages &&
        def->mem.hugepages[0].size != system_page_size &&
7752 7753 7754 7755 7756 7757 7758
        !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;
    }

7759
    if (!virDomainNumatuneNodesetIsAvailable(def->numa, priv->autoNodeset))
7760 7761
        goto cleanup;

7762
    if (VIR_ALLOC_N(nodeBackends, ncells) < 0)
7763 7764 7765 7766
        goto cleanup;

    /* using of -numa memdev= cannot be combined with -numa mem=, thus we
     * need to check which approach to use */
7767
    for (i = 0; i < ncells; i++) {
7768
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) ||
M
Marc-André Lureau 已提交
7769 7770
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE) ||
            virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD)) {
7771

7772
            if ((rc = qemuBuildMemoryCellBackendStr(def, cfg, i, priv,
7773
                                                    &nodeBackends[i])) < 0)
7774 7775
                goto cleanup;

7776 7777
            if (rc == 0)
                needBackend = true;
7778
        } else {
7779
            if (virDomainNumaGetNodeMemoryAccessMode(def->numa, i)) {
7780 7781 7782 7783 7784
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("Shared memory mapping is not supported "
                                 "with this QEMU"));
                goto cleanup;
            }
7785
        }
7786 7787
    }

7788
    if (!needBackend &&
7789
        qemuBuildMemPathStr(cfg, def, cmd, priv) < 0)
7790 7791
        goto cleanup;

7792
    for (i = 0; i < ncells; i++) {
7793
        VIR_FREE(cpumask);
7794
        if (!(cpumask = virBitmapFormat(virDomainNumaGetNodeCpumask(def->numa, i))))
7795 7796 7797 7798 7799 7800 7801 7802 7803 7804
            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;
        }

7805 7806
        if (needBackend) {
            virCommandAddArg(cmd, "-object");
7807
            virCommandAddArgBuffer(cmd, &nodeBackends[i]);
7808
        }
7809

B
Bharata B Rao 已提交
7810
        virCommandAddArg(cmd, "-numa");
7811
        virBufferAsprintf(&buf, "node,nodeid=%zu", i);
7812

7813 7814 7815 7816 7817 7818 7819
        for (tmpmask = cpumask; tmpmask; tmpmask = next) {
            if ((next = strchr(tmpmask, ',')))
                *(next++) = '\0';
            virBufferAddLit(&buf, ",cpus=");
            virBufferAdd(&buf, tmpmask, -1);
        }

7820
        if (needBackend)
7821
            virBufferAsprintf(&buf, ",memdev=ram-node%zu", i);
7822
        else
7823
            virBufferAsprintf(&buf, ",mem=%llu",
7824
                              virDomainNumaGetNodeMemorySize(def->numa, i) / 1024);
B
Bharata B Rao 已提交
7825 7826 7827

        virCommandAddArgBuffer(cmd, &buf);
    }
7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863

    /* 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);
            }
        }
    }

7864
    ret = 0;
B
Bharata B Rao 已提交
7865

7866
 cleanup:
7867
    VIR_FREE(cpumask);
7868 7869

    if (nodeBackends) {
7870
        for (i = 0; i < ncells; i++)
7871
            virBufferFreeAndReset(&nodeBackends[i]);
7872 7873 7874 7875

        VIR_FREE(nodeBackends);
    }

7876
    return ret;
B
Bharata B Rao 已提交
7877
}
7878

7879

7880
static int
7881 7882 7883
qemuBuildMemoryDeviceCommandLine(virCommandPtr cmd,
                                 virQEMUDriverConfigPtr cfg,
                                 virDomainDefPtr def,
7884
                                 qemuDomainObjPrivatePtr priv)
7885 7886 7887 7888 7889 7890
{
    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++) {
7891
        VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
7892 7893
        char *dimmStr;

7894
        if (qemuBuildMemoryDimmBackendStr(&buf, def->mems[i], def, cfg, priv) < 0)
7895 7896
            return -1;

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

7900
        if (!(dimmStr = qemuBuildMemoryDeviceStr(def->mems[i], priv)))
7901 7902
            return -1;

7903
        virCommandAddArgList(cmd, "-device", dimmStr, NULL);
7904 7905 7906 7907 7908 7909 7910 7911

        VIR_FREE(dimmStr);
    }

    return 0;
}


7912 7913 7914 7915 7916 7917
static int
qemuBuildGraphicsSDLCommandLine(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
                                virCommandPtr cmd,
                                virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED,
                                virDomainGraphicsDefPtr graphics)
{
7918
    int ret = -1;
7919
    VIR_AUTOCLEAN(virBuffer) opt = VIR_BUFFER_INITIALIZER;
7920

7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931
    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
     */
7932 7933
    virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
    virCommandAddEnvPass(cmd, "SDL_AUDIODRIVER");
7934

7935 7936
    virCommandAddArg(cmd, "-display");
    virBufferAddLit(&opt, "sdl");
7937

7938
    if (graphics->data.sdl.gl != VIR_TRISTATE_BOOL_ABSENT) {
7939 7940
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SDL_GL)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7941 7942
                           _("OpenGL for SDL is not supported with this QEMU "
                             "binary"));
7943 7944 7945
            goto cleanup;
        }

7946
        virBufferAsprintf(&opt, ",gl=%s",
7947
                          virTristateSwitchTypeToString(graphics->data.sdl.gl));
7948

7949 7950
    }

7951 7952 7953 7954
    if (virBufferCheckError(&opt) < 0)
        goto cleanup;

    virCommandAddArgBuffer(cmd, &opt);
7955 7956 7957 7958

    ret = 0;
 cleanup:
    return ret;
7959 7960 7961
}


7962 7963 7964 7965
static int
qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg,
                                virCommandPtr cmd,
                                virQEMUCapsPtr qemuCaps,
7966
                                virDomainGraphicsDefPtr graphics)
7967
{
7968
    VIR_AUTOCLEAN(virBuffer) opt = VIR_BUFFER_INITIALIZER;
7969
    virDomainGraphicsListenDefPtr glisten = NULL;
7970 7971 7972 7973 7974 7975 7976 7977
    bool escapeAddr;

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VNC)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("vnc graphics are not supported with this QEMU"));
        goto error;
    }

7978 7979 7980 7981 7982
    if (!(glisten = virDomainGraphicsGetListen(graphics, 0))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("missing listen element"));
        goto error;
    }
7983

7984 7985
    switch (glisten->type) {
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
7986 7987 7988 7989
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VNC_MULTI_SERVERS))
            virBufferAddLit(&opt, "vnc=unix:");
        else
            virBufferAddLit(&opt, "unix:");
7990
        virQEMUBuildBufferEscapeComma(&opt, glisten->socket);
7991
        break;
7992

7993 7994
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
7995 7996 7997 7998 7999 8000 8001
        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;
        }
8002

8003
        if (glisten->address) {
8004 8005 8006 8007 8008
            escapeAddr = strchr(glisten->address, ':') != NULL;
            if (escapeAddr)
                virBufferAsprintf(&opt, "[%s]", glisten->address);
            else
                virBufferAdd(&opt, glisten->address, -1);
8009 8010 8011
        }
        virBufferAsprintf(&opt, ":%d",
                          graphics->data.vnc.port - 5900);
8012

8013
        if (graphics->data.vnc.websocket)
8014
            virBufferAsprintf(&opt, ",websocket=%d", graphics->data.vnc.websocket);
8015 8016 8017
        break;

    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
8018 8019 8020
        virBufferAddLit(&opt, "none");
        break;

8021 8022
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
        break;
8023
    }
8024

8025 8026 8027
    if (graphics->data.vnc.sharePolicy) {
        virBufferAsprintf(&opt, ",share=%s",
                          virDomainGraphicsVNCSharePolicyTypeToString(
8028
                              graphics->data.vnc.sharePolicy));
8029
    }
8030

8031 8032
    if (graphics->data.vnc.auth.passwd || cfg->vncPassword)
        virBufferAddLit(&opt, ",password");
8033

8034
    if (cfg->vncTLS) {
8035 8036
        qemuDomainGraphicsPrivatePtr gfxPriv = QEMU_DOMAIN_GRAPHICS_PRIVATE(graphics);
        if (gfxPriv->tlsAlias) {
8037 8038 8039 8040 8041 8042 8043 8044 8045
            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 已提交
8046 8047 8048 8049
            if (qemuBuildTLSx509CommandLine(cmd,
                                            cfg->vncTLSx509certdir,
                                            true,
                                            cfg->vncTLSx509verify,
8050
                                            secretAlias,
8051
                                            gfxPriv->tlsAlias,
J
Ján Tomko 已提交
8052 8053 8054
                                            qemuCaps) < 0)
                goto error;

8055
            virBufferAsprintf(&opt, ",tls-creds=%s", gfxPriv->tlsAlias);
8056
        } else {
J
Ján Tomko 已提交
8057 8058 8059 8060 8061 8062 8063 8064
            virBufferAddLit(&opt, ",tls");
            if (cfg->vncTLSx509verify) {
                virBufferAddLit(&opt, ",x509verify=");
                virQEMUBuildBufferEscapeComma(&opt, cfg->vncTLSx509certdir);
            } else {
                virBufferAddLit(&opt, ",x509=");
                virQEMUBuildBufferEscapeComma(&opt, cfg->vncTLSx509certdir);
            }
8065
        }
8066
    }
8067

8068 8069
    if (cfg->vncSASL) {
        virBufferAddLit(&opt, ",sasl");
8070

8071 8072
        if (cfg->vncSASLdir)
            virCommandAddEnvPair(cmd, "SASL_CONF_PATH", cfg->vncSASLdir);
8073

8074
        /* TODO: Support ACLs later */
8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086
    }

    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)
8087
        virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
8088 8089 8090 8091 8092
    else
        virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");

    return 0;

8093
 error:
8094 8095 8096 8097
    return -1;
}


8098 8099 8100 8101 8102 8103
static int
qemuBuildGraphicsSPICECommandLine(virQEMUDriverConfigPtr cfg,
                                  virCommandPtr cmd,
                                  virQEMUCapsPtr qemuCaps,
                                  virDomainGraphicsDefPtr graphics)
{
8104
    VIR_AUTOCLEAN(virBuffer) opt = VIR_BUFFER_INITIALIZER;
8105
    virDomainGraphicsListenDefPtr glisten = NULL;
8106 8107
    int port = graphics->data.spice.port;
    int tlsPort = graphics->data.spice.tlsPort;
8108
    size_t i;
8109 8110
    bool hasSecure = false;
    bool hasInsecure = false;
8111 8112 8113 8114 8115 8116 8117

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("spice graphics are not supported with this QEMU"));
        goto error;
    }

8118 8119 8120 8121
    if (!(glisten = virDomainGraphicsGetListen(graphics, 0))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("missing listen element"));
        goto error;
8122
    }
8123

8124 8125 8126
    switch (glisten->type) {
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_UNIX)) {
8127
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8128 8129
                           _("unix socket for spice graphics are not supported "
                             "with this QEMU"));
8130 8131 8132
            goto error;
        }

8133
        virBufferAddLit(&opt, "unix,addr=");
8134
        virQEMUBuildBufferEscapeComma(&opt, glisten->socket);
8135
        virBufferAddLit(&opt, ",");
8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164
        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 已提交
8165 8166 8167 8168 8169
        /* 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;
8170 8171
    case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
        break;
8172
    }
8173

8174 8175 8176 8177 8178 8179 8180 8181 8182 8183
    if (cfg->spiceSASL) {
        virBufferAddLit(&opt, "sasl,");

        if (cfg->spiceSASLdir)
            virCommandAddEnvPair(cmd, "SASL_CONF_PATH",
                                 cfg->spiceSASLdir);

        /* TODO: Support ACLs later */
    }

8184 8185 8186
    if (graphics->data.spice.mousemode) {
        switch (graphics->data.spice.mousemode) {
        case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER:
8187
            virBufferAddLit(&opt, "agent-mouse=off,");
8188 8189
            break;
        case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT:
8190
            virBufferAddLit(&opt, "agent-mouse=on,");
8191
            break;
8192
        case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT:
8193
            break;
8194 8195 8196 8197 8198
        case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST:
        default:
            virReportEnumRangeError(virDomainGraphicsSpiceMouseMode,
                                    graphics->data.spice.mousemode);
            goto error;
8199 8200 8201 8202 8203 8204 8205 8206
        }
    }

    /* 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)
8207
        virBufferAddLit(&opt, "disable-ticketing,");
8208

8209 8210 8211 8212 8213
    if (hasSecure) {
        virBufferAddLit(&opt, "x509-dir=");
        virQEMUBuildBufferEscapeComma(&opt, cfg->spiceTLSx509certdir);
        virBufferAddLit(&opt, ",");
    }
8214

8215
    switch (graphics->data.spice.defaultMode) {
8216
    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
8217 8218 8219 8220 8221 8222 8223
        if (!hasSecure) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("spice defaultMode secure requested in XML "
                             "configuration, but TLS connection is not "
                             "available"));
            goto error;
        }
8224
        virBufferAddLit(&opt, "tls-channel=default,");
8225 8226
        break;
    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
8227 8228 8229 8230 8231 8232 8233
        if (!hasInsecure) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("spice defaultMode insecure requested in XML "
                             "configuration, but plaintext connection is not "
                             "available"));
            goto error;
        }
8234
        virBufferAddLit(&opt, "plaintext-channel=default,");
8235 8236
        break;
    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
8237
    case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST:
8238 8239 8240 8241
        /* nothing */
        break;
    }

8242
    for (i = 0; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST; i++) {
8243
        switch (graphics->data.spice.channels[i]) {
8244
        case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
8245
            if (!hasSecure) {
8246
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
8247 8248 8249
                               _("spice secure channels set in XML "
                                 "configuration, but TLS connection is not "
                                 "available"));
8250 8251
                goto error;
            }
8252
            virBufferAsprintf(&opt, "tls-channel=%s,",
8253 8254
                              virDomainGraphicsSpiceChannelNameTypeToString(i));
            break;
8255

8256
        case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
8257
            if (!hasInsecure) {
8258 8259
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("spice insecure channels set in XML "
8260 8261
                                 "configuration, but plaintext connection "
                                 "is not available"));
8262 8263
                goto error;
            }
8264
            virBufferAsprintf(&opt, "plaintext-channel=%s,",
8265 8266
                              virDomainGraphicsSpiceChannelNameTypeToString(i));
            break;
8267 8268 8269

        case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
            break;
8270 8271
        }
    }
8272

8273
    if (graphics->data.spice.image)
8274
        virBufferAsprintf(&opt, "image-compression=%s,",
8275 8276
                          virDomainGraphicsSpiceImageCompressionTypeToString(graphics->data.spice.image));
    if (graphics->data.spice.jpeg)
8277
        virBufferAsprintf(&opt, "jpeg-wan-compression=%s,",
8278 8279
                          virDomainGraphicsSpiceJpegCompressionTypeToString(graphics->data.spice.jpeg));
    if (graphics->data.spice.zlib)
8280
        virBufferAsprintf(&opt, "zlib-glz-wan-compression=%s,",
8281 8282
                          virDomainGraphicsSpiceZlibCompressionTypeToString(graphics->data.spice.zlib));
    if (graphics->data.spice.playback)
8283
        virBufferAsprintf(&opt, "playback-compression=%s,",
J
Ján Tomko 已提交
8284
                          virTristateSwitchTypeToString(graphics->data.spice.playback));
8285
    if (graphics->data.spice.streaming)
8286
        virBufferAsprintf(&opt, "streaming-video=%s,",
8287
                          virDomainGraphicsSpiceStreamingModeTypeToString(graphics->data.spice.streaming));
J
Ján Tomko 已提交
8288
    if (graphics->data.spice.copypaste == VIR_TRISTATE_BOOL_NO)
8289 8290
        virBufferAddLit(&opt, "disable-copy-paste,");

J
Ján Tomko 已提交
8291
    if (graphics->data.spice.filetransfer == VIR_TRISTATE_BOOL_NO) {
8292 8293 8294 8295 8296
        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 {
8297
            virBufferAddLit(&opt, "disable-agent-file-xfer,");
8298 8299
        }
    }
8300

8301
    if (graphics->data.spice.gl == VIR_TRISTATE_BOOL_YES) {
8302 8303 8304 8305 8306 8307 8308 8309
        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 */
8310
        virBufferAsprintf(&opt, "gl=%s,",
8311
                          virTristateSwitchTypeToString(graphics->data.spice.gl));
8312 8313 8314 8315 8316 8317 8318 8319

        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;
            }

8320 8321 8322
            virBufferAddLit(&opt, "rendernode=");
            virQEMUBuildBufferEscapeComma(&opt, graphics->data.spice.rendernode);
            virBufferAddLit(&opt, ",");
8323
        }
8324 8325
    }

8326 8327 8328
    /* Turn on seamless migration unconditionally. If migration destination
     * doesn't support it, it fallbacks to previous migration algorithm silently. */
    virBufferAddLit(&opt, "seamless-migration=on,");
8329

8330 8331
    virBufferTrim(&opt, ",", -1);

8332
    virCommandAddArg(cmd, "-spice");
P
Pavel Hrdina 已提交
8333
    virCommandAddArgBuffer(cmd, &opt);
8334 8335 8336 8337 8338 8339 8340 8341 8342 8343
    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;

8344
 error:
8345 8346 8347
    return -1;
}

8348

8349 8350 8351
static int
qemuBuildGraphicsEGLHeadlessCommandLine(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
                                        virCommandPtr cmd,
8352 8353
                                        virQEMUCapsPtr qemuCaps,
                                        virDomainGraphicsDefPtr graphics)
8354
{
8355
    int ret = -1;
8356
    VIR_AUTOCLEAN(virBuffer) opt = VIR_BUFFER_INITIALIZER;
8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375

    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;

8376
    virCommandAddArg(cmd, "-display");
8377
    virCommandAddArgBuffer(cmd, &opt);
8378

8379 8380 8381
    ret = 0;
 cleanup:
    return ret;
8382 8383 8384
}


8385
static int
8386
qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg,
8387
                             virCommandPtr cmd,
8388 8389
                             virDomainDefPtr def,
                             virQEMUCapsPtr qemuCaps)
8390
{
8391
    size_t i;
8392

8393 8394
    for (i = 0; i < def->ngraphics; i++) {
        virDomainGraphicsDefPtr graphics = def->graphics[i];
8395

8396 8397 8398 8399 8400
        switch (graphics->type) {
        case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
            if (qemuBuildGraphicsSDLCommandLine(cfg, cmd,
                                                qemuCaps, graphics) < 0)
                return -1;
8401

8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413
            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;

8414 8415
            break;
        case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
8416 8417 8418
            if (qemuBuildGraphicsEGLHeadlessCommandLine(cfg, cmd,
                                                        qemuCaps, graphics) < 0)
                return -1;
8419

8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431
            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;
        }
8432
    }
8433

8434 8435
    return 0;
}
8436

M
Michele Paolino 已提交
8437
static int
8438
qemuInterfaceVhostuserConnect(virQEMUDriverPtr driver,
8439
                              virLogManagerPtr logManager,
8440
                              virSecurityManagerPtr secManager,
8441
                              virCommandPtr cmd,
M
Michele Paolino 已提交
8442 8443
                              virDomainDefPtr def,
                              virDomainNetDefPtr net,
8444
                              virQEMUCapsPtr qemuCaps,
8445
                              char **chardev)
M
Michele Paolino 已提交
8446
{
8447
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
8448
    int ret = -1;
M
Michele Paolino 已提交
8449

8450
    switch ((virDomainChrType)net->data.vhostuser->type) {
M
Michele Paolino 已提交
8451
    case VIR_DOMAIN_CHR_TYPE_UNIX:
8452 8453 8454 8455
        if (!(*chardev = qemuBuildChrChardevStr(logManager, secManager,
                                                cmd, cfg, def,
                                                net->data.vhostuser,
                                                net->info.alias, qemuCaps, 0)))
8456
            goto cleanup;
M
Michele Paolino 已提交
8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473
        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"),
8474
                       virDomainChrTypeToString(net->data.vhostuser->type));
8475
        goto cleanup;
M
Michele Paolino 已提交
8476 8477
    }

8478 8479
    ret = 0;
 cleanup:
8480
    virObjectUnref(cfg);
8481
    return ret;
M
Michele Paolino 已提交
8482 8483
}

8484
static int
8485 8486
qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
                              virLogManagerPtr logManager,
8487
                              virSecurityManagerPtr secManager,
8488
                              virCommandPtr cmd,
8489 8490 8491
                              virDomainDefPtr def,
                              virDomainNetDefPtr net,
                              virQEMUCapsPtr qemuCaps,
8492
                              unsigned int bootindex,
8493
                              virNetDevVPortProfileOp vmop,
8494
                              bool standalone,
8495
                              size_t *nnicindexes,
8496
                              int **nicindexes)
8497 8498
{
    int ret = -1;
8499 8500 8501
    VIR_AUTOFREE(char *) nic = NULL;
    VIR_AUTOFREE(char *) host = NULL;
    VIR_AUTOFREE(char *) chardev = NULL;
8502
    int *tapfd = NULL;
8503
    size_t tapfdSize = 0;
8504
    int *vhostfd = NULL;
8505
    size_t vhostfdSize = 0;
8506 8507
    char **tapfdName = NULL;
    char **vhostfdName = NULL;
8508
    virDomainNetType actualType = virDomainNetGetActualType(net);
8509
    virNetDevBandwidthPtr actualBandwidth;
8510
    bool requireNicdev = false;
8511
    size_t i;
8512

8513 8514 8515 8516

    if (!bootindex)
        bootindex = net->info.bootIndex;

8517 8518 8519
    /* Currently nothing besides TAP devices supports multiqueue. */
    if (net->driver.virtio.queues > 0 &&
        !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
8520
          actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
8521
          actualType == VIR_DOMAIN_NET_TYPE_DIRECT ||
8522 8523
          actualType == VIR_DOMAIN_NET_TYPE_ETHERNET ||
          actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER)) {
8524 8525 8526 8527 8528 8529
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Multiqueue network is not supported for: %s"),
                       virDomainNetTypeToString(actualType));
        return -1;
    }

8530
    /* and only TAP devices support nwfilter rules */
8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549
    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;
        }
8550 8551
    }

8552 8553
    if (net->backend.tap &&
        !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
8554 8555
          actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
          actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
8556 8557 8558 8559 8560 8561
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Custom tap device path is not supported for: %s"),
                       virDomainNetTypeToString(actualType));
        return -1;
    }

8562
    switch (actualType) {
8563
    case VIR_DOMAIN_NET_TYPE_NETWORK:
8564
    case VIR_DOMAIN_NET_TYPE_BRIDGE:
8565 8566 8567 8568 8569
        tapfdSize = net->driver.virtio.queues;
        if (!tapfdSize)
            tapfdSize = 1;

        if (VIR_ALLOC_N(tapfd, tapfdSize) < 0 ||
8570
            VIR_ALLOC_N(tapfdName, tapfdSize) < 0)
8571 8572
            goto cleanup;

8573 8574
        memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));

8575
        if (qemuInterfaceBridgeConnect(def, driver, net,
8576
                                       tapfd, &tapfdSize) < 0)
8577
            goto cleanup;
8578 8579 8580
        break;

    case VIR_DOMAIN_NET_TYPE_DIRECT:
8581 8582 8583 8584 8585 8586
        tapfdSize = net->driver.virtio.queues;
        if (!tapfdSize)
            tapfdSize = 1;

        if (VIR_ALLOC_N(tapfd, tapfdSize) < 0 ||
            VIR_ALLOC_N(tapfdName, tapfdSize) < 0)
8587
            goto cleanup;
8588 8589 8590

        memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));

8591 8592
        if (qemuInterfaceDirectConnect(def, driver, net,
                                       tapfd, tapfdSize, vmop) < 0)
8593
            goto cleanup;
8594 8595 8596
        break;

    case VIR_DOMAIN_NET_TYPE_ETHERNET:
8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607
        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,
8608
                                         tapfd, tapfdSize) < 0)
8609
            goto cleanup;
8610 8611 8612
        break;

    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
8613 8614 8615 8616 8617
        /* NET_TYPE_HOSTDEV devices are really hostdev devices, so
         * their commandlines are constructed with other hostdevs.
         */
        ret = 0;
        goto cleanup;
8618 8619 8620
        break;

    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638
        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;

8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649
        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;
8650 8651
    }

8652 8653 8654 8655 8656
    /* 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:
8657
    case VIR_DOMAIN_NET_TYPE_NETWORK:
8658 8659 8660 8661 8662 8663 8664 8665
    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
         */
8666 8667
        if (virQEMUDriverIsPrivileged(driver) && nicindexes && nnicindexes &&
            net->ifname) {
8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679
            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:
8680
    case VIR_DOMAIN_NET_TYPE_UDP:
8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696
    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;
    }

8697 8698 8699 8700
    /* Set bandwidth or warn if requested and not supported. */
    actualBandwidth = virDomainNetGetActualBandwidth(net);
    if (actualBandwidth) {
        if (virNetDevSupportBandwidth(actualType)) {
8701 8702
            if (virNetDevBandwidthSet(net->ifname, actualBandwidth, false,
                                      !virDomainNetTypeSharesHostView(net)) < 0)
8703 8704 8705 8706 8707 8708 8709
                goto cleanup;
        } else {
            VIR_WARN("setting bandwidth on interfaces of "
                     "type '%s' is not implemented yet",
                     virDomainNetTypeToString(actualType));
        }
    }
8710

8711 8712 8713 8714
    if (net->mtu &&
        virNetDevSetMTU(net->ifname, net->mtu) < 0)
        goto cleanup;

8715 8716 8717 8718 8719
    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) {
8720 8721
        /* Attempt to use vhost-net mode for these types of
           network device */
8722 8723 8724 8725 8726
        vhostfdSize = net->driver.virtio.queues;
        if (!vhostfdSize)
            vhostfdSize = 1;

        if (VIR_ALLOC_N(vhostfd, vhostfdSize) < 0 ||
8727
            VIR_ALLOC_N(vhostfdName, vhostfdSize))
8728 8729
            goto cleanup;

8730 8731
        memset(vhostfd, -1, vhostfdSize * sizeof(vhostfd[0]));

J
Ján Tomko 已提交
8732
        if (qemuInterfaceOpenVhostNet(def, net, vhostfd, &vhostfdSize) < 0)
8733 8734 8735
            goto cleanup;
    }

8736
    for (i = 0; i < tapfdSize; i++) {
8737 8738
        if (qemuSecuritySetTapFDLabel(driver->securityManager,
                                      def, tapfd[i]) < 0)
M
Michal Privoznik 已提交
8739
            goto cleanup;
8740
        if (virAsprintf(&tapfdName[i], "%d", tapfd[i]) < 0)
8741
            goto cleanup;
8742 8743 8744
        virCommandPassFD(cmd, tapfd[i],
                         VIR_COMMAND_PASS_FD_CLOSE_PARENT);
        tapfd[i] = -1;
8745 8746
    }

8747
    for (i = 0; i < vhostfdSize; i++) {
8748
        if (virAsprintf(&vhostfdName[i], "%d", vhostfd[i]) < 0)
8749
            goto cleanup;
8750 8751 8752
        virCommandPassFD(cmd, vhostfd[i],
                         VIR_COMMAND_PASS_FD_CLOSE_PARENT);
        vhostfd[i] = -1;
8753 8754
    }

8755 8756 8757
    if (chardev)
        virCommandAddArgList(cmd, "-chardev", chardev, NULL);

8758 8759 8760 8761 8762 8763
    if (!(host = qemuBuildHostNetStr(net, driver,
                                     tapfdName, tapfdSize,
                                     vhostfdName, vhostfdSize)))
        goto cleanup;
    virCommandAddArgList(cmd, "-netdev", host, NULL);

8764 8765
    /* Possible combinations:
     *
8766 8767 8768
     *   Old way: -netdev type=tap,id=netdev1 \
     *              -net nic,model=e1000,netdev=netdev1
     *   New way: -netdev type=tap,id=netdev1 -device e1000,id=netdev1
8769
     */
8770
    if (qemuDomainSupportsNicdev(def, net)) {
8771 8772 8773
        if (qemuCommandAddExtDevice(cmd, &net->info) < 0)
            goto cleanup;

8774
        if (!(nic = qemuBuildNicDevStr(def, net, bootindex,
8775
                                       net->driver.virtio.queues, qemuCaps)))
8776 8777
            goto cleanup;
        virCommandAddArgList(cmd, "-device", nic, NULL);
8778
    } else if (!requireNicdev) {
8779 8780 8781
        if (qemuCommandAddExtDevice(cmd, &net->info) < 0)
            goto cleanup;

8782
        if (!(nic = qemuBuildLegacyNicStr(net)))
8783 8784
            goto cleanup;
        virCommandAddArgList(cmd, "-net", nic, NULL);
8785 8786 8787 8788
    } else {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Nicdev support unavailable"));
        goto cleanup;
8789 8790 8791
    }

    ret = 0;
8792
 cleanup:
8793 8794
    if (ret < 0) {
        virErrorPtr saved_err = virSaveLastError();
8795
        virDomainConfNWFilterTeardown(net);
8796 8797 8798
        virSetError(saved_err);
        virFreeError(saved_err);
    }
8799
    for (i = 0; vhostfd && i < vhostfdSize; i++) {
8800 8801
        if (ret < 0)
            VIR_FORCE_CLOSE(vhostfd[i]);
8802 8803
        if (vhostfdName)
            VIR_FREE(vhostfdName[i]);
8804
    }
8805
    VIR_FREE(vhostfdName);
8806
    for (i = 0; tapfd && i < tapfdSize; i++) {
8807 8808 8809 8810 8811 8812
        if (ret < 0)
            VIR_FORCE_CLOSE(tapfd[i]);
        if (tapfdName)
            VIR_FREE(tapfdName[i]);
    }
    VIR_FREE(tapfdName);
8813
    VIR_FREE(vhostfd);
8814
    VIR_FREE(tapfd);
8815 8816 8817
    return ret;
}

8818 8819

/* NOTE: Not using const virDomainDef here since eventually a call is made
8820
 *       into qemuSecuritySetTapFDLabel which calls it's driver
8821 8822 8823
 *       API domainSetSecurityTapFDLabel that doesn't use the const format.
 */
static int
8824 8825
qemuBuildNetCommandLine(virQEMUDriverPtr driver,
                        virLogManagerPtr logManager,
8826
                        virSecurityManagerPtr secManager,
8827
                        virCommandPtr cmd,
8828 8829 8830 8831 8832 8833
                        virDomainDefPtr def,
                        virQEMUCapsPtr qemuCaps,
                        virNetDevVPortProfileOp vmop,
                        bool standalone,
                        size_t *nnicindexes,
                        int **nicindexes,
8834
                        unsigned int *bootHostdevNet)
8835 8836 8837
{
    size_t i;
    int last_good_net = -1;
8838
    virErrorPtr originalError = NULL;
8839

J
Ján Tomko 已提交
8840
    if (def->nnets) {
8841
        unsigned int bootNet = 0;
8842

8843 8844 8845 8846 8847
        /* 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;
8848 8849 8850 8851 8852 8853
            }
        }

        for (i = 0; i < def->nnets; i++) {
            virDomainNetDefPtr net = def->nets[i];

8854
            if (qemuBuildInterfaceCommandLine(driver, logManager, secManager, cmd, def, net,
8855
                                              qemuCaps, bootNet, vmop,
8856
                                              standalone, nnicindexes,
8857
                                              nicindexes) < 0)
8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876
                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:
8877 8878 8879
    /* free up any resources in the network driver
     * but don't overwrite the original error */
    originalError = virSaveLastError();
8880 8881
    for (i = 0; last_good_net != -1 && i <= last_good_net; i++)
        virDomainConfNWFilterTeardown(def->nets[i]);
8882 8883
    virSetError(originalError);
    virFreeError(originalError);
8884 8885 8886 8887
    return -1;
}


8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913
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;
}


8914 8915
static int
qemuBuildSmartcardCommandLine(virLogManagerPtr logManager,
8916
                              virSecurityManagerPtr secManager,
8917
                              virCommandPtr cmd,
8918
                              virQEMUDriverConfigPtr cfg,
8919
                              const virDomainDef *def,
8920 8921
                              virQEMUCapsPtr qemuCaps,
                              bool chardevStdioLogd)
8922 8923 8924
{
    size_t i;
    virDomainSmartcardDefPtr smartcard;
8925
    VIR_AUTOFREE(char *) devstr = NULL;
8926
    VIR_AUTOCLEAN(virBuffer) opt = VIR_BUFFER_INITIALIZER;
8927
    const char *database;
8928
    const char *contAlias = NULL;
8929 8930
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
8931 8932
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952

    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"));
        return -1;
    }

    switch (smartcard->type) {
    case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
8953
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_EMULATED)) {
8954 8955 8956 8957 8958 8959 8960 8961 8962 8963
            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:
8964
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_EMULATED)) {
8965 8966 8967 8968 8969 8970 8971 8972
            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++) {
8973 8974
            virBufferAsprintf(&opt, ",cert%zu=", i + 1);
            virQEMUBuildBufferEscapeComma(&opt, smartcard->data.cert.file[i]);
8975 8976 8977 8978 8979 8980
        }
        if (smartcard->data.cert.database) {
            database = smartcard->data.cert.database;
        } else {
            database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
        }
8981 8982
        virBufferAddLit(&opt, ",db=");
        virQEMUBuildBufferEscapeComma(&opt, database);
8983 8984 8985
        break;

    case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
8986
        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CCID_PASSTHRU)) {
8987 8988 8989 8990 8991 8992
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("this QEMU binary lacks smartcard "
                             "passthrough mode support"));
            return -1;
        }

8993 8994
        if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                              cmd, cfg, def,
8995
                                              smartcard->data.passthru,
8996
                                              smartcard->info.alias,
8997
                                              qemuCaps, cdevflags))) {
8998 8999
            return -1;
        }
9000
        virCommandAddArg(cmd, "-chardev");
9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012
        virCommandAddArg(cmd, 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);
        return -1;
    }
9013 9014 9015 9016 9017 9018 9019 9020 9021

    if (!(contAlias = qemuBuildSmartcardFindCCIDController(def,
                                                           smartcard))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unable to find controller for %s"),
                       smartcard->info.alias);
        return -1;
    }

9022
    virCommandAddArg(cmd, "-device");
9023
    virBufferAsprintf(&opt, ",id=%s,bus=%s.0", smartcard->info.alias, contAlias);
9024 9025 9026 9027 9028 9029
    virCommandAddArgBuffer(cmd, &opt);

    return 0;
}


9030
static char *
9031 9032 9033
qemuBuildShmemDevLegacyStr(virDomainDefPtr def,
                           virDomainShmemDefPtr shmem,
                           virQEMUCapsPtr qemuCaps)
9034
{
9035
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9036 9037 9038 9039 9040

    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("ivshmem device is not supported "
                         "with this QEMU binary"));
9041
        return NULL;
9042 9043 9044
    }

    virBufferAddLit(&buf, "ivshmem");
9045 9046
    virBufferAsprintf(&buf, ",id=%s", shmem->info.alias);

9047
    if (shmem->size)
M
Martin Kletzander 已提交
9048
        virBufferAsprintf(&buf, ",size=%llum", shmem->size >> 20);
9049 9050

    if (!shmem->server.enabled) {
9051
        virBufferAsprintf(&buf, ",shm=%s", shmem->name);
9052
    } else {
9053
        virBufferAsprintf(&buf, ",chardev=char%s", shmem->info.alias);
9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069
        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;

9070
    return virBufferContentAndReset(&buf);
9071 9072

 error:
9073 9074 9075
    return NULL;
}

9076 9077 9078 9079 9080
char *
qemuBuildShmemDevStr(virDomainDefPtr def,
                     virDomainShmemDefPtr shmem,
                     virQEMUCapsPtr qemuCaps)
{
9081
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108

    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));
    }

9109
    if (qemuBuildDeviceAddressStr(&buf, def, &shmem->info, qemuCaps) < 0)
9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121
        return NULL;

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

    return virBufferContentAndReset(&buf);
}


virJSONValuePtr
qemuBuildShmemBackendMemProps(virDomainShmemDefPtr shmem)
{
9122 9123
    VIR_AUTOFREE(char *) mem_alias = NULL;
    VIR_AUTOFREE(char *) mem_path = NULL;
9124 9125 9126 9127 9128
    virJSONValuePtr ret = NULL;

    if (virAsprintf(&mem_path, "/dev/shm/%s", shmem->name) < 0)
        return NULL;

9129
    if (virAsprintf(&mem_alias, "shmmem-%s", shmem->info.alias) < 0)
9130 9131
        goto cleanup;

9132 9133 9134 9135 9136
    qemuMonitorCreateObjectProps(&ret, "memory-backend-file", mem_alias,
                                 "s:mem-path", mem_path,
                                 "U:size", shmem->size,
                                 "b:share", true,
                                 NULL);
9137

9138
 cleanup:
9139 9140 9141 9142
    return ret;
}


9143
static int
9144
qemuBuildShmemCommandLine(virLogManagerPtr logManager,
9145
                          virSecurityManagerPtr secManager,
9146
                          virCommandPtr cmd,
9147
                          virQEMUDriverConfigPtr cfg,
9148 9149
                          virDomainDefPtr def,
                          virDomainShmemDefPtr shmem,
9150 9151
                          virQEMUCapsPtr qemuCaps,
                          bool chardevStdioLogd)
9152
{
9153
    VIR_AUTOPTR(virJSONValue) memProps = NULL;
9154
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9155
    char *devstr = NULL;
9156
    int rc;
9157 9158
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9159 9160
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9161

9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187
    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;
    }

9188 9189 9190 9191 9192
    switch ((virDomainShmemModel)shmem->model) {
    case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
        devstr = qemuBuildShmemDevLegacyStr(def, shmem, qemuCaps);
        break;

9193
    case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
9194
        if (!(memProps = qemuBuildShmemBackendMemProps(shmem)))
9195 9196
            return -1;

9197 9198 9199 9200 9201 9202 9203
        rc = virQEMUBuildObjectCommandlineFromJSON(&buf, memProps);

        if (rc < 0)
            return -1;

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

M
Marc Hartmayer 已提交
9205
        ATTRIBUTE_FALLTHROUGH;
9206
    case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL:
9207
        devstr = qemuBuildShmemDevStr(def, shmem, qemuCaps);
9208 9209
        break;

9210 9211 9212 9213 9214
    case VIR_DOMAIN_SHMEM_MODEL_LAST:
        break;
    }

    if (!devstr)
9215
        return -1;
9216 9217 9218 9219 9220 9221

    if (qemuCommandAddExtDevice(cmd, &shmem->info) < 0) {
        VIR_FREE(devstr);
        return -1;
    }

9222 9223
    virCommandAddArgList(cmd, "-device", devstr, NULL);
    VIR_FREE(devstr);
9224 9225

    if (shmem->server.enabled) {
9226 9227
        devstr = qemuBuildChrChardevStr(logManager, secManager,
                                        cmd, cfg, def,
9228
                                        &shmem->server.chr,
9229 9230
                                        shmem->info.alias, qemuCaps,
                                        cdevflags);
9231
        if (!devstr)
9232 9233
            return -1;

9234
        virCommandAddArgList(cmd, "-chardev", devstr, NULL);
9235 9236 9237 9238 9239 9240
        VIR_FREE(devstr);
    }

    return 0;
}

9241 9242 9243 9244 9245

static virQEMUCapsFlags
qemuChrSerialTargetModelToCaps(virDomainChrSerialTargetModel targetModel)
{
    switch (targetModel) {
9246 9247
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
        return QEMU_CAPS_DEVICE_ISA_SERIAL;
9248 9249 9250 9251
    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;
9252 9253
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
        return QEMU_CAPS_DEVICE_SPAPR_VTY;
9254 9255 9256 9257
    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;
9258
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
9259
        return QEMU_CAPS_DEVICE_PL011;
9260
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
9261 9262 9263 9264 9265 9266 9267 9268 9269
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
        break;
    }

    return 0;
}


9270 9271
static int
qemuBuildChrDeviceCommandLine(virCommandPtr cmd,
9272
                              const virDomainDef *def,
9273 9274 9275
                              virDomainChrDefPtr chr,
                              virQEMUCapsPtr qemuCaps)
{
9276
    VIR_AUTOFREE(char *) devstr = NULL;
9277 9278 9279 9280 9281 9282 9283 9284

    if (qemuBuildChrDeviceStr(&devstr, def, chr, qemuCaps) < 0)
        return -1;

    virCommandAddArgList(cmd, "-device", devstr, NULL);
    return 0;
}

9285

9286 9287 9288 9289
static bool
qemuChrIsPlatformDevice(const virDomainDef *def,
                        virDomainChrDefPtr chr)
{
S
Stefan Schallenberg 已提交
9290 9291 9292
    if (def->os.arch == VIR_ARCH_ARMV6L ||
        def->os.arch == VIR_ARCH_ARMV7L ||
        def->os.arch == VIR_ARCH_AARCH64) {
9293 9294

        /* pl011 (used on mach-virt) is a platform device */
9295
        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
9296 9297
            chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM &&
            chr->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011) {
9298
            return true;
9299
        }
9300 9301
    }

9302 9303 9304 9305 9306 9307 9308 9309 9310 9311
    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;
        }
    }

9312 9313 9314 9315 9316 9317 9318 9319
    /* 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;
    }

9320 9321 9322 9323
    return false;
}


9324 9325
static int
qemuBuildSerialCommandLine(virLogManagerPtr logManager,
9326
                           virSecurityManagerPtr secManager,
9327
                           virCommandPtr cmd,
9328
                           virQEMUDriverConfigPtr cfg,
9329
                           const virDomainDef *def,
9330 9331
                           virQEMUCapsPtr qemuCaps,
                           bool chardevStdioLogd)
9332 9333 9334
{
    size_t i;
    bool havespice = false;
9335 9336
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9337 9338
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9339 9340 9341 9342 9343 9344 9345 9346 9347 9348

    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];
9349
        VIR_AUTOFREE(char *) devstr = NULL;
9350

9351
        if (serial->source->type == VIR_DOMAIN_CHR_TYPE_SPICEPORT && !havespice)
9352 9353
            continue;

9354 9355
        if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                              cmd, cfg, def,
9356 9357
                                              serial->source,
                                              serial->info.alias,
9358
                                              qemuCaps, cdevflags)))
9359 9360 9361 9362
            return -1;
        virCommandAddArg(cmd, "-chardev");
        virCommandAddArg(cmd, devstr);

9363 9364
        /* If the device is not a platform device, build the devstr */
        if (!qemuChrIsPlatformDevice(def, serial)) {
9365 9366 9367
            if (qemuBuildChrDeviceCommandLine(cmd, def, serial, qemuCaps) < 0)
                return -1;
        } else {
9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378
            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;
            }

9379
            virCommandAddArg(cmd, "-serial");
9380
            virCommandAddArgFormat(cmd, "chardev:char%s", serial->info.alias);
9381 9382 9383 9384 9385 9386 9387
        }
    }

    return 0;
}


9388 9389
static int
qemuBuildParallelsCommandLine(virLogManagerPtr logManager,
9390
                              virSecurityManagerPtr secManager,
9391
                              virCommandPtr cmd,
9392
                              virQEMUDriverConfigPtr cfg,
9393
                              const virDomainDef *def,
9394 9395
                              virQEMUCapsPtr qemuCaps,
                              bool chardevStdioLogd)
9396 9397
{
    size_t i;
9398 9399
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9400 9401
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9402 9403 9404

    for (i = 0; i < def->nparallels; i++) {
        virDomainChrDefPtr parallel = def->parallels[i];
9405
        VIR_AUTOFREE(char *) devstr = NULL;
9406

9407 9408
        if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                              cmd, cfg, def,
9409 9410
                                              parallel->source,
                                              parallel->info.alias,
9411
                                              qemuCaps, cdevflags)))
9412 9413 9414
            return -1;
        virCommandAddArg(cmd, "-chardev");
        virCommandAddArg(cmd, devstr);
9415

9416 9417 9418
        if (qemuBuildChrDeviceCommandLine(cmd, def, parallel,
                                          qemuCaps) < 0)
            return -1;
9419 9420 9421 9422 9423 9424
    }

    return 0;
}


9425 9426
static int
qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
9427
                             virSecurityManagerPtr secManager,
9428
                             virCommandPtr cmd,
9429
                             virQEMUDriverConfigPtr cfg,
9430
                             const virDomainDef *def,
9431 9432
                             virQEMUCapsPtr qemuCaps,
                             bool chardevStdioLogd)
9433 9434
{
    size_t i;
9435 9436
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9437 9438
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9439 9440 9441 9442 9443 9444 9445

    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:
9446 9447
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9448
                                                  channel->source,
9449
                                                  channel->info.alias,
9450
                                                  qemuCaps, cdevflags)))
9451
                return -1;
9452
            virCommandAddArg(cmd, "-chardev");
9453 9454 9455 9456 9457 9458 9459 9460 9461 9462
            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:
9463 9464
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9465 9466
                                                  channel->source,
                                                  channel->info.alias,
9467
                                                  qemuCaps, cdevflags)))
9468 9469 9470 9471
                return -1;
            virCommandAddArg(cmd, "-chardev");
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);
9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482

            if (qemuBuildChrDeviceCommandLine(cmd, def, channel, qemuCaps) < 0)
                return -1;
            break;
        }
    }

    return 0;
}


9483 9484
static int
qemuBuildConsoleCommandLine(virLogManagerPtr logManager,
9485
                            virSecurityManagerPtr secManager,
9486
                            virCommandPtr cmd,
9487
                            virQEMUDriverConfigPtr cfg,
9488
                            const virDomainDef *def,
9489 9490
                            virQEMUCapsPtr qemuCaps,
                            bool chardevStdioLogd)
9491 9492
{
    size_t i;
9493 9494
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9495 9496
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9497 9498 9499 9500 9501 9502 9503 9504

    /* 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:
9505
            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCLPCONSOLE)) {
9506
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9507
                               _("sclpconsole is not supported in this QEMU binary"));
9508 9509 9510
                return -1;
            }

9511 9512
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9513 9514
                                                  console->source,
                                                  console->info.alias,
9515
                                                  qemuCaps, cdevflags)))
9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531
                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;
            }

9532 9533
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9534
                                                  console->source,
9535
                                                  console->info.alias,
9536
                                                  qemuCaps, cdevflags)))
9537
                return -1;
9538
            virCommandAddArg(cmd, "-chardev");
9539 9540 9541 9542 9543 9544 9545 9546
            virCommandAddArg(cmd, devstr);
            VIR_FREE(devstr);

            if (qemuBuildChrDeviceCommandLine(cmd, def, console, qemuCaps) < 0)
                return -1;
            break;

        case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO:
9547 9548
            if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                                  cmd, cfg, def,
9549
                                                  console->source,
9550
                                                  console->info.alias,
9551
                                                  qemuCaps, cdevflags)))
9552
                return -1;
9553
            virCommandAddArg(cmd, "-chardev");
9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575
            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;
}


9576 9577 9578 9579 9580 9581
char *
qemuBuildRedirdevDevStr(const virDomainDef *def,
                        virDomainRedirdevDefPtr dev,
                        virQEMUCapsPtr qemuCaps)
{
    size_t i;
9582
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 9636 9637 9638 9639
    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, "|");
        }
    }

9640
    if (dev->info.bootIndex)
9641
        virBufferAsprintf(&buf, ",bootindex=%u", dev->info.bootIndex);
9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657

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

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

    return virBufferContentAndReset(&buf);

 error:
    return NULL;
}


static int
qemuBuildRedirdevCommandLine(virLogManagerPtr logManager,
9658
                             virSecurityManagerPtr secManager,
9659
                             virCommandPtr cmd,
9660
                             virQEMUDriverConfigPtr cfg,
9661
                             const virDomainDef *def,
9662 9663
                             virQEMUCapsPtr qemuCaps,
                             bool chardevStdioLogd)
9664 9665
{
    size_t i;
9666 9667
    unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
        QEMU_BUILD_CHARDEV_UNIX_FD_PASS;
9668 9669
    if (chardevStdioLogd)
        cdevflags |= QEMU_BUILD_CHARDEV_FILE_LOGD;
9670 9671 9672 9673 9674

    for (i = 0; i < def->nredirdevs; i++) {
        virDomainRedirdevDefPtr redirdev = def->redirdevs[i];
        char *devstr;

9675 9676
        if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
                                              cmd, cfg, def,
9677
                                              redirdev->source,
9678
                                              redirdev->info.alias,
9679
                                              qemuCaps, cdevflags))) {
9680 9681 9682
            return -1;
        }

9683
        virCommandAddArg(cmd, "-chardev");
9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697
        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;
}


9698
static void
9699
qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
9700
                                 virDomainDefPtr def)
9701 9702
{
    virDomainLoaderDefPtr loader = def->os.loader;
9703
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9704 9705 9706
    int unit = 0;

    if (!loader)
9707
        return;
9708 9709 9710 9711 9712 9713 9714 9715 9716

    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 已提交
9717 9718 9719 9720 9721 9722 9723
        if (loader->secure == VIR_TRISTATE_BOOL_YES) {
            virCommandAddArgList(cmd,
                                 "-global",
                                 "driver=cfi.pflash01,property=secure,value=on",
                                 NULL);
        }

9724 9725 9726
        virBufferAddLit(&buf, "file=");
        virQEMUBuildBufferEscapeComma(&buf, loader->path);
        virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit);
9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738
        unit++;

        if (loader->readonly) {
            virBufferAsprintf(&buf, ",readonly=%s",
                              virTristateSwitchTypeToString(loader->readonly));
        }

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

        if (loader->nvram) {
            virBufferFreeAndReset(&buf);
9739 9740 9741
            virBufferAddLit(&buf, "file=");
            virQEMUBuildBufferEscapeComma(&buf, loader->nvram);
            virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit);
9742 9743 9744 9745 9746 9747

            virCommandAddArg(cmd, "-drive");
            virCommandAddArgBuffer(cmd, &buf);
        }
        break;

9748
    case VIR_DOMAIN_LOADER_TYPE_NONE:
9749 9750 9751 9752 9753 9754
    case VIR_DOMAIN_LOADER_TYPE_LAST:
        /* nada */
        break;
    }
}

J
John Ferlan 已提交
9755

J
John Ferlan 已提交
9756 9757
static char *
qemuBuildTPMDevStr(const virDomainDef *def,
9758
                   virQEMUCapsPtr qemuCaps)
J
John Ferlan 已提交
9759
{
9760
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
J
John Ferlan 已提交
9761 9762
    const virDomainTPMDef *tpm = def->tpm;
    const char *model = virDomainTPMModelTypeToString(tpm->model);
9763
    virQEMUCapsFlags flag;
J
John Ferlan 已提交
9764

9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778
    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 已提交
9779 9780 9781
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("The QEMU executable %s does not support TPM "
                       "model %s"),
9782
                       def->emulator, model);
J
John Ferlan 已提交
9783 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 9797 9798
        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:
    return NULL;
}


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
/* 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 已提交
9824 9825 9826 9827
static char *
qemuBuildTPMBackendStr(const virDomainDef *def,
                       virCommandPtr cmd,
                       int *tpmfd,
9828 9829
                       int *cancelfd,
                       char **chardev)
J
John Ferlan 已提交
9830 9831
{
    const virDomainTPMDef *tpm = def->tpm;
9832
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9833 9834 9835
    VIR_AUTOFREE(char *) cancel_path = NULL;
    VIR_AUTOFREE(char *) devset = NULL;
    VIR_AUTOFREE(char *) cancelset = NULL;
J
John Ferlan 已提交
9836 9837 9838 9839 9840
    const char *tpmdev;

    *tpmfd = -1;
    *cancelfd = -1;

9841 9842
    virBufferAsprintf(&buf, "%s", virDomainTPMBackendTypeToString(tpm->type));
    virBufferAsprintf(&buf, ",id=tpm-%s", tpm->info.alias);
J
John Ferlan 已提交
9843 9844 9845 9846 9847 9848 9849

    switch (tpm->type) {
    case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
        tpmdev = tpm->data.passthrough.source.data.file.path;
        if (!(cancel_path = virTPMCreateCancelPath(tpmdev)))
            goto error;

9850 9851
        if (qemuBuildTPMOpenBackendFDs(tpmdev, cancel_path, tpmfd, cancelfd) < 0)
            goto error;
J
John Ferlan 已提交
9852

9853 9854 9855 9856 9857 9858
        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 已提交
9859 9860

        virBufferAddLit(&buf, ",path=");
9861
        virQEMUBuildBufferEscapeComma(&buf, devset);
J
John Ferlan 已提交
9862 9863

        virBufferAddLit(&buf, ",cancel-path=");
9864
        virQEMUBuildBufferEscapeComma(&buf, cancelset);
J
John Ferlan 已提交
9865 9866

        break;
9867
    case VIR_DOMAIN_TPM_TYPE_EMULATOR:
9868 9869 9870 9871 9872 9873 9874
        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 已提交
9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888
    case VIR_DOMAIN_TPM_TYPE_LAST:
        goto error;
    }

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

    return virBufferContentAndReset(&buf);

 error:
    return NULL;
}


9889
static int
9890 9891 9892
qemuBuildTPMCommandLine(virCommandPtr cmd,
                        const virDomainDef *def,
                        virQEMUCapsPtr qemuCaps)
9893 9894
{
    char *optstr;
9895
    VIR_AUTOFREE(char *) chardev = NULL;
9896 9897 9898
    int tpmfd = -1;
    int cancelfd = -1;
    char *fdset;
9899

9900 9901 9902
    if (!def->tpm)
        return 0;

9903
    if (!(optstr = qemuBuildTPMBackendStr(def, cmd,
9904 9905
                                          &tpmfd, &cancelfd,
                                          &chardev)))
9906 9907 9908 9909 9910
        return -1;

    virCommandAddArgList(cmd, "-tpmdev", optstr, NULL);
    VIR_FREE(optstr);

9911
    if (chardev)
9912 9913
        virCommandAddArgList(cmd, "-chardev", chardev, NULL);

9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931
    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);
    }

9932
    if (!(optstr = qemuBuildTPMDevStr(def, qemuCaps)))
9933 9934 9935 9936 9937 9938 9939 9940
        return -1;

    virCommandAddArgList(cmd, "-device", optstr, NULL);
    VIR_FREE(optstr);

    return 0;
}

9941
static int
J
Ján Tomko 已提交
9942
qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
9943
                        virDomainSEVDefPtr sev)
9944
{
9945
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
9946 9947
    qemuDomainObjPrivatePtr priv = vm->privateData;
    char *path = NULL;
9948
    int ret = -1;
9949 9950 9951 9952 9953 9954 9955

    if (!sev)
        return 0;

    VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
              sev->policy, sev->cbitpos, sev->reduced_phys_bits);

9956 9957 9958
    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);
9959 9960 9961

    if (sev->dh_cert) {
        if (virAsprintf(&path, "%s/dh_cert.base64", priv->libDir) < 0)
9962
            goto cleanup;
9963
        virBufferAsprintf(&buf, ",dh-cert-file=%s", path);
9964 9965 9966 9967 9968
        VIR_FREE(path);
    }

    if (sev->session) {
        if (virAsprintf(&path, "%s/session.base64", priv->libDir) < 0)
9969
            goto cleanup;
9970
        virBufferAsprintf(&buf, ",session-file=%s", path);
9971 9972 9973
        VIR_FREE(path);
    }

9974 9975 9976 9977 9978
    virCommandAddArg(cmd, "-object");
    virCommandAddArgBuffer(cmd, &buf);
    ret = 0;
 cleanup:
    return ret;
9979
}
9980

M
Marc-André Lureau 已提交
9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002
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;
}


10003 10004 10005 10006 10007 10008 10009 10010 10011
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) {
10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 10024 10025 10026 10027 10028 10029 10030
        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;

10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053
        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 */
10054
            if (!qemuDomainIsPSeries(def)) {
10055 10056 10057 10058 10059 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 10072
                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 "
10073
                                 "ISA panic device"));
10074 10075 10076 10077 10078 10079 10080 10081 10082 10083 10084 10085 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095 10096 10097 10098 10099 10100 10101 10102 10103 10104 10105
                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;
}


10106 10107 10108 10109 10110 10111 10112 10113 10114 10115 10116 10117 10118 10119 10120
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;
}


10121
/**
10122
 * qemuBuildPRManagedManagerInfoProps:
10123
 *
10124 10125
 * Build the JSON properties for the pr-manager object corresponding to the PR
 * daemon managed by libvirt.
10126
 */
10127
virJSONValuePtr
10128
qemuBuildPRManagedManagerInfoProps(qemuDomainObjPrivatePtr priv)
10129
{
10130
    VIR_AUTOFREE(char *) path = NULL;
10131 10132
    virJSONValuePtr ret = NULL;

10133
    if (!(path = qemuDomainGetManagedPRSocketPath(priv)))
10134 10135
        return NULL;

10136 10137 10138
    ret = qemuBuildPRManagerInfoPropsInternal(qemuDomainGetManagedPRAlias(),
                                              path);

10139
    return ret;
10140 10141 10142
}


10143 10144 10145 10146 10147 10148 10149 10150 10151 10152 10153 10154 10155
/**
 * 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);
}


10156
static int
10157 10158 10159
qemuBuildManagedPRCommandLine(virCommandPtr cmd,
                              const virDomainDef *def,
                              qemuDomainObjPrivatePtr priv)
10160
{
10161
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
10162
    VIR_AUTOPTR(virJSONValue) props = NULL;
10163 10164
    int ret = -1;

10165 10166
    if (!virDomainDefHasManagedPR(def))
        return 0;
10167

10168 10169
    if (!(props = qemuBuildPRManagedManagerInfoProps(priv)))
        return -1;
10170

10171 10172
    if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0)
        goto cleanup;
10173

10174 10175
    virCommandAddArg(cmd, "-object");
    virCommandAddArgBuffer(cmd, &buf);
10176 10177 10178 10179 10180 10181 10182

    ret = 0;
 cleanup:
    return ret;
}


10183 10184 10185 10186 10187 10188 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199
/**
 * 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;
10200
    int egl_headless = 0;
10201 10202 10203 10204 10205 10206 10207 10208 10209 10210 10211 10212 10213 10214 10215 10216 10217 10218 10219 10220

    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 ||
10221 10222
            def->cputune.quota || def->cputune.global_period ||
            def->cputune.global_quota || def->cputune.emulator_period ||
10223 10224
            def->cputune.emulator_quota || def->cputune.iothread_period ||
            def->cputune.iothread_quota) {
10225 10226 10227 10228 10229 10230 10231 10232 10233 10234 10235 10236 10237 10238 10239 10240 10241
            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;
10242 10243 10244
        case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
            ++egl_headless;
            break;
10245 10246 10247 10248
        case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
        case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
        case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
            break;
10249 10250 10251
        }
    }

10252
    if (sdl > 1 || vnc > 1 || spice > 1 || egl_headless > 1) {
10253 10254
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("only 1 graphics device of each type "
10255
                         "(sdl, vnc, spice, headless) is supported"));
10256 10257 10258 10259 10260 10261 10262 10263 10264 10265 10266 10267 10268 10269 10270 10271
        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;
}


10272 10273 10274 10275 10276
static int
qemuBuildSeccompSandboxCommandLine(virCommandPtr cmd,
                                   virQEMUDriverConfigPtr cfg,
                                   virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED)
{
10277
    if (cfg->seccompSandbox == 0) {
10278 10279
        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SECCOMP_SANDBOX))
            virCommandAddArgList(cmd, "-sandbox", "off", NULL);
10280 10281 10282
        return 0;
    }

10283 10284 10285 10286 10287 10288 10289 10290 10291 10292
    /* 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 */
10293
    if (cfg->seccompSandbox > 0)
10294 10295 10296 10297 10298 10299 10300
        virCommandAddArgList(cmd, "-sandbox", "on", NULL);

    return 0;

}


J
Ján Tomko 已提交
10301
char *
10302 10303
qemuBuildVsockDevStr(virDomainDefPtr def,
                     virDomainVsockDefPtr vsock,
J
Ján Tomko 已提交
10304 10305
                     virQEMUCapsPtr qemuCaps,
                     const char *fdprefix)
10306 10307
{
    qemuDomainVsockPrivatePtr priv = (qemuDomainVsockPrivatePtr)vsock->privateData;
10308
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
10309
    char *ret = NULL;
10310

10311

10312
    if (qemuBuildVirtioDevStr(&buf, "vhost-vsock", qemuCaps,
10313
                              VIR_DOMAIN_DEVICE_VSOCK, vsock) < 0) {
10314
        goto cleanup;
10315
    }
10316

10317 10318
    virBufferAsprintf(&buf, ",id=%s", vsock->info.alias);
    virBufferAsprintf(&buf, ",guest-cid=%u", vsock->guest_cid);
J
Ján Tomko 已提交
10319
    virBufferAsprintf(&buf, ",vhostfd=%s%u", fdprefix, priv->vhostfd);
10320 10321 10322 10323 10324 10325
    if (qemuBuildDeviceAddressStr(&buf, def, &vsock->info, qemuCaps) < 0)
        goto cleanup;

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

10326 10327 10328 10329 10330 10331 10332 10333 10334 10335 10336 10337 10338 10339
    ret = virBufferContentAndReset(&buf);

 cleanup:
    return ret;
}


static int
qemuBuildVsockCommandLine(virCommandPtr cmd,
                          virDomainDefPtr def,
                          virDomainVsockDefPtr vsock,
                          virQEMUCapsPtr qemuCaps)
{
    qemuDomainVsockPrivatePtr priv = (qemuDomainVsockPrivatePtr)vsock->privateData;
10340
    VIR_AUTOFREE(char *) devstr = NULL;
10341 10342
    int ret = -1;

J
Ján Tomko 已提交
10343
    if (!(devstr = qemuBuildVsockDevStr(def, vsock, qemuCaps, "")))
10344
        goto cleanup;
10345 10346 10347

    virCommandPassFD(cmd, priv->vhostfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
    priv->vhostfd = -1;
10348 10349 10350 10351

    if (qemuCommandAddExtDevice(cmd, &vsock->info) < 0)
        goto cleanup;

10352 10353 10354 10355 10356 10357 10358 10359
    virCommandAddArgList(cmd, "-device", devstr, NULL);

    ret = 0;
 cleanup:
    return ret;
}


10360 10361 10362 10363 10364
/*
 * Constructs a argv suitable for launching qemu with config defined
 * for a given virtual machine.
 */
virCommandPtr
10365
qemuBuildCommandLine(virQEMUDriverPtr driver,
10366
                     virLogManagerPtr logManager,
10367
                     virSecurityManagerPtr secManager,
10368
                     virDomainObjPtr vm,
10369
                     const char *migrateURI,
10370
                     virDomainMomentObjPtr snapshot,
10371
                     virNetDevVPortProfileOp vmop,
10372
                     bool standalone,
10373
                     bool enableFips,
10374
                     size_t *nnicindexes,
10375
                     int **nicindexes)
10376
{
10377
    size_t i;
10378 10379
    char uuid[VIR_UUID_STRING_BUFLEN];
    virCommandPtr cmd = NULL;
10380
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
10381
    unsigned int bootHostdevNet = 0;
10382 10383 10384 10385
    qemuDomainObjPrivatePtr priv = vm->privateData;
    virDomainDefPtr def = vm->def;
    virQEMUCapsPtr qemuCaps = priv->qemuCaps;
    bool chardevStdioLogd = priv->chardevStdioLogd;
10386

J
Ján Tomko 已提交
10387
    VIR_DEBUG("driver=%p def=%p mon=%p "
10388
              "qemuCaps=%p migrateURI=%s snapshot=%p vmop=%d",
J
Ján Tomko 已提交
10389
              driver, def, priv->monConfig,
10390
              qemuCaps, migrateURI, snapshot, vmop);
10391

10392 10393
    if (qemuBuildCommandLineValidate(driver, def) < 0)
        goto error;
10394

J
John Ferlan 已提交
10395
    cmd = virCommandNew(def->emulator);
10396

10397
    virCommandAddEnvPassCommon(cmd);
10398

10399 10400 10401 10402 10403 10404 10405 10406 10407 10408 10409 10410 10411
    /* For system QEMU we want to set both HOME and all the XDG variables to
     * libDir/qemu otherwise apps QEMU links to might try to access the default
     * home dir '/' which would always result in a permission issue.
     *
     * For session QEMU, we only want to set XDG_CACHE_HOME as cache data
     * may be purged at any time and that should not affect any app. We
     * do want VMs to integrate with services in user's session so we're
     * not re-setting any other env variables
     */
    if (!driver->privileged) {
        virCommandAddEnvFormat(cmd, "XDG_CACHE_HOME=%s/%s",
                               priv->libDir, ".cache");
    } else {
10412
        virCommandAddEnvPair(cmd, "HOME", priv->libDir);
10413 10414 10415
        virCommandAddEnvXDG(cmd, priv->libDir);
    }

M
Marc-André Lureau 已提交
10416 10417
    if (qemuBuildNameCommandLine(cmd, cfg, def, qemuCaps) < 0)
        goto error;
C
Cole Robinson 已提交
10418 10419 10420 10421

    if (!standalone)
        virCommandAddArg(cmd, "-S"); /* freeze CPU */

10422
    if (qemuBuildMasterKeyCommandLine(cmd, priv) < 0)
10423 10424
        goto error;

10425
    if (qemuBuildManagedPRCommandLine(cmd, def, priv) < 0)
10426 10427
        goto error;

10428
    if (enableFips)
10429
        virCommandAddArg(cmd, "-enable-fips");
10430

10431
    if (qemuBuildMachineCommandLine(cmd, cfg, def, qemuCaps) < 0)
10432
        goto error;
10433

10434 10435
    qemuBuildTSEGCommandLine(cmd, def);

10436
    if (qemuBuildCpuCommandLine(cmd, driver, def, qemuCaps) < 0)
10437
        goto error;
10438

10439
    qemuBuildDomainLoaderCommandLine(cmd, def);
10440

10441
    if (!migrateURI && !snapshot && qemuDomainAlignMemorySizes(def) < 0)
10442
        goto error;
10443

10444
    if (qemuBuildMemCommandLine(cmd, cfg, def, qemuCaps, priv) < 0)
10445 10446
        goto error;

10447
    if (qemuBuildSmpCommandLine(cmd, def) < 0)
10448 10449
        goto error;

10450
    if (qemuBuildIOThreadCommandLine(cmd, def) < 0)
10451
        goto error;
J
John Ferlan 已提交
10452

10453
    if (virDomainNumaGetNodeCount(def->numa) &&
10454
        qemuBuildNumaArgStr(cfg, def, cmd, priv) < 0)
10455 10456
        goto error;

10457
    if (qemuBuildMemoryDeviceCommandLine(cmd, cfg, def, priv) < 0)
10458
        goto error;
10459

10460
    virUUIDFormat(def->uuid, uuid);
10461
    virCommandAddArgList(cmd, "-uuid", uuid, NULL);
10462

10463
    if (qemuBuildSmbiosCommandLine(cmd, driver, def) < 0)
10464 10465 10466
        goto error;

    if (qemuBuildVMGenIDCommandLine(cmd, def, qemuCaps) < 0)
10467
        goto error;
10468

10469 10470 10471 10472 10473 10474 10475
    /*
     * 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...
     */
10476
    if (!def->ngraphics) {
J
Ján Tomko 已提交
10477 10478
        virCommandAddArg(cmd, "-display");
        virCommandAddArg(cmd, "none");
10479

10480
        if (cfg->nogfxAllowHostAudio)
10481
            virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
10482 10483 10484 10485
        else
            virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
    }

J
Ján Tomko 已提交
10486
    /* Disable global config files and default devices */
10487
    virCommandAddArg(cmd, "-no-user-config");
J
Ján Tomko 已提交
10488
    virCommandAddArg(cmd, "-nodefaults");
10489

10490 10491
    if (qemuBuildSgaCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10492

10493
    if (qemuBuildMonitorCommandLine(logManager, secManager, cmd, cfg, def, priv) < 0)
10494
        goto error;
10495

10496 10497
    if (qemuBuildClockCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10498

10499
    if (qemuBuildPMCommandLine(cmd, def, priv) < 0)
10500
        goto error;
10501

10502
    if (qemuBuildBootCommandLine(cmd, def, qemuCaps) < 0)
10503
        goto error;
J
Ján Tomko 已提交
10504

10505 10506 10507
    if (qemuBuildIOMMUCommandLine(cmd, def, qemuCaps) < 0)
        goto error;

10508 10509
    if (qemuBuildGlobalControllerCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10510

10511
    if (qemuBuildControllersCommandLine(cmd, def, qemuCaps) < 0)
10512
        goto error;
10513

10514 10515
    if (qemuBuildHubCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10516

10517 10518 10519 10520
    if (qemuBuildControllersByTypeCommandLine(cmd, def, qemuCaps,
                                              VIR_DOMAIN_CONTROLLER_TYPE_CCID) < 0)
        goto error;

10521
    if (qemuBuildDisksCommandLine(cmd, def, qemuCaps) < 0)
10522
        goto error;
E
Eric Blake 已提交
10523

10524
    if (qemuBuildFilesystemCommandLine(cmd, def, qemuCaps) < 0)
10525
        goto error;
10526

10527
    if (qemuBuildNetCommandLine(driver, logManager, secManager, cmd, def,
10528
                                qemuCaps, vmop, standalone,
10529
                                nnicindexes, nicindexes, &bootHostdevNet) < 0)
10530
        goto error;
10531

10532
    if (qemuBuildSmartcardCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10533
                                      chardevStdioLogd) < 0)
10534
        goto error;
10535

10536
    if (qemuBuildSerialCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10537
                                   chardevStdioLogd) < 0)
10538
        goto error;
M
Martin Kletzander 已提交
10539

10540
    if (qemuBuildParallelsCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10541
                                      chardevStdioLogd) < 0)
10542
        goto error;
10543

10544
    if (qemuBuildChannelsCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10545
                                     chardevStdioLogd) < 0)
10546
        goto error;
10547

10548
    if (qemuBuildConsoleCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10549
                                    chardevStdioLogd) < 0)
10550
        goto error;
10551

10552 10553
    if (qemuBuildTPMCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10554

10555 10556
    if (qemuBuildInputCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10557

10558 10559
    if (qemuBuildGraphicsCommandLine(cfg, cmd, def, qemuCaps) < 0)
        goto error;
10560

10561 10562
    if (qemuBuildVideoCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10563

10564 10565
    if (qemuBuildSoundCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10566

10567 10568
    if (qemuBuildWatchdogCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10569

10570
    if (qemuBuildRedirdevCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10571
                                     chardevStdioLogd) < 0)
10572
        goto error;
10573

10574
    if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps, &bootHostdevNet) < 0)
10575
        goto error;
10576

10577
    if (migrateURI)
10578
        virCommandAddArgList(cmd, "-incoming", migrateURI, NULL);
10579

10580 10581
    if (qemuBuildMemballoonCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10582

10583
    if (qemuBuildRNGCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
10584
                                chardevStdioLogd) < 0)
10585
        goto error;
10586

10587 10588
    if (qemuBuildNVRAMCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
10589

M
Marc-André Lureau 已提交
10590 10591 10592
    if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
        goto error;

J
Ján Tomko 已提交
10593
    if (qemuBuildSEVCommandLine(vm, cmd, def->sev) < 0)
10594 10595
        goto error;

10596
    if (snapshot)
10597
        virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
10598 10599

    if (def->namespaceData) {
10600 10601 10602 10603 10604 10605 10606 10607
        qemuDomainXmlNsDefPtr qemuxmlns;

        qemuxmlns = def->namespaceData;
        for (i = 0; i < qemuxmlns->num_args; i++)
            virCommandAddArg(cmd, qemuxmlns->args[i]);
        for (i = 0; i < qemuxmlns->num_env; i++)
            virCommandAddEnvPair(cmd, qemuxmlns->env_name[i],
                                 NULLSTR_EMPTY(qemuxmlns->env_value[i]));
10608 10609
    }

10610 10611
    if (qemuBuildSeccompSandboxCommandLine(cmd, cfg, qemuCaps) < 0)
        goto error;
10612

10613 10614
    if (qemuBuildPanicCommandLine(cmd, def, qemuCaps) < 0)
        goto error;
H
Hu Tao 已提交
10615

10616
    for (i = 0; i < def->nshmems; i++) {
10617
        if (qemuBuildShmemCommandLine(logManager, secManager, cmd, cfg,
10618 10619
                                      def, def->shmems[i], qemuCaps,
                                      chardevStdioLogd))
10620 10621 10622
            goto error;
    }

10623 10624 10625 10626
    if (def->vsock &&
        qemuBuildVsockCommandLine(cmd, def, def->vsock, qemuCaps) < 0)
        goto error;

10627 10628
    /* In some situations, eg. VFIO passthrough, QEMU might need to lock a
     * significant amount of memory, so we need to set the limit accordingly */
10629
    virCommandSetMaxMemLock(cmd, qemuDomainGetMemLockLimitBytes(def));
10630

10631 10632 10633 10634
    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MSG_TIMESTAMP) &&
        cfg->logTimestamp)
        virCommandAddArgList(cmd, "-msg", "timestamp=on", NULL);

10635
    virObjectUnref(cfg);
10636 10637
    return cmd;

10638
 error:
10639
    virObjectUnref(cfg);
10640 10641 10642 10643
    virCommandFree(cmd);
    return NULL;
}

10644

10645 10646 10647
/* This function generates the correct '-device' string for character
 * devices of each architecture.
 */
10648 10649
static int
qemuBuildSerialChrDeviceStr(char **deviceStr,
10650
                            const virDomainDef *def,
10651
                            virDomainChrDefPtr serial,
10652
                            virQEMUCapsPtr qemuCaps)
10653
{
10654
    VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER;
10655
    virQEMUCapsFlags caps;
10656

10657
    switch ((virDomainChrSerialTargetModel) serial->targetModel) {
10658
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_ISA_SERIAL:
10659 10660 10661
    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:
10662 10663
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
10664

10665
        caps = qemuChrSerialTargetModelToCaps(serial->targetModel);
M
Michal Privoznik 已提交
10666

10667 10668 10669 10670
        if (caps && !virQEMUCapsGet(qemuCaps, caps)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("'%s' is not supported in this QEMU binary"),
                           virDomainChrSerialTargetModelTypeToString(serial->targetModel));
10671
            goto error;
G
Guannan Ren 已提交
10672
        }
10673
        break;
10674

10675
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
10676
    case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
10677 10678 10679 10680 10681 10682 10683 10684 10685
    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 已提交
10686 10687
    }

10688
    virBufferAsprintf(&buf, "%s,chardev=char%s,id=%s",
10689 10690 10691
                      virDomainChrSerialTargetModelTypeToString(serial->targetModel),
                      serial->info.alias, serial->info.alias);

10692
    if (qemuBuildDeviceAddressStr(&buf, def, &serial->info, qemuCaps) < 0)
10693 10694
        goto error;

10695
    if (virBufferCheckError(&buf) < 0)
10696 10697
        goto error;

10698
    *deviceStr = virBufferContentAndReset(&buf);
10699
    return 0;
10700

10701
 error:
10702 10703 10704 10705 10706 10707 10708 10709
    return -1;
}

static int
qemuBuildParallelChrDeviceStr(char **deviceStr,
                              virDomainChrDefPtr chr)
{
    if (virAsprintf(deviceStr, "isa-parallel,chardev=char%s,id=%s",
J
Ján Tomko 已提交
10710
                    chr->info.alias, chr->info.alias) < 0)
10711 10712
        return -1;
    return 0;
10713
}
10714

10715 10716
static int
qemuBuildChannelChrDeviceStr(char **deviceStr,
10717
                             const virDomainDef *def,
10718
                             virDomainChrDefPtr chr)
10719 10720
{
    int ret = -1;
10721
    VIR_AUTOFREE(char *) addr = NULL;
10722 10723
    int port;

10724
    switch ((virDomainChrChannelTargetType)chr->targetType) {
10725 10726 10727 10728 10729 10730 10731 10732
    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,
10733
                        "user,guestfwd=tcp:%s:%i-chardev:char%s,id=%s",
J
Ján Tomko 已提交
10734
                        addr, port, chr->info.alias, chr->info.alias) < 0)
10735 10736 10737 10738
            goto cleanup;
        break;

    case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
10739
        if (!(*deviceStr = qemuBuildVirtioSerialPortDevStr(def, chr)))
10740
            goto cleanup;
10741 10742
        break;

J
Joao Martins 已提交
10743
    case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
10744 10745 10746 10747 10748 10749
    case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE:
    case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST:
        return ret;
    }

    ret = 0;
10750
 cleanup:
10751 10752 10753 10754 10755
    return ret;
}

static int
qemuBuildConsoleChrDeviceStr(char **deviceStr,
10756
                             const virDomainDef *def,
10757
                             virDomainChrDefPtr chr)
10758 10759 10760
{
    int ret = -1;

10761
    switch ((virDomainChrConsoleTargetType)chr->targetType) {
10762 10763 10764 10765 10766 10767 10768
    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:
10769
        if (!(*deviceStr = qemuBuildVirtioSerialPortDevStr(def, chr)))
10770 10771 10772 10773
            goto cleanup;
        break;

    case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL:
10774 10775
        break;

10776 10777 10778 10779 10780 10781
    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:
10782 10783 10784 10785
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unsupported console target type %s"),
                       NULLSTR(virDomainChrConsoleTargetTypeToString(chr->targetType)));
        goto cleanup;
10786 10787 10788
    }

    ret = 0;
10789
 cleanup:
10790 10791 10792 10793 10794
    return ret;
}

int
qemuBuildChrDeviceStr(char **deviceStr,
10795
                      const virDomainDef *vmdef,
10796 10797 10798 10799 10800
                      virDomainChrDefPtr chr,
                      virQEMUCapsPtr qemuCaps)
{
    int ret = -1;

10801
    switch ((virDomainChrDeviceType)chr->deviceType) {
10802
    case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
10803
        ret = qemuBuildSerialChrDeviceStr(deviceStr, vmdef, chr, qemuCaps);
10804 10805 10806 10807 10808 10809 10810
        break;

    case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
        ret = qemuBuildParallelChrDeviceStr(deviceStr, chr);
        break;

    case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
10811
        ret = qemuBuildChannelChrDeviceStr(deviceStr, vmdef, chr);
10812 10813 10814
        break;

    case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
10815
        ret = qemuBuildConsoleChrDeviceStr(deviceStr, vmdef, chr);
10816 10817 10818 10819 10820 10821 10822 10823
        break;

    case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
        return ret;
    }

    return ret;
}
10824 10825 10826 10827 10828 10829


virJSONValuePtr
qemuBuildHotpluggableCPUProps(const virDomainVcpuDef *vcpu)
{
    qemuDomainVcpuPrivatePtr vcpupriv = QEMU_DOMAIN_VCPU_PRIVATE(vcpu);
10830
    VIR_AUTOPTR(virJSONValue) ret = NULL;
10831 10832 10833

    if (virJSONValueObjectCreate(&ret, "s:driver", vcpupriv->type,
                                       "s:id", vcpupriv->alias, NULL) < 0)
10834
        return NULL;
10835 10836 10837

    if (vcpupriv->socket_id != -1 &&
        virJSONValueObjectAdd(ret, "i:socket-id", vcpupriv->socket_id, NULL) < 0)
10838
        return NULL;
10839 10840 10841

    if (vcpupriv->core_id != -1 &&
        virJSONValueObjectAdd(ret, "i:core-id", vcpupriv->core_id, NULL) < 0)
10842
        return NULL;
10843 10844 10845

    if (vcpupriv->thread_id != -1 &&
        virJSONValueObjectAdd(ret, "i:thread-id", vcpupriv->thread_id, NULL) < 0)
10846
        return NULL;
10847

10848 10849
    if (vcpupriv->node_id != -1 &&
        virJSONValueObjectAdd(ret, "i:node-id", vcpupriv->node_id, NULL) < 0)
10850
        return NULL;
10851

10852
    VIR_RETURN_PTR(ret);
10853
}
10854 10855 10856 10857 10858 10859


/**
 * qemuBuildStorageSourceAttachPrepareDrive:
 * @disk: disk object to prepare
 * @qemuCaps: qemu capabilities object
10860
 * @driveBoot: bootable flag for disks which don't have -device part
10861 10862 10863 10864 10865 10866
 *
 * Prepare qemuBlockStorageSourceAttachDataPtr for use with the old approach
 * using -drive/drive_add. See qemuBlockStorageSourceAttachPrepareBlockdev.
 */
qemuBlockStorageSourceAttachDataPtr
qemuBuildStorageSourceAttachPrepareDrive(virDomainDiskDefPtr disk,
10867
                                         virQEMUCapsPtr qemuCaps)
10868
{
10869 10870
    VIR_AUTOPTR(qemuBlockStorageSourceAttachData) data = NULL;
    qemuBlockStorageSourceAttachDataPtr ret = NULL;
10871 10872 10873 10874

    if (VIR_ALLOC(data) < 0)
        return NULL;

10875
    if (!(data->driveCmd = qemuBuildDriveStr(disk, qemuCaps)) ||
10876
        !(data->driveAlias = qemuAliasDiskDriveFromDisk(disk)))
10877 10878
        return NULL;

10879 10880 10881
    VIR_STEAL_PTR(ret, data);

    return ret;
10882
}
10883 10884 10885 10886 10887 10888


/**
 * qemuBuildStorageSourceAttachPrepareCommon:
 * @src: storage source
 * @data: already initialized data for disk source addition
10889
 * @qemuCaps: qemu capabilities object
10890 10891 10892 10893 10894 10895
 *
 * Prepare data for configuration associated with the disk source such as
 * secrets/TLS/pr objects etc ...
 */
int
qemuBuildStorageSourceAttachPrepareCommon(virStorageSourcePtr src,
10896 10897
                                          qemuBlockStorageSourceAttachDataPtr data,
                                          virQEMUCapsPtr qemuCaps)
10898
{
10899 10900
    qemuDomainStorageSourcePrivatePtr srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);

10901 10902 10903 10904 10905
    if (src->pr &&
        !virStoragePRDefIsManaged(src->pr) &&
        !(data->prmgrProps = qemuBuildPRManagerInfoProps(src)))
        return -1;

10906 10907 10908 10909 10910 10911 10912 10913 10914 10915 10916
    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;
    }

10917 10918 10919 10920 10921
    if (src->haveTLS == VIR_TRISTATE_BOOL_YES &&
        qemuBuildTLSx509BackendProps(src->tlsCertdir, false, true, src->tlsAlias,
                                     NULL, qemuCaps, &data->tlsProps) < 0)
        return -1;

10922 10923
    return 0;
}
10924 10925 10926 10927 10928 10929 10930 10931 10932 10933 10934 10935 10936 10937 10938 10939 10940 10941 10942 10943 10944 10945 10946 10947 10948 10949 10950 10951 10952 10953 10954 10955


/**
 * qemuBuildStorageSourceChainAttachPrepareDrive:
 * @disk: disk definition
 * @qemuCaps: qemu capabilities object
 *
 * Prepares qemuBlockStorageSourceChainDataPtr for attaching @disk via -drive.
 */
qemuBlockStorageSourceChainDataPtr
qemuBuildStorageSourceChainAttachPrepareDrive(virDomainDiskDefPtr disk,
                                              virQEMUCapsPtr qemuCaps)
{
    VIR_AUTOPTR(qemuBlockStorageSourceAttachData) elem = NULL;
    VIR_AUTOPTR(qemuBlockStorageSourceChainData) data = NULL;

    if (VIR_ALLOC(data) < 0)
        return NULL;

    if (!(elem = qemuBuildStorageSourceAttachPrepareDrive(disk, qemuCaps)))
        return NULL;

    if (qemuBuildStorageSourceAttachPrepareCommon(disk->src, elem, qemuCaps) < 0)
        return NULL;

    if (VIR_APPEND_ELEMENT(data->srcdata, data->nsrcdata, elem) < 0)
        return NULL;

    VIR_RETURN_PTR(data);
}


10956 10957 10958 10959
static qemuBlockStorageSourceChainDataPtr
qemuBuildStorageSourceChainAttachPrepareBlockdevInternal(virStorageSourcePtr top,
                                                         virQEMUCapsPtr qemuCaps,
                                                         bool onlyTop)
10960 10961 10962 10963 10964 10965 10966 10967 10968
{
    VIR_AUTOPTR(qemuBlockStorageSourceAttachData) elem = NULL;
    VIR_AUTOPTR(qemuBlockStorageSourceChainData) data = NULL;
    virStorageSourcePtr n;

    if (VIR_ALLOC(data) < 0)
        return NULL;

    for (n = top; virStorageSourceIsBacking(n); n = n->backingStore) {
10969
        if (!(elem = qemuBlockStorageSourceAttachPrepareBlockdev(n, true)))
10970 10971 10972 10973 10974 10975 10976
            return NULL;

        if (qemuBuildStorageSourceAttachPrepareCommon(n, elem, qemuCaps) < 0)
            return NULL;

        if (VIR_APPEND_ELEMENT(data->srcdata, data->nsrcdata, elem) < 0)
            return NULL;
10977 10978 10979

        if (onlyTop)
            break;
10980 10981 10982 10983
    }

    VIR_RETURN_PTR(data);
}
10984 10985 10986 10987 10988 10989 10990 10991 10992 10993 10994 10995 10996 10997 10998 10999 11000 11001 11002 11003 11004 11005 11006 11007 11008 11009 11010 11011 11012 11013 11014 11015 11016 11017


/**
 * qemuBuildStorageSourceChainAttachPrepareBlockdev:
 * @top: storage source chain
 * @qemuCaps: qemu capabilities object
 *
 * Prepares qemuBlockStorageSourceChainDataPtr for attaching the chain of images
 * starting at @top via -blockdev.
 */
qemuBlockStorageSourceChainDataPtr
qemuBuildStorageSourceChainAttachPrepareBlockdev(virStorageSourcePtr top,
                                                 virQEMUCapsPtr qemuCaps)
{
    return qemuBuildStorageSourceChainAttachPrepareBlockdevInternal(top, qemuCaps,
                                                                    false);
}


/**
 * qemuBuildStorageSourceChainAttachPrepareBlockdevTop:
 * @top: storage source chain
 * @qemuCaps: qemu capabilities object
 *
 * Prepares qemuBlockStorageSourceChainDataPtr for attaching of @top image only
 * via -blockdev.
 */
qemuBlockStorageSourceChainDataPtr
qemuBuildStorageSourceChainAttachPrepareBlockdevTop(virStorageSourcePtr top,
                                                    virQEMUCapsPtr qemuCaps)
{
    return qemuBuildStorageSourceChainAttachPrepareBlockdevInternal(top, qemuCaps,
                                                                    true);
}