* [PATCH 0/2] KVM: TDX: Enable VM-DoS Prevention Features for TDX @ 2026-08-05 3:12 Xiaoyao Li 2026-08-05 3:12 ` [PATCH 1/2] KVM: TDX: Enable Notify VM exit Xiaoyao Li 2026-08-05 3:12 ` [PATCH 2/2] KVM: TDX: Enable Bus Lock " Xiaoyao Li 0 siblings, 2 replies; 15+ messages in thread From: Xiaoyao Li @ 2026-08-05 3:12 UTC (permalink / raw) To: Sean Christopherson, Paolo Bonzini Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe, kvm, linux-kernel, xiaoyao.li There are 3 existing DoS prevention features that can be used by KVM/Linux to prevent DoS attacks from guests. 1. Bus Lock VM Exit This feature is controlled by KVM. KVM exposes KVM_CAP_X86_BUS_LOCK_EXIT as the interface for userspace to query support for and enable the feature. When enabled, a VM exit occurs after the execution of an instruction that asserts a bus lock. This VM exit is trap-like, meaning it does not prevent the bus lock from occurring but can detect that one has occurred. Similarly, there is another bus lock detection feature for OS usage, where a #DB is raised when a bus lock occurs at CPL > 0. KVM does not use this feature to detect bus locks from guests, but virtualizes it for the guest so that the guest can use it to detect bus locks from its own userspace. 2. Notify VM Exit This feature is also controlled by KVM. KVM exposes KVM_CAP_X86_NOTIFY_VMEXIT as the interface for userspace. When enabled, a VM exit occurs if certain operations prevent the processor from reaching an instruction boundary within the configured time window. 3. Split Lock Detection This feature is controlled by the host kernel rather than KVM. When enabled, a #AC is raised before a split lock can be acquired. Since the MSR controlling this feature is per-core in scope, KVM does not virtualize it for guests. As a result, when a guest split lock triggers a #AC, the exception is unexpected from the guest's perspective. KVM addresses this by intercepting the #AC and allowing the host to handle it. For features 1 and 2, support was missed (inadvertently omitted) for TDX during the initial TDX base support upstreaming. However, KVM still reports KVM_CAP_X86_BUS_LOCK_EXIT and KVM_CAP_X86_NOTIFY_VMEXIT as supported even for TDX guests. This means userspace does not receive an error when attempting to enable these features for TDs, even though they are not actually being enabled. For feature 3, KVM cannot intercept #AC from TDs. There was a prior effort[1] to enlighten the Linux TD guest kernel to handle such #AC. however, it was not accepted. We are looking at TDX architecture enhancement to allow intercepting #AC from TDs. This series therefore focuses on fixing the CAPs reporting issue and enabling features 1 and 2 for TDX. Specifically, this series adds the codes to call SEAMCALLs to set the controlling bits for the features in TD VMCS and implement the corresponding exit handlers. [1] https://lore.kernel.org/all/20260107134955.3293885-1-xiaoyao.li@intel.com/ Xiaoyao Li (2): KVM: TDX: Enable Notify VM exit KVM: TDX: Enable Bus Lock VM exit arch/x86/kvm/vmx/tdx.c | 33 ++++++++++++++++++++++++++++++++- arch/x86/kvm/vmx/vmx.c | 25 ++++++++++++++++--------- arch/x86/kvm/vmx/vmx.h | 2 ++ 3 files changed, 50 insertions(+), 10 deletions(-) base-commit: 1590cf0329716306e948a8fc29f1d3ee87d3989f -- 2.43.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] KVM: TDX: Enable Notify VM exit 2026-08-05 3:12 [PATCH 0/2] KVM: TDX: Enable VM-DoS Prevention Features for TDX Xiaoyao Li @ 2026-08-05 3:12 ` Xiaoyao Li 2026-08-05 3:38 ` sashiko-bot 2026-08-06 13:33 ` Nikolay Borisov 2026-08-05 3:12 ` [PATCH 2/2] KVM: TDX: Enable Bus Lock " Xiaoyao Li 1 sibling, 2 replies; 15+ messages in thread From: Xiaoyao Li @ 2026-08-05 3:12 UTC (permalink / raw) To: Sean Christopherson, Paolo Bonzini Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe, kvm, linux-kernel, xiaoyao.li Enable Notify VM exit functionality for TDX guests. Notify VM exit is an existing feature supported by KVM. Userspace can enable Notify VM exit through KVM_CAP_X86_NOTIFY_VMEXIT when it's reported as supported. However, KVM reports the support of this CAP just based on the hardware capability but doesn't differentiate between VMX and TDX. This leads to the issue that userspace can enable this cap for TDX guests without getting an error, but the feature is not actually enabled because KVM doesn't call the TDX module API to program the relevant TD VMCS fields. Enable Notify VM exit for TDX guests by: - Invoking TDX module API calls to set NOTIFY_VM_EXITING and Notify Window in TD VMCS. It's done in tdx_vcpu_init() where other TD VMCS bits are set. Since TDX vCPU cannot be reset, it only needs to be configured once when initializing the TDX vCPU. - Adding corresponding exit handler for TDX Notify VM Exit. Note, Notify VM exit can happen when executing the IRET instruction. If the IRET unblocks the NMI blocking state, bit 12 of the exit qualification is set. In this case, the VMM needs to restore the "blocked by NMI" state when it decides to re-enter the guest. For TDX, KVM cannot manage the GUEST_INTERRUPTIBILITY_INFO and it's TDX module's responsibility to handle it. Fixes: 161d34609f9b ("KVM: TDX: Make TDX VM type supported") Cc: stable@vger.kernel.org Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> --- The enabling of Notify VM exit was missed in the initial upstreaming of TDX base support. We suppose the patch needs to be backported to stable kernels. So, the cc stable is added. --- arch/x86/kvm/vmx/tdx.c | 10 ++++++++++ arch/x86/kvm/vmx/vmx.c | 23 +++++++++++++++-------- arch/x86/kvm/vmx/vmx.h | 1 + 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index 545b03d9d10b..cdc0d24657ac 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -2129,6 +2129,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) * - If it's not an MSMI, no need to do anything here. */ return 1; + case EXIT_REASON_NOTIFY: + /* NMI blocking state is handled by TDX module */ + return __handle_notify(vcpu, false); default: break; } @@ -3157,6 +3160,13 @@ static int tdx_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *cmd) td_vmcs_write64(tdx, POSTED_INTR_DESC_ADDR, __pa(&tdx->vt.pi_desc)); td_vmcs_setbit32(tdx, PIN_BASED_VM_EXEC_CONTROL, PIN_BASED_POSTED_INTR); + if (kvm_notify_vmexit_enabled(vcpu->kvm)) { + td_vmcs_setbit32(tdx, SECONDARY_VM_EXEC_CONTROL, + SECONDARY_EXEC_NOTIFY_VM_EXITING); + td_vmcs_write32(tdx, NOTIFY_WINDOW, + vcpu->kvm->arch.notify_window); + } + tdx->state = VCPU_TD_STATE_INITIALIZED; return 0; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index cc75feec05da..9c5a7e5c907e 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6266,20 +6266,22 @@ static int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu) return 1; } -static int handle_notify(struct kvm_vcpu *vcpu) +int __handle_notify(struct kvm_vcpu *vcpu, bool handle_nmi_unblock) { unsigned long exit_qual = vmx_get_exit_qual(vcpu); bool context_invalid = exit_qual & NOTIFY_VM_CONTEXT_INVALID; ++vcpu->stat.notify_window_exits; - /* - * Notify VM exit happened while executing iret from NMI, - * "blocked by NMI" bit has to be set before next VM entry. - */ - if (enable_vnmi && (exit_qual & INTR_INFO_UNBLOCK_NMI)) - vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, - GUEST_INTR_STATE_NMI); + if (handle_nmi_unblock) { + /* + * Notify VM exit happened while executing iret from NMI, + * "blocked by NMI" bit has to be set before next VM entry. + */ + if (enable_vnmi && (exit_qual & INTR_INFO_UNBLOCK_NMI)) + vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, + GUEST_INTR_STATE_NMI); + } if (vcpu->kvm->arch.notify_vmexit_flags & KVM_X86_NOTIFY_VMEXIT_USER || context_invalid) { @@ -6292,6 +6294,11 @@ static int handle_notify(struct kvm_vcpu *vcpu) return 1; } +static int handle_notify(struct kvm_vcpu *vcpu) +{ + return __handle_notify(vcpu, true); +} + static int vmx_get_msr_imm_reg(struct kvm_vcpu *vcpu) { return vmx_get_instr_info_reg(vmcs_read32(VMX_INSTRUCTION_INFO)); diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index dc8517f15bc4..79431b5e9bcb 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -379,6 +379,7 @@ bool __vmx_vcpu_run(struct vcpu_vmx *vmx, unsigned int flags); void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu); void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type, bool set); +int __handle_notify(struct kvm_vcpu *vcpu, bool handle_nmi_unblock); static inline void vmx_disable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type) -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] KVM: TDX: Enable Notify VM exit 2026-08-05 3:12 ` [PATCH 1/2] KVM: TDX: Enable Notify VM exit Xiaoyao Li @ 2026-08-05 3:38 ` sashiko-bot 2026-08-05 4:16 ` Xiaoyao Li 2026-08-06 13:33 ` Nikolay Borisov 1 sibling, 1 reply; 15+ messages in thread From: sashiko-bot @ 2026-08-05 3:38 UTC (permalink / raw) To: Xiaoyao Li; +Cc: kvm Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] Userspace can trigger a host-side KVM_BUG_ON (which includes a WARN_ON_ONCE) by enabling KVM_CAP_X86_NOTIFY_VMEXIT on a TDX VM when the underlying TDX module does not support the feature. -- --- Patch [1]: [PATCH 1/2] KVM: TDX: Enable Notify VM exit --- commit c9d2769fa5b2847408c7817858612eb62b0c8346 Author: Xiaoyao Li <xiaoyao.li@intel.com> KVM: TDX: Enable Notify VM exit This commit enables Notify VM exit functionality for TDX guests by configuring the NOTIFY_VM_EXITING and Notify Window in the TD VMCS during vCPU initialization. It also adds an exit handler to process TDX Notify VM Exits and delegates NMI blocking state handling to the TDX module. > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c > index 545b03d9d10b8..cdc0d24657acb 100644 > --- a/arch/x86/kvm/vmx/tdx.c > +++ b/arch/x86/kvm/vmx/tdx.c [ ... ] > @@ -3157,6 +3160,13 @@ static int tdx_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *cmd) > td_vmcs_write64(tdx, POSTED_INTR_DESC_ADDR, __pa(&tdx->vt.pi_desc)); > td_vmcs_setbit32(tdx, PIN_BASED_VM_EXEC_CONTROL, PIN_BASED_POSTED_INTR); > > + if (kvm_notify_vmexit_enabled(vcpu->kvm)) { > + td_vmcs_setbit32(tdx, SECONDARY_VM_EXEC_CONTROL, > + SECONDARY_EXEC_NOTIFY_VM_EXITING); [Severity: High] Does this allow an unprivileged userspace process to trigger a host-side KVM_BUG_ON() and crash the host if panic_on_warn is enabled? If KVM advertises KVM_CAP_X86_NOTIFY_VMEXIT globally based solely on CPU hardware support, userspace can enable it for a TDX VM. If the underlying TDX module (e.g., v1.0) does not support Notify VM Exiting, this write will fail. When the TDX module write operation fails, the macro backing td_vmcs_setbit32() calls tdh_vp_wr_failed(), which triggers a KVM_BUG_ON(): arch/x86/kvm/vmx/tdx.c:tdh_vp_wr_failed() { KVM_BUG_ON(1, tdx->vcpu.kvm); pr_err("TDH_VP_WR[%s.0x%x]%s0x%llx failed: 0x%llx\n", ...); } Should we verify that the loaded TDX module actually supports the Notify VM Exit feature before attempting to program these TD VMCS fields? > + td_vmcs_write32(tdx, NOTIFY_WINDOW, > + vcpu->kvm->arch.notify_window); > + } > + > tdx->state = VCPU_TD_STATE_INITIALIZED; > > return 0; -- Sashiko AI review · https://sashiko.dev/#/patchset/20260805031257.1844914-1-xiaoyao.li@intel.com?part=1 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] KVM: TDX: Enable Notify VM exit 2026-08-05 3:38 ` sashiko-bot @ 2026-08-05 4:16 ` Xiaoyao Li 0 siblings, 0 replies; 15+ messages in thread From: Xiaoyao Li @ 2026-08-05 4:16 UTC (permalink / raw) To: sashiko-reviews; +Cc: kvm On 8/5/2026 11:38 AM, sashiko-bot@kernel.org wrote: >> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c >> index 545b03d9d10b8..cdc0d24657acb 100644 >> --- a/arch/x86/kvm/vmx/tdx.c >> +++ b/arch/x86/kvm/vmx/tdx.c > [ ... ] >> @@ -3157,6 +3160,13 @@ static int tdx_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *cmd) >> td_vmcs_write64(tdx, POSTED_INTR_DESC_ADDR, __pa(&tdx->vt.pi_desc)); >> td_vmcs_setbit32(tdx, PIN_BASED_VM_EXEC_CONTROL, PIN_BASED_POSTED_INTR); >> >> + if (kvm_notify_vmexit_enabled(vcpu->kvm)) { >> + td_vmcs_setbit32(tdx, SECONDARY_VM_EXEC_CONTROL, >> + SECONDARY_EXEC_NOTIFY_VM_EXITING); > [Severity: High] > Does this allow an unprivileged userspace process to trigger a host-side > KVM_BUG_ON() and crash the host if panic_on_warn is enabled? > > If KVM advertises KVM_CAP_X86_NOTIFY_VMEXIT globally based solely on CPU > hardware support, userspace can enable it for a TDX VM. If the underlying > TDX module (e.g., v1.0) does not support Notify VM Exiting, this write > will fail. > > When the TDX module write operation fails, the macro backing > td_vmcs_setbit32() calls tdh_vp_wr_failed(), which triggers a KVM_BUG_ON(): > > arch/x86/kvm/vmx/tdx.c:tdh_vp_wr_failed() { > KVM_BUG_ON(1, tdx->vcpu.kvm); > pr_err("TDH_VP_WR[%s.0x%x]%s0x%llx failed: 0x%llx\n", ...); > } > > Should we verify that the loaded TDX module actually supports the Notify VM > Exit feature before attempting to program these TD VMCS fields? Every TDX module should support this feature and SEAMCALLs to set the TD VMCS will not fail as long as the hardware supports the feature. The hardware support is checked by KVM and reflected in kvm_caps.has_notify_vmexit. If any TDX module doesn't allow to program the TD VMCS fields of Notify VM exit, it's just a bug of TDX module. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] KVM: TDX: Enable Notify VM exit 2026-08-05 3:12 ` [PATCH 1/2] KVM: TDX: Enable Notify VM exit Xiaoyao Li 2026-08-05 3:38 ` sashiko-bot @ 2026-08-06 13:33 ` Nikolay Borisov 2026-08-06 13:50 ` Sean Christopherson 2026-08-07 1:06 ` Xiaoyao Li 1 sibling, 2 replies; 15+ messages in thread From: Nikolay Borisov @ 2026-08-06 13:33 UTC (permalink / raw) To: Xiaoyao Li, Sean Christopherson, Paolo Bonzini Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe, kvm, linux-kernel On 8/5/26 06:12, Xiaoyao Li wrote: > Enable Notify VM exit functionality for TDX guests. > > Notify VM exit is an existing feature supported by KVM. Userspace can > enable Notify VM exit through KVM_CAP_X86_NOTIFY_VMEXIT when it's > reported as supported. However, KVM reports the support of this CAP just > based on the hardware capability but doesn't differentiate between VMX > and TDX. This leads to the issue that userspace can enable this cap for > TDX guests without getting an error, but the feature is not actually > enabled because KVM doesn't call the TDX module API to program the > relevant TD VMCS fields. > > Enable Notify VM exit for TDX guests by: > > - Invoking TDX module API calls to set NOTIFY_VM_EXITING and Notify > Window in TD VMCS. It's done in tdx_vcpu_init() where other TD VMCS > bits are set. Since TDX vCPU cannot be reset, it only needs to be > configured once when initializing the TDX vCPU. > > - Adding corresponding exit handler for TDX Notify VM Exit. nit: That feature is completely misnamed in the kernel. It should be instruction timeout (as is in the SDM). Please reword the changelog to refer to the name of the features as they are in the SDM. I.e if you search for NOTIFY_VMEXIT or NOTIFY_WINDOW absolutely nothing can be found in the SDM. The changelog should ideally mention both - SDM's nomenclature and linux's nomenclature. > > Note, Notify VM exit can happen when executing the IRET instruction. If > the IRET unblocks the NMI blocking state, bit 12 of the exit qualification > is set. In this case, the VMM needs to restore the "blocked by NMI" state > when it decides to re-enter the guest. For TDX, KVM cannot manage the > GUEST_INTERRUPTIBILITY_INFO and it's TDX module's responsibility to > handle it. > > Fixes: 161d34609f9b ("KVM: TDX: Make TDX VM type supported") > Cc: stable@vger.kernel.org > Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> > --- > The enabling of Notify VM exit was missed in the initial upstreaming of > TDX base support. We suppose the patch needs to be backported to > stable kernels. So, the cc stable is added. > --- > arch/x86/kvm/vmx/tdx.c | 10 ++++++++++ > arch/x86/kvm/vmx/vmx.c | 23 +++++++++++++++-------- > arch/x86/kvm/vmx/vmx.h | 1 + > 3 files changed, 26 insertions(+), 8 deletions(-) > > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c > index 545b03d9d10b..cdc0d24657ac 100644 > --- a/arch/x86/kvm/vmx/tdx.c > +++ b/arch/x86/kvm/vmx/tdx.c > @@ -2129,6 +2129,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) > * - If it's not an MSMI, no need to do anything here. > */ > return 1; > + case EXIT_REASON_NOTIFY: > + /* NMI blocking state is handled by TDX module */ > + return __handle_notify(vcpu, false); I'd rather there be a private handle_tdx_notify function in tdx.c than exposing __handle_notify and introducing the boolean. This is needed because the TDX module handles the NMI unblocking, so let's keep the implementation specific to tdx. <snip> ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] KVM: TDX: Enable Notify VM exit 2026-08-06 13:33 ` Nikolay Borisov @ 2026-08-06 13:50 ` Sean Christopherson 2026-08-07 0:27 ` Edgecombe, Rick P 2026-08-07 1:06 ` Xiaoyao Li 1 sibling, 1 reply; 15+ messages in thread From: Sean Christopherson @ 2026-08-06 13:50 UTC (permalink / raw) To: Nikolay Borisov Cc: Xiaoyao Li, Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe, kvm, linux-kernel, Chang S. Bae +Chang On Thu, Aug 06, 2026, Nikolay Borisov wrote: > On 8/5/26 06:12, Xiaoyao Li wrote: > > Enable Notify VM exit functionality for TDX guests. > > > > Notify VM exit is an existing feature supported by KVM. Userspace can > > enable Notify VM exit through KVM_CAP_X86_NOTIFY_VMEXIT when it's > > reported as supported. However, KVM reports the support of this CAP just > > based on the hardware capability but doesn't differentiate between VMX > > and TDX. This leads to the issue that userspace can enable this cap for > > TDX guests without getting an error, but the feature is not actually > > enabled because KVM doesn't call the TDX module API to program the > > relevant TD VMCS fields. > > > > Enable Notify VM exit for TDX guests by: > > > > - Invoking TDX module API calls to set NOTIFY_VM_EXITING and Notify > > Window in TD VMCS. It's done in tdx_vcpu_init() where other TD VMCS > > bits are set. Since TDX vCPU cannot be reset, it only needs to be > > configured once when initializing the TDX vCPU. > > > > - Adding corresponding exit handler for TDX Notify VM Exit. > > > nit: That feature is completely misnamed in the kernel. Well that's bloody annoying. The feature was called "NOTIFY VM EXIT" in the December 2022 version of the ISE, but indeed is called Instruction Timeout in the March 2023 versio of the SDM. Intel isn't exactly building a stellar track record with ISE publications... Chang, please forward this to the right people as well. Changing the name of a feature isn't the end of the world, but things like this add friction and make it quite clear that ISEs are very much "pre-production" drafts. Which is totally fine, and there is most definitely value in publishing early drafts of features, but it means I'm going to be very hesitant to merge features in advance of them being formally defined in the SDM. > It should be instruction timeout (as is in the SDM). Please reword the > changelog to refer to the name of the features as they are in the SDM. I.e if > you search for NOTIFY_VMEXIT or NOTIFY_WINDOW absolutely nothing can be found > in the SDM. The changelog should ideally mention both - SDM's nomenclature > and linux's nomenclature. No, let's change Linux's nomenclature before merging this, "Notify" was always vague and confusing. It's unfortunate that we let that bleed into uAPI headers, but we can simply #define aliases (or just force userspace to update as well, if they use kernel headers directly). ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] KVM: TDX: Enable Notify VM exit 2026-08-06 13:50 ` Sean Christopherson @ 2026-08-07 0:27 ` Edgecombe, Rick P [not found] ` <anUngktlwsNI6oUM@google.com> 0 siblings, 1 reply; 15+ messages in thread From: Edgecombe, Rick P @ 2026-08-07 0:27 UTC (permalink / raw) To: nik.borisov@suse.com, seanjc@google.com Cc: linux-kernel@vger.kernel.org, bp@alien8.de, x86@kernel.org, kas@kernel.org, Li, Xiaoyao, hpa@zytor.com, mingo@redhat.com, dave.hansen@linux.intel.com, tglx@kernel.org, pbonzini@redhat.com, Bae, Chang Seok, kvm@vger.kernel.org On Thu, 2026-08-06 at 06:50 -0700, Sean Christopherson wrote: > > It should be instruction timeout (as is in the SDM). Please reword the > > changelog to refer to the name of the features as they are in the SDM. I.e > > if you search for NOTIFY_VMEXIT or NOTIFY_WINDOW absolutely nothing can be > > found in the SDM. The changelog should ideally mention both - SDM's > > nomenclature and linux's nomenclature. > > No, let's change Linux's nomenclature before merging this, "Notify" was always > vague and confusing. It's unfortunate that we let that bleed into uAPI > headers, but we can simply #define aliases (or just force userspace to update > as well, if they use kernel headers directly). Hmm, ok. We were trying to go with a minimal backport friendly fix. Xiaoyao, if we are going to carve it up, I guess we might as well do the consolidation of the exit handlers too on this version. (a cleanup patch that got left off of this). ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <anUngktlwsNI6oUM@google.com>]
* Re: [PATCH 1/2] KVM: TDX: Enable Notify VM exit [not found] ` <anUngktlwsNI6oUM@google.com> @ 2026-08-07 1:07 ` Xiaoyao Li 2026-08-07 6:46 ` Nikolay Borisov 1 sibling, 0 replies; 15+ messages in thread From: Xiaoyao Li @ 2026-08-07 1:07 UTC (permalink / raw) To: Sean Christopherson, Rick P Edgecombe Cc: nik.borisov@suse.com, linux-kernel@vger.kernel.org, bp@alien8.de, x86@kernel.org, kas@kernel.org, hpa@zytor.com, mingo@redhat.com, dave.hansen@linux.intel.com, tglx@kernel.org, pbonzini@redhat.com, Chang Seok Bae, kvm@vger.kernel.org On 8/7/2026 8:32 AM, Sean Christopherson wrote: > On Fri, Aug 07, 2026, Rick P Edgecombe wrote: >> On Thu, 2026-08-06 at 06:50 -0700, Sean Christopherson wrote: >>>> It should be instruction timeout (as is in the SDM). Please reword the >>>> changelog to refer to the name of the features as they are in the SDM. I.e >>>> if you search for NOTIFY_VMEXIT or NOTIFY_WINDOW absolutely nothing can be >>>> found in the SDM. The changelog should ideally mention both - SDM's >>>> nomenclature and linux's nomenclature. >>> >>> No, let's change Linux's nomenclature before merging this, "Notify" was always >>> vague and confusing. It's unfortunate that we let that bleed into uAPI >>> headers, but we can simply #define aliases (or just force userspace to update >>> as well, if they use kernel headers directly). >> >> Hmm, ok. We were trying to go with a minimal backport friendly fix. >> >> Xiaoyao, if we are going to carve it up, I guess we might as well do the >> consolidation of the exit handlers too on this version. (a cleanup patch that >> got left off of this). > > Oh, I missed that this was tagged for stable@. Do the mass rename on top. To > address Nikolay's concerns, I think a brief blurb at the end calling out that > KVM currently uses old terminology would suffice. E.g. > > Note, KVM uses "pre-production" terminology for the feature formally called > Notify VM-Exit. All public versions of the SDM refer to the feature as > Instruction Timeout. This will be remedied in the near future, for now, > use KVM's terminology for consistency. Get it. Thanks for writing the blurb! I'll add it in the v2. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] KVM: TDX: Enable Notify VM exit [not found] ` <anUngktlwsNI6oUM@google.com> 2026-08-07 1:07 ` Xiaoyao Li @ 2026-08-07 6:46 ` Nikolay Borisov 1 sibling, 0 replies; 15+ messages in thread From: Nikolay Borisov @ 2026-08-07 6:46 UTC (permalink / raw) To: Sean Christopherson, Rick P Edgecombe Cc: linux-kernel@vger.kernel.org, bp@alien8.de, x86@kernel.org, kas@kernel.org, Xiaoyao Li, hpa@zytor.com, mingo@redhat.com, dave.hansen@linux.intel.com, tglx@kernel.org, pbonzini@redhat.com, Chang Seok Bae, kvm@vger.kernel.org On 8/7/26 03:32, Sean Christopherson wrote: > On Fri, Aug 07, 2026, Rick P Edgecombe wrote: >> On Thu, 2026-08-06 at 06:50 -0700, Sean Christopherson wrote: >>>> It should be instruction timeout (as is in the SDM). Please reword the >>>> changelog to refer to the name of the features as they are in the SDM. I.e >>>> if you search for NOTIFY_VMEXIT or NOTIFY_WINDOW absolutely nothing can be >>>> found in the SDM. The changelog should ideally mention both - SDM's >>>> nomenclature and linux's nomenclature. >>> >>> No, let's change Linux's nomenclature before merging this, "Notify" was always >>> vague and confusing. It's unfortunate that we let that bleed into uAPI >>> headers, but we can simply #define aliases (or just force userspace to update >>> as well, if they use kernel headers directly). >> >> Hmm, ok. We were trying to go with a minimal backport friendly fix. >> >> Xiaoyao, if we are going to carve it up, I guess we might as well do the >> consolidation of the exit handlers too on this version. (a cleanup patch that >> got left off of this). > > Oh, I missed that this was tagged for stable@. Do the mass rename on top. To > address Nikolay's concerns, I think a brief blurb at the end calling out that > KVM currently uses old terminology would suffice. E.g. > > Note, KVM uses "pre-production" terminology for the feature formally called > Notify VM-Exit. All public versions of the SDM refer to the feature as > Instruction Timeout. This will be remedied in the near future, for now, > use KVM's terminology for consistency. That's better, at least it gives pointers what to look for in the SDM. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] KVM: TDX: Enable Notify VM exit 2026-08-06 13:33 ` Nikolay Borisov 2026-08-06 13:50 ` Sean Christopherson @ 2026-08-07 1:06 ` Xiaoyao Li 1 sibling, 0 replies; 15+ messages in thread From: Xiaoyao Li @ 2026-08-07 1:06 UTC (permalink / raw) To: Nikolay Borisov, Sean Christopherson, Paolo Bonzini Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe, kvm, linux-kernel On 8/6/2026 9:33 PM, Nikolay Borisov wrote: >> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c >> index 545b03d9d10b..cdc0d24657ac 100644 >> --- a/arch/x86/kvm/vmx/tdx.c >> +++ b/arch/x86/kvm/vmx/tdx.c >> @@ -2129,6 +2129,9 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, >> fastpath_t fastpath) >> * - If it's not an MSMI, no need to do anything here. >> */ >> return 1; >> + case EXIT_REASON_NOTIFY: >> + /* NMI blocking state is handled by TDX module */ >> + return __handle_notify(vcpu, false); > > I'd rather there be a private handle_tdx_notify function in tdx.c than > exposing __handle_notify and introducing the boolean. This is needed > because the TDX module handles the NMI unblocking, so let's keep the > implementation specific to tdx. The initial version just implemented a separate handler for TDX. It had the exact same code as VMX's handle_notify() except the "NMI blocking handling". So to eliminate the code duplication, I changed to current code. Sean, please let me if you have a preference. Otherwise, I'll follow Nikolay's preference in a v2. ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/2] KVM: TDX: Enable Bus Lock VM exit 2026-08-05 3:12 [PATCH 0/2] KVM: TDX: Enable VM-DoS Prevention Features for TDX Xiaoyao Li 2026-08-05 3:12 ` [PATCH 1/2] KVM: TDX: Enable Notify VM exit Xiaoyao Li @ 2026-08-05 3:12 ` Xiaoyao Li 2026-08-05 3:46 ` sashiko-bot 1 sibling, 1 reply; 15+ messages in thread From: Xiaoyao Li @ 2026-08-05 3:12 UTC (permalink / raw) To: Sean Christopherson, Paolo Bonzini Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe, kvm, linux-kernel, xiaoyao.li Enable Bus Lock VM exit functionality for TDX guests. Userspace can enable KVM_BUS_LOCK_DETECTION_EXIT for TDX guests without getting an error, but the feature is not actually enabled because KVM does not yet program the TDX execution control or handle the resulting exit. Enable Bus Lock VM exit for TDX guests by programming the BUS_LOCK_DETECTION control in the TD VMCS and by adding the exit handler. Fixes: 161d34609f9b ("KVM: TDX: Make TDX VM type supported") Cc: stable@vger.kernel.org Originally-by: Chenyi Qiang <chenyi.qiang@intel.com> Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> --- The enabling of Bus Lock exit was missed in the initial upstreaming of TDX base support. We suppose the patch needs to be backported to stable kernels. So, the cc stable is added. This patch makes the exit handlers for VMX and TDX look similar, we can actually consolidate them. However, considering this series needs to be backported to stable kernel while the consolidation patch doesn't need to, we plan to send the consolidation patch separately after this series settles. --- arch/x86/kvm/vmx/tdx.c | 23 ++++++++++++++++++++++- arch/x86/kvm/vmx/vmx.c | 2 +- arch/x86/kvm/vmx/vmx.h | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index cdc0d24657ac..c037e9cb5bdf 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -2031,7 +2031,7 @@ int tdx_complete_emulated_msr(struct kvm_vcpu *vcpu, int err) } -int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) +static int __tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) { struct vcpu_tdx *tdx = to_tdx(vcpu); u64 vp_enter_ret = tdx->vp_enter_ret; @@ -2132,6 +2132,8 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) case EXIT_REASON_NOTIFY: /* NMI blocking state is handled by TDX module */ return __handle_notify(vcpu, false); + case EXIT_REASON_BUS_LOCK: + return handle_bus_lock_vmexit(vcpu); default: break; } @@ -2141,6 +2143,21 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) return 0; } +int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) +{ + int ret = __tdx_handle_exit(vcpu, fastpath); + + /* Exit to user space when bus lock was detected */ + if (vmx_get_exit_reason(vcpu).bus_lock_detected) { + if (ret > 0) + vcpu->run->exit_reason = KVM_EXIT_X86_BUS_LOCK; + + vcpu->run->flags |= KVM_RUN_X86_BUS_LOCK; + return 0; + } + return ret; +} + void tdx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason, u64 *info1, u64 *info2, u32 *intr_info, u32 *error_code) { @@ -3167,6 +3184,10 @@ static int tdx_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *cmd) vcpu->kvm->arch.notify_window); } + if (vcpu->kvm->arch.bus_lock_detection_enabled) + td_vmcs_setbit32(tdx, SECONDARY_VM_EXEC_CONTROL, + SECONDARY_EXEC_BUS_LOCK_DETECTION); + tdx->state = VCPU_TD_STATE_INITIALIZED; return 0; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 9c5a7e5c907e..c590eb1e06ee 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6255,7 +6255,7 @@ static int handle_encls(struct kvm_vcpu *vcpu) } #endif /* CONFIG_X86_SGX_KVM */ -static int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu) +int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu) { /* * Hardware may or may not set the BUS_LOCK_DETECTED flag on BUS_LOCK diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 79431b5e9bcb..f2c80e4dc5ac 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -379,6 +379,7 @@ bool __vmx_vcpu_run(struct vcpu_vmx *vmx, unsigned int flags); void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu); void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type, bool set); +int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu); int __handle_notify(struct kvm_vcpu *vcpu, bool handle_nmi_unblock); static inline void vmx_disable_intercept_for_msr(struct kvm_vcpu *vcpu, -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] KVM: TDX: Enable Bus Lock VM exit 2026-08-05 3:12 ` [PATCH 2/2] KVM: TDX: Enable Bus Lock " Xiaoyao Li @ 2026-08-05 3:46 ` sashiko-bot 2026-08-05 7:53 ` Xiaoyao Li 0 siblings, 1 reply; 15+ messages in thread From: sashiko-bot @ 2026-08-05 3:46 UTC (permalink / raw) To: Xiaoyao Li; +Cc: kvm Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [High] Unmasked bus_lock_detected bit breaks TDX exit handling and guest execution. - [High] Unvalidated VMCS write for BUS_LOCK_DETECTION allows userspace to trigger host WARN and crash VM. - [High] tdx_handle_exit() silently masks negative error codes, returning undefined state to userspace. -- --- Patch [2]: [PATCH 2/2] KVM: TDX: Enable Bus Lock VM exit --- commit a95d478711dc8c7f94ecddd768bf45d636ab7635 Author: Xiaoyao Li <xiaoyao.li@intel.com> KVM: TDX: Enable Bus Lock VM exit Enable Bus Lock VM exit functionality for TDX guests by programming the BUS_LOCK_DETECTION control in the TD VMCS and by adding the exit handler. > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c > index cdc0d24657acb..c037e9cb5bdfc 100644 > --- a/arch/x86/kvm/vmx/tdx.c > +++ b/arch/x86/kvm/vmx/tdx.c > @@ -2031,7 +2031,7 @@ int tdx_complete_emulated_msr(struct kvm_vcpu *vcpu, int err) > } > > > -int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) > +static int __tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) > { > struct vcpu_tdx *tdx = to_tdx(vcpu); > u64 vp_enter_ret = tdx->vp_enter_ret; [Severity: High] Does this code handle the bus_lock_detected bit (bit 26) being set in vp_enter_ret or the raw 32-bit exit reason? If userspace triggers a bus lock concurrently with an exit, the hardware can set bit 26. Will strict equality checks on vp_enter_ret (such as checking for EXIT_REASON_EPT_MISCONFIG later in this function) fail because the bit is unmasked? This also appears to affect tdx_to_vmx_exit_reason(), where comparing the raw exit reason directly against 16-bit constants like EXIT_REASON_TDCALL will fail to match if the bus lock bit is set, leading to incorrect emulation. [ ... ] > @@ -2141,6 +2143,21 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) > return 0; > } > > +int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) > +{ > + int ret = __tdx_handle_exit(vcpu, fastpath); > + > + /* Exit to user space when bus lock was detected */ > + if (vmx_get_exit_reason(vcpu).bus_lock_detected) { > + if (ret > 0) > + vcpu->run->exit_reason = KVM_EXIT_X86_BUS_LOCK; > + > + vcpu->run->flags |= KVM_RUN_X86_BUS_LOCK; > + return 0; [Severity: High] Does this code silently drop negative error codes? If __tdx_handle_exit() returns a negative error code (like -EIO or -EFAULT) while bus_lock_detected is true, it skips setting vcpu->run->exit_reason but still returns 0. Could this cause KVM to return success to userspace with an uninitialized or stale exit_reason instead of propagating the error? > + } > + return ret; > +} [ ... ] > @@ -3167,6 +3184,10 @@ static int tdx_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *cmd) > vcpu->kvm->arch.notify_window); > } > > + if (vcpu->kvm->arch.bus_lock_detection_enabled) > + td_vmcs_setbit32(tdx, SECONDARY_VM_EXEC_CONTROL, > + SECONDARY_EXEC_BUS_LOCK_DETECTION); [Severity: High] Is it safe to write this execution control to the TD VMCS without verifying if the TDX module supports it? If a host userspace process enables KVM_CAP_X86_BUS_LOCK_EXIT but the TDX module restricts this capability, could td_vmcs_setbit32() fail on TDH.VP.WR, triggering the KVM_BUG_ON() macro and destroying the VM? > + > tdx->state = VCPU_TD_STATE_INITIALIZED; > > return 0; -- Sashiko AI review · https://sashiko.dev/#/patchset/20260805031257.1844914-1-xiaoyao.li@intel.com?part=2 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] KVM: TDX: Enable Bus Lock VM exit 2026-08-05 3:46 ` sashiko-bot @ 2026-08-05 7:53 ` Xiaoyao Li 2026-08-05 14:56 ` Sean Christopherson 0 siblings, 1 reply; 15+ messages in thread From: Xiaoyao Li @ 2026-08-05 7:53 UTC (permalink / raw) To: sashiko-reviews; +Cc: kvm On 8/5/2026 11:46 AM, sashiko-bot@kernel.org wrote: >> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c >> index cdc0d24657acb..c037e9cb5bdfc 100644 >> --- a/arch/x86/kvm/vmx/tdx.c >> +++ b/arch/x86/kvm/vmx/tdx.c >> @@ -2031,7 +2031,7 @@ int tdx_complete_emulated_msr(struct kvm_vcpu *vcpu, int err) >> } >> >> >> -int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) >> +static int __tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) >> { >> struct vcpu_tdx *tdx = to_tdx(vcpu); >> u64 vp_enter_ret = tdx->vp_enter_ret; > > [Severity: High] > Does this code handle the bus_lock_detected bit (bit 26) being set in > vp_enter_ret or the raw 32-bit exit reason? > > If userspace triggers a bus lock concurrently with an exit, the hardware can > set bit 26. Will strict equality checks on vp_enter_ret (such as checking for > EXIT_REASON_EPT_MISCONFIG later in this function) fail because the bit is > unmasked? Sashiko is correct. I think the handling like (vp_enter_ret == EXIT_REASON_EPT_MISCONFIG) is not safe, we need to first mask vp_enter_ret. Will add a separate patch for it. > This also appears to affect tdx_to_vmx_exit_reason(), where comparing the raw > exit reason directly against 16-bit constants like EXIT_REASON_TDCALL will > fail to match if the bus lock bit is set, leading to incorrect emulation. This is valid. We need to adjust tdx_to_vmx_exit_reason(). However, there is a more important problem. Since Bus Lock VM exit makes bit 26 possible in EXIT REASON, the trick of "return -1" in tdx_to_vmx_exit_reason() will introduce false-positive in the following check of if(vmx_get_exit_reason(vcpu).bus_lock_detected) added by this patch. how about something like below: ---8<--- diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index c037e9cb5bdf..54598dcda938 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -927,7 +927,7 @@ static __always_inline u32 tdcall_to_vmx_exit_reason(struct kvm_vcpu *vcpu) static __always_inline u32 tdx_to_vmx_exit_reason(struct kvm_vcpu *vcpu) { struct vcpu_tdx *tdx = to_tdx(vcpu); - u32 exit_reason; + union vmx_exit_reason exit_reason; switch (tdx->vp_enter_ret & TDX_SEAMCALL_STATUS_MASK) { case TDX_SUCCESS: @@ -937,28 +937,29 @@ static __always_inline u32 tdx_to_vmx_exit_reason(struct kvm_vcpu *vcpu) case TDX_NON_RECOVERABLE_TD_WRONG_APIC_MODE: break; default: - return -1u; + return (u16)-1u; } - exit_reason = tdx->vp_enter_ret; + exit_reason.full = tdx->vp_enter_ret; - switch (exit_reason) { + switch (exit_reason.basic) { case EXIT_REASON_TDCALL: if (tdvmcall_exit_type(vcpu)) - return EXIT_REASON_VMCALL; + exit_reason.basic = EXIT_REASON_VMCALL; - return tdcall_to_vmx_exit_reason(vcpu); + exit_reason.basic = tdcall_to_vmx_exit_reason(vcpu); + break; case EXIT_REASON_EPT_MISCONFIG: /* * Defer KVM_BUG_ON() until tdx_handle_exit() because this is in * non-instrumentable code with interrupts disabled. */ - return -1u; + return (u16)-1u; default: break; } - return exit_reason; + return exit_reason.full; } static noinstr void tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu) > [ ... ] > >> @@ -2141,6 +2143,21 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) >> return 0; >> } >> >> +int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) >> +{ >> + int ret = __tdx_handle_exit(vcpu, fastpath); >> + >> + /* Exit to user space when bus lock was detected */ >> + if (vmx_get_exit_reason(vcpu).bus_lock_detected) { >> + if (ret > 0) >> + vcpu->run->exit_reason = KVM_EXIT_X86_BUS_LOCK; >> + >> + vcpu->run->flags |= KVM_RUN_X86_BUS_LOCK; >> + return 0; > > [Severity: High] > Does this code silently drop negative error codes? > > If __tdx_handle_exit() returns a negative error code (like -EIO or -EFAULT) > while bus_lock_detected is true, it skips setting vcpu->run->exit_reason but > still returns 0. > > Could this cause KVM to return success to userspace with an uninitialized or > stale exit_reason instead of propagating the error? It won't return uninitialized or stale exit_reason. But changing the negative error codes to 0 is a wrong behavior. I will fix it. The VMX handler looks to have the issue. I'll cook a separate patch to fix it. >> + } >> + return ret; >> +} > > [ ... ] > >> @@ -3167,6 +3184,10 @@ static int tdx_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *cmd) >> vcpu->kvm->arch.notify_window); >> } >> >> + if (vcpu->kvm->arch.bus_lock_detection_enabled) >> + td_vmcs_setbit32(tdx, SECONDARY_VM_EXEC_CONTROL, >> + SECONDARY_EXEC_BUS_LOCK_DETECTION); > > [Severity: High] > Is it safe to write this execution control to the TD VMCS without verifying if > the TDX module supports it? > > If a host userspace process enables KVM_CAP_X86_BUS_LOCK_EXIT but the TDX > module restricts this capability, could td_vmcs_setbit32() fail on TDH.VP.WR, > triggering the KVM_BUG_ON() macro and destroying the VM? Same for the patch 1. This is not possible, TDX module itself should always support Bus Lock VM exit unless the hardware doesn't support it. But in the case of hardware doesn't it, KVM doesn't set kvm_caps.has_bus_lock_exit thus userspace cannot enable KVM_CAP_X86_BUS_LOCK_EXIT. >> + >> tdx->state = VCPU_TD_STATE_INITIALIZED; >> >> return 0; > ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] KVM: TDX: Enable Bus Lock VM exit 2026-08-05 7:53 ` Xiaoyao Li @ 2026-08-05 14:56 ` Sean Christopherson 2026-08-06 6:10 ` Xiaoyao Li 0 siblings, 1 reply; 15+ messages in thread From: Sean Christopherson @ 2026-08-05 14:56 UTC (permalink / raw) To: Xiaoyao Li; +Cc: sashiko-reviews, kvm On Wed, Aug 05, 2026, Xiaoyao Li wrote: > On 8/5/2026 11:46 AM, sashiko-bot@kernel.org wrote: > > This also appears to affect tdx_to_vmx_exit_reason(), where comparing the raw > > exit reason directly against 16-bit constants like EXIT_REASON_TDCALL will > > fail to match if the bus lock bit is set, leading to incorrect emulation. > > This is valid. We need to adjust tdx_to_vmx_exit_reason(). > > However, there is a more important problem. Since Bus Lock VM exit makes bit > 26 possible in EXIT REASON, the trick of "return -1" in > tdx_to_vmx_exit_reason() will introduce false-positive in the following > check of if(vmx_get_exit_reason(vcpu).bus_lock_detected) added by this > patch. > > how about something like below: Way too subtle. tdx_to_vmx_exit_reason() should return the actual union, not a raw u32, otherwise it's going to be extremely difficult to avoid reintroducing similar bugs. And looking at this all again, we should change the handling of actual EXIT_REASON_EPT_MISCONFIG exits. Stuffing a bogus value into the exit_reason is "fine", but as Sashiko points out, it's extremely brittle. Rather than stuff the exit reason, we should stuff the status to signal TDX_SW_ERROR. And to do that without introducing more fragility, we should flag the raw vp_enter_ret as "unsafe", and explicitly track vp_enter_status. I.e. separate the status from the exit_reason immediately after VP.ENTER, instead of mixing and matching the two concepts. The fastpath "handler" is also all kinds of messed up. KVM fails to trace_kvm_exit() EPT misconfigs and software errors; even though the exit reason is undefined, it should still be captured in the trace, otherwise it's a huge blindspot. And AFAICT, OPERAND_BUSY should be mutually exclusive with actual VM-Entry failures, so manually checking for VM-Entry failure is completely unnecessary, just handle OPERAND_BUSY. If TDX ever gains fastpath handlers, then we can add a true fastpath handler at that time. But OPERAND_BUSY should be a "never do the fastpath", because AIUI, VM-Enter wasn't attempted, i.e. there's nothing to handle. Compile tested only, and it should be chunked over several patches, but this? diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index 299c051d648e..19e8e3703ce1 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -921,12 +921,12 @@ static __always_inline u32 tdcall_to_vmx_exit_reason(struct kvm_vcpu *vcpu) return EXIT_REASON_TDCALL; } -static __always_inline u32 tdx_to_vmx_exit_reason(struct kvm_vcpu *vcpu) +static __always_inline union vmx_exit_reason tdx_to_vmx_exit_reason(struct kvm_vcpu *vcpu, + u64 vp_enter_ret) { - struct vcpu_tdx *tdx = to_tdx(vcpu); - u32 exit_reason; + union vmx_exit_reason exit_reason; - switch (tdx->vp_enter_ret & TDX_SEAMCALL_STATUS_MASK) { + switch (vp_enter_ret & TDX_SEAMCALL_STATUS_MASK) { case TDX_SUCCESS: case TDX_NON_RECOVERABLE_VCPU: case TDX_NON_RECOVERABLE_TD: @@ -934,40 +934,38 @@ static __always_inline u32 tdx_to_vmx_exit_reason(struct kvm_vcpu *vcpu) case TDX_NON_RECOVERABLE_TD_WRONG_APIC_MODE: break; default: - return -1u; + /* + * Synthesize an invalid bogus Exit Reason, as the TDX-Module + * never attempted to run the vCPU, i.e. the Exit Reason is + * undefined, but this is NOT a failed VM-Enter. + */ + return (union vmx_exit_reason) { + .basic = -1, + }; } - exit_reason = tdx->vp_enter_ret; + exit_reason.full = (u32)vp_enter_ret; - switch (exit_reason) { - case EXIT_REASON_TDCALL: + if (exit_reason.basic == EXIT_REASON_TDCALL) { if (tdvmcall_exit_type(vcpu)) - return EXIT_REASON_VMCALL; - - return tdcall_to_vmx_exit_reason(vcpu); - case EXIT_REASON_EPT_MISCONFIG: - /* - * Defer KVM_BUG_ON() until tdx_handle_exit() because this is in - * non-instrumentable code with interrupts disabled. - */ - return -1u; - default: - break; + exit_reason.basic = EXIT_REASON_VMCALL; + else + exit_reason.basic = tdcall_to_vmx_exit_reason(vcpu); } - return exit_reason; } -static noinstr void tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu) +static noinstr u64 tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu) { struct vcpu_tdx *tdx = to_tdx(vcpu); struct vcpu_vt *vt = to_vt(vcpu); + u64 ret; guest_state_enter_irqoff(); - tdx->vp_enter_ret = tdh_vp_enter(&tdx->vp, &tdx->vp_enter_args); + ret = tdh_vp_enter(&tdx->vp, &tdx->vp_enter_args); - vt->exit_reason.full = tdx_to_vmx_exit_reason(vcpu); + vt->exit_reason = tdx_to_vmx_exit_reason(vcpu, ret); vt->exit_qualification = tdx->vp_enter_args.rcx; tdx->ext_exit_qualification = tdx->vp_enter_args.rdx; @@ -977,33 +975,8 @@ static noinstr void tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu) vmx_handle_nmi(vcpu); guest_state_exit_irqoff(); -} -static bool tdx_failed_vmentry(struct kvm_vcpu *vcpu) -{ - return vmx_get_exit_reason(vcpu).failed_vmentry && - vmx_get_exit_reason(vcpu).full != -1u; -} - -static fastpath_t tdx_exit_handlers_fastpath(struct kvm_vcpu *vcpu) -{ - u64 vp_enter_ret = to_tdx(vcpu)->vp_enter_ret; - - /* - * TDX_OPERAND_BUSY could be returned for SEPT due to 0-step mitigation - * or for TD EPOCH due to contention with TDH.MEM.TRACK on TDH.VP.ENTER. - * - * When KVM requests KVM_REQ_OUTSIDE_GUEST_MODE, which has both - * KVM_REQUEST_WAIT and KVM_REQUEST_NO_ACTION set, it requires target - * vCPUs leaving fastpath so that interrupt can be enabled to ensure the - * IPIs can be delivered. Return EXIT_FASTPATH_EXIT_HANDLED instead of - * EXIT_FASTPATH_REENTER_GUEST to exit fastpath, otherwise, the - * requester may be blocked endlessly. - */ - if (unlikely(tdx_operand_busy(vp_enter_ret))) - return EXIT_FASTPATH_EXIT_HANDLED; - - return EXIT_FASTPATH_NONE; + return ret; } #define TDX_REGS_AVAIL_SET (BIT(VCPU_REG_EXIT_INFO_1) | \ @@ -1053,8 +1026,8 @@ static void tdx_load_host_xsave_state(struct kvm_vcpu *vcpu) fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) { - struct vcpu_tdx *tdx = to_tdx(vcpu); struct vcpu_vt *vt = to_vt(vcpu); + u64 vp_enter_ret; /* * WARN if KVM wants to force an immediate exit, as the TDX module does @@ -1084,7 +1057,7 @@ fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) kvm_wait_lapic_expire(vcpu); } - tdx_vcpu_enter_exit(vcpu); + vp_enter_ret = tdx_vcpu_enter_exit(vcpu); if (vcpu->arch.host_debugctl & ~TDX_DEBUGCTL_PRESERVED) update_debugctlmsr(vcpu->arch.host_debugctl); @@ -1093,18 +1066,23 @@ fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) kvm_clear_available_registers(vcpu, ~TDX_REGS_AVAIL_SET); - if (unlikely(tdx->vp_enter_ret == EXIT_REASON_EPT_MISCONFIG)) - return EXIT_FASTPATH_NONE; - - if (unlikely((tdx->vp_enter_ret & TDX_SW_ERROR) == TDX_SW_ERROR)) - return EXIT_FASTPATH_NONE; - trace_kvm_exit(vcpu, KVM_ISA_VMX); - if (unlikely(tdx_failed_vmentry(vcpu))) - return EXIT_FASTPATH_NONE; + /* + * TDX_OPERAND_BUSY could be returned for SEPT due to 0-step mitigation + * or for TD EPOCH due to contention with TDH.MEM.TRACK on TDH.VP.ENTER. + * + * When KVM requests KVM_REQ_OUTSIDE_GUEST_MODE, which has both + * KVM_REQUEST_WAIT and KVM_REQUEST_NO_ACTION set, it requires target + * vCPUs leaving fastpath so that interrupt can be enabled to ensure the + * IPIs can be delivered. Return EXIT_FASTPATH_EXIT_HANDLED instead of + * EXIT_FASTPATH_REENTER_GUEST to exit fastpath, otherwise, the + * requester may be blocked endlessly. + */ + if (unlikely(tdx_operand_busy(vp_enter_ret))) + return EXIT_FASTPATH_EXIT_HANDLED; - return tdx_exit_handlers_fastpath(vcpu); + return EXIT_FASTPATH_NONE; } void tdx_inject_nmi(struct kvm_vcpu *vcpu) @@ -1300,7 +1278,7 @@ static int tdx_report_fatal_error(struct kvm_vcpu *vcpu) vcpu->run->system_event.ndata = 16; /* Dump 16 general-purpose registers to userspace in ascending order. */ - regs[index++] = tdx->vp_enter_ret; + regs[index++] = tdx->vp_enter_ret__unsafe; regs[index++] = tdx->vp_enter_args.rcx; regs[index++] = tdx->vp_enter_args.rdx; regs[index++] = tdx->vp_enter_args.rbx; @@ -2030,48 +2008,44 @@ int tdx_complete_emulated_msr(struct kvm_vcpu *vcpu, int err) static int __tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) { - struct vcpu_tdx *tdx = to_tdx(vcpu); - u64 vp_enter_ret = tdx->vp_enter_ret; union vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu); + struct vcpu_tdx *tdx = to_tdx(vcpu); + u64 status = tdx->vp_enter_ret__unsafe & TDX_SEAMCALL_STATUS_MASK; if (fastpath != EXIT_FASTPATH_NONE) return 1; - if (unlikely(vp_enter_ret == EXIT_REASON_EPT_MISCONFIG)) { - KVM_BUG_ON(1, vcpu->kvm); + if (KVM_BUG_ON(exit_reason.basic == EXIT_REASON_EPT_MISCONFIG, vcpu->kvm)) return -EIO; - } /* * Handle TDX SW errors, including TDX_SEAMCALL_UD, TDX_SEAMCALL_GP and * TDX_SEAMCALL_VMFAILINVALID. */ - if (unlikely((vp_enter_ret & TDX_SW_ERROR) == TDX_SW_ERROR)) { + if (unlikely(status == TDX_SW_ERROR)) { KVM_BUG_ON(!virt_rebooting, vcpu->kvm); goto unhandled_exit; } - if (unlikely(tdx_failed_vmentry(vcpu))) { + if (unlikely(exit_reason.failed_vmentry)) { /* * If the guest state is protected, that means off-TD debug is * not enabled, TDX_NON_RECOVERABLE must be set. */ WARN_ON_ONCE(vcpu->arch.guest_state_protected && - !(vp_enter_ret & TDX_NON_RECOVERABLE)); + !(status & TDX_NON_RECOVERABLE)); vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY; vcpu->run->fail_entry.hardware_entry_failure_reason = exit_reason.full; vcpu->run->fail_entry.cpu = vcpu->arch.last_vmentry_cpu; return 0; } - if (unlikely(vp_enter_ret & (TDX_ERROR | TDX_NON_RECOVERABLE)) && - exit_reason.basic != EXIT_REASON_TRIPLE_FAULT) { - kvm_pr_unimpl("TD vp_enter_ret 0x%llx\n", vp_enter_ret); + if (unlikely(status & (TDX_ERROR | TDX_NON_RECOVERABLE)) && + exit_reason.basic != EXIT_REASON_TRIPLE_FAULT) goto unhandled_exit; - } - WARN_ON_ONCE(exit_reason.basic != EXIT_REASON_TRIPLE_FAULT && - (vp_enter_ret & TDX_SEAMCALL_STATUS_MASK) != TDX_SUCCESS); + WARN_ON_ONCE(status != TDX_SUCCESS && + exit_reason.basic != EXIT_REASON_TRIPLE_FAULT); switch (exit_reason.basic) { case EXIT_REASON_TRIPLE_FAULT: @@ -2136,7 +2110,8 @@ static int __tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) } unhandled_exit: - kvm_prepare_unexpected_reason_exit(vcpu, vp_enter_ret); + kvm_pr_unimpl("TD vp_enter_ret 0x%llx\n", tdx->vp_enter_ret__unsafe); + kvm_prepare_unexpected_reason_exit(vcpu, tdx->vp_enter_ret__unsafe); return 0; } diff --git a/arch/x86/kvm/vmx/tdx.h b/arch/x86/kvm/vmx/tdx.h index ac8323a68b16..5564617fc12a 100644 --- a/arch/x86/kvm/vmx/tdx.h +++ b/arch/x86/kvm/vmx/tdx.h @@ -66,7 +66,12 @@ struct vcpu_tdx { struct list_head cpu_list; - u64 vp_enter_ret; + /* + * Discourage direct use of the raw VP.ENTER return value, as there are + * several subtleties that need to be accounted for when working with + * the raw value. + */ + u64 HINT_UNSAFE_IN_KVM(vp_enter_ret); enum vcpu_tdx_state state; ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] KVM: TDX: Enable Bus Lock VM exit 2026-08-05 14:56 ` Sean Christopherson @ 2026-08-06 6:10 ` Xiaoyao Li 0 siblings, 0 replies; 15+ messages in thread From: Xiaoyao Li @ 2026-08-06 6:10 UTC (permalink / raw) To: Sean Christopherson; +Cc: sashiko-reviews, kvm On 8/5/2026 10:56 PM, Sean Christopherson wrote: > On Wed, Aug 05, 2026, Xiaoyao Li wrote: >> On 8/5/2026 11:46 AM, sashiko-bot@kernel.org wrote: >>> This also appears to affect tdx_to_vmx_exit_reason(), where comparing the raw >>> exit reason directly against 16-bit constants like EXIT_REASON_TDCALL will >>> fail to match if the bus lock bit is set, leading to incorrect emulation. >> >> This is valid. We need to adjust tdx_to_vmx_exit_reason(). >> >> However, there is a more important problem. Since Bus Lock VM exit makes bit >> 26 possible in EXIT REASON, the trick of "return -1" in >> tdx_to_vmx_exit_reason() will introduce false-positive in the following >> check of if(vmx_get_exit_reason(vcpu).bus_lock_detected) added by this >> patch. >> >> how about something like below: > > Way too subtle. tdx_to_vmx_exit_reason() should return the actual union, not a > raw u32, otherwise it's going to be extremely difficult to avoid reintroducing > similar bugs. > > And looking at this all again, we should change the handling of actual > EXIT_REASON_EPT_MISCONFIG exits. Stuffing a bogus value into the exit_reason > is "fine", but as Sashiko points out, it's extremely brittle. Rather than > stuff the exit reason, we should stuff the status to signal TDX_SW_ERROR. > > And to do that without introducing more fragility, we should flag the raw > vp_enter_ret as "unsafe", and explicitly track vp_enter_status. I.e. separate > the status from the exit_reason immediately after VP.ENTER, instead of mixing > and matching the two concepts. > > The fastpath "handler" is also all kinds of messed up. KVM fails to trace_kvm_exit() > EPT misconfigs and software errors; even though the exit reason is undefined, it > should still be captured in the trace, otherwise it's a huge blindspot. And AFAICT, > OPERAND_BUSY should be mutually exclusive with actual VM-Entry failures, so manually > checking for VM-Entry failure is completely unnecessary, just handle OPERAND_BUSY. > If TDX ever gains fastpath handlers, then we can add a true fastpath handler at > that time. But OPERAND_BUSY should be a "never do the fastpath", because AIUI, > VM-Enter wasn't attempted, i.e. there's nothing to handle. > > Compile tested only, and it should be chunked over several patches, but this? Basically, it looks good except some nits. I'll try to split into a formal sereis. Please let me know if you want to do if yourself. > @@ -1053,8 +1026,8 @@ static void tdx_load_host_xsave_state(struct kvm_vcpu *vcpu) > > fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) > { > - struct vcpu_tdx *tdx = to_tdx(vcpu); > struct vcpu_vt *vt = to_vt(vcpu); > + u64 vp_enter_ret; > > /* > * WARN if KVM wants to force an immediate exit, as the TDX module does > @@ -1084,7 +1057,7 @@ fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) > kvm_wait_lapic_expire(vcpu); > } > > - tdx_vcpu_enter_exit(vcpu); > + vp_enter_ret = tdx_vcpu_enter_exit(vcpu); We need assign tdx->vp_enter_ret__unsafe somewhere after here. I think we can just drop the local vp_enter_ret and make it tdx->vp_enter_ret__unsafe = tdx_vcpu_enter_exit(vcpu); > > if (vcpu->arch.host_debugctl & ~TDX_DEBUGCTL_PRESERVED) > update_debugctlmsr(vcpu->arch.host_debugctl); <...> > - if (unlikely(vp_enter_ret == EXIT_REASON_EPT_MISCONFIG)) { > - KVM_BUG_ON(1, vcpu->kvm); > + if (KVM_BUG_ON(exit_reason.basic == EXIT_REASON_EPT_MISCONFIG, vcpu->kvm)) We need to check tdx->vp_enter_ret__unsafe instead of exit_reason becase tdcall_to_vmx_exit_reason() translates TDVMCALL(EXIT_REASON_EPT_VIOLATION) from guest to EXIT_REASON_EPT_MISCONFIG <...> > diff --git a/arch/x86/kvm/vmx/tdx.h b/arch/x86/kvm/vmx/tdx.h > index ac8323a68b16..5564617fc12a 100644 > --- a/arch/x86/kvm/vmx/tdx.h > +++ b/arch/x86/kvm/vmx/tdx.h > @@ -66,7 +66,12 @@ struct vcpu_tdx { > > struct list_head cpu_list; > > - u64 vp_enter_ret; > + /* > + * Discourage direct use of the raw VP.ENTER return value, as there are > + * several subtleties that need to be accounted for when working with > + * the raw value. > + */ > + u64 HINT_UNSAFE_IN_KVM(vp_enter_ret); So the purpose is forcing people to think twice when using it because they see "__unsafe"? Maybe it's more for the reviewers and maintainers. > > enum vcpu_tdx_state state; ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-08-07 6:46 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-05 3:12 [PATCH 0/2] KVM: TDX: Enable VM-DoS Prevention Features for TDX Xiaoyao Li
2026-08-05 3:12 ` [PATCH 1/2] KVM: TDX: Enable Notify VM exit Xiaoyao Li
2026-08-05 3:38 ` sashiko-bot
2026-08-05 4:16 ` Xiaoyao Li
2026-08-06 13:33 ` Nikolay Borisov
2026-08-06 13:50 ` Sean Christopherson
2026-08-07 0:27 ` Edgecombe, Rick P
[not found] ` <anUngktlwsNI6oUM@google.com>
2026-08-07 1:07 ` Xiaoyao Li
2026-08-07 6:46 ` Nikolay Borisov
2026-08-07 1:06 ` Xiaoyao Li
2026-08-05 3:12 ` [PATCH 2/2] KVM: TDX: Enable Bus Lock " Xiaoyao Li
2026-08-05 3:46 ` sashiko-bot
2026-08-05 7:53 ` Xiaoyao Li
2026-08-05 14:56 ` Sean Christopherson
2026-08-06 6:10 ` Xiaoyao Li
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox