From d3a24134e37d57abd3e7445842cda2717f49e96d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 14 Jul 2025 10:19:36 +0200 Subject: [PATCH 1/6] target/i386: do not expose ARCH_CAPABILITIES on AMD CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KVM emulates the ARCH_CAPABILITIES on x86 for both Intel and AMD cpus, although the IA32_ARCH_CAPABILITIES MSR is an Intel-specific MSR and it makes no sense to emulate it on AMD. As a consequence, VMs created on AMD with qemu -cpu host and using KVM will advertise the ARCH_CAPABILITIES feature and provide the IA32_ARCH_CAPABILITIES MSR. This can cause issues (like Windows BSOD) as the guest OS might not expect this MSR to exist on such cpus (the AMD documentation specifies that ARCH_CAPABILITIES feature and MSR are not defined on the AMD architecture). A fix was proposed in KVM code, however KVM maintainers don't want to change this behavior that exists for 6+ years and suggest changes to be done in QEMU instead. Therefore, hide the bit from "-cpu host": migration of -cpu host guests is only possible between identical host kernel and QEMU versions, therefore this is not a problematic breakage. If a future AMD machine does include the MSR, that would re-expose the Windows guest bug; but it would not be KVM/QEMU's problem at that point, as we'd be following a genuine physical CPU impl. Reported-by: Alexandre Chartre Suggested-by: Daniel P. Berrangé Reviewed-by: Xiaoyao Li Signed-off-by: Paolo Bonzini --- target/i386/kvm/kvm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index e8c8be09ba..369626f8c8 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -503,8 +503,12 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, * Linux v4.17-v4.20 incorrectly return ARCH_CAPABILITIES on SVM hosts. * We can detect the bug by checking if MSR_IA32_ARCH_CAPABILITIES is * returned by KVM_GET_MSR_INDEX_LIST. + * + * But also, because Windows does not like ARCH_CAPABILITIES on AMD + * mcahines at all, do not show the fake ARCH_CAPABILITIES MSR that + * KVM sets up. */ - if (!has_msr_arch_capabs) { + if (!has_msr_arch_capabs || !(edx & CPUID_7_0_EDX_ARCH_CAPABILITIES)) { ret &= ~CPUID_7_0_EDX_ARCH_CAPABILITIES; } } else if (function == 7 && index == 1 && reg == R_EAX) { From e52af92e9e6f8fc00f2ae6b63214b3d6213b3cec Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Thu, 17 Jul 2025 10:39:33 +0800 Subject: [PATCH 2/6] i386/cpu: Move x86_ext_save_areas[] initialization to .instance_init In x86_cpu_post_initfn(), the initialization of x86_ext_save_areas[] marks the unsupported xsave areas based on Host support. This step must be done before accel_cpu_instance_init(), otherwise, KVM's assertion on host xsave support would fail: qemu-system-x86_64: ../target/i386/kvm/kvm-cpu.c:149: kvm_cpu_xsave_init: Assertion `esa->size == eax' failed. (on AMD EPYC 7302 16-Core Processor) Move x86_ext_save_areas[] initialization to .instance_init and place it before accel_cpu_instance_init(). Fixes: commit 5f158abef44c ("target/i386: move accel_cpu_instance_init to .instance_init") Reported-by: Paolo Abeni Tested-by: Paolo Abeni Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20250717023933.2502109-1-zhao1.liu@intel.com Reviewed-by: Xiaoyao Li Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index da7d8dca63..251d5760a0 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -9619,6 +9619,16 @@ static void x86_cpu_register_feature_bit_props(X86CPUClass *xcc, } static void x86_cpu_post_initfn(Object *obj) +{ +#ifndef CONFIG_USER_ONLY + if (current_machine && current_machine->cgs) { + x86_confidential_guest_cpu_instance_init( + X86_CONFIDENTIAL_GUEST(current_machine->cgs), (CPU(obj))); + } +#endif +} + +static void x86_cpu_init_xsave(void) { static bool first = true; uint64_t supported_xcr0; @@ -9639,13 +9649,6 @@ static void x86_cpu_post_initfn(Object *obj) } } } - -#ifndef CONFIG_USER_ONLY - if (current_machine && current_machine->cgs) { - x86_confidential_guest_cpu_instance_init( - X86_CONFIDENTIAL_GUEST(current_machine->cgs), (CPU(obj))); - } -#endif } static void x86_cpu_init_default_topo(X86CPU *cpu) @@ -9715,6 +9718,11 @@ static void x86_cpu_initfn(Object *obj) x86_cpu_load_model(cpu, xcc->model); } + /* + * accel's cpu_instance_init may have the xsave check, + * so x86_ext_save_areas[] must be initialized before this. + */ + x86_cpu_init_xsave(); accel_cpu_instance_init(CPU(obj)); } From e00cb2189a920bcfb428622c5d112469c4a094d1 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Thu, 17 Jul 2025 15:12:56 +0200 Subject: [PATCH 3/6] meson: re-generate scripts/meson-buildoptions.sh to fix IGVM entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 84fe49d94a ("meson: Add optional dependency on IGVM library") was inconsistent with the contents of meson_options.txt and the one generated in scripts/meson-buildoptions.sh Let's regenerate the file in this way to keep them consistent and prevent future changes from including the spurious diff: touch meson_options.txt make update-buildoptions Fixes: 84fe49d94a ("meson: Add optional dependency on IGVM library") Cc: roy.hopkins@randomman.co.uk Reported-by: Daniel P. Berrangé Signed-off-by: Stefano Garzarella Link: https://lore.kernel.org/r/20250717131256.157383-1-sgarzare@redhat.com Signed-off-by: Paolo Bonzini --- scripts/meson-buildoptions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index e8504689e8..0ebe6bc52a 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -130,7 +130,7 @@ meson_options_help() { printf "%s\n" ' hv-balloon hv-balloon driver (requires Glib 2.68+ GTree API)' printf "%s\n" ' hvf HVF acceleration support' printf "%s\n" ' iconv Font glyph conversion support' - printf "%s\n" ' igvm IGVM file support' + printf "%s\n" ' igvm Independent Guest Virtual Machine (IGVM) file support' printf "%s\n" ' jack JACK sound support' printf "%s\n" ' keyring Linux keyring support' printf "%s\n" ' kvm KVM acceleration support' From f2b787976342a9e1d47810f3146ad74b86a5088a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 17 Jul 2025 12:32:23 +0200 Subject: [PATCH 4/6] target/i386: tdx: fix locking for interrupt injection Take tdx_guest->lock when injecting the event notification interrupt into the guest. Fixes CID 1612364. Reported-by: Peter Maydell Cc: Xiaoyao Li Reviewed-by: Xiaoyao Li Signed-off-by: Paolo Bonzini --- target/i386/kvm/tdx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c index 7d69d6d7b0..1574e7d76f 100644 --- a/target/i386/kvm/tdx.c +++ b/target/i386/kvm/tdx.c @@ -1126,10 +1126,15 @@ int tdx_parse_tdvf(void *flash_ptr, int size) return tdvf_parse_metadata(&tdx_guest->tdvf, flash_ptr, size); } -static void tdx_inject_interrupt(uint32_t apicid, uint32_t vector) +static void tdx_inject_interrupt(TdxGuest *tdx) { int ret; + uint32_t apicid, vector; + qemu_mutex_lock(&tdx->lock); + vector = tdx->event_notify_vector; + apicid = tdx->event_notify_apicid; + qemu_mutex_unlock(&tdx->lock); if (vector < 32 || vector > 255) { return; } @@ -1179,8 +1184,7 @@ static void tdx_get_quote_completion(TdxGenerateQuoteTask *task) error_report("TDX: get-quote: failed to update GetQuote header."); } - tdx_inject_interrupt(tdx_guest->event_notify_apicid, - tdx_guest->event_notify_vector); + tdx_inject_interrupt(tdx); g_free(task->send_data); g_free(task->receive_buf); From 5fe6b9a854a91df86fdb794cbeb67d0656756137 Mon Sep 17 00:00:00 2001 From: Xiaoyao Li Date: Wed, 16 Jul 2025 14:31:16 +0800 Subject: [PATCH 5/6] i386/cpu: Cleanup host_cpu_max_instance_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The implementation of host_cpu_max_instance_init() was merged into host_cpu_instance_init() by commit 29f1ba338baf ("target/i386: merge host_cpu_instance_init() and host_cpu_max_instance_init()"), while the declaration of it remains in host-cpu.h. Clean it up. Signed-off-by: Xiaoyao Li Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Zhao Liu Link: https://lore.kernel.org/r/20250716063117.602050-1-xiaoyao.li@intel.com Signed-off-by: Paolo Bonzini --- target/i386/host-cpu.h | 1 - 1 file changed, 1 deletion(-) diff --git a/target/i386/host-cpu.h b/target/i386/host-cpu.h index 10df4b3a3a..ee65324225 100644 --- a/target/i386/host-cpu.h +++ b/target/i386/host-cpu.h @@ -12,7 +12,6 @@ uint32_t host_cpu_phys_bits(void); void host_cpu_instance_init(X86CPU *cpu); -void host_cpu_max_instance_init(X86CPU *cpu); bool host_cpu_realizefn(CPUState *cs, Error **errp); void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping); From f64832033d1262983bfe759669b4f65080f760dc Mon Sep 17 00:00:00 2001 From: Xiaoyao Li Date: Thu, 17 Jul 2025 18:37:07 +0800 Subject: [PATCH 6/6] i386/tdx: Remove the redundant qemu_mutex_init(&tdx->lock) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 40da501d8989 ("i386/tdx: handle TDG.VP.VMCALL") added redundant qemu_mutex_init(&tdx->lock) in tdx_guest_init by mistake. Fix it by removing the redundant one. Fixes: 40da501d8989 ("i386/tdx: handle TDG.VP.VMCALL") Reported-by: Peter Maydell Signed-off-by: Xiaoyao Li Reviewed-by: Daniel P. Berrangé Link: https://lore.kernel.org/r/20250717103707.688929-1-xiaoyao.li@intel.com Signed-off-by: Paolo Bonzini --- target/i386/kvm/tdx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c index 1574e7d76f..dbf0fa2c91 100644 --- a/target/i386/kvm/tdx.c +++ b/target/i386/kvm/tdx.c @@ -1527,8 +1527,6 @@ static void tdx_guest_init(Object *obj) tdx_guest_set_qgs, NULL, NULL); - qemu_mutex_init(&tdx->lock); - tdx->event_notify_vector = -1; tdx->event_notify_apicid = -1; }