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 * If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV
113 * from the saved MSR value and insert into the value RTAS will use.
114 */
115 extrdi r0, r6, 1, 63 - MSR_HV_LG
116 LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)
117 insrdi r6, r0, 1, 63 - MSR_HV_LG
118
119 li r0,0
120 mtmsrd r0,1 /* disable RI before using SRR0/1 */
121
122 mtspr SPRN_SRR0,r5
123 mtspr SPRN_SRR1,r6
124 RFI_TO_KERNEL
125 b . /* prevent speculative execution */
126rtas_return_loc:
127 FIXUP_ENDIAN
128
129 /* Set SF before anything. */
130 LOAD_REG_IMMEDIATE(r6, MSR_KERNEL & ~(MSR_IR|MSR_DR))
131 mtmsrd r6
132
133 /* relocation is off at this point */
134 GET_PACA(r13)
135
136 bcl 20,31,$+4
1370: mflr r3
138 ld r3,(1f-0b)(r3) /* get &rtas_restore_regs */
139
140 ld r1,PACAR1(r13) /* Restore our SP */
141 ld r4,PACASAVEDMSR(r13) /* Restore our MSR */
142
143 mtspr SPRN_SRR0,r3
144 mtspr SPRN_SRR1,r4
145 RFI_TO_KERNEL
146 b . /* prevent speculative execution */
147_ASM_NOKPROBE_SYMBOL(enter_rtas)
148_ASM_NOKPROBE_SYMBOL(__enter_rtas)
149_ASM_NOKPROBE_SYMBOL(rtas_return_loc)
150
151 .align 3
1521: .8byte rtas_restore_regs
153
154rtas_restore_regs:
155 /* relocation is on at this point */
156 REST_GPR(2, r1) /* Restore the TOC */
157 REST_NVGPRS(r1) /* Restore the non-volatiles */
158
159 ld r4,_CCR(r1)
160 mtcr r4
161 ld r5,_CTR(r1)
162 mtctr r5
163 ld r6,_XER(r1)
164 mtspr SPRN_XER,r6
165 ld r7,_DAR(r1)
166 mtdar r7
167 ld r8,_DSISR(r1)
168 mtdsisr r8
169
170 addi r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */
171 ld r0,16(r1) /* get return address */
172
173 mtlr r0
174 blr /* return to caller */
175
176#endif /* CONFIG_PPC32 */
177

source code of linux/arch/powerpc/kernel/rtas_entry.S