Re: [PATCH] KVM: VMX: Explicitly track TDX VMs' root level instead of guessing it from CPUID

Yan Zhao <[email protected]>
Newsgroups dev.linux.lists.linux-coco,org.kernel.vger.kvm,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On Fri, Aug 14, 2026 at 03:45:09PM -0700, Sean Christopherson wrote:
> Explicitly track the root level for TDX VMs instead of trying to infer the
> depth of the paging tree based on an individual vCPU's CPUID information.
> Applying KVM's existing logic to select the root level to TDX is flawed as
> nothing *requires* userspace to fill in the correct guest.MAXPHYADDR for a
> vCPU's CPUID.  Guessing at the correct root level is also ridiculous given
> that userspace has already told KVM the root level during TD initialization.
> 
> Relying on userspace to set the expected/correct CPUID lets a misbehaving
> userspace trip the KVM_BUG_ON() in tdx_load_mmu_pgd() by configuring guest
> CPUID to use an "incorrect" guest.MAXPHYADDR.
> 
> Keep gfn_direct_bits even though it can be trivially derived from
> mirror_root_level as saving a whole eight bytes per VM is meaningless, and
> the value is queried fairly often and in hot paths.
> 
> Cc: Rick Edgecombe <[email protected]>
> Cc: Xiaoyao Li <[email protected]>
> Cc: Binbin Wu <[email protected]>
> Cc: Kai Huang <[email protected]>
> Cc: Yan Zhao <[email protected]>
> Fixes: 20d913729c11 ("KVM: x86/mmu: Taking guest pa into consideration when calculate tdp level")
> Signed-off-by: Sean Christopherson <[email protected]>
> ---
> 
> Compile-tested only, and found by inspection, i.e. I haven't proven that this
> works, or that there's actually a bug.  But I'm pretty sure there's a bug.
I have verified this issue via a modified KVM selftest, where I set
init_vm->cpuid and vcpu->cpuid to have different maxpa values.

The warning can be successfully triggered:
...
[15466.362189] WARNING: arch/x86/kvm/vmx/tdx.c:1629 at tdx_load_mmu_pgd+0x6b/0xcf [kvm_intel], CPU#109: tdx_vm_test/42260
...

So, Tested-by: Yan Zhao <[email protected]> 

>  static inline int kvm_mmu_get_tdp_level(struct kvm_vcpu *vcpu)
>  {
> -	int maxpa;
> -
> -	if (vcpu->kvm->arch.vm_type == KVM_X86_TDX_VM)
> -		maxpa = cpuid_query_maxguestphyaddr(vcpu);
> -	else
> -		maxpa = cpuid_maxphyaddr(vcpu);
> -
>  	/* tdp_root_level is architecture forced level, use it if nonzero */
>  	if (tdp_root_level)
>  		return tdp_root_level;
>  
> +	/*
> +	 * If the VM has mirror roots, then the root level is fixed as the gfn
> +	 * used to select between the normal and mirror root must be covered.
> +	 */
> +	if (vcpu->kvm->arch.mirror_root_level)
> +		return vcpu->kvm->arch.mirror_root_level;
Also comment TDX module should have ensured
kvm->arch.mirror_root_level <= max_tdp_level?

>  	/* Use 5-level TDP if and only if it's useful/necessary. */
> -	if (max_tdp_level == 5 && maxpa <= 48)
> +	if (max_tdp_level == 5 && cpuid_maxphyaddr(vcpu) <= 48)
>  		return 4;
>
>  	return max_tdp_level;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.