* [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access
@ 2026-05-05 18:50 Doru Blânzeanu
2026-05-05 18:50 ` [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers Doru Blânzeanu
` (7 more replies)
0 siblings, 8 replies; 20+ messages in thread
From: Doru Blânzeanu @ 2026-05-05 18:50 UTC (permalink / raw)
To: qemu-devel
Cc: Doru Blânzeanu, Magnus Kulke, Zhao Liu, Wei Liu,
Paolo Bonzini
This series adds support for using the hypervisor's vp register page
in the mshv accelerator to optimize vcpu register access on mmio and pio
exits.
Currently, all register reads and write go through hypercalls (ioctls),
which adds overhead on every VM exit. The VP register page is a shared
memory page that the hypervisor populates with vcpu register state,
allowing Qemu to read and write registers directly without hypercalls.
The series is structured as follows:
1. Remove the duplicate `fetch_guest_state` function, consolidating
register loading into `mshv_load_regs`.
2. Move `mshv_arch_init_vcpu` after vcpu creation so the vcpu fd is
valid when we need it for mmap.
3. Define the `hv_vp_register_page` structure in `hvgdk_mini.h`, matching
the layout used by the Linux kernel's mshv driver.
4. Set up the register page by mmapping the vcpu fd at init time. If the
mmap fails, we fall back gracefully to the existing hypercall path.
5. Use the register page to read registers on VM exit. General purpose
registers, RIP, RFLAGS, segment registers, and control registers
(CR0, CR4, CR4, CR8, EFER) are read directly from the page. Registers
not present on the page (TR, LDTR, GDTR, IDTR, CR2, APIC_BASE) are still
fetched via hypercall.
6. Use register page to write registers on vmentry. GP registers,
RIP, and RFLAGS are written to the page with the appropriate dirty
bits set, avoiding the hypercall for the standard register store.
The register page is only used when it has been successfully mmapped and
the hypervisor has marked it as valid (`isvalid != 0`). Otherwise, the
existing hypercall-based path is used as a fallback.
Changes since v1:
- move hv_register_page struct definition to hvhdk.h
- add a compile time guard around regs_page in CPUArchState
- modify mshv_get_special_regs_vp_page to only retrieve the special
registers present in the register page (removed TR, LDTR, GDTR, IDTR,
CR2, APIC_BASE)
In local testing this hasn't created any regressions, and it is unlikely
that the mmio operations need this registers.
We'll want to keep an eye on this in case there are decoded operations
that rely on fetching these registers on every VM exit.
- add commit to fix handle_pio_non_str and handle_pio_str to correctly
store modified registers back to the register page after the pio
operation, and clear the cpu->accel->dirty flag to avoid the
mshv_arch_put_registers from resetting some registers state (fpu).
- modified register page setup to signal an error instead of a warning
in case mmap fails.
I am not sure aborting here is fine because it would make some of the
fallback logic redundant, and I think that's a bigger refactoring.
Doru Blânzeanu (7):
target/i386/mshv: remove duplicate function for reading vcpu registers
accel/mshv: move vcpu arch specific initialization after vcpu creation
include/hw/hyperv: add hv_vp_register_page struct definition
target/i386/mshv: hv_vp_register_page setup for the vcpu
target/i386/mshv: use the register page to get registers
target/i386/mshv: use the register page to set registers
target/i386/mshv: fix pio handlers clobbering device-modified
registers
accel/mshv/mshv-all.c | 3 +-
include/hw/hyperv/hvgdk.h | 2 +
include/hw/hyperv/hvhdk.h | 105 ++++++++++++++
target/i386/cpu.h | 5 +
target/i386/mshv/mshv-cpu.c | 269 ++++++++++++++++++++++++++++--------
5 files changed, 327 insertions(+), 57 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers
2026-05-05 18:50 [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
@ 2026-05-05 18:50 ` Doru Blânzeanu
2026-05-06 10:34 ` Magnus Kulke
` (2 more replies)
2026-05-05 18:50 ` [PATCH v2 2/7] accel/mshv: move vcpu arch specific initialization after vcpu creation Doru Blânzeanu
` (6 subsequent siblings)
7 siblings, 3 replies; 20+ messages in thread
From: Doru Blânzeanu @ 2026-05-05 18:50 UTC (permalink / raw)
To: qemu-devel
Cc: Doru Blânzeanu, Magnus Kulke, Zhao Liu, Wei Liu,
Paolo Bonzini
Remove function `fetch_guest_state` because it is a duplicate function
of `mshv_load_regs` function.
Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
---
target/i386/mshv/mshv-cpu.c | 21 +--------------------
1 file changed, 1 insertion(+), 20 deletions(-)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 4ed6e7548f..9defd05db6 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -1291,25 +1291,6 @@ static int handle_pio_non_str(const CPUState *cpu,
return 0;
}
-static int fetch_guest_state(CPUState *cpu)
-{
- int ret;
-
- ret = mshv_get_standard_regs(cpu);
- if (ret < 0) {
- error_report("Failed to get standard registers");
- return -1;
- }
-
- ret = mshv_get_special_regs(cpu);
- if (ret < 0) {
- error_report("Failed to get special registers");
- return -1;
- }
-
- return 0;
-}
-
static int read_memory(const CPUState *cpu, uint64_t initial_gva,
uint64_t initial_gpa, uint64_t gva, uint8_t *data,
size_t len)
@@ -1429,7 +1410,7 @@ static int handle_pio_str(CPUState *cpu, hv_x64_io_port_intercept_message *info)
X86CPU *x86_cpu = X86_CPU(cpu);
CPUX86State *env = &x86_cpu->env;
- ret = fetch_guest_state(cpu);
+ ret = mshv_load_regs(cpu);
if (ret < 0) {
error_report("Failed to fetch guest state");
return -1;
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 2/7] accel/mshv: move vcpu arch specific initialization after vcpu creation
2026-05-05 18:50 [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
2026-05-05 18:50 ` [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers Doru Blânzeanu
@ 2026-05-05 18:50 ` Doru Blânzeanu
2026-05-06 14:31 ` Magnus Kulke
2026-05-07 13:12 ` Anirudh Rayabharam
2026-05-05 18:50 ` [PATCH v2 3/7] include/hw/hyperv: add hv_vp_register_page struct definition Doru Blânzeanu
` (5 subsequent siblings)
7 siblings, 2 replies; 20+ messages in thread
From: Doru Blânzeanu @ 2026-05-05 18:50 UTC (permalink / raw)
To: qemu-devel
Cc: Doru Blânzeanu, Magnus Kulke, Zhao Liu, Wei Liu,
Paolo Bonzini
Call mshv_arch_init_vcpu after the vcpu is created to ensure a valid
vcpu fd.
Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
---
accel/mshv/mshv-all.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c
index 58af674bd9..e3da583f21 100644
--- a/accel/mshv/mshv-all.c
+++ b/accel/mshv/mshv-all.c
@@ -415,13 +415,14 @@ static int mshv_init_vcpu(CPUState *cpu)
int ret;
cpu->accel = g_new0(AccelCPUState, 1);
- mshv_arch_init_vcpu(cpu);
ret = mshv_create_vcpu(vm_fd, vp_index, &cpu->accel->cpufd);
if (ret < 0) {
return -1;
}
+ mshv_arch_init_vcpu(cpu);
+
cpu->accel->dirty = true;
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 3/7] include/hw/hyperv: add hv_vp_register_page struct definition
2026-05-05 18:50 [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
2026-05-05 18:50 ` [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers Doru Blânzeanu
2026-05-05 18:50 ` [PATCH v2 2/7] accel/mshv: move vcpu arch specific initialization after vcpu creation Doru Blânzeanu
@ 2026-05-05 18:50 ` Doru Blânzeanu
2026-05-06 10:38 ` Magnus Kulke
2026-05-07 13:15 ` Anirudh Rayabharam
2026-05-05 18:50 ` [PATCH v2 4/7] target/i386/mshv: hv_vp_register_page setup for the vcpu Doru Blânzeanu
` (4 subsequent siblings)
7 siblings, 2 replies; 20+ messages in thread
From: Doru Blânzeanu @ 2026-05-05 18:50 UTC (permalink / raw)
To: qemu-devel
Cc: Doru Blânzeanu, Magnus Kulke, Zhao Liu, Wei Liu,
Paolo Bonzini
Define the `hv_vp_register_page` structure that the linux kernel uses
to allow access to vcpu registers.
This structure is going to be used in later patches to access vcpu
registers.
Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
---
include/hw/hyperv/hvgdk.h | 2 +
include/hw/hyperv/hvhdk.h | 105 ++++++++++++++++++++++++++++++++++++++
2 files changed, 107 insertions(+)
diff --git a/include/hw/hyperv/hvgdk.h b/include/hw/hyperv/hvgdk.h
index 71161f477c..e4be861716 100644
--- a/include/hw/hyperv/hvgdk.h
+++ b/include/hw/hyperv/hvgdk.h
@@ -9,6 +9,8 @@
#ifndef HW_HYPERV_HVGDK_H
#define HW_HYPERV_HVGDK_H
+#include "hvgdk_mini.h"
+
#define HVGDK_H_VERSION (25125)
enum hv_unimplemented_msr_action {
diff --git a/include/hw/hyperv/hvhdk.h b/include/hw/hyperv/hvhdk.h
index 41af743847..4a3b543893 100644
--- a/include/hw/hyperv/hvhdk.h
+++ b/include/hw/hyperv/hvhdk.h
@@ -9,7 +9,11 @@
#ifndef HW_HYPERV_HVHDK_H
#define HW_HYPERV_HVHDK_H
+#include "hvgdk.h"
+#include "hvhdk_mini.h"
+
#define HV_PARTITION_SYNTHETIC_PROCESSOR_FEATURES_BANKS 1
+#define HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT 7
struct hv_input_set_partition_property {
uint64_t partition_id;
@@ -246,4 +250,105 @@ typedef struct hv_input_register_intercept_result {
union hv_register_intercept_result_parameters parameters;
} QEMU_PACKED hv_input_register_intercept_result;
+/* Flags for dirty mask of hv_vp_register_page */
+enum hv_x64_register_class_type {
+ HV_X64_REGISTER_CLASS_GENERAL = 0,
+ HV_X64_REGISTER_CLASS_IP = 1,
+ HV_X64_REGISTER_CLASS_XMM = 2,
+ HV_X64_REGISTER_CLASS_SEGMENT = 3,
+ HV_X64_REGISTER_CLASS_FLAGS = 4,
+};
+
+union hv_vp_register_page_interrupt_vectors {
+ uint64_t as_uint64;
+ struct {
+ uint8_t vector_count;
+ uint8_t vector[HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT];
+ };
+};
+
+struct hv_vp_register_page {
+ uint16_t version;
+ uint8_t isvalid;
+ uint8_t rsvdz;
+ uint32_t dirty;
+
+ union {
+ struct {
+ /* General purpose registers (HV_X64_REGISTER_CLASS_GENERAL) */
+ union {
+ struct {
+ uint64_t rax;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbx;
+ uint64_t rsp;
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ } QEMU_PACKED;
+
+ uint64_t gp_registers[16];
+ };
+ /* Instruction pointer (HV_X64_REGISTER_CLASS_IP) */
+ uint64_t rip;
+ /* Flags (HV_X64_REGISTER_CLASS_FLAGS) */
+ uint64_t rflags;
+ } QEMU_PACKED;
+
+ uint64_t registers[18];
+ };
+ uint8_t reserved[8];
+ /* Volatile XMM registers (HV_X64_REGISTER_CLASS_XMM) */
+ union {
+ struct {
+ struct hv_u128 xmm0;
+ struct hv_u128 xmm1;
+ struct hv_u128 xmm2;
+ struct hv_u128 xmm3;
+ struct hv_u128 xmm4;
+ struct hv_u128 xmm5;
+ } QEMU_PACKED;
+
+ struct hv_u128 xmm_registers[6];
+ };
+ /* Segment registers (HV_X64_REGISTER_CLASS_SEGMENT) */
+ union {
+ struct {
+ struct hv_x64_segment_register es;
+ struct hv_x64_segment_register cs;
+ struct hv_x64_segment_register ss;
+ struct hv_x64_segment_register ds;
+ struct hv_x64_segment_register fs;
+ struct hv_x64_segment_register gs;
+ } QEMU_PACKED;
+
+ struct hv_x64_segment_register segment_registers[6];
+ };
+ /* Misc. control registers (cannot be set via this interface) */
+ uint64_t cr0;
+ uint64_t cr3;
+ uint64_t cr4;
+ uint64_t cr8;
+ uint64_t efer;
+ uint64_t dr7;
+ union hv_x64_pending_interruption_register pending_interruption;
+ union hv_x64_interrupt_state_register interrupt_state;
+ uint64_t instruction_emulation_hints;
+ uint64_t xfem;
+
+ uint8_t reserved1[0x100];
+
+ /* Interrupts injected as part of HvCallDispatchVp. */
+ union hv_vp_register_page_interrupt_vectors interrupt_vectors;
+} QEMU_PACKED;
+
#endif /* HW_HYPERV_HVHDK_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 4/7] target/i386/mshv: hv_vp_register_page setup for the vcpu
2026-05-05 18:50 [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
` (2 preceding siblings ...)
2026-05-05 18:50 ` [PATCH v2 3/7] include/hw/hyperv: add hv_vp_register_page struct definition Doru Blânzeanu
@ 2026-05-05 18:50 ` Doru Blânzeanu
2026-05-06 14:36 ` Magnus Kulke
2026-05-05 18:50 ` [PATCH v2 5/7] target/i386/mshv: use the register page to get registers Doru Blânzeanu
` (3 subsequent siblings)
7 siblings, 1 reply; 20+ messages in thread
From: Doru Blânzeanu @ 2026-05-05 18:50 UTC (permalink / raw)
To: qemu-devel
Cc: Doru Blânzeanu, Magnus Kulke, Zhao Liu, Wei Liu,
Paolo Bonzini
When the vcpu is created, call mmap to configure access to the register page.
In case the call to mmap fails, we log an error and continue with the
previous logic (using hypercalls).
Update CPUArchState to store a pointer to the mmapped hv_vp_register_page.
Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
---
target/i386/cpu.h | 5 +++++
target/i386/mshv/mshv-cpu.c | 22 ++++++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 16de67e546..fd4c3712b1 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2019,6 +2019,11 @@ typedef struct CPUArchState {
uint64_t msr_bndcfgs;
uint64_t efer;
+#ifdef CONFIG_MSHV
+ /* Shared register page */
+ struct hv_vp_register_page *regs_page;
+#endif
+
/* Beginning of state preserved by INIT (dummy marker). */
struct {} start_init_save;
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 9defd05db6..3a3c269c33 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -1587,6 +1587,7 @@ void mshv_arch_init_vcpu(CPUState *cpu)
CPUX86State *env = &x86_cpu->env;
AccelCPUState *state = cpu->accel;
size_t page = HV_HYP_PAGE_SIZE;
+ void *regs_page;
void *mem = qemu_memalign(page, 2 * page);
/* sanity check, to make sure we don't overflow the page */
@@ -1595,6 +1596,22 @@ void mshv_arch_init_vcpu(CPUState *cpu)
+ sizeof(hv_input_get_vp_registers)
> HV_HYP_PAGE_SIZE));
+
+ /* mmap the registers page */
+ regs_page = mmap(NULL, page, PROT_READ | PROT_WRITE,
+ MAP_SHARED, mshv_vcpufd(cpu),
+ MSHV_VP_MMAP_OFFSET_REGISTERS * page);
+ if (regs_page == MAP_FAILED) {
+ /*
+ * Error is not fatal, but we won't be able to use the
+ * fast path for register access
+ */
+ error_report("register page mmap failed: %s", strerror(errno));
+ env->regs_page = NULL;
+ } else {
+ env->regs_page = (struct hv_vp_register_page *) regs_page;
+ }
+
state->hvcall_args.base = mem;
state->hvcall_args.input_page = mem;
state->hvcall_args.output_page = (uint8_t *)mem + page;
@@ -1608,6 +1625,11 @@ void mshv_arch_destroy_vcpu(CPUState *cpu)
CPUX86State *env = &x86_cpu->env;
AccelCPUState *state = cpu->accel;
+ /* Unmap the register page */
+ if (env->regs_page) {
+ munmap(env->regs_page, HV_HYP_PAGE_SIZE);
+ env->regs_page = NULL;
+ }
g_free(state->hvcall_args.base);
state->hvcall_args = (MshvHvCallArgs){0};
g_clear_pointer(&env->emu_mmio_buf, g_free);
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 5/7] target/i386/mshv: use the register page to get registers
2026-05-05 18:50 [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
` (3 preceding siblings ...)
2026-05-05 18:50 ` [PATCH v2 4/7] target/i386/mshv: hv_vp_register_page setup for the vcpu Doru Blânzeanu
@ 2026-05-05 18:50 ` Doru Blânzeanu
2026-05-07 13:23 ` Anirudh Rayabharam
2026-05-05 18:50 ` [PATCH v2 6/7] target/i386/mshv: use the register page to set registers Doru Blânzeanu
` (2 subsequent siblings)
7 siblings, 1 reply; 20+ messages in thread
From: Doru Blânzeanu @ 2026-05-05 18:50 UTC (permalink / raw)
To: qemu-devel
Cc: Doru Blânzeanu, Magnus Kulke, Zhao Liu, Wei Liu,
Paolo Bonzini
Change the mshv_load_regs to use the register page when it is mmapped
and is valid.
Otherwise use the existing logic that uses ioctls to fetch registers.
When retrieving the special registers, there are some registers that are
not present in the register page: TR, LDTR, GDTR, IDTR, CR2, APIC_BASE.
As this registers are not likely to be used in an MMIO/PIO operation,
and to avoid a hypercall overhead we do not retrieve them.
Local testing showed no regression when using this logic. To properly
retrieve all the necessary registers for each decoded operation implies
having a mechanism that tracks the state of each register, which is
beyond the scope of this patch series.
Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
---
target/i386/mshv/mshv-cpu.c | 99 +++++++++++++++++++++++++++++++++----
1 file changed, 90 insertions(+), 9 deletions(-)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 3a3c269c33..c84d3f76de 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -401,6 +401,80 @@ static void populate_special_regs(const hv_register_assoc *assocs,
cpu_set_apic_base(x86cpu->apic_state, assocs[16].value.reg64);
}
+static void mshv_get_standard_regs_vp_page(CPUState *cpu)
+{
+ X86CPU *x86cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86cpu->env;
+
+ /* General Purpose Registers */
+ env->regs[R_EAX] = env->regs_page->rax;
+ env->regs[R_EBX] = env->regs_page->rbx;
+ env->regs[R_ECX] = env->regs_page->rcx;
+ env->regs[R_EDX] = env->regs_page->rdx;
+ env->regs[R_ESI] = env->regs_page->rsi;
+ env->regs[R_EDI] = env->regs_page->rdi;
+ env->regs[R_ESP] = env->regs_page->rsp;
+ env->regs[R_EBP] = env->regs_page->rbp;
+ env->regs[R_R8] = env->regs_page->r8;
+ env->regs[R_R9] = env->regs_page->r9;
+ env->regs[R_R10] = env->regs_page->r10;
+ env->regs[R_R11] = env->regs_page->r11;
+ env->regs[R_R12] = env->regs_page->r12;
+ env->regs[R_R13] = env->regs_page->r13;
+ env->regs[R_R14] = env->regs_page->r14;
+ env->regs[R_R15] = env->regs_page->r15;
+
+ env->eip = env->regs_page->rip;
+ env->eflags = env->regs_page->rflags;
+ rflags_to_lflags(env);
+}
+
+/*
+ * This function synchronizes the special registers present in the
+ * register vp page, which are not all the special registers.
+ * The rest of the special registers (LD, TR, GDT, IDT, CR2, APIC_BASE)
+ * are not synchronized to avoid the overhead of a hypercall.
+ *
+ * These special registers are not normally used by the guest,
+ * and are only used in some specific cases.
+ */
+static void mshv_get_special_regs_vp_page(CPUState *cpu)
+{
+ X86CPU *x86cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86cpu->env;
+ hv_x64_segment_register seg;
+
+ /* Populate special registers that are in the VP register page */
+ env->cr[0] = env->regs_page->cr0;
+ env->cr[3] = env->regs_page->cr3;
+ env->cr[4] = env->regs_page->cr4;
+ env->efer = env->regs_page->efer;
+ cpu_set_apic_tpr(x86cpu->apic_state, env->regs_page->cr8);
+
+ /* Segment Registers - copy from packed struct to avoid unaligned access */
+ memcpy(&seg, &env->regs_page->es, sizeof(hv_x64_segment_register));
+ populate_segment_reg(&seg, &env->segs[R_ES]);
+ memcpy(&seg, &env->regs_page->cs, sizeof(hv_x64_segment_register));
+ populate_segment_reg(&seg, &env->segs[R_CS]);
+ memcpy(&seg, &env->regs_page->ss, sizeof(hv_x64_segment_register));
+ populate_segment_reg(&seg, &env->segs[R_SS]);
+ memcpy(&seg, &env->regs_page->ds, sizeof(hv_x64_segment_register));
+ populate_segment_reg(&seg, &env->segs[R_DS]);
+ memcpy(&seg, &env->regs_page->fs, sizeof(hv_x64_segment_register));
+ populate_segment_reg(&seg, &env->segs[R_FS]);
+ memcpy(&seg, &env->regs_page->gs, sizeof(hv_x64_segment_register));
+ populate_segment_reg(&seg, &env->segs[R_GS]);
+}
+
+static void mshv_get_registers_vp_page(CPUState *cpu)
+{
+ /* General Purpose Registers */
+ mshv_get_standard_regs_vp_page(cpu);
+
+ /* Special Registers */
+ mshv_get_special_regs_vp_page(cpu);
+}
+
int mshv_get_special_regs(CPUState *cpu)
{
@@ -424,18 +498,25 @@ int mshv_get_special_regs(CPUState *cpu)
int mshv_load_regs(CPUState *cpu)
{
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
int ret;
- ret = mshv_get_standard_regs(cpu);
- if (ret < 0) {
- error_report("Failed to load standard registers");
- return -1;
- }
+ /* Use register vp page to optimize registers access */
+ if (env->regs_page && env->regs_page->isvalid != 0) {
+ mshv_get_registers_vp_page(cpu);
+ } else {
+ ret = mshv_get_standard_regs(cpu);
+ if (ret < 0) {
+ error_report("Failed to load standard registers");
+ return -1;
+ }
- ret = mshv_get_special_regs(cpu);
- if (ret < 0) {
- error_report("Failed to load special registers");
- return -1;
+ ret = mshv_get_special_regs(cpu);
+ if (ret < 0) {
+ error_report("Failed to load special registers");
+ return -1;
+ }
}
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 6/7] target/i386/mshv: use the register page to set registers
2026-05-05 18:50 [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
` (4 preceding siblings ...)
2026-05-05 18:50 ` [PATCH v2 5/7] target/i386/mshv: use the register page to get registers Doru Blânzeanu
@ 2026-05-05 18:50 ` Doru Blânzeanu
2026-05-07 13:29 ` Anirudh Rayabharam
2026-05-05 18:50 ` [PATCH v2 7/7] target/i386/mshv: fix pio handlers clobbering device-modified registers Doru Blânzeanu
2026-05-06 14:43 ` [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Magnus Kulke
7 siblings, 1 reply; 20+ messages in thread
From: Doru Blânzeanu @ 2026-05-05 18:50 UTC (permalink / raw)
To: qemu-devel
Cc: Doru Blânzeanu, Magnus Kulke, Zhao Liu, Wei Liu,
Paolo Bonzini
Update mshv_store_regs to use the register page when it is mmapped and
valid to set registers.
Otherwise use the ioctls to set the registers.
Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
---
target/i386/mshv/mshv-cpu.c | 45 +++++++++++++++++++++++++++++++++----
1 file changed, 41 insertions(+), 4 deletions(-)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index c84d3f76de..0cfac26a5c 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -285,14 +285,51 @@ static int set_standard_regs(const CPUState *cpu)
return 0;
}
+static void mshv_set_standard_regs_vp_page(CPUState *cpu)
+{
+ X86CPU *x86cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86cpu->env;
+
+ env->regs_page->rax = env->regs[R_EAX];
+ env->regs_page->rbx = env->regs[R_EBX];
+ env->regs_page->rcx = env->regs[R_ECX];
+ env->regs_page->rdx = env->regs[R_EDX];
+ env->regs_page->rsi = env->regs[R_ESI];
+ env->regs_page->rdi = env->regs[R_EDI];
+ env->regs_page->rsp = env->regs[R_ESP];
+ env->regs_page->rbp = env->regs[R_EBP];
+ env->regs_page->r8 = env->regs[R_R8];
+ env->regs_page->r9 = env->regs[R_R9];
+ env->regs_page->r10 = env->regs[R_R10];
+ env->regs_page->r11 = env->regs[R_R11];
+ env->regs_page->r12 = env->regs[R_R12];
+ env->regs_page->r13 = env->regs[R_R13];
+ env->regs_page->r14 = env->regs[R_R14];
+ env->regs_page->r15 = env->regs[R_R15];
+ env->regs_page->rip = env->eip;
+ lflags_to_rflags(env);
+ env->regs_page->rflags = env->eflags;
+
+ env->regs_page->dirty |= (1u << HV_X64_REGISTER_CLASS_GENERAL)
+ | (1u << HV_X64_REGISTER_CLASS_IP)
+ | (1u << HV_X64_REGISTER_CLASS_FLAGS);
+}
+
int mshv_store_regs(CPUState *cpu)
{
+ X86CPU *x86cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86cpu->env;
int ret;
- ret = set_standard_regs(cpu);
- if (ret < 0) {
- error_report("Failed to store standard registers");
- return -1;
+ /* Use register vp page to optimize registers access */
+ if (env->regs_page && env->regs_page->isvalid != 0) {
+ mshv_set_standard_regs_vp_page(cpu);
+ } else {
+ ret = set_standard_regs(cpu);
+ if (ret < 0) {
+ error_report("Failed to store standard registers");
+ return -1;
+ }
}
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 7/7] target/i386/mshv: fix pio handlers clobbering device-modified registers
2026-05-05 18:50 [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
` (5 preceding siblings ...)
2026-05-05 18:50 ` [PATCH v2 6/7] target/i386/mshv: use the register page to set registers Doru Blânzeanu
@ 2026-05-05 18:50 ` Doru Blânzeanu
2026-05-06 14:38 ` Magnus Kulke
2026-05-06 14:43 ` [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Magnus Kulke
7 siblings, 1 reply; 20+ messages in thread
From: Doru Blânzeanu @ 2026-05-05 18:50 UTC (permalink / raw)
To: qemu-devel
Cc: Doru Blânzeanu, Magnus Kulke, Zhao Liu, Wei Liu,
Paolo Bonzini
When a device handler (e.g. vmport) calls cpu_synchronize_state() during
I/O port dispatch, it sets cpu->accel->dirty = true and may modify
registers directly in env. The old PIO code ignored this: it
unconditionally wrote the stale info->rax from the VM-exit intercept
message back to the hypervisor and then cleared dirty, discarding any
register changes made by the device.
Bifurcate both handlers on cpu->accel->dirty:
handle_pio_non_str:
- dirty path: update env->eip directly. For reads (IN), merge the I/O
result into env->regs[R_EAX] (which may have been modified by the
device) rather than info->rax. For writes (OUT), leave RAX untouched.
Flush all registers via mshv_store_regs() and clear dirty.
- non-dirty path: write RIP and RAX via set_x64_registers hypercall as
before.
handle_pio_str:
- dirty path: update env->eip and the appropriate index register
(RSI for OUTS, RDI for INS) directly. Flush via mshv_store_regs()
and clear dirty.
- non-dirty path: write the index register and RIP via
set_x64_registers. Drop the RAX assignment that was here before;
string I/O does not modify RAX, and set_x64_registers is hardcoded
to write only 2 registers so the third slot was silently ignored
anyway.
Remove the unconditional "cpu->accel->dirty = false" at the end of both
handlers. In the non-dirty fast path it was redundant (already false).
In the dirty path it was actively harmful: it told the vcpu run loop
that env was clean when it was not, losing the device's modifications.
Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
---
target/i386/mshv/mshv-cpu.c | 82 ++++++++++++++++++++++++++-----------
1 file changed, 59 insertions(+), 23 deletions(-)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 0cfac26a5c..7be3fdcc45 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -1348,7 +1348,7 @@ static int pio_write(uint64_t port, const uint8_t *data, uintptr_t size,
return ret;
}
-static int handle_pio_non_str(const CPUState *cpu,
+static int handle_pio_non_str(CPUState *cpu,
hv_x64_io_port_intercept_message *info)
{
size_t len = info->access_info.access_size;
@@ -1357,10 +1357,12 @@ static int handle_pio_non_str(const CPUState *cpu,
uint32_t val, eax;
const uint32_t eax_mask = 0xffffffffu >> (32 - len * 8);
size_t insn_len;
- uint64_t rip, rax;
+ uint64_t rip;
uint32_t reg_names[2];
uint64_t reg_values[2];
uint16_t port = info->port_number;
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
if (access_type == HV_X64_INTERCEPT_ACCESS_TYPE_WRITE) {
union {
@@ -1391,21 +1393,40 @@ static int handle_pio_non_str(const CPUState *cpu,
/* Advance RIP and update RAX */
rip = info->header.rip + insn_len;
- rax = info->rax;
- reg_names[0] = HV_X64_REGISTER_RIP;
- reg_values[0] = rip;
- reg_names[1] = HV_X64_REGISTER_RAX;
- reg_values[1] = rax;
+ if (cpu->accel->dirty) {
+ env->eip = rip;
+ if (access_type != HV_X64_INTERCEPT_ACCESS_TYPE_WRITE) {
+ /*
+ * For reads, merge the I/O result into the current RAX.
+ * Use env->regs[R_EAX] as the base since a device handler
+ * (e.g. vmport) may have called cpu_synchronize_state()
+ * and modified registers.
+ */
+ eax = (((uint32_t)env->regs[R_EAX]) & ~eax_mask)
+ | (val & eax_mask);
+ env->regs[R_EAX] = (uint64_t)eax;
+ }
+ /* Sync modified standard registers back and clear dirty. */
+ ret = mshv_store_regs(cpu);
+ if (ret < 0) {
+ error_report("Failed to store registers after PIO");
+ return -1;
+ }
+ cpu->accel->dirty = false;
+ } else {
+ reg_names[0] = HV_X64_REGISTER_RIP;
+ reg_values[0] = rip;
+ reg_names[1] = HV_X64_REGISTER_RAX;
+ reg_values[1] = info->rax;
- ret = set_x64_registers(cpu, reg_names, reg_values);
- if (ret < 0) {
- error_report("Failed to set x64 registers");
- return -1;
+ ret = set_x64_registers(cpu, reg_names, reg_values);
+ if (ret < 0) {
+ error_report("Failed to set x64 registers");
+ return -1;
+ }
}
- cpu->accel->dirty = false;
-
return 0;
}
@@ -1521,6 +1542,7 @@ static int handle_pio_str(CPUState *cpu, hv_x64_io_port_intercept_message *info)
bool repop = info->access_info.rep_prefix == 1;
size_t repeat = repop ? info->rcx : 1;
size_t insn_len = info->header.instruction_length;
+ uint64_t rip;
bool direction_flag;
uint32_t reg_names[3];
uint64_t reg_values[3];
@@ -1554,18 +1576,32 @@ static int handle_pio_str(CPUState *cpu, hv_x64_io_port_intercept_message *info)
reg_values[0] = info->rdi;
}
- reg_names[1] = HV_X64_REGISTER_RIP;
- reg_values[1] = info->header.rip + insn_len;
- reg_names[2] = HV_X64_REGISTER_RAX;
- reg_values[2] = info->rax;
+ rip = info->header.rip + insn_len;
- ret = set_x64_registers(cpu, reg_names, reg_values);
- if (ret < 0) {
- error_report("Failed to set x64 registers");
- return -1;
- }
+ if (cpu->accel->dirty) {
+ env->eip = rip;
+ if (access_type == HV_X64_INTERCEPT_ACCESS_TYPE_WRITE) {
+ env->regs[R_ESI] = info->rsi;
+ } else {
+ env->regs[R_EDI] = info->rdi;
+ }
+ /* Sync modified standard registers back and clear dirty. */
+ ret = mshv_store_regs(cpu);
+ if (ret < 0) {
+ error_report("Failed to store registers after string PIO");
+ return -1;
+ }
+ cpu->accel->dirty = false;
+ } else {
+ reg_names[1] = HV_X64_REGISTER_RIP;
+ reg_values[1] = rip;
- cpu->accel->dirty = false;
+ ret = set_x64_registers(cpu, reg_names, reg_values);
+ if (ret < 0) {
+ error_report("Failed to set x64 registers");
+ return -1;
+ }
+ }
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers
2026-05-05 18:50 ` [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers Doru Blânzeanu
@ 2026-05-06 10:34 ` Magnus Kulke
2026-05-06 10:35 ` Magnus Kulke
2026-05-07 13:12 ` Anirudh Rayabharam
2 siblings, 0 replies; 20+ messages in thread
From: Magnus Kulke @ 2026-05-06 10:34 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:22PM +0300, Doru Blânzeanu wrote:
> Remove function `fetch_guest_state` because it is a duplicate function
> of `mshv_load_regs` function.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> target/i386/mshv/mshv-cpu.c | 21 +--------------------
> 1 file changed, 1 insertion(+), 20 deletions(-)
>
> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
> index 4ed6e7548f..9defd05db6 100644
> --- a/target/i386/mshv/mshv-cpu.c
> +++ b/target/i386/mshv/mshv-cpu.c
> @@ -1291,25 +1291,6 @@ static int handle_pio_non_str(const CPUState *cpu,
> return 0;
> }
>
> -static int fetch_guest_state(CPUState *cpu)
> -{
> - int ret;
> -
> - ret = mshv_get_standard_regs(cpu);
> - if (ret < 0) {
> - error_report("Failed to get standard registers");
> - return -1;
> - }
> -
> - ret = mshv_get_special_regs(cpu);
> - if (ret < 0) {
> - error_report("Failed to get special registers");
> - return -1;
> - }
> -
> - return 0;
> -}
> -
> static int read_memory(const CPUState *cpu, uint64_t initial_gva,
> uint64_t initial_gpa, uint64_t gva, uint8_t *data,
> size_t len)
> @@ -1429,7 +1410,7 @@ static int handle_pio_str(CPUState *cpu, hv_x64_io_port_intercept_message *info)
> X86CPU *x86_cpu = X86_CPU(cpu);
> CPUX86State *env = &x86_cpu->env;
>
> - ret = fetch_guest_state(cpu);
> + ret = mshv_load_regs(cpu);
> if (ret < 0) {
> error_report("Failed to fetch guest state");
> return -1;
> --
> 2.53.0
Reviewed-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers
2026-05-05 18:50 ` [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers Doru Blânzeanu
2026-05-06 10:34 ` Magnus Kulke
@ 2026-05-06 10:35 ` Magnus Kulke
2026-05-07 13:12 ` Anirudh Rayabharam
2 siblings, 0 replies; 20+ messages in thread
From: Magnus Kulke @ 2026-05-06 10:35 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:22PM +0300, Doru Blânzeanu wrote:
> Remove function `fetch_guest_state` because it is a duplicate function
> of `mshv_load_regs` function.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> target/i386/mshv/mshv-cpu.c | 21 +--------------------
> 1 file changed, 1 insertion(+), 20 deletions(-)
>
> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
> index 4ed6e7548f..9defd05db6 100644
> --- a/target/i386/mshv/mshv-cpu.c
> +++ b/target/i386/mshv/mshv-cpu.c
> @@ -1291,25 +1291,6 @@ static int handle_pio_non_str(const CPUState *cpu,
> return 0;
> }
>
> -static int fetch_guest_state(CPUState *cpu)
> -{
> - int ret;
> -
> - ret = mshv_get_standard_regs(cpu);
> - if (ret < 0) {
> - error_report("Failed to get standard registers");
> - return -1;
> - }
> -
> - ret = mshv_get_special_regs(cpu);
> - if (ret < 0) {
> - error_report("Failed to get special registers");
> - return -1;
> - }
> -
> - return 0;
> -}
> -
> static int read_memory(const CPUState *cpu, uint64_t initial_gva,
> uint64_t initial_gpa, uint64_t gva, uint8_t *data,
> size_t len)
> @@ -1429,7 +1410,7 @@ static int handle_pio_str(CPUState *cpu, hv_x64_io_port_intercept_message *info)
> X86CPU *x86_cpu = X86_CPU(cpu);
> CPUX86State *env = &x86_cpu->env;
>
> - ret = fetch_guest_state(cpu);
> + ret = mshv_load_regs(cpu);
> if (ret < 0) {
> error_report("Failed to fetch guest state");
> return -1;
> --
> 2.53.0
Reviewed-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 3/7] include/hw/hyperv: add hv_vp_register_page struct definition
2026-05-05 18:50 ` [PATCH v2 3/7] include/hw/hyperv: add hv_vp_register_page struct definition Doru Blânzeanu
@ 2026-05-06 10:38 ` Magnus Kulke
2026-05-07 13:15 ` Anirudh Rayabharam
1 sibling, 0 replies; 20+ messages in thread
From: Magnus Kulke @ 2026-05-06 10:38 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:24PM +0300, Doru Blânzeanu wrote:
> Define the `hv_vp_register_page` structure that the linux kernel uses
> to allow access to vcpu registers.
>
> This structure is going to be used in later patches to access vcpu
> registers.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> include/hw/hyperv/hvgdk.h | 2 +
> include/hw/hyperv/hvhdk.h | 105 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 107 insertions(+)
>
> diff --git a/include/hw/hyperv/hvgdk.h b/include/hw/hyperv/hvgdk.h
> index 71161f477c..e4be861716 100644
> --- a/include/hw/hyperv/hvgdk.h
> +++ b/include/hw/hyperv/hvgdk.h
> @@ -9,6 +9,8 @@
> #ifndef HW_HYPERV_HVGDK_H
> #define HW_HYPERV_HVGDK_H
>
> +#include "hvgdk_mini.h"
> +
> #define HVGDK_H_VERSION (25125)
>
> enum hv_unimplemented_msr_action {
> diff --git a/include/hw/hyperv/hvhdk.h b/include/hw/hyperv/hvhdk.h
> index 41af743847..4a3b543893 100644
> --- a/include/hw/hyperv/hvhdk.h
> +++ b/include/hw/hyperv/hvhdk.h
> @@ -9,7 +9,11 @@
> #ifndef HW_HYPERV_HVHDK_H
> #define HW_HYPERV_HVHDK_H
>
> +#include "hvgdk.h"
> +#include "hvhdk_mini.h"
> +
> #define HV_PARTITION_SYNTHETIC_PROCESSOR_FEATURES_BANKS 1
> +#define HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT 7
>
> struct hv_input_set_partition_property {
> uint64_t partition_id;
> @@ -246,4 +250,105 @@ typedef struct hv_input_register_intercept_result {
> union hv_register_intercept_result_parameters parameters;
> } QEMU_PACKED hv_input_register_intercept_result;
>
> +/* Flags for dirty mask of hv_vp_register_page */
> +enum hv_x64_register_class_type {
> + HV_X64_REGISTER_CLASS_GENERAL = 0,
> + HV_X64_REGISTER_CLASS_IP = 1,
> + HV_X64_REGISTER_CLASS_XMM = 2,
> + HV_X64_REGISTER_CLASS_SEGMENT = 3,
> + HV_X64_REGISTER_CLASS_FLAGS = 4,
> +};
> +
> +union hv_vp_register_page_interrupt_vectors {
> + uint64_t as_uint64;
> + struct {
> + uint8_t vector_count;
> + uint8_t vector[HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT];
> + };
> +};
> +
> +struct hv_vp_register_page {
> + uint16_t version;
> + uint8_t isvalid;
> + uint8_t rsvdz;
> + uint32_t dirty;
> +
> + union {
> + struct {
> + /* General purpose registers (HV_X64_REGISTER_CLASS_GENERAL) */
> + union {
> + struct {
> + uint64_t rax;
> + uint64_t rcx;
> + uint64_t rdx;
> + uint64_t rbx;
> + uint64_t rsp;
> + uint64_t rbp;
> + uint64_t rsi;
> + uint64_t rdi;
> + uint64_t r8;
> + uint64_t r9;
> + uint64_t r10;
> + uint64_t r11;
> + uint64_t r12;
> + uint64_t r13;
> + uint64_t r14;
> + uint64_t r15;
> + } QEMU_PACKED;
> +
> + uint64_t gp_registers[16];
> + };
> + /* Instruction pointer (HV_X64_REGISTER_CLASS_IP) */
> + uint64_t rip;
> + /* Flags (HV_X64_REGISTER_CLASS_FLAGS) */
> + uint64_t rflags;
> + } QEMU_PACKED;
> +
> + uint64_t registers[18];
> + };
> + uint8_t reserved[8];
> + /* Volatile XMM registers (HV_X64_REGISTER_CLASS_XMM) */
> + union {
> + struct {
> + struct hv_u128 xmm0;
> + struct hv_u128 xmm1;
> + struct hv_u128 xmm2;
> + struct hv_u128 xmm3;
> + struct hv_u128 xmm4;
> + struct hv_u128 xmm5;
> + } QEMU_PACKED;
> +
> + struct hv_u128 xmm_registers[6];
> + };
> + /* Segment registers (HV_X64_REGISTER_CLASS_SEGMENT) */
> + union {
> + struct {
> + struct hv_x64_segment_register es;
> + struct hv_x64_segment_register cs;
> + struct hv_x64_segment_register ss;
> + struct hv_x64_segment_register ds;
> + struct hv_x64_segment_register fs;
> + struct hv_x64_segment_register gs;
> + } QEMU_PACKED;
> +
> + struct hv_x64_segment_register segment_registers[6];
> + };
> + /* Misc. control registers (cannot be set via this interface) */
> + uint64_t cr0;
> + uint64_t cr3;
> + uint64_t cr4;
> + uint64_t cr8;
> + uint64_t efer;
> + uint64_t dr7;
> + union hv_x64_pending_interruption_register pending_interruption;
> + union hv_x64_interrupt_state_register interrupt_state;
> + uint64_t instruction_emulation_hints;
> + uint64_t xfem;
> +
> + uint8_t reserved1[0x100];
> +
> + /* Interrupts injected as part of HvCallDispatchVp. */
> + union hv_vp_register_page_interrupt_vectors interrupt_vectors;
> +} QEMU_PACKED;
> +
> #endif /* HW_HYPERV_HVHDK_H */
> --
> 2.53.0
Reviewed-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 2/7] accel/mshv: move vcpu arch specific initialization after vcpu creation
2026-05-05 18:50 ` [PATCH v2 2/7] accel/mshv: move vcpu arch specific initialization after vcpu creation Doru Blânzeanu
@ 2026-05-06 14:31 ` Magnus Kulke
2026-05-07 13:12 ` Anirudh Rayabharam
1 sibling, 0 replies; 20+ messages in thread
From: Magnus Kulke @ 2026-05-06 14:31 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:23PM +0300, Doru Blânzeanu wrote:
> Call mshv_arch_init_vcpu after the vcpu is created to ensure a valid
> vcpu fd.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> accel/mshv/mshv-all.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c
> index 58af674bd9..e3da583f21 100644
> --- a/accel/mshv/mshv-all.c
> +++ b/accel/mshv/mshv-all.c
> @@ -415,13 +415,14 @@ static int mshv_init_vcpu(CPUState *cpu)
> int ret;
>
> cpu->accel = g_new0(AccelCPUState, 1);
> - mshv_arch_init_vcpu(cpu);
>
> ret = mshv_create_vcpu(vm_fd, vp_index, &cpu->accel->cpufd);
> if (ret < 0) {
> return -1;
> }
>
> + mshv_arch_init_vcpu(cpu);
> +
> cpu->accel->dirty = true;
>
> return 0;
> --
> 2.53.0
Reviewed-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 4/7] target/i386/mshv: hv_vp_register_page setup for the vcpu
2026-05-05 18:50 ` [PATCH v2 4/7] target/i386/mshv: hv_vp_register_page setup for the vcpu Doru Blânzeanu
@ 2026-05-06 14:36 ` Magnus Kulke
0 siblings, 0 replies; 20+ messages in thread
From: Magnus Kulke @ 2026-05-06 14:36 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:25PM +0300, Doru Blânzeanu wrote:
> When the vcpu is created, call mmap to configure access to the register page.
> In case the call to mmap fails, we log an error and continue with the
> previous logic (using hypercalls).
>
> Update CPUArchState to store a pointer to the mmapped hv_vp_register_page.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> target/i386/cpu.h | 5 +++++
> target/i386/mshv/mshv-cpu.c | 22 ++++++++++++++++++++++
> 2 files changed, 27 insertions(+)
>
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 16de67e546..fd4c3712b1 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -2019,6 +2019,11 @@ typedef struct CPUArchState {
> uint64_t msr_bndcfgs;
> uint64_t efer;
>
> +#ifdef CONFIG_MSHV
> + /* Shared register page */
> + struct hv_vp_register_page *regs_page;
> +#endif
since this is declared before this marker
/* Fields up to this point are cleared by a CPU reset */
struct {} end_reset_fields;
the pointer will be zeroed out on init, best move it after the
emu_mmio_buf field.
> +
> /* Beginning of state preserved by INIT (dummy marker). */
> struct {} start_init_save;
>
> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
> index 9defd05db6..3a3c269c33 100644
> --- a/target/i386/mshv/mshv-cpu.c
> +++ b/target/i386/mshv/mshv-cpu.c
> @@ -1587,6 +1587,7 @@ void mshv_arch_init_vcpu(CPUState *cpu)
> CPUX86State *env = &x86_cpu->env;
> AccelCPUState *state = cpu->accel;
> size_t page = HV_HYP_PAGE_SIZE;
> + void *regs_page;
> void *mem = qemu_memalign(page, 2 * page);
>
> /* sanity check, to make sure we don't overflow the page */
> @@ -1595,6 +1596,22 @@ void mshv_arch_init_vcpu(CPUState *cpu)
> + sizeof(hv_input_get_vp_registers)
> > HV_HYP_PAGE_SIZE));
>
> +
> + /* mmap the registers page */
> + regs_page = mmap(NULL, page, PROT_READ | PROT_WRITE,
> + MAP_SHARED, mshv_vcpufd(cpu),
> + MSHV_VP_MMAP_OFFSET_REGISTERS * page);
> + if (regs_page == MAP_FAILED) {
> + /*
> + * Error is not fatal, but we won't be able to use the
> + * fast path for register access
> + */
> + error_report("register page mmap failed: %s", strerror(errno));
> + env->regs_page = NULL;
> + } else {
> + env->regs_page = (struct hv_vp_register_page *) regs_page;
> + }
> +
> state->hvcall_args.base = mem;
> state->hvcall_args.input_page = mem;
> state->hvcall_args.output_page = (uint8_t *)mem + page;
> @@ -1608,6 +1625,11 @@ void mshv_arch_destroy_vcpu(CPUState *cpu)
> CPUX86State *env = &x86_cpu->env;
> AccelCPUState *state = cpu->accel;
>
> + /* Unmap the register page */
> + if (env->regs_page) {
> + munmap(env->regs_page, HV_HYP_PAGE_SIZE);
> + env->regs_page = NULL;
> + }
> g_free(state->hvcall_args.base);
> state->hvcall_args = (MshvHvCallArgs){0};
> g_clear_pointer(&env->emu_mmio_buf, g_free);
> --
> 2.53.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 7/7] target/i386/mshv: fix pio handlers clobbering device-modified registers
2026-05-05 18:50 ` [PATCH v2 7/7] target/i386/mshv: fix pio handlers clobbering device-modified registers Doru Blânzeanu
@ 2026-05-06 14:38 ` Magnus Kulke
0 siblings, 0 replies; 20+ messages in thread
From: Magnus Kulke @ 2026-05-06 14:38 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:28PM +0300, Doru Blânzeanu wrote:
> When a device handler (e.g. vmport) calls cpu_synchronize_state() during
> I/O port dispatch, it sets cpu->accel->dirty = true and may modify
> registers directly in env. The old PIO code ignored this: it
> unconditionally wrote the stale info->rax from the VM-exit intercept
> message back to the hypervisor and then cleared dirty, discarding any
> register changes made by the device.
>
> Bifurcate both handlers on cpu->accel->dirty:
>
> handle_pio_non_str:
> - dirty path: update env->eip directly. For reads (IN), merge the I/O
> result into env->regs[R_EAX] (which may have been modified by the
> device) rather than info->rax. For writes (OUT), leave RAX untouched.
> Flush all registers via mshv_store_regs() and clear dirty.
> - non-dirty path: write RIP and RAX via set_x64_registers hypercall as
> before.
>
> handle_pio_str:
> - dirty path: update env->eip and the appropriate index register
> (RSI for OUTS, RDI for INS) directly. Flush via mshv_store_regs()
> and clear dirty.
> - non-dirty path: write the index register and RIP via
> set_x64_registers. Drop the RAX assignment that was here before;
> string I/O does not modify RAX, and set_x64_registers is hardcoded
> to write only 2 registers so the third slot was silently ignored
> anyway.
>
> Remove the unconditional "cpu->accel->dirty = false" at the end of both
> handlers. In the non-dirty fast path it was redundant (already false).
> In the dirty path it was actively harmful: it told the vcpu run loop
> that env was clean when it was not, losing the device's modifications.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> target/i386/mshv/mshv-cpu.c | 82 ++++++++++++++++++++++++++-----------
> 1 file changed, 59 insertions(+), 23 deletions(-)
>
> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
> index 0cfac26a5c..7be3fdcc45 100644
> --- a/target/i386/mshv/mshv-cpu.c
> +++ b/target/i386/mshv/mshv-cpu.c
> @@ -1348,7 +1348,7 @@ static int pio_write(uint64_t port, const uint8_t *data, uintptr_t size,
> return ret;
> }
>
> -static int handle_pio_non_str(const CPUState *cpu,
> +static int handle_pio_non_str(CPUState *cpu,
> hv_x64_io_port_intercept_message *info)
> {
> size_t len = info->access_info.access_size;
> @@ -1357,10 +1357,12 @@ static int handle_pio_non_str(const CPUState *cpu,
> uint32_t val, eax;
> const uint32_t eax_mask = 0xffffffffu >> (32 - len * 8);
> size_t insn_len;
> - uint64_t rip, rax;
> + uint64_t rip;
> uint32_t reg_names[2];
> uint64_t reg_values[2];
> uint16_t port = info->port_number;
> + X86CPU *x86_cpu = X86_CPU(cpu);
> + CPUX86State *env = &x86_cpu->env;
>
> if (access_type == HV_X64_INTERCEPT_ACCESS_TYPE_WRITE) {
> union {
> @@ -1391,21 +1393,40 @@ static int handle_pio_non_str(const CPUState *cpu,
>
> /* Advance RIP and update RAX */
> rip = info->header.rip + insn_len;
> - rax = info->rax;
>
> - reg_names[0] = HV_X64_REGISTER_RIP;
> - reg_values[0] = rip;
> - reg_names[1] = HV_X64_REGISTER_RAX;
> - reg_values[1] = rax;
> + if (cpu->accel->dirty) {
> + env->eip = rip;
> + if (access_type != HV_X64_INTERCEPT_ACCESS_TYPE_WRITE) {
> + /*
> + * For reads, merge the I/O result into the current RAX.
> + * Use env->regs[R_EAX] as the base since a device handler
> + * (e.g. vmport) may have called cpu_synchronize_state()
> + * and modified registers.
> + */
> + eax = (((uint32_t)env->regs[R_EAX]) & ~eax_mask)
> + | (val & eax_mask);
> + env->regs[R_EAX] = (uint64_t)eax;
> + }
> + /* Sync modified standard registers back and clear dirty. */
> + ret = mshv_store_regs(cpu);
> + if (ret < 0) {
> + error_report("Failed to store registers after PIO");
> + return -1;
> + }
> + cpu->accel->dirty = false;
> + } else {
> + reg_names[0] = HV_X64_REGISTER_RIP;
> + reg_values[0] = rip;
> + reg_names[1] = HV_X64_REGISTER_RAX;
> + reg_values[1] = info->rax;
>
> - ret = set_x64_registers(cpu, reg_names, reg_values);
> - if (ret < 0) {
> - error_report("Failed to set x64 registers");
> - return -1;
> + ret = set_x64_registers(cpu, reg_names, reg_values);
> + if (ret < 0) {
> + error_report("Failed to set x64 registers");
> + return -1;
> + }
> }
>
> - cpu->accel->dirty = false;
> -
> return 0;
> }
>
> @@ -1521,6 +1542,7 @@ static int handle_pio_str(CPUState *cpu, hv_x64_io_port_intercept_message *info)
> bool repop = info->access_info.rep_prefix == 1;
> size_t repeat = repop ? info->rcx : 1;
> size_t insn_len = info->header.instruction_length;
> + uint64_t rip;
> bool direction_flag;
> uint32_t reg_names[3];
> uint64_t reg_values[3];
> @@ -1554,18 +1576,32 @@ static int handle_pio_str(CPUState *cpu, hv_x64_io_port_intercept_message *info)
> reg_values[0] = info->rdi;
> }
>
> - reg_names[1] = HV_X64_REGISTER_RIP;
> - reg_values[1] = info->header.rip + insn_len;
> - reg_names[2] = HV_X64_REGISTER_RAX;
> - reg_values[2] = info->rax;
> + rip = info->header.rip + insn_len;
>
> - ret = set_x64_registers(cpu, reg_names, reg_values);
> - if (ret < 0) {
> - error_report("Failed to set x64 registers");
> - return -1;
> - }
> + if (cpu->accel->dirty) {
> + env->eip = rip;
> + if (access_type == HV_X64_INTERCEPT_ACCESS_TYPE_WRITE) {
> + env->regs[R_ESI] = info->rsi;
> + } else {
> + env->regs[R_EDI] = info->rdi;
> + }
> + /* Sync modified standard registers back and clear dirty. */
> + ret = mshv_store_regs(cpu);
> + if (ret < 0) {
> + error_report("Failed to store registers after string PIO");
> + return -1;
> + }
> + cpu->accel->dirty = false;
> + } else {
> + reg_names[1] = HV_X64_REGISTER_RIP;
> + reg_values[1] = rip;
>
> - cpu->accel->dirty = false;
> + ret = set_x64_registers(cpu, reg_names, reg_values);
> + if (ret < 0) {
> + error_report("Failed to set x64 registers");
> + return -1;
> + }
> + }
>
> return 0;
> }
> --
> 2.53.0
Reviewed-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access
2026-05-05 18:50 [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
` (6 preceding siblings ...)
2026-05-05 18:50 ` [PATCH v2 7/7] target/i386/mshv: fix pio handlers clobbering device-modified registers Doru Blânzeanu
@ 2026-05-06 14:43 ` Magnus Kulke
7 siblings, 0 replies; 20+ messages in thread
From: Magnus Kulke @ 2026-05-06 14:43 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:21PM +0300, Doru Blânzeanu wrote:
> This series adds support for using the hypervisor's vp register page
> in the mshv accelerator to optimize vcpu register access on mmio and pio
> exits.
>
> Currently, all register reads and write go through hypercalls (ioctls),
> which adds overhead on every VM exit. The VP register page is a shared
> memory page that the hypervisor populates with vcpu register state,
> allowing Qemu to read and write registers directly without hypercalls.
>
> The series is structured as follows:
> 1. Remove the duplicate `fetch_guest_state` function, consolidating
> register loading into `mshv_load_regs`.
> 2. Move `mshv_arch_init_vcpu` after vcpu creation so the vcpu fd is
> valid when we need it for mmap.
> 3. Define the `hv_vp_register_page` structure in `hvgdk_mini.h`, matching
> the layout used by the Linux kernel's mshv driver.
> 4. Set up the register page by mmapping the vcpu fd at init time. If the
> mmap fails, we fall back gracefully to the existing hypercall path.
I think we don't have to fallback gracefully here. If the hypervisor
doesn't support the register page, it's likely that other assumption
don't hold either. I would suggest to abort here and relax that
constraint later, if we encounter a legit scenario where mmaping the
register page would fail.
> 5. Use the register page to read registers on VM exit. General purpose
> registers, RIP, RFLAGS, segment registers, and control registers
> (CR0, CR4, CR4, CR8, EFER) are read directly from the page. Registers
> not present on the page (TR, LDTR, GDTR, IDTR, CR2, APIC_BASE) are still
> fetched via hypercall.
> 6. Use register page to write registers on vmentry. GP registers,
> RIP, and RFLAGS are written to the page with the appropriate dirty
> bits set, avoiding the hypercall for the standard register store.
>
> The register page is only used when it has been successfully mmapped and
> the hypervisor has marked it as valid (`isvalid != 0`). Otherwise, the
> existing hypercall-based path is used as a fallback.
>
> Changes since v1:
> - move hv_register_page struct definition to hvhdk.h
> - add a compile time guard around regs_page in CPUArchState
> - modify mshv_get_special_regs_vp_page to only retrieve the special
> registers present in the register page (removed TR, LDTR, GDTR, IDTR,
> CR2, APIC_BASE)
> In local testing this hasn't created any regressions, and it is unlikely
> that the mmio operations need this registers.
> We'll want to keep an eye on this in case there are decoded operations
> that rely on fetching these registers on every VM exit.
> - add commit to fix handle_pio_non_str and handle_pio_str to correctly
> store modified registers back to the register page after the pio
> operation, and clear the cpu->accel->dirty flag to avoid the
> mshv_arch_put_registers from resetting some registers state (fpu).
> - modified register page setup to signal an error instead of a warning
> in case mmap fails.
> I am not sure aborting here is fine because it would make some of the
> fallback logic redundant, and I think that's a bigger refactoring.
>
> Doru Blânzeanu (7):
> target/i386/mshv: remove duplicate function for reading vcpu registers
> accel/mshv: move vcpu arch specific initialization after vcpu creation
> include/hw/hyperv: add hv_vp_register_page struct definition
> target/i386/mshv: hv_vp_register_page setup for the vcpu
> target/i386/mshv: use the register page to get registers
> target/i386/mshv: use the register page to set registers
> target/i386/mshv: fix pio handlers clobbering device-modified
> registers
>
> accel/mshv/mshv-all.c | 3 +-
> include/hw/hyperv/hvgdk.h | 2 +
> include/hw/hyperv/hvhdk.h | 105 ++++++++++++++
> target/i386/cpu.h | 5 +
> target/i386/mshv/mshv-cpu.c | 269 ++++++++++++++++++++++++++++--------
> 5 files changed, 327 insertions(+), 57 deletions(-)
>
> --
> 2.53.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers
2026-05-05 18:50 ` [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers Doru Blânzeanu
2026-05-06 10:34 ` Magnus Kulke
2026-05-06 10:35 ` Magnus Kulke
@ 2026-05-07 13:12 ` Anirudh Rayabharam
2 siblings, 0 replies; 20+ messages in thread
From: Anirudh Rayabharam @ 2026-05-07 13:12 UTC (permalink / raw)
To: Doru Blânzeanu
Cc: qemu-devel, Magnus Kulke, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:22PM +0300, Doru Blânzeanu wrote:
> Remove function `fetch_guest_state` because it is a duplicate function
> of `mshv_load_regs` function.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> target/i386/mshv/mshv-cpu.c | 21 +--------------------
> 1 file changed, 1 insertion(+), 20 deletions(-)
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 2/7] accel/mshv: move vcpu arch specific initialization after vcpu creation
2026-05-05 18:50 ` [PATCH v2 2/7] accel/mshv: move vcpu arch specific initialization after vcpu creation Doru Blânzeanu
2026-05-06 14:31 ` Magnus Kulke
@ 2026-05-07 13:12 ` Anirudh Rayabharam
1 sibling, 0 replies; 20+ messages in thread
From: Anirudh Rayabharam @ 2026-05-07 13:12 UTC (permalink / raw)
To: Doru Blânzeanu
Cc: qemu-devel, Magnus Kulke, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:23PM +0300, Doru Blânzeanu wrote:
> Call mshv_arch_init_vcpu after the vcpu is created to ensure a valid
> vcpu fd.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> accel/mshv/mshv-all.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c
> index 58af674bd9..e3da583f21 100644
> --- a/accel/mshv/mshv-all.c
> +++ b/accel/mshv/mshv-all.c
> @@ -415,13 +415,14 @@ static int mshv_init_vcpu(CPUState *cpu)
> int ret;
>
> cpu->accel = g_new0(AccelCPUState, 1);
> - mshv_arch_init_vcpu(cpu);
>
> ret = mshv_create_vcpu(vm_fd, vp_index, &cpu->accel->cpufd);
> if (ret < 0) {
> return -1;
> }
>
> + mshv_arch_init_vcpu(cpu);
> +
> cpu->accel->dirty = true;
>
> return 0;
> --
> 2.53.0
>
>
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 3/7] include/hw/hyperv: add hv_vp_register_page struct definition
2026-05-05 18:50 ` [PATCH v2 3/7] include/hw/hyperv: add hv_vp_register_page struct definition Doru Blânzeanu
2026-05-06 10:38 ` Magnus Kulke
@ 2026-05-07 13:15 ` Anirudh Rayabharam
1 sibling, 0 replies; 20+ messages in thread
From: Anirudh Rayabharam @ 2026-05-07 13:15 UTC (permalink / raw)
To: Doru Blânzeanu
Cc: qemu-devel, Magnus Kulke, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:24PM +0300, Doru Blânzeanu wrote:
> Define the `hv_vp_register_page` structure that the linux kernel uses
> to allow access to vcpu registers.
>
> This structure is going to be used in later patches to access vcpu
> registers.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> include/hw/hyperv/hvgdk.h | 2 +
> include/hw/hyperv/hvhdk.h | 105 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 107 insertions(+)
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 5/7] target/i386/mshv: use the register page to get registers
2026-05-05 18:50 ` [PATCH v2 5/7] target/i386/mshv: use the register page to get registers Doru Blânzeanu
@ 2026-05-07 13:23 ` Anirudh Rayabharam
0 siblings, 0 replies; 20+ messages in thread
From: Anirudh Rayabharam @ 2026-05-07 13:23 UTC (permalink / raw)
To: Doru Blânzeanu
Cc: qemu-devel, Magnus Kulke, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:26PM +0300, Doru Blânzeanu wrote:
> Change the mshv_load_regs to use the register page when it is mmapped
> and is valid.
> Otherwise use the existing logic that uses ioctls to fetch registers.
>
> When retrieving the special registers, there are some registers that are
> not present in the register page: TR, LDTR, GDTR, IDTR, CR2, APIC_BASE.
> As this registers are not likely to be used in an MMIO/PIO operation,
> and to avoid a hypercall overhead we do not retrieve them.
>
> Local testing showed no regression when using this logic. To properly
> retrieve all the necessary registers for each decoded operation implies
> having a mechanism that tracks the state of each register, which is
> beyond the scope of this patch series.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> target/i386/mshv/mshv-cpu.c | 99 +++++++++++++++++++++++++++++++++----
> 1 file changed, 90 insertions(+), 9 deletions(-)
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 6/7] target/i386/mshv: use the register page to set registers
2026-05-05 18:50 ` [PATCH v2 6/7] target/i386/mshv: use the register page to set registers Doru Blânzeanu
@ 2026-05-07 13:29 ` Anirudh Rayabharam
0 siblings, 0 replies; 20+ messages in thread
From: Anirudh Rayabharam @ 2026-05-07 13:29 UTC (permalink / raw)
To: Doru Blânzeanu
Cc: qemu-devel, Magnus Kulke, Zhao Liu, Wei Liu, Paolo Bonzini
On Tue, May 05, 2026 at 09:50:27PM +0300, Doru Blânzeanu wrote:
> Update mshv_store_regs to use the register page when it is mmapped and
> valid to set registers.
> Otherwise use the ioctls to set the registers.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> target/i386/mshv/mshv-cpu.c | 45 +++++++++++++++++++++++++++++++++----
> 1 file changed, 41 insertions(+), 4 deletions(-)
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2026-05-07 13:29 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-05 18:50 [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
2026-05-05 18:50 ` [PATCH v2 1/7] target/i386/mshv: remove duplicate function for reading vcpu registers Doru Blânzeanu
2026-05-06 10:34 ` Magnus Kulke
2026-05-06 10:35 ` Magnus Kulke
2026-05-07 13:12 ` Anirudh Rayabharam
2026-05-05 18:50 ` [PATCH v2 2/7] accel/mshv: move vcpu arch specific initialization after vcpu creation Doru Blânzeanu
2026-05-06 14:31 ` Magnus Kulke
2026-05-07 13:12 ` Anirudh Rayabharam
2026-05-05 18:50 ` [PATCH v2 3/7] include/hw/hyperv: add hv_vp_register_page struct definition Doru Blânzeanu
2026-05-06 10:38 ` Magnus Kulke
2026-05-07 13:15 ` Anirudh Rayabharam
2026-05-05 18:50 ` [PATCH v2 4/7] target/i386/mshv: hv_vp_register_page setup for the vcpu Doru Blânzeanu
2026-05-06 14:36 ` Magnus Kulke
2026-05-05 18:50 ` [PATCH v2 5/7] target/i386/mshv: use the register page to get registers Doru Blânzeanu
2026-05-07 13:23 ` Anirudh Rayabharam
2026-05-05 18:50 ` [PATCH v2 6/7] target/i386/mshv: use the register page to set registers Doru Blânzeanu
2026-05-07 13:29 ` Anirudh Rayabharam
2026-05-05 18:50 ` [PATCH v2 7/7] target/i386/mshv: fix pio handlers clobbering device-modified registers Doru Blânzeanu
2026-05-06 14:38 ` Magnus Kulke
2026-05-06 14:43 ` [PATCH v2 0/7] target/i386/mshv: use hv_vp_register_page for fast register access Magnus Kulke
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.