On Tue, Apr 29, 2025 at 12:19:50 +0200, Jiri Denemark via Devel wrote: > From: Jiri Denemark <jdene...@redhat.com> > > This patch is effectively a NOP, but it fixes a logic bug and makes the > heuristics more visible and easier to change should there be a need to > do so in the future. > > We decide which CPU model is the best match for given CPU data by > comparing lists of features that need to be enabled/disabled on top of > the selected CPU model. Since the original approach of using just the > total number of features was not working well enough, commit > v8.3.0-42-g48341b025a implemented a penalty for disabled features which > would increase for each additional disabled features. Apparently the > intention was weighting disabled features as > > disabled * (disabled + 3) > weightDisabled = ------------------------- > 2 > > and complete CPU model as > > weight = enabled + weightDisabled > > But there was a bug in the code which caused it to ignore some of the > features and counted as enabled regardless on their policy. Instead of > going through all features the code used the number of "enabled" > features (the variable was not really counting number of enabled > features though) which was initialized to the total number of features > and decremented each time a disabled features was found. Thus depending > on the number of disabled features, some features at the end of the list > were ignored. Luckily we know all the ignored features had to be > disabled because the CPU definitions were created by x86DataToCPU which > constructs a list of enabled features followed by disabled features. > > So to fix the bug while providing the same results we can come up with > an equivalent formula using properly counted features in the CPU > definition. > > The number of disabled features counted by the buggy code is > > half = (disabled + 1) div 2 > > and the weight of all disabled features is > > half * (half + 3) > weightDisabled = ----------------- > 2 > > When computing the total weight, we can't no longer use number of > enabled features because the original code counted some of the disabled > features as enabled. So to match the old behavior, we count the total > weight as > > weight = features - half + weightDisabled > > The weight of enabled features now differs from the value computed by > the old code, but we don't need to worry about it as it's not really > used anywhere except for logging. > > Fixes: https://gitlab.com/libvirt/libvirt/-/issues/759 > Signed-off-by: Jiri Denemark <jdene...@redhat.com> > --- > src/cpu/cpu_x86.c | 18 +++++++----------- > 1 file changed, 7 insertions(+), 11 deletions(-) > > diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c > index b0fe2bed4c..213af67ea4 100644 > --- a/src/cpu/cpu_x86.c > +++ b/src/cpu/cpu_x86.c > @@ -2087,9 +2087,6 @@ virCPUx86Compare(virCPUDef *host, > } > > > -/* Base penalty for disabled features. */ > -#define BASE_PENALTY 2 > - > struct virCPUx86Weight { > size_t total; > size_t enabled; > @@ -2100,26 +2097,25 @@ static void > virCPUx86WeightFeatures(const virCPUDef *cpu, > struct virCPUx86Weight *weight) > { > - int penalty = BASE_PENALTY; > size_t i; > + size_t half; /* half of disabled features rounded up */ > > weight->enabled = cpu->nfeatures; > - weight->disabled = 0; > > if (cpu->type == VIR_CPU_TYPE_HOST) { > + weight->disabled = 0; > weight->total = cpu->nfeatures; > return; > } > > - for (i = 0; i < weight->enabled; i++) { > - if (cpu->features[i].policy == VIR_CPU_FEATURE_DISABLE) { > + for (i = 0; i < cpu->nfeatures; i++) { > + if (cpu->features[i].policy == VIR_CPU_FEATURE_DISABLE) > weight->enabled--; > - weight->disabled += penalty; > - penalty++; > - }
Okay I know why the code didn't make sense in the refactor :D > } > > - weight->total = weight->enabled + weight->disabled; > + half = (cpu->nfeatures - weight->enabled + 1) / 2; > + weight->disabled = half * (half + 3) / 2; > + weight->total = cpu->nfeatures - half + weight->disabled; This looks like an excercise in reading C operator precedence :P > } > > > -- > 2.49.0 > Reviewed-by: Peter Krempa <pkre...@redhat.com>