c480ed
From c7a8133cbe9d0612db2889038079d260c3a8334f Mon Sep 17 00:00:00 2001
c480ed
Message-Id: <c7a8133cbe9d0612db2889038079d260c3a8334f@dist-git>
c480ed
From: Jiri Denemark <jdenemar@redhat.com>
c480ed
Date: Fri, 21 Jun 2019 09:25:00 +0200
c480ed
Subject: [PATCH] cpu_x86: Store CPU signature in an array
c480ed
MIME-Version: 1.0
c480ed
Content-Type: text/plain; charset=UTF-8
c480ed
Content-Transfer-Encoding: 8bit
c480ed
c480ed
In preparation for storing several CPU signatures in a single CPU model,
c480ed
we need to turn virCPUx86Model's signature into an array of signatures.
c480ed
c480ed
The parser still hardcodes the number of signatures to 1, but the
c480ed
following patch will drop this limit.
c480ed
c480ed
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c480ed
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c480ed
(cherry picked from commit b07b8b7750c6a505d4b00bd272e79ea0305cb610)
c480ed
c480ed
https://bugzilla.redhat.com/show_bug.cgi?id=1686895
c480ed
c480ed
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c480ed
Message-Id: <1d24aad1c6b9aa8142a2e882511f52a41fbaff67.1561068591.git.jdenemar@redhat.com>
c480ed
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c480ed
---
c480ed
 src/cpu/cpu_x86.c | 50 ++++++++++++++++++++++++++++++++++++++---------
c480ed
 1 file changed, 41 insertions(+), 9 deletions(-)
c480ed
c480ed
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
c480ed
index e25bc691ae..f8b8d8a96b 100644
c480ed
--- a/src/cpu/cpu_x86.c
c480ed
+++ b/src/cpu/cpu_x86.c
c480ed
@@ -145,7 +145,8 @@ typedef virCPUx86Model *virCPUx86ModelPtr;
c480ed
 struct _virCPUx86Model {
c480ed
     char *name;
c480ed
     virCPUx86VendorPtr vendor;
c480ed
-    uint32_t signature;
c480ed
+    size_t nsignatures;
c480ed
+    uint32_t *signatures;
c480ed
     virCPUx86Data data;
c480ed
 };
c480ed
 
c480ed
@@ -972,6 +973,7 @@ x86ModelFree(virCPUx86ModelPtr model)
c480ed
         return;
c480ed
 
c480ed
     VIR_FREE(model->name);
c480ed
+    VIR_FREE(model->signatures);
c480ed
     virCPUx86DataClear(&model->data);
c480ed
     VIR_FREE(model);
c480ed
 }
c480ed
@@ -981,7 +983,14 @@ static int
c480ed
 x86ModelCopySignatures(virCPUx86ModelPtr dst,
c480ed
                        virCPUx86ModelPtr src)
c480ed
 {
c480ed
-    dst->signature = src->signature;
c480ed
+    size_t i;
c480ed
+
c480ed
+    if (VIR_ALLOC_N(dst->signatures, src->nsignatures) < 0)
c480ed
+        return -1;
c480ed
+
c480ed
+    dst->nsignatures = src->nsignatures;
c480ed
+    for (i = 0; i < src->nsignatures; i++)
c480ed
+        dst->signatures[i] = src->signatures[i];
c480ed
 
c480ed
     return 0;
c480ed
 }
c480ed
@@ -1198,12 +1207,18 @@ static int
c480ed
 x86ModelParseSignature(virCPUx86ModelPtr model,
c480ed
                        xmlXPathContextPtr ctxt)
c480ed
 {
c480ed
+    /* Remove inherited signatures. */
c480ed
+    VIR_FREE(model->signatures);
c480ed
 
c480ed
     if (virXPathBoolean("boolean(./signature)", ctxt)) {
c480ed
         unsigned int sigFamily = 0;
c480ed
         unsigned int sigModel = 0;
c480ed
         int rc;
c480ed
 
c480ed
+        model->nsignatures = 1;
c480ed
+        if (VIR_ALLOC_N(model->signatures, 1) < 0)
c480ed
+            return -1;
c480ed
+
c480ed
         rc = virXPathUInt("string(./signature/@family)", ctxt, &sigFamily);
c480ed
         if (rc < 0 || sigFamily == 0) {
c480ed
             virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
@@ -1220,7 +1235,7 @@ x86ModelParseSignature(virCPUx86ModelPtr model,
c480ed
             return -1;
c480ed
         }
c480ed
 
c480ed
-        model->signature = x86MakeSignature(sigFamily, sigModel, 0);
c480ed
+        model->signatures[0] = x86MakeSignature(sigFamily, sigModel, 0);
c480ed
     }
c480ed
 
c480ed
     return 0;
c480ed
@@ -1621,7 +1636,8 @@ x86Compute(virCPUDefPtr host,
c480ed
                                      &host_model->vendor->cpuid) < 0)
c480ed
             goto error;
c480ed
 
c480ed
-        if (x86DataAddSignature(&guest_model->data, host_model->signature) < 0)
c480ed
+        if (host_model->signatures &&
c480ed
+            x86DataAddSignature(&guest_model->data, *host_model->signatures) < 0)
c480ed
             goto error;
c480ed
 
c480ed
         if (cpu->type == VIR_CPU_TYPE_GUEST
c480ed
@@ -1727,6 +1743,21 @@ virCPUx86Compare(virCPUDefPtr host,
c480ed
 }
c480ed
 
c480ed
 
c480ed
+static bool
c480ed
+x86ModelHasSignature(virCPUx86ModelPtr model,
c480ed
+                     uint32_t signature)
c480ed
+{
c480ed
+    size_t i;
c480ed
+
c480ed
+    for (i = 0; i < model->nsignatures; i++) {
c480ed
+        if (model->signatures[i] == signature)
c480ed
+            return true;
c480ed
+    }
c480ed
+
c480ed
+    return false;
c480ed
+}
c480ed
+
c480ed
+
c480ed
 /*
c480ed
  * Checks whether a candidate model is a better fit for the CPU data than the
c480ed
  * current model.
c480ed
@@ -1768,8 +1799,8 @@ x86DecodeUseCandidate(virCPUx86ModelPtr current,
c480ed
      * consider candidates with matching family/model.
c480ed
      */
c480ed
     if (signature &&
c480ed
-        current->signature == signature &&
c480ed
-        candidate->signature != signature) {
c480ed
+        x86ModelHasSignature(current, signature) &&
c480ed
+        !x86ModelHasSignature(candidate, signature)) {
c480ed
         VIR_DEBUG("%s differs in signature from matching %s",
c480ed
                   cpuCandidate->model, cpuCurrent->model);
c480ed
         return 0;
c480ed
@@ -1785,8 +1816,8 @@ x86DecodeUseCandidate(virCPUx86ModelPtr current,
c480ed
      * result in longer list of features.
c480ed
      */
c480ed
     if (signature &&
c480ed
-        candidate->signature == signature &&
c480ed
-        current->signature != signature) {
c480ed
+        x86ModelHasSignature(candidate, signature) &&
c480ed
+        !x86ModelHasSignature(current, signature)) {
c480ed
         VIR_DEBUG("%s provides matching signature", cpuCandidate->model);
c480ed
         return 1;
c480ed
     }
c480ed
@@ -2854,7 +2885,8 @@ virCPUx86Translate(virCPUDefPtr cpu,
c480ed
         virCPUx86DataAddCPUIDInt(&model->data, &model->vendor->cpuid) < 0)
c480ed
         goto cleanup;
c480ed
 
c480ed
-    if (x86DataAddSignature(&model->data, model->signature) < 0)
c480ed
+    if (model->signatures &&
c480ed
+        x86DataAddSignature(&model->data, model->signatures[0]) < 0)
c480ed
         goto cleanup;
c480ed
 
c480ed
     if (!(translated = virCPUDefCopyWithoutModel(cpu)))
c480ed
-- 
c480ed
2.22.0
c480ed