* [PATCH v3 00/14] whpx: x86 updates (2026-02)
@ 2026-02-15 5:22 Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 01/14] target/i386/emulate/x86_decode: Fix compiler warning Mohamed Mediouni
` (13 more replies)
0 siblings, 14 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
x86_64 WHPX updates:
- target/i386/emulate fixes
- move HVF x86_mmu code to common code
- fixing debug support, which was broken since around: "gdbstub: move guest debug support check to ops"
a48e7d9e52f8fe8b47f4c74f3e99d9d677b87fe5
- switch over from winhvemulation to common x86 VM exit emulation code
- remove some log lines
- Remove WHPX CPUID traps as they're currently quite broken
Changes added since v2:
- Take target/i386/emulate patches from Bernhard Beschow
https://lore.kernel.org/qemu-devel/20260214131659.31378-1-shentey@gmail.com/
- Rework state levels to an enum
- Skip some state loading on the registers save path too
Changes added since v1:
- move HVF x86_mmu code to common code
- Use x86_mmu in WHPX MMIO exits
- Remove WHPX CPUID traps as they're currently quite broken
- Optimise MMIO vmexits by not restoring the full state
Bernhard Beschow (3):
target/i386/emulate/x86_decode: Fix compiler warning
target/i386/hvf/x86_mmu: Fix compiler warning
target/i386/emulate/x86_decode: Actually use stream in
decode_instruction_stream()
Mohamed Mediouni (11):
target/i386: emulate, hvf: move x86_mmu to common code
whpx: i386: re-enable guest debug support
whpx: preparatory changes before switching over from winhvemulation
whpx: refactor whpx_destroy_vcpu to arch-specific function
whpx: move whpx_get_reg/whpx_set_reg to generic code
whpx: i386: switch over from winhvemulation to target/i386/emulate
whpx: i386: remove remaining winhvemulation support code
whpx: i386: remove messages
whpx: i386: remove CPUID trapping
whpx: common, i386, arm: rework state levels
whpx: i386: saving/restoring less state for
WHPX_LEVEL_FAST_RUNTIME_STATE
accel/whpx/whpx-accel-ops.c | 8 +
accel/whpx/whpx-common.c | 68 +++--
include/system/whpx-accel-ops.h | 16 +-
include/system/whpx-all.h | 11 +-
include/system/whpx-common.h | 6 +-
include/system/whpx-internal.h | 16 -
meson.build | 3 +-
target/arm/whpx/whpx-all.c | 41 +--
target/i386/cpu.h | 2 +-
target/i386/emulate/meson.build | 2 +
target/i386/emulate/x86_decode.c | 6 +-
target/i386/{hvf => emulate}/x86_mmu.c | 20 +-
target/i386/{hvf => emulate}/x86_mmu.h | 0
target/i386/hvf/hvf.c | 10 +-
target/i386/hvf/meson.build | 1 -
target/i386/hvf/x86.c | 2 +-
target/i386/hvf/x86_task.c | 2 +-
target/i386/mshv/meson.build | 4 +
target/i386/whpx/whpx-all.c | 391 +++++++++----------------
19 files changed, 253 insertions(+), 356 deletions(-)
rename target/i386/{hvf => emulate}/x86_mmu.c (92%)
rename target/i386/{hvf => emulate}/x86_mmu.h (100%)
--
2.50.1 (Apple Git-155)
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 01/14] target/i386/emulate/x86_decode: Fix compiler warning
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 02/14] target/i386/hvf/x86_mmu: " Mohamed Mediouni
` (12 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
From: Bernhard Beschow <shentey@gmail.com>
When compiling for i386-softmmu under MSYS2, GCC emits the following warning:
In function 'get_reg_val',
inlined from 'calc_modrm_operand64' at ../src/target/i386/emulate/x86_decode.c:1796:15:
../src/target/i386/emulate/x86_decode.c:1703:5: error: 'memcpy' forming offset [4, 7] is out of the bounds [0, 4] of object 'val' with type 'target_ulong' {aka 'unsigned int'} [-Werror=array-bounds=]
1703 | memcpy(&val,
| ^~~~~~~~~~~~
1704 | get_reg_ref(env, reg, rex_present, is_extended, size),
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1705 | size);
| ~~~~~
../src/target/i386/emulate/x86_decode.c: In function 'calc_modrm_operand64':
../src/target/i386/emulate/x86_decode.c:1702:18: note: 'val' declared here
1702 | target_ulong val = 0;
| ^~~
In the calc_modrm_operand64() case the compiler sees size == 8 to be mem-copied
to a target_ulong variable which is only 4 bytes wide in case of i386-softmmu.
Note that when size != 1, get_reg_ref() always returns a pointer to an 8 byte
register, regardless of the target_ulong size. Fix the compiler warning by
always providing 8 bytes of storage by means of uint64_t.
Fixes: 77a2dba45cc9 ("target/i386/emulate: stop overloading decode->op[N].ptr")
cc: qemu-stable
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
target/i386/emulate/x86_decode.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/i386/emulate/x86_decode.c b/target/i386/emulate/x86_decode.c
index d037ed1142..6ad03b71b0 100644
--- a/target/i386/emulate/x86_decode.c
+++ b/target/i386/emulate/x86_decode.c
@@ -1699,7 +1699,7 @@ void *get_reg_ref(CPUX86State *env, int reg, int rex_present,
target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present,
int is_extended, int size)
{
- target_ulong val = 0;
+ uint64_t val = 0;
memcpy(&val,
get_reg_ref(env, reg, rex_present, is_extended, size),
size);
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 02/14] target/i386/hvf/x86_mmu: Fix compiler warning
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 01/14] target/i386/emulate/x86_decode: Fix compiler warning Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 03/14] target/i386/emulate/x86_decode: Actually use stream in decode_instruction_stream() Mohamed Mediouni
` (11 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
From: Bernhard Beschow <shentey@gmail.com>
When reusing the code in WHPX, GCC emits the following warning when compiling
for i386-softmmu under MSYS2:
In file included from ../src/target/i386/emulate/x86_mmu.c:20:
../src/target/i386/emulate/x86_mmu.c: In function 'vmx_write_mem':
../src/target/i386/emulate/x86_mmu.c:251:25: error: format '%llx' expects argument of type 'long long unsigned int', but argument 3 has type 'target_ulong' {aka 'unsigned int'} [-Werror=format=]
251 | VM_PANIC_EX("%s: mmu_gva_to_gpa %llx failed\n", __func__, gva);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~
| |
| target_ulong {aka unsigned int}
../src/target/i386/emulate/panic.h:34:12: note: in definition of macro 'VM_PANIC_EX'
34 | printf(__VA_ARGS__); \
| ^~~~~~~~~~~
../src/target/i386/emulate/x86_mmu.c:251:48: note: format string is defined here
251 | VM_PANIC_EX("%s: mmu_gva_to_gpa %llx failed\n", __func__, gva);
| ~~~^
| |
| long long unsigned int
| %x
Fix the warning by reusing the target-specific macro TARGET_FMT_lx which exists
for this exact purpose.
Fixes: c97d6d2cdf97 ("i386: hvf: add code base from Google's QEMU repository")
cc: qemu-stable
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Mohamed Mediouni <mohamed@unpredictable.fr>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
target/i386/hvf/x86_mmu.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/target/i386/hvf/x86_mmu.c b/target/i386/hvf/x86_mmu.c
index afc5c17d5d..fe44d2edf4 100644
--- a/target/i386/hvf/x86_mmu.c
+++ b/target/i386/hvf/x86_mmu.c
@@ -244,7 +244,8 @@ void vmx_write_mem(CPUState *cpu, target_ulong gva, void *data, int bytes)
int copy = MIN(bytes, 0x1000 - (gva & 0xfff));
if (!mmu_gva_to_gpa(cpu, gva, &gpa)) {
- VM_PANIC_EX("%s: mmu_gva_to_gpa %llx failed\n", __func__, gva);
+ VM_PANIC_EX("%s: mmu_gva_to_gpa " TARGET_FMT_lx " failed\n",
+ __func__, gva);
} else {
address_space_write(&address_space_memory, gpa,
MEMTXATTRS_UNSPECIFIED, data, copy);
@@ -265,7 +266,8 @@ void vmx_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
int copy = MIN(bytes, 0x1000 - (gva & 0xfff));
if (!mmu_gva_to_gpa(cpu, gva, &gpa)) {
- VM_PANIC_EX("%s: mmu_gva_to_gpa %llx failed\n", __func__, gva);
+ VM_PANIC_EX("%s: mmu_gva_to_gpa " TARGET_FMT_lx " failed\n",
+ __func__, gva);
}
address_space_read(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED,
data, copy);
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 03/14] target/i386/emulate/x86_decode: Actually use stream in decode_instruction_stream()
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 01/14] target/i386/emulate/x86_decode: Fix compiler warning Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 02/14] target/i386/hvf/x86_mmu: " Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-16 11:23 ` Magnus Kulke
2026-02-15 5:22 ` [PATCH v3 04/14] target/i386: emulate, hvf: move x86_mmu to common code Mohamed Mediouni
` (10 subsequent siblings)
13 siblings, 1 reply; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
From: Bernhard Beschow <shentey@gmail.com>
Compared to decode_instruction(), decode_instruction_stream() has an additional
stream parameter which avoids some guest memory accesses during instruction
decoding. Both functions defer the actual work to decode_opcode() which would
set the stream pointer to zero such that decode_instruction_stream() essentially
behaved like decode_instruction(). Given that all callers of
decode_instruction_stream() properly zero-initialize the decode parameter, the
memset() call can be moved into decode_instruction() which is the only other
user of decode_opcode(). This preserves the non-zero stream pointer which
avoids extra guest memory accesses.
Fixes: 1e25327b244a ("target/i386/emulate: Allow instruction decoding from stream")
cc: qemu-stable
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
target/i386/emulate/x86_decode.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target/i386/emulate/x86_decode.c b/target/i386/emulate/x86_decode.c
index 6ad03b71b0..7bbcd2a9a2 100644
--- a/target/i386/emulate/x86_decode.c
+++ b/target/i386/emulate/x86_decode.c
@@ -2088,8 +2088,6 @@ static void decode_opcodes(CPUX86State *env, struct x86_decode *decode)
static uint32_t decode_opcode(CPUX86State *env, struct x86_decode *decode)
{
- memset(decode, 0, sizeof(*decode));
-
decode_prefix(env, decode);
set_addressing_size(env, decode);
set_operand_size(env, decode);
@@ -2101,6 +2099,8 @@ static uint32_t decode_opcode(CPUX86State *env, struct x86_decode *decode)
uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode)
{
+ memset(decode, 0, sizeof(*decode));
+
return decode_opcode(env, decode);
}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 04/14] target/i386: emulate, hvf: move x86_mmu to common code
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (2 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 03/14] target/i386/emulate/x86_decode: Actually use stream in decode_instruction_stream() Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 05/14] whpx: i386: re-enable guest debug support Mohamed Mediouni
` (9 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
target/i386/emulate/meson.build | 1 +
target/i386/{hvf => emulate}/x86_mmu.c | 14 +++++++++-----
target/i386/{hvf => emulate}/x86_mmu.h | 0
target/i386/hvf/hvf.c | 10 +++++++++-
target/i386/hvf/meson.build | 1 -
target/i386/hvf/x86.c | 2 +-
target/i386/hvf/x86_task.c | 2 +-
7 files changed, 21 insertions(+), 9 deletions(-)
rename target/i386/{hvf => emulate}/x86_mmu.c (95%)
rename target/i386/{hvf => emulate}/x86_mmu.h (100%)
diff --git a/target/i386/emulate/meson.build b/target/i386/emulate/meson.build
index b6dafb6a5b..dd047c424a 100644
--- a/target/i386/emulate/meson.build
+++ b/target/i386/emulate/meson.build
@@ -2,6 +2,7 @@ emulator_files = files(
'x86_decode.c',
'x86_emu.c',
'x86_flags.c',
+ 'x86_mmu.c'
)
i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: emulator_files)
diff --git a/target/i386/hvf/x86_mmu.c b/target/i386/emulate/x86_mmu.c
similarity index 95%
rename from target/i386/hvf/x86_mmu.c
rename to target/i386/emulate/x86_mmu.c
index fe44d2edf4..b82a55a3da 100644
--- a/target/i386/hvf/x86_mmu.c
+++ b/target/i386/emulate/x86_mmu.c
@@ -19,10 +19,10 @@
#include "qemu/osdep.h"
#include "panic.h"
#include "cpu.h"
+#include "system/address-spaces.h"
+#include "system/memory.h"
#include "emulate/x86.h"
-#include "x86_mmu.h"
-#include "vmcs.h"
-#include "vmx.h"
+#include "emulate/x86_mmu.h"
#define pte_present(pte) (pte & PT_PRESENT)
#define pte_write_access(pte) (pte & PT_WRITE)
@@ -99,6 +99,8 @@ static bool get_pt_entry(CPUState *cpu, struct gpt_translation *pt,
static bool test_pt_entry(CPUState *cpu, struct gpt_translation *pt,
int level, int *largeness, bool pae)
{
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
uint64_t pte = pt->pte[level];
if (pt->write_access) {
@@ -127,7 +129,7 @@ static bool test_pt_entry(CPUState *cpu, struct gpt_translation *pt,
pt->err_code |= MMU_PAGE_PT;
}
- uint32_t cr0 = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
+ uint32_t cr0 = env->cr[0];
/* check protection */
if (cr0 & CR0_WP_MASK) {
if (pt->write_access && !pte_write_access(pte)) {
@@ -179,9 +181,11 @@ static inline uint64_t large_page_gpa(struct gpt_translation *pt, bool pae,
static bool walk_gpt(CPUState *cpu, target_ulong addr, int err_code,
struct gpt_translation *pt, bool pae)
{
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
int top_level, level;
int largeness = 0;
- target_ulong cr3 = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
+ target_ulong cr3 = env->cr[3];
uint64_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK;
memset(pt, 0, sizeof(*pt));
diff --git a/target/i386/hvf/x86_mmu.h b/target/i386/emulate/x86_mmu.h
similarity index 100%
rename from target/i386/hvf/x86_mmu.h
rename to target/i386/emulate/x86_mmu.h
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index ce54020f00..0b3674ad33 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -62,7 +62,7 @@
#include "emulate/x86.h"
#include "x86_descr.h"
#include "emulate/x86_flags.h"
-#include "x86_mmu.h"
+#include "emulate/x86_mmu.h"
#include "emulate/x86_decode.h"
#include "emulate/x86_emu.h"
#include "x86_task.h"
@@ -254,11 +254,19 @@ static void hvf_read_segment_descriptor(CPUState *s, struct x86_segment_descript
static void hvf_read_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
{
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
+ env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
+ env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
vmx_read_mem(cpu, data, gva, bytes);
}
static void hvf_write_mem(CPUState *cpu, void *data, target_ulong gva, int bytes)
{
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
+ env->cr[0] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR0);
+ env->cr[3] = rvmcs(cpu->accel->fd, VMCS_GUEST_CR3);
vmx_write_mem(cpu, gva, data, bytes);
}
diff --git a/target/i386/hvf/meson.build b/target/i386/hvf/meson.build
index 519d190f0e..22bf886978 100644
--- a/target/i386/hvf/meson.build
+++ b/target/i386/hvf/meson.build
@@ -3,7 +3,6 @@ i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files(
'x86.c',
'x86_cpuid.c',
'x86_descr.c',
- 'x86_mmu.c',
'x86_task.c',
'x86hvf.c',
'hvf-cpu.c',
diff --git a/target/i386/hvf/x86.c b/target/i386/hvf/x86.c
index 5c75ec9a00..2fa210ff60 100644
--- a/target/i386/hvf/x86.c
+++ b/target/i386/hvf/x86.c
@@ -23,7 +23,7 @@
#include "emulate/x86_emu.h"
#include "vmcs.h"
#include "vmx.h"
-#include "x86_mmu.h"
+#include "emulate/x86_mmu.h"
#include "x86_descr.h"
/* static uint32_t x86_segment_access_rights(struct x86_segment_descriptor *var)
diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c
index bdf8b51ae6..b1e541a642 100644
--- a/target/i386/hvf/x86_task.c
+++ b/target/i386/hvf/x86_task.c
@@ -16,7 +16,7 @@
#include "vmx.h"
#include "emulate/x86.h"
#include "x86_descr.h"
-#include "x86_mmu.h"
+#include "emulate/x86_mmu.h"
#include "emulate/x86_decode.h"
#include "emulate/x86_emu.h"
#include "x86_task.h"
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 05/14] whpx: i386: re-enable guest debug support
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (3 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 04/14] target/i386: emulate, hvf: move x86_mmu to common code Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 06/14] whpx: preparatory changes before switching over from winhvemulation Mohamed Mediouni
` (8 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Fix what got broken several years ago by adding ops->supports_guest_debug
support as an architecture-specific function.
arm64 WHP doesn't currently provide support needed for this.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
accel/whpx/whpx-accel-ops.c | 8 ++++++++
include/system/whpx-all.h | 4 ++++
target/arm/whpx/whpx-all.c | 5 +++++
target/i386/whpx/whpx-all.c | 5 +++++
4 files changed, 22 insertions(+)
diff --git a/accel/whpx/whpx-accel-ops.c b/accel/whpx/whpx-accel-ops.c
index 50fadea0fd..b8f41544cb 100644
--- a/accel/whpx/whpx-accel-ops.c
+++ b/accel/whpx/whpx-accel-ops.c
@@ -17,6 +17,7 @@
#include "system/whpx.h"
#include "system/whpx-internal.h"
+#include "system/whpx-all.h"
#include "system/whpx-accel-ops.h"
static void *whpx_cpu_thread_fn(void *arg)
@@ -81,6 +82,12 @@ static bool whpx_vcpu_thread_is_idle(CPUState *cpu)
return !whpx_irqchip_in_kernel();
}
+static bool whpx_supports_guest_debug(void)
+{
+ return whpx_arch_supports_guest_debug();
+}
+
+
static void whpx_accel_ops_class_init(ObjectClass *oc, const void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
@@ -89,6 +96,7 @@ static void whpx_accel_ops_class_init(ObjectClass *oc, const void *data)
ops->kick_vcpu_thread = whpx_kick_vcpu_thread;
ops->cpu_thread_is_idle = whpx_vcpu_thread_is_idle;
ops->handle_interrupt = generic_handle_interrupt;
+ ops->supports_guest_debug = whpx_supports_guest_debug;
ops->synchronize_post_reset = whpx_cpu_synchronize_post_reset;
ops->synchronize_post_init = whpx_cpu_synchronize_post_init;
diff --git a/include/system/whpx-all.h b/include/system/whpx-all.h
index f13cdf7f66..3db074c38c 100644
--- a/include/system/whpx-all.h
+++ b/include/system/whpx-all.h
@@ -17,4 +17,8 @@ void whpx_translate_cpu_breakpoints(
struct whpx_breakpoints *breakpoints,
CPUState *cpu,
int cpu_breakpoint_count);
+
+/* called by whpx-accel-ops */
+bool whpx_arch_supports_guest_debug(void);
+
#endif
diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
index 36c5e30a03..8d0ca794af 100644
--- a/target/arm/whpx/whpx-all.c
+++ b/target/arm/whpx/whpx-all.c
@@ -304,6 +304,11 @@ void whpx_translate_cpu_breakpoints(
/* Breakpoints aren’t supported on this platform */
}
+bool whpx_arch_supports_guest_debug(void)
+{
+ return false;
+}
+
static void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val)
{
struct whpx_state *whpx = &whpx_global;
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index 8210250dc3..e1f0fa5e77 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -1272,6 +1272,11 @@ void whpx_apply_breakpoints(
}
}
+bool whpx_arch_supports_guest_debug(void)
+{
+ return true;
+}
+
/* Returns the address of the next instruction that is about to be executed. */
static vaddr whpx_vcpu_get_pc(CPUState *cpu, bool exit_context_valid)
{
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 06/14] whpx: preparatory changes before switching over from winhvemulation
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (4 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 05/14] whpx: i386: re-enable guest debug support Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 07/14] whpx: refactor whpx_destroy_vcpu to arch-specific function Mohamed Mediouni
` (7 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
target/i386/cpu.h | 2 +-
target/i386/emulate/meson.build | 1 +
target/i386/mshv/meson.build | 4 ++++
3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9f222a0c9f..065613722f 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2286,7 +2286,7 @@ typedef struct CPUArchState {
QEMUTimer *xen_periodic_timer;
QemuMutex xen_timers_lock;
#endif
-#if defined(CONFIG_HVF) || defined(CONFIG_MSHV)
+#if defined(CONFIG_HVF) || defined(CONFIG_MSHV) || defined(CONFIG_WHPX)
void *emu_mmio_buf;
#endif
diff --git a/target/i386/emulate/meson.build b/target/i386/emulate/meson.build
index dd047c424a..1bb3516249 100644
--- a/target/i386/emulate/meson.build
+++ b/target/i386/emulate/meson.build
@@ -7,3 +7,4 @@ emulator_files = files(
i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: emulator_files)
i386_system_ss.add(when: 'CONFIG_MSHV', if_true: emulator_files)
+i386_system_ss.add(when: 'CONFIG_WHPX', if_true: emulator_files)
diff --git a/target/i386/mshv/meson.build b/target/i386/mshv/meson.build
index 647e5dafb7..3fadd4598a 100644
--- a/target/i386/mshv/meson.build
+++ b/target/i386/mshv/meson.build
@@ -6,3 +6,7 @@ i386_mshv_ss.add(files(
))
i386_system_ss.add_all(when: 'CONFIG_MSHV', if_true: i386_mshv_ss)
+
+i386_system_ss.add(when: 'CONFIG_WHPX', if_true: files(
+ 'x86.c',
+))
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 07/14] whpx: refactor whpx_destroy_vcpu to arch-specific function
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (5 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 06/14] whpx: preparatory changes before switching over from winhvemulation Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 08/14] whpx: move whpx_get_reg/whpx_set_reg to generic code Mohamed Mediouni
` (6 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Avoid a TARGET_X86_64 define by moving platform-specific code
away from generic WHPX support.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
accel/whpx/whpx-common.c | 5 +----
include/system/whpx-all.h | 1 +
target/arm/whpx/whpx-all.c | 5 +++++
target/i386/whpx/whpx-all.c | 6 ++++++
4 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index f018a8f5c7..c57a0d3f0f 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -236,10 +236,7 @@ void whpx_destroy_vcpu(CPUState *cpu)
struct whpx_state *whpx = &whpx_global;
whp_dispatch.WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index);
-#ifdef HOST_X86_64
- AccelCPUState *vcpu = cpu->accel;
- whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
-#endif
+ whpx_arch_destroy_vcpu(cpu);
g_free(cpu->accel);
}
diff --git a/include/system/whpx-all.h b/include/system/whpx-all.h
index 3db074c38c..b831c463b0 100644
--- a/include/system/whpx-all.h
+++ b/include/system/whpx-all.h
@@ -17,6 +17,7 @@ void whpx_translate_cpu_breakpoints(
struct whpx_breakpoints *breakpoints,
CPUState *cpu,
int cpu_breakpoint_count);
+void whpx_arch_destroy_vcpu(CPUState *cpu);
/* called by whpx-accel-ops */
bool whpx_arch_supports_guest_debug(void);
diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
index 8d0ca794af..d52580a082 100644
--- a/target/arm/whpx/whpx-all.c
+++ b/target/arm/whpx/whpx-all.c
@@ -309,6 +309,11 @@ bool whpx_arch_supports_guest_debug(void)
return false;
}
+void whpx_arch_destroy_vcpu(CPUState *cpu)
+{
+ /* currently empty on Arm */
+}
+
static void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val)
{
struct whpx_state *whpx = &whpx_global;
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index e1f0fa5e77..cdcaebbe16 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -1277,6 +1277,12 @@ bool whpx_arch_supports_guest_debug(void)
return true;
}
+void whpx_arch_destroy_vcpu(CPUState *cpu)
+{
+ AccelCPUState *vcpu = cpu->accel;
+ whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
+}
+
/* Returns the address of the next instruction that is about to be executed. */
static vaddr whpx_vcpu_get_pc(CPUState *cpu, bool exit_context_valid)
{
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 08/14] whpx: move whpx_get_reg/whpx_set_reg to generic code
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (6 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 07/14] whpx: refactor whpx_destroy_vcpu to arch-specific function Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-16 18:45 ` Bernhard Beschow
2026-02-15 5:22 ` [PATCH v3 09/14] whpx: i386: switch over from winhvemulation to target/i386/emulate Mohamed Mediouni
` (5 subsequent siblings)
13 siblings, 1 reply; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
These will be used in the next commit on the x86_64 backend too.
Also move flush_cpu_state as it's used by get_reg/set_reg and the arm64 code.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/whpx/whpx-common.c | 35 +++++++++++++++++++++++++++++++++++
include/system/whpx-common.h | 3 +++
target/arm/whpx/whpx-all.c | 35 -----------------------------------
3 files changed, 38 insertions(+), 35 deletions(-)
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index c57a0d3f0f..c2263c2496 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -46,6 +46,41 @@ static HMODULE hWinHvEmulation;
struct whpx_state whpx_global;
struct WHPDispatch whp_dispatch;
+void flush_cpu_state(CPUState *cpu)
+{
+ if (cpu->vcpu_dirty) {
+ whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
+ cpu->vcpu_dirty = false;
+ }
+}
+
+void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val)
+{
+ struct whpx_state *whpx = &whpx_global;
+ HRESULT hr;
+
+ flush_cpu_state(cpu);
+
+ hr = whp_dispatch.WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
+ ®, 1, val);
+
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to get register %08x, hr=%08lx", reg, hr);
+ }
+}
+
+void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val)
+{
+ struct whpx_state *whpx = &whpx_global;
+ HRESULT hr;
+ hr = whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
+ ®, 1, &val);
+
+ if (FAILED(hr)) {
+ error_report("WHPX: Failed to set register %08x, hr=%08lx", reg, hr);
+ }
+}
+
/* Tries to find a breakpoint at the specified address. */
struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address)
{
diff --git a/include/system/whpx-common.h b/include/system/whpx-common.h
index b86fe9db6e..5bce33e336 100644
--- a/include/system/whpx-common.h
+++ b/include/system/whpx-common.h
@@ -20,6 +20,9 @@ int whpx_first_vcpu_starting(CPUState *cpu);
int whpx_last_vcpu_stopping(CPUState *cpu);
void whpx_memory_init(void);
struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address);
+void flush_cpu_state(CPUState *cpu);
+void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val);
+void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val);
/* On x64: same as WHvX64ExceptionTypeDebugTrapOrFault */
#define WHPX_INTERCEPT_DEBUG_TRAPS 1
diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
index d52580a082..c8d71a252e 100644
--- a/target/arm/whpx/whpx-all.c
+++ b/target/arm/whpx/whpx-all.c
@@ -274,14 +274,6 @@ static struct whpx_sreg_match whpx_sreg_match[] = {
{ WHvArm64RegisterSpEl1, ENCODE_AA64_CP_REG(4, 1, 3, 4, 0) },
};
-static void flush_cpu_state(CPUState *cpu)
-{
- if (cpu->vcpu_dirty) {
- whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
- cpu->vcpu_dirty = false;
- }
-}
-
HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions)
{
if (exceptions != 0) {
@@ -314,33 +306,6 @@ void whpx_arch_destroy_vcpu(CPUState *cpu)
/* currently empty on Arm */
}
-static void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val)
-{
- struct whpx_state *whpx = &whpx_global;
- HRESULT hr;
-
- flush_cpu_state(cpu);
-
- hr = whp_dispatch.WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
- ®, 1, val);
-
- if (FAILED(hr)) {
- error_report("WHPX: Failed to get register %08x, hr=%08lx", reg, hr);
- }
-}
-
-static void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val)
-{
- struct whpx_state *whpx = &whpx_global;
- HRESULT hr;
- hr = whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
- ®, 1, &val);
-
- if (FAILED(hr)) {
- error_report("WHPX: Failed to set register %08x, hr=%08lx", reg, hr);
- }
-}
-
static void whpx_get_global_reg(WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE *val)
{
struct whpx_state *whpx = &whpx_global;
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 09/14] whpx: i386: switch over from winhvemulation to target/i386/emulate
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (7 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 08/14] whpx: move whpx_get_reg/whpx_set_reg to generic code Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 10/14] whpx: i386: remove remaining winhvemulation support code Mohamed Mediouni
` (4 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Using the mshv backend as a base, move away from winhvemulation
to using common QEMU code used by the HVF and mshv backends.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
target/i386/whpx/whpx-all.c | 250 ++++++++++++++++--------------------
1 file changed, 114 insertions(+), 136 deletions(-)
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index cdcaebbe16..eabb0ef913 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -15,6 +15,7 @@
#include "gdbstub/helpers.h"
#include "qemu/accel.h"
#include "accel/accel-ops.h"
+#include "system/memory.h"
#include "system/whpx.h"
#include "system/cpus.h"
#include "system/runstate.h"
@@ -36,8 +37,12 @@
#include "system/whpx-all.h"
#include "system/whpx-common.h"
+#include "emulate/x86_decode.h"
+#include "emulate/x86_emu.h"
+#include "emulate/x86_flags.h"
+#include "emulate/x86_mmu.h"
+
#include <winhvplatform.h>
-#include <winhvemulation.h>
#define HYPERV_APIC_BUS_FREQUENCY (200000000ULL)
@@ -756,158 +761,138 @@ void whpx_get_registers(CPUState *cpu)
x86_update_hflags(env);
}
-static HRESULT CALLBACK whpx_emu_ioport_callback(
- void *ctx,
- WHV_EMULATOR_IO_ACCESS_INFO *IoAccess)
+static int emulate_instruction(CPUState *cpu, const uint8_t *insn_bytes, size_t insn_len)
{
- MemTxAttrs attrs = { 0 };
- address_space_rw(&address_space_io, IoAccess->Port, attrs,
- &IoAccess->Data, IoAccess->AccessSize,
- IoAccess->Direction);
- return S_OK;
-}
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
+ struct x86_decode decode = { 0 };
+ x86_insn_stream stream = { .bytes = insn_bytes, .len = insn_len };
-static HRESULT CALLBACK whpx_emu_mmio_callback(
- void *ctx,
- WHV_EMULATOR_MEMORY_ACCESS_INFO *ma)
-{
- CPUState *cs = (CPUState *)ctx;
- AddressSpace *as = cpu_addressspace(cs, MEMTXATTRS_UNSPECIFIED);
+ whpx_get_registers(cpu);
+ decode_instruction_stream(env, &decode, &stream);
+ exec_instruction(env, &decode);
+ whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
- address_space_rw(as, ma->GpaAddress, MEMTXATTRS_UNSPECIFIED,
- ma->Data, ma->AccessSize, ma->Direction);
- return S_OK;
+ return 0;
}
-static HRESULT CALLBACK whpx_emu_getreg_callback(
- void *ctx,
- const WHV_REGISTER_NAME *RegisterNames,
- UINT32 RegisterCount,
- WHV_REGISTER_VALUE *RegisterValues)
+static int whpx_handle_mmio(CPUState *cpu, WHV_RUN_VP_EXIT_CONTEXT *exit_ctx)
{
- HRESULT hr;
- struct whpx_state *whpx = &whpx_global;
- CPUState *cpu = (CPUState *)ctx;
+ WHV_MEMORY_ACCESS_CONTEXT *ctx = &exit_ctx->MemoryAccess;
+ int ret;
- hr = whp_dispatch.WHvGetVirtualProcessorRegisters(
- whpx->partition, cpu->cpu_index,
- RegisterNames, RegisterCount,
- RegisterValues);
- if (FAILED(hr)) {
- error_report("WHPX: Failed to get virtual processor registers,"
- " hr=%08lx", hr);
+ ret = emulate_instruction(cpu, ctx->InstructionBytes, exit_ctx->VpContext.InstructionLength);
+ if (ret < 0) {
+ error_report("failed to emulate mmio");
+ return -1;
}
- return hr;
+ return 0;
}
-static HRESULT CALLBACK whpx_emu_setreg_callback(
- void *ctx,
- const WHV_REGISTER_NAME *RegisterNames,
- UINT32 RegisterCount,
- const WHV_REGISTER_VALUE *RegisterValues)
+static void handle_io(CPUState *env, uint16_t port, void *buffer,
+ int direction, int size, int count)
{
- HRESULT hr;
- struct whpx_state *whpx = &whpx_global;
- CPUState *cpu = (CPUState *)ctx;
+ int i;
+ uint8_t *ptr = buffer;
- hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
- whpx->partition, cpu->cpu_index,
- RegisterNames, RegisterCount,
- RegisterValues);
- if (FAILED(hr)) {
- error_report("WHPX: Failed to set virtual processor registers,"
- " hr=%08lx", hr);
+ for (i = 0; i < count; i++) {
+ address_space_rw(&address_space_io, port, MEMTXATTRS_UNSPECIFIED,
+ ptr, size,
+ direction);
+ ptr += size;
}
-
- /*
- * The emulator just successfully wrote the register state. We clear the
- * dirty state so we avoid the double write on resume of the VP.
- */
- cpu->vcpu_dirty = false;
-
- return hr;
}
-static HRESULT CALLBACK whpx_emu_translate_callback(
- void *ctx,
- WHV_GUEST_VIRTUAL_ADDRESS Gva,
- WHV_TRANSLATE_GVA_FLAGS TranslateFlags,
- WHV_TRANSLATE_GVA_RESULT_CODE *TranslationResult,
- WHV_GUEST_PHYSICAL_ADDRESS *Gpa)
+static void whpx_bump_rip(CPUState *cpu, WHV_RUN_VP_EXIT_CONTEXT *exit_ctx)
{
- HRESULT hr;
- struct whpx_state *whpx = &whpx_global;
- CPUState *cpu = (CPUState *)ctx;
- WHV_TRANSLATE_GVA_RESULT res;
-
- hr = whp_dispatch.WHvTranslateGva(whpx->partition, cpu->cpu_index,
- Gva, TranslateFlags, &res, Gpa);
- if (FAILED(hr)) {
- error_report("WHPX: Failed to translate GVA, hr=%08lx", hr);
- } else {
- *TranslationResult = res.ResultCode;
- }
-
- return hr;
+ WHV_REGISTER_VALUE reg;
+ whpx_get_reg(cpu, WHvX64RegisterRip, ®);
+ reg.Reg64 = exit_ctx->VpContext.Rip + exit_ctx->VpContext.InstructionLength;
+ whpx_set_reg(cpu, WHvX64RegisterRip, reg);
}
-static const WHV_EMULATOR_CALLBACKS whpx_emu_callbacks = {
- .Size = sizeof(WHV_EMULATOR_CALLBACKS),
- .WHvEmulatorIoPortCallback = whpx_emu_ioport_callback,
- .WHvEmulatorMemoryCallback = whpx_emu_mmio_callback,
- .WHvEmulatorGetVirtualProcessorRegisters = whpx_emu_getreg_callback,
- .WHvEmulatorSetVirtualProcessorRegisters = whpx_emu_setreg_callback,
- .WHvEmulatorTranslateGvaPage = whpx_emu_translate_callback,
-};
-
-static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_ACCESS_CONTEXT *ctx)
+static int whpx_handle_portio(CPUState *cpu,
+ WHV_RUN_VP_EXIT_CONTEXT *exit_ctx)
{
- HRESULT hr;
- AccelCPUState *vcpu = cpu->accel;
- WHV_EMULATOR_STATUS emu_status;
-
- hr = whp_dispatch.WHvEmulatorTryMmioEmulation(
- vcpu->emulator, cpu,
- &vcpu->exit_ctx.VpContext, ctx,
- &emu_status);
- if (FAILED(hr)) {
- error_report("WHPX: Failed to parse MMIO access, hr=%08lx", hr);
- return -1;
- }
+ WHV_X64_IO_PORT_ACCESS_CONTEXT *ctx = &exit_ctx->IoPortAccess;
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
+ int ret;
- if (!emu_status.EmulationSuccessful) {
- error_report("WHPX: Failed to emulate MMIO access with"
- " EmulatorReturnStatus: %u", emu_status.AsUINT32);
+ if (!ctx->AccessInfo.StringOp && !ctx->AccessInfo.IsWrite) {
+ uint64_t val = 0;
+ WHV_REGISTER_VALUE reg;
+
+ whpx_get_reg(cpu, WHvX64RegisterRax, ®);
+ handle_io(cpu, ctx->PortNumber, &val, 0, ctx->AccessInfo.AccessSize, 1);
+ if (ctx->AccessInfo.AccessSize == 1) {
+ reg.Reg8 = val;
+ } else if (ctx->AccessInfo.AccessSize == 2) {
+ reg.Reg16 = val;
+ } else if (ctx->AccessInfo.AccessSize == 4) {
+ reg.Reg64 = (uint32_t)val;
+ } else {
+ reg.Reg64 = (uint64_t)val;
+ }
+ whpx_bump_rip(cpu, exit_ctx);
+ whpx_set_reg(cpu, WHvX64RegisterRax, reg);
+ return 0;
+ } else if (!ctx->AccessInfo.StringOp && ctx->AccessInfo.IsWrite) {
+ RAX(env) = ctx->Rax;
+ handle_io(cpu, ctx->PortNumber, &RAX(env), 1, ctx->AccessInfo.AccessSize, 1);
+ whpx_bump_rip(cpu, exit_ctx);
+ return 0;
+ }
+
+ ret = emulate_instruction(cpu, ctx->InstructionBytes, exit_ctx->VpContext.InstructionLength);
+ if (ret < 0) {
+ error_report("failed to emulate I/O port access");
return -1;
}
return 0;
}
-static int whpx_handle_portio(CPUState *cpu,
- WHV_X64_IO_PORT_ACCESS_CONTEXT *ctx)
+static void write_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
{
- HRESULT hr;
- AccelCPUState *vcpu = cpu->accel;
- WHV_EMULATOR_STATUS emu_status;
+ vmx_write_mem(cpu, addr, data, bytes);
+}
- hr = whp_dispatch.WHvEmulatorTryIoEmulation(
- vcpu->emulator, cpu,
- &vcpu->exit_ctx.VpContext, ctx,
- &emu_status);
- if (FAILED(hr)) {
- error_report("WHPX: Failed to parse PortIO access, hr=%08lx", hr);
- return -1;
- }
+static void read_mem(CPUState *cpu, void *data, target_ulong addr, int bytes)
+{
+ vmx_read_mem(cpu, data, addr, bytes);
+}
- if (!emu_status.EmulationSuccessful) {
- error_report("WHPX: Failed to emulate PortIO access with"
- " EmulatorReturnStatus: %u", emu_status.AsUINT32);
- return -1;
+static void read_segment_descriptor(CPUState *cpu,
+ struct x86_segment_descriptor *desc,
+ enum X86Seg seg_idx)
+{
+ bool ret;
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
+ SegmentCache *seg = &env->segs[seg_idx];
+ x86_segment_selector sel = { .sel = seg->selector & 0xFFFF };
+
+ ret = x86_read_segment_descriptor(cpu, desc, sel);
+ if (ret == false) {
+ error_report("failed to read segment descriptor");
+ abort();
}
+}
- return 0;
+
+static const struct x86_emul_ops whpx_x86_emul_ops = {
+ .read_mem = read_mem,
+ .write_mem = write_mem,
+ .read_segment_descriptor = read_segment_descriptor,
+ .handle_io = handle_io
+};
+
+static void whpx_init_emu(void)
+{
+ init_decoder();
+ init_emu(&whpx_x86_emul_ops);
}
/*
@@ -1279,8 +1264,9 @@ bool whpx_arch_supports_guest_debug(void)
void whpx_arch_destroy_vcpu(CPUState *cpu)
{
- AccelCPUState *vcpu = cpu->accel;
- whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
+ X86CPU *x86cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86cpu->env;
+ g_free(env->emu_mmio_buf);
}
/* Returns the address of the next instruction that is about to be executed. */
@@ -1639,11 +1625,11 @@ int whpx_vcpu_run(CPUState *cpu)
switch (vcpu->exit_ctx.ExitReason) {
case WHvRunVpExitReasonMemoryAccess:
- ret = whpx_handle_mmio(cpu, &vcpu->exit_ctx.MemoryAccess);
+ ret = whpx_handle_mmio(cpu, &vcpu->exit_ctx);
break;
case WHvRunVpExitReasonX64IoPortAccess:
- ret = whpx_handle_portio(cpu, &vcpu->exit_ctx.IoPortAccess);
+ ret = whpx_handle_portio(cpu, &vcpu->exit_ctx);
break;
case WHvRunVpExitReasonX64InterruptWindow:
@@ -1990,22 +1976,11 @@ int whpx_init_vcpu(CPUState *cpu)
vcpu = g_new0(AccelCPUState, 1);
- hr = whp_dispatch.WHvEmulatorCreateEmulator(
- &whpx_emu_callbacks,
- &vcpu->emulator);
- if (FAILED(hr)) {
- error_report("WHPX: Failed to setup instruction completion support,"
- " hr=%08lx", hr);
- ret = -EINVAL;
- goto error;
- }
-
hr = whp_dispatch.WHvCreateVirtualProcessor(
whpx->partition, cpu->cpu_index, 0);
if (FAILED(hr)) {
error_report("WHPX: Failed to create a virtual processor,"
" hr=%08lx", hr);
- whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
ret = -EINVAL;
goto error;
}
@@ -2067,6 +2042,8 @@ int whpx_init_vcpu(CPUState *cpu)
max_vcpu_index = max(max_vcpu_index, cpu->cpu_index);
qemu_add_vm_change_state_handler(whpx_cpu_update_state, env);
+ env->emu_mmio_buf = g_new(char, 4096);
+
return 0;
error:
@@ -2256,6 +2233,7 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
}
whpx_memory_init();
+ whpx_init_emu();
printf("Windows Hypervisor Platform accelerator is operational\n");
return 0;
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 10/14] whpx: i386: remove remaining winhvemulation support code
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (8 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 09/14] whpx: i386: switch over from winhvemulation to target/i386/emulate Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 11/14] whpx: i386: remove messages Mohamed Mediouni
` (3 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
After moving away to target/i386/emulate, this is no longer necessary.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/whpx/whpx-common.c | 22 ----------------------
include/system/whpx-common.h | 3 ---
include/system/whpx-internal.h | 16 ----------------
meson.build | 3 +--
4 files changed, 1 insertion(+), 43 deletions(-)
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index c2263c2496..245e64a12f 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -39,9 +39,6 @@ bool whpx_allowed;
bool whpx_irqchip_in_kernel;
static bool whp_dispatch_initialized;
static HMODULE hWinHvPlatform;
-#ifdef HOST_X86_64
-static HMODULE hWinHvEmulation;
-#endif
struct whpx_state whpx_global;
struct WHPDispatch whp_dispatch;
@@ -393,7 +390,6 @@ static bool load_whp_dispatch_fns(HMODULE *handle,
HMODULE hLib = *handle;
#define WINHV_PLATFORM_DLL "WinHvPlatform.dll"
- #define WINHV_EMULATION_DLL "WinHvEmulation.dll"
#define WHP_LOAD_FIELD_OPTIONAL(return_type, function_name, signature) \
whp_dispatch.function_name = \
(function_name ## _t)GetProcAddress(hLib, #function_name); \
@@ -420,14 +416,6 @@ static bool load_whp_dispatch_fns(HMODULE *handle,
WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)
LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD)
break;
- case WINHV_EMULATION_FNS_DEFAULT:
-#ifdef HOST_X86_64
- WHP_LOAD_LIB(WINHV_EMULATION_DLL, hLib)
- LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD)
-#else
- g_assert_not_reached();
-#endif
- break;
case WINHV_PLATFORM_FNS_SUPPLEMENTAL:
WHP_LOAD_LIB(WINHV_PLATFORM_DLL, hLib)
LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_LOAD_FIELD_OPTIONAL)
@@ -543,11 +531,6 @@ bool init_whp_dispatch(void)
if (!load_whp_dispatch_fns(&hWinHvPlatform, WINHV_PLATFORM_FNS_DEFAULT)) {
goto error;
}
-#ifdef HOST_X86_64
- if (!load_whp_dispatch_fns(&hWinHvEmulation, WINHV_EMULATION_FNS_DEFAULT)) {
- goto error;
- }
-#endif
assert(load_whp_dispatch_fns(&hWinHvPlatform,
WINHV_PLATFORM_FNS_SUPPLEMENTAL));
whp_dispatch_initialized = true;
@@ -557,11 +540,6 @@ error:
if (hWinHvPlatform) {
FreeLibrary(hWinHvPlatform);
}
-#ifdef HOST_X86_64
- if (hWinHvEmulation) {
- FreeLibrary(hWinHvEmulation);
- }
-#endif
return false;
}
diff --git a/include/system/whpx-common.h b/include/system/whpx-common.h
index 5bce33e336..fa2cc9a2ce 100644
--- a/include/system/whpx-common.h
+++ b/include/system/whpx-common.h
@@ -3,9 +3,6 @@
#define SYSTEM_WHPX_COMMON_H
struct AccelCPUState {
-#ifdef HOST_X86_64
- WHV_EMULATOR_HANDLE emulator;
-#endif
bool window_registered;
bool interruptable;
bool ready_for_pic_interrupt;
diff --git a/include/system/whpx-internal.h b/include/system/whpx-internal.h
index ad6ade223e..7a1c9871f1 100644
--- a/include/system/whpx-internal.h
+++ b/include/system/whpx-internal.h
@@ -4,9 +4,6 @@
#include <windows.h>
#include <winhvplatform.h>
-#ifdef HOST_X86_64
-#include <winhvemulation.h>
-#endif
#include "hw/i386/apic.h"
#include "exec/vaddr.h"
@@ -89,12 +86,6 @@ void whpx_apic_get(APICCommonState *s);
X(HRESULT, WHvResetPartition, \
(WHV_PARTITION_HANDLE Partition)) \
-#define LIST_WINHVEMULATION_FUNCTIONS(X) \
- X(HRESULT, WHvEmulatorCreateEmulator, (const WHV_EMULATOR_CALLBACKS* Callbacks, WHV_EMULATOR_HANDLE* Emulator)) \
- X(HRESULT, WHvEmulatorDestroyEmulator, (WHV_EMULATOR_HANDLE Emulator)) \
- X(HRESULT, WHvEmulatorTryIoEmulation, (WHV_EMULATOR_HANDLE Emulator, VOID* Context, const WHV_VP_EXIT_CONTEXT* VpContext, const WHV_X64_IO_PORT_ACCESS_CONTEXT* IoInstructionContext, WHV_EMULATOR_STATUS* EmulatorReturnStatus)) \
- X(HRESULT, WHvEmulatorTryMmioEmulation, (WHV_EMULATOR_HANDLE Emulator, VOID* Context, const WHV_VP_EXIT_CONTEXT* VpContext, const WHV_MEMORY_ACCESS_CONTEXT* MmioInstructionContext, WHV_EMULATOR_STATUS* EmulatorReturnStatus)) \
-
#define WHP_DEFINE_TYPE(return_type, function_name, signature) \
typedef return_type (WINAPI *function_name ## _t) signature;
@@ -103,16 +94,10 @@ void whpx_apic_get(APICCommonState *s);
/* Define function typedef */
LIST_WINHVPLATFORM_FUNCTIONS(WHP_DEFINE_TYPE)
-#ifdef HOST_X86_64
-LIST_WINHVEMULATION_FUNCTIONS(WHP_DEFINE_TYPE)
-#endif
LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_DEFINE_TYPE)
struct WHPDispatch {
LIST_WINHVPLATFORM_FUNCTIONS(WHP_DECLARE_MEMBER)
-#ifdef HOST_X86_64
- LIST_WINHVEMULATION_FUNCTIONS(WHP_DECLARE_MEMBER)
-#endif
LIST_WINHVPLATFORM_FUNCTIONS_SUPPLEMENTAL(WHP_DECLARE_MEMBER)
};
@@ -122,7 +107,6 @@ bool init_whp_dispatch(void);
typedef enum WHPFunctionList {
WINHV_PLATFORM_FNS_DEFAULT,
- WINHV_EMULATION_FNS_DEFAULT,
WINHV_PLATFORM_FNS_SUPPLEMENTAL
} WHPFunctionList;
diff --git a/meson.build b/meson.build
index 4af32c3e1f..86bc807e56 100644
--- a/meson.build
+++ b/meson.build
@@ -865,8 +865,7 @@ if get_option('whpx').allowed() and host_os == 'windows'
endif
# Leave CONFIG_WHPX disabled
else
- if cc.has_header('winhvplatform.h', required: get_option('whpx')) and \
- cc.has_header('winhvemulation.h', required: get_option('whpx'))
+ if cc.has_header('winhvplatform.h', required: get_option('whpx'))
accelerators += 'CONFIG_WHPX'
endif
endif
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 11/14] whpx: i386: remove messages
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (9 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 10/14] whpx: i386: remove remaining winhvemulation support code Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 12/14] whpx: i386: remove CPUID trapping Mohamed Mediouni
` (2 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Remove some messages printed by the WHPX backend that don't
have an equivalent elsewhere and don't convey an error.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
target/i386/whpx/whpx-all.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index eabb0ef913..e815ca9bfa 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -2161,7 +2161,6 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
whp_dispatch.WHvSetVirtualProcessorInterruptControllerState2) {
WHV_X64_LOCAL_APIC_EMULATION_MODE mode =
WHvX64LocalApicEmulationModeXApic;
- printf("WHPX: setting APIC emulation mode in the hypervisor\n");
hr = whp_dispatch.WHvSetPartitionProperty(
whpx->partition,
WHvPartitionPropertyCodeLocalApicEmulationMode,
@@ -2235,7 +2234,6 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
whpx_memory_init();
whpx_init_emu();
- printf("Windows Hypervisor Platform accelerator is operational\n");
return 0;
error:
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 12/14] whpx: i386: remove CPUID trapping
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (10 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 11/14] whpx: i386: remove messages Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 13/14] whpx: common, i386, arm: rework state levels Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 14/14] whpx: i386: saving/restoring less state for WHPX_LEVEL_FAST_RUNTIME_STATE Mohamed Mediouni
13 siblings, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Very partial in its current state and results in significantly inconsistent
CPUID data. Remove it until it's reimplemented later.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
target/i386/whpx/whpx-all.c | 104 ------------------------------------
1 file changed, 104 deletions(-)
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index e815ca9bfa..0e8fb0e72e 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -1793,75 +1793,6 @@ int whpx_vcpu_run(CPUState *cpu)
ret = 0;
break;
}
- case WHvRunVpExitReasonX64Cpuid: {
- WHV_REGISTER_VALUE reg_values[5];
- WHV_REGISTER_NAME reg_names[5];
- UINT32 reg_count = 5;
- UINT64 cpuid_fn, rip = 0, rax = 0, rcx = 0, rdx = 0, rbx = 0;
- X86CPU *x86_cpu = X86_CPU(cpu);
- CPUX86State *env = &x86_cpu->env;
-
- memset(reg_values, 0, sizeof(reg_values));
-
- rip = vcpu->exit_ctx.VpContext.Rip +
- vcpu->exit_ctx.VpContext.InstructionLength;
- cpuid_fn = vcpu->exit_ctx.CpuidAccess.Rax;
-
- /*
- * Ideally, these should be supplied to the hypervisor during VCPU
- * initialization and it should be able to satisfy this request.
- * But, currently, WHPX doesn't support setting CPUID values in the
- * hypervisor once the partition has been setup, which is too late
- * since VCPUs are realized later. For now, use the values from
- * QEMU to satisfy these requests, until WHPX adds support for
- * being able to set these values in the hypervisor at runtime.
- */
- cpu_x86_cpuid(env, cpuid_fn, 0, (UINT32 *)&rax, (UINT32 *)&rbx,
- (UINT32 *)&rcx, (UINT32 *)&rdx);
- switch (cpuid_fn) {
- case 0x40000000:
- /* Expose the vmware cpu frequency cpuid leaf */
- rax = 0x40000010;
- rbx = rcx = rdx = 0;
- break;
-
- case 0x40000010:
- rax = env->tsc_khz;
- rbx = env->apic_bus_freq / 1000; /* Hz to KHz */
- rcx = rdx = 0;
- break;
-
- case 0x80000001:
- /* Remove any support of OSVW */
- rcx &= ~CPUID_EXT3_OSVW;
- break;
- }
-
- reg_names[0] = WHvX64RegisterRip;
- reg_names[1] = WHvX64RegisterRax;
- reg_names[2] = WHvX64RegisterRcx;
- reg_names[3] = WHvX64RegisterRdx;
- reg_names[4] = WHvX64RegisterRbx;
-
- reg_values[0].Reg64 = rip;
- reg_values[1].Reg64 = rax;
- reg_values[2].Reg64 = rcx;
- reg_values[3].Reg64 = rdx;
- reg_values[4].Reg64 = rbx;
-
- hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
- whpx->partition, cpu->cpu_index,
- reg_names,
- reg_count,
- reg_values);
-
- if (FAILED(hr)) {
- error_report("WHPX: Failed to set CpuidAccess state registers,"
- " hr=%08lx", hr);
- }
- ret = 0;
- break;
- }
case WHvRunVpExitReasonException:
whpx_get_registers(cpu);
@@ -2015,26 +1946,6 @@ int whpx_init_vcpu(CPUState *cpu)
}
}
- /*
- * If the vmware cpuid frequency leaf option is set, and we have a valid
- * tsc value, trap the corresponding cpuid's.
- */
- if (x86_cpu->vmware_cpuid_freq && env->tsc_khz) {
- UINT32 cpuidExitList[] = {1, 0x80000001, 0x40000000, 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;
@@ -2071,7 +1982,6 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
WHV_CAPABILITY whpx_cap;
UINT32 whpx_cap_size;
WHV_PARTITION_PROPERTY prop;
- UINT32 cpuidExitList[] = {1, 0x80000001};
WHV_CAPABILITY_FEATURES features = {0};
whpx = &whpx_global;
@@ -2181,7 +2091,6 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
/* Register for MSR and CPUID exits */
memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));
prop.ExtendedVmExits.X64MsrExit = 1;
- prop.ExtendedVmExits.X64CpuidExit = 1;
prop.ExtendedVmExits.ExceptionExit = 1;
if (whpx_irqchip_in_kernel()) {
prop.ExtendedVmExits.X64ApicInitSipiExitTrap = 1;
@@ -2198,19 +2107,6 @@ int whpx_accel_init(AccelState *as, MachineState *ms)
goto error;
}
- 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;
- }
-
/*
* We do not want to intercept any exceptions from the guest,
* until we actually start debugging with gdb.
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 13/14] whpx: common, i386, arm: rework state levels
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (11 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 12/14] whpx: i386: remove CPUID trapping Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-16 17:27 ` Philippe Mathieu-Daudé
2026-02-15 5:22 ` [PATCH v3 14/14] whpx: i386: saving/restoring less state for WHPX_LEVEL_FAST_RUNTIME_STATE Mohamed Mediouni
13 siblings, 1 reply; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Change state levels from a set of ifdefs to an enum.
Make register state loads use state levels too.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
accel/whpx/whpx-common.c | 8 ++++----
include/system/whpx-accel-ops.h | 16 ++++++++++------
include/system/whpx-all.h | 6 ++++--
target/arm/whpx/whpx-all.c | 8 ++++----
target/i386/whpx/whpx-all.c | 16 ++++++++--------
5 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
index 245e64a12f..06038dd7f1 100644
--- a/accel/whpx/whpx-common.c
+++ b/accel/whpx/whpx-common.c
@@ -46,7 +46,7 @@ struct WHPDispatch whp_dispatch;
void flush_cpu_state(CPUState *cpu)
{
if (cpu->vcpu_dirty) {
- whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
+ whpx_set_registers(cpu, WHPX_LEVEL_RUNTIME_STATE);
cpu->vcpu_dirty = false;
}
}
@@ -180,7 +180,7 @@ int whpx_last_vcpu_stopping(CPUState *cpu)
static void do_whpx_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
{
if (!cpu->vcpu_dirty) {
- whpx_get_registers(cpu);
+ whpx_get_registers(cpu, WHPX_LEVEL_FULL_STATE);
cpu->vcpu_dirty = true;
}
}
@@ -188,14 +188,14 @@ static void do_whpx_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
static void do_whpx_cpu_synchronize_post_reset(CPUState *cpu,
run_on_cpu_data arg)
{
- whpx_set_registers(cpu, WHPX_SET_RESET_STATE);
+ whpx_set_registers(cpu, WHPX_LEVEL_RESET_STATE);
cpu->vcpu_dirty = false;
}
static void do_whpx_cpu_synchronize_post_init(CPUState *cpu,
run_on_cpu_data arg)
{
- whpx_set_registers(cpu, WHPX_SET_FULL_STATE);
+ whpx_set_registers(cpu, WHPX_LEVEL_FULL_STATE);
cpu->vcpu_dirty = false;
}
diff --git a/include/system/whpx-accel-ops.h b/include/system/whpx-accel-ops.h
index ed9d4c49f4..4b2a732654 100644
--- a/include/system/whpx-accel-ops.h
+++ b/include/system/whpx-accel-ops.h
@@ -22,11 +22,15 @@ void whpx_cpu_synchronize_post_reset(CPUState *cpu);
void whpx_cpu_synchronize_post_init(CPUState *cpu);
void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu);
-/* state subset only touched by the VCPU itself during runtime */
-#define WHPX_SET_RUNTIME_STATE 1
-/* state subset modified during VCPU reset */
-#define WHPX_SET_RESET_STATE 2
-/* full state set, modified during initialization or on vmload */
-#define WHPX_SET_FULL_STATE 3
+typedef enum WHPXStateLevel {
+ /* subset of runtime state for faster returns from vmexit */
+ WHPX_LEVEL_FAST_RUNTIME_STATE,
+ /* state subset only touched by the VCPU itself during runtime */
+ WHPX_LEVEL_RUNTIME_STATE,
+ /* state subset modified during VCPU reset */
+ WHPX_LEVEL_RESET_STATE,
+ /* full state set, modified during initialization or on vmload */
+ WHPX_LEVEL_FULL_STATE
+} WHPXStateLevel;
#endif /* TARGET_I386_WHPX_ACCEL_OPS_H */
diff --git a/include/system/whpx-all.h b/include/system/whpx-all.h
index b831c463b0..2cbea71b14 100644
--- a/include/system/whpx-all.h
+++ b/include/system/whpx-all.h
@@ -2,10 +2,12 @@
#ifndef SYSTEM_WHPX_ALL_H
#define SYSTEM_WHPX_ALL_H
+#include "system/whpx-accel-ops.h"
+
/* Called by whpx-common */
int whpx_vcpu_run(CPUState *cpu);
-void whpx_get_registers(CPUState *cpu);
-void whpx_set_registers(CPUState *cpu, int level);
+void whpx_get_registers(CPUState *cpu, WHPXStateLevel level);
+void whpx_set_registers(CPUState *cpu, WHPXStateLevel level);
int whpx_accel_init(AccelState *as, MachineState *ms);
void whpx_cpu_instance_init(CPUState *cs);
HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions);
diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
index c8d71a252e..a1be82b878 100644
--- a/target/arm/whpx/whpx-all.c
+++ b/target/arm/whpx/whpx-all.c
@@ -418,7 +418,7 @@ int whpx_vcpu_run(CPUState *cpu)
do {
bool advance_pc = false;
if (cpu->vcpu_dirty) {
- whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
+ whpx_set_registers(cpu, WHPX_LEVEL_RUNTIME_STATE);
cpu->vcpu_dirty = false;
}
@@ -483,7 +483,7 @@ int whpx_vcpu_run(CPUState *cpu)
default:
error_report("WHPX: Unexpected VP exit code 0x%08x",
vcpu->exit_ctx.ExitReason);
- whpx_get_registers(cpu);
+ whpx_get_registers(cpu, WHPX_LEVEL_FULL_STATE);
bql_lock();
qemu_system_guest_panicked(cpu_get_crash_info(cpu));
bql_unlock();
@@ -517,7 +517,7 @@ static void clean_whv_register_value(WHV_REGISTER_VALUE *val)
memset(val, 0, sizeof(WHV_REGISTER_VALUE));
}
-void whpx_get_registers(CPUState *cpu)
+void whpx_get_registers(CPUState *cpu, WHPXStateLevel level)
{
ARMCPU *arm_cpu = ARM_CPU(cpu);
CPUARMState *env = &arm_cpu->env;
@@ -564,7 +564,7 @@ void whpx_get_registers(CPUState *cpu)
aarch64_restore_sp(env, arm_current_el(env));
}
-void whpx_set_registers(CPUState *cpu, int level)
+void whpx_set_registers(CPUState *cpu, WHPXStateLevel level)
{
ARMCPU *arm_cpu = ARM_CPU(cpu);
CPUARMState *env = &arm_cpu->env;
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index 0e8fb0e72e..7bbe63e794 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -367,7 +367,7 @@ static uint64_t whpx_cr8_to_apic_tpr(uint64_t cr8)
return cr8 << 4;
}
-void whpx_set_registers(CPUState *cpu, int level)
+void whpx_set_registers(CPUState *cpu, WHPXStateLevel level)
{
struct whpx_state *whpx = &whpx_global;
AccelCPUState *vcpu = cpu->accel;
@@ -386,7 +386,7 @@ void whpx_set_registers(CPUState *cpu, int level)
* Following MSRs have side effects on the guest or are too heavy for
* runtime. Limit them to full state update.
*/
- if (level >= WHPX_SET_RESET_STATE) {
+ if (level >= WHPX_LEVEL_RESET_STATE) {
whpx_set_tsc(cpu);
}
@@ -582,7 +582,7 @@ static void whpx_get_xcrs(CPUState *cpu)
cpu_env(cpu)->xcr0 = xcr0.Reg64;
}
-void whpx_get_registers(CPUState *cpu)
+void whpx_get_registers(CPUState *cpu, WHPXStateLevel level)
{
struct whpx_state *whpx = &whpx_global;
AccelCPUState *vcpu = cpu->accel;
@@ -768,10 +768,10 @@ static int emulate_instruction(CPUState *cpu, const uint8_t *insn_bytes, size_t
struct x86_decode decode = { 0 };
x86_insn_stream stream = { .bytes = insn_bytes, .len = insn_len };
- whpx_get_registers(cpu);
+ whpx_get_registers(cpu, WHPX_LEVEL_FAST_RUNTIME_STATE);
decode_instruction_stream(env, &decode, &stream);
exec_instruction(env, &decode);
- whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
+ whpx_set_registers(cpu, WHPX_LEVEL_FAST_RUNTIME_STATE);
return 0;
}
@@ -1587,7 +1587,7 @@ int whpx_vcpu_run(CPUState *cpu)
do {
if (cpu->vcpu_dirty) {
- whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
+ whpx_set_registers(cpu, WHPX_LEVEL_RUNTIME_STATE);
cpu->vcpu_dirty = false;
}
@@ -1794,7 +1794,7 @@ int whpx_vcpu_run(CPUState *cpu)
break;
}
case WHvRunVpExitReasonException:
- whpx_get_registers(cpu);
+ whpx_get_registers(cpu, WHPX_LEVEL_FULL_STATE);
if ((vcpu->exit_ctx.VpException.ExceptionType ==
WHvX64ExceptionTypeDebugTrapOrFault) &&
@@ -1826,7 +1826,7 @@ int whpx_vcpu_run(CPUState *cpu)
default:
error_report("WHPX: Unexpected VP exit code %d",
vcpu->exit_ctx.ExitReason);
- whpx_get_registers(cpu);
+ whpx_get_registers(cpu, WHPX_LEVEL_FULL_STATE);
bql_lock();
qemu_system_guest_panicked(cpu_get_crash_info(cpu));
bql_unlock();
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 14/14] whpx: i386: saving/restoring less state for WHPX_LEVEL_FAST_RUNTIME_STATE
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
` (12 preceding siblings ...)
2026-02-15 5:22 ` [PATCH v3 13/14] whpx: common, i386, arm: rework state levels Mohamed Mediouni
@ 2026-02-15 5:22 ` Mohamed Mediouni
2026-02-16 18:41 ` Bernhard Beschow
13 siblings, 1 reply; 19+ messages in thread
From: Mohamed Mediouni @ 2026-02-15 5:22 UTC (permalink / raw)
To: qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Mohamed Mediouni, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Optimise vmexits by save/restoring less state in those cases instead of the full state.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
target/i386/whpx/whpx-all.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index 7bbe63e794..9d1febce52 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -420,6 +420,13 @@ void whpx_set_registers(CPUState *cpu, WHPXStateLevel level)
vcxt.values[idx].Segment = whpx_seg_q2h(&env->segs[i], v86, r86);
}
+ /*
+ * This is a hot path called on every MMIO access.
+ */
+ if (level <= WHPX_LEVEL_FAST_RUNTIME_STATE) {
+ goto skip_to_set_registers;
+ }
+
assert(idx == WHvX64RegisterLdtr);
vcxt.values[idx++].Segment = whpx_seg_q2h(&env->ldt, 0, 0);
@@ -529,10 +536,11 @@ void whpx_set_registers(CPUState *cpu, WHPXStateLevel level)
assert(idx == RTL_NUMBER_OF(whpx_register_names));
+ skip_to_set_registers:
hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
whpx->partition, cpu->cpu_index,
whpx_register_names,
- RTL_NUMBER_OF(whpx_register_names),
+ idx,
&vcxt.values[0]);
if (FAILED(hr)) {
@@ -612,7 +620,7 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level)
hr);
}
- if (whpx_irqchip_in_kernel()) {
+ if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && whpx_irqchip_in_kernel()) {
/*
* Fetch the TPR value from the emulated APIC. It may get overwritten
* below with the value from CR8 returned by
@@ -668,7 +676,7 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level)
env->cr[4] = vcxt.values[idx++].Reg64;
assert(whpx_register_names[idx] == WHvX64RegisterCr8);
tpr = vcxt.values[idx++].Reg64;
- if (tpr != vcpu->tpr) {
+ if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && tpr != vcpu->tpr) {
vcpu->tpr = tpr;
cpu_set_apic_tpr(x86_cpu->apic_state, whpx_cr8_to_apic_tpr(tpr));
}
@@ -754,7 +762,7 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level)
assert(idx == RTL_NUMBER_OF(whpx_register_names));
- if (whpx_irqchip_in_kernel()) {
+ if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && whpx_irqchip_in_kernel()) {
whpx_apic_get(x86_cpu->apic_state);
}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v3 03/14] target/i386/emulate/x86_decode: Actually use stream in decode_instruction_stream()
2026-02-15 5:22 ` [PATCH v3 03/14] target/i386/emulate/x86_decode: Actually use stream in decode_instruction_stream() Mohamed Mediouni
@ 2026-02-16 11:23 ` Magnus Kulke
0 siblings, 0 replies; 19+ messages in thread
From: Magnus Kulke @ 2026-02-16 11:23 UTC (permalink / raw)
To: Mohamed Mediouni
Cc: qemu-devel, Phil Dennis-Jordan, Bernhard Beschow,
Cameron Esfahani, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Pedro Barbuda, Daniel P. Berrangé,
Marc-André Lureau, Philippe Mathieu-Daudé, Wei Liu,
Zhao Liu
> Fixes: 1e25327b244a ("target/i386/emulate: Allow instruction decoding from stream")
> cc: qemu-stable
> Signed-off-by: Bernhard Beschow <shentey@gmail.com>
> Reviewed-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> target/i386/emulate/x86_decode.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/target/i386/emulate/x86_decode.c b/target/i386/emulate/x86_decode.c
> index 6ad03b71b0..7bbcd2a9a2 100644
> --- a/target/i386/emulate/x86_decode.c
> +++ b/target/i386/emulate/x86_decode.c
> @@ -2088,8 +2088,6 @@ static void decode_opcodes(CPUX86State *env, struct x86_decode *decode)
>
> static uint32_t decode_opcode(CPUX86State *env, struct x86_decode *decode)
> {
> - memset(decode, 0, sizeof(*decode));
> -
> decode_prefix(env, decode);
> set_addressing_size(env, decode);
> set_operand_size(env, decode);
> @@ -2101,6 +2099,8 @@ static uint32_t decode_opcode(CPUX86State *env, struct x86_decode *decode)
>
> uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode)
> {
> + memset(decode, 0, sizeof(*decode));
> +
> return decode_opcode(env, decode);
> }
>
> --
> 2.50.1 (Apple Git-155)
Tested-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
makes sense, thx.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 13/14] whpx: common, i386, arm: rework state levels
2026-02-15 5:22 ` [PATCH v3 13/14] whpx: common, i386, arm: rework state levels Mohamed Mediouni
@ 2026-02-16 17:27 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-02-16 17:27 UTC (permalink / raw)
To: Mohamed Mediouni, qemu-devel
Cc: Phil Dennis-Jordan, Bernhard Beschow, Cameron Esfahani,
Magnus Kulke, qemu-arm, Peter Maydell, Roman Bolshakov,
Paolo Bonzini, Pedro Barbuda, Daniel P. Berrangé,
Marc-André Lureau, Magnus Kulke, Wei Liu, Zhao Liu
On 15/2/26 06:22, Mohamed Mediouni wrote:
> Change state levels from a set of ifdefs to an enum.
> Make register state loads use state levels too.
>
> Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> accel/whpx/whpx-common.c | 8 ++++----
> include/system/whpx-accel-ops.h | 16 ++++++++++------
> include/system/whpx-all.h | 6 ++++--
> target/arm/whpx/whpx-all.c | 8 ++++----
> target/i386/whpx/whpx-all.c | 16 ++++++++--------
> 5 files changed, 30 insertions(+), 24 deletions(-)
Thank you :)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 14/14] whpx: i386: saving/restoring less state for WHPX_LEVEL_FAST_RUNTIME_STATE
2026-02-15 5:22 ` [PATCH v3 14/14] whpx: i386: saving/restoring less state for WHPX_LEVEL_FAST_RUNTIME_STATE Mohamed Mediouni
@ 2026-02-16 18:41 ` Bernhard Beschow
0 siblings, 0 replies; 19+ messages in thread
From: Bernhard Beschow @ 2026-02-16 18:41 UTC (permalink / raw)
To: Mohamed Mediouni, qemu-devel
Cc: Phil Dennis-Jordan, Cameron Esfahani, Magnus Kulke, qemu-arm,
Peter Maydell, Roman Bolshakov, Paolo Bonzini, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Am 15. Februar 2026 05:22:25 UTC schrieb Mohamed Mediouni <mohamed@unpredictable.fr>:
>Optimise vmexits by save/restoring less state in those cases instead of the full state.
>
>Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
>---
> target/i386/whpx/whpx-all.c | 16 ++++++++++++----
> 1 file changed, 12 insertions(+), 4 deletions(-)
>
>diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
>index 7bbe63e794..9d1febce52 100644
>--- a/target/i386/whpx/whpx-all.c
>+++ b/target/i386/whpx/whpx-all.c
>@@ -420,6 +420,13 @@ void whpx_set_registers(CPUState *cpu, WHPXStateLevel level)
> vcxt.values[idx].Segment = whpx_seg_q2h(&env->segs[i], v86, r86);
> }
>
>+ /*
>+ * This is a hot path called on every MMIO access.
>+ */
>+ if (level <= WHPX_LEVEL_FAST_RUNTIME_STATE) {
>+ goto skip_to_set_registers;
>+ }
Looks like we can get rid of the goto by extending the scope of the if statement to the skip_to_set_registers label.
With this fixed:
Reviewed-by: Bernhard Beschow <shentey@gmail.com>
>+
> assert(idx == WHvX64RegisterLdtr);
> vcxt.values[idx++].Segment = whpx_seg_q2h(&env->ldt, 0, 0);
>
>@@ -529,10 +536,11 @@ void whpx_set_registers(CPUState *cpu, WHPXStateLevel level)
>
> assert(idx == RTL_NUMBER_OF(whpx_register_names));
>
>+ skip_to_set_registers:
> hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
> whpx->partition, cpu->cpu_index,
> whpx_register_names,
>- RTL_NUMBER_OF(whpx_register_names),
>+ idx,
> &vcxt.values[0]);
>
> if (FAILED(hr)) {
>@@ -612,7 +620,7 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level)
> hr);
> }
>
>- if (whpx_irqchip_in_kernel()) {
>+ if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && whpx_irqchip_in_kernel()) {
> /*
> * Fetch the TPR value from the emulated APIC. It may get overwritten
> * below with the value from CR8 returned by
>@@ -668,7 +676,7 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level)
> env->cr[4] = vcxt.values[idx++].Reg64;
> assert(whpx_register_names[idx] == WHvX64RegisterCr8);
> tpr = vcxt.values[idx++].Reg64;
>- if (tpr != vcpu->tpr) {
>+ if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && tpr != vcpu->tpr) {
> vcpu->tpr = tpr;
> cpu_set_apic_tpr(x86_cpu->apic_state, whpx_cr8_to_apic_tpr(tpr));
> }
>@@ -754,7 +762,7 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level)
>
> assert(idx == RTL_NUMBER_OF(whpx_register_names));
>
>- if (whpx_irqchip_in_kernel()) {
>+ if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && whpx_irqchip_in_kernel()) {
> whpx_apic_get(x86_cpu->apic_state);
> }
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 08/14] whpx: move whpx_get_reg/whpx_set_reg to generic code
2026-02-15 5:22 ` [PATCH v3 08/14] whpx: move whpx_get_reg/whpx_set_reg to generic code Mohamed Mediouni
@ 2026-02-16 18:45 ` Bernhard Beschow
0 siblings, 0 replies; 19+ messages in thread
From: Bernhard Beschow @ 2026-02-16 18:45 UTC (permalink / raw)
To: Mohamed Mediouni, qemu-devel
Cc: Phil Dennis-Jordan, Cameron Esfahani, Magnus Kulke, qemu-arm,
Peter Maydell, Roman Bolshakov, Paolo Bonzini, Pedro Barbuda,
Daniel P. Berrangé, Marc-André Lureau, Magnus Kulke,
Philippe Mathieu-Daudé, Wei Liu, Zhao Liu
Am 15. Februar 2026 05:22:19 UTC schrieb Mohamed Mediouni <mohamed@unpredictable.fr>:
>These will be used in the next commit on the x86_64 backend too.
>Also move flush_cpu_state as it's used by get_reg/set_reg and the arm64 code.
>
>Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
>---
> accel/whpx/whpx-common.c | 35 +++++++++++++++++++++++++++++++++++
> include/system/whpx-common.h | 3 +++
> target/arm/whpx/whpx-all.c | 35 -----------------------------------
> 3 files changed, 38 insertions(+), 35 deletions(-)
>
>diff --git a/accel/whpx/whpx-common.c b/accel/whpx/whpx-common.c
>index c57a0d3f0f..c2263c2496 100644
>--- a/accel/whpx/whpx-common.c
>+++ b/accel/whpx/whpx-common.c
>@@ -46,6 +46,41 @@ static HMODULE hWinHvEmulation;
> struct whpx_state whpx_global;
> struct WHPDispatch whp_dispatch;
>
>+void flush_cpu_state(CPUState *cpu)
>+{
>+ if (cpu->vcpu_dirty) {
>+ whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
>+ cpu->vcpu_dirty = false;
>+ }
>+}
>+
>+void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val)
>+{
>+ struct whpx_state *whpx = &whpx_global;
>+ HRESULT hr;
>+
>+ flush_cpu_state(cpu);
>+
>+ hr = whp_dispatch.WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
>+ ®, 1, val);
>+
>+ if (FAILED(hr)) {
>+ error_report("WHPX: Failed to get register %08x, hr=%08lx", reg, hr);
>+ }
>+}
>+
>+void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val)
>+{
>+ struct whpx_state *whpx = &whpx_global;
>+ HRESULT hr;
>+ hr = whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
>+ ®, 1, &val);
>+
>+ if (FAILED(hr)) {
>+ error_report("WHPX: Failed to set register %08x, hr=%08lx", reg, hr);
>+ }
>+}
>+
> /* Tries to find a breakpoint at the specified address. */
> struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address)
> {
>diff --git a/include/system/whpx-common.h b/include/system/whpx-common.h
>index b86fe9db6e..5bce33e336 100644
>--- a/include/system/whpx-common.h
>+++ b/include/system/whpx-common.h
>@@ -20,6 +20,9 @@ int whpx_first_vcpu_starting(CPUState *cpu);
> int whpx_last_vcpu_stopping(CPUState *cpu);
> void whpx_memory_init(void);
> struct whpx_breakpoint *whpx_lookup_breakpoint_by_addr(uint64_t address);
>+void flush_cpu_state(CPUState *cpu);
Now that flush_cpu_state() is exported we should better prefix it with "whpx_" to avoid name clashes.
With this fixed:
Reviewed-by: Bernhard Beschow <shentey@gmail.com>
>+void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val);
>+void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val);
>
> /* On x64: same as WHvX64ExceptionTypeDebugTrapOrFault */
> #define WHPX_INTERCEPT_DEBUG_TRAPS 1
>diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c
>index d52580a082..c8d71a252e 100644
>--- a/target/arm/whpx/whpx-all.c
>+++ b/target/arm/whpx/whpx-all.c
>@@ -274,14 +274,6 @@ static struct whpx_sreg_match whpx_sreg_match[] = {
> { WHvArm64RegisterSpEl1, ENCODE_AA64_CP_REG(4, 1, 3, 4, 0) },
> };
>
>-static void flush_cpu_state(CPUState *cpu)
>-{
>- if (cpu->vcpu_dirty) {
>- whpx_set_registers(cpu, WHPX_SET_RUNTIME_STATE);
>- cpu->vcpu_dirty = false;
>- }
>-}
>-
> HRESULT whpx_set_exception_exit_bitmap(UINT64 exceptions)
> {
> if (exceptions != 0) {
>@@ -314,33 +306,6 @@ void whpx_arch_destroy_vcpu(CPUState *cpu)
> /* currently empty on Arm */
> }
>
>-static void whpx_get_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE* val)
>-{
>- struct whpx_state *whpx = &whpx_global;
>- HRESULT hr;
>-
>- flush_cpu_state(cpu);
>-
>- hr = whp_dispatch.WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
>- ®, 1, val);
>-
>- if (FAILED(hr)) {
>- error_report("WHPX: Failed to get register %08x, hr=%08lx", reg, hr);
>- }
>-}
>-
>-static void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE val)
>-{
>- struct whpx_state *whpx = &whpx_global;
>- HRESULT hr;
>- hr = whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
>- ®, 1, &val);
>-
>- if (FAILED(hr)) {
>- error_report("WHPX: Failed to set register %08x, hr=%08lx", reg, hr);
>- }
>-}
>-
> static void whpx_get_global_reg(WHV_REGISTER_NAME reg, WHV_REGISTER_VALUE *val)
> {
> struct whpx_state *whpx = &whpx_global;
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-02-16 20:46 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-15 5:22 [PATCH v3 00/14] whpx: x86 updates (2026-02) Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 01/14] target/i386/emulate/x86_decode: Fix compiler warning Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 02/14] target/i386/hvf/x86_mmu: " Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 03/14] target/i386/emulate/x86_decode: Actually use stream in decode_instruction_stream() Mohamed Mediouni
2026-02-16 11:23 ` Magnus Kulke
2026-02-15 5:22 ` [PATCH v3 04/14] target/i386: emulate, hvf: move x86_mmu to common code Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 05/14] whpx: i386: re-enable guest debug support Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 06/14] whpx: preparatory changes before switching over from winhvemulation Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 07/14] whpx: refactor whpx_destroy_vcpu to arch-specific function Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 08/14] whpx: move whpx_get_reg/whpx_set_reg to generic code Mohamed Mediouni
2026-02-16 18:45 ` Bernhard Beschow
2026-02-15 5:22 ` [PATCH v3 09/14] whpx: i386: switch over from winhvemulation to target/i386/emulate Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 10/14] whpx: i386: remove remaining winhvemulation support code Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 11/14] whpx: i386: remove messages Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 12/14] whpx: i386: remove CPUID trapping Mohamed Mediouni
2026-02-15 5:22 ` [PATCH v3 13/14] whpx: common, i386, arm: rework state levels Mohamed Mediouni
2026-02-16 17:27 ` Philippe Mathieu-Daudé
2026-02-15 5:22 ` [PATCH v3 14/14] whpx: i386: saving/restoring less state for WHPX_LEVEL_FAST_RUNTIME_STATE Mohamed Mediouni
2026-02-16 18:41 ` Bernhard Beschow
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.