diff options
| -rw-r--r-- | arch/powerpc/include/asm/mmu-book3e.h | 13 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/mmu.h | 21 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/paca.h | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 9 | ||||
| -rw-r--r-- | arch/powerpc/kernel/paca.c | 5 | ||||
| -rw-r--r-- | arch/powerpc/kernel/setup_64.c | 31 | ||||
| -rw-r--r-- | arch/powerpc/mm/fsl_booke_mmu.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/mm/mem.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/mm/tlb_low_64e.S | 171 | ||||
| -rw-r--r-- | arch/powerpc/mm/tlb_nohash.c | 93 |
10 files changed, 326 insertions, 36 deletions
diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h index 936db360790a..89b785d16846 100644 --- a/arch/powerpc/include/asm/mmu-book3e.h +++ b/arch/powerpc/include/asm/mmu-book3e.h | |||
| @@ -286,8 +286,21 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) | |||
| 286 | extern int mmu_linear_psize; | 286 | extern int mmu_linear_psize; |
| 287 | extern int mmu_vmemmap_psize; | 287 | extern int mmu_vmemmap_psize; |
| 288 | 288 | ||
| 289 | struct tlb_core_data { | ||
| 290 | /* For software way selection, as on Freescale TLB1 */ | ||
| 291 | u8 esel_next, esel_max, esel_first; | ||
| 292 | |||
| 293 | /* Per-core spinlock for e6500 TLB handlers (no tlbsrx.) */ | ||
| 294 | u8 lock; | ||
| 295 | }; | ||
| 296 | |||
| 289 | #ifdef CONFIG_PPC64 | 297 | #ifdef CONFIG_PPC64 |
| 290 | extern unsigned long linear_map_top; | 298 | extern unsigned long linear_map_top; |
| 299 | extern int book3e_htw_mode; | ||
| 300 | |||
| 301 | #define PPC_HTW_NONE 0 | ||
| 302 | #define PPC_HTW_IBM 1 | ||
| 303 | #define PPC_HTW_E6500 2 | ||
| 291 | 304 | ||
| 292 | /* | 305 | /* |
| 293 | * 64-bit booke platforms don't load the tlb in the tlb miss handler code. | 306 | * 64-bit booke platforms don't load the tlb in the tlb miss handler code. |
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index 691fd8aca939..f8d1d6dcf7db 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h | |||
| @@ -180,16 +180,17 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr) | |||
| 180 | #define MMU_PAGE_64K_AP 3 /* "Admixed pages" (hash64 only) */ | 180 | #define MMU_PAGE_64K_AP 3 /* "Admixed pages" (hash64 only) */ |
| 181 | #define MMU_PAGE_256K 4 | 181 | #define MMU_PAGE_256K 4 |
| 182 | #define MMU_PAGE_1M 5 | 182 | #define MMU_PAGE_1M 5 |
| 183 | #define MMU_PAGE_4M 6 | 183 | #define MMU_PAGE_2M 6 |
| 184 | #define MMU_PAGE_8M 7 | 184 | #define MMU_PAGE_4M 7 |
| 185 | #define MMU_PAGE_16M 8 | 185 | #define MMU_PAGE_8M 8 |
| 186 | #define MMU_PAGE_64M 9 | 186 | #define MMU_PAGE_16M 9 |
| 187 | #define MMU_PAGE_256M 10 | 187 | #define MMU_PAGE_64M 10 |
| 188 | #define MMU_PAGE_1G 11 | 188 | #define MMU_PAGE_256M 11 |
| 189 | #define MMU_PAGE_16G 12 | 189 | #define MMU_PAGE_1G 12 |
| 190 | #define MMU_PAGE_64G 13 | 190 | #define MMU_PAGE_16G 13 |
| 191 | 191 | #define MMU_PAGE_64G 14 | |
| 192 | #define MMU_PAGE_COUNT 14 | 192 | |
| 193 | #define MMU_PAGE_COUNT 15 | ||
| 193 | 194 | ||
| 194 | #if defined(CONFIG_PPC_STD_MMU_64) | 195 | #if defined(CONFIG_PPC_STD_MMU_64) |
| 195 | /* 64-bit classic hash table MMU */ | 196 | /* 64-bit classic hash table MMU */ |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index c3523d1dda58..e81731c62a7f 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
| @@ -113,6 +113,10 @@ struct paca_struct { | |||
| 113 | /* Keep pgd in the same cacheline as the start of extlb */ | 113 | /* Keep pgd in the same cacheline as the start of extlb */ |
| 114 | pgd_t *pgd __attribute__((aligned(0x80))); /* Current PGD */ | 114 | pgd_t *pgd __attribute__((aligned(0x80))); /* Current PGD */ |
| 115 | pgd_t *kernel_pgd; /* Kernel PGD */ | 115 | pgd_t *kernel_pgd; /* Kernel PGD */ |
| 116 | |||
| 117 | /* Shared by all threads of a core -- points to tcd of first thread */ | ||
| 118 | struct tlb_core_data *tcd_ptr; | ||
| 119 | |||
| 116 | /* We can have up to 3 levels of reentrancy in the TLB miss handler */ | 120 | /* We can have up to 3 levels of reentrancy in the TLB miss handler */ |
| 117 | u64 extlb[3][EX_TLB_SIZE / sizeof(u64)]; | 121 | u64 extlb[3][EX_TLB_SIZE / sizeof(u64)]; |
| 118 | u64 exmc[8]; /* used for machine checks */ | 122 | u64 exmc[8]; /* used for machine checks */ |
| @@ -123,6 +127,8 @@ struct paca_struct { | |||
| 123 | void *mc_kstack; | 127 | void *mc_kstack; |
| 124 | void *crit_kstack; | 128 | void *crit_kstack; |
| 125 | void *dbg_kstack; | 129 | void *dbg_kstack; |
| 130 | |||
| 131 | struct tlb_core_data tcd; | ||
| 126 | #endif /* CONFIG_PPC_BOOK3E */ | 132 | #endif /* CONFIG_PPC_BOOK3E */ |
| 127 | 133 | ||
| 128 | mm_context_t context; | 134 | mm_context_t context; |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 41a283956a29..ed8d68ce71f3 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -203,6 +203,15 @@ int main(void) | |||
| 203 | DEFINE(PACA_MC_STACK, offsetof(struct paca_struct, mc_kstack)); | 203 | DEFINE(PACA_MC_STACK, offsetof(struct paca_struct, mc_kstack)); |
| 204 | DEFINE(PACA_CRIT_STACK, offsetof(struct paca_struct, crit_kstack)); | 204 | DEFINE(PACA_CRIT_STACK, offsetof(struct paca_struct, crit_kstack)); |
| 205 | DEFINE(PACA_DBG_STACK, offsetof(struct paca_struct, dbg_kstack)); | 205 | DEFINE(PACA_DBG_STACK, offsetof(struct paca_struct, dbg_kstack)); |
| 206 | DEFINE(PACA_TCD_PTR, offsetof(struct paca_struct, tcd_ptr)); | ||
| 207 | |||
| 208 | DEFINE(TCD_ESEL_NEXT, | ||
| 209 | offsetof(struct tlb_core_data, esel_next)); | ||
| 210 | DEFINE(TCD_ESEL_MAX, | ||
| 211 | offsetof(struct tlb_core_data, esel_max)); | ||
| 212 | DEFINE(TCD_ESEL_FIRST, | ||
| 213 | offsetof(struct tlb_core_data, esel_first)); | ||
| 214 | DEFINE(TCD_LOCK, offsetof(struct tlb_core_data, lock)); | ||
| 206 | #endif /* CONFIG_PPC_BOOK3E */ | 215 | #endif /* CONFIG_PPC_BOOK3E */ |
| 207 | 216 | ||
| 208 | #ifdef CONFIG_PPC_STD_MMU_64 | 217 | #ifdef CONFIG_PPC_STD_MMU_64 |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 623c356fe34f..bf0aada02fe4 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
| @@ -160,6 +160,11 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu) | |||
| 160 | #ifdef CONFIG_PPC_STD_MMU_64 | 160 | #ifdef CONFIG_PPC_STD_MMU_64 |
| 161 | new_paca->slb_shadow_ptr = init_slb_shadow(cpu); | 161 | new_paca->slb_shadow_ptr = init_slb_shadow(cpu); |
| 162 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 162 | #endif /* CONFIG_PPC_STD_MMU_64 */ |
| 163 | |||
| 164 | #ifdef CONFIG_PPC_BOOK3E | ||
| 165 | /* For now -- if we have threads this will be adjusted later */ | ||
| 166 | new_paca->tcd_ptr = &new_paca->tcd; | ||
| 167 | #endif | ||
| 163 | } | 168 | } |
| 164 | 169 | ||
| 165 | /* Put the paca pointer into r13 and SPRG_PACA */ | 170 | /* Put the paca pointer into r13 and SPRG_PACA */ |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 2232aff66059..1ce9b87d7df8 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -97,6 +97,36 @@ int dcache_bsize; | |||
| 97 | int icache_bsize; | 97 | int icache_bsize; |
| 98 | int ucache_bsize; | 98 | int ucache_bsize; |
| 99 | 99 | ||
| 100 | #if defined(CONFIG_PPC_BOOK3E) && defined(CONFIG_SMP) | ||
| 101 | static void setup_tlb_core_data(void) | ||
| 102 | { | ||
| 103 | int cpu; | ||
| 104 | |||
| 105 | for_each_possible_cpu(cpu) { | ||
| 106 | int first = cpu_first_thread_sibling(cpu); | ||
| 107 | |||
| 108 | paca[cpu].tcd_ptr = &paca[first].tcd; | ||
| 109 | |||
| 110 | /* | ||
| 111 | * If we have threads, we need either tlbsrx. | ||
| 112 | * or e6500 tablewalk mode, or else TLB handlers | ||
| 113 | * will be racy and could produce duplicate entries. | ||
| 114 | */ | ||
| 115 | if (smt_enabled_at_boot >= 2 && | ||
| 116 | !mmu_has_feature(MMU_FTR_USE_TLBRSRV) && | ||
| 117 | book3e_htw_mode != PPC_HTW_E6500) { | ||
| 118 | /* Should we panic instead? */ | ||
| 119 | WARN_ONCE("%s: unsupported MMU configuration -- expect problems\n", | ||
| 120 | __func__); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||
| 124 | #else | ||
| 125 | static void setup_tlb_core_data(void) | ||
| 126 | { | ||
| 127 | } | ||
| 128 | #endif | ||
| 129 | |||
| 100 | #ifdef CONFIG_SMP | 130 | #ifdef CONFIG_SMP |
| 101 | 131 | ||
| 102 | static char *smt_enabled_cmdline; | 132 | static char *smt_enabled_cmdline; |
| @@ -445,6 +475,7 @@ void __init setup_system(void) | |||
| 445 | 475 | ||
| 446 | smp_setup_cpu_maps(); | 476 | smp_setup_cpu_maps(); |
| 447 | check_smt_enabled(); | 477 | check_smt_enabled(); |
| 478 | setup_tlb_core_data(); | ||
| 448 | 479 | ||
| 449 | #ifdef CONFIG_SMP | 480 | #ifdef CONFIG_SMP |
| 450 | /* Release secondary cpus out of their spinloops at 0x60 now that | 481 | /* Release secondary cpus out of their spinloops at 0x60 now that |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index a68671c18ad4..94cd728166d3 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include <asm/smp.h> | 52 | #include <asm/smp.h> |
| 53 | #include <asm/machdep.h> | 53 | #include <asm/machdep.h> |
| 54 | #include <asm/setup.h> | 54 | #include <asm/setup.h> |
| 55 | #include <asm/paca.h> | ||
| 55 | 56 | ||
| 56 | #include "mmu_decl.h" | 57 | #include "mmu_decl.h" |
| 57 | 58 | ||
| @@ -191,6 +192,12 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt, | |||
| 191 | } | 192 | } |
| 192 | tlbcam_index = i; | 193 | tlbcam_index = i; |
| 193 | 194 | ||
| 195 | #ifdef CONFIG_PPC64 | ||
| 196 | get_paca()->tcd.esel_next = i; | ||
| 197 | get_paca()->tcd.esel_max = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY; | ||
| 198 | get_paca()->tcd.esel_first = i; | ||
| 199 | #endif | ||
| 200 | |||
| 194 | return amount_mapped; | 201 | return amount_mapped; |
| 195 | } | 202 | } |
| 196 | 203 | ||
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 3fa93dc7fe75..94448cd4b444 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
| @@ -307,6 +307,12 @@ static void __init register_page_bootmem_info(void) | |||
| 307 | 307 | ||
| 308 | void __init mem_init(void) | 308 | void __init mem_init(void) |
| 309 | { | 309 | { |
| 310 | /* | ||
| 311 | * book3s is limited to 16 page sizes due to encoding this in | ||
| 312 | * a 4-bit field for slices. | ||
| 313 | */ | ||
| 314 | BUILD_BUG_ON(MMU_PAGE_COUNT > 16); | ||
| 315 | |||
| 310 | #ifdef CONFIG_SWIOTLB | 316 | #ifdef CONFIG_SWIOTLB |
| 311 | swiotlb_init(0); | 317 | swiotlb_init(0); |
| 312 | #endif | 318 | #endif |
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 * |
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index 8805b7b87dc6..735839b74dc5 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include <asm/tlb.h> | 43 | #include <asm/tlb.h> |
| 44 | #include <asm/code-patching.h> | 44 | #include <asm/code-patching.h> |
| 45 | #include <asm/hugetlb.h> | 45 | #include <asm/hugetlb.h> |
| 46 | #include <asm/paca.h> | ||
| 46 | 47 | ||
| 47 | #include "mmu_decl.h" | 48 | #include "mmu_decl.h" |
| 48 | 49 | ||
| @@ -58,6 +59,10 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { | |||
| 58 | .shift = 12, | 59 | .shift = 12, |
| 59 | .enc = BOOK3E_PAGESZ_4K, | 60 | .enc = BOOK3E_PAGESZ_4K, |
| 60 | }, | 61 | }, |
| 62 | [MMU_PAGE_2M] = { | ||
| 63 | .shift = 21, | ||
| 64 | .enc = BOOK3E_PAGESZ_2M, | ||
| 65 | }, | ||
| 61 | [MMU_PAGE_4M] = { | 66 | [MMU_PAGE_4M] = { |
| 62 | .shift = 22, | 67 | .shift = 22, |
| 63 | .enc = BOOK3E_PAGESZ_4M, | 68 | .enc = BOOK3E_PAGESZ_4M, |
| @@ -136,7 +141,7 @@ static inline int mmu_get_tsize(int psize) | |||
| 136 | int mmu_linear_psize; /* Page size used for the linear mapping */ | 141 | int mmu_linear_psize; /* Page size used for the linear mapping */ |
| 137 | int mmu_pte_psize; /* Page size used for PTE pages */ | 142 | int mmu_pte_psize; /* Page size used for PTE pages */ |
| 138 | int mmu_vmemmap_psize; /* Page size used for the virtual mem map */ | 143 | int mmu_vmemmap_psize; /* Page size used for the virtual mem map */ |
| 139 | int book3e_htw_enabled; /* Is HW tablewalk enabled ? */ | 144 | int book3e_htw_mode; /* HW tablewalk? Value is PPC_HTW_* */ |
| 140 | unsigned long linear_map_top; /* Top of linear mapping */ | 145 | unsigned long linear_map_top; /* Top of linear mapping */ |
| 141 | 146 | ||
| 142 | #endif /* CONFIG_PPC64 */ | 147 | #endif /* CONFIG_PPC64 */ |
| @@ -377,7 +382,7 @@ void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address) | |||
| 377 | { | 382 | { |
| 378 | int tsize = mmu_psize_defs[mmu_pte_psize].enc; | 383 | int tsize = mmu_psize_defs[mmu_pte_psize].enc; |
| 379 | 384 | ||
| 380 | if (book3e_htw_enabled) { | 385 | if (book3e_htw_mode != PPC_HTW_NONE) { |
| 381 | unsigned long start = address & PMD_MASK; | 386 | unsigned long start = address & PMD_MASK; |
| 382 | unsigned long end = address + PMD_SIZE; | 387 | unsigned long end = address + PMD_SIZE; |
| 383 | unsigned long size = 1UL << mmu_psize_defs[mmu_pte_psize].shift; | 388 | unsigned long size = 1UL << mmu_psize_defs[mmu_pte_psize].shift; |
| @@ -430,7 +435,7 @@ static void setup_page_sizes(void) | |||
| 430 | def = &mmu_psize_defs[psize]; | 435 | def = &mmu_psize_defs[psize]; |
| 431 | shift = def->shift; | 436 | shift = def->shift; |
| 432 | 437 | ||
| 433 | if (shift == 0) | 438 | if (shift == 0 || shift & 1) |
| 434 | continue; | 439 | continue; |
| 435 | 440 | ||
| 436 | /* adjust to be in terms of 4^shift Kb */ | 441 | /* adjust to be in terms of 4^shift Kb */ |
| @@ -440,21 +445,40 @@ static void setup_page_sizes(void) | |||
| 440 | def->flags |= MMU_PAGE_SIZE_DIRECT; | 445 | def->flags |= MMU_PAGE_SIZE_DIRECT; |
| 441 | } | 446 | } |
| 442 | 447 | ||
| 443 | goto no_indirect; | 448 | goto out; |
| 444 | } | 449 | } |
| 445 | 450 | ||
| 446 | if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V2) { | 451 | if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V2) { |
| 447 | u32 tlb1ps = mfspr(SPRN_TLB1PS); | 452 | u32 tlb1cfg, tlb1ps; |
| 453 | |||
| 454 | tlb0cfg = mfspr(SPRN_TLB0CFG); | ||
| 455 | tlb1cfg = mfspr(SPRN_TLB1CFG); | ||
| 456 | tlb1ps = mfspr(SPRN_TLB1PS); | ||
| 457 | eptcfg = mfspr(SPRN_EPTCFG); | ||
| 458 | |||
| 459 | if ((tlb1cfg & TLBnCFG_IND) && (tlb0cfg & TLBnCFG_PT)) | ||
| 460 | book3e_htw_mode = PPC_HTW_E6500; | ||
| 461 | |||
| 462 | /* | ||
| 463 | * We expect 4K subpage size and unrestricted indirect size. | ||
| 464 | * The lack of a restriction on indirect size is a Freescale | ||
| 465 | * extension, indicated by PSn = 0 but SPSn != 0. | ||
| 466 | */ | ||
| 467 | if (eptcfg != 2) | ||
| 468 | book3e_htw_mode = PPC_HTW_NONE; | ||
| 448 | 469 | ||
| 449 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { | 470 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { |
| 450 | struct mmu_psize_def *def = &mmu_psize_defs[psize]; | 471 | struct mmu_psize_def *def = &mmu_psize_defs[psize]; |
| 451 | 472 | ||
| 452 | if (tlb1ps & (1U << (def->shift - 10))) { | 473 | if (tlb1ps & (1U << (def->shift - 10))) { |
| 453 | def->flags |= MMU_PAGE_SIZE_DIRECT; | 474 | def->flags |= MMU_PAGE_SIZE_DIRECT; |
| 475 | |||
| 476 | if (book3e_htw_mode && psize == MMU_PAGE_2M) | ||
| 477 | def->flags |= MMU_PAGE_SIZE_INDIRECT; | ||
| 454 | } | 478 | } |
| 455 | } | 479 | } |
| 456 | 480 | ||
| 457 | goto no_indirect; | 481 | goto out; |
| 458 | } | 482 | } |
| 459 | #endif | 483 | #endif |
| 460 | 484 | ||
| @@ -471,8 +495,11 @@ static void setup_page_sizes(void) | |||
| 471 | } | 495 | } |
| 472 | 496 | ||
| 473 | /* Indirect page sizes supported ? */ | 497 | /* Indirect page sizes supported ? */ |
| 474 | if ((tlb0cfg & TLBnCFG_IND) == 0) | 498 | if ((tlb0cfg & TLBnCFG_IND) == 0 || |
| 475 | goto no_indirect; | 499 | (tlb0cfg & TLBnCFG_PT) == 0) |
| 500 | goto out; | ||
| 501 | |||
| 502 | book3e_htw_mode = PPC_HTW_IBM; | ||
| 476 | 503 | ||
| 477 | /* Now, we only deal with one IND page size for each | 504 | /* Now, we only deal with one IND page size for each |
| 478 | * direct size. Hopefully all implementations today are | 505 | * direct size. Hopefully all implementations today are |
| @@ -497,8 +524,8 @@ static void setup_page_sizes(void) | |||
| 497 | def->ind = ps + 10; | 524 | def->ind = ps + 10; |
| 498 | } | 525 | } |
| 499 | } | 526 | } |
| 500 | no_indirect: | ||
| 501 | 527 | ||
| 528 | out: | ||
| 502 | /* Cleanup array and print summary */ | 529 | /* Cleanup array and print summary */ |
| 503 | pr_info("MMU: Supported page sizes\n"); | 530 | pr_info("MMU: Supported page sizes\n"); |
| 504 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { | 531 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { |
| @@ -520,23 +547,23 @@ static void setup_page_sizes(void) | |||
| 520 | 547 | ||
| 521 | static void setup_mmu_htw(void) | 548 | static void setup_mmu_htw(void) |
| 522 | { | 549 | { |
| 523 | /* Check if HW tablewalk is present, and if yes, enable it by: | 550 | /* |
| 524 | * | 551 | * If we want to use HW tablewalk, enable it by patching the TLB miss |
| 525 | * - patching the TLB miss handlers to branch to the | 552 | * handlers to branch to the one dedicated to it. |
| 526 | * one dedicates to it | 553 | */ |
| 527 | * | ||
| 528 | * - setting the global book3e_htw_enabled | ||
| 529 | */ | ||
| 530 | unsigned int tlb0cfg = mfspr(SPRN_TLB0CFG); | ||
| 531 | 554 | ||
| 532 | if ((tlb0cfg & TLBnCFG_IND) && | 555 | switch (book3e_htw_mode) { |
| 533 | (tlb0cfg & TLBnCFG_PT)) { | 556 | case PPC_HTW_IBM: |
| 534 | patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e); | 557 | patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e); |
| 535 | patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e); | 558 | patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e); |
| 536 | book3e_htw_enabled = 1; | 559 | break; |
| 560 | case PPC_HTW_E6500: | ||
| 561 | patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e); | ||
| 562 | patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e); | ||
| 563 | break; | ||
| 537 | } | 564 | } |
| 538 | pr_info("MMU: Book3E HW tablewalk %s\n", | 565 | pr_info("MMU: Book3E HW tablewalk %s\n", |
| 539 | book3e_htw_enabled ? "enabled" : "not supported"); | 566 | book3e_htw_mode != PPC_HTW_NONE ? "enabled" : "not supported"); |
| 540 | } | 567 | } |
| 541 | 568 | ||
| 542 | /* | 569 | /* |
| @@ -576,8 +603,16 @@ static void __early_init_mmu(int boot_cpu) | |||
| 576 | /* Set MAS4 based on page table setting */ | 603 | /* Set MAS4 based on page table setting */ |
| 577 | 604 | ||
| 578 | mas4 = 0x4 << MAS4_WIMGED_SHIFT; | 605 | mas4 = 0x4 << MAS4_WIMGED_SHIFT; |
| 579 | if (book3e_htw_enabled) { | 606 | switch (book3e_htw_mode) { |
| 580 | mas4 |= mas4 | MAS4_INDD; | 607 | case PPC_HTW_E6500: |
| 608 | mas4 |= MAS4_INDD; | ||
| 609 | mas4 |= BOOK3E_PAGESZ_2M << MAS4_TSIZED_SHIFT; | ||
| 610 | mas4 |= MAS4_TLBSELD(1); | ||
| 611 | mmu_pte_psize = MMU_PAGE_2M; | ||
| 612 | break; | ||
| 613 | |||
| 614 | case PPC_HTW_IBM: | ||
| 615 | mas4 |= MAS4_INDD; | ||
| 581 | #ifdef CONFIG_PPC_64K_PAGES | 616 | #ifdef CONFIG_PPC_64K_PAGES |
| 582 | mas4 |= BOOK3E_PAGESZ_256M << MAS4_TSIZED_SHIFT; | 617 | mas4 |= BOOK3E_PAGESZ_256M << MAS4_TSIZED_SHIFT; |
| 583 | mmu_pte_psize = MMU_PAGE_256M; | 618 | mmu_pte_psize = MMU_PAGE_256M; |
| @@ -585,13 +620,16 @@ static void __early_init_mmu(int boot_cpu) | |||
| 585 | mas4 |= BOOK3E_PAGESZ_1M << MAS4_TSIZED_SHIFT; | 620 | mas4 |= BOOK3E_PAGESZ_1M << MAS4_TSIZED_SHIFT; |
| 586 | mmu_pte_psize = MMU_PAGE_1M; | 621 | mmu_pte_psize = MMU_PAGE_1M; |
| 587 | #endif | 622 | #endif |
| 588 | } else { | 623 | break; |
| 624 | |||
| 625 | case PPC_HTW_NONE: | ||
| 589 | #ifdef CONFIG_PPC_64K_PAGES | 626 | #ifdef CONFIG_PPC_64K_PAGES |
| 590 | mas4 |= BOOK3E_PAGESZ_64K << MAS4_TSIZED_SHIFT; | 627 | mas4 |= BOOK3E_PAGESZ_64K << MAS4_TSIZED_SHIFT; |
| 591 | #else | 628 | #else |
| 592 | mas4 |= BOOK3E_PAGESZ_4K << MAS4_TSIZED_SHIFT; | 629 | mas4 |= BOOK3E_PAGESZ_4K << MAS4_TSIZED_SHIFT; |
| 593 | #endif | 630 | #endif |
| 594 | mmu_pte_psize = mmu_virtual_psize; | 631 | mmu_pte_psize = mmu_virtual_psize; |
| 632 | break; | ||
| 595 | } | 633 | } |
| 596 | mtspr(SPRN_MAS4, mas4); | 634 | mtspr(SPRN_MAS4, mas4); |
| 597 | 635 | ||
| @@ -611,8 +649,11 @@ static void __early_init_mmu(int boot_cpu) | |||
| 611 | /* limit memory so we dont have linear faults */ | 649 | /* limit memory so we dont have linear faults */ |
| 612 | memblock_enforce_memory_limit(linear_map_top); | 650 | memblock_enforce_memory_limit(linear_map_top); |
| 613 | 651 | ||
| 614 | patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); | 652 | if (book3e_htw_mode == PPC_HTW_NONE) { |
| 615 | patch_exception(0x1e0, exc_instruction_tlb_miss_bolted_book3e); | 653 | patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); |
| 654 | patch_exception(0x1e0, | ||
| 655 | exc_instruction_tlb_miss_bolted_book3e); | ||
| 656 | } | ||
| 616 | } | 657 | } |
| 617 | #endif | 658 | #endif |
| 618 | 659 | ||
