From: Simon Schuster Date: Thu, 27 Mar 2025 13:54:22 +0000 (+0100) Subject: nios2: force update_mmu_cache on spurious tlb-permission--related pagefaults X-Git-Tag: v6.16-rc1~134^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2d8a3179ea035f9341b6a73e5ba4029fc67e983d;p=thirdparty%2Flinux.git nios2: force update_mmu_cache on spurious tlb-permission--related pagefaults NIOS2 uses a software-managed TLB for virtual address translation. To flush a cache line, the original mapping is replaced by one to physical address 0x0 with no permissions (rwx mapped to 0) set. This can lead to TLB-permission--related traps when such a nominally flushed entry is encountered as a mapping for an otherwise valid virtual address within a process (e.g. due to an MMU-PID-namespace rollover that previously flushed the complete TLB including entries of existing, running processes). The default ptep_set_access_flags implementation from mm/pgtable-generic.c only forces a TLB-update when the page-table entry has changed within the page table: /* * [...] We return whether the PTE actually changed, which in turn * instructs the caller to do things like update__mmu_cache. [...] */ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, pte_t *ptep, pte_t entry, int dirty) { int changed = !pte_same(*ptep, entry); if (changed) { set_pte_at(vma->vm_mm, address, ptep, entry); flush_tlb_fix_spurious_fault(vma, address); } return changed; } However, no cross-referencing with the TLB-state occurs, so the flushing-induced pseudo entries that are responsible for the pagefault in the first place are never pre-empted from TLB on this code path. This commit fixes this behaviour by always requesting a TLB-update in this part of the pagefault handling, fixing spurious page-faults on the way. The handling is a straightforward port of the logic from the MIPS architecture via an arch-specific ptep_set_access_flags function ported from arch/mips/include/asm/pgtable.h. Signed-off-by: Simon Schuster Signed-off-by: Andreas Oetken Signed-off-by: Dinh Nguyen --- diff --git a/arch/nios2/include/asm/pgtable.h b/arch/nios2/include/asm/pgtable.h index eab87c6beacb5..e5d64c84aadf7 100644 --- a/arch/nios2/include/asm/pgtable.h +++ b/arch/nios2/include/asm/pgtable.h @@ -291,4 +291,20 @@ void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, #define update_mmu_cache(vma, addr, ptep) \ update_mmu_cache_range(NULL, vma, addr, ptep, 1) +static inline int pte_same(pte_t pte_a, pte_t pte_b); + +#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS +static inline int ptep_set_access_flags(struct vm_area_struct *vma, + unsigned long address, pte_t *ptep, + pte_t entry, int dirty) +{ + if (!pte_same(*ptep, entry)) + set_ptes(vma->vm_mm, address, ptep, entry, 1); + /* + * update_mmu_cache will unconditionally execute, handling both + * the case that the PTE changed and the spurious fault case. + */ + return true; +} + #endif /* _ASM_NIOS2_PGTABLE_H */