Send both model name and a set of features/properties to QEMU for
expansion rather than just the model name.
---
src/qemu/qemu_capabilities.c | 33 +++++++++++++------
src/qemu/qemu_monitor.c | 38 ++++++++++++++++++----
src/qemu/qemu_monitor.h | 5 ++-
src/qemu/qemu_monitor_json.c | 61 +++++++++++++++++++++++-------------
src/qemu/qemu_monitor_json.h | 7 ++---
tests/cputest.c | 7 ++++-
6 files changed, 105 insertions(+), 46 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 0c5e4bb766..da6fb1f614 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -2333,7 +2333,7 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps,
qemuMonitorCPUModelInfoPtr modelInfo = NULL;
qemuMonitorCPUModelInfoPtr nonMigratable = NULL;
virHashTablePtr hash = NULL;
- const char *model;
+ const char *model_name;
qemuMonitorCPUModelExpansionType type;
virDomainVirtType virtType;
virQEMUCapsHostCPUDataPtr cpuData;
@@ -2344,12 +2344,20 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps,
if (tcg || !virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) {
virtType = VIR_DOMAIN_VIRT_QEMU;
- model = "max";
+ model_name = "max";
} else {
virtType = VIR_DOMAIN_VIRT_KVM;
- model = "host";
+ model_name = "host";
}
+ if ((VIR_ALLOC(modelInfo) < 0) ||
+ (VIR_ALLOC(nonMigratable) < 0))
+ goto cleanup;
+
+ if ((qemuMonitorCPUModelInfoInit(model_name, modelInfo) < 0) ||
+ (qemuMonitorCPUModelInfoInit(model_name, nonMigratable) < 0))
+ goto cleanup;
+
cpuData = virQEMUCapsGetHostCPUData(qemuCaps, virtType);
/* Some x86_64 features defined in cpu_map.xml use spelling which differ
@@ -2362,15 +2370,20 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps,
else
type = QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC;
- if (qemuMonitorGetCPUModelExpansion(mon, type, model, true, &modelInfo) < 0)
- goto cleanup;
-
- /* Try to check migratability of each feature. */
- if (modelInfo &&
- qemuMonitorGetCPUModelExpansion(mon, type, model, false,
- &nonMigratable) < 0)
+ if ((qemuMonitorGetCPUModelExpansion(mon, type, true, modelInfo) < 0) ||
+ (qemuMonitorGetCPUModelExpansion(mon, type, false, nonMigratable) < 0))
goto cleanup;
+ /* Try to check migratability of each feature */
+ /* Expansion 1 sets migratable features true
+ * Expansion 2 sets migratable and non-migratable features true
+ * (non-migratable set true only in some archs like X86)
+ *
+ * If delta between Expansion 1 and 2 exists...
+ * - both migratable and non-migratable features set prop->value = true
+ * - migratable features set prop->migatable = VIR_TRISTATE_BOOL_YES
+ * - non-migratable features set prop->migatable = VIR_TRISTATE_BOOL_NO
+ */
if (nonMigratable) {
qemuMonitorCPUPropertyPtr prop;
qemuMonitorCPUPropertyPtr nmProp;
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 3fd73e2cd1..558bc37aff 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3615,20 +3615,46 @@ qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu)
}
+/*
+ * type static:
+ * Expand to static base model + delta property changes
+ * Returned model is invariant and migration safe
+ *
+ * model_info->name = base model name
+ * model_info->props = features to +/- to base model to achive model_name
+ *
+ * type full:
+ * Expand model to enumerate all properties
+ * Returned model isn't guaranteed to be invariant or migration safe.
+ *
+ * model_info->name = base model name
+ * model_info->props = features to +/- to empty set to achive model_name
+ *
+ * type static_full:
+ * Expand to static base model + delta property changes (pass 0)
+ * Expand model to enumerate all properties (pass 1)
+ * Returned model is invariant and migration safe
+ *
+ * model_info->name = base model name
+ * model_info->props = features to +/- to empty set to achive model_name
+ *
+ * migratable_only:
+ * true: QEMU excludes non-migratable features
+ * false: QEMU includes non-migratable features for some archs like X86
+ */
int
qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon,
qemuMonitorCPUModelExpansionType type,
- const char *model_name,
- bool migratable,
- qemuMonitorCPUModelInfoPtr *model_info)
+ bool migratable_only,
+ qemuMonitorCPUModelInfoPtr model_info)
{
VIR_DEBUG("type=%d model_name=%s migratable=%d",
- type, model_name, migratable);
+ type, (model_info ? NULLSTR(model_info->name):"NULL"),
+ migratable_only);
QEMU_CHECK_MONITOR(mon);
- return qemuMonitorJSONGetCPUModelExpansion(mon, type, model_name,
- migratable, model_info);
+ return qemuMonitorJSONGetCPUModelExpansion(mon, type, migratable_only, model_info);
}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 08b787e28c..7165aa9076 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1016,9 +1016,8 @@ typedef enum {
int qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon,
qemuMonitorCPUModelExpansionType type,
- const char *model_name,
- bool migratable,
- qemuMonitorCPUModelInfoPtr *model_info);
+ bool migratable_only,
+ qemuMonitorCPUModelInfoPtr model_info);
void qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfoPtr model_info);
void qemuMonitorCPUModelInfoFreeContents(qemuMonitorCPUModelInfoPtr model_info);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 729578414b..bcd7828e8d 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -5403,8 +5403,11 @@ qemuMonitorJSONBuildCPUModelInfoToJSON(qemuMonitorCPUModelInfoPtr
model)
}
}
- ignore_value(virJSONValueObjectCreate(&model_json, "s:name",
model->name,
- "a:props", &cpu_props, NULL));
+ if (model->nprops > 0)
+ ignore_value(virJSONValueObjectCreate(&model_json, "s:name",
model->name,
+ "a:props", &cpu_props,
NULL));
+ else
+ ignore_value(virJSONValueObjectCreate(&model_json, "s:name",
model->name, NULL));
cleanup:
virJSONValueFree(cpu_props);
@@ -5456,35 +5459,43 @@ qemuMonitorJSONBuildCPUModelInfoFromJSON(virJSONValuePtr
cpu_model)
int
qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon,
qemuMonitorCPUModelExpansionType type,
- const char *model_name,
- bool migratable,
- qemuMonitorCPUModelInfoPtr *model_info)
+ bool migratable_only,
+ qemuMonitorCPUModelInfoPtr model)
{
int ret = -1;
- virJSONValuePtr model = NULL;
- virJSONValuePtr props = NULL;
+ virJSONValuePtr json_model = NULL;
virJSONValuePtr cmd = NULL;
virJSONValuePtr reply = NULL;
virJSONValuePtr data;
virJSONValuePtr cpu_model;
+ qemuMonitorCPUModelInfoPtr expanded_model = NULL;
+ qemuMonitorCPUModelInfoPtr model_info = NULL;
const char *typeStr = "";
- *model_info = NULL;
+ if (!(model_info = qemuMonitorCPUModelInfoCopy(model)))
+ return -1;
- if (!(model = virJSONValueNewObject()))
- goto cleanup;
+ qemuMonitorCPUModelInfoFreeContents(model);
- if (virJSONValueObjectAppendString(model, "name", model_name) < 0)
- goto cleanup;
+ if (!migratable_only) {
+ /* Add property to input CPUModelInfo causing QEMU to include
+ * non-migratable properties for some architectures like X86 */
+
+ qemuMonitorCPUProperty prop;
+ prop.type = QEMU_MONITOR_CPU_PROPERTY_BOOLEAN;
+ prop.value.boolean = false;
+ prop.migratable = false;
+
+ if (VIR_STRDUP(prop.name, "migratable") < 0)
+ goto cleanup;
- if (!migratable) {
- if (!(props = virJSONValueNewObject()) ||
- virJSONValueObjectAppendBoolean(props, "migratable", false) < 0
||
- virJSONValueObjectAppend(model, "props", props) < 0)
+ if (VIR_APPEND_ELEMENT(model_info->props, model_info->nprops, prop) <
0)
goto cleanup;
- props = NULL;
}
+ if (!(json_model = qemuMonitorJSONBuildCPUModelInfoToJSON(model_info)))
+ goto cleanup;
+
retry:
switch (type) {
case QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC:
@@ -5499,7 +5510,7 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon,
if (!(cmd = qemuMonitorJSONMakeCommand("query-cpu-model-expansion",
"s:type", typeStr,
- "a:model", &model,
+ "a:model", &json_model,
NULL)))
goto cleanup;
@@ -5530,7 +5541,9 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon,
* on the result of the initial "static" expansion.
*/
if (type == QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL) {
- if (!(model = virJSONValueCopy(cpu_model)))
+ virJSONValueFree(json_model);
+
+ if (!(json_model = virJSONValueCopy(cpu_model)))
goto cleanup;
virJSONValueFree(cmd);
@@ -5539,16 +5552,20 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon,
goto retry;
}
- if (!(*model_info = qemuMonitorJSONBuildCPUModelInfoFromJSON(cpu_model)))
+ if (!(expanded_model = qemuMonitorJSONBuildCPUModelInfoFromJSON(cpu_model)))
goto cleanup;
+ *model = *expanded_model; /* overwrite contents */
+
ret = 0;
cleanup:
+ VIR_FREE(expanded_model); /* Free structure but not reused contents */
+ qemuMonitorCPUModelInfoFreeContents(model_info);
+
virJSONValueFree(cmd);
virJSONValueFree(reply);
- virJSONValueFree(model);
- virJSONValueFree(props);
+ virJSONValueFree(json_model);
return ret;
}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 73e1cb6ace..9950483c5c 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -362,10 +362,9 @@ int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
int qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon,
qemuMonitorCPUModelExpansionType type,
- const char *model_name,
- bool migratable,
- qemuMonitorCPUModelInfoPtr *model_info)
- ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(5);
+ bool migratable_only,
+ qemuMonitorCPUModelInfoPtr model_info)
+ ATTRIBUTE_NONNULL(4);
int qemuMonitorJSONGetCPUModelBaseline(qemuMonitorPtr mon,
qemuMonitorCPUModelInfoPtr model_a,
diff --git a/tests/cputest.c b/tests/cputest.c
index baf2b3c648..27727aa29e 100644
--- a/tests/cputest.c
+++ b/tests/cputest.c
@@ -495,9 +495,14 @@ cpuTestMakeQEMUCaps(const struct data *data)
if (!(testMon = qemuMonitorTestNewFromFile(json, driver.xmlopt, true)))
goto error;
+ if ((VIR_ALLOC(model) < 0) ||
+ (qemuMonitorCPUModelInfoInit("host", model) < 0))
+ goto cleanup;
+
+
if (qemuMonitorGetCPUModelExpansion(qemuMonitorTestGetMonitor(testMon),
QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC,
- "host", true, &model) < 0)
+ true, model) < 0)
goto error;
if (!(qemuCaps = virQEMUCapsNew()))
--
2.17.1