blob: abb057a86739b791c6fa8c50f8d8fa850b6e2543 [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __HEAD_32_H__
3#define __HEAD_32_H__
4
5#include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */
6
7/*
8 * Exception entry code. This code runs with address translation
9 * turned off, i.e. using physical addresses.
10 * We assume sprg3 has the physical address of the current
11 * task's thread_struct.
12 */
Olivier Deprez157378f2022-04-04 15:47:50 +020013.macro EXCEPTION_PROLOG handle_dar_dsisr=0
14 EXCEPTION_PROLOG_0 handle_dar_dsisr=\handle_dar_dsisr
David Brazdil0f672f62019-12-10 10:32:29 +000015 EXCEPTION_PROLOG_1
Olivier Deprez157378f2022-04-04 15:47:50 +020016 EXCEPTION_PROLOG_2 handle_dar_dsisr=\handle_dar_dsisr
David Brazdil0f672f62019-12-10 10:32:29 +000017.endm
18
Olivier Deprez157378f2022-04-04 15:47:50 +020019.macro EXCEPTION_PROLOG_0 handle_dar_dsisr=0
20 mtspr SPRN_SPRG_SCRATCH0,r10
21 mtspr SPRN_SPRG_SCRATCH1,r11
22#ifdef CONFIG_VMAP_STACK
23 mfspr r10, SPRN_SPRG_THREAD
24 .if \handle_dar_dsisr
25 mfspr r11, SPRN_DAR
26 stw r11, DAR(r10)
27 mfspr r11, SPRN_DSISR
28 stw r11, DSISR(r10)
29 .endif
30 mfspr r11, SPRN_SRR0
31 stw r11, SRR0(r10)
32#endif
33 mfspr r11, SPRN_SRR1 /* check whether user or kernel */
34#ifdef CONFIG_VMAP_STACK
35 stw r11, SRR1(r10)
36#endif
37 mfcr r10
38 andi. r11, r11, MSR_PR
39.endm
40
41.macro EXCEPTION_PROLOG_1 for_rtas=0
42#ifdef CONFIG_VMAP_STACK
43 mr r11, r1
44 subi r1, r1, INT_FRAME_SIZE /* use r1 if kernel */
45 beq 1f
46 mfspr r1,SPRN_SPRG_THREAD
47 lwz r1,TASK_STACK-THREAD(r1)
48 addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
49#else
50 subi r11, r1, INT_FRAME_SIZE /* use r1 if kernel */
David Brazdil0f672f62019-12-10 10:32:29 +000051 beq 1f
52 mfspr r11,SPRN_SPRG_THREAD
53 lwz r11,TASK_STACK-THREAD(r11)
Olivier Deprez157378f2022-04-04 15:47:50 +020054 addi r11, r11, THREAD_SIZE - INT_FRAME_SIZE
55#endif
561:
57 tophys_novmstack r11, r11
58#ifdef CONFIG_VMAP_STACK
59 mtcrf 0x3f, r1
60 bt 32 - THREAD_ALIGN_SHIFT, stack_overflow
61#endif
David Brazdil0f672f62019-12-10 10:32:29 +000062.endm
63
Olivier Deprez157378f2022-04-04 15:47:50 +020064.macro EXCEPTION_PROLOG_2 handle_dar_dsisr=0
65#ifdef CONFIG_VMAP_STACK
66 mtcr r10
67 li r10, MSR_KERNEL & ~(MSR_IR | MSR_RI) /* can take DTLB miss */
68 mtmsr r10
69 isync
70#else
David Brazdil0f672f62019-12-10 10:32:29 +000071 stw r10,_CCR(r11) /* save registers */
Olivier Deprez157378f2022-04-04 15:47:50 +020072#endif
73 mfspr r10, SPRN_SPRG_SCRATCH0
74#ifdef CONFIG_VMAP_STACK
75 stw r11,GPR1(r1)
76 stw r11,0(r1)
77 mr r11, r1
78#else
79 stw r1,GPR1(r11)
80 stw r1,0(r11)
81 tovirt(r1, r11) /* set new kernel sp */
82#endif
David Brazdil0f672f62019-12-10 10:32:29 +000083 stw r12,GPR12(r11)
84 stw r9,GPR9(r11)
David Brazdil0f672f62019-12-10 10:32:29 +000085 stw r10,GPR10(r11)
Olivier Deprez157378f2022-04-04 15:47:50 +020086#ifdef CONFIG_VMAP_STACK
87 mfcr r10
88 stw r10, _CCR(r11)
89#endif
David Brazdil0f672f62019-12-10 10:32:29 +000090 mfspr r12,SPRN_SPRG_SCRATCH1
91 stw r12,GPR11(r11)
92 mflr r10
93 stw r10,_LINK(r11)
Olivier Deprez157378f2022-04-04 15:47:50 +020094#ifdef CONFIG_VMAP_STACK
95 mfspr r12, SPRN_SPRG_THREAD
96 tovirt(r12, r12)
97 .if \handle_dar_dsisr
98 lwz r10, DAR(r12)
99 stw r10, _DAR(r11)
100 lwz r10, DSISR(r12)
101 stw r10, _DSISR(r11)
102 .endif
103 lwz r9, SRR1(r12)
104 andi. r10, r9, MSR_PR
105 lwz r12, SRR0(r12)
106#else
David Brazdil0f672f62019-12-10 10:32:29 +0000107 mfspr r12,SPRN_SRR0
108 mfspr r9,SPRN_SRR1
Olivier Deprez157378f2022-04-04 15:47:50 +0200109#endif
David Brazdil0f672f62019-12-10 10:32:29 +0000110#ifdef CONFIG_40x
111 rlwinm r9,r9,0,14,12 /* clear MSR_WE (necessary?) */
112#else
Olivier Deprez157378f2022-04-04 15:47:50 +0200113#ifdef CONFIG_VMAP_STACK
114 li r10, MSR_KERNEL & ~MSR_IR /* can take exceptions */
115#else
David Brazdil0f672f62019-12-10 10:32:29 +0000116 li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR) /* can take exceptions */
Olivier Deprez157378f2022-04-04 15:47:50 +0200117#endif
118 mtmsr r10 /* (except for mach check in rtas) */
David Brazdil0f672f62019-12-10 10:32:29 +0000119#endif
120 stw r0,GPR0(r11)
121 lis r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
122 addi r10,r10,STACK_FRAME_REGS_MARKER@l
123 stw r10,8(r11)
124 SAVE_4GPRS(3, r11)
125 SAVE_2GPRS(7, r11)
126.endm
127
128.macro SYSCALL_ENTRY trapno
129 mfspr r12,SPRN_SPRG_THREAD
Olivier Deprez157378f2022-04-04 15:47:50 +0200130 mfspr r9, SPRN_SRR1
131#ifdef CONFIG_VMAP_STACK
132 mfspr r11, SPRN_SRR0
133 mtctr r11
134 andi. r11, r9, MSR_PR
135 mr r11, r1
136 lwz r1,TASK_STACK-THREAD(r12)
137 beq- 99f
138 addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
139 li r10, MSR_KERNEL & ~(MSR_IR | MSR_RI) /* can take DTLB miss */
140 mtmsr r10
141 isync
142 tovirt(r12, r12)
143 stw r11,GPR1(r1)
144 stw r11,0(r1)
145 mr r11, r1
146#else
147 andi. r11, r9, MSR_PR
David Brazdil0f672f62019-12-10 10:32:29 +0000148 lwz r11,TASK_STACK-THREAD(r12)
Olivier Deprez157378f2022-04-04 15:47:50 +0200149 beq- 99f
150 addi r11, r11, THREAD_SIZE - INT_FRAME_SIZE
151 tophys(r11, r11)
David Brazdil0f672f62019-12-10 10:32:29 +0000152 stw r1,GPR1(r11)
153 stw r1,0(r11)
Olivier Deprez157378f2022-04-04 15:47:50 +0200154 tovirt(r1, r11) /* set new kernel sp */
155#endif
156 mflr r10
157 stw r10, _LINK(r11)
158#ifdef CONFIG_VMAP_STACK
159 mfctr r10
160#else
161 mfspr r10,SPRN_SRR0
162#endif
David Brazdil0f672f62019-12-10 10:32:29 +0000163 stw r10,_NIP(r11)
Olivier Deprez157378f2022-04-04 15:47:50 +0200164 mfcr r10
165 rlwinm r10,r10,0,4,2 /* Clear SO bit in CR */
166 stw r10,_CCR(r11) /* save registers */
David Brazdil0f672f62019-12-10 10:32:29 +0000167#ifdef CONFIG_40x
168 rlwinm r9,r9,0,14,12 /* clear MSR_WE (necessary?) */
169#else
Olivier Deprez157378f2022-04-04 15:47:50 +0200170#ifdef CONFIG_VMAP_STACK
171 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL & ~MSR_IR) /* can take exceptions */
172#else
David Brazdil0f672f62019-12-10 10:32:29 +0000173 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL & ~(MSR_IR|MSR_DR)) /* can take exceptions */
Olivier Deprez157378f2022-04-04 15:47:50 +0200174#endif
175 mtmsr r10 /* (except for mach check in rtas) */
David Brazdil0f672f62019-12-10 10:32:29 +0000176#endif
177 lis r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
178 stw r2,GPR2(r11)
179 addi r10,r10,STACK_FRAME_REGS_MARKER@l
180 stw r9,_MSR(r11)
181 li r2, \trapno + 1
182 stw r10,8(r11)
183 stw r2,_TRAP(r11)
184 SAVE_GPR(0, r11)
185 SAVE_4GPRS(3, r11)
186 SAVE_2GPRS(7, r11)
187 addi r11,r1,STACK_FRAME_OVERHEAD
188 addi r2,r12,-THREAD
189 stw r11,PT_REGS(r12)
190#if defined(CONFIG_40x)
191 /* Check to see if the dbcr0 register is set up to debug. Use the
192 internal debug mode bit to do this. */
193 lwz r12,THREAD_DBCR0(r12)
194 andis. r12,r12,DBCR0_IDM@h
195#endif
196 ACCOUNT_CPU_USER_ENTRY(r2, r11, r12)
197#if defined(CONFIG_40x)
198 beq+ 3f
199 /* From user and task is ptraced - load up global dbcr0 */
200 li r12,-1 /* clear all pending debug events */
201 mtspr SPRN_DBSR,r12
202 lis r11,global_dbcr0@ha
203 tophys(r11,r11)
204 addi r11,r11,global_dbcr0@l
205 lwz r12,0(r11)
206 mtspr SPRN_DBCR0,r12
207 lwz r12,4(r11)
208 addi r12,r12,-1
209 stw r12,4(r11)
210#endif
211
2123:
Olivier Deprez157378f2022-04-04 15:47:50 +0200213 tovirt_novmstack r2, r2 /* set r2 to current */
David Brazdil0f672f62019-12-10 10:32:29 +0000214 lis r11, transfer_to_syscall@h
215 ori r11, r11, transfer_to_syscall@l
216#ifdef CONFIG_TRACE_IRQFLAGS
217 /*
218 * If MSR is changing we need to keep interrupts disabled at this point
219 * otherwise we might risk taking an interrupt before we tell lockdep
220 * they are enabled.
221 */
222 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL)
223 rlwimi r10, r9, 0, MSR_EE
224#else
225 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL | MSR_EE)
226#endif
227#if defined(CONFIG_PPC_8xx) && defined(CONFIG_PERF_EVENTS)
228 mtspr SPRN_NRI, r0
229#endif
230 mtspr SPRN_SRR1,r10
231 mtspr SPRN_SRR0,r11
David Brazdil0f672f62019-12-10 10:32:29 +0000232 RFI /* jump to handler, enable MMU */
Olivier Deprez157378f2022-04-04 15:47:50 +020023399: b ret_from_kernel_syscall
234.endm
235
236.macro save_dar_dsisr_on_stack reg1, reg2, sp
237#ifndef CONFIG_VMAP_STACK
238 mfspr \reg1, SPRN_DAR
239 mfspr \reg2, SPRN_DSISR
240 stw \reg1, _DAR(\sp)
241 stw \reg2, _DSISR(\sp)
242#endif
243.endm
244
245.macro get_and_save_dar_dsisr_on_stack reg1, reg2, sp
246#ifdef CONFIG_VMAP_STACK
247 lwz \reg1, _DAR(\sp)
248 lwz \reg2, _DSISR(\sp)
249#else
250 save_dar_dsisr_on_stack \reg1, \reg2, \sp
251#endif
252.endm
253
254.macro tovirt_vmstack dst, src
255#ifdef CONFIG_VMAP_STACK
256 tovirt(\dst, \src)
257#else
258 .ifnc \dst, \src
259 mr \dst, \src
260 .endif
261#endif
262.endm
263
264.macro tovirt_novmstack dst, src
265#ifndef CONFIG_VMAP_STACK
266 tovirt(\dst, \src)
267#else
268 .ifnc \dst, \src
269 mr \dst, \src
270 .endif
271#endif
272.endm
273
274.macro tophys_novmstack dst, src
275#ifndef CONFIG_VMAP_STACK
276 tophys(\dst, \src)
277#else
278 .ifnc \dst, \src
279 mr \dst, \src
280 .endif
281#endif
David Brazdil0f672f62019-12-10 10:32:29 +0000282.endm
283
284/*
285 * Note: code which follows this uses cr0.eq (set if from kernel),
286 * r11, r12 (SRR0), and r9 (SRR1).
287 *
288 * Note2: once we have set r1 we are in a position to take exceptions
289 * again, and we could thus set MSR:RI at that point.
290 */
291
292/*
293 * Exception vectors.
294 */
295#ifdef CONFIG_PPC_BOOK3S
296#define START_EXCEPTION(n, label) \
297 . = n; \
298 DO_KVM n; \
299label:
300
301#else
302#define START_EXCEPTION(n, label) \
303 . = n; \
304label:
305
306#endif
307
308#define EXCEPTION(n, label, hdlr, xfer) \
309 START_EXCEPTION(n, label) \
310 EXCEPTION_PROLOG; \
311 addi r3,r1,STACK_FRAME_OVERHEAD; \
312 xfer(n, hdlr)
313
314#define EXC_XFER_TEMPLATE(hdlr, trap, msr, tfer, ret) \
315 li r10,trap; \
316 stw r10,_TRAP(r11); \
317 LOAD_REG_IMMEDIATE(r10, msr); \
318 bl tfer; \
319 .long hdlr; \
320 .long ret
321
322#define EXC_XFER_STD(n, hdlr) \
323 EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, transfer_to_handler_full, \
324 ret_from_except_full)
325
326#define EXC_XFER_LITE(n, hdlr) \
327 EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, transfer_to_handler, \
328 ret_from_except)
329
Olivier Deprez157378f2022-04-04 15:47:50 +0200330.macro vmap_stack_overflow_exception
331#ifdef CONFIG_VMAP_STACK
332#ifdef CONFIG_SMP
333 mfspr r1, SPRN_SPRG_THREAD
334 lwz r1, TASK_CPU - THREAD(r1)
335 slwi r1, r1, 3
336 addis r1, r1, emergency_ctx-PAGE_OFFSET@ha
337#else
338 lis r1, emergency_ctx-PAGE_OFFSET@ha
339#endif
340 lwz r1, emergency_ctx-PAGE_OFFSET@l(r1)
341 addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
342 EXCEPTION_PROLOG_2
343 SAVE_NVGPRS(r11)
344 addi r3, r1, STACK_FRAME_OVERHEAD
345 EXC_XFER_STD(0, stack_overflow_exception)
346#endif
347.endm
348
David Brazdil0f672f62019-12-10 10:32:29 +0000349#endif /* __HEAD_32_H__ */