aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-09-22 22:04:45 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-10-11 01:48:34 -0400
commit5c0484e25ec03243d4c2f2d4416d4a13efc77f6a (patch)
treefe31fb5e5be50119f39d2e22953f13d8ace85cb1
parentc57a5ce0df04be61bafedc0f3043d568103c7ab5 (diff)
powerpc: Endian safe trampoline
Create a trampoline that works in either endian and flips to the expected endian. Use it for primary and secondary thread entry as well as RTAS and OF call return. Credit for finding the magic instruction goes to Paul Mackerras Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h31
-rw-r--r--arch/powerpc/kernel/entry_64.S36
-rw-r--r--arch/powerpc/kernel/head_64.S3
3 files changed, 53 insertions, 17 deletions
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0c51fb4fd2aa..ce05bba0bfc6 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -845,6 +845,35 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946)
845#define N_SLINE 68 845#define N_SLINE 68
846#define N_SO 100 846#define N_SO 100
847 847
848#endif /* __ASSEMBLY__ */ 848/*
849 * Create an endian fixup trampoline
850 *
851 * This starts with a "tdi 0,0,0x48" instruction which is
852 * essentially a "trap never", and thus akin to a nop.
853 *
854 * The opcode for this instruction read with the wrong endian
855 * however results in a b . + 8
856 *
857 * So essentially we use that trick to execute the following
858 * trampoline in "reverse endian" if we are running with the
859 * MSR_LE bit set the "wrong" way for whatever endianness the
860 * kernel is built for.
861 */
849 862
863#ifdef CONFIG_PPC_BOOK3E
864#define FIXUP_ENDIAN
865#else
866#define FIXUP_ENDIAN \
867 tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
868 b $+36; /* Skip trampoline if endian is good */ \
869 .long 0x05009f42; /* bcl 20,31,$+4 */ \
870 .long 0xa602487d; /* mflr r10 */ \
871 .long 0x1c004a39; /* addi r10,r10,28 */ \
872 .long 0xa600607d; /* mfmsr r11 */ \
873 .long 0x01006b69; /* xori r11,r11,1 */ \
874 .long 0xa6035a7d; /* mtsrr0 r10 */ \
875 .long 0xa6037b7d; /* mtsrr1 r11 */ \
876 .long 0x2400004c /* rfid */
877#endif /* !CONFIG_PPC_BOOK3E */
878#endif /* __ASSEMBLY__ */
850#endif /* _ASM_POWERPC_PPC_ASM_H */ 879#endif /* _ASM_POWERPC_PPC_ASM_H */
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index c04cdf70d487..889ea2b19383 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -1017,7 +1017,7 @@ _GLOBAL(enter_rtas)
1017 1017
1018 li r9,1 1018 li r9,1
1019 rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG) 1019 rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
1020 ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI 1020 ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI|MSR_LE
1021 andc r6,r0,r9 1021 andc r6,r0,r9
1022 sync /* disable interrupts so SRR0/1 */ 1022 sync /* disable interrupts so SRR0/1 */
1023 mtmsrd r0 /* don't get trashed */ 1023 mtmsrd r0 /* don't get trashed */
@@ -1032,6 +1032,8 @@ _GLOBAL(enter_rtas)
1032 b . /* prevent speculative execution */ 1032 b . /* prevent speculative execution */
1033 1033
1034_STATIC(rtas_return_loc) 1034_STATIC(rtas_return_loc)
1035 FIXUP_ENDIAN
1036
1035 /* relocation is off at this point */ 1037 /* relocation is off at this point */
1036 GET_PACA(r4) 1038 GET_PACA(r4)
1037 clrldi r4,r4,2 /* convert to realmode address */ 1039 clrldi r4,r4,2 /* convert to realmode address */
@@ -1103,28 +1105,30 @@ _GLOBAL(enter_prom)
1103 std r10,_CCR(r1) 1105 std r10,_CCR(r1)
1104 std r11,_MSR(r1) 1106 std r11,_MSR(r1)
1105 1107
1106 /* Get the PROM entrypoint */ 1108 /* Put PROM address in SRR0 */
1107 mtlr r4 1109 mtsrr0 r4
1110
1111 /* Setup our trampoline return addr in LR */
1112 bcl 20,31,$+4
11130: mflr r4
1114 addi r4,r4,(1f - 0b)
1115 mtlr r4
1108 1116
1109 /* Switch MSR to 32 bits mode 1117 /* Prepare a 32-bit mode big endian MSR
1110 */ 1118 */
1111#ifdef CONFIG_PPC_BOOK3E 1119#ifdef CONFIG_PPC_BOOK3E
1112 rlwinm r11,r11,0,1,31 1120 rlwinm r11,r11,0,1,31
1113 mtmsr r11 1121 mtsrr1 r11
1122 rfi
1114#else /* CONFIG_PPC_BOOK3E */ 1123#else /* CONFIG_PPC_BOOK3E */
1115 mfmsr r11 1124 LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_ISF | MSR_LE)
1116 li r12,1 1125 andc r11,r11,r12
1117 rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) 1126 mtsrr1 r11
1118 andc r11,r11,r12 1127 rfid
1119 li r12,1
1120 rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
1121 andc r11,r11,r12
1122 mtmsrd r11
1123#endif /* CONFIG_PPC_BOOK3E */ 1128#endif /* CONFIG_PPC_BOOK3E */
1124 isync
1125 1129
1126 /* Enter PROM here... */ 11301: /* Return from OF */
1127 blrl 1131 FIXUP_ENDIAN
1128 1132
1129 /* Just make sure that r1 top 32 bits didn't get 1133 /* Just make sure that r1 top 32 bits didn't get
1130 * corrupt by OF 1134 * corrupt by OF
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 3d11d8038dee..2ae41aba4053 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -68,6 +68,7 @@ _stext:
68_GLOBAL(__start) 68_GLOBAL(__start)
69 /* NOP this out unconditionally */ 69 /* NOP this out unconditionally */
70BEGIN_FTR_SECTION 70BEGIN_FTR_SECTION
71 FIXUP_ENDIAN
71 b .__start_initialization_multiplatform 72 b .__start_initialization_multiplatform
72END_FTR_SECTION(0, 1) 73END_FTR_SECTION(0, 1)
73 74
@@ -115,6 +116,7 @@ __run_at_load:
115 */ 116 */
116 .globl __secondary_hold 117 .globl __secondary_hold
117__secondary_hold: 118__secondary_hold:
119 FIXUP_ENDIAN
118#ifndef CONFIG_PPC_BOOK3E 120#ifndef CONFIG_PPC_BOOK3E
119 mfmsr r24 121 mfmsr r24
120 ori r24,r24,MSR_RI 122 ori r24,r24,MSR_RI
@@ -205,6 +207,7 @@ _GLOBAL(generic_secondary_thread_init)
205 * as SCOM before entry). 207 * as SCOM before entry).
206 */ 208 */
207_GLOBAL(generic_secondary_smp_init) 209_GLOBAL(generic_secondary_smp_init)
210 FIXUP_ENDIAN
208 mr r24,r3 211 mr r24,r3
209 mr r25,r4 212 mr r25,r4
210 213