aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/tlb_low_64e.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/tlb_low_64e.S')
-rw-r--r--arch/powerpc/mm/tlb_low_64e.S171
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 */
287tlb_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
2951: 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
3022: 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
378tlb_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
390tlb_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
398tlb_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
403dtlb_miss_fault_e6500:
404 TLB_MISS_STATS_D(MMSTAT_TLB_MISS_NORM_FAULT)
405 tlb_epilog_bolted
406 b exc_data_storage_book3e
407itlb_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 *