qemuBuildCPUDeviceStr being introduced is responsible for creating command line argument for '-device' for given cpu device, and checking host cpu compat. Signed-off-by: Zhu Guihua <zhugh.fnst@xxxxxxxxxxxxxx> --- src/qemu/qemu_command.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_command.h | 7 ++++ 2 files changed, 95 insertions(+) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 6201e29..513b726 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6003,6 +6003,88 @@ static char *qemuBuildTPMDevStr(const virDomainDef *def, } +int +qemuBuildCPUDeviceStr(char **deviceStr, + virQEMUDriverPtr driver, + const virDomainDef *def, + virDomainCPUDefPtr dev, + virQEMUCapsPtr qemuCaps) +{ + char *model = NULL; + virCPUDefPtr host = NULL; + char *compare_msg = NULL; + virCPUCompareResult cmp; + virCapsPtr caps = NULL; + bool compareAgainstHost = ((def->virtType == VIR_DOMAIN_VIRT_KVM || + def->cpu->mode != VIR_CPU_MODE_CUSTOM) && + def->cpu->mode != VIR_CPU_MODE_HOST_PASSTHROUGH); + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_X86_64_CPU)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("%s not supported in this QEMU binary"), dev->virCPU->model); + goto error; + } + + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + goto error; + + host = caps->host.cpu; + + /* For KVM, CPU features are not emulated, so should consider host compat */ + if (compareAgainstHost) { + cmp = cpuGuestData(host, dev->virCPU, NULL, &compare_msg); + switch (cmp) { + case VIR_CPU_COMPARE_INCOMPATIBLE: + if (compare_msg) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("guest and host CPU are not compatible: %s"), + compare_msg); + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("guest CPU is not compatible with host CPU")); + } + case VIR_CPU_COMPARE_ERROR: + goto error; + + default: + break; + } + } + + if (virAsprintf(&model, "%s-x86_64-cpu", dev->virCPU->model) < 0) + goto error; + + if (virAsprintf(deviceStr, "%s,id=%s,apic-id=%d", + model, dev->info.alias, dev->apic_id) < 0) + goto error; + + return 0; + + error: + VIR_FREE(model); + VIR_FREE(compare_msg); + virObjectUnref(caps); + return -1; +} + +static int +qemuBuildCPUDeviceCommandLine(virCommandPtr cmd, + virQEMUDriverPtr driver, + const virDomainDef *def, + virDomainCPUDefPtr dev, + virQEMUCapsPtr qemuCaps) +{ + char *devstr = NULL; + + if (qemuBuildCPUDeviceStr(&devstr, driver, def, dev, qemuCaps) < 0) + return -1; + + virCommandAddArgList(cmd, "-device", devstr, NULL); + VIR_FREE(devstr); + return 0; +} + + static char *qemuBuildSmbiosBiosStr(virSysinfoDefPtr def) { virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -9922,6 +10004,12 @@ qemuBuildCommandLine(virConnectPtr conn, goto error; } + /* add cpu devices */ + for (i = 0; i < def->ncpus; i++) { + if (qemuBuildCPUDeviceCommandLine(cmd, driver, def, def->cpus[i], qemuCaps) < 0) + goto error; + } + if (def->nvram) { if (ARCH_IS_PPC64(def->os.arch) && STRPREFIX(def->os.machine, "pseries")) { diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index c63fd30..18e0dfb 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -94,6 +94,13 @@ qemuBuildChrDeviceStr(char **deviceStr, virDomainChrDefPtr chr, virQEMUCapsPtr qemuCaps); +int +qemuBuildCPUDeviceStr(char **deviceStr, + virQEMUDriverPtr driver, + const virDomainDef *def, + virDomainCPUDefPtr cpu, + virQEMUCapsPtr qemuCaps); + /* With vlan == -1, use netdev syntax, else old hostnet */ char *qemuBuildHostNetStr(virDomainNetDefPtr net, virQEMUDriverPtr driver, -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list