diff options
| author | Kumar Gala <galak@kernel.crashing.org> | 2009-03-18 23:55:41 -0400 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-03-23 22:47:32 -0400 |
| commit | 2319f1239592d0de80414ad2338c2bd7384a2a41 (patch) | |
| tree | 805de041dfc84ae9ca767c9767d833977654dbe0 | |
| parent | eb3436a0139a651a39dbb37a75b10a2cccd00ad5 (diff) | |
powerpc/mm: e300c2/c3/c4 TLB errata workaround
Complete workaround for DTLB errata in e300c2/c3/c4 processors.
Due to the bug, the hardware-implemented LRU algorythm always goes to way
1 of the TLB. This fix implements the proposed software workaround in
form of a LRW table for chosing the TLB-way.
Based on patch from David Jander <david@protonic.nl>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
| -rw-r--r-- | arch/powerpc/include/asm/mmu.h | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/cpu_setup_6xx.S | 5 | ||||
| -rw-r--r-- | arch/powerpc/kernel/cputable.c | 9 | ||||
| -rw-r--r-- | arch/powerpc/kernel/head_32.S | 32 |
4 files changed, 45 insertions, 7 deletions
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index dc82dcd06aea..c073de4af849 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h | |||
| @@ -46,6 +46,12 @@ | |||
| 46 | */ | 46 | */ |
| 47 | #define MMU_FTR_LOCK_BCAST_INVAL ASM_CONST(0x00100000) | 47 | #define MMU_FTR_LOCK_BCAST_INVAL ASM_CONST(0x00100000) |
| 48 | 48 | ||
| 49 | /* This indicates that the processor doesn't handle way selection | ||
| 50 | * properly and needs SW to track and update the LRU state. This | ||
| 51 | * is specific to an errata on e300c2/c3/c4 class parts | ||
| 52 | */ | ||
| 53 | #define MMU_FTR_NEED_DTLB_SW_LRU ASM_CONST(0x00200000) | ||
| 54 | |||
| 49 | #ifndef __ASSEMBLY__ | 55 | #ifndef __ASSEMBLY__ |
| 50 | #include <asm/cputable.h> | 56 | #include <asm/cputable.h> |
| 51 | 57 | ||
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index 72d1d7395254..54f767e31a1a 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S | |||
| @@ -15,9 +15,14 @@ | |||
| 15 | #include <asm/ppc_asm.h> | 15 | #include <asm/ppc_asm.h> |
| 16 | #include <asm/asm-offsets.h> | 16 | #include <asm/asm-offsets.h> |
| 17 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
| 18 | #include <asm/mmu.h> | ||
| 18 | 19 | ||
| 19 | _GLOBAL(__setup_cpu_603) | 20 | _GLOBAL(__setup_cpu_603) |
| 20 | mflr r4 | 21 | mflr r4 |
| 22 | BEGIN_MMU_FTR_SECTION | ||
| 23 | li r10,0 | ||
| 24 | mtspr SPRN_SPRG4,r10 /* init SW LRU tracking */ | ||
| 25 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) | ||
| 21 | BEGIN_FTR_SECTION | 26 | BEGIN_FTR_SECTION |
| 22 | bl __init_fpu_registers | 27 | bl __init_fpu_registers |
| 23 | END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE) | 28 | END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE) |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index ccea2431ddf8..cd1b687544f3 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -1090,7 +1090,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1090 | .cpu_name = "e300c2", | 1090 | .cpu_name = "e300c2", |
| 1091 | .cpu_features = CPU_FTRS_E300C2, | 1091 | .cpu_features = CPU_FTRS_E300C2, |
| 1092 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 1092 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, |
| 1093 | .mmu_features = MMU_FTR_USE_HIGH_BATS, | 1093 | .mmu_features = MMU_FTR_USE_HIGH_BATS | |
| 1094 | MMU_FTR_NEED_DTLB_SW_LRU, | ||
| 1094 | .icache_bsize = 32, | 1095 | .icache_bsize = 32, |
| 1095 | .dcache_bsize = 32, | 1096 | .dcache_bsize = 32, |
| 1096 | .cpu_setup = __setup_cpu_603, | 1097 | .cpu_setup = __setup_cpu_603, |
| @@ -1103,7 +1104,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1103 | .cpu_name = "e300c3", | 1104 | .cpu_name = "e300c3", |
| 1104 | .cpu_features = CPU_FTRS_E300, | 1105 | .cpu_features = CPU_FTRS_E300, |
| 1105 | .cpu_user_features = COMMON_USER, | 1106 | .cpu_user_features = COMMON_USER, |
| 1106 | .mmu_features = MMU_FTR_USE_HIGH_BATS, | 1107 | .mmu_features = MMU_FTR_USE_HIGH_BATS | |
| 1108 | MMU_FTR_NEED_DTLB_SW_LRU, | ||
| 1107 | .icache_bsize = 32, | 1109 | .icache_bsize = 32, |
| 1108 | .dcache_bsize = 32, | 1110 | .dcache_bsize = 32, |
| 1109 | .cpu_setup = __setup_cpu_603, | 1111 | .cpu_setup = __setup_cpu_603, |
| @@ -1118,7 +1120,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1118 | .cpu_name = "e300c4", | 1120 | .cpu_name = "e300c4", |
| 1119 | .cpu_features = CPU_FTRS_E300, | 1121 | .cpu_features = CPU_FTRS_E300, |
| 1120 | .cpu_user_features = COMMON_USER, | 1122 | .cpu_user_features = COMMON_USER, |
| 1121 | .mmu_features = MMU_FTR_USE_HIGH_BATS, | 1123 | .mmu_features = MMU_FTR_USE_HIGH_BATS | |
| 1124 | MMU_FTR_NEED_DTLB_SW_LRU, | ||
| 1122 | .icache_bsize = 32, | 1125 | .icache_bsize = 32, |
| 1123 | .dcache_bsize = 32, | 1126 | .dcache_bsize = 32, |
| 1124 | .cpu_setup = __setup_cpu_603, | 1127 | .cpu_setup = __setup_cpu_603, |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index 58dcc7c03109..54e68c11ae15 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
| @@ -593,9 +593,21 @@ BEGIN_FTR_SECTION | |||
| 593 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ | 593 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ |
| 594 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | 594 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) |
| 595 | mtspr SPRN_RPA,r1 | 595 | mtspr SPRN_RPA,r1 |
| 596 | mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ | ||
| 597 | mtcrf 0x80,r2 | ||
| 598 | BEGIN_MMU_FTR_SECTION | ||
| 599 | li r0,1 | ||
| 600 | mfspr r1,SPRN_SPRG4 | ||
| 601 | rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ | ||
| 602 | slw r0,r0,r2 | ||
| 603 | xor r1,r0,r1 | ||
| 604 | srw r0,r1,r2 | ||
| 605 | mtspr SPRN_SPRG4,r1 | ||
| 606 | mfspr r2,SPRN_SRR1 | ||
| 607 | rlwimi r2,r0,31-14,14,14 | ||
| 608 | mtspr SPRN_SRR1,r2 | ||
| 609 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) | ||
| 596 | tlbld r3 | 610 | tlbld r3 |
| 597 | mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ | ||
| 598 | mtcrf 0x80,r3 | ||
| 599 | rfi | 611 | rfi |
| 600 | DataAddressInvalid: | 612 | DataAddressInvalid: |
| 601 | mfspr r3,SPRN_SRR1 | 613 | mfspr r3,SPRN_SRR1 |
| @@ -661,9 +673,21 @@ BEGIN_FTR_SECTION | |||
| 661 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ | 673 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ |
| 662 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | 674 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) |
| 663 | mtspr SPRN_RPA,r1 | 675 | mtspr SPRN_RPA,r1 |
| 676 | mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ | ||
| 677 | mtcrf 0x80,r2 | ||
| 678 | BEGIN_MMU_FTR_SECTION | ||
| 679 | li r0,1 | ||
| 680 | mfspr r1,SPRN_SPRG4 | ||
| 681 | rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ | ||
| 682 | slw r0,r0,r2 | ||
| 683 | xor r1,r0,r1 | ||
| 684 | srw r0,r1,r2 | ||
| 685 | mtspr SPRN_SPRG4,r1 | ||
| 686 | mfspr r2,SPRN_SRR1 | ||
| 687 | rlwimi r2,r0,31-14,14,14 | ||
| 688 | mtspr SPRN_SRR1,r2 | ||
| 689 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) | ||
| 664 | tlbld r3 | 690 | tlbld r3 |
| 665 | mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ | ||
| 666 | mtcrf 0x80,r3 | ||
| 667 | rfi | 691 | rfi |
| 668 | 692 | ||
| 669 | #ifndef CONFIG_ALTIVEC | 693 | #ifndef CONFIG_ALTIVEC |
