[PATCH v6 07/11] whpx: i386: introduce proper cpuid support

Mohamed Mediouni posted 11 patches 1 week ago
Maintainers: Pedro Barbuda <pbarbuda@microsoft.com>, Mohamed Mediouni <mohamed@unpredictable.fr>, Peter Maydell <peter.maydell@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>, Zhao Liu <zhao1.liu@intel.com>, Roman Bolshakov <rbolshakov@ddn.com>, Phil Dennis-Jordan <phil@philjordan.eu>, Wei Liu <wei.liu@kernel.org>
There is a newer version of this series
[PATCH v6 07/11] whpx: i386: introduce proper cpuid support
Posted by Mohamed Mediouni 1 week ago
Unlike the implementation in QEMU 10.2, this one works.

It's not optimal though as it doesn't use the Hyper-V support for this.

Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
 target/i386/whpx/whpx-all.c | 39 ++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index 03233d1b94..3e006496be 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -2127,6 +2127,35 @@ int whpx_vcpu_run(CPUState *cpu)
                     }
                     break;
                 }
+            } else {
+                switch (vcpu->exit_ctx.CpuidAccess.Rax) {
+                case 0x40000000:
+                case 0x40000001:
+                case 0x40000010:
+                    reg_values[1].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRax;
+                    reg_values[2].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRcx;
+                    reg_values[3].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx;
+                    reg_values[4].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx;
+                    break;
+                }
+            }
+
+            /* Dynamic depending on XCR0 and XSS, so query DefaultResult */
+            if (vcpu->exit_ctx.CpuidAccess.Rax == 0x07
+                && vcpu->exit_ctx.CpuidAccess.Rcx == 0) {
+                if (vcpu->exit_ctx.CpuidAccess.DefaultResultRdx
+                    & CPUID_7_0_EDX_CET_IBT) {
+                    reg_values[3].Reg32 |= CPUID_7_0_EDX_CET_IBT;
+                } else {
+                    reg_values[3].Reg32 &= ~CPUID_7_0_EDX_CET_IBT;
+                }
+
+                if (vcpu->exit_ctx.CpuidAccess.DefaultResultRcx
+                    & CPUID_7_0_ECX_CET_SHSTK) {
+                    reg_values[2].Reg32 |= CPUID_7_0_ECX_CET_SHSTK;
+                } else {
+                    reg_values[2].Reg32 &= ~CPUID_7_0_ECX_CET_SHSTK;
+                }
             }
 
             hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
@@ -2345,8 +2374,12 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
     WHV_CAPABILITY_FEATURES features = {0};
     WHV_PROCESSOR_FEATURES_BANKS processor_features;
     WHV_PROCESSOR_PERFMON_FEATURES perfmon_features;
-    UINT32 cpuidExitList[] = {1};
-    UINT32 cpuidExitList_nohyperv[] = {1, 0x40000000, 0x40000001, 0x40000010};
+
+    UINT32 cpuidExitList[] = {0x0, 0x1, 0x6, 0x7, 0x14, 0x24, 0x29, 0x1E,
+        0x40000000, 0x40000001, 0x40000010, 0x80000000, 0x80000001,
+        0x80000002, 0x80000003, 0x80000004, 0x80000007, 0x80000008,
+        0x8000000A, 0x80000021, 0x80000022, 0xC0000000, 0xC0000001};
+    UINT32 cpuidExitList_legacy_os[] = {1, 0x40000000, 0x40000001, 0x40000010};
 
     whpx = &whpx_global;
 
@@ -2602,7 +2635,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
     hr = whp_dispatch.WHvSetPartitionProperty(
         whpx->partition,
         WHvPartitionPropertyCodeCpuidExitList,
-        whpx->hyperv_enlightenments_enabled ? cpuidExitList : cpuidExitList_nohyperv,
+        !whpx_is_legacy_os() ? cpuidExitList : cpuidExitList_legacy_os,
         RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32));
 
     if (FAILED(hr)) {
-- 
2.50.1 (Apple Git-155)
Re: [PATCH v6 07/11] whpx: i386: introduce proper cpuid support
Posted by Mohamed Mediouni 1 week ago

> On 4. Apr 2026, at 06:20, Mohamed Mediouni <mohamed@unpredictable.fr> wrote:
> 
> Unlike the implementation in QEMU 10.2, this one works.
> 
> It's not optimal though as it doesn't use the Hyper-V support for this.
> 
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> target/i386/whpx/whpx-all.c | 39 ++++++++++++++++++++++++++++++++++---
> 1 file changed, 36 insertions(+), 3 deletions(-)
> 
> diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
> index 03233d1b94..3e006496be 100644
> --- a/target/i386/whpx/whpx-all.c
> +++ b/target/i386/whpx/whpx-all.c
> @@ -2127,6 +2127,35 @@ int whpx_vcpu_run(CPUState *cpu)
>                     }
>                     break;
>                 }
> +            } else {
> +                switch (vcpu->exit_ctx.CpuidAccess.Rax) {
> +                case 0x40000000:
> +                case 0x40000001:
> +                case 0x40000010:
> +                    reg_values[1].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRax;
> +                    reg_values[2].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRcx;
> +                    reg_values[3].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx;
> +                    reg_values[4].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx;
> +                    break;
> +                }
> +            }
> +
> +            /* Dynamic depending on XCR0 and XSS, so query DefaultResult */
> +            if (vcpu->exit_ctx.CpuidAccess.Rax == 0x07
> +                && vcpu->exit_ctx.CpuidAccess.Rcx == 0) {
> +                if (vcpu->exit_ctx.CpuidAccess.DefaultResultRdx
> +                    & CPUID_7_0_EDX_CET_IBT) {
> +                    reg_values[3].Reg32 |= CPUID_7_0_EDX_CET_IBT;
> +                } else {
> +                    reg_values[3].Reg32 &= ~CPUID_7_0_EDX_CET_IBT;
> +                }
> +
> +                if (vcpu->exit_ctx.CpuidAccess.DefaultResultRcx
> +                    & CPUID_7_0_ECX_CET_SHSTK) {
> +                    reg_values[2].Reg32 |= CPUID_7_0_ECX_CET_SHSTK;
> +                } else {
> +                    reg_values[2].Reg32 &= ~CPUID_7_0_ECX_CET_SHSTK;
> +                }

Hello,

To not send yet another revision again (if no further revision
needed, can be squashed with this when the time comes):

From: Mohamed Mediouni <mohamed@unpredictable.fr>
Date: Sat, 4 Apr 2026 07:00:42 +0200
Subject: [PATCH] whpx: i386: fix osxsave

OSXSAVE is dynamic and relies on the state of CR4.
Instead of reading CR4, falling back on the default
CPUID results provided by the hypervisor.

Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
 target/i386/whpx/whpx-all.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index ac2671745f..71cc3e0991 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -2149,6 +2149,16 @@ int whpx_vcpu_run(CPUState *cpu)
                 }
             }
 
+            /* OSXSAVE is dynamic. Do this instead of syncing CR4 */
+            if (vcpu->exit_ctx.CpuidAccess.Rax == 1) {
+                if (vcpu->exit_ctx.CpuidAccess.DefaultResultRcx
+                    & CPUID_EXT_OSXSAVE) {
+                    reg_values[2].Reg32 |= CPUID_EXT_OSXSAVE;
+                } else {
+                    reg_values[2].Reg32 &= ~CPUID_EXT_OSXSAVE;
+                }
+            }
+
             hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
                 whpx->partition,
                 cpu->cpu_index,
-- 
2.50.1 (Apple Git-155)