When qmp query-cpu-model-expansion is available probe Qemu for its view of the host model. In kvm environments this can provide a more complete view of the host model because features supported by Qemu and Kvm can be considered. Signed-off-by: Collin L. Walling <walling@xxxxxxxxxxxxxxxxxx> Signed-off-by: Jason J. Herne <jjherne@xxxxxxxxxxxxxxxxxx> # Conflicts: # tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies Signed-off-by: Jason J. Herne <jjherne@xxxxxxxxxxxxxxxxxx> --- src/qemu/qemu_capabilities.c | 185 ++++++++++++++++++++- tests/domaincapsschemadata/qemu_2.7.0.s390x.xml | 4 +- tests/domaincapsschemadata/qemu_2.8.0.s390x.xml | 17 +- .../qemucapabilitiesdata/caps_2.8.0.s390x.replies | 26 +++ tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml | 17 ++ 5 files changed, 239 insertions(+), 10 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index bff30ed..7d33b19 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -399,6 +399,8 @@ struct _virQEMUCaps { size_t ngicCapabilities; virGICCapability *gicCapabilities; + qemuMonitorCPUModelInfoPtr hostCPUModelInfo; + /* Anything below is not stored in the cache since the values are * re-computed from the other fields or external data sources every * time we probe QEMU or load the results from the cache. @@ -2163,6 +2165,10 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps) !(ret->hostCPUModel = virCPUDefCopy(qemuCaps->hostCPUModel))) goto error; + if (qemuCaps->hostCPUModelInfo && + !(ret->hostCPUModelInfo = qemuMonitorCPUModelInfoCopy(qemuCaps->hostCPUModelInfo))) + goto error; + if (VIR_ALLOC_N(ret->machineTypes, qemuCaps->nmachineTypes) < 0) goto error; ret->nmachineTypes = qemuCaps->nmachineTypes; @@ -2811,6 +2817,18 @@ virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps, return ret; } +static int +virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps, + qemuMonitorPtr mon) +{ + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION) || + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) + return 0; + + return qemuMonitorGetCPUModelExpansion(mon, "static", "host", + &qemuCaps->hostCPUModelInfo); +} + struct tpmTypeToCaps { int type; virQEMUCapsFlags caps; @@ -3020,18 +3038,62 @@ virQEMUCapsCPUFilterFeatures(const char *name, } -void -virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, - virCapsPtr caps) +static void +virQEMUCapsCopyCPUModelFromQEMU(virQEMUCapsPtr qemuCaps) { virCPUDefPtr cpu = NULL; + qemuMonitorCPUModelInfoPtr modelInfo = NULL; + size_t i; - if (!caps) - return; + if (!(modelInfo = qemuCaps->hostCPUModelInfo)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing host CPU model info from QEMU capabilities" + " for binary %s"), qemuCaps->binary); + goto error; + } - if (!virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch)) + if (VIR_ALLOC(cpu) < 0) goto error; + if (VIR_STRDUP(cpu->model, modelInfo->name) < 0 || + VIR_ALLOC_N(cpu->features, modelInfo->nprops) < 0) + goto error; + + cpu->nfeatures_max = modelInfo->nprops; + cpu->nfeatures = 0; + cpu->sockets = cpu->cores = cpu->threads = 0; + cpu->type = VIR_CPU_TYPE_GUEST; + cpu->mode = VIR_CPU_MODE_CUSTOM; + cpu->match = VIR_CPU_MATCH_EXACT; + + for (i = 0; i < modelInfo->nprops; i++) { + if (VIR_STRDUP(cpu->features[i].name, modelInfo->props[i].name) < 0) + goto error; + + if (modelInfo->props[i].supported) + cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE; + else + cpu->features[i].policy = VIR_CPU_FEATURE_DISABLE; + + cpu->nfeatures++; + } + + qemuCaps->hostCPUModel = cpu; + return; + + error: + virCPUDefFree(cpu); + qemuCaps->hostCPUModel = NULL; + virResetLastError(); +} + + +static void +virQEMUCapsCopyCPUModelFromHost(virQEMUCapsPtr qemuCaps, + virCapsPtr caps) +{ + virCPUDefPtr cpu = NULL; + if (caps->host.cpu && caps->host.cpu->model) { if (VIR_ALLOC(cpu) < 0) goto error; @@ -3055,6 +3117,98 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, virResetLastError(); } +void +virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + virCapsPtr caps) +{ + if (!caps || !virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch)) + return; + + switch (qemuCaps->arch) { + case VIR_ARCH_S390: + case VIR_ARCH_S390X: + virQEMUCapsCopyCPUModelFromQEMU(qemuCaps); + break; + default: virQEMUCapsCopyCPUModelFromHost(qemuCaps, caps); + } +} + + +static int +virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCaps, + xmlXPathContextPtr ctxt) +{ + char *str = NULL; + xmlNodePtr hostCPUNode; + xmlNodePtr *featureNodes = NULL; + xmlNodePtr oldnode = ctxt->node; + qemuMonitorCPUModelInfoPtr hostCPU = NULL; + int ret = -1; + size_t i; + int n; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION)) { + ret = 0; + goto cleanup; + } + + if (!(hostCPUNode = virXPathNode("./hostCPU", ctxt)) || + VIR_ALLOC(hostCPU) < 0) + goto cleanup; + + if ((str = virXMLPropString(hostCPUNode, "model"))) { + if (VIR_STRDUP(hostCPU->name, str) < 0) + goto cleanup; + } + + ctxt->node = hostCPUNode; + + if ((n = virXPathNodeSet("./feature", ctxt, &featureNodes)) > 0) { + if (VIR_ALLOC_N(hostCPU->props, n) < 0) + goto cleanup; + + hostCPU->nprops = n; + + for (i = 0; i < n; i++) { + if (!(str = virXMLPropString(featureNodes[i], "name"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing 'name' element for a host CPU model" + " feature in QEMU capabilities cache")); + goto cleanup; + } + if (VIR_STRDUP(hostCPU->props[i].name, str) < 0) + goto cleanup; + if (!(str = virXMLPropString(featureNodes[i], "supported"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing 'supported' element for a host CPU" + " model feature in QEMU capabilities cache")); + goto cleanup; + } + if (STREQ(str, "yes")) { + hostCPU->props[i].supported = true; + } else if (STREQ(str, "no")) { + hostCPU->props[i].supported = false; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed supported value: expected 'yes'" + " or 'no'")); + goto cleanup; + } + } + } + + qemuCaps->hostCPUModelInfo = hostCPU; + hostCPU = NULL; + ret = 0; + + cleanup: + ctxt->node = oldnode; + VIR_FREE(str); + VIR_FREE(featureNodes); + qemuMonitorCPUModelInfoFree(hostCPU); + return ret; +} + static int virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, @@ -3250,6 +3404,9 @@ virQEMUCapsLoadCache(virCapsPtr caps, } VIR_FREE(str); + if (virQEMUCapsLoadHostCPUModelInfo(qemuCaps, ctxt) < 0) + goto cleanup; + if (virQEMUCapsLoadCPUModels(qemuCaps, ctxt, VIR_DOMAIN_VIRT_KVM) < 0 || virQEMUCapsLoadCPUModels(qemuCaps, ctxt, VIR_DOMAIN_VIRT_QEMU) < 0) goto cleanup; @@ -3443,6 +3600,20 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps, virBufferAsprintf(&buf, "<arch>%s</arch>\n", virArchToString(qemuCaps->arch)); + if (qemuCaps->hostCPUModelInfo) { + virBufferAsprintf(&buf, "<hostCPU model='%s'>\n", + qemuCaps->hostCPUModelInfo->name); + virBufferAdjustIndent(&buf, 2); + for (i = 0; i < qemuCaps->hostCPUModelInfo->nprops; i++) { + virBufferAsprintf(&buf, "<feature name='%s' supported='%s'/>\n", + qemuCaps->hostCPUModelInfo->props[i].name, + qemuCaps->hostCPUModelInfo->props[i].supported ? + "yes" : "no"); + } + virBufferAdjustIndent(&buf, -2); + virBufferAddLit(&buf, "</hostCPU>\n"); + } + virQEMUCapsFormatCPUModels(qemuCaps, &buf, VIR_DOMAIN_VIRT_KVM); virQEMUCapsFormatCPUModels(qemuCaps, &buf, VIR_DOMAIN_VIRT_QEMU); @@ -4135,6 +4306,8 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps, if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_QMP_SCHEMA) && virQEMUCapsProbeQMPSchemaCapabilities(qemuCaps, mon) < 0) goto cleanup; + if (virQEMUCapsProbeQMPHostCPU(qemuCaps, mon) < 0) + goto cleanup; /* 'intel-iommu' shows up as a device since 2.2.0, but can * not be used with -device until 2.7.0. Before that it diff --git a/tests/domaincapsschemadata/qemu_2.7.0.s390x.xml b/tests/domaincapsschemadata/qemu_2.7.0.s390x.xml index 9f181d3..999e279 100644 --- a/tests/domaincapsschemadata/qemu_2.7.0.s390x.xml +++ b/tests/domaincapsschemadata/qemu_2.7.0.s390x.xml @@ -20,9 +20,7 @@ </os> <cpu> <mode name='host-passthrough' supported='yes'/> - <mode name='host-model' supported='yes'> - <model fallback='allow'></model> - </mode> + <mode name='host-model' supported='no'/> <mode name='custom' supported='no'/> </cpu> <devices> diff --git a/tests/domaincapsschemadata/qemu_2.8.0.s390x.xml b/tests/domaincapsschemadata/qemu_2.8.0.s390x.xml index 0b792b2..efe3459 100644 --- a/tests/domaincapsschemadata/qemu_2.8.0.s390x.xml +++ b/tests/domaincapsschemadata/qemu_2.8.0.s390x.xml @@ -21,7 +21,22 @@ <cpu> <mode name='host-passthrough' supported='yes'/> <mode name='host-model' supported='yes'> - <model fallback='allow'></model> + <model fallback='allow'>zEC12.2-base</model> + <feature policy='require' name='aefsi'/> + <feature policy='require' name='msa5'/> + <feature policy='require' name='msa4'/> + <feature policy='require' name='msa3'/> + <feature policy='require' name='msa2'/> + <feature policy='require' name='msa1'/> + <feature policy='require' name='sthyi'/> + <feature policy='require' name='edat'/> + <feature policy='require' name='ri'/> + <feature policy='require' name='edat2'/> + <feature policy='require' name='ipter'/> + <feature policy='require' name='esop'/> + <feature policy='require' name='cte'/> + <feature policy='require' name='te'/> + <feature policy='require' name='cmm'/> </mode> <mode name='custom' supported='yes'> <model usable='unknown'>z10EC-base</model> diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies index 3ccad4f..0405d5d 100644 --- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies +++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.replies @@ -13023,6 +13023,32 @@ { "return": { + "model": { + "name": "zEC12.2-base", + "props": { + "aefsi": true, + "msa5": true, + "msa4": true, + "msa3": true, + "msa2": true, + "msa1": true, + "sthyi": true, + "edat": true, + "ri": true, + "edat2": true, + "ipter": true, + "esop": true, + "cte": true, + "te": true, + "cmm": true + } + } + }, + "id": "libvirt-48" +} + +{ + "return": { }, "id": "libvirt-1" } diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml index 1b955cf..c4c9bf9 100644 --- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml @@ -133,6 +133,23 @@ <kvmVersion>0</kvmVersion> <package></package> <arch>s390x</arch> + <hostCPU model='zEC12.2-base'> + <feature name='aefsi' supported='yes'/> + <feature name='msa5' supported='yes'/> + <feature name='msa4' supported='yes'/> + <feature name='msa3' supported='yes'/> + <feature name='msa2' supported='yes'/> + <feature name='msa1' supported='yes'/> + <feature name='sthyi' supported='yes'/> + <feature name='edat' supported='yes'/> + <feature name='ri' supported='yes'/> + <feature name='edat2' supported='yes'/> + <feature name='ipter' supported='yes'/> + <feature name='esop' supported='yes'/> + <feature name='cte' supported='yes'/> + <feature name='te' supported='yes'/> + <feature name='cmm' supported='yes'/> + </hostCPU> <cpu type='kvm' name='z10EC-base'/> <cpu type='kvm' name='z9EC-base'/> <cpu type='kvm' name='z196.2-base'/> -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list