{"id":2229595,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2229595/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260428135053.251200-6-dblanzeanu@linux.microsoft.com/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/1.1/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260428135053.251200-6-dblanzeanu@linux.microsoft.com>","date":"2026-04-28T13:50:52","name":"[5/6] target/i386/mshv: use the register page to get registers","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"218e51dbba5daf24a804ad7a0132adf4573dbf29","submitter":{"id":93106,"url":"http://patchwork.ozlabs.org/api/1.1/people/93106/?format=json","name":"Doru Blânzeanu","email":"dblanzeanu@linux.microsoft.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260428135053.251200-6-dblanzeanu@linux.microsoft.com/mbox/","series":[{"id":501862,"url":"http://patchwork.ozlabs.org/api/1.1/series/501862/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=501862","date":"2026-04-28T13:50:49","name":"target/i386/mshv: use hv_vp_register_page for fast register access","version":1,"mbox":"http://patchwork.ozlabs.org/series/501862/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2229595/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2229595/checks/","tags":{},"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=EK9CYF0E;\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 4g4htn2FK8z1yJs\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 00:01:35 +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 1wHizx-00042O-Tc; Tue, 28 Apr 2026 10:01:13 -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 <dblanzeanu@linux.microsoft.com>)\n id 1wHiqH-0002U3-97\n for qemu-devel@nongnu.org; Tue, 28 Apr 2026 09:51:13 -0400","from linux.microsoft.com ([13.77.154.182])\n by eggs.gnu.org with esmtp (Exim 4.90_1)\n (envelope-from <dblanzeanu@linux.microsoft.com>) id 1wHiqF-0005kw-Fc\n for qemu-devel@nongnu.org; Tue, 28 Apr 2026 09:51:13 -0400","from laptop.localdomain (unknown [86.121.140.248])\n by linux.microsoft.com (Postfix) with ESMTPSA id B989A20B716E;\n Tue, 28 Apr 2026 06:51:09 -0700 (PDT)"],"DKIM-Filter":"OpenDKIM Filter v2.11.0 linux.microsoft.com B989A20B716E","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com;\n s=default; t=1777384271;\n bh=zW0yVN2CFXrXlGkrEKmvsT7yWR8YAOcUe2edHP9ocQs=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n b=EK9CYF0Egtw1iy6Y5h5Q0h8Ux7m7Ci7wecL3GkWgJT9iN/QFKOU32Xs/i+JBzDXjA\n o4c23ENwHsPdv8T5k/R4tvQwcuk6RHj0QiJ2qL5QMjvgNwyLVCjSvx2LaP7PI36zSQ\n Ub/3XEdYQOQikrT878hF8OwEfnpKRWNnaRkEcNes=","From":"=?utf-8?q?Doru_Bl=C3=A2nzeanu?= <dblanzeanu@linux.microsoft.com>","To":"qemu-devel@nongnu.org","Cc":"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>","Subject":"[PATCH 5/6] target/i386/mshv: use the register page to get registers","Date":"Tue, 28 Apr 2026 16:50:52 +0300","Message-ID":"<20260428135053.251200-6-dblanzeanu@linux.microsoft.com>","X-Mailer":"git-send-email 2.53.0","In-Reply-To":"<20260428135053.251200-1-dblanzeanu@linux.microsoft.com>","References":"<20260428135053.251200-1-dblanzeanu@linux.microsoft.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Received-SPF":"pass client-ip=13.77.154.182;\n envelope-from=dblanzeanu@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-Mailman-Approved-At":"Tue, 28 Apr 2026 10:00:26 -0400","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"},"content":"Change the mshv_load_regs to use the register page when it is mmapped\nand is valid.\nOtherwise use the existing logic that uses ioctls to fetch registers.\n\nWhen retrieving the special registers, there are some registers that are\nnot present in the register page: TR, LDTR, GDTR, IDTR, CR2, APIC_BASE.\nFor this ones we still need to use ioctls to correctly fetch.\n\nSigned-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(-)","diff":"diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c\nindex 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+\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","prefixes":["5/6"]}