Re: [PATCH v2 3/3] KVM: TDX: Enable Bus Lock VM exit

From: Edgecombe, Rick P

Date: Mon Aug 10 2026 - 21:19:26 EST


On Mon, 2026-08-10 at 19:22 +0800, Xiaoyao Li wrote:
> 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.

A bit run-on to me. Why not break it up like it's explained in patch 1.

>
> 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.
> Clear the bus_lock_detected bit to avoid being counted multiple times if
> it needs to return early for wait_for_sept_zap case in tdx_vcpu_run().
> Since the wait_for_sept_zap case is expected to be rare, just do the
> clearing of bus_lock_detected unconditionally.
>
> Note, there is no enumeration bit for this feature by TDX module because
> all TDX modules support it, and allow to set the TD VMCS as long as the
> hardware supports the feature.
>
> Fixes: 161d34609f9b ("KVM: TDX: Make TDX VM type supported")
> Cc: stable@xxxxxxxxxxxxxxx
> Originally-by: Chenyi Qiang <chenyi.qiang@xxxxxxxxx>
> Signed-off-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx>
> ---
> Changes in v2:
> - Don't overwrite the negative return value to 0. (Sashiko)
> - Clear the bus_lock_detected bit when it returns early for
> wait_for_sept_zap case.
> - Add a note to clarify the feature is always supported by the TDX
> module, to make Sashiko happy.

Ha! This is probably just being a bit funny. But let's treat AI review as
suggestions only. If it is a good feedback, it can stand on it's own.

> ---
> arch/x86/kvm/vmx/tdx.c | 28 ++++++++++++++++++++++++++--
> arch/x86/kvm/vmx/vmx.c | 2 +-
> arch/x86/kvm/vmx/vmx.h | 1 +
> 3 files changed, 28 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
> index a89885d550c9..ac3f71643cd5 100644
> --- a/arch/x86/kvm/vmx/tdx.c
> +++ b/arch/x86/kvm/vmx/tdx.c
> @@ -1080,8 +1080,10 @@ fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
> * allowing vCPU entry to avoid contention with tdh_vp_enter() and
> * TDCALLs.
> */
> - if (unlikely(READ_ONCE(to_kvm_tdx(vcpu->kvm)->wait_for_sept_zap)))
> + if (unlikely(READ_ONCE(to_kvm_tdx(vcpu->kvm)->wait_for_sept_zap))) {
> + vt->exit_reason.bus_lock_detected = 0;
> return EXIT_FASTPATH_EXIT_HANDLED;
> + }

Hmm. Why is this the only part of exit_reason that we care about in this
scenario?

I went and looked for similar scenarios on the VMX side to see what it did, and
didn't find any. Same for you?

>
> trace_kvm_entry(vcpu, run_flags & KVM_RUN_FORCE_IMMEDIATE_EXIT);
>
> @@ -2037,7 +2039,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;
> @@ -2138,6 +2140,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 __vmx_handle_notify(vcpu, vmx_get_exit_qual(vcpu));
> + case EXIT_REASON_BUS_LOCK:
> + return handle_bus_lock_vmexit(vcpu);
> default:
> break;
> }
> @@ -2147,6 +2151,22 @@ 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;
> + ret = 0;
> + }
> +
> + vcpu->run->flags |= KVM_RUN_X86_BUS_LOCK;
> + }
> + return ret;
> +}

Ok, so the plan is to consolidate this duplication on top of the backportable
fix.

> +
> void tdx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason,
> u64 *info1, u64 *info2, u32 *intr_info, u32 *error_code)
> {
> @@ -3173,6 +3193,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 e53cc96002c7..c429db9b9205 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -6265,7 +6265,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 dc8517f15bc4..8faf04c09721 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);
>
> static inline void vmx_disable_intercept_for_msr(struct kvm_vcpu *vcpu,
> u32 msr, int type)