diff options
author | Paul Walmsley <paul.walmsley@sifive.com> | 2019-11-22 18:58:32 -0800 |
---|---|---|
committer | Paul Walmsley <paul.walmsley@sifive.com> | 2019-11-22 18:58:32 -0800 |
commit | e8cad25b7e8ac8a1ecd7d7243cbea9cfa7049bee (patch) | |
tree | fd9261b2ee8c1e7a2ea509f8042f76eafb39210c | |
parent | 9acfd6f5387dbded57a2d8e9f8480ebbbc3b03c6 (diff) | |
parent | 6efb16b1d5514865d0f7a01910648568ad3225d8 (diff) |
Merge branch 'next/tlb-opt' into for-next
-rw-r--r-- | arch/riscv/mm/tlbflush.c | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 24cd33d2c48f..720b443c4528 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -2,6 +2,7 @@ #include <linux/mm.h> #include <linux/smp.h> +#include <linux/sched.h> #include <asm/sbi.h> void flush_tlb_all(void) @@ -9,13 +10,33 @@ void flush_tlb_all(void) sbi_remote_sfence_vma(NULL, 0, -1); } +/* + * This function must not be called with cmask being null. + * Kernel may panic if cmask is NULL. + */ static void __sbi_tlb_flush_range(struct cpumask *cmask, unsigned long start, unsigned long size) { struct cpumask hmask; + unsigned int cpuid; - riscv_cpuid_to_hartid_mask(cmask, &hmask); - sbi_remote_sfence_vma(hmask.bits, start, size); + if (cpumask_empty(cmask)) + return; + + cpuid = get_cpu(); + + if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) { + /* local cpu is the only cpu present in cpumask */ + if (size <= PAGE_SIZE) + local_flush_tlb_page(start); + else + local_flush_tlb_all(); + } else { + riscv_cpuid_to_hartid_mask(cmask, &hmask); + sbi_remote_sfence_vma(cpumask_bits(&hmask), start, size); + } + + put_cpu(); } void flush_tlb_mm(struct mm_struct *mm) |