Skip to content

Commit 7a21b2e

Browse files
Alexandre Ghitipalmer-dabbelt
authored andcommitted
riscv: Stop emitting preventive sfence.vma for new userspace mappings with Svvptc
The preventive sfence.vma were emitted because new mappings must be made visible to the page table walker but Svvptc guarantees that it will happen within a bounded timeframe, so no need to sfence.vma for the uarchs that implement this extension, we will then take gratuitous (but very unlikely) page faults, similarly to x86 and arm64. This allows to drastically reduce the number of sfence.vma emitted: * Ubuntu boot to login: Before: ~630k sfence.vma After: ~200k sfence.vma * ltp - mmapstress01 Before: ~45k After: ~6.3k * lmbench - lat_pagefault Before: ~665k After: 832 (!) * lmbench - lat_mmap Before: ~546k After: 718 (!) Signed-off-by: Alexandre Ghiti <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 503638e commit 7a21b2e

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

arch/riscv/include/asm/pgtable.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
476476
struct vm_area_struct *vma, unsigned long address,
477477
pte_t *ptep, unsigned int nr)
478478
{
479+
asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1)
480+
: : : : svvptc);
481+
479482
/*
480483
* The kernel assumes that TLBs don't cache invalid entries, but
481484
* in RISC-V, SFENCE.VMA specifies an ordering constraint, not a
@@ -485,12 +488,23 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
485488
*/
486489
while (nr--)
487490
local_flush_tlb_page(address + nr * PAGE_SIZE);
491+
492+
svvptc:;
493+
/*
494+
* Svvptc guarantees that the new valid pte will be visible within
495+
* a bounded timeframe, so when the uarch does not cache invalid
496+
* entries, we don't have to do anything.
497+
*/
488498
}
489499
#define update_mmu_cache(vma, addr, ptep) \
490500
update_mmu_cache_range(NULL, vma, addr, ptep, 1)
491501

492502
#define __HAVE_ARCH_UPDATE_MMU_TLB
493-
#define update_mmu_tlb update_mmu_cache
503+
static inline void update_mmu_tlb(struct vm_area_struct *vma,
504+
unsigned long address, pte_t *ptep)
505+
{
506+
flush_tlb_range(vma, address, address + PAGE_SIZE);
507+
}
494508

495509
static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
496510
unsigned long address, pmd_t *pmdp)

arch/riscv/mm/pgtable.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,26 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
99
unsigned long address, pte_t *ptep,
1010
pte_t entry, int dirty)
1111
{
12+
asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1)
13+
: : : : svvptc);
14+
1215
if (!pte_same(ptep_get(ptep), entry))
1316
__set_pte_at(vma->vm_mm, ptep, entry);
1417
/*
1518
* update_mmu_cache will unconditionally execute, handling both
1619
* the case that the PTE changed and the spurious fault case.
1720
*/
1821
return true;
22+
23+
svvptc:
24+
if (!pte_same(ptep_get(ptep), entry)) {
25+
__set_pte_at(vma->vm_mm, ptep, entry);
26+
/* Here only not svadu is impacted */
27+
flush_tlb_page(vma, address);
28+
return true;
29+
}
30+
31+
return false;
1932
}
2033

2134
int ptep_test_and_clear_young(struct vm_area_struct *vma,

0 commit comments

Comments
 (0)