Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c0484e2 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarAnton Blanchard <anton@samba.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent c57a5ce0
Loading
Loading
Loading
Loading
+30 −1
Original line number Original line Diff line number Diff line
@@ -845,6 +845,35 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946)
#define N_SLINE	68
#define N_SLINE	68
#define N_SO	100
#define N_SO	100


#endif /*  __ASSEMBLY__ */
/*
 * Create an endian fixup trampoline
 *
 * This starts with a "tdi 0,0,0x48" instruction which is
 * essentially a "trap never", and thus akin to a nop.
 *
 * The opcode for this instruction read with the wrong endian
 * however results in a b . + 8
 *
 * So essentially we use that trick to execute the following
 * trampoline in "reverse endian" if we are running with the
 * MSR_LE bit set the "wrong" way for whatever endianness the
 * kernel is built for.
 */


#ifdef CONFIG_PPC_BOOK3E
#define FIXUP_ENDIAN
#else
#define FIXUP_ENDIAN						   \
	tdi   0,0,0x48;	  /* Reverse endian of b . + 8		*/ \
	b     $+36;	  /* Skip trampoline if endian is good	*/ \
	.long 0x05009f42; /* bcl 20,31,$+4			*/ \
	.long 0xa602487d; /* mflr r10				*/ \
	.long 0x1c004a39; /* addi r10,r10,28			*/ \
	.long 0xa600607d; /* mfmsr r11				*/ \
	.long 0x01006b69; /* xori r11,r11,1			*/ \
	.long 0xa6035a7d; /* mtsrr0 r10				*/ \
	.long 0xa6037b7d; /* mtsrr1 r11				*/ \
	.long 0x2400004c  /* rfid				*/
#endif /* !CONFIG_PPC_BOOK3E */
#endif /*  __ASSEMBLY__ */
#endif /* _ASM_POWERPC_PPC_ASM_H */
#endif /* _ASM_POWERPC_PPC_ASM_H */
+20 −16
Original line number Original line Diff line number Diff line
@@ -1017,7 +1017,7 @@ _GLOBAL(enter_rtas)
	
	
        li      r9,1
        li      r9,1
        rldicr  r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
        rldicr  r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
	ori	r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI
	ori	r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI|MSR_LE
	andc	r6,r0,r9
	andc	r6,r0,r9
	sync				/* disable interrupts so SRR0/1 */
	sync				/* disable interrupts so SRR0/1 */
	mtmsrd	r0			/* don't get trashed */
	mtmsrd	r0			/* don't get trashed */
@@ -1032,6 +1032,8 @@ _GLOBAL(enter_rtas)
	b	.	/* prevent speculative execution */
	b	.	/* prevent speculative execution */


_STATIC(rtas_return_loc)
_STATIC(rtas_return_loc)
	FIXUP_ENDIAN

	/* relocation is off at this point */
	/* relocation is off at this point */
	GET_PACA(r4)
	GET_PACA(r4)
	clrldi	r4,r4,2			/* convert to realmode address */
	clrldi	r4,r4,2			/* convert to realmode address */
@@ -1103,28 +1105,30 @@ _GLOBAL(enter_prom)
	std	r10,_CCR(r1)
	std	r10,_CCR(r1)
	std	r11,_MSR(r1)
	std	r11,_MSR(r1)


	/* Get the PROM entrypoint */
	/* Put PROM address in SRR0 */
	mtsrr0	r4

	/* Setup our trampoline return addr in LR */
	bcl	20,31,$+4
0:	mflr	r4
	addi	r4,r4,(1f - 0b)
       	mtlr	r4
       	mtlr	r4


	/* Switch MSR to 32 bits mode
	/* Prepare a 32-bit mode big endian MSR
	 */
	 */
#ifdef CONFIG_PPC_BOOK3E
#ifdef CONFIG_PPC_BOOK3E
	rlwinm	r11,r11,0,1,31
	rlwinm	r11,r11,0,1,31
	mtmsr	r11
	mtsrr1	r11
	rfi
#else /* CONFIG_PPC_BOOK3E */
#else /* CONFIG_PPC_BOOK3E */
        mfmsr   r11
	LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_ISF | MSR_LE)
        li      r12,1
        rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
	andc	r11,r11,r12
	andc	r11,r11,r12
        li      r12,1
	mtsrr1	r11
        rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
	rfid
        andc    r11,r11,r12
        mtmsrd  r11
#endif /* CONFIG_PPC_BOOK3E */
#endif /* CONFIG_PPC_BOOK3E */
        isync


	/* Enter PROM here... */
1:	/* Return from OF */
	blrl
	FIXUP_ENDIAN


	/* Just make sure that r1 top 32 bits didn't get
	/* Just make sure that r1 top 32 bits didn't get
	 * corrupt by OF
	 * corrupt by OF
+3 −0
Original line number Original line Diff line number Diff line
@@ -68,6 +68,7 @@ _stext:
_GLOBAL(__start)
_GLOBAL(__start)
	/* NOP this out unconditionally */
	/* NOP this out unconditionally */
BEGIN_FTR_SECTION
BEGIN_FTR_SECTION
	FIXUP_ENDIAN
	b	.__start_initialization_multiplatform
	b	.__start_initialization_multiplatform
END_FTR_SECTION(0, 1)
END_FTR_SECTION(0, 1)


@@ -115,6 +116,7 @@ __run_at_load:
 */
 */
	.globl	__secondary_hold
	.globl	__secondary_hold
__secondary_hold:
__secondary_hold:
	FIXUP_ENDIAN
#ifndef CONFIG_PPC_BOOK3E
#ifndef CONFIG_PPC_BOOK3E
	mfmsr	r24
	mfmsr	r24
	ori	r24,r24,MSR_RI
	ori	r24,r24,MSR_RI
@@ -205,6 +207,7 @@ _GLOBAL(generic_secondary_thread_init)
 * as SCOM before entry).
 * as SCOM before entry).
 */
 */
_GLOBAL(generic_secondary_smp_init)
_GLOBAL(generic_secondary_smp_init)
	FIXUP_ENDIAN
	mr	r24,r3
	mr	r24,r3
	mr	r25,r4
	mr	r25,r4