diff options
Diffstat (limited to 'arch/powerpc/mm')
| -rw-r--r-- | arch/powerpc/mm/Makefile | 6 | ||||
| -rw-r--r-- | arch/powerpc/mm/fault.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/mm/fsl_booke_mmu.c | 15 | ||||
| -rw-r--r-- | arch/powerpc/mm/mmu_context_nohash.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/mm/mmu_decl.h | 5 | ||||
| -rw-r--r-- | arch/powerpc/mm/tlb_nohash.c | 56 | ||||
| -rw-r--r-- | arch/powerpc/mm/tlb_nohash_low.S | 2 |
7 files changed, 79 insertions, 17 deletions
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index ce68708bbad..bdca46e0838 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
| @@ -4,9 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror |
| 6 | 6 | ||
| 7 | ifeq ($(CONFIG_PPC64),y) | 7 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc |
| 8 | EXTRA_CFLAGS += -mno-minimal-toc | ||
| 9 | endif | ||
| 10 | 8 | ||
| 11 | obj-y := fault.o mem.o pgtable.o gup.o \ | 9 | obj-y := fault.o mem.o pgtable.o gup.o \ |
| 12 | init_$(CONFIG_WORD_SIZE).o \ | 10 | init_$(CONFIG_WORD_SIZE).o \ |
| @@ -25,7 +23,7 @@ obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \ | |||
| 25 | mmu_context_hash$(CONFIG_WORD_SIZE).o | 23 | mmu_context_hash$(CONFIG_WORD_SIZE).o |
| 26 | obj-$(CONFIG_40x) += 40x_mmu.o | 24 | obj-$(CONFIG_40x) += 40x_mmu.o |
| 27 | obj-$(CONFIG_44x) += 44x_mmu.o | 25 | obj-$(CONFIG_44x) += 44x_mmu.o |
| 28 | obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o | 26 | obj-$(CONFIG_PPC_FSL_BOOK3E) += fsl_booke_mmu.o |
| 29 | obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o | 27 | obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o |
| 30 | obj-$(CONFIG_PPC_MM_SLICES) += slice.o | 28 | obj-$(CONFIG_PPC_MM_SLICES) += slice.o |
| 31 | ifeq ($(CONFIG_HUGETLB_PAGE),y) | 29 | ifeq ($(CONFIG_HUGETLB_PAGE),y) |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 1bd712c33ce..54f4fb994e9 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/kprobes.h> | 30 | #include <linux/kprobes.h> |
| 31 | #include <linux/kdebug.h> | 31 | #include <linux/kdebug.h> |
| 32 | #include <linux/perf_event.h> | 32 | #include <linux/perf_event.h> |
| 33 | #include <linux/magic.h> | ||
| 33 | 34 | ||
| 34 | #include <asm/firmware.h> | 35 | #include <asm/firmware.h> |
| 35 | #include <asm/page.h> | 36 | #include <asm/page.h> |
| @@ -385,6 +386,7 @@ do_sigbus: | |||
| 385 | void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) | 386 | void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) |
| 386 | { | 387 | { |
| 387 | const struct exception_table_entry *entry; | 388 | const struct exception_table_entry *entry; |
| 389 | unsigned long *stackend; | ||
| 388 | 390 | ||
| 389 | /* Are we prepared to handle this fault? */ | 391 | /* Are we prepared to handle this fault? */ |
| 390 | if ((entry = search_exception_tables(regs->nip)) != NULL) { | 392 | if ((entry = search_exception_tables(regs->nip)) != NULL) { |
| @@ -413,5 +415,9 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) | |||
| 413 | printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", | 415 | printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", |
| 414 | regs->nip); | 416 | regs->nip); |
| 415 | 417 | ||
| 418 | stackend = end_of_stack(current); | ||
| 419 | if (current != &init_task && *stackend != STACK_END_MAGIC) | ||
| 420 | printk(KERN_ALERT "Thread overran stack, or stack corrupted\n"); | ||
| 421 | |||
| 416 | die("Kernel access of bad area", regs, sig); | 422 | die("Kernel access of bad area", regs, sig); |
| 417 | } | 423 | } |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index cde270847e7..f7802c8bba0 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
| @@ -57,11 +57,6 @@ | |||
| 57 | 57 | ||
| 58 | unsigned int tlbcam_index; | 58 | unsigned int tlbcam_index; |
| 59 | 59 | ||
| 60 | |||
| 61 | #if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS) | ||
| 62 | #error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS" | ||
| 63 | #endif | ||
| 64 | |||
| 65 | #define NUM_TLBCAMS (64) | 60 | #define NUM_TLBCAMS (64) |
| 66 | struct tlbcam TLBCAM[NUM_TLBCAMS]; | 61 | struct tlbcam TLBCAM[NUM_TLBCAMS]; |
| 67 | 62 | ||
| @@ -138,7 +133,8 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys, | |||
| 138 | if (mmu_has_feature(MMU_FTR_BIG_PHYS)) | 133 | if (mmu_has_feature(MMU_FTR_BIG_PHYS)) |
| 139 | TLBCAM[index].MAS7 = (u64)phys >> 32; | 134 | TLBCAM[index].MAS7 = (u64)phys >> 32; |
| 140 | 135 | ||
| 141 | if (flags & _PAGE_USER) { | 136 | /* Below is unlikely -- only for large user pages or similar */ |
| 137 | if (pte_user(flags)) { | ||
| 142 | TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR; | 138 | TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR; |
| 143 | TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0); | 139 | TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0); |
| 144 | } | 140 | } |
| @@ -185,6 +181,12 @@ unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx) | |||
| 185 | return amount_mapped; | 181 | return amount_mapped; |
| 186 | } | 182 | } |
| 187 | 183 | ||
| 184 | #ifdef CONFIG_PPC32 | ||
| 185 | |||
| 186 | #if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS) | ||
| 187 | #error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS" | ||
| 188 | #endif | ||
| 189 | |||
| 188 | unsigned long __init mmu_mapin_ram(unsigned long top) | 190 | unsigned long __init mmu_mapin_ram(unsigned long top) |
| 189 | { | 191 | { |
| 190 | return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1; | 192 | return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1; |
| @@ -225,3 +227,4 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, | |||
| 225 | /* 64M mapped initially according to head_fsl_booke.S */ | 227 | /* 64M mapped initially according to head_fsl_booke.S */ |
| 226 | memblock_set_current_limit(min_t(u64, limit, 0x04000000)); | 228 | memblock_set_current_limit(min_t(u64, limit, 0x04000000)); |
| 227 | } | 229 | } |
| 230 | #endif | ||
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index ddfd7ad4e1d..5ce99848d91 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c | |||
| @@ -334,7 +334,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, | |||
| 334 | /* We don't touch CPU 0 map, it's allocated at aboot and kept | 334 | /* We don't touch CPU 0 map, it's allocated at aboot and kept |
| 335 | * around forever | 335 | * around forever |
| 336 | */ | 336 | */ |
| 337 | if (cpu == 0) | 337 | if (cpu == boot_cpuid) |
| 338 | return NOTIFY_OK; | 338 | return NOTIFY_OK; |
| 339 | 339 | ||
| 340 | switch (action) { | 340 | switch (action) { |
| @@ -420,9 +420,11 @@ void __init mmu_context_init(void) | |||
| 420 | */ | 420 | */ |
| 421 | context_map = alloc_bootmem(CTX_MAP_SIZE); | 421 | context_map = alloc_bootmem(CTX_MAP_SIZE); |
| 422 | context_mm = alloc_bootmem(sizeof(void *) * (last_context + 1)); | 422 | context_mm = alloc_bootmem(sizeof(void *) * (last_context + 1)); |
| 423 | #ifndef CONFIG_SMP | ||
| 423 | stale_map[0] = alloc_bootmem(CTX_MAP_SIZE); | 424 | stale_map[0] = alloc_bootmem(CTX_MAP_SIZE); |
| 425 | #else | ||
| 426 | stale_map[boot_cpuid] = alloc_bootmem(CTX_MAP_SIZE); | ||
| 424 | 427 | ||
| 425 | #ifdef CONFIG_SMP | ||
| 426 | register_cpu_notifier(&mmu_context_cpu_nb); | 428 | register_cpu_notifier(&mmu_context_cpu_nb); |
| 427 | #endif | 429 | #endif |
| 428 | 430 | ||
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 63b84a0d3b1..dd0a2589591 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
| @@ -140,10 +140,13 @@ extern void wii_memory_fixups(void); | |||
| 140 | extern void MMU_init_hw(void); | 140 | extern void MMU_init_hw(void); |
| 141 | extern unsigned long mmu_mapin_ram(unsigned long top); | 141 | extern unsigned long mmu_mapin_ram(unsigned long top); |
| 142 | 142 | ||
| 143 | #elif defined(CONFIG_FSL_BOOKE) | 143 | #elif defined(CONFIG_PPC_FSL_BOOK3E) |
| 144 | extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx); | ||
| 145 | #ifdef CONFIG_PPC32 | ||
| 144 | extern void MMU_init_hw(void); | 146 | extern void MMU_init_hw(void); |
| 145 | extern unsigned long mmu_mapin_ram(unsigned long top); | 147 | extern unsigned long mmu_mapin_ram(unsigned long top); |
| 146 | extern void adjust_total_lowmem(void); | 148 | extern void adjust_total_lowmem(void); |
| 149 | #endif | ||
| 147 | extern void loadcam_entry(unsigned int index); | 150 | extern void loadcam_entry(unsigned int index); |
| 148 | 151 | ||
| 149 | struct tlbcam { | 152 | struct tlbcam { |
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index 6a0f20c2546..36c0c449a89 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
| @@ -349,11 +349,47 @@ void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address) | |||
| 349 | 349 | ||
| 350 | static void setup_page_sizes(void) | 350 | static void setup_page_sizes(void) |
| 351 | { | 351 | { |
| 352 | unsigned int tlb0cfg = mfspr(SPRN_TLB0CFG); | 352 | unsigned int tlb0cfg; |
| 353 | unsigned int tlb0ps = mfspr(SPRN_TLB0PS); | 353 | unsigned int tlb0ps; |
| 354 | unsigned int eptcfg = mfspr(SPRN_EPTCFG); | 354 | unsigned int eptcfg; |
| 355 | int i, psize; | 355 | int i, psize; |
| 356 | 356 | ||
| 357 | #ifdef CONFIG_PPC_FSL_BOOK3E | ||
| 358 | unsigned int mmucfg = mfspr(SPRN_MMUCFG); | ||
| 359 | |||
| 360 | if (((mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) && | ||
| 361 | (mmu_has_feature(MMU_FTR_TYPE_FSL_E))) { | ||
| 362 | unsigned int tlb1cfg = mfspr(SPRN_TLB1CFG); | ||
| 363 | unsigned int min_pg, max_pg; | ||
| 364 | |||
| 365 | min_pg = (tlb1cfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT; | ||
| 366 | max_pg = (tlb1cfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT; | ||
| 367 | |||
| 368 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { | ||
| 369 | struct mmu_psize_def *def; | ||
| 370 | unsigned int shift; | ||
| 371 | |||
| 372 | def = &mmu_psize_defs[psize]; | ||
| 373 | shift = def->shift; | ||
| 374 | |||
| 375 | if (shift == 0) | ||
| 376 | continue; | ||
| 377 | |||
| 378 | /* adjust to be in terms of 4^shift Kb */ | ||
| 379 | shift = (shift - 10) >> 1; | ||
| 380 | |||
| 381 | if ((shift >= min_pg) && (shift <= max_pg)) | ||
| 382 | def->flags |= MMU_PAGE_SIZE_DIRECT; | ||
| 383 | } | ||
| 384 | |||
| 385 | goto no_indirect; | ||
| 386 | } | ||
| 387 | #endif | ||
| 388 | |||
| 389 | tlb0cfg = mfspr(SPRN_TLB0CFG); | ||
| 390 | tlb0ps = mfspr(SPRN_TLB0PS); | ||
| 391 | eptcfg = mfspr(SPRN_EPTCFG); | ||
| 392 | |||
| 357 | /* Look for supported direct sizes */ | 393 | /* Look for supported direct sizes */ |
| 358 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { | 394 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { |
| 359 | struct mmu_psize_def *def = &mmu_psize_defs[psize]; | 395 | struct mmu_psize_def *def = &mmu_psize_defs[psize]; |
| @@ -505,6 +541,20 @@ static void __early_init_mmu(int boot_cpu) | |||
| 505 | */ | 541 | */ |
| 506 | linear_map_top = memblock_end_of_DRAM(); | 542 | linear_map_top = memblock_end_of_DRAM(); |
| 507 | 543 | ||
| 544 | #ifdef CONFIG_PPC_FSL_BOOK3E | ||
| 545 | if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { | ||
| 546 | unsigned int num_cams; | ||
| 547 | |||
| 548 | /* use a quarter of the TLBCAM for bolted linear map */ | ||
| 549 | num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; | ||
| 550 | linear_map_top = map_mem_in_cams(linear_map_top, num_cams); | ||
| 551 | |||
| 552 | /* limit memory so we dont have linear faults */ | ||
| 553 | memblock_enforce_memory_limit(linear_map_top); | ||
| 554 | memblock_analyze(); | ||
| 555 | } | ||
| 556 | #endif | ||
| 557 | |||
| 508 | /* A sync won't hurt us after mucking around with | 558 | /* A sync won't hurt us after mucking around with |
| 509 | * the MMU configuration | 559 | * the MMU configuration |
| 510 | */ | 560 | */ |
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S index b9d9fed8f36..af405eefe48 100644 --- a/arch/powerpc/mm/tlb_nohash_low.S +++ b/arch/powerpc/mm/tlb_nohash_low.S | |||
| @@ -367,7 +367,7 @@ _GLOBAL(set_context) | |||
| 367 | #error Unsupported processor type ! | 367 | #error Unsupported processor type ! |
| 368 | #endif | 368 | #endif |
| 369 | 369 | ||
| 370 | #if defined(CONFIG_FSL_BOOKE) | 370 | #if defined(CONFIG_PPC_FSL_BOOK3E) |
| 371 | /* | 371 | /* |
| 372 | * extern void loadcam_entry(unsigned int index) | 372 | * extern void loadcam_entry(unsigned int index) |
| 373 | * | 373 | * |
