From nobody Sat Jul 25 22:03:16 2026 Received: from mail-pj2-f4.google.com (mail-pj2-f4.google.com [74.125.227.132]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3427231283E for ; Mon, 13 Jul 2026 07:21:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.132 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783927302; cv=none; b=oa4Neuj8YGZt/tI6p6vPrJOlBLT4HVj3gtxNoe43ytVKc2trrkqy4IGs40eopsiSlKRKLdXWYo/IOTErqqu3bcUAhDcNbXmFG0tHVynh6TlKvxFFJd/hlCfq/QQD6vTaOnuqc/W6enuLKiqyAgN+cihTf+Uj9TW7f6xLUxbVCXs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783927302; c=relaxed/simple; bh=0GN9jdsp5y+GN7usd3hPGt5G7dPiAcDDERv3sy7M2go=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=e5ubnU8SLOeriZ0KueosVvyQjMg3Bsy9NKuqsWb0Zgef97YpMwhCp23PwZU/9d4ek8SqdQfySBPxK4JhmyIIBVg5hfgQNzP1uMhr4Nxr1lP+H1BHOs5T1z0ord8nsuNWH3NoI+HMkxYf4zYuzWQaN8CfBP6hfLMlk0iKZ3DuKuk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=N9G8uXF7; arc=none smtp.client-ip=74.125.227.132 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="N9G8uXF7" Received: by mail-pj2-f4.google.com with SMTP id d9443c01a7336-2cabe9335f1so17232785ad.0 for ; Mon, 13 Jul 2026 00:21:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783927300; x=1784532100; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=uoXDjnnGnfjdjZLeKSIkqLVfLmi5f0feB1W9q0yXDSk=; b=N9G8uXF7PU2YLF4vQNVA1PMnApcytLp4YAhpzUvF9Wllh+9yLFrVBCn+d/2qvFY3TP SvIRzhBQdwYCxo3Tg5W6v6FxC9lO/NuTtmFQaZ1gQ3Hk9N9qYZU1f+wOpRfWJceeDapN E22Ou/odsDbWuWX+K8BbL61oZpx4g2dwlttTfVKWB1BM1tNTRtuzxsY6Td30PhxTqRSB 2WQ6pJmx1G7gvC3nsrQxR78kzjHUE5e14xNhyzH3xru7HntkCPfVgLHSD93hLOxODKOK p1YMbAk4JwuJmy73HCHcjtPJcj9YS7VHpQT89NV10pf8NbjCyw7blgqQTfZMRabv5RZM z72g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783927300; x=1784532100; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=uoXDjnnGnfjdjZLeKSIkqLVfLmi5f0feB1W9q0yXDSk=; b=cuwCEhwTVvieq8N3i9OZCQJb9iZ1k4vto9kyeSTekTB9gmu41cgl2hhANPJKhLj0N1 Yk0yLzFa+AC3hPmjZIvAHDAdeIknL5MKIsVgS/OqDlye5GL2Rk1folcgHpChLtUBs3A3 oKohQkh/zShLsE5xOXKCQTqwReq5+ez30v9jdDDmPjv6IyuQwIag/nOv4grmHUd+SmeX lzHwZCD5BUW4u3eKTJqBaV36UfeStCvx4oahgObRN+OhS+4aWD61Ltys/TyG3kNsmqId 3IMOzDykbNyb9nvv3skvzkYngO12qdmWnfwLT62fxg9NiaKAiISSRdzRiHE0fBmxTnPN LZtw== X-Forwarded-Encrypted: i=1; AHgh+RpYVlGnUWCYTaOEwpaNhPJjIDZVyY0pjq0LKTy3mPEfW0U4faLPWUZqQYM7nXq0rKepqfCnFqHVN1jPzPU=@vger.kernel.org X-Gm-Message-State: AOJu0YwM/bQ54JmWT9fJMJp0ZWib4rMyUBLG0u0VX9wpFG6GfMvuA94b JVzD0gRZDHZw4beKgnw5btlNVmJ3Ewb9Tg9G0NcITLqAiuuqK14r5WN1 X-Gm-Gg: AfdE7cnuhS9I7S9678YIaS/u1h0VVS3eHaCgf5kvFoqn3I4nzFadbY4kqishWAtWXZK aaLi0HfgzBXy99m5ESBskYskwP5ctbRkPUTW5/X9Q85P1yCAXncuZWiMM2MM5iGdTeF3HrQlf8p zkS9FO69r0SfA8XQnlR/5tT1dMYNFroHwIAuNPGTHZNgOWyMZ3Jv2Wdw83qV8fZoJpM/2JzX4wi YWXhoFD1u5U3UrqMDUO8PV174d9z5JHpqJAQOgnhAyQM2XTX1vn6dneam/TwHpiWmclrHlvObL1 +HrBO36NWdTHQCnB4yXJ+CdGpg2rIAhUo03Op7UnBOypsLb6IAet1Wdvq3Eed2G1bjKxwo9LL5T e6AU5mQYlNOb3+Vlu576vh1ZLM6C8pdoToRQwt2naiD+sVyQhs1yGwn/3X+t2JCsNFRQK2WpgQw k80rb3R5ufhk+p2EhPE8GWWIlq938TDpL8YWezBw== X-Received: by 2002:a17:902:fc45:b0:2ca:e08e:9e70 with SMTP id d9443c01a7336-2ce9f18381dmr80811085ad.46.1783927300494; Mon, 13 Jul 2026 00:21:40 -0700 (PDT) Received: from q-System-Product-Name ([129.227.183.200]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ccc9bdb7e9sm97547295ad.10.2026.07.13.00.21.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jul 2026 00:21:40 -0700 (PDT) From: "Bingyu.Xian" To: Anup Patel Cc: Atish Patra , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Quan Zhou , kvm@vger.kernel.org, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH RFC v3] KVM: riscv: Allow G-stage PMD block mappings for VM_PFNMAP Date: Mon, 13 Jul 2026 15:21:23 +0800 Message-ID: <20260713072123.1591097-1-shanbeeyoo@gmail.com> X-Mailer: git-send-email 2.54.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" RISC-V KVM currently forces all VM_PFNMAP faults to PAGE_SIZE, so a 256 MB VFIO BAR requires 65 536 G-stage PTEs instead of 128 PMD blocks. This becomes critical as RISC-V targets server workloads with GPU/NPU VFIO passthrough and the RISC-V IOMMU nears mainstream support. Adapt arm64's "stage-2 block mapping for host device MMIO" idea from commit 2aa53d68cee6 ("KVM: arm64: Try stage2 block mapping for host device MMIO"), but with a safer approach: instead of deriving the host physical address from vma->vm_pgoff (unreliable since the VFIO unmap_mapping_range() changes), pfnmap_mapping_size() walks the host page tables via get_hva_mapping_size(). If the host mm installed a PMD leaf, physical contiguity is guaranteed and KVM uses a 2 MB G-stage block; otherwise it falls back to 4 KB as before. RISC-V has an advantage here: memory type comes from the physical address PMA, not the G-stage PTE attributes, so 4 KB -> 2 MB promotion does not alter memory-type semantics. Also generalize fault_supports_gstage_huge_mapping() to accept a map_size parameter, fix gfn alignment to use vma_pagesize instead of huge_page_mask(hstate_vma(vma)) since PFNMAP VMAs are not hugetlb, and add a kvm_mmu_map tracepoint for debugging. Conservative for now: only PMD (2 MB), not PUD (1 GB); dirty logging still forces PAGE_SIZE; falls back whenever contiguity/alignment cannot be proven. Tested on QEMU (rv64) with a custom module that installs a PMD leaf for a VM_PFNMAP VMA: tracepoint confirms 4 KB fallback when host has no PMD leaf, and 2 MB block mapping when host does. Assisted-by: YuanSheng:deepseek-v4-pro Co-developed-by: Quan Zhou Signed-off-by: Quan Zhou Signed-off-by: Bingyu.Xian --- Changes from v2: - https://lore.kernel.org/kvm-riscv/20260710051903.3454598-1-shanbeeyoo@gma= il.com/ - Correct the author and Signed-off-by identity to: Bingyu.Xian - Use the canonical commit-reference and Assisted-by formats. - No code changes. arch/riscv/kvm/mmu.c | 45 ++++++++++++++++++++++++++++++++++++------ arch/riscv/kvm/trace.h | 29 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c index 2d3def024270..53fb34d4b76d 100644 --- a/arch/riscv/kvm/mmu.c +++ b/arch/riscv/kvm/mmu.c @@ -16,6 +16,8 @@ #include #include =20 +#include "trace.h" + static void mmu_wp_memory_region(struct kvm *kvm, int slot) { struct kvm_memslots *slots =3D kvm_memslots(kvm); @@ -286,7 +288,7 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_r= ange *range) } =20 static bool fault_supports_gstage_huge_mapping(struct kvm_memory_slot *mem= slot, - unsigned long hva) + unsigned long hva, unsigned long map_size) { hva_t uaddr_start, uaddr_end; gpa_t gpa_start; @@ -321,7 +323,7 @@ static bool fault_supports_gstage_huge_mapping(struct k= vm_memory_slot *memslot, * e -> g * f -> h */ - if ((gpa_start & (PMD_SIZE - 1)) !=3D (uaddr_start & (PMD_SIZE - 1))) + if ((gpa_start & (map_size - 1)) !=3D (uaddr_start & (map_size - 1))) return false; =20 /* @@ -336,7 +338,7 @@ static bool fault_supports_gstage_huge_mapping(struct k= vm_memory_slot *memslot, * userspace_addr or the base_gfn, as both are equally aligned (per * the check above) and equally sized. */ - return (hva >=3D ALIGN(uaddr_start, PMD_SIZE)) && (hva < ALIGN_DOWN(uaddr= _end, PMD_SIZE)); + return (hva >=3D ALIGN(uaddr_start, map_size)) && (hva < ALIGN_DOWN(uaddr= _end, map_size)); } =20 static int get_hva_mapping_size(struct kvm *kvm, @@ -404,7 +406,7 @@ static unsigned long transparent_hugepage_adjust(struct= kvm *kvm, * sure that the HVA and GPA are sufficiently aligned and that the * block map is contained within the memslot. */ - if (fault_supports_gstage_huge_mapping(memslot, hva)) { + if (fault_supports_gstage_huge_mapping(memslot, hva, PMD_SIZE)) { int sz; =20 sz =3D get_hva_mapping_size(kvm, hva); @@ -421,6 +423,31 @@ static unsigned long transparent_hugepage_adjust(struc= t kvm *kvm, return PAGE_SIZE; } =20 +/* + * Determine the G-stage mapping size for a VM_PFNMAP (e.g. host device + * MMIO) fault. Unlike arm64's original implementation, we never derive t= he + * host physical address from vma->vm_pgoff (which is unreliable since the + * VFIO unmap_mapping_range() changes). Instead we walk the host page tab= les + * via get_hva_mapping_size(): if the host itself installed a leaf block f= or + * this address, physical contiguity within that block is already guarante= ed + * by the host mm. The memory type stays correct because RISC-V derives it + * from the physical address' PMA, independent of the G-stage PTE size. + * + * Be conservative for now and only promote to PMD-sized blocks; PUD-sized + * device blocks are left as future work. Fall back to PAGE_SIZE whenever + * contiguity or HVA/GPA alignment cannot be proven. + */ +static unsigned long pfnmap_mapping_size(struct kvm *kvm, + struct kvm_memory_slot *memslot, + unsigned long hva) +{ + if (get_hva_mapping_size(kvm, hva) >=3D PMD_SIZE && + fault_supports_gstage_huge_mapping(memslot, hva, PMD_SIZE)) + return PMD_SIZE; + + return PAGE_SIZE; +} + int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memsl= ot, gpa_t gpa, unsigned long hva, bool is_write, struct kvm_gstage_mapping *out_map) @@ -465,11 +492,14 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct k= vm_memory_slot *memslot, else vma_pageshift =3D PAGE_SHIFT; vma_pagesize =3D 1ULL << vma_pageshift; - if (logging || (vma->vm_flags & VM_PFNMAP)) + + if (logging) vma_pagesize =3D PAGE_SIZE; + else if (vma->vm_flags & VM_PFNMAP) + vma_pagesize =3D pfnmap_mapping_size(kvm, memslot, hva); =20 if (vma_pagesize =3D=3D PMD_SIZE || vma_pagesize =3D=3D PUD_SIZE) - gfn =3D (gpa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT; + gfn =3D (gpa & ~(vma_pagesize - 1)) >> PAGE_SHIFT; =20 /* * Read mmu_invalidate_seq so that KVM can detect if the results of @@ -515,6 +545,9 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm= _memory_slot *memslot, if (!logging && (vma_pagesize =3D=3D PAGE_SIZE)) vma_pagesize =3D transparent_hugepage_adjust(kvm, memslot, hva, &hfn, &g= pa); =20 + trace_kvm_mmu_map(gpa, hva, hfn, vma_pagesize, + !!(vma->vm_flags & VM_PFNMAP)); + if (writable) { mark_page_dirty_in_slot(kvm, memslot, gfn); ret =3D kvm_riscv_gstage_map_page(&gstage, pcache, gpa, hfn << PAGE_SHIF= T, diff --git a/arch/riscv/kvm/trace.h b/arch/riscv/kvm/trace.h index 3d54175d805c..db2d28f1d714 100644 --- a/arch/riscv/kvm/trace.h +++ b/arch/riscv/kvm/trace.h @@ -56,6 +56,35 @@ TRACE_EVENT(kvm_exit, __entry->htinst) ); =20 +TRACE_EVENT(kvm_mmu_map, + TP_PROTO(unsigned long gpa, unsigned long hva, unsigned long hfn, + unsigned long map_size, bool is_pfnmap), + TP_ARGS(gpa, hva, hfn, map_size, is_pfnmap), + + TP_STRUCT__entry( + __field(unsigned long, gpa) + __field(unsigned long, hva) + __field(unsigned long, hfn) + __field(unsigned long, map_size) + __field(bool, is_pfnmap) + ), + + TP_fast_assign( + __entry->gpa =3D gpa; + __entry->hva =3D hva; + __entry->hfn =3D hfn; + __entry->map_size =3D map_size; + __entry->is_pfnmap =3D is_pfnmap; + ), + + TP_printk("GPA:0x%lx, HVA:0x%lx, HFN:0x%lx, size:%luKB, pfnmap:%d", + __entry->gpa, + __entry->hva, + __entry->hfn, + __entry->map_size >> 10, + __entry->is_pfnmap) +); + #endif /* _TRACE_RSICV_KVM_H */ =20 #undef TRACE_INCLUDE_PATH --=20 2.54.0