[libvirt PATCH 7/8] cpu_x86: Penalize disabled features when computing CPU model

Michal Prívozník mprivozn at redhat.com
Thu May 5 10:16:27 UTC 2022


On 5/4/22 18:54, Jiri Denemark wrote:
> For finding the best matching CPU model for a given set of features
> while we don't know the CPU signature (i.e., when computing a baseline
> CPU model) we've been using a "shortest list of features" heuristics.
> This works well if new CPU models are supersets of older models, but
> that's not always the case. As a result it may actually select a new CPU
> model as a baseline while removing some features from it to make it
> compatible with older models. This is in general worse than using an old
> CPU model with a bunch of added features as a guest OS or apps may crash
> when using features that were disabled.
> 
> On the other hand we don't want to end up with a very old model which
> would guarantee no disabled features as it could stop a guest OS or apps
> from using some features provided by the CPU because they would not
> expect them on such an old CPU.
> 
> This patch changes the heuristics to something in between. Enabled and
> disabled features are counted separately so that a CPU model requiring
> some features to be disabled looks worse than a model with fewer
> disabled features even if its complete list of features is longer. The
> penalty given for each additional disabled feature gets bigger to make
> longer list of disabled features look even worse.
> 
> https://bugzilla.redhat.com/show_bug.cgi?id=1851227
> 
> Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
> ---
>  src/cpu/cpu_x86.c                             | 44 ++++++++++++++++---
>  .../x86_64-cpuid-Atom-D510-guest.xml          |  5 ++-
>  .../x86_64-cpuid-Atom-N450-guest.xml          |  5 ++-
>  .../x86_64-cpuid-Phenom-B95-json.xml          | 21 +++++----
>  ...id-baseline-Broadwell-IBRS+Cascadelake.xml | 11 +++--
>  ..._64-cpuid-baseline-Cascadelake+Icelake.xml | 13 +++---
>  ...puid-baseline-Cascadelake+Skylake-IBRS.xml |  5 ++-
>  ...6_64-cpuid-baseline-Cooperlake+Icelake.xml | 13 +++---
>  .../x86_64-host+guest,models-result.xml       | 10 +++--
>  .../domaincapsdata/qemu_3.1.0-tcg.x86_64.xml  | 35 +++++++++------
>  .../domaincapsdata/qemu_4.0.0-tcg.x86_64.xml  | 36 ++++++++-------
>  .../domaincapsdata/qemu_4.1.0-tcg.x86_64.xml  | 37 +++++++++-------
>  .../domaincapsdata/qemu_4.2.0-tcg.x86_64.xml  | 37 +++++++++-------
>  .../domaincapsdata/qemu_5.0.0-tcg.x86_64.xml  | 36 +++++++++------
>  .../domaincapsdata/qemu_5.1.0-tcg.x86_64.xml  | 36 +++++++++------
>  .../domaincapsdata/qemu_5.2.0-tcg.x86_64.xml  | 36 +++++++++------
>  .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml  | 36 +++++++++------
>  .../domaincapsdata/qemu_6.1.0-tcg.x86_64.xml  | 36 +++++++++------
>  .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml  | 36 +++++++++------
>  .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml  | 36 +++++++++------
>  tests/qemuxml2argvdata/cpu-fallback.args      |  2 +-
>  .../cpu-host-model-cmt.x86_64-4.0.0.args      |  2 +-
>  .../cpu-host-model-fallback.args              |  2 +-
>  23 files changed, 330 insertions(+), 200 deletions(-)
> 
> diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
> index fdee107ce9..3001fc2b8f 100644
> --- a/src/cpu/cpu_x86.c
> +++ b/src/cpu/cpu_x86.c
> @@ -1956,23 +1956,57 @@ virCPUx86Compare(virCPUDef *host,
>  }
>  
>  
> +/* Base penalty for disabled features. */
> +#define BASE_PENALTY 2
> +
>  static int
>  virCPUx86CompareCandidateFeatureList(virCPUDef *cpuCurrent,
>                                       virCPUDef *cpuCandidate)
>  {
>      size_t current = cpuCurrent->nfeatures;
> +    size_t enabledCurrent = current;
> +    size_t disabledCurrent = 0;
>      size_t candidate = cpuCandidate->nfeatures;
> +    size_t enabled = candidate;
> +    size_t disabled = 0;
> +
> +    if (cpuCandidate->type != VIR_CPU_TYPE_HOST) {
> +        size_t i;
> +        int penalty = BASE_PENALTY;
> +
> +        for (i = 0; i < enabledCurrent; i++) {
> +            if (cpuCurrent->features[i].policy == VIR_CPU_FEATURE_DISABLE) {
> +                enabledCurrent--;
> +                disabledCurrent += penalty;
> +                penalty++;
> +            }
> +        }
> +        current = enabledCurrent + disabledCurrent;
> +
> +        penalty = BASE_PENALTY;
> +        for (i = 0; i < enabled; i++) {
> +            if (cpuCandidate->features[i].policy == VIR_CPU_FEATURE_DISABLE) {
> +                enabled--;
> +                disabled += penalty;
> +                penalty++;
> +            }
> +        }
> +        candidate = enabled + disabled;
> +    }
>  
> -    if (candidate < current) {
> -        VIR_DEBUG("%s is better than %s: %zu < %zu",
> +    if (candidate < current ||
> +        (candidate == current && disabled < disabledCurrent)) {
> +        VIR_DEBUG("%s is better than %s: %zu (%zu, %zu) < %zu (%zu, %zu)",
>                    cpuCandidate->model, cpuCurrent->model,
> -                  candidate, current);
> +                  candidate, enabled, disabled,
> +                  current, enabledCurrent, disabledCurrent);
>          return 1;
>      }
>  
> -    VIR_DEBUG("%s is not better than %s: %zu >= %zu",
> +    VIR_DEBUG("%s is not better than %s: %zu (%zu, %zu) >= %zu (%zu, %zu)",
>                cpuCandidate->model, cpuCurrent->model,
> -              candidate, current);
> +              candidate, enabled, disabled,
> +              current, enabledCurrent, disabledCurrent);
>      return 0;


What a nice algorithm you have here :-)

Michal



More information about the libvir-list mailing list