From: Mohamed Mediouni <mohamed@unpredictable.fr>
To: qemu-devel@nongnu.org
Cc: Wei Liu <wei.liu@kernel.org>,
Roman Bolshakov <rbolshakov@ddn.com>,
Pedro Barbuda <pbarbuda@microsoft.com>,
Zhao Liu <zhao1.liu@intel.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Mohamed Mediouni <mohamed@unpredictable.fr>,
Phil Dennis-Jordan <phil@philjordan.eu>
Subject: [PATCH 3/4] whpx: i386: wire up feature probing
Date: Thu, 2 Apr 2026 07:33:25 +0200 [thread overview]
Message-ID: <20260402053326.23402-4-mohamed@unpredictable.fr> (raw)
In-Reply-To: <20260402053326.23402-1-mohamed@unpredictable.fr>
Windows 10 doesn't have the API for this, so using this
only for Windows 11.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
include/system/whpx-internal.h | 3 ++
target/i386/cpu.c | 25 ++++++++++++++
target/i386/whpx/whpx-all.c | 63 +++++++++++++++++++++++++++++++++-
target/i386/whpx/whpx-i386.h | 4 +++
4 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 target/i386/whpx/whpx-i386.h
diff --git a/include/system/whpx-internal.h b/include/system/whpx-internal.h
index 8482901f71..480d05fdca 100644
--- a/include/system/whpx-internal.h
+++ b/include/system/whpx-internal.h
@@ -89,6 +89,9 @@ void whpx_apic_get(APICCommonState *s);
UINT32 StateSize)) \
X(HRESULT, WHvResetPartition, \
(WHV_PARTITION_HANDLE Partition)) \
+ X(HRESULT, WHvGetVirtualProcessorCpuidOutput, \
+ (WHV_PARTITION_HANDLE Partition, UINT32 VpIndex, UINT32 Eax, \
+ UINT32 Ecx, WHV_CPUID_OUTPUT* CpuidOutput))
#define WHP_DEFINE_TYPE(return_type, function_name, signature) \
typedef return_type (WINAPI *function_name ## _t) signature;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index c6fd1dc00e..0000093fa3 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -26,6 +26,8 @@
#include "tcg/helper-tcg.h"
#include "exec/translation-block.h"
#include "system/hvf.h"
+#include "system/whpx.h"
+#include "whpx/whpx-i386.h"
#include "hvf/hvf-i386.h"
#include "kvm/kvm_i386.h"
#include "kvm/tdx.h"
@@ -8087,6 +8089,17 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w)
r = hvf_get_supported_cpuid(wi->cpuid.eax,
wi->cpuid.ecx,
wi->cpuid.reg);
+ } else if (whpx_enabled()) {
+ if (wi->type != CPUID_FEATURE_WORD) {
+ return 0;
+ }
+ if (whpx_is_legacy_os()) {
+ r = wi->tcg_features;
+ } else {
+ r = whpx_get_supported_cpuid(wi->cpuid.eax,
+ wi->cpuid.ecx,
+ wi->cpuid.reg);
+ }
} else if (tcg_enabled() || qtest_enabled()) {
r = wi->tcg_features;
} else {
@@ -8168,6 +8181,18 @@ static void x86_cpu_get_supported_cpuid(uint32_t func, uint32_t index,
*ebx = hvf_get_supported_cpuid(func, index, R_EBX);
*ecx = hvf_get_supported_cpuid(func, index, R_ECX);
*edx = hvf_get_supported_cpuid(func, index, R_EDX);
+ } else if (whpx_enabled()) {
+ if (whpx_is_legacy_os()) {
+ *eax = 0;
+ *ebx = 0;
+ *ecx = 0;
+ *edx = 0;
+ } else {
+ *eax = whpx_get_supported_cpuid(func, index, R_EAX);
+ *ebx = whpx_get_supported_cpuid(func, index, R_EBX);
+ *ecx = whpx_get_supported_cpuid(func, index, R_ECX);
+ *edx = whpx_get_supported_cpuid(func, index, R_EDX);
+ }
} else {
*eax = 0;
*ebx = 0;
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index f06474c31b..ad5ec3e700 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -36,6 +36,7 @@
#include "system/whpx-accel-ops.h"
#include "system/whpx-all.h"
#include "system/whpx-common.h"
+#include "whpx-i386.h"
#include "emulate/x86_decode.h"
#include "emulate/x86_emu.h"
@@ -49,6 +50,8 @@
/* for kernel-irqchip=off */
#define HV_X64_MSR_APIC_FREQUENCY 0x40000023
+bool is_legacy_os = false;
+
static const WHV_REGISTER_NAME whpx_register_names[] = {
/* X64 General purpose registers */
@@ -1062,6 +1065,65 @@ static void whpx_init_emu(void)
init_emu(&whpx_x86_emul_ops);
}
+bool whpx_is_legacy_os(void)
+{
+ return is_legacy_os;
+}
+
+uint32_t whpx_get_supported_cpuid(uint32_t func, uint32_t idx, int reg)
+{
+ WHV_CPUID_OUTPUT output;
+ uint32_t eax, ebx, ecx, edx;
+ uint32_t cpu_index = 0;
+ bool temp_cpu = true;
+ HRESULT hr;
+
+ hr = whp_dispatch.WHvCreateVirtualProcessor(
+ whpx_global.partition, cpu_index, 0);
+
+ /* This means that the CPU already exists... */
+ if (FAILED(hr)) {
+ temp_cpu = false;
+ }
+
+ hr = whp_dispatch.WHvGetVirtualProcessorCpuidOutput(whpx_global.partition,
+ cpu_index, func, idx, &output);
+
+ if (FAILED(hr)) {
+ abort();
+ }
+
+ if (temp_cpu) {
+ hr = whp_dispatch.WHvDeleteVirtualProcessor(whpx_global.partition, cpu_index);
+ if (FAILED(hr)) {
+ abort();
+ }
+ }
+
+ eax = output.Eax;
+ ebx = output.Ebx;
+ ecx = output.Ecx;
+ edx = output.Edx;
+
+ /* We can emulate X2APIC even for the kernel-irqchip=off case */
+ if (func == 1) {
+ ecx |= CPUID_EXT_X2APIC;
+ }
+
+ switch (reg) {
+ case R_EAX:
+ return eax;
+ case R_EBX:
+ return ebx;
+ case R_ECX:
+ return ecx;
+ case R_EDX:
+ return edx;
+ default:
+ return 0;
+ }
+}
+
/*
* Controls whether we should intercept various exceptions on the guest,
* namely breakpoint/single-step events.
@@ -2229,7 +2291,6 @@ 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;
- bool is_legacy_os = false;
UINT32 cpuidExitList[] = {1};
whpx = &whpx_global;
diff --git a/target/i386/whpx/whpx-i386.h b/target/i386/whpx/whpx-i386.h
new file mode 100644
index 0000000000..6db9a75d39
--- /dev/null
+++ b/target/i386/whpx/whpx-i386.h
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+uint32_t whpx_get_supported_cpuid(uint32_t func, uint32_t idx, int reg);
+bool whpx_is_legacy_os(void);
--
2.50.1 (Apple Git-155)
next prev parent reply other threads:[~2026-04-02 5:34 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-02 5:33 [PATCH 0/4] whpx: i386: x2apic emulation for kernel-irqchip=off, feature probing Mohamed Mediouni
2026-04-02 5:33 ` [PATCH 1/4] target/i386: emulate: include name of unhandled instruction Mohamed Mediouni
2026-04-02 5:33 ` [PATCH 2/4] whpx: i386: x2apic emulation Mohamed Mediouni
2026-04-02 5:33 ` Mohamed Mediouni [this message]
2026-04-02 5:33 ` [PATCH 4/4] whpx: i386: disable TbFlushHypercalls for emulated LAPIC Mohamed Mediouni
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260402053326.23402-4-mohamed@unpredictable.fr \
--to=mohamed@unpredictable.fr \
--cc=pbarbuda@microsoft.com \
--cc=pbonzini@redhat.com \
--cc=phil@philjordan.eu \
--cc=qemu-devel@nongnu.org \
--cc=rbolshakov@ddn.com \
--cc=wei.liu@kernel.org \
--cc=zhao1.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.