[PATCH RFC 0/1] KVM: riscv: G-stage PMD block mappings for VM_PFNMAP
Bingyu.Xian
shanbeeyoo at gmail.com
Thu Jul 9 06:00:35 PDT 2026
From: "Bingyu.Xian" <Shanbeeyoo at gmail.com>
This RFC adapts the arm64 "stage-2 block mapping for host device MMIO"
idea (commit 2aa53d68cee6) to RISC-V KVM, allowing VM_PFNMAP regions
such as VFIO-assigned PCI BARs to use 2 MB G-stage PMD block mappings
instead of being forced to 4 KB PTEs.
=== Why this matters for RISC-V ===
1. RISC-V virtualization is maturing rapidly. The H-extension was
ratified in 2021 and KVM/riscv has been upstream since v5.15, but
many performance optimizations that exist on arm64 and x86 are still
missing. This patch closes one of those gaps.
2. Server-class RISC-V platforms are on the roadmap. Device passthrough
(VFIO) for GPUs, NPUs, and high-speed NICs is essential for
data-center workloads. These devices have BARs ranging from tens of
MB to multiple GB. Without this patch, a single 256 MB GPU BAR
requires 65 536 G-stage PTEs (512 KB of page-table memory and 65 536
G-stage faults), compared to 128 PMD blocks with this optimization.
3. RISC-V IOMMU specification was ratified in March 2023 and Linux
driver support is under active development. Once RISC-V IOMMU
hardware becomes available, VFIO passthrough will be a first-class
use case. This KVM G-stage optimization is a prerequisite for
acceptable passthrough performance.
4. RISC-V has a natural advantage over arm64 here: the memory type is
determined by the physical address' PMA (Physical Memory Attribute),
not by the G-stage PTE attributes. So promoting 4 KB -> 2 MB does
not alter memory-type semantics, unlike arm64 where the stage-2 PTE
MemAttr field requires careful handling.
=== Design choices ===
Unlike arm64's original implementation which derives the host physical
address from vma->vm_pgoff, this patch walks the host page tables via
get_hva_mapping_size(). This is more conservative but safer: if the
host mm itself has not installed a PMD leaf, KVM falls back to 4 KB
exactly as before. The vm_pgoff approach is unreliable since the VFIO
unmap_mapping_range() changes discussed on the RISC-V list in 2025.
The first version is deliberately conservative:
- Only PMD (2 MB) blocks, not PUD (1 GB)
- dirty logging still forces PAGE_SIZE
- falls back to PAGE_SIZE whenever contiguity/alignment cannot be
proven
=== Testing ===
Verified on QEMU (rv64, h=true, sstc=true) with a custom kernel module
(pfnmap-huge-test.ko) that installs a PMD leaf in the host page table
for a VM_PFNMAP VMA, simulating a VFIO BAR with a 2 MB host mapping.
Tracepoint kvm_mmu_map confirms all three scenarios:
- anonymous memory: size=4KB pfnmap=0 (control group)
- /dev/mem (4KB host): size=4KB pfnmap=1 (safe fallback works)
- PMD leaf module: size=2048KB pfnmap=1 (block mapping works!)
I welcome feedback on:
- Whether the host-page-table-walk approach is preferred over the
arm64 vm_pgoff approach
- Whether PUD (1 GB) block support should be added now or deferred
- Whether the tracepoint should be kept or removed before non-RFC
submission
Bingyu.Xian (1):
KVM: riscv: Allow safe G-stage PMD block mappings for VM_PFNMAP
arch/riscv/kvm/mmu.c | 45 ++++++++++++++++++++++++++++++++++++------
arch/riscv/kvm/trace.h | 29 +++++++++++++++++++++++++++
2 files changed, 68 insertions(+), 6 deletions(-)
--
2.54.0
More information about the linux-riscv
mailing list