Re: [PATCH v2 2/3] KVM: TDX: Fix the exit reason handling
Xiaoyao Li <[email protected]>
| Newsgroups | dev.linux.lists.sashiko-reviews,org.kernel.vger.kvm |
|---|---|
| Message-ID | <[email protected]> |
On 8/12/2026 11:20 AM, Xiaoyao Li wrote: > On 8/11/2026 8:04 AM, Sean Christopherson wrote: >> On Mon, Aug 10, 2026, Sean Christopherson wrote: >>> On Mon, Aug 10, 2026, Xiaoyao Li wrote: >>>> On 8/10/2026 7:39 PM, [email protected] wrote: >>>>>> @@ -2147,7 +2156,7 @@ void tdx_get_exit_info(struct kvm_vcpu >>>>>> *vcpu, u32 *reason, >>>>>> struct vcpu_tdx *tdx = to_tdx(vcpu); >>>>>> *reason = tdx->vt.exit_reason.full; >>>>>> - if (*reason != -1u) { >>>>>> + if (tdx->vt.exit_reason.basic != -1) { >>>>> [Severity: Medium] >>>>> Will this check always evaluate to true due to C integer promotion >>>>> rules? >>>>> >>>>> The basic field in union vmx_exit_reason is a 16-bit unsigned >>>>> bitfield. When >>>>> comparing it to -1, the unsigned 16-bit value is promoted to a >>>>> signed 32-bit >>>>> integer. If the value was set to -1 (65535), the comparison >>>>> evaluates as >>>>> 65535 != -1, which is always true. >>>>> >>>> >>>> Well, how about something below on top of this patch? >>> >>> No, we need to not rely on magic exit_reason.basic values. Can't >>> this be? >>> >>> if ((tdx->vp_enter_ret & TDX_SW_ERROR) != TDX_SW_ERROR) { >> >> This would arguably be a bug fix as well, because the "real" >> EXIT_REASON_EPT_MISCONFIG >> path gets a false negative. E.g. when getting information for an EPT >> Misconfig >> for the tracepoint, KVM really should print all information, not zeros. >> >> At a glance, this exact change can probably be a separate patch too. > > Yeah, this issue can be fixed by the patch which turns real > EPT_MISCONFIG to TDX_SW_ERROR. > > Side topic, tdx_to_vmx_exit_reason() can change EXIT_REASON_TDCALL to > other Exit Reason. Do we want to print TDCALL instead of the transformed > reason here? Well, the more I think about this all, the more I dislike the fancy trick to turn TDCALL into other Exit Reason, in tdx_to_vmx_exit_reason(). Without it, it's straightforward to handle the EPT_MISCONFIG. And without it, the exit trace can also get the correct Exit Reason. How about something below? which is on top of kvm-x86/next diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index b272c20586a7..2474a298e2cd 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -924,7 +924,6 @@ 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; switch (tdx->vp_enter_ret & TDX_SEAMCALL_STATUS_MASK) { case TDX_SUCCESS: @@ -932,30 +931,11 @@ static __always_inline u32 tdx_to_vmx_exit_reason(struct kvm_vcpu *vcpu) case TDX_NON_RECOVERABLE_TD: case TDX_NON_RECOVERABLE_TD_NON_ACCESSIBLE: case TDX_NON_RECOVERABLE_TD_WRONG_APIC_MODE: - break; + return (u32)tdx->vp_enter_ret; default: return -1u; } - exit_reason = tdx->vp_enter_ret; - - switch (exit_reason) { - case 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; - } - - return exit_reason; } static noinstr void tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu) @@ -1093,9 +1073,6 @@ 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; @@ -2027,6 +2004,41 @@ int tdx_complete_emulated_msr(struct kvm_vcpu *vcpu, int err) return 1; } +#define TDVMCALL_CPUID EXIT_REASON_CPUID +#define TDVMCALL_HLT EXIT_REASON_HLT +#define TDVMCALL_IO_INSTRUCTION EXIT_REASON_IO_INSTRUCTION +#define TDVMCALL_MSR_READ EXIT_REASON_MSR_READ +#define TDVMCALL_MSR_WRITE EXIT_REASON_MSR_WRITE +#define TDVMCALL_MMIO EXIT_REASON_EPT_VIOLATION + +static int handle_tdcall(struct kvm_vcpu *vcpu) +{ + struct vcpu_tdx *tdx = to_tdx(vcpu); + + if (tdvmcall_exit_type(vcpu)) + return tdx_emulate_vmcall(vcpu); + + switch (tdvmcall_leaf(vcpu)) { + case TDVMCALL_CPUID: + return tdx_emulate_cpuid(vcpu); + case TDVMCALL_HLT: + return kvm_emulate_halt_noskip(vcpu); + case TDVMCALL_IO_INSTRUCTION: + return tdx_emulate_io(vcpu); + case TDVMCALL_MSR_READ: + kvm_ecx_write(vcpu, tdx->vp_enter_args.r12); + return kvm_emulate_rdmsr(vcpu); + case TDVMCALL_MSR_WRITE: + kvm_ecx_write(vcpu, tdx->vp_enter_args.r12); + kvm_eax_write(vcpu, tdx->vp_enter_args.r13); + kvm_edx_write(vcpu, tdx->vp_enter_args.r13 >> 32); + return kvm_emulate_wrmsr(vcpu); + case TDVMCALL_MMIO: + return tdx_emulate_mmio(vcpu); + default: + return handle_tdvmcall(vcpu); + } +} int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) { @@ -2037,11 +2049,6 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) if (fastpath != EXIT_FASTPATH_NONE) return 1; - if (unlikely(vp_enter_ret == EXIT_REASON_EPT_MISCONFIG)) { - KVM_BUG_ON(1, vcpu->kvm); - return -EIO; - } - /* * Handle TDX SW errors, including TDX_SEAMCALL_UD, TDX_SEAMCALL_GP and * TDX_SEAMCALL_VMFAILINVALID. @@ -2083,26 +2090,12 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath) case EXIT_REASON_EXTERNAL_INTERRUPT: ++vcpu->stat.irq_exits; return 1; - case EXIT_REASON_CPUID: - return tdx_emulate_cpuid(vcpu); - case EXIT_REASON_HLT: - return kvm_emulate_halt_noskip(vcpu); case EXIT_REASON_TDCALL: - return handle_tdvmcall(vcpu); - case EXIT_REASON_VMCALL: - return tdx_emulate_vmcall(vcpu); - case EXIT_REASON_IO_INSTRUCTION: - return tdx_emulate_io(vcpu); - case EXIT_REASON_MSR_READ: - kvm_ecx_write(vcpu, tdx->vp_enter_args.r12); - return kvm_emulate_rdmsr(vcpu); - case EXIT_REASON_MSR_WRITE: - kvm_ecx_write(vcpu, tdx->vp_enter_args.r12); - kvm_eax_write(vcpu, tdx->vp_enter_args.r13); - kvm_edx_write(vcpu, tdx->vp_enter_args.r13 >> 32); - return kvm_emulate_wrmsr(vcpu); + return handle_tdcall(vcpu); case EXIT_REASON_EPT_MISCONFIG: - return tdx_emulate_mmio(vcpu); + /* EPT MISCONFIGs are *always* KVM/kernel bugs. */ + KVM_BUG_ON(1, vcpu->kvm); + return -EIO; case EXIT_REASON_EPT_VIOLATION: return tdx_handle_ept_violation(vcpu); case EXIT_REASON_OTHER_SMI: