* [PATCH v4 RESEND 0/5] KVM: riscv: Add KVM_PRE_FAULT_MEMORY support
@ 2026-08-15 10:28 Jinyu Tang
2026-08-15 10:32 ` [PATCH v4 RESEND 2/5] KVM: riscv: Avoid THP adjustment for existing 4K G-stage leaves Jinyu Tang
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Jinyu Tang @ 2026-08-15 10:28 UTC (permalink / raw)
To: Anup Patel, Anup Patel, Atish Patra
Cc: kvm, kvm-riscv, linux-riscv, linux-kernel, linux-kselftest,
Paolo Bonzini, Sean Christopherson, Shuah Khan, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Andrew Jones,
Conor Dooley, Yong-Xuan Wang, Nutty Liu, Jinyu Tang, Jinyu Tang
Add RISC-V support for the generic KVM_PRE_FAULT_MEMORY ioctl.
Patch 1 and patch 2 fix existing G-stage huge-page corner cases. They
are included first because the prefault hook relies on the map path
reporting the mapping that actually covers the requested GPA.
Patch 3 adds the RISC-V arch hook for KVM_PRE_FAULT_MEMORY. Patch 4 adds
Sv57 indexing support to the RISC-V KVM selftest helpers, and patch 5
enables the generic pre_fault_memory_test for RISC-V.
Patch 1 folds the previously posted standalone G-stage table overwrite
fix into this series:
https://lore.kernel.org/kvm-riscv/20260814105752.565325-1-jinyu.tang@linux.dev/T/#u
Changes in v4 resend:
- Resend the full series because the previous v4 send was interrupted
and the kvm-riscv list archive did not show a complete thread. No
code changes.
Changes in v4:
- Fold the standalone G-stage non-leaf overwrite fix into this series.
- Avoid THP adjustment when the original faulting GPA already has an
existing 4K G-stage leaf.
- Return an error for HWPOISON instead of reporting success without a
visible G-stage mapping. (Sashiko)
Changes in v3:
- Retry internally when the map path returns success without a visible
G-stage mapping, instead of exposing -EAGAIN. (Sashiko)
Changes in v2:
- Drop the per-test guest_modes_append_default() call from
pre_fault_memory_test.c. (Sean)
Jinyu Tang (5):
KVM: riscv: Avoid overwriting G-stage tables with huge leaves
KVM: riscv: Avoid THP adjustment for existing 4K G-stage leaves
KVM: riscv: Implement KVM_PRE_FAULT_MEMORY
KVM: selftests: Add RISC-V Sv57 page table indexing
KVM: selftests: Enable pre_fault_memory_test for RISC-V
arch/riscv/kvm/Kconfig | 1 +
arch/riscv/kvm/gstage.c | 9 ++
arch/riscv/kvm/mmu.c | 83 ++++++++++++++++++-
arch/riscv/kvm/vm.c | 1 +
tools/testing/selftests/kvm/Makefile.kvm | 1 +
.../selftests/kvm/include/riscv/processor.h | 6 ++
.../selftests/kvm/lib/riscv/processor.c | 2 +
7 files changed, 100 insertions(+), 3 deletions(-)
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v4 RESEND 2/5] KVM: riscv: Avoid THP adjustment for existing 4K G-stage leaves
2026-08-15 10:28 [PATCH v4 RESEND 0/5] KVM: riscv: Add KVM_PRE_FAULT_MEMORY support Jinyu Tang
@ 2026-08-15 10:32 ` Jinyu Tang
2026-08-15 10:33 ` [PATCH v4 RESEND 3/5] KVM: riscv: Implement KVM_PRE_FAULT_MEMORY Jinyu Tang
2026-08-15 10:34 ` [PATCH v4 RESEND 5/5] KVM: selftests: Enable pre_fault_memory_test for RISC-V Jinyu Tang
2 siblings, 0 replies; 4+ messages in thread
From: Jinyu Tang @ 2026-08-15 10:32 UTC (permalink / raw)
To: Anup Patel, Anup Patel, Atish Patra
Cc: kvm, kvm-riscv, linux-riscv, linux-kernel, linux-kselftest,
Paolo Bonzini, Sean Christopherson, Shuah Khan, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Andrew Jones,
Conor Dooley, Yong-Xuan Wang, Nutty Liu, Jinyu Tang
When dirty logging is disabled after a G-stage PMD mapping has been
split, the fault path may see a 4K G-stage leaf while the backing host
page is still THP-backed. The existing kvm_riscv_gstage_map_page()
comment says that this path should update the small leaf and leave huge
mapping recovery to a later ioctl path.
However, transparent_hugepage_adjust() runs before that G-stage lookup
and rewrites the fault GPA to the PMD base. If the original fault is not
at the PMD base, the lookup can find and update the wrong 4K leaf.
Check the original fault GPA in transparent_hugepage_adjust(). If it
already has a 4K G-stage leaf, skip THP adjustment and keep handling the
fault at PAGE_SIZE granularity.
Signed-off-by: Jinyu Tang <jinyu.tang@linux.dev>
---
arch/riscv/kvm/mmu.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index bfd6168ebe30..2fabcd409991 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -500,10 +500,21 @@ static int get_hva_mapping_size(struct kvm *kvm,
static unsigned long transparent_hugepage_adjust(struct kvm *kvm,
struct kvm_memory_slot *memslot,
+ struct kvm_gstage *gstage,
unsigned long hva,
kvm_pfn_t *hfnp, gpa_t *gpa)
{
kvm_pfn_t hfn = *hfnp;
+ u32 ptep_level;
+ pte_t *ptep;
+
+ /*
+ * Keep the existing split G-stage leaf and update the original
+ * faulting 4K page in the vCPU fault path.
+ */
+ if (kvm_riscv_gstage_get_leaf(gstage, *gpa, &ptep, &ptep_level) &&
+ !ptep_level)
+ return PAGE_SIZE;
/*
* Make sure the adjustment is done only for THP pages. Also make
@@ -730,7 +741,8 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
* so do not promote them through the THP helper.
*/
if (!logging && !is_hugetlb && vma_pagesize == PAGE_SIZE)
- vma_pagesize = transparent_hugepage_adjust(kvm, memslot, hva, &hfn, &gpa);
+ vma_pagesize = transparent_hugepage_adjust(kvm, memslot, &gstage,
+ hva, &hfn, &gpa);
if (writable) {
mark_page_dirty_in_slot(kvm, memslot, gfn);
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v4 RESEND 3/5] KVM: riscv: Implement KVM_PRE_FAULT_MEMORY
2026-08-15 10:28 [PATCH v4 RESEND 0/5] KVM: riscv: Add KVM_PRE_FAULT_MEMORY support Jinyu Tang
2026-08-15 10:32 ` [PATCH v4 RESEND 2/5] KVM: riscv: Avoid THP adjustment for existing 4K G-stage leaves Jinyu Tang
@ 2026-08-15 10:33 ` Jinyu Tang
2026-08-15 10:34 ` [PATCH v4 RESEND 5/5] KVM: selftests: Enable pre_fault_memory_test for RISC-V Jinyu Tang
2 siblings, 0 replies; 4+ messages in thread
From: Jinyu Tang @ 2026-08-15 10:33 UTC (permalink / raw)
To: Anup Patel, Anup Patel, Atish Patra
Cc: kvm, kvm-riscv, linux-riscv, linux-kernel, linux-kselftest,
Paolo Bonzini, Sean Christopherson, Shuah Khan, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Andrew Jones,
Conor Dooley, Yong-Xuan Wang, Nutty Liu, Jinyu Tang
The generic KVM_PRE_FAULT_MEMORY ioctl lets userspace populate KVM page
tables before running a vCPU over a GPA range. x86 already supports the
ioctl, but RISC-V does not expose the capability and has no arch hook.
Add the RISC-V arch hook and reuse the existing G-stage fault mapping
path with a read access. Report progress using the G-stage mapping
returned by the map path, so the ioctl can advance by the actual leaf
size that covers the requested GPA. Retry until a mapping is installed
or a signal, VM-dead request, or real error is observed.
Signed-off-by: Jinyu Tang <jinyu.tang@linux.dev>
---
arch/riscv/kvm/Kconfig | 1 +
arch/riscv/kvm/gstage.c | 3 +++
arch/riscv/kvm/mmu.c | 45 ++++++++++++++++++++++++++++++++++++++++-
arch/riscv/kvm/vm.c | 1 +
4 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig
index ec2cee0a39e0..8ac209e8ac87 100644
--- a/arch/riscv/kvm/Kconfig
+++ b/arch/riscv/kvm/Kconfig
@@ -28,6 +28,7 @@ config KVM
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_GENERIC_HARDWARE_ENABLING
+ select KVM_GENERIC_PRE_FAULT_MEMORY
select KVM_MMIO
select VIRT_XFER_TO_GUEST_WORK
select SCHED_INFO
diff --git a/arch/riscv/kvm/gstage.c b/arch/riscv/kvm/gstage.c
index 54d45addf18f..dff315dfd24e 100644
--- a/arch/riscv/kvm/gstage.c
+++ b/arch/riscv/kvm/gstage.c
@@ -286,6 +286,9 @@ int kvm_riscv_gstage_map_page(struct kvm_gstage *gstage,
out_map->level, true);
} else if (ALIGN_DOWN(PFN_PHYS(pte_pfn(ptep_get(ptep))), page_size) == hpa) {
kvm_riscv_gstage_update_pte_prot(gstage, ptep_level, gpa, ptep, prot);
+ out_map->addr = ALIGN_DOWN(gpa, page_size);
+ out_map->level = ptep_level;
+ out_map->pte = ptep_get(ptep);
return 0;
}
}
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 2fabcd409991..f6ca86da53eb 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -717,7 +717,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
if (hfn == KVM_PFN_ERR_HWPOISON) {
send_sig_mceerr(BUS_MCEERR_AR, (void __user *)hva,
vma_pageshift, current);
- return 0;
+ return -EFAULT;
}
if (is_error_noslot_pfn(hfn))
return -EFAULT;
@@ -782,6 +782,49 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
return ret;
}
+long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
+ struct kvm_pre_fault_memory *range)
+{
+ struct kvm_gstage_mapping out_map = { 0 };
+ struct kvm_memory_slot *memslot;
+ unsigned long map_size;
+ unsigned long hva;
+ gpa_t end;
+ gfn_t gfn;
+ int ret;
+
+ gfn = gpa_to_gfn(range->gpa);
+ memslot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
+ if (!memslot)
+ return -ENOENT;
+
+ hva = gfn_to_hva_memslot_prot(memslot, gfn, NULL);
+ if (kvm_is_error_hva(hva))
+ return -ENOENT;
+
+ for (;;) {
+ if (signal_pending(current))
+ return -EINTR;
+
+ if (kvm_check_request(KVM_REQ_VM_DEAD, vcpu))
+ return -EIO;
+
+ cond_resched();
+ ret = kvm_riscv_mmu_map(vcpu, memslot, range->gpa, hva, false, &out_map);
+ if (ret)
+ return ret;
+
+ if (!pte_val(out_map.pte))
+ continue;
+
+ map_size = PAGE_SIZE << (out_map.level * kvm_riscv_gstage_index_bits);
+ end = out_map.addr + map_size;
+ break;
+ }
+
+ return min_t(u64, range->size, end - range->gpa);
+}
+
int kvm_riscv_mmu_alloc_pgd(struct kvm *kvm)
{
struct page *pgd_page;
diff --git a/arch/riscv/kvm/vm.c b/arch/riscv/kvm/vm.c
index a9f083feeb76..58500a19b33b 100644
--- a/arch/riscv/kvm/vm.c
+++ b/arch/riscv/kvm/vm.c
@@ -187,6 +187,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_MP_STATE:
case KVM_CAP_IMMEDIATE_EXIT:
case KVM_CAP_SET_GUEST_DEBUG:
+ case KVM_CAP_PRE_FAULT_MEMORY:
r = 1;
break;
case KVM_CAP_NR_VCPUS:
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v4 RESEND 5/5] KVM: selftests: Enable pre_fault_memory_test for RISC-V
2026-08-15 10:28 [PATCH v4 RESEND 0/5] KVM: riscv: Add KVM_PRE_FAULT_MEMORY support Jinyu Tang
2026-08-15 10:32 ` [PATCH v4 RESEND 2/5] KVM: riscv: Avoid THP adjustment for existing 4K G-stage leaves Jinyu Tang
2026-08-15 10:33 ` [PATCH v4 RESEND 3/5] KVM: riscv: Implement KVM_PRE_FAULT_MEMORY Jinyu Tang
@ 2026-08-15 10:34 ` Jinyu Tang
2 siblings, 0 replies; 4+ messages in thread
From: Jinyu Tang @ 2026-08-15 10:34 UTC (permalink / raw)
To: Anup Patel, Anup Patel, Atish Patra
Cc: kvm, kvm-riscv, linux-riscv, linux-kernel, linux-kselftest,
Paolo Bonzini, Sean Christopherson, Shuah Khan, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Andrew Jones,
Conor Dooley, Yong-Xuan Wang, Nutty Liu, Jinyu Tang
RISC-V now supports KVM_PRE_FAULT_MEMORY, so include the generic
pre_fault_memory_test in the RISC-V KVM selftest build.
The test uses PAGE_SIZE from the architecture processor header. Define
the normal 4K RISC-V selftest page size so the generic test can build
for RISC-V.
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
Signed-off-by: Jinyu Tang <jinyu.tang@linux.dev>
---
tools/testing/selftests/kvm/Makefile.kvm | 1 +
tools/testing/selftests/kvm/include/riscv/processor.h | 3 +++
2 files changed, 4 insertions(+)
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 6fc34e9bf8e1..ac64ac92fd4b 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -225,6 +225,7 @@ TEST_GEN_PROGS_riscv += coalesced_io_test
TEST_GEN_PROGS_riscv += dirty_log_perf_test
TEST_GEN_PROGS_riscv += get-reg-list
TEST_GEN_PROGS_riscv += mmu_stress_test
+TEST_GEN_PROGS_riscv += pre_fault_memory_test
TEST_GEN_PROGS_riscv += rseq_test
TEST_GEN_PROGS_riscv += steal_time
diff --git a/tools/testing/selftests/kvm/include/riscv/processor.h b/tools/testing/selftests/kvm/include/riscv/processor.h
index abde3c71c891..70487c8ed155 100644
--- a/tools/testing/selftests/kvm/include/riscv/processor.h
+++ b/tools/testing/selftests/kvm/include/riscv/processor.h
@@ -12,6 +12,9 @@
#include <asm/vdso/processor.h>
#include "kvm_util.h"
+#define PAGE_SHIFT 12
+#define PAGE_SIZE BIT_ULL(PAGE_SHIFT)
+
#define INSN_OPCODE_MASK 0x007c
#define INSN_OPCODE_SHIFT 2
#define INSN_OPCODE_SYSTEM 28
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-15 10:35 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-15 10:28 [PATCH v4 RESEND 0/5] KVM: riscv: Add KVM_PRE_FAULT_MEMORY support Jinyu Tang
2026-08-15 10:32 ` [PATCH v4 RESEND 2/5] KVM: riscv: Avoid THP adjustment for existing 4K G-stage leaves Jinyu Tang
2026-08-15 10:33 ` [PATCH v4 RESEND 3/5] KVM: riscv: Implement KVM_PRE_FAULT_MEMORY Jinyu Tang
2026-08-15 10:34 ` [PATCH v4 RESEND 5/5] KVM: selftests: Enable pre_fault_memory_test for RISC-V Jinyu Tang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox