whpx: i386: workaround for Windows 10 support
Windows Server 2022 and later support WHvCapabilityCodeProcessorPerfmonFeatures and WHvPartitionPropertyCodeSyntheticProcessorFeaturesBanks. Windows 10 supports neither of those. As the QEMU executable doesn't have a manifest, OS version queries do not return the actual Windows version but 6.2.9200 which corresponds to Windows 8. Windows Server 2022 and Windows 11 still use the 10.0 number, with distinction being the build number. As such, use the absence of perf monitoring feature query as a cutoff to detect if a legacy OS is present. Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Link: https://lore.kernel.org/r/20260324151323.74473-2-mohamed@unpredictable.fr Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Mohamed Mediouni committed
Mar 24, 2026 at 16:13 UTC
68438cb3cbcb298af63383a7d537e6610daf96a3
1 file changed
+28
-15
target/i386/whpx/whpx-all.c
+28
-15
@@ -1948,6 +1948,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
1948
WHV_CAPABILITY_FEATURES features = {0};
1949
WHV_PROCESSOR_FEATURES_BANKS processor_features;
1950
WHV_PROCESSOR_PERFMON_FEATURES perfmon_features;
1951
+ bool is_legacy_os = false;
1952
1953
whpx = &whpx_global;
1954
@@ -2096,21 +2097,29 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
2097
hr = whp_dispatch.WHvGetCapability(
2098
WHvCapabilityCodeProcessorPerfmonFeatures, &perfmon_features,
2099
sizeof(WHV_PROCESSOR_PERFMON_FEATURES), &whpx_cap_size);
2100
+ /*
2101
+ * Relying on this is a crutch to maintain Windows 10 support.
2102
+ *
2103
+ * WHvCapabilityCodeProcessorPerfmonFeatures and
2104
+ * WHvPartitionPropertyCodeSyntheticProcessorFeaturesBanks
2105
+ * are implemented starting from Windows Server 2022 (build 20348).
2106
+ */
2107
if (FAILED(hr)) {
2100
- error_report("WHPX: Failed to get performance monitoring features, hr=%08lx", hr);
2101
- ret = -ENOSPC;
2102
- goto error;
2103
- }
2104
-
2105
- hr = whp_dispatch.WHvSetPartitionProperty(
2106
- whpx->partition,
2107
- WHvPartitionPropertyCodeProcessorPerfmonFeatures,
2108
- &perfmon_features,
2109
- sizeof(WHV_PROCESSOR_PERFMON_FEATURES));
2110
- if (FAILED(hr)) {
2111
- error_report("WHPX: Failed to set performance monitoring features, hr=%08lx", hr);
2112
- ret = -EINVAL;
2113
- goto error;
2108
+ warn_report("WHPX: Failed to get performance "
2109
+ "monitoring features, hr=%08lx", hr);
2110
+ is_legacy_os = true;
2111
+ } else {
2112
+ hr = whp_dispatch.WHvSetPartitionProperty(
2113
+ whpx->partition,
2114
+ WHvPartitionPropertyCodeProcessorPerfmonFeatures,
2115
+ &perfmon_features,
2116
+ sizeof(WHV_PROCESSOR_PERFMON_FEATURES));
2117
+ if (FAILED(hr)) {
2118
+ error_report("WHPX: Failed to set performance "
2119
+ "monitoring features, hr=%08lx", hr);
2120
+ ret = -EINVAL;
2121
+ goto error;
2122
+ }
2123
}
2124
2125
/* Enable synthetic processor features */
@@ -2138,7 +2147,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
2147
synthetic_features.Bank0.DirectSyntheticTimers = 1;
2148
}
2149
2141
- if (whpx->hyperv_enlightenments_allowed) {
2150
+ if (!is_legacy_os && whpx->hyperv_enlightenments_allowed) {
2151
hr = whp_dispatch.WHvSetPartitionProperty(
2152
whpx->partition,
2153
WHvPartitionPropertyCodeSyntheticProcessorFeaturesBanks,
@@ -2149,6 +2158,10 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
2158
ret = -EINVAL;
2159
goto error;
2160
}
2161
+ } else if (is_legacy_os && whpx->hyperv_enlightenments_required) {
2162
+ error_report("Hyper-V enlightenments not available on legacy Windows");
2163
+ ret = -EINVAL;
2164
+ goto error;
2165
}
2166
2167
/* Register for MSR and CPUID exits */