summaryrefslogtreecommitdiffstats
path: root/arch/riscv/mm/context.c
diff options
context:
space:
mode:
authorPalmer Dabbelt <palmer@rivosinc.com>2023-03-10 00:22:05 +0100
committerPalmer Dabbelt <palmer@rivosinc.com>2023-03-10 00:22:05 +0100
commit9b7fef255c80db8fc33fc06f2ad6d8e3ced1389b (patch)
tree1502eff3eb6bb0d198553344e0dac48d64da3cd1 /arch/riscv/mm/context.c
parentRISC-V: Don't check text_mutex during stop_machine (diff)
parentriscv: asid: Fixup stale TLB entry cause application crash (diff)
downloadlinux-9b7fef255c80db8fc33fc06f2ad6d8e3ced1389b.tar.xz
linux-9b7fef255c80db8fc33fc06f2ad6d8e3ced1389b.zip
Merge patch series "riscv: asid: switch to alternative way to fix stale TLB entries"
Sergey Matyukevich <geomatsi@gmail.com> says: Some time ago two different patches have been posted to fix stale TLB entries that caused applications crashes. The patch [0] suggested 'aggregating' mm_cpumask, i.e. current cpu is not cleared for the switched-out task in switch_mm function. For additional explanations see the commit message by Guo Ren. The same approach is used by arc architecture, so another good comment is for switch_mm in arch/arc/include/asm/mmu_context.h. The patch [1] attempted to reduce the number of TLB flushes by deferring (and possibly avoiding) them for CPUs not running the task. Patch [1] has been merged. However we already have two bug reports from different vendors. So apparently something is missing in the approach suggested in [1]. In both cases the patch [0] fixed the issue. This patch series reverts [1] and replaces it by [0]. [0] https://lore.kernel.org/linux-riscv/20221111075902.798571-1-guoren@kernel.org/ [1] https://lore.kernel.org/linux-riscv/20220829205219.283543-1-geomatsi@gmail.com/ * b4-shazam-merge: riscv: asid: Fixup stale TLB entry cause application crash Revert "riscv: mm: notify remote harts about mmu cache updates" Link: https://lore.kernel.org/r/20230226150137.1919750-1-geomatsi@gmail.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Diffstat (limited to 'arch/riscv/mm/context.c')
-rw-r--r--arch/riscv/mm/context.c40
1 files changed, 20 insertions, 20 deletions
diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c
index 80ce9caba8d2..0f784e3d307b 100644
--- a/arch/riscv/mm/context.c
+++ b/arch/riscv/mm/context.c
@@ -196,16 +196,6 @@ switch_mm_fast:
if (need_flush_tlb)
local_flush_tlb_all();
-#ifdef CONFIG_SMP
- else {
- cpumask_t *mask = &mm->context.tlb_stale_mask;
-
- if (cpumask_test_cpu(cpu, mask)) {
- cpumask_clear_cpu(cpu, mask);
- local_flush_tlb_all_asid(cntx & asid_mask);
- }
- }
-#endif
}
static void set_mm_noasid(struct mm_struct *mm)
@@ -215,12 +205,24 @@ static void set_mm_noasid(struct mm_struct *mm)
local_flush_tlb_all();
}
-static inline void set_mm(struct mm_struct *mm, unsigned int cpu)
+static inline void set_mm(struct mm_struct *prev,
+ struct mm_struct *next, unsigned int cpu)
{
- if (static_branch_unlikely(&use_asid_allocator))
- set_mm_asid(mm, cpu);
- else
- set_mm_noasid(mm);
+ /*
+ * The mm_cpumask indicates which harts' TLBs contain the virtual
+ * address mapping of the mm. Compared to noasid, using asid
+ * can't guarantee that stale TLB entries are invalidated because
+ * the asid mechanism wouldn't flush TLB for every switch_mm for
+ * performance. So when using asid, keep all CPUs footmarks in
+ * cpumask() until mm reset.
+ */
+ cpumask_set_cpu(cpu, mm_cpumask(next));
+ if (static_branch_unlikely(&use_asid_allocator)) {
+ set_mm_asid(next, cpu);
+ } else {
+ cpumask_clear_cpu(cpu, mm_cpumask(prev));
+ set_mm_noasid(next);
+ }
}
static int __init asids_init(void)
@@ -274,7 +276,8 @@ static int __init asids_init(void)
}
early_initcall(asids_init);
#else
-static inline void set_mm(struct mm_struct *mm, unsigned int cpu)
+static inline void set_mm(struct mm_struct *prev,
+ struct mm_struct *next, unsigned int cpu)
{
/* Nothing to do here when there is no MMU */
}
@@ -327,10 +330,7 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next,
*/
cpu = smp_processor_id();
- cpumask_clear_cpu(cpu, mm_cpumask(prev));
- cpumask_set_cpu(cpu, mm_cpumask(next));
-
- set_mm(next, cpu);
+ set_mm(prev, next, cpu);
flush_icache_deferred(next, cpu);
}