[libvirt] [PATCH v3 08/28] qemu: Store more types in qemuMonitorCPUModelInfo

Jiri Denemark jdenemar at redhat.com
Thu Feb 23 14:15:06 UTC 2017


While query-cpu-model-expansion returns only boolean features on s390,
but x86_64 reports some integer and string properties which we are
interested in.

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---

Notes:
    Version 3:
    - change the XML element to
        <property name='...' type='boolean|string|number' value='...'/>
    
    Version 2:
    - no change

 src/qemu/qemu_capabilities.c                     | 100 +++++++++++++++++------
 src/qemu/qemu_monitor.c                          |  25 +++++-
 src/qemu/qemu_monitor.h                          |  27 +++++-
 src/qemu/qemu_monitor_json.c                     |  42 ++++++++--
 tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml |   7 ++
 5 files changed, 163 insertions(+), 38 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index e037d5f95..0b611c323 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3076,14 +3076,16 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps,
     cpu->nfeatures = 0;
 
     for (i = 0; i < modelInfo->nprops; i++) {
-        if (VIR_STRDUP(cpu->features[i].name, modelInfo->props[i].name) < 0)
+        virCPUFeatureDefPtr feature = cpu->features + cpu->nfeatures;
+        qemuMonitorCPUPropertyPtr prop = modelInfo->props + i;
+
+        if (prop->type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN)
+            continue;
+
+        if (VIR_STRDUP(feature->name, prop->name) < 0)
             return -1;
-
-        if (modelInfo->props[i].supported)
-            cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE;
-        else
-            cpu->features[i].policy = VIR_CPU_FEATURE_DISABLE;
-
+        feature->policy = prop->value.boolean ? VIR_CPU_FEATURE_REQUIRE
+                                              : VIR_CPU_FEATURE_DISABLE;
         cpu->nfeatures++;
     }
 
@@ -3189,30 +3191,59 @@ virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
         hostCPU->nprops = n;
 
         for (i = 0; i < n; i++) {
-            hostCPU->props[i].name = virXMLPropString(nodes[i], "name");
-            if (!hostCPU->props[i].name) {
+            qemuMonitorCPUPropertyPtr prop = hostCPU->props + i;
+            int type;
+
+            ctxt->node = nodes[i];
+
+            if (!(prop->name = virXMLPropString(ctxt->node, "name"))) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("missing 'name' attribute for a host CPU"
                                  " model property in QEMU capabilities cache"));
                 goto cleanup;
             }
 
-            if (!(str = virXMLPropString(nodes[i], "value"))) {
+            if (!(str = virXMLPropString(ctxt->node, "type")) ||
+                (type = qemuMonitorCPUPropertyTypeFromString(str)) < 0) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("missing 'value' attribute for a host CPU"
-                                 " model property in QEMU capabilities cache"));
-                goto cleanup;
-            }
-            if (STREQ(str, "true")) {
-                hostCPU->props[i].supported = true;
-            } else if (STREQ(str, "false")) {
-                hostCPU->props[i].supported = false;
-            } else {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("invalid boolean  value: '%s'"), str);
+                               _("missing CPU model property type in QEMU "
+                                 "capabilities cache"));
                 goto cleanup;
             }
             VIR_FREE(str);
+
+            prop->type = type;
+            switch (prop->type) {
+            case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+                if (virXPathBoolean("./@value='true'", ctxt))
+                    prop->value.boolean = true;
+                break;
+
+            case QEMU_MONITOR_CPU_PROPERTY_STRING:
+                prop->value.string = virXMLPropString(ctxt->node, "value");
+                if (!prop->value.string) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("invalid string value for '%s' host CPU "
+                                     "model property in QEMU capabilities cache"),
+                                   prop->name);
+                    goto cleanup;
+                }
+                break;
+
+            case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+                if (virXPathULongLong("string(./@value)", ctxt,
+                                      &prop->value.number) < 0) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("invalid number value for '%s' host CPU "
+                                     "model property in QEMU capabilities cache"),
+                                   prop->name);
+                    goto cleanup;
+                }
+                break;
+
+            case QEMU_MONITOR_CPU_PROPERTY_LAST:
+                break;
+            }
         }
     }
 
@@ -3554,9 +3585,30 @@ virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
     virBufferAdjustIndent(buf, 2);
 
     for (i = 0; i < model->nprops; i++) {
-        virBufferAsprintf(buf, "<property name='%s' type='boolean' value='%s'/>\n",
-                          model->props[i].name,
-                          model->props[i].supported ? "true" : "false");
+        qemuMonitorCPUPropertyPtr prop = model->props + i;
+
+        virBufferAsprintf(buf, "<property name='%s' type='%s' ",
+                          prop->name,
+                          qemuMonitorCPUPropertyTypeToString(prop->type));
+
+        switch (prop->type) {
+        case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+            virBufferAsprintf(buf, "value='%s'",
+                              prop->value.boolean ? "true" : "false");
+            break;
+
+        case QEMU_MONITOR_CPU_PROPERTY_STRING:
+            virBufferEscapeString(buf, "value='%s'", prop->value.string);
+            break;
+
+        case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+            virBufferAsprintf(buf, "value='%llu'", prop->value.number);
+            break;
+
+        case QEMU_MONITOR_CPU_PROPERTY_LAST:
+            break;
+        }
+        virBufferAddLit(buf, "/>\n");
     }
 
     virBufferAdjustIndent(buf, -2);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b15207a69..4c3f7a20f 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3661,8 +3661,11 @@ qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfoPtr model_info)
     if (!model_info)
         return;
 
-    for (i = 0; i < model_info->nprops; i++)
+    for (i = 0; i < model_info->nprops; i++) {
         VIR_FREE(model_info->props[i].name);
+        if (model_info->props[i].type == QEMU_MONITOR_CPU_PROPERTY_STRING)
+            VIR_FREE(model_info->props[i].value.string);
+    }
 
     VIR_FREE(model_info->props);
     VIR_FREE(model_info->name);
@@ -3691,7 +3694,25 @@ qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig)
         if (VIR_STRDUP(copy->props[i].name, orig->props[i].name) < 0)
             goto error;
 
-        copy->props[i].supported = orig->props[i].supported;
+        copy->props[i].type = orig->props[i].type;
+        switch (orig->props[i].type) {
+        case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+            copy->props[i].value.boolean = orig->props[i].value.boolean;
+            break;
+
+        case QEMU_MONITOR_CPU_PROPERTY_STRING:
+            if (VIR_STRDUP(copy->props[i].value.string,
+                           orig->props[i].value.string) < 0)
+                goto error;
+            break;
+
+        case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+            copy->props[i].value.number = orig->props[i].value.number;
+            break;
+
+        case QEMU_MONITOR_CPU_PROPERTY_LAST:
+            break;
+        }
     }
 
     return copy;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 8811d8501..ff8731bdd 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -921,16 +921,35 @@ int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
                                  qemuMonitorCPUDefInfoPtr **cpus);
 void qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu);
 
+typedef enum {
+    QEMU_MONITOR_CPU_PROPERTY_BOOLEAN,
+    QEMU_MONITOR_CPU_PROPERTY_STRING,
+    QEMU_MONITOR_CPU_PROPERTY_NUMBER,
+
+    QEMU_MONITOR_CPU_PROPERTY_LAST
+} qemuMonitorCPUPropertyType;
+
+VIR_ENUM_DECL(qemuMonitorCPUProperty)
+
+typedef struct _qemuMonitorCPUProperty qemuMonitorCPUProperty;
+typedef qemuMonitorCPUProperty *qemuMonitorCPUPropertyPtr;
+struct _qemuMonitorCPUProperty {
+    char *name;
+    qemuMonitorCPUPropertyType type;
+    union {
+        bool boolean;
+        char *string;
+        unsigned long long number;
+    } value;
+};
+
 typedef struct _qemuMonitorCPUModelInfo qemuMonitorCPUModelInfo;
 typedef qemuMonitorCPUModelInfo *qemuMonitorCPUModelInfoPtr;
 
 struct _qemuMonitorCPUModelInfo {
     char *name;
     size_t nprops;
-    struct {
-        char *name;
-        bool supported;
-    } *props;
+    qemuMonitorCPUPropertyPtr props;
 };
 
 int qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 7aa9e314c..b6a4824d6 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4977,24 +4977,50 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
     return ret;
 }
 
+
+VIR_ENUM_IMPL(qemuMonitorCPUProperty,
+              QEMU_MONITOR_CPU_PROPERTY_LAST,
+              "boolean", "string", "number")
+
 static int
 qemuMonitorJSONParseCPUModelProperty(const char *key,
                                      virJSONValue *value,
                                      void *opaque)
 {
     qemuMonitorCPUModelInfoPtr machine_model = opaque;
-    size_t n = machine_model->nprops;
-    bool supported;
+    qemuMonitorCPUPropertyPtr prop;
 
-    if (virJSONValueGetBoolean(value, &supported) < 0)
+    prop = machine_model->props + machine_model->nprops;
+
+    switch ((virJSONType) value->type) {
+    case VIR_JSON_TYPE_STRING:
+        if (VIR_STRDUP(prop->value.string, virJSONValueGetString(value)) < 0)
+            return -1;
+        prop->type = QEMU_MONITOR_CPU_PROPERTY_STRING;
+        break;
+
+    case VIR_JSON_TYPE_NUMBER:
+        /* Ignore numbers which cannot be parsed as unsigned long long */
+        if (virJSONValueGetNumberUlong(value, &prop->value.number) < 0)
+            return 0;
+        prop->type = QEMU_MONITOR_CPU_PROPERTY_NUMBER;
+        break;
+
+    case VIR_JSON_TYPE_BOOLEAN:
+        virJSONValueGetBoolean(value, &prop->value.boolean);
+        prop->type = QEMU_MONITOR_CPU_PROPERTY_BOOLEAN;
+        break;
+
+    case VIR_JSON_TYPE_OBJECT:
+    case VIR_JSON_TYPE_ARRAY:
+    case VIR_JSON_TYPE_NULL:
         return 0;
-
-    if (VIR_STRDUP(machine_model->props[n].name, key) < 0)
-        return -1;
-
-    machine_model->props[n].supported = supported;
+    }
 
     machine_model->nprops++;
+    if (VIR_STRDUP(prop->name, key) < 0)
+        return -1;
+
     return 0;
 }
 
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
index 73d1e59c8..805fee78b 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
@@ -224,11 +224,13 @@
     <property name='avx512cd' type='boolean' value='false'/>
     <property name='decodeassists' type='boolean' value='false'/>
     <property name='sse4.1' type='boolean' value='true'/>
+    <property name='family' type='number' value='6'/>
     <property name='avx512f' type='boolean' value='false'/>
     <property name='msr' type='boolean' value='true'/>
     <property name='mce' type='boolean' value='true'/>
     <property name='mca' type='boolean' value='true'/>
     <property name='xcrypt' type='boolean' value='false'/>
+    <property name='min-level' type='number' value='13'/>
     <property name='xgetbv1' type='boolean' value='true'/>
     <property name='cid' type='boolean' value='false'/>
     <property name='ds' type='boolean' value='false'/>
@@ -244,6 +246,7 @@
     <property name='xcrypt-en' type='boolean' value='false'/>
     <property name='pn' type='boolean' value='false'/>
     <property name='dca' type='boolean' value='false'/>
+    <property name='vendor' type='string' value='GenuineIntel'/>
     <property name='pku' type='boolean' value='false'/>
     <property name='smx' type='boolean' value='false'/>
     <property name='cmp-legacy' type='boolean' value='false'/>
@@ -289,6 +292,7 @@
     <property name='sse4.2' type='boolean' value='true'/>
     <property name='pge' type='boolean' value='true'/>
     <property name='pdcm' type='boolean' value='false'/>
+    <property name='model' type='number' value='94'/>
     <property name='movbe' type='boolean' value='true'/>
     <property name='nrip-save' type='boolean' value='false'/>
     <property name='ssse3' type='boolean' value='true'/>
@@ -299,6 +303,7 @@
     <property name='fma' type='boolean' value='true'/>
     <property name='cx16' type='boolean' value='true'/>
     <property name='de' type='boolean' value='true'/>
+    <property name='stepping' type='number' value='3'/>
     <property name='xsave' type='boolean' value='true'/>
     <property name='clflush' type='boolean' value='true'/>
     <property name='skinit' type='boolean' value='false'/>
@@ -336,6 +341,7 @@
     <property name='sep' type='boolean' value='true'/>
     <property name='nodeid-msr' type='boolean' value='false'/>
     <property name='misalignsse' type='boolean' value='false'/>
+    <property name='min-xlevel' type='number' value='2147483656'/>
     <property name='bmi1' type='boolean' value='true'/>
     <property name='bmi2' type='boolean' value='true'/>
     <property name='kvm-pv-unhalt' type='boolean' value='true'/>
@@ -365,6 +371,7 @@
     <property name='pse36' type='boolean' value='true'/>
     <property name='tbm' type='boolean' value='false'/>
     <property name='wdt' type='boolean' value='false'/>
+    <property name='model-id' type='string' value='Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz'/>
     <property name='sha-ni' type='boolean' value='false'/>
     <property name='abm' type='boolean' value='true'/>
     <property name='avx512pf' type='boolean' value='false'/>
-- 
2.11.1




More information about the libvir-list mailing list