aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-06-11 17:09:32 -0400
committerScott Wood <scottwood@freescale.com>2014-07-29 20:26:29 -0400
commit48cd9b5d590aee1664170968a9eae068e36761eb (patch)
treebd5fbc4d6d01fac8363be43b9038988f45c33e04
parente16c8765533a155ebd3d7c36fc80440a03bbf46a (diff)
powerpc/e6500: Work around erratum A-008139
Erratum A-008139 can cause duplicate TLB entries if an indirect entry is overwritten using tlbwe while the other thread is using it to do a lookup. Work around this by using tlbilx to invalidate prior to overwriting. To avoid the need to save another register to hold MAS1 during the workaround code, TID clearing has been moved from tlb_miss_kernel_e6500 until after the SMT section. Signed-off-by: Scott Wood <scottwood@freescale.com>
-rw-r--r--arch/powerpc/mm/tlb_low_64e.S68
1 files changed, 56 insertions, 12 deletions
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index 57c4d662be33..89bf95bd63b1 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -299,7 +299,9 @@ itlb_miss_fault_bolted:
299 * r10 = crap (free to use) 299 * r10 = crap (free to use)
300 */ 300 */
301tlb_miss_common_e6500: 301tlb_miss_common_e6500:
302BEGIN_FTR_SECTION 302 crmove cr2*4+2,cr0*4+2 /* cr2.eq != 0 if kernel address */
303
304BEGIN_FTR_SECTION /* CPU_FTR_SMT */
303 /* 305 /*
304 * Search if we already have an indirect entry for that virtual 306 * Search if we already have an indirect entry for that virtual
305 * address, and if we do, bail out. 307 * address, and if we do, bail out.
@@ -324,17 +326,62 @@ BEGIN_FTR_SECTION
324 b 1b 326 b 1b
325 .previous 327 .previous
326 328
329 /*
330 * Erratum A-008139 says that we can't use tlbwe to change
331 * an indirect entry in any way (including replacing or
332 * invalidating) if the other thread could be in the process
333 * of a lookup. The workaround is to invalidate the entry
334 * with tlbilx before overwriting.
335 */
336
337 lbz r15,TCD_ESEL_NEXT(r11)
338 rlwinm r10,r15,16,0xff0000
339 oris r10,r10,MAS0_TLBSEL(1)@h
340 mtspr SPRN_MAS0,r10
341 isync
342 tlbre
327 mfspr r15,SPRN_MAS1 343 mfspr r15,SPRN_MAS1
328 mfspr r10,SPRN_MAS2 344 andis. r15,r15,MAS1_VALID@h
345 beq 5f
346
347BEGIN_FTR_SECTION_NESTED(532)
348 mfspr r10,SPRN_MAS8
349 rlwinm r10,r10,0,0x80000fff /* tgs,tlpid -> sgs,slpid */
350 mtspr SPRN_MAS5,r10
351END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532)
329 352
330 tlbsx 0,r16
331 mtspr SPRN_MAS2,r10
332 mfspr r10,SPRN_MAS1 353 mfspr r10,SPRN_MAS1
333 mtspr SPRN_MAS1,r15 354 rlwinm r15,r10,0,0x3fff0000 /* tid -> spid */
355 rlwimi r15,r10,20,0x00000003 /* ind,ts -> sind,sas */
356 mfspr r10,SPRN_MAS6
357 mtspr SPRN_MAS6,r15
358
359 mfspr r15,SPRN_MAS2
360 isync
361 tlbilxva 0,r15
362 isync
363
364 mtspr SPRN_MAS6,r10
334 365
335 andis. r10,r10,MAS1_VALID@h 3665:
367BEGIN_FTR_SECTION_NESTED(532)
368 li r10,0
369 mtspr SPRN_MAS8,r10
370 mtspr SPRN_MAS5,r10
371END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532)
372
373 tlbsx 0,r16
374 mfspr r10,SPRN_MAS1
375 andis. r15,r10,MAS1_VALID@h
336 bne tlb_miss_done_e6500 376 bne tlb_miss_done_e6500
337END_FTR_SECTION_IFSET(CPU_FTR_SMT) 377FTR_SECTION_ELSE
378 mfspr r10,SPRN_MAS1
379ALT_FTR_SECTION_END_IFSET(CPU_FTR_SMT)
380
381 oris r10,r10,MAS1_VALID@h
382 beq cr2,4f
383 rlwinm r10,r10,0,16,1 /* Clear TID */
3844: mtspr SPRN_MAS1,r10
338 385
339 /* Now, we need to walk the page tables. First check if we are in 386 /* Now, we need to walk the page tables. First check if we are in
340 * range. 387 * range.
@@ -410,12 +457,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_SMT)
410 rfi 457 rfi
411 458
412tlb_miss_kernel_e6500: 459tlb_miss_kernel_e6500:
413 mfspr r10,SPRN_MAS1
414 ld r14,PACA_KERNELPGD(r13) 460 ld r14,PACA_KERNELPGD(r13)
415 cmpldi cr0,r15,8 /* Check for vmalloc region */ 461 cmpldi cr1,r15,8 /* Check for vmalloc region */
416 rlwinm r10,r10,0,16,1 /* Clear TID */ 462 beq+ cr1,tlb_miss_common_e6500
417 mtspr SPRN_MAS1,r10
418 beq+ tlb_miss_common_e6500
419 463
420tlb_miss_fault_e6500: 464tlb_miss_fault_e6500:
421 tlb_unlock_e6500 465 tlb_unlock_e6500