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(a)cn.fujitsu.com>
---
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