99cbc7
From 26527762b782dbac88abea82d570bc89fcd9af40 Mon Sep 17 00:00:00 2001
99cbc7
Message-Id: <26527762b782dbac88abea82d570bc89fcd9af40@dist-git>
99cbc7
From: Jiri Denemark <jdenemar@redhat.com>
99cbc7
Date: Fri, 22 Feb 2019 17:20:59 +0100
99cbc7
Subject: [PATCH] cpu_x86: Allow multiple signatures for a CPU model
99cbc7
MIME-Version: 1.0
99cbc7
Content-Type: text/plain; charset=UTF-8
99cbc7
Content-Transfer-Encoding: 8bit
99cbc7
99cbc7
CPU signatures in the cpu_map serve as a hint for CPUID to CPU model
99cbc7
matching algorithm. If the CPU signatures matches any CPU model in the
99cbc7
cpu_map, this model will be the preferred one.
99cbc7
99cbc7
This works out well and solved several mismatches, but in real world
99cbc7
CPUs which should match a single CPU model may be produced with several
99cbc7
different signatures. For example, low voltage Broadwell CPUs for
99cbc7
laptops and Broadwell CPUs for servers differ in CPU model numbers while
99cbc7
we should detect them all as Broadwell CPU model.
99cbc7
99cbc7
This patch adds support for storing several signatures for a single CPU
99cbc7
model to make this hint useful for more CPUs. Later commits will provide
99cbc7
additional signatures for existing CPU models, which will correct some
99cbc7
results in our CPU test suite.
99cbc7
99cbc7
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
99cbc7
Reviewed-by: Ján Tomko <jtomko@redhat.com>
99cbc7
(cherry picked from commit dfeb3e598438a891a05487c34e6723d1d3ed9256)
99cbc7
99cbc7
https://bugzilla.redhat.com/show_bug.cgi?id=1558558
99cbc7
https://bugzilla.redhat.com/show_bug.cgi?id=1687515
99cbc7
99cbc7
Conflicts:
99cbc7
	src/cpu/cpu_x86.c
99cbc7
            - most refactoring was not backported
99cbc7
            - VIR_AUTOFREE is not in RHEL-7.6
99cbc7
99cbc7
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
99cbc7
Reviewed-by: Ján Tomko <jtomko@redhat.com>
99cbc7
---
99cbc7
 src/cpu/cpu_x86.c | 44 ++++++++++++++++++++++++++++++--------------
99cbc7
 1 file changed, 30 insertions(+), 14 deletions(-)
99cbc7
99cbc7
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
99cbc7
index 543533148f..f6844aaa0d 100644
99cbc7
--- a/src/cpu/cpu_x86.c
99cbc7
+++ b/src/cpu/cpu_x86.c
99cbc7
@@ -1204,41 +1204,57 @@ x86ModelCompare(virCPUx86ModelPtr model1,
99cbc7
 
99cbc7
 
99cbc7
 static int
99cbc7
-x86ModelParseSignature(virCPUx86ModelPtr model,
99cbc7
-                       xmlXPathContextPtr ctxt)
99cbc7
+x86ModelParseSignatures(virCPUx86ModelPtr model,
99cbc7
+                        xmlXPathContextPtr ctxt)
99cbc7
 {
99cbc7
+    xmlNodePtr *nodes = NULL;
99cbc7
+    xmlNodePtr root = ctxt->node;
99cbc7
+    size_t i;
99cbc7
+    int n;
99cbc7
+    int ret = -1;
99cbc7
+
99cbc7
+    if ((n = virXPathNodeSet("./signature", ctxt, &nodes)) <= 0)
99cbc7
+        return n;
99cbc7
+
99cbc7
     /* Remove inherited signatures. */
99cbc7
     VIR_FREE(model->signatures);
99cbc7
 
99cbc7
-    if (virXPathBoolean("boolean(./signature)", ctxt)) {
99cbc7
+    model->nsignatures = n;
99cbc7
+    if (VIR_ALLOC_N(model->signatures, n) < 0)
99cbc7
+       goto cleanup;
99cbc7
+
99cbc7
+    for (i = 0; i < n; i++) {
99cbc7
         unsigned int sigFamily = 0;
99cbc7
         unsigned int sigModel = 0;
99cbc7
         int rc;
99cbc7
 
99cbc7
-        model->nsignatures = 1;
99cbc7
-        if (VIR_ALLOC_N(model->signatures, 1) < 0)
99cbc7
-            return -1;
99cbc7
+        ctxt->node = nodes[i];
99cbc7
 
99cbc7
-        rc = virXPathUInt("string(./signature/@family)", ctxt, &sigFamily);
99cbc7
+        rc = virXPathUInt("string(@family)", ctxt, &sigFamily);
99cbc7
         if (rc < 0 || sigFamily == 0) {
99cbc7
             virReportError(VIR_ERR_INTERNAL_ERROR,
99cbc7
                            _("Invalid CPU signature family in model %s"),
99cbc7
                            model->name);
99cbc7
-            return -1;
99cbc7
+            goto cleanup;
99cbc7
         }
99cbc7
 
99cbc7
-        rc = virXPathUInt("string(./signature/@model)", ctxt, &sigModel);
99cbc7
+        rc = virXPathUInt("string(@model)", ctxt, &sigModel);
99cbc7
         if (rc < 0 || sigModel == 0) {
99cbc7
             virReportError(VIR_ERR_INTERNAL_ERROR,
99cbc7
                            _("Invalid CPU signature model in model %s"),
99cbc7
                            model->name);
99cbc7
-            return -1;
99cbc7
+            goto cleanup;
99cbc7
         }
99cbc7
 
99cbc7
-        model->signatures[0] = x86MakeSignature(sigFamily, sigModel, 0);
99cbc7
+        model->signatures[i] = x86MakeSignature(sigFamily, sigModel, 0);
99cbc7
     }
99cbc7
 
99cbc7
-    return 0;
99cbc7
+    ctxt->node = root;
99cbc7
+    ret = 0;
99cbc7
+
99cbc7
+ cleanup:
99cbc7
+    VIR_FREE(nodes);
99cbc7
+    return ret;
99cbc7
 }
99cbc7
 
99cbc7
 
99cbc7
@@ -1290,8 +1306,8 @@ x86ModelParse(xmlXPathContextPtr ctxt,
99cbc7
             goto error;
99cbc7
     }
99cbc7
 
99cbc7
-    if (x86ModelParseSignature(model, ctxt) < 0)
99cbc7
-        goto error;
99cbc7
+    if (x86ModelParseSignatures(model, ctxt) < 0)
99cbc7
+        goto cleanup;
99cbc7
 
99cbc7
     if (virXPathBoolean("boolean(./vendor)", ctxt)) {
99cbc7
         vendor = virXPathString("string(./vendor/@name)", ctxt);
99cbc7
-- 
99cbc7
2.21.0
99cbc7