diff options
Diffstat (limited to 'arch/powerpc/mm/tlb_low_64e.S')
-rw-r--r-- | arch/powerpc/mm/tlb_low_64e.S | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S index b4113bf86353..75f5d2777f61 100644 --- a/arch/powerpc/mm/tlb_low_64e.S +++ b/arch/powerpc/mm/tlb_low_64e.S | |||
@@ -239,6 +239,177 @@ itlb_miss_fault_bolted: | |||
239 | beq tlb_miss_common_bolted | 239 | beq tlb_miss_common_bolted |
240 | b itlb_miss_kernel_bolted | 240 | b itlb_miss_kernel_bolted |
241 | 241 | ||
242 | /* | ||
243 | * TLB miss handling for e6500 and derivatives, using hardware tablewalk. | ||
244 | * | ||
245 | * Linear mapping is bolted: no virtual page table or nested TLB misses | ||
246 | * Indirect entries in TLB1, hardware loads resulting direct entries | ||
247 | * into TLB0 | ||
248 | * No HES or NV hint on TLB1, so we need to do software round-robin | ||
249 | * No tlbsrx. so we need a spinlock, and we have to deal | ||
250 | * with MAS-damage caused by tlbsx | ||
251 | * 4K pages only | ||
252 | */ | ||
253 | |||
254 | START_EXCEPTION(instruction_tlb_miss_e6500) | ||
255 | tlb_prolog_bolted BOOKE_INTERRUPT_ITLB_MISS SPRN_SRR0 | ||
256 | |||
257 | ld r11,PACA_TCD_PTR(r13) | ||
258 | srdi. r15,r16,60 /* get region */ | ||
259 | ori r16,r16,1 | ||
260 | |||
261 | TLB_MISS_STATS_SAVE_INFO_BOLTED | ||
262 | bne tlb_miss_kernel_e6500 /* user/kernel test */ | ||
263 | |||
264 | b tlb_miss_common_e6500 | ||
265 | |||
266 | START_EXCEPTION(data_tlb_miss_e6500) | ||
267 | tlb_prolog_bolted BOOKE_INTERRUPT_DTLB_MISS SPRN_DEAR | ||
268 | |||
269 | ld r11,PACA_TCD_PTR(r13) | ||
270 | srdi. r15,r16,60 /* get region */ | ||
271 | rldicr r16,r16,0,62 | ||
272 | |||
273 | TLB_MISS_STATS_SAVE_INFO_BOLTED | ||
274 | bne tlb_miss_kernel_e6500 /* user vs kernel check */ | ||
275 | |||
276 | /* | ||
277 | * This is the guts of the TLB miss handler for e6500 and derivatives. | ||
278 | * We are entered with: | ||
279 | * | ||
280 | * r16 = page of faulting address (low bit 0 if data, 1 if instruction) | ||
281 | * r15 = crap (free to use) | ||
282 | * r14 = page table base | ||
283 | * r13 = PACA | ||
284 | * r11 = tlb_per_core ptr | ||
285 | * r10 = crap (free to use) | ||
286 | */ | ||
287 | tlb_miss_common_e6500: | ||
288 | /* | ||
289 | * Search if we already have an indirect entry for that virtual | ||
290 | * address, and if we do, bail out. | ||
291 | * | ||
292 | * MAS6:IND should be already set based on MAS4 | ||
293 | */ | ||
294 | addi r10,r11,TCD_LOCK | ||
295 | 1: lbarx r15,0,r10 | ||
296 | cmpdi r15,0 | ||
297 | bne 2f | ||
298 | li r15,1 | ||
299 | stbcx. r15,0,r10 | ||
300 | bne 1b | ||
301 | .subsection 1 | ||
302 | 2: lbz r15,0(r10) | ||
303 | cmpdi r15,0 | ||
304 | bne 2b | ||
305 | b 1b | ||
306 | .previous | ||
307 | |||
308 | mfspr r15,SPRN_MAS2 | ||
309 | |||
310 | tlbsx 0,r16 | ||
311 | mfspr r10,SPRN_MAS1 | ||
312 | andis. r10,r10,MAS1_VALID@h | ||
313 | bne tlb_miss_done_e6500 | ||
314 | |||
315 | /* Undo MAS-damage from the tlbsx */ | ||
316 | mfspr r10,SPRN_MAS1 | ||
317 | oris r10,r10,MAS1_VALID@h | ||
318 | mtspr SPRN_MAS1,r10 | ||
319 | mtspr SPRN_MAS2,r15 | ||
320 | |||
321 | /* Now, we need to walk the page tables. First check if we are in | ||
322 | * range. | ||
323 | */ | ||
324 | rldicl. r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4 | ||
325 | bne- tlb_miss_fault_e6500 | ||
326 | |||
327 | rldicl r15,r16,64-PGDIR_SHIFT+3,64-PGD_INDEX_SIZE-3 | ||
328 | cmpldi cr0,r14,0 | ||
329 | clrrdi r15,r15,3 | ||
330 | beq- tlb_miss_fault_e6500 /* No PGDIR, bail */ | ||
331 | ldx r14,r14,r15 /* grab pgd entry */ | ||
332 | |||
333 | rldicl r15,r16,64-PUD_SHIFT+3,64-PUD_INDEX_SIZE-3 | ||
334 | clrrdi r15,r15,3 | ||
335 | cmpdi cr0,r14,0 | ||
336 | bge tlb_miss_fault_e6500 /* Bad pgd entry or hugepage; bail */ | ||
337 | ldx r14,r14,r15 /* grab pud entry */ | ||
338 | |||
339 | rldicl r15,r16,64-PMD_SHIFT+3,64-PMD_INDEX_SIZE-3 | ||
340 | clrrdi r15,r15,3 | ||
341 | cmpdi cr0,r14,0 | ||
342 | bge tlb_miss_fault_e6500 | ||
343 | ldx r14,r14,r15 /* Grab pmd entry */ | ||
344 | |||
345 | mfspr r10,SPRN_MAS0 | ||
346 | cmpdi cr0,r14,0 | ||
347 | bge tlb_miss_fault_e6500 | ||
348 | |||
349 | /* Now we build the MAS for a 2M indirect page: | ||
350 | * | ||
351 | * MAS 0 : ESEL needs to be filled by software round-robin | ||
352 | * MAS 1 : Fully set up | ||
353 | * - PID already updated by caller if necessary | ||
354 | * - TSIZE for now is base ind page size always | ||
355 | * - TID already cleared if necessary | ||
356 | * MAS 2 : Default not 2M-aligned, need to be redone | ||
357 | * MAS 3+7 : Needs to be done | ||
358 | */ | ||
359 | |||
360 | ori r14,r14,(BOOK3E_PAGESZ_4K << MAS3_SPSIZE_SHIFT) | ||
361 | mtspr SPRN_MAS7_MAS3,r14 | ||
362 | |||
363 | clrrdi r15,r16,21 /* make EA 2M-aligned */ | ||
364 | mtspr SPRN_MAS2,r15 | ||
365 | |||
366 | lbz r15,TCD_ESEL_NEXT(r11) | ||
367 | lbz r16,TCD_ESEL_MAX(r11) | ||
368 | lbz r14,TCD_ESEL_FIRST(r11) | ||
369 | rlwimi r10,r15,16,0x00ff0000 /* insert esel_next into MAS0 */ | ||
370 | addi r15,r15,1 /* increment esel_next */ | ||
371 | mtspr SPRN_MAS0,r10 | ||
372 | cmpw r15,r16 | ||
373 | iseleq r15,r14,r15 /* if next == last use first */ | ||
374 | stb r15,TCD_ESEL_NEXT(r11) | ||
375 | |||
376 | tlbwe | ||
377 | |||
378 | tlb_miss_done_e6500: | ||
379 | .macro tlb_unlock_e6500 | ||
380 | li r15,0 | ||
381 | isync | ||
382 | stb r15,TCD_LOCK(r11) | ||
383 | .endm | ||
384 | |||
385 | tlb_unlock_e6500 | ||
386 | TLB_MISS_STATS_X(MMSTAT_TLB_MISS_NORM_OK) | ||
387 | tlb_epilog_bolted | ||
388 | rfi | ||
389 | |||
390 | tlb_miss_kernel_e6500: | ||
391 | mfspr r10,SPRN_MAS1 | ||
392 | ld r14,PACA_KERNELPGD(r13) | ||
393 | cmpldi cr0,r15,8 /* Check for vmalloc region */ | ||
394 | rlwinm r10,r10,0,16,1 /* Clear TID */ | ||
395 | mtspr SPRN_MAS1,r10 | ||
396 | beq+ tlb_miss_common_e6500 | ||
397 | |||
398 | tlb_miss_fault_e6500: | ||
399 | tlb_unlock_e6500 | ||
400 | /* We need to check if it was an instruction miss */ | ||
401 | andi. r16,r16,1 | ||
402 | bne itlb_miss_fault_e6500 | ||
403 | dtlb_miss_fault_e6500: | ||
404 | TLB_MISS_STATS_D(MMSTAT_TLB_MISS_NORM_FAULT) | ||
405 | tlb_epilog_bolted | ||
406 | b exc_data_storage_book3e | ||
407 | itlb_miss_fault_e6500: | ||
408 | TLB_MISS_STATS_I(MMSTAT_TLB_MISS_NORM_FAULT) | ||
409 | tlb_epilog_bolted | ||
410 | b exc_instruction_storage_book3e | ||
411 | |||
412 | |||
242 | /********************************************************************** | 413 | /********************************************************************** |
243 | * * | 414 | * * |
244 | * TLB miss handling for Book3E with TLB reservation and HES support * | 415 | * TLB miss handling for Book3E with TLB reservation and HES support * |