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 |
33 | 1: |
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 */ |
40 | 1: |
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 */ |
126 | rtas_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 |
137 | 0: 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 |
152 | 1: .8byte rtas_restore_regs |
153 | |
154 | rtas_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 | |