From: Sandesh Patel <sandesh.patel@nutanix.com> Persist the list of ARM CPU properties and their host-supported values that was probed from QEMU into the on-disk QEMU capabilities cache, so that subsequent libvirtd starts do not have to re-issue the QMP query. Signed-off-by: Sandesh Patel <sandesh.patel@nutanix.com> --- src/qemu/qemu_capabilities.c | 120 +++++++++++++++++- .../caps_11.1.0_aarch64.xml | 13 ++ 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index cb933aa630..6c78e2a2da 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -4531,6 +4531,82 @@ virQEMUCapsLoadMachines(virQEMUCapsAccel *caps, } +static int +virQEMUCapsLoadCPUProps(virQEMUCaps *qemuCaps, + xmlXPathContextPtr ctxt) +{ + g_autoptr(qemuMonitorCPUPropsInfoList) cpuProps = NULL; + g_autofree char *xpath = NULL; + g_autofree xmlNodePtr *nodes = NULL; + int nprops; + size_t i; + + VIR_XPATH_NODE_AUTORESTORE(ctxt); + + xpath = g_strdup("/qemuCaps/cpuPropertyInfo/property"); + if ((nprops = virXPathNodeSet(xpath, ctxt, &nodes)) < 0) + return -1; + + if (nprops == 0) + return 0; + + cpuProps = g_new0(qemuMonitorCPUPropsInfoList, 1); + cpuProps->nprops = nprops; + cpuProps->props = g_new0(qemuMonitorCPUPropsInfo, nprops); + + for (i = 0; i < (size_t) nprops; i++) { + qemuMonitorCPUPropsInfo *prop = cpuProps->props + i; + g_autofree char *type_str = NULL; + g_autofree xmlNodePtr *svsNodes = NULL; + int nsvs; + size_t j; + + prop->name = virXMLPropString(nodes[i], "name"); + if (!prop->name) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing property name in QEMU capabilities cache")); + return -1; + } + + if (!(type_str = virXMLPropString(nodes[i], "type"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing property type in QEMU capabilities cache for property '%1$s'"), + prop->name); + return -1; + } + if ((prop->type = qemuMonitorCPUPropertyTypeFromString(type_str)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown property type '%1$s' in QEMU capabilities cache for property '%2$s'"), + type_str, prop->name); + return -1; + } + + prop->composite = virXMLPropString(nodes[i], "composite"); + + ctxt->node = nodes[i]; + if ((nsvs = virXPathNodeSet("./supportedValue", ctxt, &svsNodes)) < 0) + return -1; + + if (nsvs == 0) + continue; + + prop->supportedValues = g_new0(char *, nsvs + 1); + for (j = 0; j < (size_t) nsvs; j++) { + prop->supportedValues[j] = virXMLPropString(svsNodes[j], "value"); + if (!prop->supportedValues[j]) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing 'value' attribute in QEMU capabilities cache for property '%1$s'"), + prop->name); + return -1; + } + } + } + + qemuCaps->kvm.cpuProps = g_steal_pointer(&cpuProps); + return 0; +} + + static int virQEMUCapsLoadAccel(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt, @@ -5089,6 +5165,9 @@ virQEMUCapsLoadCache(virArch hostArch, virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_HYPERV); virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU); + if (virQEMUCapsLoadCPUProps(qemuCaps, ctxt) < 0) + return -1; + if (virXPathBoolean("boolean(./kvmSupportsNesting)", ctxt) > 0) qemuCaps->kvmSupportsNesting = true; @@ -5182,6 +5261,45 @@ virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsAccel *caps, } +static void +virQEMUCapsFormatCPUProps(virQEMUCapsAccel *caps, virBuffer *buf) +{ + qemuMonitorCPUPropsInfoList *cpuProps = caps->cpuProps; + size_t i; + + if (!cpuProps) + return; + + virBufferAddLit(buf, "<cpuPropertyInfo>\n"); + virBufferAdjustIndent(buf, 2); + + for (i = 0; i < cpuProps->nprops; i++) { + qemuMonitorCPUPropsInfo *prop = cpuProps->props + i; + + virBufferEscapeString(buf, "<property name='%s'", prop->name); + virBufferAsprintf(buf, " type='%s'", + qemuMonitorCPUPropertyTypeToString(prop->type)); + virBufferEscapeString(buf, " composite='%s'", prop->composite); + virBufferAddLit(buf, ">\n"); + + virBufferAdjustIndent(buf, 2); + if (prop->supportedValues) { + size_t j; + + for (j = 0; prop->supportedValues[j]; j++) { + virBufferEscapeString(buf, "<supportedValue value='%s'/>\n", + prop->supportedValues[j]); + } + } + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</property>\n"); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</cpuPropertyInfo>\n"); +} + + static void virQEMUCapsFormatCPUModels(virArch arch, virQEMUCapsAccel *caps, @@ -5275,7 +5393,7 @@ virQEMUCapsFormatAccel(virQEMUCaps *qemuCaps, virQEMUCapsFormatHostCPUModelInfo(caps, buf, typeStr); virQEMUCapsFormatCPUModels(qemuCaps->arch, caps, buf, typeStr); virQEMUCapsFormatMachines(caps, buf, typeStr); - + virQEMUCapsFormatCPUProps(caps, buf); } diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml index f2340830fd..ef7b5a6ae9 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml @@ -362,6 +362,19 @@ <machine type='kvm' name='netduinoplus2' maxCpus='1' defaultCPU='cortex-m4-arm-cpu' acpi='no'/> <machine type='kvm' name='collie' maxCpus='1' defaultCPU='sa1110-arm-cpu' defaultRAMid='strongarm.sdram' acpi='no'/> <machine type='kvm' name='raspi0' maxCpus='1' defaultRAMid='ram' acpi='no'/> + <cpuPropertyInfo> + <property name='hw_prop_WRPs' type='number'> + <supportedValue value='0-3'/> + </property> + <property name='hw_prop_API' type='string' composite='pauth'> + <supportedValue value='off'/> + </property> + <property name='feat_RAS' type='string'> + <supportedValue value='0.0'/> + <supportedValue value='1.0'/> + <supportedValue value='1.1_base'/> + </property> + </cpuPropertyInfo> <hostCPU type='tcg' model='max' migratability='no'> <property name='pauth-qarma5' type='boolean' value='false'/> <property name='sve768' type='boolean' value='true'/> -- 2.43.7