[PATCH v5 01/13] accel/mshv: extract common CPU register helpers

Aastha Rawat <[email protected]>
Newsgroups org.nongnu.qemu-arm,org.nongnu.qemu-devel
Message-ID <20260717-mshv_accel_arm64_supp-v5-1-ef07d4c6b337@linux.microsoft.com>
Move arch-independent MSHV CPU register handling functions into
accel/mshv/mshv-cpu-common.c. Update x86 MSHV backends to use these
shared helpers.

Prefix get_generic_regs() with mshv_ for proper namespacing since it
is now public.

Signed-off-by: Aastha Rawat <[email protected]>
---
 accel/mshv/meson.build       |   3 +-
 accel/mshv/mshv-cpu-common.c | 151 +++++++++++++++++++++++++++++++++++++++++++
 include/system/mshv_int.h    |   1 +
 target/i386/mshv/mshv-cpu.c  | 125 +----------------------------------
 4 files changed, 155 insertions(+), 125 deletions(-)

diff --git a/accel/mshv/meson.build b/accel/mshv/meson.build
index e433187cde..ebe32921b3 100644
--- a/accel/mshv/meson.build
+++ b/accel/mshv/meson.build
@@ -1,5 +1,6 @@
 system_ss.add(when: 'CONFIG_MSHV', if_true: files(
   'irq.c',
   'mem.c',
-  'mshv-all.c'
+  'mshv-all.c',
+  'mshv-cpu-common.c'
 ))
diff --git a/accel/mshv/mshv-cpu-common.c b/accel/mshv/mshv-cpu-common.c
new file mode 100644
index 0000000000..b104720161
--- /dev/null
+++ b/accel/mshv/mshv-cpu-common.c
@@ -0,0 +1,151 @@
+/*
+ * QEMU MSHV common CPU register helpers
+ *
+ * Copyright Microsoft, Corp. 2026
+ *
+ * Authors: Ziqiao Zhou   <[email protected]>
+ *          Magnus Kulke  <[email protected]>
+ *          Jinank Jain   <[email protected]>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/memalign.h"
+
+#include "system/mshv.h"
+#include "system/mshv_int.h"
+
+#include "hw/core/cpu.h"
+#include "linux/mshv.h"
+
+#include <sys/ioctl.h>
+
+int mshv_set_generic_regs(const CPUState *cpu, const hv_register_assoc *assocs,
+                          size_t n_regs)
+{
+    int cpu_fd = mshv_vcpufd(cpu);
+    int vp_index = cpu->cpu_index;
+    size_t in_sz, assocs_sz;
+    hv_input_set_vp_registers *in = cpu->accel->hvcall_args.input_page;
+    struct mshv_root_hvcall args = {0};
+    int ret;
+
+    /* find out the size of the struct w/ a flexible array at the tail */
+    assocs_sz = n_regs * sizeof(hv_register_assoc);
+    in_sz = sizeof(hv_input_set_vp_registers) + assocs_sz;
+
+    /* fill the input struct */
+    memset(in, 0, sizeof(hv_input_set_vp_registers));
+    in->vp_index = vp_index;
+    memcpy(in->elements, assocs, assocs_sz);
+
+    /* create the hvcall envelope */
+    args.code = HVCALL_SET_VP_REGISTERS;
+    args.in_sz = in_sz;
+    args.in_ptr = (uint64_t) in;
+    args.reps = (uint16_t) n_regs;
+
+    /* perform the call */
+    ret = mshv_hvcall(cpu_fd, &args);
+    if (ret < 0) {
+        error_report("Failed to set registers");
+        return -1;
+    }
+
+    /* assert we set all registers */
+    if (args.reps != n_regs) {
+        error_report("Failed to set registers: expected %zu elements"
+                     ", got %u", n_regs, args.reps);
+        return -1;
+    }
+
+    return 0;
+}
+
+int mshv_get_generic_regs(CPUState *cpu, hv_register_assoc *assocs,
+                            size_t n_regs)
+{
+    int cpu_fd = mshv_vcpufd(cpu);
+    int vp_index = cpu->cpu_index;
+    hv_input_get_vp_registers *in = cpu->accel->hvcall_args.input_page;
+    hv_register_value *values = cpu->accel->hvcall_args.output_page;
+    size_t in_sz, names_sz, values_sz;
+    int i, ret;
+    struct mshv_root_hvcall args = {0};
+
+    /* find out the size of the struct w/ a flexible array at the tail */
+    names_sz = n_regs * sizeof(hv_register_name);
+    in_sz = sizeof(hv_input_get_vp_registers) + names_sz;
+
+    /* fill the input struct */
+    memset(in, 0, sizeof(hv_input_get_vp_registers));
+    in->vp_index = vp_index;
+    for (i = 0; i < n_regs; i++) {
+        in->names[i] = assocs[i].name;
+    }
+
+    /* determine size of value output buffer */
+    values_sz = n_regs * sizeof(union hv_register_value);
+
+    /* create the hvcall envelope */
+    args.code = HVCALL_GET_VP_REGISTERS;
+    args.in_sz = in_sz;
+    args.in_ptr = (uint64_t) in;
+    args.out_sz = values_sz;
+    args.out_ptr = (uint64_t) values;
+    args.reps = (uint16_t) n_regs;
+
+    /* perform the call */
+    ret = mshv_hvcall(cpu_fd, &args);
+    if (ret < 0) {
+        error_report("Failed to retrieve registers");
+        return -1;
+    }
+
+    /* assert we got all registers */
+    if (args.reps != n_regs) {
+        error_report("Failed to retrieve registers: expected %zu elements"
+                     ", got %u", n_regs, args.reps);
+        return -1;
+    }
+
+    /* copy values into assoc */
+    for (i = 0; i < n_regs; i++) {
+        assocs[i].value = values[i];
+    }
+
+    return 0;
+}
+
+int mshv_create_vcpu(int vm_fd, uint8_t vp_index, int *cpu_fd)
+{
+    int ret;
+    struct mshv_create_vp vp_arg = {
+        .vp_index = vp_index,
+    };
+
+    ret = ioctl(vm_fd, MSHV_CREATE_VP, &vp_arg);
+    if (ret < 0) {
+        error_report("failed to create mshv vcpu: %s", strerror(errno));
+        return -1;
+    }
+
+    *cpu_fd = ret;
+
+    return 0;
+}
+
+void mshv_remove_vcpu(int vm_fd, int cpu_fd)
+{
+    close(cpu_fd);
+}
+
+void mshv_setup_hvcall_args(AccelCPUState *state)
+{
+    void *mem = qemu_memalign(HV_HYP_PAGE_SIZE, 2 * HV_HYP_PAGE_SIZE);
+
+    state->hvcall_args.base = mem;
+    state->hvcall_args.input_page = mem;
+    state->hvcall_args.output_page = (uint8_t *)mem + HV_HYP_PAGE_SIZE;
+}
diff --git a/include/system/mshv_int.h b/include/system/mshv_int.h
index b91c4d661a..e9f4a2f9b9 100644
--- a/include/system/mshv_int.h
+++ b/include/system/mshv_int.h
@@ -105,6 +105,7 @@ void mshv_arch_amend_proc_features(
 void mshv_arch_disable_partition_proc_features(
      union hv_partition_processor_features *disabled_features);
 int mshv_arch_post_init_vm(int vm_fd);
+void mshv_setup_hvcall_args(AccelCPUState *state);
 
 typedef struct mshv_root_hvcall mshv_root_hvcall;
 int mshv_hvcall(int fd, const mshv_root_hvcall *args);
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 1c433c408c..a142f79801 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -320,103 +320,6 @@ static int translate_gva(const CPUState *cpu, uint64_t gva, uint64_t *gpa,
     return 0;
 }
 
-int mshv_set_generic_regs(const CPUState *cpu, const hv_register_assoc *assocs,
-                          size_t n_regs)
-{
-    int cpu_fd = mshv_vcpufd(cpu);
-    int vp_index = cpu->cpu_index;
-    size_t in_sz, assocs_sz;
-    hv_input_set_vp_registers *in = cpu->accel->hvcall_args.input_page;
-    struct mshv_root_hvcall args = {0};
-    int ret;
-
-    /* find out the size of the struct w/ a flexible array at the tail */
-    assocs_sz = n_regs * sizeof(hv_register_assoc);
-    in_sz = sizeof(hv_input_set_vp_registers) + assocs_sz;
-
-    /* fill the input struct */
-    memset(in, 0, sizeof(hv_input_set_vp_registers));
-    in->vp_index = vp_index;
-    memcpy(in->elements, assocs, assocs_sz);
-
-    /* create the hvcall envelope */
-    args.code = HVCALL_SET_VP_REGISTERS;
-    args.in_sz = in_sz;
-    args.in_ptr = (uint64_t) in;
-    args.reps = (uint16_t) n_regs;
-
-    /* perform the call */
-    ret = mshv_hvcall(cpu_fd, &args);
-    if (ret < 0) {
-        error_report("Failed to set registers");
-        return -1;
-    }
-
-    /* assert we set all registers */
-    if (args.reps != n_regs) {
-        error_report("Failed to set registers: expected %zu elements"
-                     ", got %u", n_regs, args.reps);
-        return -1;
-    }
-
-    return 0;
-}
-
-int mshv_get_generic_regs(CPUState *cpu, hv_register_assoc *assocs,
-                          size_t n_regs)
-{
-    int cpu_fd = mshv_vcpufd(cpu);
-    int vp_index = cpu->cpu_index;
-    hv_input_get_vp_registers *in = cpu->accel->hvcall_args.input_page;
-    hv_register_value *values = cpu->accel->hvcall_args.output_page;
-    size_t in_sz, names_sz, values_sz;
-    int i, ret;
-    struct mshv_root_hvcall args = {0};
-
-    /* find out the size of the struct w/ a flexible array at the tail */
-    names_sz = n_regs * sizeof(hv_register_name);
-    in_sz = sizeof(hv_input_get_vp_registers) + names_sz;
-
-    /* fill the input struct */
-    memset(in, 0, sizeof(hv_input_get_vp_registers));
-    in->vp_index = vp_index;
-    for (i = 0; i < n_regs; i++) {
-        in->names[i] = assocs[i].name;
-    }
-
-    /* determine size of value output buffer */
-    values_sz = n_regs * sizeof(union hv_register_value);
-
-    /* create the hvcall envelope */
-    args.code = HVCALL_GET_VP_REGISTERS;
-    args.in_sz = in_sz;
-    args.in_ptr = (uint64_t) in;
-    args.out_sz = values_sz;
-    args.out_ptr = (uint64_t) values;
-    args.reps = (uint16_t) n_regs;
-
-    /* perform the call */
-    ret = mshv_hvcall(cpu_fd, &args);
-    if (ret < 0) {
-        error_report("Failed to retrieve registers");
-        return -1;
-    }
-
-    /* assert we got all registers */
-    if (args.reps != n_regs) {
-        error_report("Failed to retrieve registers: expected %zu elements"
-                     ", got %u", n_regs, args.reps);
-        return -1;
-    }
-
-    /* copy values into assoc */
-    for (i = 0; i < n_regs; i++) {
-        assocs[i].value = values[i];
-    }
-
-    return 0;
-}
-
 static int set_standard_regs(const CPUState *cpu)
 {
     X86CPU *x86cpu = X86_CPU(cpu);
@@ -1968,29 +1871,6 @@ int mshv_run_vcpu(int vm_fd, CPUState *cpu, hv_message *msg, MshvVmExit *exit)
     return 0;
 }
 
-void mshv_remove_vcpu(int vm_fd, int cpu_fd)
-{
-    close(cpu_fd);
-}
-
-
-int mshv_create_vcpu(int vm_fd, uint8_t vp_index, int *cpu_fd)
-{
-    int ret;
-    struct mshv_create_vp vp_arg = {
-        .vp_index = vp_index,
-    };
-    ret = ioctl(vm_fd, MSHV_CREATE_VP, &vp_arg);
-    if (ret < 0) {
-        error_report("failed to create mshv vcpu: %s", strerror(errno));
-        return -1;
-    }
-
-    *cpu_fd = ret;
-
-    return 0;
-}
-
 static void read_segment_descriptor(CPUState *cpu,
                                     struct x86_segment_descriptor *desc,
                                     enum X86Seg seg_idx)
@@ -2049,7 +1929,6 @@ void mshv_arch_init_vcpu(CPUState *cpu)
     CPUX86State *env = &x86_cpu->env;
     AccelCPUState *state = cpu->accel;
     size_t page = HV_HYP_PAGE_SIZE, xsave_len;
-    void *mem = qemu_memalign(page, 2 * page);
     int ret;
     X86XSaveHeader *header;
 
@@ -2071,9 +1950,7 @@ void mshv_arch_init_vcpu(CPUState *cpu)
         env->regs_page = (struct hv_vp_register_page *) rp;
     }
 
-    state->hvcall_args.base = mem;
-    state->hvcall_args.input_page = mem;
-    state->hvcall_args.output_page = (uint8_t *)mem + page;
+    mshv_setup_hvcall_args(state);
 
     env->emu_mmio_buf = g_new(char, 4096);
 

-- 
2.45.4
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.