xref: /openbmc/linux/arch/riscv/mm/tlbflush.c (revision 95298d63)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/mm.h>
4 #include <linux/smp.h>
5 #include <linux/sched.h>
6 #include <asm/sbi.h>
7 
8 void flush_tlb_all(void)
9 {
10 	sbi_remote_sfence_vma(NULL, 0, -1);
11 }
12 
13 /*
14  * This function must not be called with cmask being null.
15  * Kernel may panic if cmask is NULL.
16  */
17 static void __sbi_tlb_flush_range(struct cpumask *cmask, unsigned long start,
18 				  unsigned long size)
19 {
20 	struct cpumask hmask;
21 	unsigned int cpuid;
22 
23 	if (cpumask_empty(cmask))
24 		return;
25 
26 	cpuid = get_cpu();
27 
28 	if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) {
29 		/* local cpu is the only cpu present in cpumask */
30 		if (size <= PAGE_SIZE)
31 			local_flush_tlb_page(start);
32 		else
33 			local_flush_tlb_all();
34 	} else {
35 		riscv_cpuid_to_hartid_mask(cmask, &hmask);
36 		sbi_remote_sfence_vma(cpumask_bits(&hmask), start, size);
37 	}
38 
39 	put_cpu();
40 }
41 
42 void flush_tlb_mm(struct mm_struct *mm)
43 {
44 	__sbi_tlb_flush_range(mm_cpumask(mm), 0, -1);
45 }
46 
47 void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
48 {
49 	__sbi_tlb_flush_range(mm_cpumask(vma->vm_mm), addr, PAGE_SIZE);
50 }
51 
52 void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
53 		     unsigned long end)
54 {
55 	__sbi_tlb_flush_range(mm_cpumask(vma->vm_mm), start, end - start);
56 }
57