diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/tlbflush.h | 11 | ||||
-rw-r--r-- | arch/powerpc/mm/mmu_decl.h | 16 | ||||
-rw-r--r-- | arch/powerpc/mm/tlb_nohash.c | 42 | ||||
-rw-r--r-- | arch/powerpc/mm/tlb_nohash_low.S | 6 |
4 files changed, 56 insertions, 19 deletions
diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h index abbe3419d1dd..d50a380b2b6f 100644 --- a/arch/powerpc/include/asm/tlbflush.h +++ b/arch/powerpc/include/asm/tlbflush.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * - flush_tlb_mm(mm) flushes the specified mm context TLB's | 7 | * - flush_tlb_mm(mm) flushes the specified mm context TLB's |
8 | * - flush_tlb_page(vma, vmaddr) flushes one page | 8 | * - flush_tlb_page(vma, vmaddr) flushes one page |
9 | * - local_flush_tlb_mm(mm) flushes the specified mm context on | 9 | * - local_flush_tlb_mm(mm, full) flushes the specified mm context on |
10 | * the local processor | 10 | * the local processor |
11 | * - local_flush_tlb_page(vma, vmaddr) flushes one page on the local processor | 11 | * - local_flush_tlb_page(vma, vmaddr) flushes one page on the local processor |
12 | * - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB | 12 | * - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB |
@@ -29,7 +29,8 @@ | |||
29 | * specific tlbie's | 29 | * specific tlbie's |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <linux/mm.h> | 32 | struct vm_area_struct; |
33 | struct mm_struct; | ||
33 | 34 | ||
34 | #define MMU_NO_CONTEXT ((unsigned int)-1) | 35 | #define MMU_NO_CONTEXT ((unsigned int)-1) |
35 | 36 | ||
@@ -40,12 +41,18 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); | |||
40 | extern void local_flush_tlb_mm(struct mm_struct *mm); | 41 | extern void local_flush_tlb_mm(struct mm_struct *mm); |
41 | extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); | 42 | extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); |
42 | 43 | ||
44 | extern void __local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, | ||
45 | int tsize, int ind); | ||
46 | |||
43 | #ifdef CONFIG_SMP | 47 | #ifdef CONFIG_SMP |
44 | extern void flush_tlb_mm(struct mm_struct *mm); | 48 | extern void flush_tlb_mm(struct mm_struct *mm); |
45 | extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); | 49 | extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); |
50 | extern void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, | ||
51 | int tsize, int ind); | ||
46 | #else | 52 | #else |
47 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) | 53 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) |
48 | #define flush_tlb_page(vma,addr) local_flush_tlb_page(vma,addr) | 54 | #define flush_tlb_page(vma,addr) local_flush_tlb_page(vma,addr) |
55 | #define __flush_tlb_page(mm,addr,p,i) __local_flush_tlb_page(mm,addr,p,i) | ||
49 | #endif | 56 | #endif |
50 | #define flush_tlb_page_nohash(vma,addr) flush_tlb_page(vma,addr) | 57 | #define flush_tlb_page_nohash(vma,addr) flush_tlb_page(vma,addr) |
51 | 58 | ||
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index d1f9c62dc177..3871dceee2dd 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
@@ -36,21 +36,30 @@ static inline void _tlbil_pid(unsigned int pid) | |||
36 | { | 36 | { |
37 | asm volatile ("sync; tlbia; isync" : : : "memory"); | 37 | asm volatile ("sync; tlbia; isync" : : : "memory"); |
38 | } | 38 | } |
39 | #define _tlbil_pid_noind(pid) _tlbil_pid(pid) | ||
40 | |||
39 | #else /* CONFIG_40x || CONFIG_8xx */ | 41 | #else /* CONFIG_40x || CONFIG_8xx */ |
40 | extern void _tlbil_all(void); | 42 | extern void _tlbil_all(void); |
41 | extern void _tlbil_pid(unsigned int pid); | 43 | extern void _tlbil_pid(unsigned int pid); |
44 | #define _tlbil_pid_noind(pid) _tlbil_pid(pid) | ||
42 | #endif /* !(CONFIG_40x || CONFIG_8xx) */ | 45 | #endif /* !(CONFIG_40x || CONFIG_8xx) */ |
43 | 46 | ||
44 | /* | 47 | /* |
45 | * On 8xx, we directly inline tlbie, on others, it's extern | 48 | * On 8xx, we directly inline tlbie, on others, it's extern |
46 | */ | 49 | */ |
47 | #ifdef CONFIG_8xx | 50 | #ifdef CONFIG_8xx |
48 | static inline void _tlbil_va(unsigned long address, unsigned int pid) | 51 | static inline void _tlbil_va(unsigned long address, unsigned int pid, |
52 | unsigned int tsize, unsigned int ind) | ||
49 | { | 53 | { |
50 | asm volatile ("tlbie %0; sync" : : "r" (address) : "memory"); | 54 | asm volatile ("tlbie %0; sync" : : "r" (address) : "memory"); |
51 | } | 55 | } |
52 | #else /* CONFIG_8xx */ | 56 | #else /* CONFIG_8xx */ |
53 | extern void _tlbil_va(unsigned long address, unsigned int pid); | 57 | extern void __tlbil_va(unsigned long address, unsigned int pid); |
58 | static inline void _tlbil_va(unsigned long address, unsigned int pid, | ||
59 | unsigned int tsize, unsigned int ind) | ||
60 | { | ||
61 | __tlbil_va(address, pid); | ||
62 | } | ||
54 | #endif /* CONIFG_8xx */ | 63 | #endif /* CONIFG_8xx */ |
55 | 64 | ||
56 | /* | 65 | /* |
@@ -58,7 +67,8 @@ extern void _tlbil_va(unsigned long address, unsigned int pid); | |||
58 | * implementation. When that becomes the case, this will be | 67 | * implementation. When that becomes the case, this will be |
59 | * an extern. | 68 | * an extern. |
60 | */ | 69 | */ |
61 | static inline void _tlbivax_bcast(unsigned long address, unsigned int pid) | 70 | static inline void _tlbivax_bcast(unsigned long address, unsigned int pid, |
71 | unsigned int tsize, unsigned int ind) | ||
62 | { | 72 | { |
63 | BUG(); | 73 | BUG(); |
64 | } | 74 | } |
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index d908e75cc3b5..761e8882416f 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
@@ -67,18 +67,24 @@ void local_flush_tlb_mm(struct mm_struct *mm) | |||
67 | } | 67 | } |
68 | EXPORT_SYMBOL(local_flush_tlb_mm); | 68 | EXPORT_SYMBOL(local_flush_tlb_mm); |
69 | 69 | ||
70 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) | 70 | void __local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, |
71 | int tsize, int ind) | ||
71 | { | 72 | { |
72 | unsigned int pid; | 73 | unsigned int pid; |
73 | 74 | ||
74 | preempt_disable(); | 75 | preempt_disable(); |
75 | pid = vma ? vma->vm_mm->context.id : 0; | 76 | pid = mm ? mm->context.id : 0; |
76 | if (pid != MMU_NO_CONTEXT) | 77 | if (pid != MMU_NO_CONTEXT) |
77 | _tlbil_va(vmaddr, pid); | 78 | _tlbil_va(vmaddr, pid, tsize, ind); |
78 | preempt_enable(); | 79 | preempt_enable(); |
79 | } | 80 | } |
80 | EXPORT_SYMBOL(local_flush_tlb_page); | ||
81 | 81 | ||
82 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) | ||
83 | { | ||
84 | __local_flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, | ||
85 | 0 /* tsize unused for now */, 0); | ||
86 | } | ||
87 | EXPORT_SYMBOL(local_flush_tlb_page); | ||
82 | 88 | ||
83 | /* | 89 | /* |
84 | * And here are the SMP non-local implementations | 90 | * And here are the SMP non-local implementations |
@@ -96,6 +102,8 @@ static int mm_is_core_local(struct mm_struct *mm) | |||
96 | struct tlb_flush_param { | 102 | struct tlb_flush_param { |
97 | unsigned long addr; | 103 | unsigned long addr; |
98 | unsigned int pid; | 104 | unsigned int pid; |
105 | unsigned int tsize; | ||
106 | unsigned int ind; | ||
99 | }; | 107 | }; |
100 | 108 | ||
101 | static void do_flush_tlb_mm_ipi(void *param) | 109 | static void do_flush_tlb_mm_ipi(void *param) |
@@ -109,7 +117,7 @@ static void do_flush_tlb_page_ipi(void *param) | |||
109 | { | 117 | { |
110 | struct tlb_flush_param *p = param; | 118 | struct tlb_flush_param *p = param; |
111 | 119 | ||
112 | _tlbil_va(p->addr, p->pid); | 120 | _tlbil_va(p->addr, p->pid, p->tsize, p->ind); |
113 | } | 121 | } |
114 | 122 | ||
115 | 123 | ||
@@ -149,37 +157,49 @@ void flush_tlb_mm(struct mm_struct *mm) | |||
149 | } | 157 | } |
150 | EXPORT_SYMBOL(flush_tlb_mm); | 158 | EXPORT_SYMBOL(flush_tlb_mm); |
151 | 159 | ||
152 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) | 160 | void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, |
161 | int tsize, int ind) | ||
153 | { | 162 | { |
154 | struct cpumask *cpu_mask; | 163 | struct cpumask *cpu_mask; |
155 | unsigned int pid; | 164 | unsigned int pid; |
156 | 165 | ||
157 | preempt_disable(); | 166 | preempt_disable(); |
158 | pid = vma ? vma->vm_mm->context.id : 0; | 167 | pid = mm ? mm->context.id : 0; |
159 | if (unlikely(pid == MMU_NO_CONTEXT)) | 168 | if (unlikely(pid == MMU_NO_CONTEXT)) |
160 | goto bail; | 169 | goto bail; |
161 | cpu_mask = mm_cpumask(vma->vm_mm); | 170 | cpu_mask = mm_cpumask(mm); |
162 | if (!mm_is_core_local(mm)) { | 171 | if (!mm_is_core_local(mm)) { |
163 | /* If broadcast tlbivax is supported, use it */ | 172 | /* If broadcast tlbivax is supported, use it */ |
164 | if (mmu_has_feature(MMU_FTR_USE_TLBIVAX_BCAST)) { | 173 | if (mmu_has_feature(MMU_FTR_USE_TLBIVAX_BCAST)) { |
165 | int lock = mmu_has_feature(MMU_FTR_LOCK_BCAST_INVAL); | 174 | int lock = mmu_has_feature(MMU_FTR_LOCK_BCAST_INVAL); |
166 | if (lock) | 175 | if (lock) |
167 | spin_lock(&tlbivax_lock); | 176 | spin_lock(&tlbivax_lock); |
168 | _tlbivax_bcast(vmaddr, pid); | 177 | _tlbivax_bcast(vmaddr, pid, tsize, ind); |
169 | if (lock) | 178 | if (lock) |
170 | spin_unlock(&tlbivax_lock); | 179 | spin_unlock(&tlbivax_lock); |
171 | goto bail; | 180 | goto bail; |
172 | } else { | 181 | } else { |
173 | struct tlb_flush_param p = { .pid = pid, .addr = vmaddr }; | 182 | struct tlb_flush_param p = { |
183 | .pid = pid, | ||
184 | .addr = vmaddr, | ||
185 | .tsize = tsize, | ||
186 | .ind = ind, | ||
187 | }; | ||
174 | /* Ignores smp_processor_id() even if set in cpu_mask */ | 188 | /* Ignores smp_processor_id() even if set in cpu_mask */ |
175 | smp_call_function_many(cpu_mask, | 189 | smp_call_function_many(cpu_mask, |
176 | do_flush_tlb_page_ipi, &p, 1); | 190 | do_flush_tlb_page_ipi, &p, 1); |
177 | } | 191 | } |
178 | } | 192 | } |
179 | _tlbil_va(vmaddr, pid); | 193 | _tlbil_va(vmaddr, pid, tsize, ind); |
180 | bail: | 194 | bail: |
181 | preempt_enable(); | 195 | preempt_enable(); |
182 | } | 196 | } |
197 | |||
198 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) | ||
199 | { | ||
200 | __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, | ||
201 | 0 /* tsize unused for now */, 0); | ||
202 | } | ||
183 | EXPORT_SYMBOL(flush_tlb_page); | 203 | EXPORT_SYMBOL(flush_tlb_page); |
184 | 204 | ||
185 | #endif /* CONFIG_SMP */ | 205 | #endif /* CONFIG_SMP */ |
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S index 3037911279b1..c7d89a0adba2 100644 --- a/arch/powerpc/mm/tlb_nohash_low.S +++ b/arch/powerpc/mm/tlb_nohash_low.S | |||
@@ -39,7 +39,7 @@ | |||
39 | /* | 39 | /* |
40 | * 40x implementation needs only tlbil_va | 40 | * 40x implementation needs only tlbil_va |
41 | */ | 41 | */ |
42 | _GLOBAL(_tlbil_va) | 42 | _GLOBAL(__tlbil_va) |
43 | /* We run the search with interrupts disabled because we have to change | 43 | /* We run the search with interrupts disabled because we have to change |
44 | * the PID and I don't want to preempt when that happens. | 44 | * the PID and I don't want to preempt when that happens. |
45 | */ | 45 | */ |
@@ -71,7 +71,7 @@ _GLOBAL(_tlbil_va) | |||
71 | * 440 implementation uses tlbsx/we for tlbil_va and a full sweep | 71 | * 440 implementation uses tlbsx/we for tlbil_va and a full sweep |
72 | * of the TLB for everything else. | 72 | * of the TLB for everything else. |
73 | */ | 73 | */ |
74 | _GLOBAL(_tlbil_va) | 74 | _GLOBAL(__tlbil_va) |
75 | mfspr r5,SPRN_MMUCR | 75 | mfspr r5,SPRN_MMUCR |
76 | rlwimi r5,r4,0,24,31 /* Set TID */ | 76 | rlwimi r5,r4,0,24,31 /* Set TID */ |
77 | 77 | ||
@@ -170,7 +170,7 @@ ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_USE_TLBILX) | |||
170 | * Flush MMU TLB for a particular address, but only on the local processor | 170 | * Flush MMU TLB for a particular address, but only on the local processor |
171 | * (no broadcast) | 171 | * (no broadcast) |
172 | */ | 172 | */ |
173 | _GLOBAL(_tlbil_va) | 173 | _GLOBAL(__tlbil_va) |
174 | mfmsr r10 | 174 | mfmsr r10 |
175 | wrteei 0 | 175 | wrteei 0 |
176 | slwi r4,r4,16 | 176 | slwi r4,r4,16 |