PowerISA allows processors to run VMs in binary compatibility ("compat") mode supporting an older version of ISA. Eg,in compatibility mode, a POWER8 host can run a "Power7" VM,conforming to PowerISA v2.06, while a POWER7 host can run a "POWER6" VM, conforming to PowerISA v2.05. QEMU has recently added support to explicitly denote a VM running in compatibility mode through commit 6d9412ea. Now, a "compat" mode VM can be run by invoking this qemu commandline on a POWER8 host: -cpu host,compat=power7 as against the older specification of "-cpu power7". However, running in compatibility mode is not identical to running natively on an older processor. Hence the virtualization stack needs to explicitly provide for a compat-mode VM. This patch allows libvirt to extend the "fallback" semantics of cpu model to describe this new mode for PowerKVM guests. Additionally with the new scheme of things, qemu doesn't provide a way to query for the supported compat models and models returned when querying with '-cpu ?' are no longer valid. Hence removing the check cpuModelIsAllowed() for now. When a user wants to request a power7 vm to run in compatibility mode on a Power8 host, this can be described in XML as follows : <cpu mode='custom' match='exact'> <model fallback='compat'>power7</model> </cpu> An alternative approach could be to leave the libvirt XML intact, and merely change the backend qemu command generation when the VM-requested cpu does not match the host processor. Looking forward to suggestions on how this can best be implemented.. Signed-off-by: Li Zhang <zhlcindy@xxxxxxxxxxxxxxxxxx> Signed-off-by: Pradipta Kr. Banerjee <bpradip@xxxxxxxxxx> Signed-off-by: Prerna Saxena <prerna@xxxxxxxxxxxxxxxxxx> diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index ebdaa19..2f41bd7 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -47,7 +47,8 @@ VIR_ENUM_IMPL(virCPUMatch, VIR_CPU_MATCH_LAST, VIR_ENUM_IMPL(virCPUFallback, VIR_CPU_FALLBACK_LAST, "allow", - "forbid") + "forbid", + "compat") VIR_ENUM_IMPL(virCPUFeaturePolicy, VIR_CPU_FEATURE_LAST, "force", diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index 8c932ce..50354f2 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -65,6 +65,7 @@ VIR_ENUM_DECL(virCPUMatch) typedef enum { VIR_CPU_FALLBACK_ALLOW, VIR_CPU_FALLBACK_FORBID, + VIR_CPU_FALLBACK_COMPAT, VIR_CPU_FALLBACK_LAST } virCPUFallback; diff --git a/src/cpu/cpu_powerpc.c b/src/cpu/cpu_powerpc.c index b220448..218c013 100644 --- a/src/cpu/cpu_powerpc.c +++ b/src/cpu/cpu_powerpc.c @@ -457,8 +457,8 @@ ppcCompare(virCPUDefPtr host, static int ppcDecode(virCPUDefPtr cpu, const virCPUData *data, - const char **models, - unsigned int nmodels, + const char **models ATTRIBUTE_UNUSED, + unsigned int nmodels ATTRIBUTE_UNUSED, const char *preferred ATTRIBUTE_UNUSED, unsigned int flags) { @@ -478,13 +478,6 @@ ppcDecode(virCPUDefPtr cpu, goto cleanup; } - if (!cpuModelIsAllowed(model->name, models, nmodels)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("CPU model %s is not supported by hypervisor"), - model->name); - goto cleanup; - } - if (VIR_STRDUP(cpu->model, model->name) < 0 || (model->vendor && VIR_STRDUP(cpu->vendor, model->vendor->name) < 0)) { goto cleanup; @@ -498,7 +491,6 @@ ppcDecode(virCPUDefPtr cpu, return ret; } - static void ppcDataFree(virCPUDataPtr data) { @@ -561,8 +553,8 @@ ppcUpdate(virCPUDefPtr guest, static virCPUDefPtr ppcBaseline(virCPUDefPtr *cpus, unsigned int ncpus, - const char **models, - unsigned int nmodels, + const char **models ATTRIBUTE_UNUSED, + unsigned int nmodels ATTRIBUTE_UNUSED, unsigned int flags) { struct ppc_map *map = NULL; @@ -582,13 +574,6 @@ ppcBaseline(virCPUDefPtr *cpus, goto error; } - if (!cpuModelIsAllowed(model->name, models, nmodels)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("CPU model %s is not supported by hypervisor"), - model->name); - goto error; - } - for (i = 0; i < ncpus; i++) { const struct ppc_vendor *vnd; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 1d5bce6..94e9b78 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6176,7 +6176,9 @@ qemuBuildCpuArgStr(virQEMUDriverPtr driver, *hasHwVirt = hasSVM > 0 ? true : false; } - if (cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) { + if ((cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) || + ((cpu->mode == VIR_CPU_MODE_HOST_MODEL) && + (def->os.arch == VIR_ARCH_PPC64))) { const char *mode = virCPUModeTypeToString(cpu->mode); if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_HOST)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -6208,7 +6210,13 @@ qemuBuildCpuArgStr(virQEMUDriverPtr driver, if (cpuDecode(guest, data, (const char **)cpus, ncpus, preferred) < 0) goto cleanup; - virBufferAdd(&buf, guest->model, -1); + if (def->os.arch == VIR_ARCH_PPC64 && + cpu->fallback == VIR_CPU_FALLBACK_COMPAT) { + virBufferAddLit(&buf, "host"); + virBufferAsprintf(&buf, ",compat=%s", guest->model); + } else + virBufferAdd(&buf, guest->model, -1); + if (guest->vendor_id) virBufferAsprintf(&buf, ",vendor=%s", guest->vendor_id); for (i = 0; i < guest->nfeatures; i++) { -- Prerna Saxena Linux Technology Centre, IBM Systems and Technology Lab, Bangalore, India -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list