diff options
Diffstat (limited to 'arch/powerpc/kernel/setup_64.c')
| -rw-r--r-- | arch/powerpc/kernel/setup_64.c | 113 | 
1 files changed, 94 insertions, 19 deletions
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 278ca93e1f2..ee082d77117 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -36,6 +36,7 @@  #include <linux/lockdep.h>  #include <linux/memblock.h>  #include <linux/hugetlb.h> +#include <linux/memory.h>  #include <asm/io.h>  #include <asm/kdump.h> @@ -68,15 +69,12 @@  #include <asm/hugetlb.h>  #include <asm/epapr_hcalls.h> -#include "setup.h" -  #ifdef DEBUG  #define DBG(fmt...) udbg_printf(fmt)  #else  #define DBG(fmt...)  #endif -int boot_cpuid = 0;  int spinning_secondaries;  u64 ppc64_pft_size; @@ -99,6 +97,38 @@ int dcache_bsize;  int icache_bsize;  int ucache_bsize; +#if defined(CONFIG_PPC_BOOK3E) && defined(CONFIG_SMP) +static void setup_tlb_core_data(void) +{ +	int cpu; + +	BUILD_BUG_ON(offsetof(struct tlb_core_data, lock) != 0); + +	for_each_possible_cpu(cpu) { +		int first = cpu_first_thread_sibling(cpu); + +		paca[cpu].tcd_ptr = &paca[first].tcd; + +		/* +		 * If we have threads, we need either tlbsrx. +		 * or e6500 tablewalk mode, or else TLB handlers +		 * will be racy and could produce duplicate entries. +		 */ +		if (smt_enabled_at_boot >= 2 && +		    !mmu_has_feature(MMU_FTR_USE_TLBRSRV) && +		    book3e_htw_mode != PPC_HTW_E6500) { +			/* Should we panic instead? */ +			WARN_ONCE("%s: unsupported MMU configuration -- expect problems\n", +				  __func__); +		} +	} +} +#else +static void setup_tlb_core_data(void) +{ +} +#endif +  #ifdef CONFIG_SMP  static char *smt_enabled_cmdline; @@ -166,6 +196,19 @@ static void fixup_boot_paca(void)  	get_paca()->data_offset = 0;  } +static void cpu_ready_for_interrupts(void) +{ +	/* Set IR and DR in PACA MSR */ +	get_paca()->kernel_msr = MSR_KERNEL; + +	/* Enable AIL if supported */ +	if (cpu_has_feature(CPU_FTR_HVMODE) && +	    cpu_has_feature(CPU_FTR_ARCH_207S)) { +		unsigned long lpcr = mfspr(SPRN_LPCR); +		mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3); +	} +} +  /*   * Early initialization entry point. This is called by head.S   * with MMU translation disabled. We rely on the "feature" of @@ -232,6 +275,14 @@ void __init early_setup(unsigned long dt_ptr)  	/* Initialize the hash table or TLB handling */  	early_init_mmu(); +	/* +	 * At this point, we can let interrupts switch to virtual mode +	 * (the MMU has been setup), so adjust the MSR in the PACA to +	 * have IR and DR set and enable AIL if it exists +	 */ +	cpu_ready_for_interrupts(); + +	/* Reserve large chunks of memory for use by CMA for KVM */  	kvm_cma_reserve();  	/* @@ -264,6 +315,13 @@ void early_setup_secondary(void)  	/* Initialize the hash table or TLB handling */  	early_init_mmu_secondary(); + +	/* +	 * At this point, we can let interrupts switch to virtual mode +	 * (the MMU has been setup), so adjust the MSR in the PACA to +	 * have IR and DR set. +	 */ +	cpu_ready_for_interrupts();  }  #endif /* CONFIG_SMP */ @@ -284,7 +342,7 @@ void smp_release_cpus(void)  	ptr  = (unsigned long *)((unsigned long)&__secondary_hold_spinloop  			- PHYSICAL_START); -	*ptr = __pa(generic_secondary_smp_init); +	*ptr = ppc_function_entry(generic_secondary_smp_init);  	/* And wait a bit for them to catch up */  	for (i = 0; i < 100000; i++) { @@ -447,6 +505,7 @@ void __init setup_system(void)  	smp_setup_cpu_maps();  	check_smt_enabled(); +	setup_tlb_core_data();  #ifdef CONFIG_SMP  	/* Release secondary cpus out of their spinloops at 0x60 now that @@ -522,23 +581,25 @@ static void __init irqstack_early_init(void)  #ifdef CONFIG_PPC_BOOK3E  static void __init exc_lvl_early_init(void)  { -	extern unsigned int interrupt_base_book3e; -	extern unsigned int exc_debug_debug_book3e; -  	unsigned int i; +	unsigned long sp;  	for_each_possible_cpu(i) { -		critirq_ctx[i] = (struct thread_info *) -			__va(memblock_alloc(THREAD_SIZE, THREAD_SIZE)); -		dbgirq_ctx[i] = (struct thread_info *) -			__va(memblock_alloc(THREAD_SIZE, THREAD_SIZE)); -		mcheckirq_ctx[i] = (struct thread_info *) -			__va(memblock_alloc(THREAD_SIZE, THREAD_SIZE)); +		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE); +		critirq_ctx[i] = (struct thread_info *)__va(sp); +		paca[i].crit_kstack = __va(sp + THREAD_SIZE); + +		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE); +		dbgirq_ctx[i] = (struct thread_info *)__va(sp); +		paca[i].dbg_kstack = __va(sp + THREAD_SIZE); + +		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE); +		mcheckirq_ctx[i] = (struct thread_info *)__va(sp); +		paca[i].mc_kstack = __va(sp + THREAD_SIZE);  	}  	if (cpu_has_feature(CPU_FTR_DEBUG_LVL_EXC)) -		patch_branch(&interrupt_base_book3e + (0x040 / 4) + 1, -			     (unsigned long)&exc_debug_debug_book3e, 0); +		patch_exception(0x040, exc_debug_debug_book3e);  }  #else  #define exc_lvl_early_init() @@ -546,7 +607,8 @@ static void __init exc_lvl_early_init(void)  /*   * Stack space used when we detect a bad kernel stack pointer, and - * early in SMP boots before relocation is enabled. + * early in SMP boots before relocation is enabled. Exclusive emergency + * stack for machine checks.   */  static void __init emergency_stack_init(void)  { @@ -569,6 +631,13 @@ static void __init emergency_stack_init(void)  		sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);  		sp += THREAD_SIZE;  		paca[i].emergency_sp = __va(sp); + +#ifdef CONFIG_PPC_BOOK3S_64 +		/* emergency stack for machine check exception handling. */ +		sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); +		sp += THREAD_SIZE; +		paca[i].mc_emergency_sp = __va(sp); +#endif  	}  } @@ -590,9 +659,6 @@ void __init setup_arch(char **cmdline_p)  	dcache_bsize = ppc64_caches.dline_size;  	icache_bsize = ppc64_caches.iline_size; -	/* reboot on panic */ -	panic_timeout = 180; -  	if (ppc_md.panic)  		setup_panic(); @@ -715,6 +781,15 @@ void __init setup_per_cpu_areas(void)  }  #endif +#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE +unsigned long memory_block_size_bytes(void) +{ +	if (ppc_md.memory_block_size) +		return ppc_md.memory_block_size(); + +	return MIN_MEMORY_BLOCK_SIZE; +} +#endif  #if defined(CONFIG_PPC_INDIRECT_PIO) || defined(CONFIG_PPC_INDIRECT_MMIO)  struct ppc_pci_io ppc_pci_io;  | 
