Blame SOURCES/libvirt-cpu_x86-Ignore-enabled-features-for-input-models-in-x86DecodeUseCandidate.patch

abb18f
From 5b5f684bfceeed923e1733931b6c4c75d5ed4149 Mon Sep 17 00:00:00 2001
abb18f
Message-Id: <5b5f684bfceeed923e1733931b6c4c75d5ed4149@dist-git>
abb18f
From: Jiri Denemark <jdenemar@redhat.com>
abb18f
Date: Fri, 29 Apr 2022 10:35:02 +0200
abb18f
Subject: [PATCH] cpu_x86: Ignore enabled features for input models in
abb18f
 x86DecodeUseCandidate
abb18f
abb18f
While we don't want to aim for the shortest list of disabled features in
abb18f
the baseline result (it would select a very old model), we want to do so
abb18f
while looking at any of the input models for which we're trying to
abb18f
compute a baseline CPU model. Given a set of input models, we always
abb18f
want to take the least capable one of them (i.e., the one with shortest
abb18f
list of disabled features) or a better model which is not one of the
abb18f
input models.
abb18f
abb18f
So when considering an input model, we just check whether its list of
abb18f
disabled features is shorter than the currently best one. When looking
abb18f
at other models we check both enabled and disabled features while
abb18f
penalizing disabled features as implemented by the previous patch.
abb18f
abb18f
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
abb18f
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
abb18f
(cherry picked from commit bb6cedd2082599323257ee0df18c93a6e0551b0b)
abb18f
abb18f
https://bugzilla.redhat.com/show_bug.cgi?id=2084030
abb18f
abb18f
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
abb18f
---
abb18f
 src/cpu/cpu_x86.c                             | 66 ++++++++++++-------
abb18f
 ...4-baseline-Westmere+Nehalem-migratable.xml |  8 ++-
abb18f
 ...86_64-baseline-Westmere+Nehalem-result.xml |  8 ++-
abb18f
 ...-cpuid-baseline-Cooperlake+Cascadelake.xml | 13 ++--
abb18f
 4 files changed, 64 insertions(+), 31 deletions(-)
abb18f
abb18f
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
abb18f
index ebcd96edb1..7b59dad8bf 100644
abb18f
--- a/src/cpu/cpu_x86.c
abb18f
+++ b/src/cpu/cpu_x86.c
abb18f
@@ -1975,7 +1975,8 @@ virCPUx86Compare(virCPUDef *host,
abb18f
 
abb18f
 static int
abb18f
 virCPUx86CompareCandidateFeatureList(virCPUDef *cpuCurrent,
abb18f
-                                     virCPUDef *cpuCandidate)
abb18f
+                                     virCPUDef *cpuCandidate,
abb18f
+                                     bool isPreferred)
abb18f
 {
abb18f
     size_t current = cpuCurrent->nfeatures;
abb18f
     size_t enabledCurrent = current;
abb18f
@@ -2017,6 +2018,14 @@ virCPUx86CompareCandidateFeatureList(virCPUDef *cpuCurrent,
abb18f
         return 1;
abb18f
     }
abb18f
 
abb18f
+    if (isPreferred && disabled < disabledCurrent) {
abb18f
+        VIR_DEBUG("%s is in the list of preferred models and provides fewer "
abb18f
+                  "disabled features than %s: %zu < %zu",
abb18f
+                  cpuCandidate->model, cpuCurrent->model,
abb18f
+                  disabled, disabledCurrent);
abb18f
+        return 1;
abb18f
+    }
abb18f
+
abb18f
     VIR_DEBUG("%s is not better than %s: %zu (%zu, %zu) >= %zu (%zu, %zu)",
abb18f
               cpuCandidate->model, cpuCurrent->model,
abb18f
               candidate, enabled, disabled,
abb18f
@@ -2039,8 +2048,10 @@ x86DecodeUseCandidate(virCPUx86Model *current,
abb18f
                       virCPUx86Model *candidate,
abb18f
                       virCPUDef *cpuCandidate,
abb18f
                       uint32_t signature,
abb18f
-                      const char *preferred)
abb18f
+                      const char **preferred)
abb18f
 {
abb18f
+    bool isPreferred = false;
abb18f
+
abb18f
     if (cpuCandidate->type == VIR_CPU_TYPE_HOST &&
abb18f
         !candidate->decodeHost) {
abb18f
         VIR_DEBUG("%s is not supposed to be used for host CPU definition",
abb18f
@@ -2064,9 +2075,13 @@ x86DecodeUseCandidate(virCPUx86Model *current,
abb18f
         }
abb18f
     }
abb18f
 
abb18f
-    if (preferred && STREQ(cpuCandidate->model, preferred)) {
abb18f
-        VIR_DEBUG("%s is the preferred model", cpuCandidate->model);
abb18f
-        return 2;
abb18f
+    if (preferred) {
abb18f
+        isPreferred = g_strv_contains(preferred, cpuCandidate->model);
abb18f
+
abb18f
+        if (isPreferred && !preferred[1]) {
abb18f
+            VIR_DEBUG("%s is the preferred model", cpuCandidate->model);
abb18f
+            return 2;
abb18f
+        }
abb18f
     }
abb18f
 
abb18f
     if (!cpuCurrent) {
abb18f
@@ -2093,7 +2108,8 @@ x86DecodeUseCandidate(virCPUx86Model *current,
abb18f
         }
abb18f
     }
abb18f
 
abb18f
-    return virCPUx86CompareCandidateFeatureList(cpuCurrent, cpuCandidate);
abb18f
+    return virCPUx86CompareCandidateFeatureList(cpuCurrent, cpuCandidate,
abb18f
+                                                isPreferred);
abb18f
 }
abb18f
 
abb18f
 
abb18f
@@ -2136,7 +2152,7 @@ static int
abb18f
 x86Decode(virCPUDef *cpu,
abb18f
           const virCPUx86Data *cpuData,
abb18f
           virDomainCapsCPUModels *models,
abb18f
-          const char *preferred,
abb18f
+          const char **preferred,
abb18f
           bool migratable)
abb18f
 {
abb18f
     virCPUx86Map *map;
abb18f
@@ -2169,6 +2185,9 @@ x86Decode(virCPUDef *cpu,
abb18f
 
abb18f
     x86DataFilterTSX(&data, vendor, map);
abb18f
 
abb18f
+    if (preferred && !preferred[0])
abb18f
+        preferred = NULL;
abb18f
+
abb18f
     /* Walk through the CPU models in reverse order to check newest
abb18f
      * models first.
abb18f
      */
abb18f
@@ -2176,16 +2195,18 @@ x86Decode(virCPUDef *cpu,
abb18f
         candidate = map->models[i];
abb18f
         if (models &&
abb18f
             !(hvModel = virDomainCapsCPUModelsGet(models, candidate->name))) {
abb18f
-            if (preferred && STREQ(candidate->name, preferred)) {
abb18f
+            if (preferred &&
abb18f
+                !preferred[1] &&
abb18f
+                STREQ(candidate->name, preferred[0])) {
abb18f
                 if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) {
abb18f
                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
abb18f
                                    _("CPU model %s is not supported by hypervisor"),
abb18f
-                                   preferred);
abb18f
+                                   preferred[0]);
abb18f
                     return -1;
abb18f
                 } else {
abb18f
                     VIR_WARN("Preferred CPU model %s not allowed by"
abb18f
                              " hypervisor; closest supported model will be"
abb18f
-                             " used", preferred);
abb18f
+                             " used", preferred[0]);
abb18f
                 }
abb18f
             } else {
abb18f
                 VIR_DEBUG("CPU model %s not allowed by hypervisor; ignoring",
abb18f
@@ -2793,8 +2814,8 @@ virCPUx86Baseline(virCPUDef **cpus,
abb18f
     size_t i;
abb18f
     virCPUx86Vendor *vendor = NULL;
abb18f
     bool outputVendor = true;
abb18f
-    const char *modelName;
abb18f
-    bool matchingNames = true;
abb18f
+    g_autofree char **modelNames = NULL;
abb18f
+    size_t namesLen = 0;
abb18f
     g_autoptr(virCPUData) featData = NULL;
abb18f
 
abb18f
     if (!(map = virCPUx86GetMap()))
abb18f
@@ -2816,19 +2837,17 @@ virCPUx86Baseline(virCPUDef **cpus,
abb18f
         return NULL;
abb18f
     }
abb18f
 
abb18f
-    modelName = cpus[0]->model;
abb18f
+    modelNames = g_new0(char *, ncpus + 1);
abb18f
+    if (cpus[0]->model)
abb18f
+        modelNames[namesLen++] = cpus[0]->model;
abb18f
+
abb18f
     for (i = 1; i < ncpus; i++) {
abb18f
         g_autoptr(virCPUx86Model) model = NULL;
abb18f
         const char *vn = NULL;
abb18f
 
abb18f
-        if (matchingNames && cpus[i]->model) {
abb18f
-            if (!modelName) {
abb18f
-                modelName = cpus[i]->model;
abb18f
-            } else if (STRNEQ(modelName, cpus[i]->model)) {
abb18f
-                modelName = NULL;
abb18f
-                matchingNames = false;
abb18f
-            }
abb18f
-        }
abb18f
+        if (cpus[i]->model &&
abb18f
+            !g_strv_contains((const char **) modelNames, cpus[i]->model))
abb18f
+            modelNames[namesLen++] = cpus[i]->model;
abb18f
 
abb18f
         if (!(model = x86ModelFromCPU(cpus[i], map, -1)))
abb18f
             return NULL;
abb18f
@@ -2891,10 +2910,11 @@ virCPUx86Baseline(virCPUDef **cpus,
abb18f
         virCPUx86DataAddItem(&base_model->data, &vendor->data) < 0)
abb18f
         return NULL;
abb18f
 
abb18f
-    if (x86Decode(cpu, &base_model->data, models, modelName, migratable) < 0)
abb18f
+    if (x86Decode(cpu, &base_model->data, models,
abb18f
+                  (const char **) modelNames, migratable) < 0)
abb18f
         return NULL;
abb18f
 
abb18f
-    if (STREQ_NULLABLE(cpu->model, modelName))
abb18f
+    if (namesLen == 1 && STREQ(cpu->model, modelNames[0]))
abb18f
         cpu->fallback = VIR_CPU_FALLBACK_FORBID;
abb18f
 
abb18f
     if (!outputVendor)
abb18f
diff --git a/tests/cputestdata/x86_64-baseline-Westmere+Nehalem-migratable.xml b/tests/cputestdata/x86_64-baseline-Westmere+Nehalem-migratable.xml
abb18f
index 775a27de2e..f5846b1619 100644
abb18f
--- a/tests/cputestdata/x86_64-baseline-Westmere+Nehalem-migratable.xml
abb18f
+++ b/tests/cputestdata/x86_64-baseline-Westmere+Nehalem-migratable.xml
abb18f
@@ -1,10 +1,14 @@
abb18f
 <cpu mode='custom' match='exact'>
abb18f
-  <model fallback='allow'>SandyBridge</model>
abb18f
+  <model fallback='allow'>Westmere</model>
abb18f
   <vendor>Intel</vendor>
abb18f
   <feature policy='require' name='vme'/>
abb18f
   <feature policy='require' name='ss'/>
abb18f
+  <feature policy='require' name='pclmuldq'/>
abb18f
   <feature policy='require' name='pcid'/>
abb18f
+  <feature policy='require' name='x2apic'/>
abb18f
+  <feature policy='require' name='tsc-deadline'/>
abb18f
+  <feature policy='require' name='xsave'/>
abb18f
   <feature policy='require' name='osxsave'/>
abb18f
+  <feature policy='require' name='avx'/>
abb18f
   <feature policy='require' name='hypervisor'/>
abb18f
-  <feature policy='disable' name='rdtscp'/>
abb18f
 </cpu>
abb18f
diff --git a/tests/cputestdata/x86_64-baseline-Westmere+Nehalem-result.xml b/tests/cputestdata/x86_64-baseline-Westmere+Nehalem-result.xml
abb18f
index cafca97d62..166833276c 100644
abb18f
--- a/tests/cputestdata/x86_64-baseline-Westmere+Nehalem-result.xml
abb18f
+++ b/tests/cputestdata/x86_64-baseline-Westmere+Nehalem-result.xml
abb18f
@@ -1,11 +1,15 @@
abb18f
 <cpu mode='custom' match='exact'>
abb18f
-  <model fallback='allow'>SandyBridge</model>
abb18f
+  <model fallback='allow'>Westmere</model>
abb18f
   <vendor>Intel</vendor>
abb18f
   <feature policy='require' name='vme'/>
abb18f
   <feature policy='require' name='ss'/>
abb18f
+  <feature policy='require' name='pclmuldq'/>
abb18f
   <feature policy='require' name='pcid'/>
abb18f
+  <feature policy='require' name='x2apic'/>
abb18f
+  <feature policy='require' name='tsc-deadline'/>
abb18f
+  <feature policy='require' name='xsave'/>
abb18f
   <feature policy='require' name='osxsave'/>
abb18f
+  <feature policy='require' name='avx'/>
abb18f
   <feature policy='require' name='hypervisor'/>
abb18f
   <feature policy='require' name='invtsc'/>
abb18f
-  <feature policy='disable' name='rdtscp'/>
abb18f
 </cpu>
abb18f
diff --git a/tests/cputestdata/x86_64-cpuid-baseline-Cooperlake+Cascadelake.xml b/tests/cputestdata/x86_64-cpuid-baseline-Cooperlake+Cascadelake.xml
abb18f
index 46c32c996f..ecac749b97 100644
abb18f
--- a/tests/cputestdata/x86_64-cpuid-baseline-Cooperlake+Cascadelake.xml
abb18f
+++ b/tests/cputestdata/x86_64-cpuid-baseline-Cooperlake+Cascadelake.xml
abb18f
@@ -1,17 +1,22 @@
abb18f
 <cpu mode='custom' match='exact'>
abb18f
-  <model fallback='allow'>Cooperlake</model>
abb18f
+  <model fallback='allow'>Cascadelake-Server</model>
abb18f
   <vendor>Intel</vendor>
abb18f
   <feature policy='require' name='ss'/>
abb18f
   <feature policy='require' name='vmx'/>
abb18f
   <feature policy='require' name='hypervisor'/>
abb18f
   <feature policy='require' name='tsc_adjust'/>
abb18f
-  <feature policy='require' name='mpx'/>
abb18f
   <feature policy='require' name='umip'/>
abb18f
+  <feature policy='require' name='pku'/>
abb18f
   <feature policy='require' name='md-clear'/>
abb18f
+  <feature policy='require' name='stibp'/>
abb18f
+  <feature policy='require' name='arch-capabilities'/>
abb18f
   <feature policy='require' name='xsaves'/>
abb18f
   <feature policy='require' name='ibpb'/>
abb18f
   <feature policy='require' name='amd-ssbd'/>
abb18f
+  <feature policy='require' name='rdctl-no'/>
abb18f
+  <feature policy='require' name='ibrs-all'/>
abb18f
+  <feature policy='require' name='skip-l1dfl-vmentry'/>
abb18f
+  <feature policy='require' name='mds-no'/>
abb18f
+  <feature policy='require' name='pschange-mc-no'/>
abb18f
   <feature policy='require' name='tsx-ctrl'/>
abb18f
-  <feature policy='disable' name='avx512-bf16'/>
abb18f
-  <feature policy='disable' name='taa-no'/>
abb18f
 </cpu>
abb18f
-- 
abb18f
2.35.1
abb18f