All of lore.kernel.org
 help / color / mirror / Atom feed
* [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,
+         &reg, 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,
+         &reg, 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,
-         &reg, 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,
-         &reg, 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);
+    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, &reg);
+        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,
>+         &reg, 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,
>+         &reg, 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,
>-         &reg, 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,
>-         &reg, 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.