diff options
Diffstat (limited to 'arch/powerpc/kernel/setup_64.c')
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 95 |
1 files changed, 74 insertions, 21 deletions
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 1f6816003ebe..797ea95aae2e 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -57,11 +57,13 @@ | |||
57 | #include <asm/cache.h> | 57 | #include <asm/cache.h> |
58 | #include <asm/page.h> | 58 | #include <asm/page.h> |
59 | #include <asm/mmu.h> | 59 | #include <asm/mmu.h> |
60 | #include <asm/mmu-hash64.h> | ||
60 | #include <asm/firmware.h> | 61 | #include <asm/firmware.h> |
61 | #include <asm/xmon.h> | 62 | #include <asm/xmon.h> |
62 | #include <asm/udbg.h> | 63 | #include <asm/udbg.h> |
63 | #include <asm/kexec.h> | 64 | #include <asm/kexec.h> |
64 | #include <asm/swiotlb.h> | 65 | #include <asm/swiotlb.h> |
66 | #include <asm/mmu_context.h> | ||
65 | 67 | ||
66 | #include "setup.h" | 68 | #include "setup.h" |
67 | 69 | ||
@@ -142,11 +144,14 @@ early_param("smt-enabled", early_smt_enabled); | |||
142 | #define check_smt_enabled() | 144 | #define check_smt_enabled() |
143 | #endif /* CONFIG_SMP */ | 145 | #endif /* CONFIG_SMP */ |
144 | 146 | ||
145 | /* Put the paca pointer into r13 and SPRG3 */ | 147 | /* Put the paca pointer into r13 and SPRG_PACA */ |
146 | void __init setup_paca(int cpu) | 148 | void __init setup_paca(int cpu) |
147 | { | 149 | { |
148 | local_paca = &paca[cpu]; | 150 | local_paca = &paca[cpu]; |
149 | mtspr(SPRN_SPRG3, local_paca); | 151 | mtspr(SPRN_SPRG_PACA, local_paca); |
152 | #ifdef CONFIG_PPC_BOOK3E | ||
153 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); | ||
154 | #endif | ||
150 | } | 155 | } |
151 | 156 | ||
152 | /* | 157 | /* |
@@ -230,9 +235,6 @@ void early_setup_secondary(void) | |||
230 | #endif /* CONFIG_SMP */ | 235 | #endif /* CONFIG_SMP */ |
231 | 236 | ||
232 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) | 237 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) |
233 | extern unsigned long __secondary_hold_spinloop; | ||
234 | extern void generic_secondary_smp_init(void); | ||
235 | |||
236 | void smp_release_cpus(void) | 238 | void smp_release_cpus(void) |
237 | { | 239 | { |
238 | unsigned long *ptr; | 240 | unsigned long *ptr; |
@@ -453,6 +455,24 @@ static void __init irqstack_early_init(void) | |||
453 | #define irqstack_early_init() | 455 | #define irqstack_early_init() |
454 | #endif | 456 | #endif |
455 | 457 | ||
458 | #ifdef CONFIG_PPC_BOOK3E | ||
459 | static void __init exc_lvl_early_init(void) | ||
460 | { | ||
461 | unsigned int i; | ||
462 | |||
463 | for_each_possible_cpu(i) { | ||
464 | critirq_ctx[i] = (struct thread_info *) | ||
465 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
466 | dbgirq_ctx[i] = (struct thread_info *) | ||
467 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
468 | mcheckirq_ctx[i] = (struct thread_info *) | ||
469 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
470 | } | ||
471 | } | ||
472 | #else | ||
473 | #define exc_lvl_early_init() | ||
474 | #endif | ||
475 | |||
456 | /* | 476 | /* |
457 | * Stack space used when we detect a bad kernel stack pointer, and | 477 | * Stack space used when we detect a bad kernel stack pointer, and |
458 | * early in SMP boots before relocation is enabled. | 478 | * early in SMP boots before relocation is enabled. |
@@ -512,6 +532,7 @@ void __init setup_arch(char **cmdline_p) | |||
512 | init_mm.brk = klimit; | 532 | init_mm.brk = klimit; |
513 | 533 | ||
514 | irqstack_early_init(); | 534 | irqstack_early_init(); |
535 | exc_lvl_early_init(); | ||
515 | emergency_stack_init(); | 536 | emergency_stack_init(); |
516 | 537 | ||
517 | #ifdef CONFIG_PPC_STD_MMU_64 | 538 | #ifdef CONFIG_PPC_STD_MMU_64 |
@@ -534,6 +555,10 @@ void __init setup_arch(char **cmdline_p) | |||
534 | #endif | 555 | #endif |
535 | 556 | ||
536 | paging_init(); | 557 | paging_init(); |
558 | |||
559 | /* Initialize the MMU context management stuff */ | ||
560 | mmu_context_init(); | ||
561 | |||
537 | ppc64_boot_msg(0x15, "Setup Done"); | 562 | ppc64_boot_msg(0x15, "Setup Done"); |
538 | } | 563 | } |
539 | 564 | ||
@@ -569,25 +594,53 @@ void cpu_die(void) | |||
569 | } | 594 | } |
570 | 595 | ||
571 | #ifdef CONFIG_SMP | 596 | #ifdef CONFIG_SMP |
572 | void __init setup_per_cpu_areas(void) | 597 | #define PCPU_DYN_SIZE () |
598 | |||
599 | static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align) | ||
573 | { | 600 | { |
574 | int i; | 601 | return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align, |
575 | unsigned long size; | 602 | __pa(MAX_DMA_ADDRESS)); |
576 | char *ptr; | 603 | } |
577 | |||
578 | /* Copy section for each CPU (we discard the original) */ | ||
579 | size = ALIGN(__per_cpu_end - __per_cpu_start, PAGE_SIZE); | ||
580 | #ifdef CONFIG_MODULES | ||
581 | if (size < PERCPU_ENOUGH_ROOM) | ||
582 | size = PERCPU_ENOUGH_ROOM; | ||
583 | #endif | ||
584 | 604 | ||
585 | for_each_possible_cpu(i) { | 605 | static void __init pcpu_fc_free(void *ptr, size_t size) |
586 | ptr = alloc_bootmem_pages_node(NODE_DATA(cpu_to_node(i)), size); | 606 | { |
607 | free_bootmem(__pa(ptr), size); | ||
608 | } | ||
587 | 609 | ||
588 | paca[i].data_offset = ptr - __per_cpu_start; | 610 | static int pcpu_cpu_distance(unsigned int from, unsigned int to) |
589 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); | 611 | { |
590 | } | 612 | if (cpu_to_node(from) == cpu_to_node(to)) |
613 | return LOCAL_DISTANCE; | ||
614 | else | ||
615 | return REMOTE_DISTANCE; | ||
616 | } | ||
617 | |||
618 | void __init setup_per_cpu_areas(void) | ||
619 | { | ||
620 | const size_t dyn_size = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; | ||
621 | size_t atom_size; | ||
622 | unsigned long delta; | ||
623 | unsigned int cpu; | ||
624 | int rc; | ||
625 | |||
626 | /* | ||
627 | * Linear mapping is one of 4K, 1M and 16M. For 4K, no need | ||
628 | * to group units. For larger mappings, use 1M atom which | ||
629 | * should be large enough to contain a number of units. | ||
630 | */ | ||
631 | if (mmu_linear_psize == MMU_PAGE_4K) | ||
632 | atom_size = PAGE_SIZE; | ||
633 | else | ||
634 | atom_size = 1 << 20; | ||
635 | |||
636 | rc = pcpu_embed_first_chunk(0, dyn_size, atom_size, pcpu_cpu_distance, | ||
637 | pcpu_fc_alloc, pcpu_fc_free); | ||
638 | if (rc < 0) | ||
639 | panic("cannot initialize percpu area (err=%d)", rc); | ||
640 | |||
641 | delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; | ||
642 | for_each_possible_cpu(cpu) | ||
643 | paca[cpu].data_offset = delta + pcpu_unit_offsets[cpu]; | ||
591 | } | 644 | } |
592 | #endif | 645 | #endif |
593 | 646 | ||