[PATCH 3/5] KVM: riscv: Add a G-stage PTE cmpxchg helper
Jinyu Tang
tjytimi at 163.com
Sun May 17 08:34:25 PDT 2026
Permission-only G-stage PTE updates can run in parallel once they are
moved to the read side of mmu_lock. Plain set_pte() is not enough for
that case because another CPU may update the same PTE first.
x86 handles the same class of SPTE races with cmpxchg-based updates in
its fast page fault and TDP MMU paths. Add a small RISC-V helper for
atomic G-stage PTE updates. The helper reports contention to the caller
and flushes the target range only when the PTE value actually changes.
Signed-off-by: Jinyu Tang <tjytimi at 163.com>
---
arch/riscv/include/asm/kvm_gstage.h | 4 ++++
arch/riscv/kvm/gstage.c | 14 ++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/arch/riscv/include/asm/kvm_gstage.h b/arch/riscv/include/asm/kvm_gstage.h
index 9c908432b..afe80e4bf 100644
--- a/arch/riscv/include/asm/kvm_gstage.h
+++ b/arch/riscv/include/asm/kvm_gstage.h
@@ -54,6 +54,10 @@ int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,
struct kvm_mmu_memory_cache *pcache,
const struct kvm_gstage_mapping *map);
+bool kvm_riscv_gstage_try_update_pte(struct kvm_gstage *gstage, u32 level,
+ gpa_t addr, pte_t *ptep,
+ pte_t old_pte, pte_t new_pte);
+
int kvm_riscv_gstage_map_page(struct kvm_gstage *gstage,
struct kvm_mmu_memory_cache *pcache,
gpa_t gpa, phys_addr_t hpa, unsigned long page_size,
diff --git a/arch/riscv/kvm/gstage.c b/arch/riscv/kvm/gstage.c
index 6f934cb4a..d70584b9e 100644
--- a/arch/riscv/kvm/gstage.c
+++ b/arch/riscv/kvm/gstage.c
@@ -123,6 +123,20 @@ static void gstage_tlb_flush(struct kvm_gstage *gstage, u32 level, gpa_t addr)
gstage->vmid);
}
+bool kvm_riscv_gstage_try_update_pte(struct kvm_gstage *gstage, u32 level,
+ gpa_t addr, pte_t *ptep,
+ pte_t old_pte, pte_t new_pte)
+{
+ if (cmpxchg(&ptep->pte, pte_val(old_pte), pte_val(new_pte)) !=
+ pte_val(old_pte))
+ return false;
+
+ if (pte_val(old_pte) != pte_val(new_pte))
+ gstage_tlb_flush(gstage, level, addr);
+
+ return true;
+}
+
int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,
struct kvm_mmu_memory_cache *pcache,
const struct kvm_gstage_mapping *map)
--
2.43.0
More information about the linux-riscv
mailing list