aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm/tlb-sb1.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mm/tlb-sb1.c')
-rw-r--r--arch/mips/mm/tlb-sb1.c59
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
185void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) 185void 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
222void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) 221void 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);