On Thu, Jul 02, 2026 at 02:53:09PM +0200, Magnus Kulke wrote: > In the current implementation there are subtle bugs that have to do with > the termination of subleaves, resulting in features reported on the > guest that it should not have according to the model. > > If a guest model has fewer valid subleaves stopping too early leaves > unspecified gaps that are filled by the host, resulting in potentially > invalid feature combinations, for example: > > The host reports features: > > CPUID[EAX=01H].ECX.AVX [bit 28] and > CPUID[EAX=07H,ECX=01H].EAX.AVX_VNNI [bit 4] > > In the current implementation we would skip over 7.1 completely, not > registering CPUID responses for the subleaf, resulting in a guest with > qemu64 model (which does not feature AVX), reporting AVX_VNNI as > available (passthrough from host). > > We need to walk through the max subleaves of leaf 7 and register them > explicitly (also if they're 0). > > A second bug was about the propagation of "terminator" subleaves, > all-zero responses that signal the end. We also want to register this > terminator response , so the guest stops enumerating. In the current > implementation we weren't doing that. > > Fixes: 4fa04dd1621 > Signed-off-by: Magnus Kulke <[email protected]> > --- > target/i386/mshv/mshv-cpu.c | 21 +++++++++++++++++++-- > 1 file changed, 19 insertions(+), 2 deletions(-) > > diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c > index 126ca40b48..a3b5f4474f 100644 > --- a/target/i386/mshv/mshv-cpu.c > +++ b/target/i386/mshv/mshv-cpu.c > @@ -997,7 +997,7 @@ static void collect_cpuid_entries(const CPUState *cpu, > GList **cpuid_entries) > CPUX86State *env = &x86_cpu->env; > uint32_t eax, ebx, ecx, edx; > uint32_t leaf, subleaf; > - uint32_t max_basic_leaf, max_extended_leaf; > + uint32_t max_basic_leaf, max_extended_leaf, max_subleaf_7; > uint32_t max_subleaf = 0x20; > uint32_t leaves_with_subleaves[] = {0x04, 0x07, 0x0d, 0x0f, 0x10}; > int n_subleaf_leaves = ARRAY_SIZE(leaves_with_subleaves); > @@ -1035,14 +1035,31 @@ static void collect_cpuid_entries(const CPUState > *cpu, GList **cpuid_entries) > continue; > } > > + /* > + * Valid subleaves for are reported in 7.0:EAX. We need to register > all
I think there's an additional "for" word above. Reviewed-by: Doru Blânzeanu <[email protected]> > + * subleaves to the maximum subleaf, even if they are 0. Otherwise > the > + * host will supply its own values for a unregistered subleaf, which > + * can result in an inconsistent feature set. > + */ > + if (leaf == 0x07) { > + cpu_x86_cpuid(env, leaf, 0, &max_subleaf_7, &ebx, &ecx, &edx); > + for (subleaf = 0; subleaf <= max_subleaf_7; subleaf++) { > + cpu_x86_cpuid(env, leaf, subleaf, &eax, &ebx, &ecx, &edx); > + add_cpuid_entry(cpuid_entries, leaf, subleaf, > + eax, ebx, ecx, edx); > + } > + continue; > + } > + > subleaf = 0; > while (subleaf < max_subleaf) { > cpu_x86_cpuid(env, leaf, subleaf, &eax, &ebx, &ecx, &edx); > > + /* register the "terminator" to the guest, before breaking */ > + add_cpuid_entry(cpuid_entries, leaf, subleaf, eax, ebx, ecx, > edx); > if (eax == 0 && ebx == 0 && ecx == 0 && edx == 0) { > break; > } > - add_cpuid_entry(cpuid_entries, leaf, subleaf, eax, ebx, ecx, > edx); > subleaf++; > } > } > -- > 2.34.1
