All of lore.kernel.org
 help / color / mirror / Atom feed
From: Magnus Kulke <magnuskulke@linux.microsoft.com>
To: "Doru Blânzeanu" <dblanzeanu@linux.microsoft.com>
Cc: qemu-devel@nongnu.org, Wei Liu <wei.liu@kernel.org>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Zhao Liu <zhao1.liu@intel.com>
Subject: Re: [PATCH 5/6] target/i386/mshv: use the register page to get registers
Date: Wed, 29 Apr 2026 13:31:45 +0200	[thread overview]
Message-ID: <afHsIXVVG1vFsVK0@example.com> (raw)
In-Reply-To: <20260428135053.251200-6-dblanzeanu@linux.microsoft.com>

On Tue, Apr 28, 2026 at 04:50:52PM +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.
> For this ones we still need to use ioctls to correctly fetch.
> 
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
>  target/i386/mshv/mshv-cpu.c | 137 +++++++++++++++++++++++++++++++++---
>  1 file changed, 128 insertions(+), 9 deletions(-)
> 
> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
> index 42b6fb1912..7949493e97 100644
> --- a/target/i386/mshv/mshv-cpu.c
> +++ b/target/i386/mshv/mshv-cpu.c
> @@ -107,6 +107,15 @@ static enum hv_register_name FPU_REGISTER_NAMES[26] = {
>      HV_X64_REGISTER_XMM_CONTROL_STATUS,
>  };
>  
> +static enum hv_register_name NON_VP_PAGE_REGISTER_NAMES[6] = {
> +    HV_X64_REGISTER_TR,
> +    HV_X64_REGISTER_LDTR,
> +    HV_X64_REGISTER_GDTR,
> +    HV_X64_REGISTER_IDTR,
> +    HV_X64_REGISTER_CR2,
> +    HV_X64_REGISTER_APIC_BASE,
> +};
> +
>  static int translate_gva(const CPUState *cpu, uint64_t gva, uint64_t *gpa,
>                           uint64_t flags)
>  {
> @@ -401,6 +410,105 @@ 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);
> +}
> +
> +static int mshv_get_special_regs_vp_page(CPUState *cpu)
> +{
> +    X86CPU *x86cpu = X86_CPU(cpu);
> +    CPUX86State *env = &x86cpu->env;
> +    struct hv_register_assoc assocs[ARRAY_SIZE(NON_VP_PAGE_REGISTER_NAMES)];
> +    int ret;
> +    size_t n_regs = ARRAY_SIZE(NON_VP_PAGE_REGISTER_NAMES);
> +    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]);
> +
> +    /* The rest of the special registers that are not in the VP register page */
> +    for (size_t i = 0; i < n_regs; i++) {
> +        assocs[i].name = NON_VP_PAGE_REGISTER_NAMES[i];
> +    }
> +
> +    ret = get_generic_regs(cpu, assocs, n_regs);
> +    if (ret < 0) {
> +        error_report("failed to get non-vp-page special registers");
> +        return -1;
> +    }
> +
> +    /* Non-VP page registers - TR, LDTR, GDTR, IDTR, CR2, APIC_BASE */
> +    populate_segment_reg(&assocs[0].value.segment, &env->tr);
> +    populate_segment_reg(&assocs[1].value.segment, &env->ldt);
> +
> +    populate_table_reg(&assocs[2].value.table, &env->gdt);
> +    populate_table_reg(&assocs[3].value.table, &env->idt);
> +    env->cr[2] = assocs[4].value.reg64;
> +
> +    cpu_set_apic_base(x86cpu->apic_state, assocs[5].value.reg64);

Do we know whether MMIO emulation requires the
NON_VP_PAGE_REGISTER_NAMES to be roundtripped? I understand this is how
it is done in the mshv-ioctls crate, but I understand this was motivated
mostly by maitaining parity for sregs between KVM and MSHV
implementations.

Did you test what happens if we don't perform an ioctl and just ignore
those registers?

> +
> +    return ret;
> +}
> +
> +static int mshv_get_registers_vp_page(CPUState *cpu)
> +{
> +    int ret;
> +
> +    /* General Purpose Registers  */
> +    mshv_get_standard_regs_vp_page(cpu);
> +
> +    /* Special Registers - makes a hypercall */
> +    ret = mshv_get_special_regs_vp_page(cpu);
> +    if (ret < 0) {
> +        error_report("failed to get special registers for vp page");
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
>  
>  int mshv_get_special_regs(CPUState *cpu)
>  {
> @@ -424,18 +532,29 @@ 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) {
> +        ret = mshv_get_registers_vp_page(cpu);
> +        if (ret < 0) {
> +            error_report("Failed to load registers from vp page");

nit: slightly inaccurate, since loading registers is infallible. it's
the ioctl op that fails, no?

> +            return -1;
> +        }
> +    } 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


  parent reply	other threads:[~2026-04-29 11:31 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-28 13:50 [PATCH 0/6] target/i386/mshv: use hv_vp_register_page for fast register access Doru Blânzeanu
2026-04-28 13:50 ` [PATCH 1/6] target/i386/mshv: remove duplicate function for reading vcpu registers Doru Blânzeanu
2026-04-29 10:19   ` Magnus Kulke
2026-04-28 13:50 ` [PATCH 2/6] accel/mshv: move vcpu arch specific initialization after vcpu creation Doru Blânzeanu
2026-04-29 10:21   ` Magnus Kulke
2026-04-28 13:50 ` [PATCH 3/6] include/hw/hyperv: add hv_vp_register_page struct definition Doru Blânzeanu
2026-04-28 17:44   ` Mohamed Mediouni
2026-04-29 10:28   ` Magnus Kulke
2026-04-28 13:50 ` [PATCH 4/6] target/i386/mshv: hv_vp_register_page setup for the vcpu Doru Blânzeanu
2026-04-28 17:49   ` Mohamed Mediouni
2026-04-29 11:21   ` Magnus Kulke
2026-04-28 13:50 ` [PATCH 5/6] target/i386/mshv: use the register page to get registers Doru Blânzeanu
2026-04-28 18:04   ` Mohamed Mediouni
2026-04-29 11:31   ` Magnus Kulke [this message]
2026-04-28 13:50 ` [PATCH 6/6] target/i386/mshv: use the register page to set registers Doru Blânzeanu
2026-04-28 18:05   ` Mohamed Mediouni
2026-04-29 11:38   ` Magnus Kulke
2026-04-28 18:36 ` [PATCH 0/6] target/i386/mshv: use hv_vp_register_page for fast register access Mohamed Mediouni

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=afHsIXVVG1vFsVK0@example.com \
    --to=magnuskulke@linux.microsoft.com \
    --cc=dblanzeanu@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.