riscv: mm: Apply Svinval in update_mmu_cache()

Use Svinval in update_mmu_cache_range() when the extension is available.

Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
Link: https://patch.msgid.link/20260715132009.10634-3-luxu.kernel@bytedance.com
Tested-by: Klara Modin <klarasmodin@gmail.com>
Signed-off-by: Paul Walmsley <pjw@kernel.org>
This commit is contained in:
Xu Lu 2026-08-07 19:24:29 -06:00 committed by Paul Walmsley
parent af842aea58
commit 905be00304
3 changed files with 26 additions and 18 deletions

View File

@ -578,6 +578,14 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC))
return;
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)) {
local_sfence_w_inval();
while (nr--)
local_sinval_vma(address + nr * PAGE_SIZE, asid);
local_sfence_inval_ir();
return;
}
/*
* The kernel assumes that TLBs don't cache invalid entries, but
* in RISC-V, SFENCE.VMA specifies an ordering constraint, not a

View File

@ -20,6 +20,24 @@ static inline unsigned long get_mm_asid(struct mm_struct *mm)
return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
}
static inline void local_sfence_inval_ir(void)
{
asm volatile(SFENCE_INVAL_IR() ::: "memory");
}
static inline void local_sfence_w_inval(void)
{
asm volatile(SFENCE_W_INVAL() ::: "memory");
}
static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
{
if (asid != FLUSH_TLB_NO_ASID)
asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
else
asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
}
static inline void local_flush_tlb_all(void)
{
__asm__ __volatile__ ("sfence.vma" : : : "memory");

View File

@ -11,24 +11,6 @@
#define has_svinval() riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
static inline void local_sfence_inval_ir(void)
{
asm volatile(SFENCE_INVAL_IR() ::: "memory");
}
static inline void local_sfence_w_inval(void)
{
asm volatile(SFENCE_W_INVAL() ::: "memory");
}
static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
{
if (asid != FLUSH_TLB_NO_ASID)
asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
else
asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
}
/*
* Flush entire TLB if number of entries to be flushed is greater
* than the threshold below.