summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/head_64.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/head_64.S')
-rw-r--r--arch/powerpc/kernel/head_64.S152
1 files changed, 79 insertions, 73 deletions
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 831acbdf2592..3065b472b95d 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -21,7 +21,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/threads.h>
#include <asm/reg.h>
#include <asm/page.h>
@@ -85,34 +84,6 @@ END_FTR_SECTION(0, 1)
/* Catch branch to 0 in real mode */
trap
-#ifdef CONFIG_PPC_ISERIES
- /*
- * At offset 0x20, there is a pointer to iSeries LPAR data.
- * This is required by the hypervisor
- */
- . = 0x20
- .llong hvReleaseData-KERNELBASE
-
- /*
- * At offset 0x28 and 0x30 are offsets to the mschunks_map
- * array (used by the iSeries LPAR debugger to do translation
- * between physical addresses and absolute addresses) and
- * to the pidhash table (also used by the debugger)
- */
- .llong mschunks_map-KERNELBASE
- .llong 0 /* pidhash-KERNELBASE SFRXXX */
-
- /* Offset 0x38 - Pointer to start of embedded System.map */
- .globl embedded_sysmap_start
-embedded_sysmap_start:
- .llong 0
- /* Offset 0x40 - Pointer to end of embedded System.map */
- .globl embedded_sysmap_end
-embedded_sysmap_end:
- .llong 0
-
-#endif /* CONFIG_PPC_ISERIES */
-
/* Secondary processors spin on this value until it goes to 1. */
.globl __secondary_hold_spinloop
__secondary_hold_spinloop:
@@ -124,6 +95,15 @@ __secondary_hold_spinloop:
__secondary_hold_acknowledge:
.llong 0x0
+#ifdef CONFIG_PPC_ISERIES
+ /*
+ * At offset 0x20, there is a pointer to iSeries LPAR data.
+ * This is required by the hypervisor
+ */
+ . = 0x20
+ .llong hvReleaseData-KERNELBASE
+#endif /* CONFIG_PPC_ISERIES */
+
. = 0x60
/*
* The following code is used on pSeries to hold secondary processors
@@ -152,7 +132,7 @@ _GLOBAL(__secondary_hold)
bne 100b
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
- LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init)
+ LOAD_REG_IMMEDIATE(r4, .generic_secondary_smp_init)
mtctr r4
mr r3,r24
bctr
@@ -211,6 +191,37 @@ exception_marker:
ori reg,reg,(label)@l; /* virt addr of handler ... */
#endif
+/*
+ * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode.
+ * The firmware calls the registered system_reset_fwnmi and
+ * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run
+ * a 32bit application at the time of the event.
+ * This firmware bug is present on POWER4 and JS20.
+ */
+#define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label) \
+ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
+ std r9,area+EX_R9(r13); /* save r9 - r12 */ \
+ std r10,area+EX_R10(r13); \
+ std r11,area+EX_R11(r13); \
+ std r12,area+EX_R12(r13); \
+ mfspr r9,SPRN_SPRG1; \
+ std r9,area+EX_R13(r13); \
+ mfcr r9; \
+ clrrdi r12,r13,32; /* get high part of &label */ \
+ mfmsr r10; \
+ /* force 64bit mode */ \
+ li r11,5; /* MSR_SF_LG|MSR_ISF_LG */ \
+ rldimi r10,r11,61,0; /* insert into top 3 bits */ \
+ /* done 64bit mode */ \
+ mfspr r11,SPRN_SRR0; /* save SRR0 */ \
+ LOAD_HANDLER(r12,label) \
+ ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
+ mtspr SPRN_SRR0,r12; \
+ mfspr r12,SPRN_SRR1; /* and SRR1 */ \
+ mtspr SPRN_SRR1,r10; \
+ rfid; \
+ b . /* prevent speculative execution */
+
#define EXCEPTION_PROLOG_PSERIES(area, label) \
mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
std r9,area+EX_R9(r13); /* save r9 - r12 */ \
@@ -624,14 +635,14 @@ slb_miss_user_pseries:
system_reset_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+ EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)
.globl machine_check_fwnmi
.align 7
machine_check_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
- EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+ EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)
#ifdef CONFIG_PPC_ISERIES
/*** ISeries-LPAR interrupt handlers ***/
@@ -1473,19 +1484,17 @@ fwnmi_data_area:
. = 0x8000
/*
- * On pSeries, secondary processors spin in the following code.
+ * On pSeries and most other platforms, secondary processors spin
+ * in the following code.
* At entry, r3 = this processor's number (physical cpu id)
*/
-_GLOBAL(pSeries_secondary_smp_init)
+_GLOBAL(generic_secondary_smp_init)
mr r24,r3
/* turn on 64-bit mode */
bl .enable_64b_mode
isync
- /* Copy some CPU settings from CPU 0 */
- bl .__restore_cpu_setup
-
/* Set up a paca value for this processor. Since we have the
* physical cpu id in r24, we need to search the pacas to find
* which logical id maps to our physical one.
@@ -1511,15 +1520,28 @@ _GLOBAL(pSeries_secondary_smp_init)
/* start. */
sync
- /* Create a temp kernel stack for use before relocation is on. */
+#ifndef CONFIG_SMP
+ b 3b /* Never go on non-SMP */
+#else
+ cmpwi 0,r23,0
+ beq 3b /* Loop until told to go */
+
+ /* See if we need to call a cpu state restore handler */
+ LOAD_REG_IMMEDIATE(r23, cur_cpu_spec)
+ ld r23,0(r23)
+ ld r23,CPU_SPEC_RESTORE(r23)
+ cmpdi 0,r23,0
+ beq 4f
+ ld r23,0(r23)
+ mtctr r23
+ bctrl
+
+4: /* Create a temp kernel stack for use before relocation is on. */
ld r1,PACAEMERGSP(r13)
subi r1,r1,STACK_FRAME_OVERHEAD
- cmpwi 0,r23,0
-#ifdef CONFIG_SMP
- bne .__secondary_start
+ b .__secondary_start
#endif
- b 3b /* Loop until told to go */
#ifdef CONFIG_PPC_ISERIES
_STATIC(__start_initialization_iSeries)
@@ -1600,10 +1622,16 @@ _GLOBAL(__start_initialization_multiplatform)
bl .enable_64b_mode
/* Setup some critical 970 SPRs before switching MMU off */
- bl .__970_cpu_preinit
-
- /* cpu # */
- li r24,0
+ mfspr r0,SPRN_PVR
+ srwi r0,r0,16
+ cmpwi r0,0x39 /* 970 */
+ beq 1f
+ cmpwi r0,0x3c /* 970FX */
+ beq 1f
+ cmpwi r0,0x44 /* 970MP */
+ bne 2f
+1: bl .__cpu_preinit_ppc970
+2:
/* Switch off MMU if not already */
LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
@@ -1683,6 +1711,9 @@ _STATIC(__after_prom_start)
/* i.e. where we are running */
/* the source addr */
+ cmpdi r4,0 /* In some cases the loader may */
+ beq .start_here_multiplatform /* have already put us at zero */
+ /* so we can skip the copy. */
LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */
sub r5,r5,r27
@@ -1717,7 +1748,7 @@ _STATIC(__after_prom_start)
_GLOBAL(copy_and_flush)
addi r5,r5,-8
addi r6,r6,-8
-4: li r0,16 /* Use the least common */
+4: li r0,8 /* Use the smallest common */
/* denominator cache line */
/* size. This results in */
/* extra cache line flushes */
@@ -1771,7 +1802,7 @@ _GLOBAL(pmac_secondary_start)
isync
/* Copy some CPU settings from CPU 0 */
- bl .__restore_cpu_setup
+ bl .__restore_cpu_ppc970
/* pSeries do that early though I don't think we really need it */
mfmsr r3
@@ -1921,12 +1952,6 @@ _STATIC(start_here_multiplatform)
mr r5,r26
bl .identify_cpu
- /* Save some low level config HIDs of CPU0 to be copied to
- * other CPUs later on, or used for suspend/resume
- */
- bl .__save_cpu_setup
- sync
-
/* Do very early kernel initializations, including initial hash table,
* stab and slb setup before we turn on relocation. */
@@ -1962,14 +1987,6 @@ _STATIC(start_here_common)
li r3,0
bl .do_cpu_ftr_fixups
- LOAD_REG_IMMEDIATE(r26, boot_cpuid)
- lwz r26,0(r26)
-
- LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
- mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */
- add r13,r13,r24 /* for this processor. */
- mtspr SPRN_SPRG3,r13
-
/* ptr to current */
LOAD_REG_IMMEDIATE(r4, init_task)
std r4,PACACURRENT(r13)
@@ -1995,17 +2012,6 @@ _STATIC(start_here_common)
/* Not reached */
BUG_OPCODE
-/* Put the paca pointer into r13 and SPRG3 */
-_GLOBAL(setup_boot_paca)
- LOAD_REG_IMMEDIATE(r3, boot_cpuid)
- lwz r3,0(r3)
- LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */
- mulli r3,r3,PACA_SIZE /* Calculate vaddr of right paca */
- add r13,r3,r4 /* for this processor. */
- mtspr SPRN_SPRG3,r13
-
- blr
-
/*
* We put a few things here that have to be page-aligned.
* This stuff goes at the beginning of the bss, which is page-aligned.
OpenPOWER on IntegriCloud