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