]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
nios2: force update_mmu_cache on spurious tlb-permission--related pagefaults
authorSimon Schuster <schuster.simon@siemens-energy.com>
Thu, 27 Mar 2025 13:54:22 +0000 (14:54 +0100)
committerDinh Nguyen <dinguyen@kernel.org>
Thu, 24 Apr 2025 22:18:40 +0000 (17:18 -0500)
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 <schuster.simon@siemens-energy.com>
Signed-off-by: Andreas Oetken <andreas.oetken@siemens-energy.com>
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
arch/nios2/include/asm/pgtable.h

index eab87c6beacb5a46607e2f4fd81e8cc18112d1af..e5d64c84aadf7d35308f7ed30941827e48c1b215 100644 (file)
@@ -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 */