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

Reply via email to