xref: /openbmc/linux/arch/powerpc/kernel/rtas_entry.S (revision 2bc7d3e0)
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include <asm/asm-offsets.h>
4#include <asm/bug.h>
5#include <asm/page.h>
6#include <asm/ppc_asm.h>
7
8/*
9 * RTAS is called with MSR IR, DR, EE disabled, and LR in the return address.
10 *
11 * Note: r3 is an input parameter to rtas, so don't trash it...
12 */
13
14#ifdef CONFIG_PPC32
15_GLOBAL(enter_rtas)
16	stwu	r1,-INT_FRAME_SIZE(r1)
17	mflr	r0
18	stw	r0,INT_FRAME_SIZE+4(r1)
19	LOAD_REG_ADDR(r4, rtas)
20	lis	r6,1f@ha	/* physical return address for rtas */
21	addi	r6,r6,1f@l
22	tophys(r6,r6)
23	lwz	r8,RTASENTRY(r4)
24	lwz	r4,RTASBASE(r4)
25	mfmsr	r9
26	stw	r9,8(r1)
27	li	r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
28	mtlr	r6
29	stw	r1, THREAD + RTAS_SP(r2)
30	mtspr	SPRN_SRR0,r8
31	mtspr	SPRN_SRR1,r9
32	rfi
331:
34	lis	r8, 1f@h
35	ori	r8, r8, 1f@l
36	LOAD_REG_IMMEDIATE(r9,MSR_KERNEL)
37	mtspr	SPRN_SRR0,r8
38	mtspr	SPRN_SRR1,r9
39	rfi			/* Reactivate MMU translation */
401:
41	lwz	r8,INT_FRAME_SIZE+4(r1)	/* get return address */
42	lwz	r9,8(r1)	/* original msr value */
43	addi	r1,r1,INT_FRAME_SIZE
44	li	r0,0
45	stw	r0, THREAD + RTAS_SP(r2)
46	mtlr	r8
47	mtmsr	r9
48	blr			/* return to caller */
49_ASM_NOKPROBE_SYMBOL(enter_rtas)
50
51#else /* CONFIG_PPC32 */
52#include <asm/exception-64s.h>
53
54/*
55 * 32-bit rtas on 64-bit machines has the additional problem that RTAS may
56 * not preserve the upper parts of registers it uses.
57 */
58_GLOBAL(enter_rtas)
59	mflr	r0
60	std	r0,16(r1)
61	stdu	r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */
62
63	/* Because RTAS is running in 32b mode, it clobbers the high order half
64	 * of all registers that it saves.  We therefore save those registers
65	 * RTAS might touch to the stack.  (r0, r3-r12 are caller saved)
66	 */
67	SAVE_GPR(2, r1)			/* Save the TOC */
68	SAVE_NVGPRS(r1)			/* Save the non-volatiles */
69
70	mfcr	r4
71	std	r4,_CCR(r1)
72	mfctr	r5
73	std	r5,_CTR(r1)
74	mfspr	r6,SPRN_XER
75	std	r6,_XER(r1)
76	mfdar	r7
77	std	r7,_DAR(r1)
78	mfdsisr	r8
79	std	r8,_DSISR(r1)
80
81	/* Temporary workaround to clear CR until RTAS can be modified to
82	 * ignore all bits.
83	 */
84	li	r0,0
85	mtcr	r0
86
87	mfmsr	r6
88
89	/* Unfortunately, the stack pointer and the MSR are also clobbered,
90	 * so they are saved in the PACA which allows us to restore
91	 * our original state after RTAS returns.
92	 */
93	std	r1,PACAR1(r13)
94	std	r6,PACASAVEDMSR(r13)
95
96	/* Setup our real return addr */
97	LOAD_REG_ADDR(r4,rtas_return_loc)
98	clrldi	r4,r4,2			/* convert to realmode address */
99	mtlr	r4
100
101__enter_rtas:
102	LOAD_REG_ADDR(r4, rtas)
103	ld	r5,RTASENTRY(r4)	/* get the rtas->entry value */
104	ld	r4,RTASBASE(r4)		/* get the rtas->base value */
105
106	/*
107	 * RTAS runs in 32-bit big endian real mode, but leave MSR[RI] on as we
108	 * may hit NMI (SRESET or MCE) while in RTAS. RTAS should disable RI in
109	 * its critical regions (as specified in PAPR+ section 7.2.1). MSR[S]
110	 * is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if
111	 * MSR[S] is set, it will remain when entering RTAS.
112	 */
113	LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)
114
115	li      r0,0
116	mtmsrd  r0,1                    /* disable RI before using SRR0/1 */
117
118	mtspr	SPRN_SRR0,r5
119	mtspr	SPRN_SRR1,r6
120	RFI_TO_KERNEL
121	b	.	/* prevent speculative execution */
122rtas_return_loc:
123	FIXUP_ENDIAN
124
125	/* Set SF before anything. */
126	LOAD_REG_IMMEDIATE(r6, MSR_KERNEL & ~(MSR_IR|MSR_DR))
127	mtmsrd	r6
128
129	/* relocation is off at this point */
130	GET_PACA(r13)
131
132	bcl	20,31,$+4
1330:	mflr	r3
134	ld	r3,(1f-0b)(r3)		/* get &rtas_restore_regs */
135
136	ld	r1,PACAR1(r13)		/* Restore our SP */
137	ld	r4,PACASAVEDMSR(r13)	/* Restore our MSR */
138
139	mtspr	SPRN_SRR0,r3
140	mtspr	SPRN_SRR1,r4
141	RFI_TO_KERNEL
142	b	.	/* prevent speculative execution */
143_ASM_NOKPROBE_SYMBOL(enter_rtas)
144_ASM_NOKPROBE_SYMBOL(__enter_rtas)
145_ASM_NOKPROBE_SYMBOL(rtas_return_loc)
146
147	.align	3
1481:	.8byte	rtas_restore_regs
149
150rtas_restore_regs:
151	/* relocation is on at this point */
152	REST_GPR(2, r1)			/* Restore the TOC */
153	REST_NVGPRS(r1)			/* Restore the non-volatiles */
154
155	ld	r4,_CCR(r1)
156	mtcr	r4
157	ld	r5,_CTR(r1)
158	mtctr	r5
159	ld	r6,_XER(r1)
160	mtspr	SPRN_XER,r6
161	ld	r7,_DAR(r1)
162	mtdar	r7
163	ld	r8,_DSISR(r1)
164	mtdsisr	r8
165
166	addi	r1,r1,SWITCH_FRAME_SIZE	/* Unstack our frame */
167	ld	r0,16(r1)		/* get return address */
168
169	mtlr	r0
170	blr				/* return to caller */
171
172#endif /* CONFIG_PPC32 */
173