@samitouri / QOSamiQemu / commits / f741457c1a

whpx: i386: reintroduce enlightenments for Windows 10

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. Pretend to be vmware to be able to use vmport's functionality. If the vmware frequency leaf is disabled, pretend to be KVM, with the only capability reported being X2APIC support. Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Link: https://lore.kernel.org/r/20260422214225.2242-7-mohamed@unpredictable.fr Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Mohamed Mediouni committed Apr 22, 2026 at 23:41 UTC f741457c1a179a066943f54570eed784e2510c92
4 files changed +58 -9
accel/whpx/whpx-common.c
+2
@@ -550,6 +550,8 @@ static void whpx_accel_instance_init(Object *obj)
550
551 whpx->hyperv_enlightenments_allowed = true;
552 whpx->hyperv_enlightenments_required = false;
553 + /* Value determined at whpx_accel_init */
554 + whpx->hyperv_enlightenments_enabled = false;
555 }
556
557 static const TypeInfo whpx_accel_type = {
include/system/whpx-internal.h
+1
@@ -45,6 +45,7 @@ struct whpx_state {
45
46 bool hyperv_enlightenments_allowed;
47 bool hyperv_enlightenments_required;
48 + bool hyperv_enlightenments_enabled;
49
50 };
51
target/arm/whpx/whpx-all.c
+1
@@ -968,6 +968,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
968 * as they're not needed for performance.
969 */
970 if (whpx->hyperv_enlightenments_required) {
971 + whpx->hyperv_enlightenments_enabled = true;
972 hr = whp_dispatch.WHvSetPartitionProperty(
973 whpx->partition,
974 WHvPartitionPropertyCodeSyntheticProcessorFeaturesBanks,
target/i386/whpx/whpx-all.c
+54 -9
@@ -2168,14 +2168,57 @@ int whpx_vcpu_run(CPUState *cpu)
2168 vcpu->exit_ctx.VpContext.Rip +
2169 vcpu->exit_ctx.VpContext.InstructionLength;
2170
2171 - reg_values[1].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRax;
2172 - reg_values[2].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRcx;
2173 - reg_values[3].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx;
2174 - reg_values[4].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx;
2175 -
2176 - if (vcpu->exit_ctx.CpuidAccess.Rax == 1) {
2177 - if (cpu_has_x2apic_feature(env)) {
2178 - reg_values[2].Reg64 |= CPUID_EXT_X2APIC;
2171 + if (whpx_is_legacy_os()) {
2172 + reg_values[1].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRax;
2173 + reg_values[2].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRcx;
2174 + reg_values[3].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx;
2175 + reg_values[4].Reg64 = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx;
2176 + } else {
2177 + cpu_x86_cpuid(env, vcpu->exit_ctx.CpuidAccess.Rax,
2178 + vcpu->exit_ctx.CpuidAccess.Rcx,
2179 + (UINT32 *)&reg_values[1].Reg32,
2180 + (UINT32 *)&reg_values[4].Reg32, (UINT32 *)&reg_values[2].Reg32,
2181 + (UINT32 *)&reg_values[3].Reg32);
2182 + }
2183 +
2184 + if (!whpx->hyperv_enlightenments_enabled) {
2185 + switch (vcpu->exit_ctx.CpuidAccess.Rax) {
2186 + case 1:
2187 + reg_values[2].Reg64 |= CPUID_EXT_HYPERVISOR;
2188 + break;
2189 + case 0x40000000:
2190 + /*
2191 + * Use vmware_cpuid_freq as a proxy to report VMware.
2192 + * This is to get the TSC/APIC frequency query functionality
2193 + * provided through vmport, as Linux doesn't use leaf
2194 + * 0x40000010 for getting those frequencies.
2195 + */
2196 + if (x86_cpu->vmware_cpuid_freq) {
2197 + reg_values[1].Reg64 = 0x40000010;
2198 + reg_values[4].Reg64 = 0x61774d56;
2199 + reg_values[2].Reg64 = 0x4d566572;
2200 + reg_values[3].Reg64 = 0x65726177;
2201 + } else {
2202 + /* report KVM otherwise if that's disabled */
2203 + reg_values[1].Reg64 = 0x40000001;
2204 + reg_values[4].Reg64 = 0x4b4d564b;
2205 + reg_values[2].Reg64 = 0x564b4d56;
2206 + reg_values[3].Reg64 = 0x4d;
2207 + }
2208 + break;
2209 + case 0x40000001:
2210 + if (!x86_cpu->vmware_cpuid_freq) {
2211 + /* KVM reporting of X2APIC support */
2212 + reg_values[1].Reg64 = reg_values[4].Reg64 =
2213 + reg_values[2].Reg64 = 1 << 15;
2214 + }
2215 + break;
2216 + case 0x40000010:
2217 + if (x86_cpu->vmware_cpuid_freq) {
2218 + reg_values[1].Reg64 = env->tsc_khz;
2219 + reg_values[4].Reg64 = env->apic_bus_freq / 1000; /* Hz to KHz */
2220 + }
2221 + break;
2222 }
2223 }
2224
@@ -2396,6 +2439,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
2439 WHV_PROCESSOR_FEATURES_BANKS processor_features;
2440 WHV_PROCESSOR_PERFMON_FEATURES perfmon_features;
2441 UINT32 cpuidExitList[] = {1};
2442 + UINT32 cpuidExitList_nohyperv[] = {1, 0x40000000, 0x40000001, 0x40000010};
2443
2444 whpx = &whpx_global;
2445
@@ -2601,6 +2645,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
2645 }
2646
2647 if (is_modern_os && whpx->hyperv_enlightenments_allowed) {
2648 + whpx->hyperv_enlightenments_enabled = true;
2649 hr = whp_dispatch.WHvSetPartitionProperty(
2650 whpx->partition,
2651 WHvPartitionPropertyCodeSyntheticProcessorFeaturesBanks,
@@ -2653,7 +2698,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
2698 hr = whp_dispatch.WHvSetPartitionProperty(
2699 whpx->partition,
2700 WHvPartitionPropertyCodeCpuidExitList,
2656 - cpuidExitList,
2701 + whpx->hyperv_enlightenments_enabled ? cpuidExitList : cpuidExitList_nohyperv,
2702 RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32));
2703
2704 if (FAILED(hr)) {