[RFC PATCH 0/3] Arm CPU features with supported values
From: Sandesh Patel <sandesh.patel@nutanix.com> Hi, This RFC series adds libvirt support for ARM CPU features that are exposed by QEMU as multi-valued properties, rather than the on/off booleans we are used to from x86. Background ========== On ARM, several CPU properties can take one of a small set of values (e.g. "0.0", "1.0", "1.1_base", "off"), and the set of values supported by each property is host-specific. This cannot be expressed using libvirt's existing boolean feature model. This series depends on a pending QEMU RFC [1] that introduces non-boolean feature handling for ARM CPUs. That series also adds a new QMP command, query-arm-cpu-props-info, which reports the values the host accelerator supports for each ARM CPU property. Example reply fragment: { "name": "hw_prop_WRPs", "supported-values": ["0-3"], "type": "number" } On top of that QEMU work, this libvirt RFC wires up the end-to-end flow: probing the host, caching the probed information, exposing the values in the guest CPU XML, and passing them through to the QEMU -cpu command line. I am posting this as an RFC primarily to get maintainer feedback on the overall approach before investing in the missing pieces (in particular, value validation, which is intentionally not yet implemented). See "Open questions" below. Overview of the series ====================== 1. "Query supported ARM CPU property values from QEMU" Adds the QMP wrapper for query-arm-cpu-props-info, a new QEMU_CAPS_QUERY_ARM_CPU_PROPS_INFO capability bit, and the qemuMonitorCPUPropsInfoList data structure. The command is issued on ARM + KVM hosts and the reply is stored in the per-accelerator capabilities. 2. "Cache ARM CPU property information" Persists the probed list into the on-disk QEMU capabilities cache as <cpuPropertyInfo>, so that subsequent libvirtd restarts do not need to re-issue the QMP query. 3. "Support 'value' attribute on CPU features" Extends the guest CPU XML with an optional 'value' attribute on <feature>: <cpu mode='host-passthrough'> <feature policy='require' name='feat_RAS' value='1.0'/> <feature policy='require' name='hw_prop_API' value='off'/> <feature policy='enable' name='hw_prop_WRPs' value='2'/> </cpu> When a feature carries a non-NULL 'value', libvirt emits '<name>=<value>' on the QEMU -cpu command line; in that case the policy must be 'require' or 'force'. The existing policy-driven '=on' / '=off' path is used only for features without an explicit value. All ARM property names returned by query-arm-cpu-props-info are registered in src/cpu_map/arm_features.xml so that the guest XML parser and validator accept them. With this change, the generated QEMU command line can look like: -cpu host-passthrough,hw_prop_API=off,hw_prop_WRPs=2 Open questions ============== - Value validation: should libvirt validate the requested value against the host's supported-values list at define time, at start time, or defer entirely to QEMU? - Policy vs. value conflicts: is requiring policy='require' / 'force' whenever 'value' is set the right rule? - Caching location: is the per-accelerator QEMU capabilities cache the right place to store the probed property list, or should this live alongside the CPU model data in cpu_map? [1] https://lore.kernel.org/qemu-arm/20260605083358.1320563-1-khushit.shah@nutan... Thanks Sandesh Patel (3): Query supported ARM CPU property values from QEMU Cache ARM CPU property information Support 'value' attribute on CPU features src/conf/cpu_conf.c | 21 ++- src/conf/cpu_conf.h | 1 + src/conf/schemas/cputypes.rng | 5 + src/cpu_map/arm_features.xml | 170 ++++++++++++++++++ src/qemu/qemu_capabilities.c | 133 +++++++++++++- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 13 ++ src/qemu/qemu_monitor.c | 51 ++++++ src/qemu/qemu_monitor.h | 26 +++ src/qemu/qemu_monitor_json.c | 66 +++++++ src/qemu/qemu_monitor_json.h | 5 + .../caps_11.1.0_aarch64.replies | 69 +++++++ .../caps_11.1.0_aarch64.xml | 14 ++ tests/qemumonitorjsontest.c | 91 ++++++++++ ...arch64-cpu-passthrough.aarch64-latest.args | 2 +- ...aarch64-cpu-passthrough.aarch64-latest.xml | 6 +- .../aarch64-cpu-passthrough.xml | 6 +- tests/testutilshostcpus.h | 74 ++++---- 18 files changed, 709 insertions(+), 45 deletions(-) -- 2.43.7
From: Sandesh Patel <sandesh.patel@nutanix.com> Unlike x86 boolean CPU features, ARM CPU features are exposed by QEMU as multi-bit properties whose accepted values depend on the host; only a subset of the possible values are valid on any given host. A pending QEMU patch series [1] introduces a new QMP command, 'query-arm-cpu-props-info', which returns, for each ARM CPU property, its type and the set of values supported on the host. Add support to query feature supported values [1] https://lore.kernel.org/qemu-arm/20260605083358.1320563-1-khushit.shah@nutan... Signed-off-by: Sandesh Patel <sandesh.patel@nutanix.com> --- src/qemu/qemu_capabilities.c | 13 +++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_monitor.c | 51 +++++++++++ src/qemu/qemu_monitor.h | 26 ++++++ src/qemu/qemu_monitor_json.c | 66 ++++++++++++++ src/qemu/qemu_monitor_json.h | 5 + .../caps_11.1.0_aarch64.replies | 69 ++++++++++++++ .../caps_11.1.0_aarch64.xml | 1 + tests/qemumonitorjsontest.c | 91 +++++++++++++++++++ 9 files changed, 323 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index a28f87ad2b..cb933aa630 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -767,6 +767,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 495 */ "blockdev-mirror.target-is-zero", /* QEMU_CAPS_BLOCKDEV_MIRROR_TARGET_IS_ZERO */ + "query-arm-cpu-props-info", /* QEMU_CAPS_QUERY_ARM_CPU_PROPS_INFO */ ); @@ -812,6 +813,7 @@ struct _virQEMUCapsAccel { virQEMUCapsMachineType *machineTypes; virQEMUCapsHostCPUData hostCPU; qemuMonitorCPUDefs *cpuModels; + qemuMonitorCPUPropsInfoList *cpuProps; /* currently only populated on ARM + KVM */ }; @@ -1298,6 +1300,7 @@ struct virQEMUCapsStringFlags virQEMUCapsCommands[] = { { "blockdev-set-active", QEMU_CAPS_BLOCKDEV_SET_ACTIVE }, { "qom-list-get", QEMU_CAPS_QOM_LIST_GET }, { "query-accelerators", QEMU_CAPS_QUERY_ACCELERATORS }, + { "query-arm-cpu-props-info", QEMU_CAPS_QUERY_ARM_CPU_PROPS_INFO }, }; struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { @@ -2092,6 +2095,7 @@ virQEMUCapsAccelCopy(virQEMUCapsAccel *dst, virQEMUCapsHostCPUDataCopy(&dst->hostCPU, &src->hostCPU); dst->cpuModels = qemuMonitorCPUDefsCopy(src->cpuModels); + dst->cpuProps = qemuMonitorCPUPropsInfoListCopy(src->cpuProps); } @@ -2157,6 +2161,7 @@ virQEMUCapsAccelClear(virQEMUCapsAccel *caps) virQEMUCapsHostCPUDataClear(&caps->hostCPU); qemuMonitorCPUDefsFree(caps->cpuModels); + qemuMonitorCPUPropsInfoListFree(caps->cpuProps); } @@ -3453,6 +3458,14 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCaps *qemuCaps, } accel->hostCPU.info = g_steal_pointer(&modelInfo); + + /* Query the ARM CPU property info. Only applicable on ARM + KVM. */ + if (ARCH_IS_ARM(qemuCaps->arch) && + virQEMUCapsTypeIsAccelerated(virtType) && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_ARM_CPU_PROPS_INFO) && + qemuMonitorGetCPUPropsInfoList(mon, &accel->cpuProps) < 0) + return -1; + return 0; } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 3014f3dc5e..5bb6d5e1da 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -741,6 +741,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 495 */ QEMU_CAPS_BLOCKDEV_MIRROR_TARGET_IS_ZERO, /* 'blockdev-mirror' supports 'target-is-zero' */ + QEMU_CAPS_QUERY_ARM_CPU_PROPS_INFO, /* 'query-arm-cpu-props-info' qmp command is supported */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index baa78dd6fe..38a46cffc4 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3339,6 +3339,57 @@ qemuMonitorGetCPUModelComparison(qemuMonitor *mon, } +int +qemuMonitorGetCPUPropsInfoList(qemuMonitor *mon, + qemuMonitorCPUPropsInfoList **props_info) +{ + QEMU_CHECK_MONITOR(mon); + return qemuMonitorJSONGetCPUPropsInfoList(mon, props_info); +} + + +void +qemuMonitorCPUPropsInfoListFree(qemuMonitorCPUPropsInfoList *list) +{ + size_t i; + + if (!list) + return; + + for (i = 0; i < list->nprops; i++) { + g_free(list->props[i].name); + g_free(list->props[i].composite); + g_strfreev(list->props[i].supportedValues); + } + g_free(list->props); + g_free(list); +} + + +qemuMonitorCPUPropsInfoList * +qemuMonitorCPUPropsInfoListCopy(const qemuMonitorCPUPropsInfoList *orig) +{ + qemuMonitorCPUPropsInfoList *copy; + size_t i; + + if (!orig) + return NULL; + + copy = g_new0(qemuMonitorCPUPropsInfoList, 1); + copy->nprops = orig->nprops; + copy->props = g_new0(qemuMonitorCPUPropsInfo, orig->nprops); + + for (i = 0; i < orig->nprops; i++) { + copy->props[i].name = g_strdup(orig->props[i].name); + copy->props[i].type = orig->props[i].type; + copy->props[i].supportedValues = g_strdupv(orig->props[i].supportedValues); + copy->props[i].composite = g_strdup(orig->props[i].composite); + } + + return copy; +} + + void qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfo *model_info) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c2afb580e4..1653d63722 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1455,6 +1455,20 @@ struct _qemuMonitorCPUModelInfo { bool migratability; }; +typedef struct _qemuMonitorCPUPropsInfo qemuMonitorCPUPropsInfo; +struct _qemuMonitorCPUPropsInfo { + char *name; + qemuMonitorCPUPropertyType type; + GStrv supportedValues; + char *composite; +}; + +typedef struct _qemuMonitorCPUPropsInfoList qemuMonitorCPUPropsInfoList; +struct _qemuMonitorCPUPropsInfoList { + size_t nprops; + qemuMonitorCPUPropsInfo *props; +}; + typedef enum { QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC, QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL, @@ -1490,6 +1504,18 @@ qemuMonitorGetCPUModelComparison(qemuMonitor *mon, qemuMonitorCPUModelInfo * qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig); +int +qemuMonitorGetCPUPropsInfoList(qemuMonitor *mon, + qemuMonitorCPUPropsInfoList **props_list); + +void +qemuMonitorCPUPropsInfoListFree(qemuMonitorCPUPropsInfoList *list); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuMonitorCPUPropsInfoList, qemuMonitorCPUPropsInfoListFree); + +qemuMonitorCPUPropsInfoList * +qemuMonitorCPUPropsInfoListCopy(const qemuMonitorCPUPropsInfoList *orig); + GHashTable * qemuMonitorGetCommandLineOptions(qemuMonitor *mon); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 28f7d93834..d44a6ab270 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5727,6 +5727,72 @@ qemuMonitorJSONGetCPUModelComparison(qemuMonitor *mon, } +int +qemuMonitorJSONGetCPUPropsInfoList(qemuMonitor *mon, + qemuMonitorCPUPropsInfoList **props_list) +{ + g_autoptr(virJSONValue) cmd = NULL; + g_autoptr(virJSONValue) reply = NULL; + g_autoptr(qemuMonitorCPUPropsInfoList) props_info = NULL; + virJSONValue *data; + size_t nprops; + size_t i; + + if (!(cmd = qemuMonitorJSONMakeCommand("query-arm-cpu-props-info", NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + return -1; + + if (!(data = qemuMonitorJSONGetReply(cmd, reply, VIR_JSON_TYPE_ARRAY))) + return -1; + + nprops = virJSONValueArraySize(data); + + props_info = g_new0(qemuMonitorCPUPropsInfoList, 1); + props_info->nprops = nprops; + props_info->props = g_new0(qemuMonitorCPUPropsInfo, nprops); + + for (i = 0; i < nprops; i++) { + virJSONValue *item = virJSONValueArrayGet(data, i); + virJSONValue *sv_array; + const char *name; + const char *type_str; + int type; + + if (!(name = virJSONValueObjectGetString(item, "name"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-arm-cpu-props-info reply is missing 'name'")); + return -1; + } + + if (!(type_str = virJSONValueObjectGetString(item, "type"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("query-arm-cpu-props-info reply for '%1$s' is missing 'type'"), + name); + return -1; + } + + if ((type = qemuMonitorCPUPropertyTypeFromString(type_str)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("query-arm-cpu-props-info reply for '%1$s' has unknown type '%2$s'"), + name, type_str); + return -1; + } + + props_info->props[i].name = g_strdup(name); + props_info->props[i].type = type; + props_info->props[i].composite = g_strdup(virJSONValueObjectGetString(item, "composite")); + + if ((sv_array = virJSONValueObjectGetArray(item, "supported-values"))) + props_info->props[i].supportedValues = virJSONValueArrayToStringList(sv_array); + } + + *props_list = g_steal_pointer(&props_info); + return 0; +} + + static int qemuMonitorJSONGetCommandLineOptionsWorker(size_t pos G_GNUC_UNUSED, virJSONValue *item, diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index f4c093d717..11b07a6770 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -446,6 +446,11 @@ qemuMonitorJSONGetCPUModelComparison(qemuMonitor *mon, char **result) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +int +qemuMonitorJSONGetCPUPropsInfoList(qemuMonitor *mon, + qemuMonitorCPUPropsInfoList **props_list) + ATTRIBUTE_NONNULL(2); + GHashTable * qemuMonitorJSONGetCommandLineOptions(qemuMonitor *mon); diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.replies b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.replies index 41cd5496c6..40fd157680 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.replies +++ b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.replies @@ -24932,6 +24932,40 @@ "in-use", "auto" ] + }, + { + "name": "query-arm-cpu-props-info", + "ret-type": "[999]", + "meta-type": "command", + "arg-type": "0" + }, + { + "name": "[999]", + "element-type": "999", + "meta-type": "array" + }, + { + "name": "999", + "members": [ + { + "name": "name", + "type": "str" + }, + { + "name": "type", + "type": "str" + }, + { + "name": "supported-values", + "type": "[str]" + }, + { + "name": "composite", + "default": null, + "type": "str" + } + ], + "meta-type": "object" } ], "id": "libvirt-4" @@ -37945,6 +37979,41 @@ } } +{ + "execute": "query-arm-cpu-props-info", + "id": "libvirt-46" +} + +{ + "return": [ + { + "name": "hw_prop_WRPs", + "supported-values": [ + "0-3" + ], + "type": "number" + }, + { + "name": "hw_prop_API", + "composite": "pauth", + "supported-values": [ + "off" + ], + "type": "string" + }, + { + "name": "feat_RAS", + "supported-values": [ + "0.0", + "1.0", + "1.1_base" + ], + "type": "string" + } + ], + "id": "libvirt-46" +} + { "execute": "qmp_capabilities", "id": "libvirt-1" diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml index f7dd14a1ad..f2340830fd 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml @@ -188,6 +188,7 @@ <flag name='uefi-vars'/> <flag name='query-block-flat'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='query-arm-cpu-props-info'/> <version>11000050</version> <microcodeVersion>61700287</microcodeVersion> <package>v11.0.0-1600-g5611a9268d</package> diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index f59b97c1c3..0808c23c18 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -2682,6 +2682,86 @@ testQemuMonitorJSONqemuMonitorJSONGetCPUModelBaseline(const void *opaque) } +static int +testQemuMonitorJSONqemuMonitorJSONGetCPUPropsInfoList(const void *opaque) +{ + const testGenericData *data = opaque; + g_autoptr(qemuMonitorTest) test = NULL; + g_autoptr(qemuMonitorCPUPropsInfoList) props_list = NULL; + + if (!(test = qemuMonitorTestNewSchema(data->xmlopt, data->schema))) + return -1; + + if (qemuMonitorTestAddItem(test, "query-arm-cpu-props-info", + "{ " + " \"return\": [ " + " { " + " \"name\": \"hw_prop_API\", " + " \"supported-values\": [\"off\"], " + " \"type\": \"string\", " + " \"composite\": \"pauth\" " + " }, " + " { " + " \"name\": \"feat_RAS\", " + " \"supported-values\": [\"0.0\", \"1.0\", \"1.1_base\"], " + " \"type\": \"string\" " + " } " + " ] " + "}") < 0) + return -1; + + if (qemuMonitorJSONGetCPUPropsInfoList(qemuMonitorTestGetMonitor(test), &props_list) < 0) + return -1; + + if (props_list->nprops != 2) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "Expected 2 properties, got %zu", props_list->nprops); + return -1; + } + + if (STRNEQ(props_list->props[0].name, "hw_prop_API") || + props_list->props[0].type != QEMU_MONITOR_CPU_PROPERTY_STRING || + STRNEQ(props_list->props[1].name, "feat_RAS") || + props_list->props[1].type != QEMU_MONITOR_CPU_PROPERTY_STRING) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + "Unexpected property name or type"); + return -1; + } + + if (!props_list->props[0].supportedValues || + STRNEQ_NULLABLE(props_list->props[0].supportedValues[0], "off") || + props_list->props[0].supportedValues[1] != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + "Unexpected supportedValues for hw_prop_API"); + return -1; + } + + if (!props_list->props[1].supportedValues || + STRNEQ_NULLABLE(props_list->props[1].supportedValues[0], "0.0") || + STRNEQ_NULLABLE(props_list->props[1].supportedValues[1], "1.0") || + STRNEQ_NULLABLE(props_list->props[1].supportedValues[2], "1.1_base") || + props_list->props[1].supportedValues[3] != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + "Unexpected supportedValues for feat_RAS"); + return -1; + } + + if (STRNEQ_NULLABLE(props_list->props[0].composite, "pauth")) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + "Expected composite 'pauth' for hw_prop_API"); + return -1; + } + + if (props_list->props[1].composite != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + "Expected NULL composite for feat_RAS"); + return -1; + } + + return 0; +} + + static int testQemuMonitorJSONGetSEVInfo(const void *opaque) { @@ -2933,6 +3013,7 @@ mymain(void) testQemuMonitorJSONSimpleFuncData simpleFunc; g_autoptr(GHashTable) qapischema_x86_64 = NULL; g_autoptr(GHashTable) qapischema_s390x = NULL; + g_autoptr(GHashTable) qapischema_aarch64 = NULL; struct testQAPISchemaData qapiData; if (qemuTestDriverInit(&driver) < 0) @@ -3195,6 +3276,16 @@ mymain(void) DO_TEST(qemuMonitorJSONGetCPUModelComparison); DO_TEST(qemuMonitorJSONGetCPUModelBaseline); + if (!(qapischema_aarch64 = testQEMUSchemaLoadLatest("aarch64"))) { + VIR_TEST_VERBOSE("failed to load qapi schema for aarch64"); + ret = -1; + goto cleanup; + } + + qapiData.schema = qapischema_aarch64; + + DO_TEST(qemuMonitorJSONGetCPUPropsInfoList); + cleanup: qemuTestDriverFree(&driver); return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -- 2.43.7
On Wed, Jun 24, 2026 at 09:17:05 +0000, sandesh.patel--- via Devel wrote:
From: Sandesh Patel <sandesh.patel@nutanix.com>
Unlike x86 boolean CPU features, ARM CPU features are exposed by QEMU as multi-bit properties whose accepted values depend on the host; only a subset of the possible values are valid on any given host.
A pending QEMU patch series [1] introduces a new QMP command, 'query-arm-cpu-props-info', which returns, for each ARM CPU property, its type and the set of values supported on the host.
Add support to query feature supported values
[1] https://lore.kernel.org/qemu-arm/20260605083358.1320563-1-khushit.shah@nutan...
Signed-off-by: Sandesh Patel <sandesh.patel@nutanix.com> ---
Couple points about capability changes:
src/qemu/qemu_capabilities.c | 13 +++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_monitor.c | 51 +++++++++++ src/qemu/qemu_monitor.h | 26 ++++++ src/qemu/qemu_monitor_json.c | 66 ++++++++++++++ src/qemu/qemu_monitor_json.h | 5 + .../caps_11.1.0_aarch64.replies | 69 ++++++++++++++ .../caps_11.1.0_aarch64.xml | 1 + tests/qemumonitorjsontest.c | 91 +++++++++++++++++++ 9 files changed, 323 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index a28f87ad2b..cb933aa630 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -767,6 +767,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
/* 495 */ "blockdev-mirror.target-is-zero", /* QEMU_CAPS_BLOCKDEV_MIRROR_TARGET_IS_ZERO */ + "query-arm-cpu-props-info", /* QEMU_CAPS_QUERY_ARM_CPU_PROPS_INFO */
Generally new capability goes in a separate patch to show what it influences.
);
@@ -812,6 +813,7 @@ struct _virQEMUCapsAccel { virQEMUCapsMachineType *machineTypes; virQEMUCapsHostCPUData hostCPU; qemuMonitorCPUDefs *cpuModels; + qemuMonitorCPUPropsInfoList *cpuProps; /* currently only populated on ARM + KVM */ };
[...]
diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.replies b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.replies index 41cd5496c6..40fd157680 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.replies +++ b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.replies @@ -24932,6 +24932,40 @@ "in-use", "auto" ] + }, + { + "name": "query-arm-cpu-props-info", + "ret-type": "[999]", + "meta-type": "command", + "arg-type": "0" + }, + { + "name": "[999]", + "element-type": "999", + "meta-type": "array" + }, + { + "name": "999", + "members": [ + { + "name": "name", + "type": "str" + }, + { + "name": "type", + "type": "str" + }, + { + "name": "supported-values", + "type": "[str]" + }, + { + "name": "composite", + "default": null, + "type": "str" + } + ], + "meta-type": "object" } ], "id": "libvirt-4" @@ -37945,6 +37979,41 @@ } }
+{ + "execute": "query-arm-cpu-props-info", + "id": "libvirt-46" +} + +{ + "return": [ + { + "name": "hw_prop_WRPs", + "supported-values": [ + "0-3" + ], + "type": "number" + }, + { + "name": "hw_prop_API", + "composite": "pauth", + "supported-values": [ + "off" + ], + "type": "string" + }, + { + "name": "feat_RAS", + "supported-values": [ + "0.0", + "1.0", + "1.1_base" + ], + "type": "string" + } + ], + "id": "libvirt-46" +} + { "execute": "qmp_capabilities", "id": "libvirt-1"
Changes to this file *must* be generated from a real qemu using the dumping tool. Manual change like this are not acceptable. Also changes to the capability dumps *must* be a separate patch. The change will also only be accepted once the qemu code hits the upstream repo. I'm taking care of re-generating this one so once the corresponding code is upstream feel free to ping me to do a refresh. In case the CPU I'm generating this on (a raspberry pi 5) doesn't support what you need you can add another variant of the caps (see the README in tests/qemucapabilitiesdata). In case you generate that on a non-released qemu version you'll be also responsible to updating it once qemu-11.1 is released. Further updates will happen only when you then contribute another version of said variant once next qemu version is released.
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
From: Sandesh Patel <sandesh.patel@nutanix.com> ARM CPU features exposed by QEMU are not pure booleans: each property may take one of several QEMU-defined values (e.g. "1.0", "1.1_base", "off"). To let users request a specific value, extend the guest CPU XML <feature> element with an optional 'value' attribute: <feature policy='require' name='feat_RAS' value='1.0'/> Signed-off-by: Sandesh Patel <sandesh.patel@nutanix.com> --- src/conf/cpu_conf.c | 21 ++- src/conf/cpu_conf.h | 1 + src/conf/schemas/cputypes.rng | 5 + src/cpu_map/arm_features.xml | 170 ++++++++++++++++++ src/qemu/qemu_command.c | 13 ++ ...arch64-cpu-passthrough.aarch64-latest.args | 2 +- ...aarch64-cpu-passthrough.aarch64-latest.xml | 6 +- .../aarch64-cpu-passthrough.xml | 6 +- tests/testutilshostcpus.h | 74 ++++---- 9 files changed, 254 insertions(+), 44 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index f5a2004ee6..4326c06b48 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -101,8 +101,10 @@ virCPUDefFreeFeatures(virCPUDef *def) { size_t i; - for (i = 0; i < def->nfeatures; i++) + for (i = 0; i < def->nfeatures; i++) { VIR_FREE(def->features[i].name); + VIR_FREE(def->features[i].value); + } VIR_FREE(def->features); def->nfeatures = def->nfeatures_max = 0; @@ -184,6 +186,7 @@ virCPUDefCopyModelFilter(virCPUDef *dst, } dst->features[n].name = g_strdup(src->features[i].name); + dst->features[n].value = g_strdup(src->features[i].value); } } @@ -652,6 +655,7 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, def->features[i].name = g_steal_pointer(&name); def->features[i].policy = policy; + def->features[i].value = virXMLPropString(nodes[i], "value"); } if ((ncacheNodes = virXPathNodeSet("./cache", ctxt, &cacheNodes)) > 0) { @@ -894,12 +898,16 @@ virCPUDefFormatBuf(virBuffer *buf, feature->policy); return -1; } - virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n", + virBufferAsprintf(buf, "<feature policy='%s' name='%s'", policy, feature->name); } else { - virBufferAsprintf(buf, "<feature name='%s'/>\n", - feature->name); + virBufferAsprintf(buf, "<feature name='%s'", feature->name); } + + if (feature->value) + virBufferEscapeString(buf, " value='%s'", feature->value); + + virBufferAddLit(buf, "/>\n"); } return 0; @@ -1194,6 +1202,11 @@ virCPUDefIsEqual(virCPUDef *src, virCPUFeaturePolicyTypeToString(src->features[i].policy)); return false; } + if (STRNEQ_NULLABLE(src->features[i].value, dst->features[i].value)) { + MISMATCH(_("Target CPU feature value %1$s does not match source %2$s"), + NULLSTR(dst->features[i].value), NULLSTR(src->features[i].value)); + return false; + } } if ((src->cache && !dst->cache) || diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index 0cac1a1489..c0bab0765f 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -96,6 +96,7 @@ typedef struct _virCPUFeatureDef virCPUFeatureDef; struct _virCPUFeatureDef { char *name; int policy; /* enum virCPUFeaturePolicy */ + char *value; /* optional property value; currently only used by ARM CPU features */ }; diff --git a/src/conf/schemas/cputypes.rng b/src/conf/schemas/cputypes.rng index 8edf1d14e3..e50fb2c385 100644 --- a/src/conf/schemas/cputypes.rng +++ b/src/conf/schemas/cputypes.rng @@ -78,6 +78,11 @@ <attribute name="name"> <ref name="featureName"/> </attribute> + <optional> + <attribute name="value"> + <text/> + </attribute> + </optional> <empty/> </element> </define> diff --git a/src/cpu_map/arm_features.xml b/src/cpu_map/arm_features.xml index fc80a3b5bd..8df9ee321f 100644 --- a/src/cpu_map/arm_features.xml +++ b/src/cpu_map/arm_features.xml @@ -22,4 +22,174 @@ <!-- Pointer authentication --> <feature name='pauth'/> + <!-- + ARM CPU properties exposed by QEMU. Names match the QMP property + names returned by query-arm-cpu-props-info + --> + <feature name='feat_AES'/> + <feature name='feat_SHA1'/> + <feature name='feat_SHA2'/> + <feature name='feat_CRC32'/> + <feature name='feat_ATOMIC'/> + <feature name='feat_RDM'/> + <feature name='feat_SHA3'/> + <feature name='feat_SM3'/> + <feature name='feat_SM4'/> + <feature name='feat_DP'/> + <feature name='feat_FHM'/> + <feature name='feat_TS'/> + <feature name='feat_TLB'/> + <feature name='feat_RNDR'/> + <feature name='feat_DPB'/> + <feature name='hw_prop_APA'/> + <feature name='hw_prop_API'/> + <feature name='feat_JSCVT'/> + <feature name='feat_FCMA'/> + <feature name='feat_LRCPC'/> + <feature name='hw_prop_GPA'/> + <feature name='hw_prop_GPI'/> + <feature name='feat_FRINTTS'/> + <feature name='feat_SB'/> + <feature name='feat_SPECRES'/> + <feature name='feat_BF16'/> + <feature name='feat_DGH'/> + <feature name='feat_I8MM'/> + <feature name='feat_XS'/> + <feature name='feat_LS64'/> + <feature name='feat_WFXT'/> + <feature name='feat_RPRES'/> + <feature name='hw_prop_GPA3'/> + <feature name='hw_prop_APA3'/> + <feature name='feat_MOPS'/> + <feature name='feat_BC'/> + <feature name='feat_CLRBHB'/> + <feature name='feat_RPRFM'/> + <feature name='feat_CSSC'/> + <feature name='feat_LUT'/> + <feature name='feat_FAMINMAX'/> + <feature name='feat_LSFE'/> + <feature name='feat_FPRCVT'/> + <feature name='el0_mode'/> + <feature name='el1_mode'/> + <feature name='el2_mode'/> + <feature name='el3_mode'/> + <feature name='feat_FP'/> + <feature name='feat_AdvSIMD'/> + <feature name='feat_SVE'/> + <feature name='feat_SEL2'/> + <feature name='feat_AMU'/> + <feature name='feat_DIT'/> + <feature name='feat_CSV3'/> + <feature name='feat_BT'/> + <feature name='feat_SSBS'/> + <feature name='feat_MTE'/> + <feature name='feat_NMI'/> + <feature name='feat_MTE_FRAC'/> + <feature name='feat_GCS'/> + <feature name='feat_DF2'/> + <feature name='feat_MTESTOREONLY'/> + <feature name='feat_MTEFAR'/> + <feature name='feat_FPMR'/> + <feature name='hw_prop_PARANGE'/> + <feature name='hw_prop_ASIDBITS'/> + <feature name='feat_BIGEND'/> + <feature name='feat_SNSMEM'/> + <feature name='feat_BIGENDEL0'/> + <feature name='hw_prop_TGRAN16'/> + <feature name='hw_prop_TGRAN64'/> + <feature name='hw_prop_TGRAN4'/> + <feature name='hw_prop_TGRAN16_2'/> + <feature name='hw_prop_TGRAN64_2'/> + <feature name='hw_prop_TGRAN4_2'/> + <feature name='feat_EXS'/> + <feature name='feat_FGT'/> + <feature name='feat_ECV'/> + <feature name='feat_HAFDBS'/> + <feature name='hw_prop_VMIDBITS'/> + <feature name='feat_VH'/> + <feature name='feat_HPDS'/> + <feature name='feat_LO'/> + <feature name='feat_PAN'/> + <feature name='feat_SpecSEI'/> + <feature name='feat_XNX'/> + <feature name='feat_TWED'/> + <feature name='feat_ETS'/> + <feature name='feat_HCX'/> + <feature name='feat_AFP'/> + <feature name='feat_TIDCP1'/> + <feature name='feat_ECBHB'/> + <feature name='feat_CNP'/> + <feature name='feat_UAO'/> + <feature name='feat_LSM'/> + <feature name='feat_IESB'/> + <feature name='hw_prop_VARANGE'/> + <feature name='hw_prop_CCIDX'/> + <feature name='hw_prop_ST'/> + <feature name='feat_AT'/> + <feature name='hw_prop_IDS'/> + <feature name='hw_prop_FWB'/> + <feature name='feat_TTL'/> + <feature name='feat_BBM'/> + <feature name='feat_EVT'/> + <feature name='feat_E0PD'/> + <feature name='feat_TCRX'/> + <feature name='feat_SCTLRX'/> + <feature name='feat_S1PIE'/> + <feature name='feat_S1POE'/> + <feature name='feat_E2H0'/> + <feature name='feat_DBG'/> + <feature name='feat_PMU'/> + <feature name='hw_prop_BRPS'/> + <feature name='hw_prop_WRPs'/> + <feature name='hw_prop_CTX_CMPs'/> + <feature name='hw_prop_PMSVer'/> + <feature name='feat_DoubleLock'/> + <feature name='hw_prop_SVEVer'/> + <feature name='feat_SVE_AES'/> + <feature name='feat_SVE_ELTPERM'/> + <feature name='feat_SVE_BITPERM'/> + <feature name='feat_SVE_BFLOAT16'/> + <feature name='feat_SVE_B16B16'/> + <feature name='feat_SVE_SHA3'/> + <feature name='feat_SVE_SM4'/> + <feature name='feat_SVE_I8MM'/> + <feature name='feat_SVE_F16MM'/> + <feature name='feat_SVE_F32MM'/> + <feature name='feat_SVE_F64MM'/> + <feature name='feat_F8E5M2'/> + <feature name='feat_F8E4M3'/> + <feature name='feat_F8MM4'/> + <feature name='feat_F8MM8'/> + <feature name='feat_F8DP2'/> + <feature name='feat_F8DP4'/> + <feature name='feat_F8FMA'/> + <feature name='feat_F8CVT'/> + <feature name='hw_prop_IMInline'/> + <feature name='hw_prop_L1IP'/> + <feature name='hw_prop_DMInline'/> + <feature name='hw_prop_ERG'/> + <feature name='hw_prop_CWG'/> + <feature name='hw_prop_IDC'/> + <feature name='hw_prop_DIC'/> + <feature name='hw_prop_BS'/> + <feature name='hw_prop_DZP'/> + <feature name='cpu_revision'/> + <feature name='cpu_partnum'/> + <feature name='cpu_architecture'/> + <feature name='cpu_variant'/> + <feature name='cpu_implementer'/> + <feature name='cpu_revidr'/> + <feature name='cpu_aidr'/> + <feature name='cache_lvl1_type'/> + <feature name='cache_lvl2_type'/> + <feature name='cache_lvl3_type'/> + <feature name='cache_louis'/> + <feature name='cache_loc'/> + <feature name='cache_louu'/> + <feature name='cache_icb_type'/> + <feature name='cache_ttypen'/> + <feature name='feat_CSV2'/> + <feature name='feat_MPAM'/> + <feature name='feat_RAS'/> + <feature name='feat_NV'/> </cpus> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index e726dc661c..792f9d5748 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6516,6 +6516,19 @@ qemuBuildCpuModelArgStr(virQEMUDriver *driver, const char *featname = virQEMUCapsCPUFeatureToQEMU(def->os.arch, cpu->features[i].name); + /* If an explicit value is provided, policy must be "require". */ + if (cpu->features[i].value) { + if (cpu->features[i].policy != VIR_CPU_FEATURE_FORCE + && cpu->features[i].policy != VIR_CPU_FEATURE_REQUIRE) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Feature %1$s with explicit values must have policy 'force' or 'require'"), + cpu->features[i].name); + return -1; + } + virBufferAsprintf(buf, ",%s=%s", featname, cpu->features[i].value); + continue; + } + switch ((virCPUFeaturePolicy) cpu->features[i].policy) { case VIR_CPU_FEATURE_FORCE: case VIR_CPU_FEATURE_REQUIRE: diff --git a/tests/qemuxmlconfdata/aarch64-cpu-passthrough.aarch64-latest.args b/tests/qemuxmlconfdata/aarch64-cpu-passthrough.aarch64-latest.args index 65dba77871..10adb0bcef 100644 --- a/tests/qemuxmlconfdata/aarch64-cpu-passthrough.aarch64-latest.args +++ b/tests/qemuxmlconfdata/aarch64-cpu-passthrough.aarch64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-aarch64test/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-aarch64test/master-key.aes"}' \ -machine virt,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=off \ -accel kvm \ --cpu host \ +-cpu host,feat_RAS=1.0,hw_prop_API=off,hw_prop_WRPs=2 \ -m size=1048576k \ -object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/aarch64-cpu-passthrough.aarch64-latest.xml b/tests/qemuxmlconfdata/aarch64-cpu-passthrough.aarch64-latest.xml index cf59cf9fef..8ef4e07b03 100644 --- a/tests/qemuxmlconfdata/aarch64-cpu-passthrough.aarch64-latest.xml +++ b/tests/qemuxmlconfdata/aarch64-cpu-passthrough.aarch64-latest.xml @@ -13,7 +13,11 @@ <pae/> <gic version='2'/> </features> - <cpu mode='host-passthrough' check='none'/> + <cpu mode='host-passthrough' check='none'> + <feature policy='require' name='feat_RAS' value='1.0'/> + <feature policy='require' name='hw_prop_API' value='off'/> + <feature policy='require' name='hw_prop_WRPs' value='2'/> + </cpu> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> diff --git a/tests/qemuxmlconfdata/aarch64-cpu-passthrough.xml b/tests/qemuxmlconfdata/aarch64-cpu-passthrough.xml index 0dda095049..b3f77b273e 100644 --- a/tests/qemuxmlconfdata/aarch64-cpu-passthrough.xml +++ b/tests/qemuxmlconfdata/aarch64-cpu-passthrough.xml @@ -11,7 +11,11 @@ <apic/> <pae/> </features> - <cpu mode='host-passthrough'/> + <cpu mode='host-passthrough'> + <feature policy='require' name='feat_RAS' value='1.0'/> + <feature policy='require' name='hw_prop_API' value='off'/> + <feature policy='require' name='hw_prop_WRPs' value='2'/> + </cpu> <clock offset="utc"/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> diff --git a/tests/testutilshostcpus.h b/tests/testutilshostcpus.h index 36118d6acb..c808fc8ce0 100644 --- a/tests/testutilshostcpus.h +++ b/tests/testutilshostcpus.h @@ -21,19 +21,19 @@ #include "util/virarch.h" static virCPUFeatureDef cpuDefaultFeatures[] = { - { (char *) "ds", -1 }, - { (char *) "acpi", -1 }, - { (char *) "ss", -1 }, - { (char *) "ht", -1 }, - { (char *) "tm", -1 }, - { (char *) "pbe", -1 }, - { (char *) "ds_cpl", -1 }, - { (char *) "vmx", -1 }, - { (char *) "est", -1 }, - { (char *) "tm2", -1 }, - { (char *) "cx16", -1 }, - { (char *) "xtpr", -1 }, - { (char *) "lahf_lm", -1 }, + { (char *) "ds", -1, NULL}, + { (char *) "acpi", -1, NULL}, + { (char *) "ss", -1, NULL}, + { (char *) "ht", -1, NULL}, + { (char *) "tm", -1, NULL}, + { (char *) "pbe", -1, NULL}, + { (char *) "ds_cpl", -1, NULL}, + { (char *) "vmx", -1, NULL}, + { (char *) "est", -1, NULL}, + { (char *) "tm2", -1, NULL}, + { (char *) "cx16", -1, NULL}, + { (char *) "xtpr", -1, NULL}, + { (char *) "lahf_lm", -1, NULL}, }; static virCPUDef cpuDefaultData = { .type = VIR_CPU_TYPE_HOST, @@ -49,30 +49,30 @@ static virCPUDef cpuDefaultData = { }; static virCPUFeatureDef cpuHaswellFeatures[] = { - { (char *) "vme", -1 }, - { (char *) "ds", -1 }, - { (char *) "acpi", -1 }, - { (char *) "ss", -1 }, - { (char *) "ht", -1 }, - { (char *) "tm", -1 }, - { (char *) "pbe", -1 }, - { (char *) "dtes64", -1 }, - { (char *) "monitor", -1 }, - { (char *) "ds_cpl", -1 }, - { (char *) "vmx", -1 }, - { (char *) "smx", -1 }, - { (char *) "est", -1 }, - { (char *) "tm2", -1 }, - { (char *) "xtpr", -1 }, - { (char *) "pdcm", -1 }, - { (char *) "osxsave", -1 }, - { (char *) "f16c", -1 }, - { (char *) "rdrand", -1 }, - { (char *) "cmt", -1 }, - { (char *) "pdpe1gb", -1 }, - { (char *) "abm", -1 }, - { (char *) "invtsc", -1 }, - { (char *) "lahf_lm", -1 }, + { (char *) "vme", -1, NULL}, + { (char *) "ds", -1, NULL}, + { (char *) "acpi", -1, NULL}, + { (char *) "ss", -1, NULL}, + { (char *) "ht", -1, NULL}, + { (char *) "tm", -1, NULL}, + { (char *) "pbe", -1, NULL}, + { (char *) "dtes64", -1, NULL}, + { (char *) "monitor", -1, NULL}, + { (char *) "ds_cpl", -1, NULL}, + { (char *) "vmx", -1, NULL}, + { (char *) "smx", -1, NULL}, + { (char *) "est", -1, NULL}, + { (char *) "tm2", -1, NULL}, + { (char *) "xtpr", -1, NULL}, + { (char *) "pdcm", -1, NULL}, + { (char *) "osxsave", -1, NULL}, + { (char *) "f16c", -1, NULL}, + { (char *) "rdrand", -1, NULL}, + { (char *) "cmt", -1, NULL}, + { (char *) "pdpe1gb", -1, NULL}, + { (char *) "abm", -1, NULL}, + { (char *) "invtsc", -1, NULL}, + { (char *) "lahf_lm", -1, NULL}, }; static virCPUDef cpuHaswellData = { .type = VIR_CPU_TYPE_HOST, -- 2.43.7
participants (2)
-
Peter Krempa -
sandesh.patel@nutanix.com