* [PATCH v6 1/9] accel/mshv: use mshv_create_partition_v2 payload
2026-04-16 12:11 [PATCH v6 0/9] Support QEMU cpu models in MSHV accelerator Magnus Kulke
@ 2026-04-16 12:11 ` Magnus Kulke
2026-04-30 8:43 ` Doru Blânzeanu
2026-04-16 12:11 ` [PATCH v6 2/9] target/i386/mshv: fix cpuid propagation bug Magnus Kulke
` (7 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Magnus Kulke @ 2026-04-16 12:11 UTC (permalink / raw)
To: qemu-devel
Cc: Wei Liu, Magnus Kulke, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
When using the extended request format we can instruct the hypervisor to
provision enough space for requested XSAVE features. This is required
for supporting QEMU models provided via the -cpu flag properly.
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
Acked-by: Wei Liu <wei.liu@kernel.org>
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
---
accel/mshv/mshv-all.c | 71 ++++++++++--
include/hw/hyperv/hvgdk_mini.h | 2 +
include/hw/hyperv/hvhdk.h | 195 +++++++++++++++++++++++++++++++++
3 files changed, 261 insertions(+), 7 deletions(-)
diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c
index d4cc7f5371..c50641f174 100644
--- a/accel/mshv/mshv-all.c
+++ b/accel/mshv/mshv-all.c
@@ -110,21 +110,78 @@ static int resume_vm(int vm_fd)
return 0;
}
+static int get_host_partition_property(int mshv_fd, uint32_t property_code,
+ uint64_t *value)
+{
+ int ret;
+ struct hv_input_get_partition_property in = {0};
+ struct hv_output_get_partition_property out = {0};
+ struct mshv_root_hvcall args = {0};
+
+ in.property_code = property_code;
+
+ args.code = HVCALL_GET_PARTITION_PROPERTY;
+ args.in_sz = sizeof(in);
+ args.in_ptr = (uint64_t)∈
+ args.out_sz = sizeof(out);
+ args.out_ptr = (uint64_t)&out;
+
+ ret = ioctl(mshv_fd, MSHV_ROOT_HVCALL, &args);
+ if (ret < 0) {
+ error_report("Failed to get host partition property bank: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ *value = out.property_value;
+ return 0;
+}
+
static int create_partition(int mshv_fd, int *vm_fd)
{
int ret;
- struct mshv_create_partition args = {0};
+ uint64_t pt_flags, host_proc_features;
+ union hv_partition_processor_xsave_features disabled_xsave_features;
+ struct mshv_create_partition_v2 args = {0};
+
+ QEMU_BUILD_BUG_ON(MSHV_NUM_CPU_FEATURES_BANKS != 2);
/* Initialize pt_flags with the desired features */
- uint64_t pt_flags = (1ULL << MSHV_PT_BIT_LAPIC) |
- (1ULL << MSHV_PT_BIT_X2APIC) |
- (1ULL << MSHV_PT_BIT_GPA_SUPER_PAGES);
+ pt_flags = (1ULL << MSHV_PT_BIT_LAPIC) |
+ (1ULL << MSHV_PT_BIT_X2APIC) |
+ (1ULL << MSHV_PT_BIT_GPA_SUPER_PAGES) |
+ (1ULL << MSHV_PT_BIT_CPU_AND_XSAVE_FEATURES);
+
+ /* enable all */
+ disabled_xsave_features.as_uint64 = 0;
+
+ /*
+ * query host for supported processor features and disable unsupported
+ * features: (0 means supported, 1 means disabled, hence the negation)
+ */
+ ret = get_host_partition_property(mshv_fd,
+ HV_PARTITION_PROPERTY_PROCESSOR_FEATURES0,
+ &host_proc_features);
+ if (ret < 0) {
+ error_report("Failed to get host processor feature bank 0");
+ return -1;
+ }
+ args.pt_cpu_fbanks[0] = ~host_proc_features;
- /* Set default isolation type */
- uint64_t pt_isolation = MSHV_PT_ISOLATION_NONE;
+ ret = get_host_partition_property(mshv_fd,
+ HV_PARTITION_PROPERTY_PROCESSOR_FEATURES1,
+ &host_proc_features);
+ if (ret < 0) {
+ error_report("Failed to get host processor feature bank 1");
+ return -1;
+ }
+ args.pt_cpu_fbanks[1] = ~host_proc_features;
+ /* populate args structure */
args.pt_flags = pt_flags;
- args.pt_isolation = pt_isolation;
+ args.pt_isolation = MSHV_PT_ISOLATION_NONE;
+ args.pt_disabled_xsave = disabled_xsave_features.as_uint64;
+ args.pt_num_cpu_fbanks = MSHV_NUM_CPU_FEATURES_BANKS;
ret = ioctl(mshv_fd, MSHV_CREATE_PARTITION, &args);
if (ret < 0) {
diff --git a/include/hw/hyperv/hvgdk_mini.h b/include/hw/hyperv/hvgdk_mini.h
index c3a8f33280..367519143e 100644
--- a/include/hw/hyperv/hvgdk_mini.h
+++ b/include/hw/hyperv/hvgdk_mini.h
@@ -454,6 +454,8 @@ typedef struct hv_input_set_vp_registers {
struct hv_register_assoc elements[];
} QEMU_PACKED hv_input_set_vp_registers;
+#define MSHV_VP_MAX_REGISTERS 128
+
union hv_interrupt_control {
uint64_t as_uint64;
struct {
diff --git a/include/hw/hyperv/hvhdk.h b/include/hw/hyperv/hvhdk.h
index 41af743847..9ad16c47da 100644
--- a/include/hw/hyperv/hvhdk.h
+++ b/include/hw/hyperv/hvhdk.h
@@ -11,6 +11,16 @@
#define HV_PARTITION_SYNTHETIC_PROCESSOR_FEATURES_BANKS 1
+struct hv_input_get_partition_property {
+ uint64_t partition_id;
+ uint32_t property_code; /* enum hv_partition_property_code */
+ uint32_t padding;
+} QEMU_PACKED;
+
+struct hv_output_get_partition_property {
+ uint64_t property_value;
+} QEMU_PACKED;
+
struct hv_input_set_partition_property {
uint64_t partition_id;
uint32_t property_code; /* enum hv_partition_property_code */
@@ -161,6 +171,191 @@ union hv_partition_synthetic_processor_features {
};
};
+union hv_partition_processor_xsave_features {
+ struct {
+ uint64_t xsave_support:1;
+ uint64_t xsaveopt_support:1;
+ uint64_t avx_support:1;
+ uint64_t avx2_support:1;
+ uint64_t fma_support:1;
+ uint64_t mpx_support:1;
+ uint64_t avx512_support:1;
+ uint64_t avx512_dq_support:1;
+ uint64_t avx512_cd_support:1;
+ uint64_t avx512_bw_support:1;
+ uint64_t avx512_vl_support:1;
+ uint64_t xsave_comp_support:1;
+ uint64_t xsave_supervisor_support:1;
+ uint64_t xcr1_support:1;
+ uint64_t avx512_bitalg_support:1;
+ uint64_t avx512_i_fma_support:1;
+ uint64_t avx512_v_bmi_support:1;
+ uint64_t avx512_v_bmi2_support:1;
+ uint64_t avx512_vnni_support:1;
+ uint64_t gfni_support:1;
+ uint64_t vaes_support:1;
+ uint64_t avx512_v_popcntdq_support:1;
+ uint64_t vpclmulqdq_support:1;
+ uint64_t avx512_bf16_support:1;
+ uint64_t avx512_vp2_intersect_support:1;
+ uint64_t avx512_fp16_support:1;
+ uint64_t xfd_support:1;
+ uint64_t amx_tile_support:1;
+ uint64_t amx_bf16_support:1;
+ uint64_t amx_int8_support:1;
+ uint64_t avx_vnni_support:1;
+ uint64_t avx_ifma_support:1;
+ uint64_t avx_ne_convert_support:1;
+ uint64_t avx_vnni_int8_support:1;
+ uint64_t avx_vnni_int16_support:1;
+ uint64_t avx10_1_256_support:1;
+ uint64_t avx10_1_512_support:1;
+ uint64_t amx_fp16_support:1;
+ uint64_t reserved1:26;
+ };
+ uint64_t as_uint64;
+};
+
+#define HV_PARTITION_PROCESSOR_FEATURES_BANKS 2
+#define HV_PARTITION_PROCESSOR_FEATURES_RESERVEDBANK1_BITFIELD_COUNT 4
+
+
+union hv_partition_processor_features {
+ uint64_t as_uint64[HV_PARTITION_PROCESSOR_FEATURES_BANKS];
+ struct {
+ uint64_t sse3_support:1;
+ uint64_t lahf_sahf_support:1;
+ uint64_t ssse3_support:1;
+ uint64_t sse4_1_support:1;
+ uint64_t sse4_2_support:1;
+ uint64_t sse4a_support:1;
+ uint64_t xop_support:1;
+ uint64_t pop_cnt_support:1;
+ uint64_t cmpxchg16b_support:1;
+ uint64_t altmovcr8_support:1;
+ uint64_t lzcnt_support:1;
+ uint64_t mis_align_sse_support:1;
+ uint64_t mmx_ext_support:1;
+ uint64_t amd3dnow_support:1;
+ uint64_t extended_amd3dnow_support:1;
+ uint64_t page_1gb_support:1;
+ uint64_t aes_support:1;
+ uint64_t pclmulqdq_support:1;
+ uint64_t pcid_support:1;
+ uint64_t fma4_support:1;
+ uint64_t f16c_support:1;
+ uint64_t rd_rand_support:1;
+ uint64_t rd_wr_fs_gs_support:1;
+ uint64_t smep_support:1;
+ uint64_t enhanced_fast_string_support:1;
+ uint64_t bmi1_support:1;
+ uint64_t bmi2_support:1;
+ uint64_t hle_support_deprecated:1;
+ uint64_t rtm_support_deprecated:1;
+ uint64_t movbe_support:1;
+ uint64_t npiep1_support:1;
+ uint64_t dep_x87_fpu_save_support:1;
+ uint64_t rd_seed_support:1;
+ uint64_t adx_support:1;
+ uint64_t intel_prefetch_support:1;
+ uint64_t smap_support:1;
+ uint64_t hle_support:1;
+ uint64_t rtm_support:1;
+ uint64_t rdtscp_support:1;
+ uint64_t clflushopt_support:1;
+ uint64_t clwb_support:1;
+ uint64_t sha_support:1;
+ uint64_t x87_pointers_saved_support:1;
+ uint64_t invpcid_support:1;
+ uint64_t ibrs_support:1;
+ uint64_t stibp_support:1;
+ uint64_t ibpb_support:1;
+ uint64_t unrestricted_guest_support:1;
+ uint64_t mdd_support:1;
+ uint64_t fast_short_rep_mov_support:1;
+ uint64_t l1dcache_flush_support:1;
+ uint64_t rdcl_no_support:1;
+ uint64_t ibrs_all_support:1;
+ uint64_t skip_l1df_support:1;
+ uint64_t ssb_no_support:1;
+ uint64_t rsb_a_no_support:1;
+ uint64_t virt_spec_ctrl_support:1;
+ uint64_t rd_pid_support:1;
+ uint64_t umip_support:1;
+ uint64_t mbs_no_support:1;
+ uint64_t mb_clear_support:1;
+ uint64_t taa_no_support:1;
+ uint64_t tsx_ctrl_support:1;
+ uint64_t reserved_bank0:1;
+
+ /* N.B. Begin bank 1 processor features. */
+ uint64_t a_count_m_count_support:1;
+ uint64_t tsc_invariant_support:1;
+ uint64_t cl_zero_support:1;
+ uint64_t rdpru_support:1;
+ uint64_t la57_support:1;
+ uint64_t mbec_support:1;
+ uint64_t nested_virt_support:1;
+ uint64_t psfd_support:1;
+ uint64_t cet_ss_support:1;
+ uint64_t cet_ibt_support:1;
+ uint64_t vmx_exception_inject_support:1;
+ uint64_t enqcmd_support:1;
+ uint64_t umwait_tpause_support:1;
+ uint64_t movdiri_support:1;
+ uint64_t movdir64b_support:1;
+ uint64_t cldemote_support:1;
+ uint64_t serialize_support:1;
+ uint64_t tsc_deadline_tmr_support:1;
+ uint64_t tsc_adjust_support:1;
+ uint64_t fzl_rep_movsb:1;
+ uint64_t fs_rep_stosb:1;
+ uint64_t fs_rep_cmpsb:1;
+ uint64_t tsx_ld_trk_support:1;
+ uint64_t vmx_ins_outs_exit_info_support:1;
+ uint64_t hlat_support:1;
+ uint64_t sbdr_ssdp_no_support:1;
+ uint64_t fbsdp_no_support:1;
+ uint64_t psdp_no_support:1;
+ uint64_t fb_clear_support:1;
+ uint64_t btc_no_support:1;
+ uint64_t ibpb_rsb_flush_support:1;
+ uint64_t stibp_always_on_support:1;
+ uint64_t perf_global_ctrl_support:1;
+ uint64_t npt_execute_only_support:1;
+ uint64_t npt_ad_flags_support:1;
+ uint64_t npt1_gb_page_support:1;
+ uint64_t amd_processor_topology_node_id_support:1;
+ uint64_t local_machine_check_support:1;
+ uint64_t extended_topology_leaf_fp256_amd_support:1;
+ uint64_t gds_no_support:1;
+ uint64_t cmpccxadd_support:1;
+ uint64_t tsc_aux_virtualization_support:1;
+ uint64_t rmp_query_support:1;
+ uint64_t bhi_no_support:1;
+ uint64_t bhi_dis_support:1;
+ uint64_t prefetch_i_support:1;
+ uint64_t sha512_support:1;
+ uint64_t mitigation_ctrl_support:1;
+ uint64_t rfds_no_support:1;
+ uint64_t rfds_clear_support:1;
+ uint64_t sm3_support:1;
+ uint64_t sm4_support:1;
+ uint64_t secure_avic_support:1;
+ uint64_t guest_intercept_ctrl_support:1;
+ uint64_t sbpb_supported:1;
+ uint64_t ibpb_br_type_supported:1;
+ uint64_t srso_no_supported:1;
+ uint64_t srso_user_kernel_no_supported:1;
+ uint64_t vrew_clear_supported:1;
+ uint64_t tsa_l1_no_supported:1;
+ uint64_t tsa_sq_no_supported:1;
+ uint64_t lass_support:1;
+ uint64_t idle_hlt_intercept_support:1;
+ uint64_t msr_list_support:1;
+ };
+};
+
enum hv_translate_gva_result_code {
HV_TRANSLATE_GVA_SUCCESS = 0,
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 1/9] accel/mshv: use mshv_create_partition_v2 payload
2026-04-16 12:11 ` [PATCH v6 1/9] accel/mshv: use mshv_create_partition_v2 payload Magnus Kulke
@ 2026-04-30 8:43 ` Doru Blânzeanu
0 siblings, 0 replies; 19+ messages in thread
From: Doru Blânzeanu @ 2026-04-30 8:43 UTC (permalink / raw)
To: Magnus Kulke
Cc: qemu-devel, Wei Liu, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
On Thu, Apr 16, 2026 at 02:11:08PM +0200, Magnus Kulke wrote:
> When using the extended request format we can instruct the hypervisor to
> provision enough space for requested XSAVE features. This is required
> for supporting QEMU models provided via the -cpu flag properly.
>
> Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
> Acked-by: Wei Liu <wei.liu@kernel.org>
> Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
> ---
> accel/mshv/mshv-all.c | 71 ++++++++++--
> include/hw/hyperv/hvgdk_mini.h | 2 +
> include/hw/hyperv/hvhdk.h | 195 +++++++++++++++++++++++++++++++++
> 3 files changed, 261 insertions(+), 7 deletions(-)
Reviewed-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 2/9] target/i386/mshv: fix cpuid propagation bug
2026-04-16 12:11 [PATCH v6 0/9] Support QEMU cpu models in MSHV accelerator Magnus Kulke
2026-04-16 12:11 ` [PATCH v6 1/9] accel/mshv: use mshv_create_partition_v2 payload Magnus Kulke
@ 2026-04-16 12:11 ` Magnus Kulke
2026-04-30 9:05 ` Doru Blânzeanu
2026-04-16 12:11 ` [PATCH v6 3/9] target/i386/mshv: fix various cpuid traversal bugs Magnus Kulke
` (6 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Magnus Kulke @ 2026-04-16 12:11 UTC (permalink / raw)
To: qemu-devel
Cc: Wei Liu, Magnus Kulke, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
The list argument was missing a pointer and hence e.g. -cpu qemu64 and
-cpu EPYC would produce the same of cpuid leaves.
Fixes: 4fa04dd1621 ("target/i386: Register CPUID entries with MSHV")
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
---
target/i386/mshv/mshv-cpu.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 2bc978deb2..f1cc4abc5c 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -441,7 +441,7 @@ int mshv_load_regs(CPUState *cpu)
return 0;
}
-static void add_cpuid_entry(GList *cpuid_entries,
+static void add_cpuid_entry(GList **cpuid_entries,
uint32_t function, uint32_t index,
uint32_t eax, uint32_t ebx,
uint32_t ecx, uint32_t edx)
@@ -456,10 +456,10 @@ static void add_cpuid_entry(GList *cpuid_entries,
entry->ecx = ecx;
entry->edx = edx;
- cpuid_entries = g_list_append(cpuid_entries, entry);
+ *cpuid_entries = g_list_append(*cpuid_entries, entry);
}
-static void collect_cpuid_entries(const CPUState *cpu, GList *cpuid_entries)
+static void collect_cpuid_entries(const CPUState *cpu, GList **cpuid_entries)
{
X86CPU *x86_cpu = X86_CPU(cpu);
CPUX86State *env = &x86_cpu->env;
@@ -615,7 +615,7 @@ static int set_cpuid2(const CPUState *cpu)
struct hv_cpuid_entry *entry;
GList *entries = NULL;
- collect_cpuid_entries(cpu, entries);
+ collect_cpuid_entries(cpu, &entries);
n_entries = g_list_length(entries);
cpuid_size = sizeof(struct hv_cpuid)
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 2/9] target/i386/mshv: fix cpuid propagation bug
2026-04-16 12:11 ` [PATCH v6 2/9] target/i386/mshv: fix cpuid propagation bug Magnus Kulke
@ 2026-04-30 9:05 ` Doru Blânzeanu
0 siblings, 0 replies; 19+ messages in thread
From: Doru Blânzeanu @ 2026-04-30 9:05 UTC (permalink / raw)
To: Magnus Kulke
Cc: qemu-devel, Wei Liu, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
On Thu, Apr 16, 2026 at 02:11:09PM +0200, Magnus Kulke wrote:
> The list argument was missing a pointer and hence e.g. -cpu qemu64 and
> -cpu EPYC would produce the same of cpuid leaves.
>
> Fixes: 4fa04dd1621 ("target/i386: Register CPUID entries with MSHV")
>
> Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
> ---
> target/i386/mshv/mshv-cpu.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
Reviewed-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 3/9] target/i386/mshv: fix various cpuid traversal bugs
2026-04-16 12:11 [PATCH v6 0/9] Support QEMU cpu models in MSHV accelerator Magnus Kulke
2026-04-16 12:11 ` [PATCH v6 1/9] accel/mshv: use mshv_create_partition_v2 payload Magnus Kulke
2026-04-16 12:11 ` [PATCH v6 2/9] target/i386/mshv: fix cpuid propagation bug Magnus Kulke
@ 2026-04-16 12:11 ` Magnus Kulke
2026-04-30 9:35 ` Doru Blânzeanu
2026-04-16 12:11 ` [PATCH v6 4/9] target/i386/mshv: change cpuid mask to UINT32_MAX Magnus Kulke
` (5 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Magnus Kulke @ 2026-04-16 12:11 UTC (permalink / raw)
To: qemu-devel
Cc: Wei Liu, Magnus Kulke, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
- Hardcoded max_leaf was not accurate. We query leaf 0x0 and 0x80000000 to
get the actual max leaves
- On all 0 zeroes on leaf 0x0d, we register 0-63 subleaves with zeros
indicating XSAVE is disabled
- Subleaf 0 was hardcoded, so the Hypervisor returned defaults for other
subleaves
- Subleaf 0 was hardcoded, so we were passing 0 instead of actual subleaf
when adding entries. We now pass the correct subleaf value to
add_cpuid_entry()
- Leaves 0x04,0x07,0d,0f,10 weren't marked as subleaf-specific
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
Acked-by: Wei Liu <wei.liu@kernel.org>
---
target/i386/mshv/mshv-cpu.c | 88 +++++++++++++++++++++++++------------
1 file changed, 61 insertions(+), 27 deletions(-)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index f1cc4abc5c..4183727a86 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -465,14 +465,17 @@ static void collect_cpuid_entries(const CPUState *cpu, GList **cpuid_entries)
CPUX86State *env = &x86_cpu->env;
uint32_t eax, ebx, ecx, edx;
uint32_t leaf, subleaf;
- size_t max_leaf = 0x1F;
- size_t max_subleaf = 0x20;
-
- uint32_t leaves_with_subleaves[] = {0x4, 0x7, 0xD, 0xF, 0x10};
+ uint32_t max_basic_leaf, max_extended_leaf;
+ uint32_t max_subleaf = 0x20;
+ uint32_t leaves_with_subleaves[] = {0x04, 0x07, 0x0d, 0x0f, 0x10};
int n_subleaf_leaves = ARRAY_SIZE(leaves_with_subleaves);
- /* Regular leaves without subleaves */
- for (leaf = 0; leaf <= max_leaf; leaf++) {
+ /* Get maximum basic and and extended CPUID leaves */
+ cpu_x86_cpuid(env, 0, 0, &max_basic_leaf, &ebx, &ecx, &edx);
+ cpu_x86_cpuid(env, 0x80000000, 0, &max_extended_leaf, &ebx, &ecx, &edx);
+
+ /* Collect basic leaves (0x0 to max_basic_leaf) */
+ for (leaf = 0; leaf <= max_basic_leaf; leaf++) {
bool has_subleaves = false;
for (int i = 0; i < n_subleaf_leaves; i++) {
if (leaf == leaves_with_subleaves[i]) {
@@ -483,27 +486,40 @@ static void collect_cpuid_entries(const CPUState *cpu, GList **cpuid_entries)
if (!has_subleaves) {
cpu_x86_cpuid(env, leaf, 0, &eax, &ebx, &ecx, &edx);
- if (eax == 0 && ebx == 0 && ecx == 0 && edx == 0) {
- /* all zeroes indicates no more leaves */
- continue;
- }
-
add_cpuid_entry(cpuid_entries, leaf, 0, eax, ebx, ecx, edx);
continue;
}
+ /*
+ * Valid XSAVE components can exist at a higher index se we need to set
+ * all subleaves for leaf 0x0d, even if we encounter an empty one.
+ */
+ if (leaf == 0x0d) {
+ for (subleaf = 0; subleaf <= 63; subleaf++) {
+ cpu_x86_cpuid(env, leaf, subleaf, &eax, &ebx, &ecx, &edx);
+ add_cpuid_entry(cpuid_entries, leaf, subleaf,
+ eax, ebx, ecx, edx);
+ }
+ continue;
+ }
+
subleaf = 0;
while (subleaf < max_subleaf) {
cpu_x86_cpuid(env, leaf, subleaf, &eax, &ebx, &ecx, &edx);
if (eax == 0 && ebx == 0 && ecx == 0 && edx == 0) {
- /* all zeroes indicates no more leaves */
break;
}
- add_cpuid_entry(cpuid_entries, leaf, 0, eax, ebx, ecx, edx);
+ add_cpuid_entry(cpuid_entries, leaf, subleaf, eax, ebx, ecx, edx);
subleaf++;
}
}
+
+ /* Collect extended leaves (0x80000000 to max_extended_leaf) */
+ for (leaf = 0x80000000; leaf <= max_extended_leaf; leaf++) {
+ cpu_x86_cpuid(env, leaf, 0, &eax, &ebx, &ecx, &edx);
+ add_cpuid_entry(cpuid_entries, leaf, 0, eax, ebx, ecx, edx);
+ }
}
static int register_intercept_result_cpuid_entry(const CPUState *cpu,
@@ -576,22 +592,40 @@ static int register_intercept_result_cpuid(const CPUState *cpu,
subleaf_specific = 0;
always_override = 1;
- /* Intel */
- /* 0xb - Extended Topology Enumeration Leaf */
- /* 0x1f - V2 Extended Topology Enumeration Leaf */
- /* AMD */
- /* 0x8000_001e - Processor Topology Information */
- /* 0x8000_0026 - Extended CPU Topology */
- if (entry->function == 0xb
- || entry->function == 0x1f
- || entry->function == 0x8000001e
- || entry->function == 0x80000026) {
+ /*
+ * Intel
+ * 0xb - Extended Topology Enumeration Leaf
+ * 0x1f - V2 Extended Topology Enumeration Leaf
+ * AMD
+ * 0x8000_001e - Processor Topology Information
+ * 0x8000_0026 - Extended CPU Topology
+ */
+ if (entry->function == 0xb ||
+ entry->function == 0x1f ||
+ entry->function == 0x8000001e ||
+ entry->function == 0x80000026) {
+ subleaf_specific = 1;
+ always_override = 1;
+ /*
+ * Feature enumeration leaves (subleaf-specific)
+ * 0x04: Deterministic Cache Parameters
+ * 0x07: Structured Extended Feature Flags
+ * 0x0D: Processor Extended State Enumeration
+ * 0x0F: Platform QoS Monitoring
+ * 0x10: Platform QoS Enforcement
+ */
+ } else if (entry->function == 0x04 ||
+ entry->function == 0x07 ||
+ entry->function == 0x0d ||
+ entry->function == 0x0f ||
+ entry->function == 0x10) {
subleaf_specific = 1;
always_override = 1;
- } else if (entry->function == 0x00000001
- || entry->function == 0x80000000
- || entry->function == 0x80000001
- || entry->function == 0x80000008) {
+ /* Basic feature leaves (no subleaves) */
+ } else if (entry->function == 0x00000001 ||
+ entry->function == 0x80000000 ||
+ entry->function == 0x80000001 ||
+ entry->function == 0x80000008) {
subleaf_specific = 0;
always_override = 1;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 3/9] target/i386/mshv: fix various cpuid traversal bugs
2026-04-16 12:11 ` [PATCH v6 3/9] target/i386/mshv: fix various cpuid traversal bugs Magnus Kulke
@ 2026-04-30 9:35 ` Doru Blânzeanu
0 siblings, 0 replies; 19+ messages in thread
From: Doru Blânzeanu @ 2026-04-30 9:35 UTC (permalink / raw)
To: Magnus Kulke
Cc: qemu-devel, Wei Liu, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
On Thu, Apr 16, 2026 at 02:11:10PM +0200, Magnus Kulke wrote:
> - Hardcoded max_leaf was not accurate. We query leaf 0x0 and 0x80000000 to
> get the actual max leaves
>
> - On all 0 zeroes on leaf 0x0d, we register 0-63 subleaves with zeros
> indicating XSAVE is disabled
>
> - Subleaf 0 was hardcoded, so the Hypervisor returned defaults for other
> subleaves
>
> - Subleaf 0 was hardcoded, so we were passing 0 instead of actual subleaf
> when adding entries. We now pass the correct subleaf value to
> add_cpuid_entry()
>
> - Leaves 0x04,0x07,0d,0f,10 weren't marked as subleaf-specific
>
> Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
> Acked-by: Wei Liu <wei.liu@kernel.org>
> ---
> target/i386/mshv/mshv-cpu.c | 88 +++++++++++++++++++++++++------------
> 1 file changed, 61 insertions(+), 27 deletions(-)
Reviewed-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 4/9] target/i386/mshv: change cpuid mask to UINT32_MAX
2026-04-16 12:11 [PATCH v6 0/9] Support QEMU cpu models in MSHV accelerator Magnus Kulke
` (2 preceding siblings ...)
2026-04-16 12:11 ` [PATCH v6 3/9] target/i386/mshv: fix various cpuid traversal bugs Magnus Kulke
@ 2026-04-16 12:11 ` Magnus Kulke
2026-04-30 11:27 ` Doru Blânzeanu
2026-04-16 12:11 ` [PATCH v6 5/9] target/i386/mshv: set cpu model name on -cpu host Magnus Kulke
` (4 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Magnus Kulke @ 2026-04-16 12:11 UTC (permalink / raw)
To: qemu-devel
Cc: Wei Liu, Magnus Kulke, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
The current implementation would only override the feature bits that are
enabled, however we also want to consider disabled features, hence all
bits are set on the masks in the hypercall argument.
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
Acked-by: Wei Liu <wei.liu@kernel.org>
---
target/i386/mshv/mshv-cpu.c | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 4183727a86..e42b5a614d 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -538,22 +538,17 @@ static int register_intercept_result_cpuid_entry(const CPUState *cpu,
.input.always_override = always_override,
.input.padding = 0,
/*
- * With regard to masks - these are to specify bits to be overwritten
- * The current CpuidEntry structure wouldn't allow to carry the masks
- * in addition to the actual register values. For this reason, the
- * masks are set to the exact values of the corresponding register bits
- * to be registered for an overwrite. To view resulting values the
- * hypervisor would return, HvCallGetVpCpuidValues hypercall can be
- * used.
+ * Masks specify which bits to override. Set to 0xFFFFFFFF to
+ * override all bits with the values from the QEMU CPU model.
*/
.result.eax = entry->eax,
- .result.eax_mask = entry->eax,
+ .result.eax_mask = 0xFFFFFFFF,
.result.ebx = entry->ebx,
- .result.ebx_mask = entry->ebx,
+ .result.ebx_mask = 0xFFFFFFFF,
.result.ecx = entry->ecx,
- .result.ecx_mask = entry->ecx,
+ .result.ecx_mask = 0xFFFFFFFF,
.result.edx = entry->edx,
- .result.edx_mask = entry->edx,
+ .result.edx_mask = 0xFFFFFFFF,
};
union hv_register_intercept_result_parameters parameters = {
.cpuid = cpuid_params,
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 4/9] target/i386/mshv: change cpuid mask to UINT32_MAX
2026-04-16 12:11 ` [PATCH v6 4/9] target/i386/mshv: change cpuid mask to UINT32_MAX Magnus Kulke
@ 2026-04-30 11:27 ` Doru Blânzeanu
0 siblings, 0 replies; 19+ messages in thread
From: Doru Blânzeanu @ 2026-04-30 11:27 UTC (permalink / raw)
To: Magnus Kulke
Cc: qemu-devel, Wei Liu, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
On Thu, Apr 16, 2026 at 02:11:11PM +0200, Magnus Kulke wrote:
> The current implementation would only override the feature bits that are
> enabled, however we also want to consider disabled features, hence all
> bits are set on the masks in the hypercall argument.
>
> Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
> Acked-by: Wei Liu <wei.liu@kernel.org>
> ---
> target/i386/mshv/mshv-cpu.c | 17 ++++++-----------
> 1 file changed, 6 insertions(+), 11 deletions(-)
>
Reviewed-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 5/9] target/i386/mshv: set cpu model name on -cpu host
2026-04-16 12:11 [PATCH v6 0/9] Support QEMU cpu models in MSHV accelerator Magnus Kulke
` (3 preceding siblings ...)
2026-04-16 12:11 ` [PATCH v6 4/9] target/i386/mshv: change cpuid mask to UINT32_MAX Magnus Kulke
@ 2026-04-16 12:11 ` Magnus Kulke
2026-04-30 11:47 ` Doru Blânzeanu
2026-04-16 12:11 ` [PATCH v6 6/9] target/i386: query mshv accel for supported cpuids Magnus Kulke
` (3 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Magnus Kulke @ 2026-04-16 12:11 UTC (permalink / raw)
To: qemu-devel
Cc: Wei Liu, Magnus Kulke, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
By registering a cpu_accel_class for mshv, we can report an accurate
model name on -cpu host.
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
Acked-by: Wei Liu <wei.liu@kernel.org>
---
target/i386/mshv/mshv-cpu.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index e42b5a614d..09878ef357 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -24,10 +24,13 @@
#include "hw/i386/apic_internal.h"
#include "cpu.h"
+#include "host-cpu.h"
#include "emulate/x86_decode.h"
#include "emulate/x86_emu.h"
#include "emulate/x86_flags.h"
+#include "accel/accel-cpu-target.h"
+
#include "trace-accel_mshv.h"
#include "trace.h"
@@ -1675,3 +1678,31 @@ int mshv_arch_post_init_vm(int vm_fd)
return ret;
}
+
+static void mshv_cpu_instance_init(CPUState *cs)
+{
+ X86CPU *cpu = X86_CPU(cs);
+
+ host_cpu_instance_init(cpu);
+}
+
+static void mshv_cpu_accel_class_init(ObjectClass *oc, const void *data)
+{
+ AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
+
+ acc->cpu_instance_init = mshv_cpu_instance_init;
+}
+
+static const TypeInfo mshv_cpu_accel_type_info = {
+ .name = ACCEL_CPU_NAME("mshv"),
+ .parent = TYPE_ACCEL_CPU,
+ .class_init = mshv_cpu_accel_class_init,
+ .abstract = true,
+};
+
+static void mshv_cpu_accel_register_types(void)
+{
+ type_register_static(&mshv_cpu_accel_type_info);
+}
+
+type_init(mshv_cpu_accel_register_types);
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 5/9] target/i386/mshv: set cpu model name on -cpu host
2026-04-16 12:11 ` [PATCH v6 5/9] target/i386/mshv: set cpu model name on -cpu host Magnus Kulke
@ 2026-04-30 11:47 ` Doru Blânzeanu
0 siblings, 0 replies; 19+ messages in thread
From: Doru Blânzeanu @ 2026-04-30 11:47 UTC (permalink / raw)
To: Magnus Kulke
Cc: qemu-devel, Wei Liu, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
On Thu, Apr 16, 2026 at 02:11:12PM +0200, Magnus Kulke wrote:
> By registering a cpu_accel_class for mshv, we can report an accurate
> model name on -cpu host.
>
> Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
> Acked-by: Wei Liu <wei.liu@kernel.org>
> ---
> target/i386/mshv/mshv-cpu.c | 31 +++++++++++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
>
Reviewed-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 6/9] target/i386: query mshv accel for supported cpuids
2026-04-16 12:11 [PATCH v6 0/9] Support QEMU cpu models in MSHV accelerator Magnus Kulke
` (4 preceding siblings ...)
2026-04-16 12:11 ` [PATCH v6 5/9] target/i386/mshv: set cpu model name on -cpu host Magnus Kulke
@ 2026-04-16 12:11 ` Magnus Kulke
2026-05-06 10:41 ` Doru Blânzeanu
2026-04-16 12:11 ` [PATCH v6 7/9] target/i386/mshv: populate xsave area offsets Magnus Kulke
` (2 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Magnus Kulke @ 2026-04-16 12:11 UTC (permalink / raw)
To: qemu-devel
Cc: Wei Liu, Magnus Kulke, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
We implement mshv_get_supported_cpuid() and invoke it in
x86_cpu_get_supported_feature_word() retrieve the cpu features that the
host is supporting. Initially we mask the virtualization capabilitities
potentially we might need to mask more in the future.
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
---
include/system/mshv.h | 3 +++
target/i386/cpu.c | 8 ++++++++
target/i386/mshv/mshv-cpu.c | 27 +++++++++++++++++++++++++++
3 files changed, 38 insertions(+)
diff --git a/include/system/mshv.h b/include/system/mshv.h
index 75286baf16..51b0420735 100644
--- a/include/system/mshv.h
+++ b/include/system/mshv.h
@@ -60,4 +60,7 @@ int mshv_irqchip_add_irqfd_notifier_gsi(const EventNotifier *n,
const EventNotifier *rn, int virq);
int mshv_irqchip_remove_irqfd_notifier_gsi(const EventNotifier *n, int virq);
+/* cpuid */
+uint32_t mshv_get_supported_cpuid(uint32_t func, uint32_t idx, int reg);
+
#endif
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index c6fd1dc00e..4dd9752fd0 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -26,6 +26,7 @@
#include "tcg/helper-tcg.h"
#include "exec/translation-block.h"
#include "system/hvf.h"
+#include "system/mshv.h"
#include "hvf/hvf-i386.h"
#include "kvm/kvm_i386.h"
#include "kvm/tdx.h"
@@ -8087,6 +8088,13 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w)
r = hvf_get_supported_cpuid(wi->cpuid.eax,
wi->cpuid.ecx,
wi->cpuid.reg);
+ } else if (mshv_enabled()) {
+ if (wi->type != CPUID_FEATURE_WORD) {
+ return 0;
+ }
+ r = mshv_get_supported_cpuid(wi->cpuid.eax,
+ wi->cpuid.ecx,
+ wi->cpuid.reg);
} else if (tcg_enabled() || qtest_enabled()) {
r = wi->tcg_features;
} else {
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 09878ef357..3b392533b4 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -1639,6 +1639,33 @@ void mshv_arch_destroy_vcpu(CPUState *cpu)
g_clear_pointer(&env->emu_mmio_buf, g_free);
}
+uint32_t mshv_get_supported_cpuid(uint32_t func, uint32_t idx, int reg)
+{
+ uint32_t eax, ebx, ecx, edx;
+ uint32_t ret = 0;
+
+ host_cpuid(func, idx, &eax, &ebx, &ecx, &edx);
+ switch (reg) {
+ case R_EAX:
+ ret = eax; break;
+ case R_EBX:
+ ret = ebx; break;
+ case R_ECX:
+ ret = ecx; break;
+ case R_EDX:
+ ret = edx; break;
+ }
+
+ /* Disable nested virtualization features not yet supported by MSHV */
+ if (func == 0x80000001 && reg == R_ECX) {
+ ret &= ~CPUID_EXT3_SVM;
+ }
+ if (func == 0x01 && reg == R_ECX) {
+ ret &= ~CPUID_EXT_VMX;
+ }
+ return ret;
+}
+
/*
* Default Microsoft Hypervisor behavior for unimplemented MSR is to send a
* fault to the guest if it tries to access it. It is possible to override
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 6/9] target/i386: query mshv accel for supported cpuids
2026-04-16 12:11 ` [PATCH v6 6/9] target/i386: query mshv accel for supported cpuids Magnus Kulke
@ 2026-05-06 10:41 ` Doru Blânzeanu
0 siblings, 0 replies; 19+ messages in thread
From: Doru Blânzeanu @ 2026-05-06 10:41 UTC (permalink / raw)
To: Magnus Kulke
Cc: qemu-devel, Wei Liu, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke, Doru Blânzeanu
On Thu, Apr 16, 2026 at 02:11:13PM +0200, Magnus Kulke wrote:
> We implement mshv_get_supported_cpuid() and invoke it in
> x86_cpu_get_supported_feature_word() retrieve the cpu features that the
> host is supporting. Initially we mask the virtualization capabilitities
> potentially we might need to mask more in the future.
>
> Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
> ---
> include/system/mshv.h | 3 +++
> target/i386/cpu.c | 8 ++++++++
> target/i386/mshv/mshv-cpu.c | 27 +++++++++++++++++++++++++++
> 3 files changed, 38 insertions(+)
Reviewed-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 7/9] target/i386/mshv: populate xsave area offsets
2026-04-16 12:11 [PATCH v6 0/9] Support QEMU cpu models in MSHV accelerator Magnus Kulke
` (5 preceding siblings ...)
2026-04-16 12:11 ` [PATCH v6 6/9] target/i386: query mshv accel for supported cpuids Magnus Kulke
@ 2026-04-16 12:11 ` Magnus Kulke
2026-05-06 11:02 ` Doru Blânzeanu
2026-04-16 12:11 ` [PATCH v6 8/9] target/i386/mshv: use hv-provided [0xD,1+2].EBX Magnus Kulke
2026-04-16 12:11 ` [PATCH v6 9/9] accel/mshv: disable la57 (5lvl paging) Magnus Kulke
8 siblings, 1 reply; 19+ messages in thread
From: Magnus Kulke @ 2026-04-16 12:11 UTC (permalink / raw)
To: qemu-devel
Cc: Wei Liu, Magnus Kulke, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
This function is copied verbatim from kvm_cpu_xsave_init(), for MSHV we
need to populate the offsets similarly.
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
---
target/i386/mshv/mshv-cpu.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 3b392533b4..ee25eb5f6f 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -1706,11 +1706,42 @@ int mshv_arch_post_init_vm(int vm_fd)
return ret;
}
+static void mshv_cpu_xsave_init(void)
+{
+ static bool first = true;
+ uint32_t eax, ebx, ecx, edx;
+ int i;
+
+ if (!first) {
+ return;
+ }
+ first = false;
+
+ /* x87 and SSE states are in the legacy region of the XSAVE area. */
+ x86_ext_save_areas[XSTATE_FP_BIT].offset = 0;
+ x86_ext_save_areas[XSTATE_SSE_BIT].offset = 0;
+
+ for (i = XSTATE_SSE_BIT + 1; i < XSAVE_STATE_AREA_COUNT; i++) {
+ ExtSaveArea *esa = &x86_ext_save_areas[i];
+
+ if (!esa->size) {
+ continue;
+ }
+ host_cpuid(0xd, i, &eax, &ebx, &ecx, &edx);
+ if (eax != 0) {
+ assert(esa->size == eax);
+ esa->offset = ebx;
+ esa->ecx = ecx;
+ }
+ }
+}
+
static void mshv_cpu_instance_init(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
host_cpu_instance_init(cpu);
+ mshv_cpu_xsave_init();
}
static void mshv_cpu_accel_class_init(ObjectClass *oc, const void *data)
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 7/9] target/i386/mshv: populate xsave area offsets
2026-04-16 12:11 ` [PATCH v6 7/9] target/i386/mshv: populate xsave area offsets Magnus Kulke
@ 2026-05-06 11:02 ` Doru Blânzeanu
0 siblings, 0 replies; 19+ messages in thread
From: Doru Blânzeanu @ 2026-05-06 11:02 UTC (permalink / raw)
To: Magnus Kulke
Cc: qemu-devel, Wei Liu, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke, Doru Blânzeanu
On Thu, Apr 16, 2026 at 02:11:14PM +0200, Magnus Kulke wrote:
> This function is copied verbatim from kvm_cpu_xsave_init(), for MSHV we
> need to populate the offsets similarly.
>
> Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
> Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
> ---
> target/i386/mshv/mshv-cpu.c | 31 +++++++++++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
>
Reviewed-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 8/9] target/i386/mshv: use hv-provided [0xD,1+2].EBX
2026-04-16 12:11 [PATCH v6 0/9] Support QEMU cpu models in MSHV accelerator Magnus Kulke
` (6 preceding siblings ...)
2026-04-16 12:11 ` [PATCH v6 7/9] target/i386/mshv: populate xsave area offsets Magnus Kulke
@ 2026-04-16 12:11 ` Magnus Kulke
2026-05-06 11:14 ` Doru Blânzeanu
2026-04-16 12:11 ` [PATCH v6 9/9] accel/mshv: disable la57 (5lvl paging) Magnus Kulke
8 siblings, 1 reply; 19+ messages in thread
From: Magnus Kulke @ 2026-04-16 12:11 UTC (permalink / raw)
To: qemu-devel
Cc: Wei Liu, Magnus Kulke, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
We cannot statically set the responses for CPUID[0xD,{1,2}].EBX, b/c
those are dynamic, dependent on which features the guest enables.
Hence we mask EBX when registering answers for those subleaves at the
hypervisor, which will result in the hypervisor providing us answers,
considering XCR0 and XSS.
The reported size now reflects the field masks properly (without the
mask they were 576 and 10728, which is wrong):
$ cpuid -l 0xd -s 0
CPU 0:
XSAVE features (0xd/0):
XCR0 valid bit field mask = 0x00000000000600e7
...
bytes required by fields in XCR0 = 0x00002b00 (11008)
bytes required by XSAVE/XRSTOR area = 0x00002b00 (11008)
$ cpuid -l 0xd -s 1
CPU 0:
XSAVE features (0xd/1):
...
SAVE area size in bytes = 0x000029c0 (10688)
IA32_XSS lower 32 bits valid bit field mask = 0x00001800
IA32_XSS upper 32 bits valid bit field mask = 0x00000000
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
---
target/i386/mshv/mshv-cpu.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index ee25eb5f6f..b90e2983c8 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -528,6 +528,7 @@ static void collect_cpuid_entries(const CPUState *cpu, GList **cpuid_entries)
static int register_intercept_result_cpuid_entry(const CPUState *cpu,
uint8_t subleaf_specific,
uint8_t always_override,
+ uint32_t ebx_mask,
struct hv_cpuid_entry *entry)
{
int ret;
@@ -543,11 +544,12 @@ static int register_intercept_result_cpuid_entry(const CPUState *cpu,
/*
* Masks specify which bits to override. Set to 0xFFFFFFFF to
* override all bits with the values from the QEMU CPU model.
+ * A mask of 0 lets the hypervisor supply its own value.
*/
.result.eax = entry->eax,
.result.eax_mask = 0xFFFFFFFF,
.result.ebx = entry->ebx,
- .result.ebx_mask = 0xFFFFFFFF,
+ .result.ebx_mask = ebx_mask,
.result.ecx = entry->ecx,
.result.ecx_mask = 0xFFFFFFFF,
.result.edx = entry->edx,
@@ -582,6 +584,7 @@ static int register_intercept_result_cpuid(const CPUState *cpu,
int ret = 0, entry_ret;
struct hv_cpuid_entry *entry;
uint8_t subleaf_specific, always_override;
+ uint32_t ebx_mask;
for (size_t i = 0; i < cpuid->nent; i++) {
entry = &cpuid->entries[i];
@@ -589,6 +592,7 @@ static int register_intercept_result_cpuid(const CPUState *cpu,
/* set defaults */
subleaf_specific = 0;
always_override = 1;
+ ebx_mask = 0xFFFFFFFF;
/*
* Intel
@@ -628,8 +632,22 @@ static int register_intercept_result_cpuid(const CPUState *cpu,
always_override = 1;
}
- entry_ret = register_intercept_result_cpuid_entry(cpu, subleaf_specific,
+ /*
+ * CPUID[0xD,0].EBX and CPUID[0xD,1].EBX report the XSAVE area
+ * size based on features currently enabled in XCR0/XSS. These
+ * values are dynamic and must not be overridden with static
+ * results from the QEMU CPU model. Setting ebx_mask to 0 lets
+ * the hypervisor supply EBX based on the guest's actual state.
+ */
+ if (entry->function == 0x0d &&
+ (entry->index == 0 || entry->index == 1)) {
+ ebx_mask = 0;
+ }
+
+ entry_ret = register_intercept_result_cpuid_entry(cpu,
+ subleaf_specific,
always_override,
+ ebx_mask,
entry);
if ((entry_ret < 0) && (ret == 0)) {
ret = entry_ret;
@@ -1663,6 +1681,7 @@ uint32_t mshv_get_supported_cpuid(uint32_t func, uint32_t idx, int reg)
if (func == 0x01 && reg == R_ECX) {
ret &= ~CPUID_EXT_VMX;
}
+
return ret;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 8/9] target/i386/mshv: use hv-provided [0xD,1+2].EBX
2026-04-16 12:11 ` [PATCH v6 8/9] target/i386/mshv: use hv-provided [0xD,1+2].EBX Magnus Kulke
@ 2026-05-06 11:14 ` Doru Blânzeanu
0 siblings, 0 replies; 19+ messages in thread
From: Doru Blânzeanu @ 2026-05-06 11:14 UTC (permalink / raw)
To: Magnus Kulke
Cc: qemu-devel, Wei Liu, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke, Doru Blânzeanu
On Thu, Apr 16, 2026 at 02:11:15PM +0200, Magnus Kulke wrote:
> We cannot statically set the responses for CPUID[0xD,{1,2}].EBX, b/c
> those are dynamic, dependent on which features the guest enables.
>
> Hence we mask EBX when registering answers for those subleaves at the
> hypervisor, which will result in the hypervisor providing us answers,
> considering XCR0 and XSS.
>
> The reported size now reflects the field masks properly (without the
> mask they were 576 and 10728, which is wrong):
>
> $ cpuid -l 0xd -s 0
> CPU 0:
> XSAVE features (0xd/0):
> XCR0 valid bit field mask = 0x00000000000600e7
> ...
> bytes required by fields in XCR0 = 0x00002b00 (11008)
> bytes required by XSAVE/XRSTOR area = 0x00002b00 (11008)
>
> $ cpuid -l 0xd -s 1
> CPU 0:
> XSAVE features (0xd/1):
> ...
> SAVE area size in bytes = 0x000029c0 (10688)
> IA32_XSS lower 32 bits valid bit field mask = 0x00001800
> IA32_XSS upper 32 bits valid bit field mask = 0x00000000
>
> Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
> ---
> target/i386/mshv/mshv-cpu.c | 23 +++++++++++++++++++++--
> 1 file changed, 21 insertions(+), 2 deletions(-)
>
Reviewed-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 9/9] accel/mshv: disable la57 (5lvl paging)
2026-04-16 12:11 [PATCH v6 0/9] Support QEMU cpu models in MSHV accelerator Magnus Kulke
` (7 preceding siblings ...)
2026-04-16 12:11 ` [PATCH v6 8/9] target/i386/mshv: use hv-provided [0xD,1+2].EBX Magnus Kulke
@ 2026-04-16 12:11 ` Magnus Kulke
2026-05-06 11:24 ` Doru Blânzeanu
8 siblings, 1 reply; 19+ messages in thread
From: Magnus Kulke @ 2026-04-16 12:11 UTC (permalink / raw)
To: qemu-devel
Cc: Wei Liu, Magnus Kulke, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke
This change disable la57 paging on the mshv hypervisor on both the
mshv processor feature bitmap and mask the cpuid feature leaf to the
guest.
Since the removal of hypervisor-assisted gva=>gpa translation in
1c85a4a3d7 we have seen MMIO errors in guests on la57-enabled hw. We
will have to investigate and test this further.
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
Reviewed-by: Wei Liu <wei.liu@kernel.org>
---
accel/mshv/mshv-all.c | 7 +++++++
include/system/mshv_int.h | 2 ++
target/i386/mshv/mshv-cpu.c | 15 +++++++++++++++
3 files changed, 24 insertions(+)
diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c
index c50641f174..a557623531 100644
--- a/accel/mshv/mshv-all.c
+++ b/accel/mshv/mshv-all.c
@@ -142,6 +142,8 @@ static int create_partition(int mshv_fd, int *vm_fd)
int ret;
uint64_t pt_flags, host_proc_features;
union hv_partition_processor_xsave_features disabled_xsave_features;
+ union hv_partition_processor_features disabled_partition_features = {0};
+
struct mshv_create_partition_v2 args = {0};
QEMU_BUILD_BUG_ON(MSHV_NUM_CPU_FEATURES_BANKS != 2);
@@ -177,6 +179,11 @@ static int create_partition(int mshv_fd, int *vm_fd)
}
args.pt_cpu_fbanks[1] = ~host_proc_features;
+ /* arch-specific features we disable regardless of host support */
+ mshv_arch_disable_partition_proc_features(&disabled_partition_features);
+ args.pt_cpu_fbanks[0] |= disabled_partition_features.as_uint64[0];
+ args.pt_cpu_fbanks[1] |= disabled_partition_features.as_uint64[1];
+
/* populate args structure */
args.pt_flags = pt_flags;
args.pt_isolation = MSHV_PT_ISOLATION_NONE;
diff --git a/include/system/mshv_int.h b/include/system/mshv_int.h
index 35386c422f..ca156cdf4b 100644
--- a/include/system/mshv_int.h
+++ b/include/system/mshv_int.h
@@ -94,6 +94,8 @@ void mshv_arch_init_vcpu(CPUState *cpu);
void mshv_arch_destroy_vcpu(CPUState *cpu);
void mshv_arch_amend_proc_features(
union hv_partition_synthetic_processor_features *features);
+void mshv_arch_disable_partition_proc_features(
+ union hv_partition_processor_features *disabled_features);
int mshv_arch_post_init_vm(int vm_fd);
typedef struct mshv_root_hvcall mshv_root_hvcall;
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index b90e2983c8..eb3e167c0d 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -1129,6 +1129,12 @@ void mshv_arch_amend_proc_features(
features->access_guest_idle_reg = 1;
}
+void mshv_arch_disable_partition_proc_features(
+ union hv_partition_processor_features *disabled_features)
+{
+ disabled_features->la57_support = 1;
+}
+
static int set_memory_info(const struct hyperv_message *msg,
struct hv_x64_memory_intercept_message *info)
{
@@ -1682,6 +1688,15 @@ uint32_t mshv_get_supported_cpuid(uint32_t func, uint32_t idx, int reg)
ret &= ~CPUID_EXT_VMX;
}
+ if (func == 0x07 && idx == 0 && reg == R_ECX) {
+ /*
+ * LA57 (5-level paging) causes incorrect GVA=>GPA translations
+ * in the instruction decoder/emulator. Disable until page table
+ * walk in x86_mmu.c works w/ 5-level paging.
+ */
+ ret &= ~CPUID_7_0_ECX_LA57;
+ }
+
return ret;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v6 9/9] accel/mshv: disable la57 (5lvl paging)
2026-04-16 12:11 ` [PATCH v6 9/9] accel/mshv: disable la57 (5lvl paging) Magnus Kulke
@ 2026-05-06 11:24 ` Doru Blânzeanu
0 siblings, 0 replies; 19+ messages in thread
From: Doru Blânzeanu @ 2026-05-06 11:24 UTC (permalink / raw)
To: Magnus Kulke
Cc: qemu-devel, Wei Liu, Zhao Liu, Paolo Bonzini, Wei Liu,
Magnus Kulke, Doru Blânzeanu
On Thu, Apr 16, 2026 at 02:11:16PM +0200, Magnus Kulke wrote:
> This change disable la57 paging on the mshv hypervisor on both the
> mshv processor feature bitmap and mask the cpuid feature leaf to the
> guest.
>
> Since the removal of hypervisor-assisted gva=>gpa translation in
> 1c85a4a3d7 we have seen MMIO errors in guests on la57-enabled hw. We
> will have to investigate and test this further.
>
> Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
> Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
> Reviewed-by: Wei Liu <wei.liu@kernel.org>
> ---
> accel/mshv/mshv-all.c | 7 +++++++
> include/system/mshv_int.h | 2 ++
> target/i386/mshv/mshv-cpu.c | 15 +++++++++++++++
> 3 files changed, 24 insertions(+)
>
Reviewed-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
^ permalink raw reply [flat|nested] 19+ messages in thread