From: "Doru Blânzeanu" <dblanzeanu@linux.microsoft.com>
To: qemu-devel@nongnu.org
Cc: "Doru Blânzeanu" <dblanzeanu@linux.microsoft.com>,
"Magnus Kulke" <magnuskulke@linux.microsoft.com>,
"Zhao Liu" <zhao1.liu@intel.com>, "Wei Liu" <wei.liu@kernel.org>,
"Paolo Bonzini" <pbonzini@redhat.com>
Subject: [PATCH v2 5/7] target/i386/mshv: use the register page to get registers
Date: Tue, 5 May 2026 21:50:26 +0300 [thread overview]
Message-ID: <20260505185028.237207-6-dblanzeanu@linux.microsoft.com> (raw)
In-Reply-To: <20260505185028.237207-1-dblanzeanu@linux.microsoft.com>
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
next prev parent reply other threads:[~2026-05-05 18:51 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Doru Blânzeanu [this message]
2026-05-07 13:23 ` [PATCH v2 5/7] target/i386/mshv: use the register page to get registers 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260505185028.237207-6-dblanzeanu@linux.microsoft.com \
--to=dblanzeanu@linux.microsoft.com \
--cc=magnuskulke@linux.microsoft.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=wei.liu@kernel.org \
--cc=zhao1.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.