[PATCH 2/2] whpx: i386: reintroduce enlightenments for Windows 10

Mohamed Mediouni posted 2 patches 1 week, 2 days ago
Maintainers: Pedro Barbuda <pbarbuda@microsoft.com>, Mohamed Mediouni <mohamed@unpredictable.fr>
[PATCH 2/2] whpx: i386: reintroduce enlightenments for Windows 10
Posted by Mohamed Mediouni 1 week, 2 days ago
Was removed in 2c08624 but it's still useful for
Windows 10 so reintroduce it there.

And this time, actually make it work by reporting
the hypervisor bit in CPUID.

Also pretend to be KVM, with the only capability
reported being X2APIC support.

Although looks like Linux doesn't use that vmware leaf...

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

diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index 5460207bdb..e4f297eec1 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -2071,15 +2071,45 @@ int whpx_vcpu_run(CPUState *cpu)
                 vcpu->exit_ctx.VpContext.Rip +
                 vcpu->exit_ctx.VpContext.InstructionLength;
 
-            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;
-
-            if (vcpu->exit_ctx.CpuidAccess.Rax == 1) {
-                if (cpu_has_x2apic_feature(env)) {
-                    reg_values[2].Reg64 |= CPUID_EXT_X2APIC;
+            if (whpx_is_legacy_os()) {
+                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;
+                switch (vcpu->exit_ctx.CpuidAccess.Rax) {
+                case 1:
+                    if (cpu_has_x2apic_feature(env)) {
+                        reg_values[2].Reg64 |= CPUID_EXT_X2APIC;
+                    }
+                    reg_values[2].Reg64 |= CPUID_EXT_HYPERVISOR;
+                    break;
+                case 0x40000000:
+                    /* report KVM */
+                    if (x86_cpu->vmware_cpuid_freq) {
+                        reg_values[1].Reg64 = 0x40000010;
+                    } else {
+                        reg_values[1].Reg64 = 0x40000001;
+                    }
+                    reg_values[4].Reg64 = 0x4b4d564b;
+                    reg_values[2].Reg64 = 0x564b4d56;
+                    reg_values[3].Reg64 = 0x4d;
+                    break;
+                case 0x40000001:
+                    /* report X2APIC */
+                    reg_values[1].Reg64 = reg_values[4].Reg64 = reg_values[2].Reg64 = 1 << 15;
+                    break;
+                case 0x40000010:
+                    if (x86_cpu->vmware_cpuid_freq) {
+                        reg_values[1].Reg64 = env->tsc_khz;
+                        reg_values[4].Reg64 = env->apic_bus_freq / 1000; /* Hz to KHz */
+                    }
+                    break;
                 }
+            } else {
+                cpu_x86_cpuid(env, vcpu->exit_ctx.CpuidAccess.Rax, 0, 
+                    (UINT32 *)&reg_values[1].Reg32,
+                    (UINT32 *)&reg_values[4].Reg32, (UINT32 *)&reg_values[2].Reg32,
+                    (UINT32 *)&reg_values[3].Reg32);
             }
 
             hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
@@ -2253,6 +2283,24 @@ int whpx_init_vcpu(CPUState *cpu)
         env->apic_bus_freq = 1000000000;
     }
 
+    /* Windows 10 doesn't provide Hyper-V enlightenments. */
+    if (whpx_is_legacy_os()) {
+         UINT32 cpuidExitList[] = {1, 0x40000000, 0x40000001, 0x40000010};
+
+         hr = whp_dispatch.WHvSetPartitionProperty(
+                 whpx->partition,
+                 WHvPartitionPropertyCodeCpuidExitList,
+                 cpuidExitList,
+                 RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32));
+
+         if (FAILED(hr)) {
+             error_report("WHPX: Failed to set partition CpuidExitList hr=%08lx",
+                         hr);
+             ret = -EINVAL;
+             goto error;
+         }
+     }
+
     vcpu->interruptable = true;
     cpu->vcpu_dirty = true;
     cpu->accel = vcpu;
-- 
2.50.1 (Apple Git-155)