[{"id":3683622,"web_url":"http://patchwork.ozlabs.org/comment/3683622/","msgid":"<080FDF70-96CA-4F1E-95F7-BBC70A14BE91@unpredictable.fr>","list_archive_url":null,"date":"2026-04-28T18:04:13","subject":"Re: [PATCH 5/6] target/i386/mshv: use the register page to get\n registers","submitter":{"id":91318,"url":"http://patchwork.ozlabs.org/api/people/91318/","name":"Mohamed Mediouni","email":"mohamed@unpredictable.fr"},"content":"> On 28. Apr 2026, at 15:50, Doru Blânzeanu <dblanzeanu@linux.microsoft.com> wrote:\n> \n> Change the mshv_load_regs to use the register page when it is mmapped\n> and is valid.\n> Otherwise use the existing logic that uses ioctls to fetch registers.\n> \n> When retrieving the special registers, there are some registers that are\n> not present in the register page: TR, LDTR, GDTR, IDTR, CR2, APIC_BASE.\n> For this ones we still need to use ioctls to correctly fetch.\n> \n> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>\n\nReviewed-by: Mohamed Mediouni <mohamed@unpredictable.fr>\n\nBut with comments below...\n\n> ---\n> target/i386/mshv/mshv-cpu.c | 137 +++++++++++++++++++++++++++++++++---\n> 1 file changed, 128 insertions(+), 9 deletions(-)\n> \n> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c\n> index 42b6fb1912..7949493e97 100644\n> --- a/target/i386/mshv/mshv-cpu.c\n> +++ b/target/i386/mshv/mshv-cpu.c\n> @@ -107,6 +107,15 @@ static enum hv_register_name FPU_REGISTER_NAMES[26] = {\n>     HV_X64_REGISTER_XMM_CONTROL_STATUS,\n> };\n> \n> +static enum hv_register_name NON_VP_PAGE_REGISTER_NAMES[6] = {\n> +    HV_X64_REGISTER_TR,\n> +    HV_X64_REGISTER_LDTR,\n> +    HV_X64_REGISTER_GDTR,\n\nThose two _not_ being in a shared register page does cause quite a bit of\npain for perf if not dealt with carefully which leads to…\n\n> +    HV_X64_REGISTER_IDTR,\n> +    HV_X64_REGISTER_CR2,\n> +    HV_X64_REGISTER_APIC_BASE,\n> +};\n> +\n> static int translate_gva(const CPUState *cpu, uint64_t gva, uint64_t *gpa,\n>                          uint64_t flags)\n> {\n> @@ -401,6 +410,105 @@ static void populate_special_regs(const hv_register_assoc *assocs,\n>     cpu_set_apic_base(x86cpu->apic_state, assocs[16].value.reg64);\n> }\n> \n> +static void mshv_get_standard_regs_vp_page(CPUState *cpu)\n> +{\n> +    X86CPU *x86cpu = X86_CPU(cpu);\n> +    CPUX86State *env = &x86cpu->env;\n> +\n> +    /* General Purpose Registers  */\n> +    env->regs[R_EAX] = env->regs_page->rax;\n> +    env->regs[R_EBX] = env->regs_page->rbx;\n> +    env->regs[R_ECX] = env->regs_page->rcx;\n> +    env->regs[R_EDX] = env->regs_page->rdx;\n> +    env->regs[R_ESI] = env->regs_page->rsi;\n> +    env->regs[R_EDI] = env->regs_page->rdi;\n> +    env->regs[R_ESP] = env->regs_page->rsp;\n> +    env->regs[R_EBP] = env->regs_page->rbp;\n> +    env->regs[R_R8]  = env->regs_page->r8;\n> +    env->regs[R_R9]  = env->regs_page->r9;\n> +    env->regs[R_R10] = env->regs_page->r10;\n> +    env->regs[R_R11] = env->regs_page->r11;\n> +    env->regs[R_R12] = env->regs_page->r12;\n> +    env->regs[R_R13] = env->regs_page->r13;\n> +    env->regs[R_R14] = env->regs_page->r14;\n> +    env->regs[R_R15] = env->regs_page->r15;\n> +\n> +    env->eip = env->regs_page->rip;\n> +    env->eflags = env->regs_page->rflags;\n> +    rflags_to_lflags(env);\n> +}\n> +\n> +static int mshv_get_special_regs_vp_page(CPUState *cpu)\n> +{\n> +    X86CPU *x86cpu = X86_CPU(cpu);\n> +    CPUX86State *env = &x86cpu->env;\n> +    struct hv_register_assoc assocs[ARRAY_SIZE(NON_VP_PAGE_REGISTER_NAMES)];\n> +    int ret;\n> +    size_t n_regs = ARRAY_SIZE(NON_VP_PAGE_REGISTER_NAMES);\n> +    hv_x64_segment_register seg;\n> +\n> +    /* Populate special registers that are in the VP register page */\n> +    env->cr[0] = env->regs_page->cr0;\n> +    env->cr[3] = env->regs_page->cr3;\n> +    env->cr[4] = env->regs_page->cr4;\n> +    env->efer = env->regs_page->efer;\n> +    cpu_set_apic_tpr(x86cpu->apic_state, env->regs_page->cr8);\n> +\n> +    /* Segment Registers - copy from packed struct to avoid unaligned access */\n> +    memcpy(&seg, &env->regs_page->es, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_ES]);\n> +    memcpy(&seg, &env->regs_page->cs, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_CS]);\n> +    memcpy(&seg, &env->regs_page->ss, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_SS]);\n> +    memcpy(&seg, &env->regs_page->ds, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_DS]);\n> +    memcpy(&seg, &env->regs_page->fs, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_FS]);\n> +    memcpy(&seg, &env->regs_page->gs, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_GS]);\n\nIt’s probably best to split this function.\n\nA “regular” MMIO access is going to need segment info, but not GDTR/LDTR.\n\nOtherwise you’d effectively defeat the point of the shared register page. Ideally\n0 register fetch/writes outside of the shared register page would happen on an MMIO\naccess.\n\n> +\n> +    /* The rest of the special registers that are not in the VP register page */\n> +    for (size_t i = 0; i < n_regs; i++) {\n> +        assocs[i].name = NON_VP_PAGE_REGISTER_NAMES[i];\n> +    }\n> +\n> +    ret = get_generic_regs(cpu, assocs, n_regs);\n> +    if (ret < 0) {\n> +        error_report(\"failed to get non-vp-page special registers\");\n> +        return -1;\n> +    }\n> +\n> +    /* Non-VP page registers - TR, LDTR, GDTR, IDTR, CR2, APIC_BASE */\n> +    populate_segment_reg(&assocs[0].value.segment, &env->tr);\n> +    populate_segment_reg(&assocs[1].value.segment, &env->ldt);\n> +\n> +    populate_table_reg(&assocs[2].value.table, &env->gdt);\n> +    populate_table_reg(&assocs[3].value.table, &env->idt);\n> +    env->cr[2] = assocs[4].value.reg64;\n\nFor CRs, there’s a read_cr x86 emulation callback now, although it never\nneeds to read CR2.\n\n> +\n> +    cpu_set_apic_base(x86cpu->apic_state, assocs[5].value.reg64);\n\nFor APIC base, what I ended up doing on WHPX (upcoming 11.1 series) is \nto just trap APIC base writes so that there’s never a need to read it.\n\n> +\n> +    return ret;\n> +}\n> +\n> +static int mshv_get_registers_vp_page(CPUState *cpu)\n> +{\n> +    int ret;\n> +\n> +    /* General Purpose Registers  */\n> +    mshv_get_standard_regs_vp_page(cpu);\n> +\n> +    /* Special Registers - makes a hypercall */\n> +    ret = mshv_get_special_regs_vp_page(cpu);\n> +    if (ret < 0) {\n> +        error_report(\"failed to get special registers for vp page\");\n> +        return -1;\n> +    }\n> +\n> +    return 0;\n> +}\n> +\n> \n> int mshv_get_special_regs(CPUState *cpu)\n> {\n> @@ -424,18 +532,29 @@ int mshv_get_special_regs(CPUState *cpu)\n> \n> int mshv_load_regs(CPUState *cpu)\n> {\n> +    X86CPU *x86_cpu = X86_CPU(cpu);\n> +    CPUX86State *env = &x86_cpu->env;\n>     int ret;\n> \n> -    ret = mshv_get_standard_regs(cpu);\n> -    if (ret < 0) {\n> -        error_report(\"Failed to load standard registers\");\n> -        return -1;\n> -    }\n> +    /* Use register vp page to optimize registers access */\n> +    if (env->regs_page && env->regs_page->isvalid != 0) {\n> +        ret = mshv_get_registers_vp_page(cpu);\n> +        if (ret < 0) {\n> +            error_report(\"Failed to load registers from vp page\");\n> +            return -1;\n> +        }\n> +    } else {\n> +        ret = mshv_get_standard_regs(cpu);\n> +        if (ret < 0) {\n> +            error_report(\"Failed to load standard registers\");\n> +            return -1;\n> +        }\n> \n> -    ret = mshv_get_special_regs(cpu);\n> -    if (ret < 0) {\n> -        error_report(\"Failed to load special registers\");\n> -        return -1;\n> +        ret = mshv_get_special_regs(cpu);\n> +        if (ret < 0) {\n> +            error_report(\"Failed to load special registers\");\n> +            return -1;\n> +        }\n>     }\n> \n>     return 0;\n> -- \n> 2.53.0\n> \n>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=unpredictable.fr header.i=@unpredictable.fr\n header.a=rsa-sha256 header.s=sig1 header.b=P+r9Wkce;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4pJB0g2Sz1xrS\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 04:05:28 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wHmnn-0003Nr-K5; Tue, 28 Apr 2026 14:04:55 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <mohamed@unpredictable.fr>)\n id 1wHmnU-0003Md-BI\n for qemu-devel@nongnu.org; Tue, 28 Apr 2026 14:04:38 -0400","from p-west3-cluster5-host11-snip4-10.eps.apple.com ([57.103.72.113]\n helo=outbound.ms.icloud.com)\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <mohamed@unpredictable.fr>)\n id 1wHmnQ-00077j-8k\n for qemu-devel@nongnu.org; Tue, 28 Apr 2026 14:04:35 -0400","from outbound.ms.icloud.com (unknown [127.0.0.2])\n by p00-icloudmta-asmtp-us-west-3a-60-percent-6 (Postfix) with ESMTPS id\n 3555118000E8; Tue, 28 Apr 2026 18:04:27 +0000 (UTC)","from smtpclient.apple (unknown [17.57.154.37])\n by p00-icloudmta-asmtp-us-west-3a-60-percent-6 (Postfix) with ESMTPSA id\n 12F3B1800C3F; Tue, 28 Apr 2026 18:04:25 +0000 (UTC)"],"X-ICL-Out-Info":"\n HUtFAUMHWwJACUgBTUQeDx5WFlZNRAJCTQFIHV8DWRxBAUkdXw9LVxQEFVwFVgZXFHkNXR1FDlYZWgxSD1sOHBZLWFUJCgZdGFgVVgl3HlwASx1XBFQfUxJVHR0LRUtAEwROEwVSB11NVg1HD1geXBQXFUBDXgheH0wcHQ5YBhIATQoONgZZBV4JVgNDBTYSFF1FRgNHGVcUUBtHDFUHV15fChMAXg8PTAlAAytzLQVAFEEFLnZGBjYIPR5UAi0FXXs6cFoHKgNEez0KXHceXABLHVcEVB9TElUdHQtFVRIEQAhWUFQeQQRWFWwJWAZTGVc=","Dkim-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=unpredictable.fr;\n s=sig1; t=1777399470; x=1779991470;\n bh=q+AkgagEpEvE6yK+m9+tMpe+n2FML2MuyQJLGwNRiS4=;\n h=Content-Type:Mime-Version:Subject:From:Date:Message-Id:To:x-icloud-hme;\n b=P+r9WkcevOvyim0VzUAmLN5JGeG3XiuPpY2Wo7vkmgpVr24oRl/1gRJ5ue/4qvfxtLqDstXyztoi/GvE4zM7lX78JchC1cmNVitZLj60XAnw/Vy556l53EPAowMel3m8YOQKcyWUvEZDQaDn5AiqmoiqC0/UtbmJbgHZbh86VXuipOffJLK6NpYxzCeyqogtFwceHrdslxQKdEyzH5T6idz6aEXS9M9skqGaSvflHuO5m1SQrtVkqvZIN5wHCDGOFCJRxIHuWdVDgu1MCr98TWC7xDWzyD1Gx7PWMYCxcjXfxMYm+ZbN4r3QUYEE4VR5XOvFf9NqQtix7nU2CVDxXA==","mail-alias-created-date":"1752046281608","Content-Type":"text/plain;\n\tcharset=utf-8","Mime-Version":"1.0 (Mac OS X Mail 16.0 \\(3864.500.181\\))","Subject":"Re: [PATCH 5/6] target/i386/mshv: use the register page to get\n registers","From":"Mohamed Mediouni <mohamed@unpredictable.fr>","In-Reply-To":"<20260428135053.251200-6-dblanzeanu@linux.microsoft.com>","Date":"Tue, 28 Apr 2026 20:04:13 +0200","Cc":"qemu-devel@nongnu.org, Magnus Kulke <magnuskulke@linux.microsoft.com>,\n Wei Liu <wei.liu@kernel.org>, Paolo Bonzini <pbonzini@redhat.com>,\n Zhao Liu <zhao1.liu@intel.com>","Content-Transfer-Encoding":"quoted-printable","Message-Id":"<080FDF70-96CA-4F1E-95F7-BBC70A14BE91@unpredictable.fr>","References":"<20260428135053.251200-1-dblanzeanu@linux.microsoft.com>\n <20260428135053.251200-6-dblanzeanu@linux.microsoft.com>","To":"=?utf-8?q?Doru_Bl=C3=A2nzeanu?= <dblanzeanu@linux.microsoft.com>","X-Mailer":"Apple Mail (2.3864.500.181)","X-Authority-Info-Out":"v=2.4 cv=LvifC3dc c=1 sm=1 tr=0 ts=69f0f6ad\n cx=c_apl:c_pps:t_out a=qkKslKyYc0ctBTeLUVfTFg==:117 a=IkcTkHD0fZMA:10\n a=A5OVakUREuEA:10 a=VkNPw1HP01LnGYTKEx00:22 a=yMhMjlubAAAA:8\n a=gy0if3euEij6_eOLcIMA:9 a=QEXdDO2ut3YA:10","X-Proofpoint-GUID":"FT3LtnMlotzliQ8v-aUmQWtV3VwHeTnH","X-Proofpoint-ORIG-GUID":"FT3LtnMlotzliQ8v-aUmQWtV3VwHeTnH","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwNDI4MDE3NSBTYWx0ZWRfX3+h4YchNlxsi\n VjMzd7RI6DOl8YAOJRwkZtm33y+nap5RozXgIMUvWnu7TpKdN8ceIAHdKI3jgXXlUkH9B8bzbd4\n 6QO9UXHWGfPJ3Q6Rzs1uJyvHpXF7qiEyvOCRt4lseC9zc4sqfHkFfA1bl/oYOX8UZqq01pYcMSz\n XIl83yz8juxHHvtGJtJOvVomDmcTf2eAd9OfeGDEyWlZiBpXIs9Jh4XUVATLY65SGWwxyE7xrA7\n ycRS/InQCdV20K3vBbX0yhToqMRDWj2cGbPHLKOFIZguuH6CADyWPx3a9cCf3Vcco8m3HuUGbwm\n 27+RNuwjohUN9JXTRcYUkBDRFLgTth+uGKX2P9Jwl2NwE+RBMpTupTowsTVWYk=","Received-SPF":"pass client-ip=57.103.72.113;\n envelope-from=mohamed@unpredictable.fr; helo=outbound.ms.icloud.com","X-Spam_score_int":"-27","X-Spam_score":"-2.8","X-Spam_bar":"--","X-Spam_report":"(-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=0.001, SPF_HELO_PASS=-0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}},{"id":3684008,"web_url":"http://patchwork.ozlabs.org/comment/3684008/","msgid":"<afHsIXVVG1vFsVK0@example.com>","list_archive_url":null,"date":"2026-04-29T11:31:45","subject":"Re: [PATCH 5/6] target/i386/mshv: use the register page to get\n registers","submitter":{"id":90753,"url":"http://patchwork.ozlabs.org/api/people/90753/","name":"Magnus Kulke","email":"magnuskulke@linux.microsoft.com"},"content":"On Tue, Apr 28, 2026 at 04:50:52PM +0300, Doru Blânzeanu wrote:\n> Change the mshv_load_regs to use the register page when it is mmapped\n> and is valid.\n> Otherwise use the existing logic that uses ioctls to fetch registers.\n> \n> When retrieving the special registers, there are some registers that are\n> not present in the register page: TR, LDTR, GDTR, IDTR, CR2, APIC_BASE.\n> For this ones we still need to use ioctls to correctly fetch.\n> \n> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>\n> ---\n>  target/i386/mshv/mshv-cpu.c | 137 +++++++++++++++++++++++++++++++++---\n>  1 file changed, 128 insertions(+), 9 deletions(-)\n> \n> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c\n> index 42b6fb1912..7949493e97 100644\n> --- a/target/i386/mshv/mshv-cpu.c\n> +++ b/target/i386/mshv/mshv-cpu.c\n> @@ -107,6 +107,15 @@ static enum hv_register_name FPU_REGISTER_NAMES[26] = {\n>      HV_X64_REGISTER_XMM_CONTROL_STATUS,\n>  };\n>  \n> +static enum hv_register_name NON_VP_PAGE_REGISTER_NAMES[6] = {\n> +    HV_X64_REGISTER_TR,\n> +    HV_X64_REGISTER_LDTR,\n> +    HV_X64_REGISTER_GDTR,\n> +    HV_X64_REGISTER_IDTR,\n> +    HV_X64_REGISTER_CR2,\n> +    HV_X64_REGISTER_APIC_BASE,\n> +};\n> +\n>  static int translate_gva(const CPUState *cpu, uint64_t gva, uint64_t *gpa,\n>                           uint64_t flags)\n>  {\n> @@ -401,6 +410,105 @@ static void populate_special_regs(const hv_register_assoc *assocs,\n>      cpu_set_apic_base(x86cpu->apic_state, assocs[16].value.reg64);\n>  }\n>  \n> +static void mshv_get_standard_regs_vp_page(CPUState *cpu)\n> +{\n> +    X86CPU *x86cpu = X86_CPU(cpu);\n> +    CPUX86State *env = &x86cpu->env;\n> +\n> +    /* General Purpose Registers  */\n> +    env->regs[R_EAX] = env->regs_page->rax;\n> +    env->regs[R_EBX] = env->regs_page->rbx;\n> +    env->regs[R_ECX] = env->regs_page->rcx;\n> +    env->regs[R_EDX] = env->regs_page->rdx;\n> +    env->regs[R_ESI] = env->regs_page->rsi;\n> +    env->regs[R_EDI] = env->regs_page->rdi;\n> +    env->regs[R_ESP] = env->regs_page->rsp;\n> +    env->regs[R_EBP] = env->regs_page->rbp;\n> +    env->regs[R_R8]  = env->regs_page->r8;\n> +    env->regs[R_R9]  = env->regs_page->r9;\n> +    env->regs[R_R10] = env->regs_page->r10;\n> +    env->regs[R_R11] = env->regs_page->r11;\n> +    env->regs[R_R12] = env->regs_page->r12;\n> +    env->regs[R_R13] = env->regs_page->r13;\n> +    env->regs[R_R14] = env->regs_page->r14;\n> +    env->regs[R_R15] = env->regs_page->r15;\n> +\n> +    env->eip = env->regs_page->rip;\n> +    env->eflags = env->regs_page->rflags;\n> +    rflags_to_lflags(env);\n> +}\n> +\n> +static int mshv_get_special_regs_vp_page(CPUState *cpu)\n> +{\n> +    X86CPU *x86cpu = X86_CPU(cpu);\n> +    CPUX86State *env = &x86cpu->env;\n> +    struct hv_register_assoc assocs[ARRAY_SIZE(NON_VP_PAGE_REGISTER_NAMES)];\n> +    int ret;\n> +    size_t n_regs = ARRAY_SIZE(NON_VP_PAGE_REGISTER_NAMES);\n> +    hv_x64_segment_register seg;\n> +\n> +    /* Populate special registers that are in the VP register page */\n> +    env->cr[0] = env->regs_page->cr0;\n> +    env->cr[3] = env->regs_page->cr3;\n> +    env->cr[4] = env->regs_page->cr4;\n> +    env->efer = env->regs_page->efer;\n> +    cpu_set_apic_tpr(x86cpu->apic_state, env->regs_page->cr8);\n> +\n> +    /* Segment Registers - copy from packed struct to avoid unaligned access */\n> +    memcpy(&seg, &env->regs_page->es, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_ES]);\n> +    memcpy(&seg, &env->regs_page->cs, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_CS]);\n> +    memcpy(&seg, &env->regs_page->ss, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_SS]);\n> +    memcpy(&seg, &env->regs_page->ds, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_DS]);\n> +    memcpy(&seg, &env->regs_page->fs, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_FS]);\n> +    memcpy(&seg, &env->regs_page->gs, sizeof(hv_x64_segment_register));\n> +    populate_segment_reg(&seg, &env->segs[R_GS]);\n> +\n> +    /* The rest of the special registers that are not in the VP register page */\n> +    for (size_t i = 0; i < n_regs; i++) {\n> +        assocs[i].name = NON_VP_PAGE_REGISTER_NAMES[i];\n> +    }\n> +\n> +    ret = get_generic_regs(cpu, assocs, n_regs);\n> +    if (ret < 0) {\n> +        error_report(\"failed to get non-vp-page special registers\");\n> +        return -1;\n> +    }\n> +\n> +    /* Non-VP page registers - TR, LDTR, GDTR, IDTR, CR2, APIC_BASE */\n> +    populate_segment_reg(&assocs[0].value.segment, &env->tr);\n> +    populate_segment_reg(&assocs[1].value.segment, &env->ldt);\n> +\n> +    populate_table_reg(&assocs[2].value.table, &env->gdt);\n> +    populate_table_reg(&assocs[3].value.table, &env->idt);\n> +    env->cr[2] = assocs[4].value.reg64;\n> +\n> +    cpu_set_apic_base(x86cpu->apic_state, assocs[5].value.reg64);\n\nDo we know whether MMIO emulation requires the\nNON_VP_PAGE_REGISTER_NAMES to be roundtripped? I understand this is how\nit is done in the mshv-ioctls crate, but I understand this was motivated\nmostly by maitaining parity for sregs between KVM and MSHV\nimplementations.\n\nDid you test what happens if we don't perform an ioctl and just ignore\nthose registers?\n\n> +\n> +    return ret;\n> +}\n> +\n> +static int mshv_get_registers_vp_page(CPUState *cpu)\n> +{\n> +    int ret;\n> +\n> +    /* General Purpose Registers  */\n> +    mshv_get_standard_regs_vp_page(cpu);\n> +\n> +    /* Special Registers - makes a hypercall */\n> +    ret = mshv_get_special_regs_vp_page(cpu);\n> +    if (ret < 0) {\n> +        error_report(\"failed to get special registers for vp page\");\n> +        return -1;\n> +    }\n> +\n> +    return 0;\n> +}\n> +\n>  \n>  int mshv_get_special_regs(CPUState *cpu)\n>  {\n> @@ -424,18 +532,29 @@ int mshv_get_special_regs(CPUState *cpu)\n>  \n>  int mshv_load_regs(CPUState *cpu)\n>  {\n> +    X86CPU *x86_cpu = X86_CPU(cpu);\n> +    CPUX86State *env = &x86_cpu->env;\n>      int ret;\n>  \n> -    ret = mshv_get_standard_regs(cpu);\n> -    if (ret < 0) {\n> -        error_report(\"Failed to load standard registers\");\n> -        return -1;\n> -    }\n> +    /* Use register vp page to optimize registers access */\n> +    if (env->regs_page && env->regs_page->isvalid != 0) {\n> +        ret = mshv_get_registers_vp_page(cpu);\n> +        if (ret < 0) {\n> +            error_report(\"Failed to load registers from vp page\");\n\nnit: slightly inaccurate, since loading registers is infallible. it's\nthe ioctl op that fails, no?\n\n> +            return -1;\n> +        }\n> +    } else {\n> +        ret = mshv_get_standard_regs(cpu);\n> +        if (ret < 0) {\n> +            error_report(\"Failed to load standard registers\");\n> +            return -1;\n> +        }\n>  \n> -    ret = mshv_get_special_regs(cpu);\n> -    if (ret < 0) {\n> -        error_report(\"Failed to load special registers\");\n> -        return -1;\n> +        ret = mshv_get_special_regs(cpu);\n> +        if (ret < 0) {\n> +            error_report(\"Failed to load special registers\");\n> +            return -1;\n> +        }\n>      }\n>  \n>      return 0;\n> -- \n> 2.53.0","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=linux.microsoft.com header.i=@linux.microsoft.com\n header.a=rsa-sha256 header.s=default header.b=iZUmPyRa;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g5FWf6mPrz1yHZ\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 21:31:58 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wI391-0004KE-Gk; Wed, 29 Apr 2026 07:31:55 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <magnuskulke@linux.microsoft.com>)\n id 1wI38z-0004Js-AI\n for qemu-devel@nongnu.org; Wed, 29 Apr 2026 07:31:53 -0400","from linux.microsoft.com ([13.77.154.182])\n by eggs.gnu.org with esmtp (Exim 4.90_1)\n (envelope-from <magnuskulke@linux.microsoft.com>) id 1wI38x-0000LT-FI\n for qemu-devel@nongnu.org; Wed, 29 Apr 2026 07:31:53 -0400","from example.com (unknown [167.220.208.81])\n by linux.microsoft.com (Postfix) with ESMTPSA id 0F27820B716C;\n Wed, 29 Apr 2026 04:31:48 -0700 (PDT)"],"DKIM-Filter":"OpenDKIM Filter v2.11.0 linux.microsoft.com 0F27820B716C","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com;\n s=default; t=1777462310;\n bh=VTeUmvrowZ5KEwQhdobWjOGoJJMLtnKmRIKWO/DyW/E=;\n h=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n b=iZUmPyRa/K6UY0uE58puRbcU92tq/0AkRrH7DeH+Fr7o0m6FE4ZCNcLdFvtB/3xpS\n Br+11UUC/7ugPFA7Luywny5TAXSywiToENXfOY4OKojXy17LhXbCpfK3U+qifP+a1J\n Q9ViEatvfn63RgGyZsuDjW2M5wTuZWwNd7uQ8/5k=","Date":"Wed, 29 Apr 2026 13:31:45 +0200","From":"Magnus Kulke <magnuskulke@linux.microsoft.com>","To":"Doru =?iso-8859-1?q?Bl=E2nzeanu?= <dblanzeanu@linux.microsoft.com>","Cc":"qemu-devel@nongnu.org, Wei Liu <wei.liu@kernel.org>,\n 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\n registers","Message-ID":"<afHsIXVVG1vFsVK0@example.com>","References":"<20260428135053.251200-1-dblanzeanu@linux.microsoft.com>\n <20260428135053.251200-6-dblanzeanu@linux.microsoft.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20260428135053.251200-6-dblanzeanu@linux.microsoft.com>","Received-SPF":"pass client-ip=13.77.154.182;\n envelope-from=magnuskulke@linux.microsoft.com; helo=linux.microsoft.com","X-Spam_score_int":"-26","X-Spam_score":"-2.7","X-Spam_bar":"--","X-Spam_report":"(-2.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, RCVD_IN_DNSWL_LOW=-0.7,\n SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}}]