Merge tag 'lkmm.2023.04.07a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck...
[linux-block.git] / arch / riscv / mm / tlbflush.c
CommitLineData
95594cb4
CH
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/mm.h>
4#include <linux/smp.h>
31738ede 5#include <linux/sched.h>
95594cb4 6#include <asm/sbi.h>
3f1e7829 7#include <asm/mmu_context.h>
e9210500
SM
8
9static inline void local_flush_tlb_all_asid(unsigned long asid)
10{
11 __asm__ __volatile__ ("sfence.vma x0, %0"
12 :
13 : "r" (asid)
14 : "memory");
15}
16
17static inline void local_flush_tlb_page_asid(unsigned long addr,
18 unsigned long asid)
19{
20 __asm__ __volatile__ ("sfence.vma %0, %1"
21 :
22 : "r" (addr), "r" (asid)
23 : "memory");
24}
95594cb4
CH
25
26void flush_tlb_all(void)
27{
28 sbi_remote_sfence_vma(NULL, 0, -1);
29}
30
70c7605c 31static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
c3b2d670 32 unsigned long size, unsigned long stride)
95594cb4 33{
70c7605c 34 struct cpumask *cmask = mm_cpumask(mm);
31738ede 35 unsigned int cpuid;
3f1e7829 36 bool broadcast;
95594cb4 37
6384423f
AP
38 if (cpumask_empty(cmask))
39 return;
40
31738ede 41 cpuid = get_cpu();
3f1e7829
GR
42 /* check if the tlbflush needs to be sent to other CPUs */
43 broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
44 if (static_branch_unlikely(&use_asid_allocator)) {
9a801afd 45 unsigned long asid = atomic_long_read(&mm->context.id) & asid_mask;
31738ede 46
3f1e7829 47 if (broadcast) {
26fb751c 48 sbi_remote_sfence_vma_asid(cmask, start, size, asid);
3f1e7829
GR
49 } else if (size <= stride) {
50 local_flush_tlb_page_asid(start, asid);
51 } else {
52 local_flush_tlb_all_asid(asid);
53 }
54 } else {
55 if (broadcast) {
26fb751c 56 sbi_remote_sfence_vma(cmask, start, size);
3f1e7829 57 } else if (size <= stride) {
6efb16b1 58 local_flush_tlb_page(start);
3f1e7829 59 } else {
6efb16b1 60 local_flush_tlb_all();
3f1e7829 61 }
31738ede
AP
62 }
63
64 put_cpu();
95594cb4
CH
65}
66
67void flush_tlb_mm(struct mm_struct *mm)
68{
70c7605c 69 __sbi_tlb_flush_range(mm, 0, -1, PAGE_SIZE);
95594cb4
CH
70}
71
72void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
73{
70c7605c 74 __sbi_tlb_flush_range(vma->vm_mm, addr, PAGE_SIZE, PAGE_SIZE);
95594cb4
CH
75}
76
77void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
78 unsigned long end)
79{
70c7605c 80 __sbi_tlb_flush_range(vma->vm_mm, start, end - start, PAGE_SIZE);
95594cb4 81}
e88b3331
NS
82#ifdef CONFIG_TRANSPARENT_HUGEPAGE
83void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
84 unsigned long end)
85{
70c7605c 86 __sbi_tlb_flush_range(vma->vm_mm, start, end - start, PMD_SIZE);
e88b3331
NS
87}
88#endif