1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ALPHA_TLBFLUSH_H 3 #define _ALPHA_TLBFLUSH_H 4 5 #include <linux/mm.h> 6 #include <linux/sched.h> 7 #include <asm/compiler.h> 8 9 #ifndef __EXTERN_INLINE 10 #define __EXTERN_INLINE extern inline 11 #define __MMU_EXTERN_INLINE 12 #endif 13 14 extern void __load_new_mm_context(struct mm_struct *); 15 16 17 __EXTERN_INLINE void 18 ev5_flush_tlb_current(struct mm_struct *mm) 19 { 20 __load_new_mm_context(mm); 21 } 22 23 /* Flush just one page in the current TLB set. We need to be very 24 careful about the icache here, there is no way to invalidate a 25 specific icache page. */ 26 27 __EXTERN_INLINE void 28 ev5_flush_tlb_current_page(struct mm_struct * mm, 29 struct vm_area_struct *vma, 30 unsigned long addr) 31 { 32 if (vma->vm_flags & VM_EXEC) 33 __load_new_mm_context(mm); 34 else 35 tbi(2, addr); 36 } 37 38 39 #define flush_tlb_current ev5_flush_tlb_current 40 #define flush_tlb_current_page ev5_flush_tlb_current_page 41 42 #ifdef __MMU_EXTERN_INLINE 43 #undef __EXTERN_INLINE 44 #undef __MMU_EXTERN_INLINE 45 #endif 46 47 /* Flush current user mapping. */ 48 static inline void 49 flush_tlb(void) 50 { 51 flush_tlb_current(current->active_mm); 52 } 53 54 /* Flush someone else's user mapping. */ 55 static inline void 56 flush_tlb_other(struct mm_struct *mm) 57 { 58 unsigned long *mmc = &mm->context[smp_processor_id()]; 59 /* Check it's not zero first to avoid cacheline ping pong 60 when possible. */ 61 62 if (READ_ONCE(*mmc)) 63 WRITE_ONCE(*mmc, 0); 64 } 65 66 #ifndef CONFIG_SMP 67 /* Flush everything (kernel mapping may also have changed 68 due to vmalloc/vfree). */ 69 static inline void flush_tlb_all(void) 70 { 71 tbia(); 72 } 73 74 /* Flush a specified user mapping. */ 75 static inline void 76 flush_tlb_mm(struct mm_struct *mm) 77 { 78 if (mm == current->active_mm) 79 flush_tlb_current(mm); 80 else 81 flush_tlb_other(mm); 82 } 83 84 /* Page-granular tlb flush. */ 85 static inline void 86 flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) 87 { 88 struct mm_struct *mm = vma->vm_mm; 89 90 /* A targeted tbi() needs a thread of MM to be current. */ 91 if (mm == current->mm) 92 flush_tlb_current_page(mm, vma, addr); 93 else 94 flush_tlb_other(mm); 95 } 96 97 /* Flush a specified range of user mapping. On the Alpha we flush 98 the whole user tlb. */ 99 static inline void 100 flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 101 unsigned long end) 102 { 103 flush_tlb_mm(vma->vm_mm); 104 } 105 106 #else /* CONFIG_SMP */ 107 108 extern void flush_tlb_all(void); 109 extern void flush_tlb_mm(struct mm_struct *); 110 extern void flush_tlb_page(struct vm_area_struct *, unsigned long); 111 extern void flush_tlb_range(struct vm_area_struct *, unsigned long, 112 unsigned long); 113 114 #endif /* CONFIG_SMP */ 115 116 static inline void flush_tlb_kernel_range(unsigned long start, 117 unsigned long end) 118 { 119 flush_tlb_all(); 120 } 121 122 #endif /* _ALPHA_TLBFLUSH_H */ 123