On Fri, 2025-08-29 at 16:18 +0800, Yan Zhao wrote: > > + /* > > + * 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. I'm seeing the same thing in the TDX module. It could fail because of contention controllable from userspace. So the KVM_BUG_ON() is not appropriate. Today though if tdh_mr_extend() fails because of contention then the TD is essentially dead anyway. Trying to redo KVM_TDX_INIT_MEM_REGION will fail. The M-EPT fault could be spurious but the second tdh_mem_page_add() would return an error and never get back to the tdh_mr_extend(). The version in this patch can't recover for a different reason. That is kvm_tdp_mmu_map_private_pfn() doesn't handle spurious faults, so I'd say just drop the KVM_BUG_ON(), and try to handle the contention in a separate effort. I guess the two approaches could be to make KVM_TDX_INIT_MEM_REGION more robust, or prevent the contention. For the latter case: tdh_vp_create()/tdh_vp_addcx()/tdh_vp_init*()/tdh_vp_rd()/tdh_vp_wr() ...I think we could just take slots_lock during KVM_TDX_INIT_VCPU and KVM_TDX_GET_CPUID. For tdh_vp_flush() the vcpu_load() in kvm_arch_vcpu_ioctl() could be hard to handle. So I'd think maybe to look towards making KVM_TDX_INIT_MEM_REGION more robust, which would mean the eventual solution wouldn't have ABI concerns by later blocking things that used to be allowed. Maybe having kvm_tdp_mmu_map_private_pfn() return success for spurious faults is enough. But this is all for a case that userspace isn't expected to actually hit, so seems like something that could be kicked down the road easily.