diff options
Diffstat (limited to 'arch/mips/mm/tlb-sb1.c')
-rw-r--r-- | arch/mips/mm/tlb-sb1.c | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/arch/mips/mm/tlb-sb1.c b/arch/mips/mm/tlb-sb1.c index 6256cafcf3a2..bba7130e7547 100644 --- a/arch/mips/mm/tlb-sb1.c +++ b/arch/mips/mm/tlb-sb1.c | |||
@@ -94,7 +94,7 @@ void local_flush_tlb_all(void) | |||
94 | 94 | ||
95 | local_irq_save(flags); | 95 | local_irq_save(flags); |
96 | /* Save old context and create impossible VPN2 value */ | 96 | /* Save old context and create impossible VPN2 value */ |
97 | old_ctx = read_c0_entryhi() & ASID_MASK; | 97 | old_ctx = read_c0_entryhi(); |
98 | write_c0_entrylo0(0); | 98 | write_c0_entrylo0(0); |
99 | write_c0_entrylo1(0); | 99 | write_c0_entrylo1(0); |
100 | 100 | ||
@@ -144,17 +144,17 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
144 | unsigned long end) | 144 | unsigned long end) |
145 | { | 145 | { |
146 | struct mm_struct *mm = vma->vm_mm; | 146 | struct mm_struct *mm = vma->vm_mm; |
147 | unsigned long flags; | 147 | int cpu = smp_processor_id(); |
148 | int cpu; | ||
149 | 148 | ||
150 | local_irq_save(flags); | ||
151 | cpu = smp_processor_id(); | ||
152 | if (cpu_context(cpu, mm) != 0) { | 149 | if (cpu_context(cpu, mm) != 0) { |
150 | unsigned long flags; | ||
153 | int size; | 151 | int size; |
152 | |||
154 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 153 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; |
155 | size = (size + 1) >> 1; | 154 | size = (size + 1) >> 1; |
155 | local_irq_save(flags); | ||
156 | if (size <= (current_cpu_data.tlbsize/2)) { | 156 | if (size <= (current_cpu_data.tlbsize/2)) { |
157 | int oldpid = read_c0_entryhi() & ASID_MASK; | 157 | int oldpid = read_c0_entryhi(); |
158 | int newpid = cpu_asid(cpu, mm); | 158 | int newpid = cpu_asid(cpu, mm); |
159 | 159 | ||
160 | start &= (PAGE_MASK << 1); | 160 | start &= (PAGE_MASK << 1); |
@@ -169,17 +169,17 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
169 | idx = read_c0_index(); | 169 | idx = read_c0_index(); |
170 | write_c0_entrylo0(0); | 170 | write_c0_entrylo0(0); |
171 | write_c0_entrylo1(0); | 171 | write_c0_entrylo1(0); |
172 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); | ||
173 | if (idx < 0) | 172 | if (idx < 0) |
174 | continue; | 173 | continue; |
174 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); | ||
175 | tlb_write_indexed(); | 175 | tlb_write_indexed(); |
176 | } | 176 | } |
177 | write_c0_entryhi(oldpid); | 177 | write_c0_entryhi(oldpid); |
178 | } else { | 178 | } else { |
179 | drop_mmu_context(mm, cpu); | 179 | drop_mmu_context(mm, cpu); |
180 | } | 180 | } |
181 | local_irq_restore(flags); | ||
181 | } | 182 | } |
182 | local_irq_restore(flags); | ||
183 | } | 183 | } |
184 | 184 | ||
185 | void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | 185 | void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) |
@@ -189,7 +189,6 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
189 | 189 | ||
190 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 190 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; |
191 | size = (size + 1) >> 1; | 191 | size = (size + 1) >> 1; |
192 | |||
193 | local_irq_save(flags); | 192 | local_irq_save(flags); |
194 | if (size <= (current_cpu_data.tlbsize/2)) { | 193 | if (size <= (current_cpu_data.tlbsize/2)) { |
195 | int pid = read_c0_entryhi(); | 194 | int pid = read_c0_entryhi(); |
@@ -207,9 +206,9 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
207 | idx = read_c0_index(); | 206 | idx = read_c0_index(); |
208 | write_c0_entrylo0(0); | 207 | write_c0_entrylo0(0); |
209 | write_c0_entrylo1(0); | 208 | write_c0_entrylo1(0); |
210 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); | ||
211 | if (idx < 0) | 209 | if (idx < 0) |
212 | continue; | 210 | continue; |
211 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); | ||
213 | tlb_write_indexed(); | 212 | tlb_write_indexed(); |
214 | } | 213 | } |
215 | write_c0_entryhi(pid); | 214 | write_c0_entryhi(pid); |
@@ -221,15 +220,16 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
221 | 220 | ||
222 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | 221 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) |
223 | { | 222 | { |
224 | unsigned long flags; | ||
225 | int cpu = smp_processor_id(); | 223 | int cpu = smp_processor_id(); |
226 | 224 | ||
227 | local_irq_save(flags); | ||
228 | if (cpu_context(cpu, vma->vm_mm) != 0) { | 225 | if (cpu_context(cpu, vma->vm_mm) != 0) { |
226 | unsigned long flags; | ||
229 | int oldpid, newpid, idx; | 227 | int oldpid, newpid, idx; |
228 | |||
230 | newpid = cpu_asid(cpu, vma->vm_mm); | 229 | newpid = cpu_asid(cpu, vma->vm_mm); |
231 | page &= (PAGE_MASK << 1); | 230 | page &= (PAGE_MASK << 1); |
232 | oldpid = read_c0_entryhi() & ASID_MASK; | 231 | local_irq_save(flags); |
232 | oldpid = read_c0_entryhi(); | ||
233 | write_c0_entryhi(page | newpid); | 233 | write_c0_entryhi(page | newpid); |
234 | tlb_probe(); | 234 | tlb_probe(); |
235 | idx = read_c0_index(); | 235 | idx = read_c0_index(); |
@@ -240,10 +240,11 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
240 | /* Make sure all entries differ. */ | 240 | /* Make sure all entries differ. */ |
241 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); | 241 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); |
242 | tlb_write_indexed(); | 242 | tlb_write_indexed(); |
243 | |||
243 | finish: | 244 | finish: |
244 | write_c0_entryhi(oldpid); | 245 | write_c0_entryhi(oldpid); |
246 | local_irq_restore(flags); | ||
245 | } | 247 | } |
246 | local_irq_restore(flags); | ||
247 | } | 248 | } |
248 | 249 | ||
249 | /* | 250 | /* |
@@ -255,18 +256,17 @@ void local_flush_tlb_one(unsigned long page) | |||
255 | unsigned long flags; | 256 | unsigned long flags; |
256 | int oldpid, idx; | 257 | int oldpid, idx; |
257 | 258 | ||
258 | page &= (PAGE_MASK << 1); | ||
259 | oldpid = read_c0_entryhi() & ASID_MASK; | ||
260 | |||
261 | local_irq_save(flags); | 259 | local_irq_save(flags); |
260 | oldpid = read_c0_entryhi(); | ||
261 | page &= (PAGE_MASK << 1); | ||
262 | write_c0_entryhi(page); | 262 | write_c0_entryhi(page); |
263 | tlb_probe(); | 263 | tlb_probe(); |
264 | idx = read_c0_index(); | 264 | idx = read_c0_index(); |
265 | write_c0_entrylo0(0); | ||
266 | write_c0_entrylo1(0); | ||
265 | if (idx >= 0) { | 267 | if (idx >= 0) { |
266 | /* Make sure all entries differ. */ | 268 | /* Make sure all entries differ. */ |
267 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); | 269 | write_c0_entryhi(UNIQUE_ENTRYHI(idx)); |
268 | write_c0_entrylo0(0); | ||
269 | write_c0_entrylo1(0); | ||
270 | tlb_write_indexed(); | 270 | tlb_write_indexed(); |
271 | } | 271 | } |
272 | 272 | ||
@@ -297,6 +297,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) | |||
297 | { | 297 | { |
298 | unsigned long flags; | 298 | unsigned long flags; |
299 | pgd_t *pgdp; | 299 | pgd_t *pgdp; |
300 | pud_t *pudp; | ||
300 | pmd_t *pmdp; | 301 | pmd_t *pmdp; |
301 | pte_t *ptep; | 302 | pte_t *ptep; |
302 | int idx, pid; | 303 | int idx, pid; |
@@ -311,19 +312,26 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) | |||
311 | 312 | ||
312 | pid = read_c0_entryhi() & ASID_MASK; | 313 | pid = read_c0_entryhi() & ASID_MASK; |
313 | address &= (PAGE_MASK << 1); | 314 | address &= (PAGE_MASK << 1); |
314 | write_c0_entryhi(address | (pid)); | 315 | write_c0_entryhi(address | pid); |
315 | pgdp = pgd_offset(vma->vm_mm, address); | 316 | pgdp = pgd_offset(vma->vm_mm, address); |
316 | tlb_probe(); | 317 | tlb_probe(); |
317 | pmdp = pmd_offset(pgdp, address); | 318 | pudp = pud_offset(pgdp, address); |
319 | pmdp = pmd_offset(pudp, address); | ||
318 | idx = read_c0_index(); | 320 | idx = read_c0_index(); |
319 | ptep = pte_offset_map(pmdp, address); | 321 | ptep = pte_offset_map(pmdp, address); |
322 | |||
323 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | ||
324 | write_c0_entrylo0(ptep->pte_high); | ||
325 | ptep++; | ||
326 | write_c0_entrylo1(ptep->pte_high); | ||
327 | #else | ||
320 | write_c0_entrylo0(pte_val(*ptep++) >> 6); | 328 | write_c0_entrylo0(pte_val(*ptep++) >> 6); |
321 | write_c0_entrylo1(pte_val(*ptep) >> 6); | 329 | write_c0_entrylo1(pte_val(*ptep) >> 6); |
322 | if (idx < 0) { | 330 | #endif |
331 | if (idx < 0) | ||
323 | tlb_write_random(); | 332 | tlb_write_random(); |
324 | } else { | 333 | else |
325 | tlb_write_indexed(); | 334 | tlb_write_indexed(); |
326 | } | ||
327 | local_irq_restore(flags); | 335 | local_irq_restore(flags); |
328 | } | 336 | } |
329 | 337 | ||
@@ -336,7 +344,8 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, | |||
336 | unsigned long old_ctx; | 344 | unsigned long old_ctx; |
337 | 345 | ||
338 | local_irq_save(flags); | 346 | local_irq_save(flags); |
339 | old_ctx = read_c0_entryhi() & 0xff; | 347 | /* Save old context and create impossible VPN2 value */ |
348 | old_ctx = read_c0_entryhi(); | ||
340 | old_pagemask = read_c0_pagemask(); | 349 | old_pagemask = read_c0_pagemask(); |
341 | wired = read_c0_wired(); | 350 | wired = read_c0_wired(); |
342 | write_c0_wired(wired + 1); | 351 | write_c0_wired(wired + 1); |