[RFC PATCH] RISC-V: KVM: Add minimal guest_memfd support
"Bingyu.Xian" <[email protected]> Wed, 29 Jul 2026 15:07:56 +0800
| Newsgroups | org.infradead.lists.kvm-riscv,org.infradead.lists.linux-riscv,org.kernel.vger.kvm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Add minimal guest_memfd support for RISC-V KVM, following the same pattern as x86 and arm64. 1. Select KVM_GUEST_MEMFD in Kconfig 2. In kvm_riscv_mmu_map(), check kvm_slot_has_gmem() early, before taking mmap_read_lock(). For gmem memslots, resolve the PFN via kvm_gmem_get_pfn(), then acquire kvm->mmu_lock and jump to G-stage mapping, bypassing vma_lookup()/__kvm_faultin_pfn(). The gmem PFN is resolved before mmap_read_lock() so the mmu_lock taken for the mapping is never held while waiting for mmap_lock, which would deadlock against mmu_notifier invalidation (mmu_lock -> mmap_lock). 3. Skip kvm_release_faultin_page() for gmem pages; their lifetime is managed by the gmem inode and invalidation notifiers. Verified: defconfig + CONFIG_KVM_GUEST_MEMFD=y compiles cleanly. Assisted-by: YuanSheng: deepseek-v4-pro Co-developed-by: Quan Zhou <[email protected]> Signed-off-by: Quan Zhou <[email protected]> Signed-off-by: Bingyu Xian <[email protected]> --- arch/riscv/kvm/Kconfig | 1 + arch/riscv/kvm/mmu.c | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig index ec2cee0a39e0..77121100579f 100644 --- a/arch/riscv/kvm/Kconfig +++ b/arch/riscv/kvm/Kconfig @@ -29,6 +29,7 @@ config KVM select KVM_GENERIC_DIRTYLOG_READ_PROTECT select KVM_GENERIC_HARDWARE_ENABLING select KVM_MMIO + select KVM_GUEST_MEMFD select VIRT_XFER_TO_GUEST_WORK select SCHED_INFO select GUEST_PERF_EVENTS if PERF_EVENTS diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c index d2a06a54be17..a9d61d0366e2 100644 --- a/arch/riscv/kvm/mmu.c +++ b/arch/riscv/kvm/mmu.c @@ -557,6 +557,19 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, /* Setup initial state of output mapping */ memset(out_map, 0, sizeof(*out_map)); + if (kvm_slot_has_gmem(memslot)) { + int max_order; + + ret = kvm_gmem_get_pfn(kvm, memslot, gfn, &hfn, &page, &max_order); + if (ret) + return ret; + + vma_pagesize = PAGE_SIZE; + writable = true; + write_lock(&kvm->mmu_lock); + goto map_gstage; + } + if (is_write && logging && kvm_riscv_mmu_dirty_log_write_fault_fast(kvm, memslot, gpa, out_map)) return 0; @@ -643,6 +656,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, if (!logging && !is_hugetlb && vma_pagesize == PAGE_SIZE) vma_pagesize = transparent_hugepage_adjust(kvm, memslot, hva, &hfn, &gpa); +map_gstage: if (writable) { mark_page_dirty_in_slot(kvm, memslot, gfn); ret = kvm_riscv_gstage_map_page(&gstage, pcache, gpa, hfn << PAGE_SHIFT, @@ -658,7 +672,8 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, kvm_err("Failed to map in G-stage\n"); out_unlock: - kvm_release_faultin_page(kvm, page, ret, writable); + if (!kvm_slot_has_gmem(memslot)) + kvm_release_faultin_page(kvm, page, ret, writable); write_unlock(&kvm->mmu_lock); return ret; } -- 2.54.0 -- kvm-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kvm-riscv