On Thu, Aug 28, 2025 at 05:06:12PM -0700, Sean Christopherson wrote: > WARN and terminate the VM if TDH_MR_EXTEND fails, as extending the > measurement should fail if and only if there is a KVM bug, or if the S-EPT > mapping is invalid, and it should be impossibe for the S-EPT mappings to > be removed between kvm_tdp_mmu_map_private_pfn() and tdh_mr_extend(). > > Holding slots_lock prevents zaps due to memslot updates, > filemap_invalidate_lock() prevents zaps due to guest_memfd PUNCH_HOLE, > and all usage of kvm_zap_gfn_range() is mutually exclusive with S-EPT > entries that can be used for the initial image. The call from sev.c is > obviously mutually exclusive, TDX disallows KVM_X86_QUIRK_IGNORE_GUEST_PAT > so same goes for kvm_noncoherent_dma_assignment_start_or_stop, and while > __kvm_set_or_clear_apicv_inhibit() can likely be tripped while building the > image, the APIC page has its own non-guest_memfd memslot and so can't be > used for the initial image, which means that too is mutually exclusive. > > Opportunistically switch to "goto" to jump around the measurement code, > partly to make it clear that KVM needs to bail entirely if extending the > measurement fails, partly in anticipation of reworking how and when > TDH_MEM_PAGE_ADD is done. > > Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> > --- > arch/x86/kvm/vmx/tdx.c | 24 ++++++++++++++++-------- > 1 file changed, 16 insertions(+), 8 deletions(-) > > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c > index 06dd2861eba7..bc92e87a1dbb 100644 > --- a/arch/x86/kvm/vmx/tdx.c > +++ b/arch/x86/kvm/vmx/tdx.c > @@ -3145,14 +3145,22 @@ static int tdx_gmem_post_populate(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, > > KVM_BUG_ON(atomic64_dec_return(&kvm_tdx->nr_premapped) < 0, kvm); > > - if (arg->flags & KVM_TDX_MEASURE_MEMORY_REGION) { > - for (i = 0; i < PAGE_SIZE; i += TDX_EXTENDMR_CHUNKSIZE) { > - err = tdh_mr_extend(&kvm_tdx->td, gpa + i, &entry, > - &level_state); > - if (err) { > - ret = -EIO; > - break; > - } > + if (!(arg->flags & KVM_TDX_MEASURE_MEMORY_REGION)) > + goto out; > + > + /* > + * Note, MR.EXTEND can fail if the S-EPT mapping is somehow removed > + * between mapping the pfn and now, but slots_lock prevents memslot > + * updates, filemap_invalidate_lock() prevents guest_memfd updates, > + * mmu_notifier events can't reach S-EPT entries, and KVM's internal > + * zapping flows are mutually exclusive with S-EPT mappings. > + */ > + for (i = 0; i < PAGE_SIZE; i += TDX_EXTENDMR_CHUNKSIZE) { > + err = tdh_mr_extend(&kvm_tdx->td, gpa + i, &entry, &level_state); > + if (KVM_BUG_ON(err, kvm)) { I suspect tdh_mr_extend() running on one vCPU may contend with tdh_vp_create()/tdh_vp_addcx()/tdh_vp_init*()/tdh_vp_rd()/tdh_vp_wr()/ tdh_mng_rd()/tdh_vp_flush() on other vCPUs, if userspace invokes ioctl KVM_TDX_INIT_MEM_REGION on one vCPU while initializing other vCPUs. It's similar to the analysis of contention of tdh_mem_page_add() [1], as both tdh_mr_extend() and tdh_mem_page_add() acquire exclusive lock on resource TDR. I'll try to write a test to verify it and come back to you. [1] https://lore.kernel.org/kvm/20250113021050.18828-1-yan.y.zhao@xxxxxxxxx/ > + pr_tdx_error_2(TDH_MR_EXTEND, err, entry, level_state); > + ret = -EIO; > + goto out; > } > } > > -- > 2.51.0.318.gd7df087d1a-goog >