render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
b971b8
From 51290a9442c1b9347c43b2fec34b7aa979d26c77 Mon Sep 17 00:00:00 2001
b971b8
Message-Id: <51290a9442c1b9347c43b2fec34b7aa979d26c77@dist-git>
b971b8
From: Jiri Denemark <jdenemar@redhat.com>
b971b8
Date: Tue, 26 May 2020 10:59:34 +0200
b971b8
Subject: [PATCH] cpu_x86: Add support for stepping part of CPU signature
b971b8
MIME-Version: 1.0
b971b8
Content-Type: text/plain; charset=UTF-8
b971b8
Content-Transfer-Encoding: 8bit
b971b8
b971b8
CPU models defined in the cpu_map can use signature/@stepping attribute
b971b8
to match a limited set of stepping numbers. The value is a bitmap for
b971b8
bits 0..15 each corresponding to a single stepping value. For example,
b971b8
stepping='4-6,9' will match 4, 5, 6, and 9. Omitting the attribute is
b971b8
equivalent to stepping='0-15'.
b971b8
b971b8
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
b971b8
Reviewed-by: Ján Tomko <jtomko@redhat.com>
b971b8
(cherry picked from commit c7a27949954d78dc95459758e329fb9c580361bb)
b971b8
b971b8
https://bugzilla.redhat.com/show_bug.cgi?id=1840010
b971b8
b971b8
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
b971b8
Message-Id: <20bd9df72a22a004bb665409ddba20ff89a5b66d.1590483392.git.jdenemar@redhat.com>
b971b8
Reviewed-by: Ján Tomko <jtomko@redhat.com>
b971b8
---
b971b8
 src/cpu/cpu_x86.c | 60 +++++++++++++++++++++++++++++++++++++++--------
b971b8
 1 file changed, 50 insertions(+), 10 deletions(-)
b971b8
b971b8
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
b971b8
index 45a073c1d0..0d81f3d2ae 100644
b971b8
--- a/src/cpu/cpu_x86.c
b971b8
+++ b/src/cpu/cpu_x86.c
b971b8
@@ -125,6 +125,7 @@ typedef struct _virCPUx86Signature virCPUx86Signature;
b971b8
 struct _virCPUx86Signature {
b971b8
     unsigned int family;
b971b8
     unsigned int model;
b971b8
+    virBitmapPtr stepping;
b971b8
 };
b971b8
 
b971b8
 typedef struct _virCPUx86Signatures virCPUx86Signatures;
b971b8
@@ -732,7 +733,17 @@ x86MakeSignature(unsigned int family,
b971b8
 static uint32_t
b971b8
 virCPUx86SignatureToCPUID(virCPUx86Signature *sig)
b971b8
 {
b971b8
-    return x86MakeSignature(sig->family, sig->model, 0);
b971b8
+    unsigned int stepping = 0;
b971b8
+
b971b8
+    if (sig->stepping) {
b971b8
+        ssize_t firstBit;
b971b8
+
b971b8
+        firstBit = virBitmapNextSetBit(sig->stepping, -1);
b971b8
+        if (firstBit >= 0)
b971b8
+            stepping = firstBit;
b971b8
+    }
b971b8
+
b971b8
+    return x86MakeSignature(sig->family, sig->model, stepping);
b971b8
 }
b971b8
 
b971b8
 
b971b8
@@ -767,8 +778,8 @@ x86DataToSignatureFull(const virCPUx86Data *data,
b971b8
 }
b971b8
 
b971b8
 
b971b8
-/* Mask out irrelevant bits (R and Step) from processor signature. */
b971b8
-#define SIGNATURE_MASK  0x0fff3ff0
b971b8
+/* Mask out reserved bits from processor signature. */
b971b8
+#define SIGNATURE_MASK  0x0fff3fff
b971b8
 
b971b8
 static uint32_t
b971b8
 x86DataToSignature(const virCPUx86Data *data)
b971b8
@@ -1134,9 +1145,14 @@ virCPUx86SignaturesNew(size_t count)
b971b8
 static void
b971b8
 virCPUx86SignaturesFree(virCPUx86SignaturesPtr sigs)
b971b8
 {
b971b8
+    size_t i;
b971b8
+
b971b8
     if (!sigs)
b971b8
         return;
b971b8
 
b971b8
+    for (i = 0; i < sigs->count; i++)
b971b8
+        virBitmapFree(sigs->items[i].stepping);
b971b8
+
b971b8
     g_free(sigs->items);
b971b8
     g_free(sigs);
b971b8
 }
b971b8
@@ -1153,8 +1169,12 @@ virCPUx86SignaturesCopy(virCPUx86SignaturesPtr src)
b971b8
 
b971b8
     dst = virCPUx86SignaturesNew(src->count);
b971b8
 
b971b8
-    for (i = 0; i < src->count; i++)
b971b8
-        dst->items[i] = src->items[i];
b971b8
+    for (i = 0; i < src->count; i++) {
b971b8
+        dst->items[i].family = src->items[i].family;
b971b8
+        dst->items[i].model = src->items[i].model;
b971b8
+        if (src->items[i].stepping)
b971b8
+            dst->items[i].stepping = virBitmapNewCopy(src->items[i].stepping);
b971b8
+    }
b971b8
 
b971b8
     return dst;
b971b8
 }
b971b8
@@ -1176,7 +1196,9 @@ virCPUx86SignaturesMatch(virCPUx86SignaturesPtr sigs,
b971b8
 
b971b8
     for (i = 0; i < sigs->count; i++) {
b971b8
         if (sigs->items[i].family == family &&
b971b8
-            sigs->items[i].model == model)
b971b8
+            sigs->items[i].model == model &&
b971b8
+            (!sigs->items[i].stepping ||
b971b8
+             virBitmapIsBitSet(sigs->items[i].stepping, stepping)))
b971b8
             return true;
b971b8
     }
b971b8
 
b971b8
@@ -1194,9 +1216,15 @@ virCPUx86SignaturesFormat(virCPUx86SignaturesPtr sigs)
b971b8
         return virBufferContentAndReset(&buf;;
b971b8
 
b971b8
     for (i = 0; i < sigs->count; i++) {
b971b8
-        virBufferAsprintf(&buf, "(%u,%u,0), ",
b971b8
+        g_autofree char *stepping = NULL;
b971b8
+
b971b8
+        if (sigs->items[i].stepping)
b971b8
+            stepping = virBitmapFormat(sigs->items[i].stepping);
b971b8
+
b971b8
+        virBufferAsprintf(&buf, "(%u,%u,%s), ",
b971b8
                           sigs->items[i].family,
b971b8
-                          sigs->items[i].model);
b971b8
+                          sigs->items[i].model,
b971b8
+                          stepping ? stepping : "0-15");
b971b8
     }
b971b8
 
b971b8
     virBufferTrim(&buf, ", ", -1);
b971b8
@@ -1473,6 +1501,7 @@ x86ModelParseSignatures(virCPUx86ModelPtr model,
b971b8
 
b971b8
     for (i = 0; i < n; i++) {
b971b8
         virCPUx86Signature *sig = &model->signatures->items[i];
b971b8
+        g_autofree char *stepping = NULL;
b971b8
         int rc;
b971b8
 
b971b8
         ctxt->node = nodes[i];
b971b8
@@ -1492,6 +1521,11 @@ x86ModelParseSignatures(virCPUx86ModelPtr model,
b971b8
                            model->name);
b971b8
             return -1;
b971b8
         }
b971b8
+
b971b8
+        stepping = virXPathString("string(@stepping)", ctxt);
b971b8
+        /* stepping corresponds to 4 bits in 32b signature, see above */
b971b8
+        if (stepping && virBitmapParse(stepping, &sig->stepping, 16) < 0)
b971b8
+            return -1;
b971b8
     }
b971b8
 
b971b8
     ctxt->node = root;
b971b8
@@ -2090,6 +2124,9 @@ x86Decode(virCPUDefPtr cpu,
b971b8
     virDomainCapsCPUModelPtr hvModel = NULL;
b971b8
     g_autofree char *sigs = NULL;
b971b8
     uint32_t signature;
b971b8
+    unsigned int sigFamily;
b971b8
+    unsigned int sigModel;
b971b8
+    unsigned int sigStepping;
b971b8
     ssize_t i;
b971b8
     int rc;
b971b8
 
b971b8
@@ -2103,6 +2140,7 @@ x86Decode(virCPUDefPtr cpu,
b971b8
 
b971b8
     vendor = x86DataToVendor(&data, map);
b971b8
     signature = x86DataToSignature(&data);
b971b8
+    virCPUx86SignatureFromCPUID(signature, &sigFamily, &sigModel, &sigStepping);
b971b8
 
b971b8
     x86DataFilterTSX(&data, vendor, map);
b971b8
 
b971b8
@@ -2184,8 +2222,10 @@ x86Decode(virCPUDefPtr cpu,
b971b8
 
b971b8
     sigs = virCPUx86SignaturesFormat(model->signatures);
b971b8
 
b971b8
-    VIR_DEBUG("Using CPU model %s (signatures %s) for CPU with signature %06lx",
b971b8
-              model->name, NULLSTR(sigs), (unsigned long)signature);
b971b8
+    VIR_DEBUG("Using CPU model %s with signatures [%s] for "
b971b8
+              "CPU with signature (%u,%u,%u)",
b971b8
+              model->name, NULLSTR(sigs),
b971b8
+              sigFamily, sigModel, sigStepping);
b971b8
 
b971b8
     cpu->model = g_steal_pointer(&cpuModel->model);
b971b8
     cpu->features = g_steal_pointer(&cpuModel->features);
b971b8
-- 
b971b8
2.26.2
b971b8