[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