1 /* SPDX-License-Identifier: GPL-2.0 */
5 #include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */
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.
13 .macro EXCEPTION_PROLOG handle_dar_dsisr=0
14 EXCEPTION_PROLOG_0 handle_dar_dsisr=\handle_dar_dsisr
16 EXCEPTION_PROLOG_2 handle_dar_dsisr=\handle_dar_dsisr
19 .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
33 mfspr r11, SPRN_SRR1 /* check whether user or kernel */
34 #ifdef CONFIG_VMAP_STACK
38 andi. r11, r11, MSR_PR
41 .macro EXCEPTION_PROLOG_1 for_rtas=0
42 #ifdef CONFIG_VMAP_STACK
44 subi r1, r1, INT_FRAME_SIZE /* use r1 if kernel */
46 mfspr r1,SPRN_SPRG_THREAD
47 lwz r1,TASK_STACK-THREAD(r1)
48 addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
50 subi r11, r1, INT_FRAME_SIZE /* use r1 if kernel */
52 mfspr r11,SPRN_SPRG_THREAD
53 lwz r11,TASK_STACK-THREAD(r11)
54 addi r11, r11, THREAD_SIZE - INT_FRAME_SIZE
57 tophys_novmstack r11, r11
58 #ifdef CONFIG_VMAP_STACK
60 bt 32 - THREAD_ALIGN_SHIFT, stack_overflow
64 .macro EXCEPTION_PROLOG_2 handle_dar_dsisr=0
65 #ifdef CONFIG_VMAP_STACK
67 li r10, MSR_KERNEL & ~(MSR_IR | MSR_RI) /* can take DTLB miss */
71 stw r10,_CCR(r11) /* save registers */
73 mfspr r10, SPRN_SPRG_SCRATCH0
74 #ifdef CONFIG_VMAP_STACK
81 tovirt(r1, r11) /* set new kernel sp */
86 #ifdef CONFIG_VMAP_STACK
90 mfspr r12,SPRN_SPRG_SCRATCH1
94 #ifdef CONFIG_VMAP_STACK
95 mfspr r12, SPRN_SPRG_THREAD
104 andi. r10, r9, MSR_PR
111 rlwinm r9,r9,0,14,12 /* clear MSR_WE (necessary?) */
113 #ifdef CONFIG_VMAP_STACK
114 li r10, MSR_KERNEL & ~MSR_IR /* can take exceptions */
116 li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR) /* can take exceptions */
118 mtmsr r10 /* (except for mach check in rtas) */
121 lis r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
122 addi r10,r10,STACK_FRAME_REGS_MARKER@l
128 .macro SYSCALL_ENTRY trapno
129 mfspr r12,SPRN_SPRG_THREAD
131 #ifdef CONFIG_VMAP_STACK
134 andi. r11, r9, MSR_PR
136 lwz r1,TASK_STACK-THREAD(r12)
138 addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
139 li r10, MSR_KERNEL & ~(MSR_IR | MSR_RI) /* can take DTLB miss */
147 andi. r11, r9, MSR_PR
148 lwz r11,TASK_STACK-THREAD(r12)
150 addi r11, r11, THREAD_SIZE - INT_FRAME_SIZE
154 tovirt(r1, r11) /* set new kernel sp */
158 #ifdef CONFIG_VMAP_STACK
165 rlwinm r10,r10,0,4,2 /* Clear SO bit in CR */
166 stw r10,_CCR(r11) /* save registers */
168 rlwinm r9,r9,0,14,12 /* clear MSR_WE (necessary?) */
170 #ifdef CONFIG_VMAP_STACK
171 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL & ~MSR_IR) /* can take exceptions */
173 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL & ~(MSR_IR|MSR_DR)) /* can take exceptions */
175 mtmsr r10 /* (except for mach check in rtas) */
177 lis r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
179 addi r10,r10,STACK_FRAME_REGS_MARKER@l
187 addi r11,r1,STACK_FRAME_OVERHEAD
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
196 ACCOUNT_CPU_USER_ENTRY(r2, r11, r12)
197 #if defined(CONFIG_40x)
199 /* From user and task is ptraced - load up global dbcr0 */
200 li r12,-1 /* clear all pending debug events */
202 lis r11,global_dbcr0@ha
204 addi r11,r11,global_dbcr0@l
213 tovirt_novmstack r2, r2 /* set r2 to current */
214 lis r11, transfer_to_syscall@h
215 ori r11, r11, transfer_to_syscall@l
216 #ifdef CONFIG_TRACE_IRQFLAGS
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
222 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL)
223 rlwimi r10, r9, 0, MSR_EE
225 LOAD_REG_IMMEDIATE(r10, MSR_KERNEL | MSR_EE)
227 #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PERF_EVENTS)
232 RFI /* jump to handler, enable MMU */
233 99: b ret_from_kernel_syscall
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
241 stw \reg2, _DSISR(\sp)
245 .macro get_and_save_dar_dsisr_on_stack reg1, reg2, sp
246 #ifdef CONFIG_VMAP_STACK
248 lwz \reg2, _DSISR(\sp)
250 save_dar_dsisr_on_stack \reg1, \reg2, \sp
254 .macro tovirt_vmstack dst, src
255 #ifdef CONFIG_VMAP_STACK
264 .macro tovirt_novmstack dst, src
265 #ifndef CONFIG_VMAP_STACK
274 .macro tophys_novmstack dst, src
275 #ifndef CONFIG_VMAP_STACK
285 * Note: code which follows this uses cr0.eq (set if from kernel),
286 * r11, r12 (SRR0), and r9 (SRR1).
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.
295 #ifdef CONFIG_PPC_BOOK3S
296 #define START_EXCEPTION(n, label) \
302 #define START_EXCEPTION(n, label) \
308 #define EXCEPTION(n, label, hdlr, xfer) \
309 START_EXCEPTION(n, label) \
311 addi r3,r1,STACK_FRAME_OVERHEAD; \
314 #define EXC_XFER_TEMPLATE(hdlr, trap, msr, tfer, ret) \
316 stw r10,_TRAP(r11); \
317 LOAD_REG_IMMEDIATE(r10, msr); \
322 #define EXC_XFER_STD(n, hdlr) \
323 EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, transfer_to_handler_full, \
324 ret_from_except_full)
326 #define EXC_XFER_LITE(n, hdlr) \
327 EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, transfer_to_handler, \
330 .macro vmap_stack_overflow_exception
331 #ifdef CONFIG_VMAP_STACK
333 mfspr r1, SPRN_SPRG_THREAD
334 lwz r1, TASK_CPU - THREAD(r1)
336 addis r1, r1, emergency_ctx-PAGE_OFFSET@ha
338 lis r1, emergency_ctx-PAGE_OFFSET@ha
340 lwz r1, emergency_ctx-PAGE_OFFSET@l(r1)
341 addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
344 addi r3, r1, STACK_FRAME_OVERHEAD
345 EXC_XFER_STD(0, stack_overflow_exception)
349 #endif /* __HEAD_32_H__ */