xref: /openbmc/linux/arch/powerpc/kernel/head_32.h (revision e0652f8b)
1 /* 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  */
13 .macro EXCEPTION_PROLOG		trapno name handle_dar_dsisr=0
14 	EXCEPTION_PROLOG_0	handle_dar_dsisr=\handle_dar_dsisr
15 	EXCEPTION_PROLOG_1
16 	EXCEPTION_PROLOG_2	\trapno \name handle_dar_dsisr=\handle_dar_dsisr
17 .endm
18 
19 .macro EXCEPTION_PROLOG_0 handle_dar_dsisr=0
20 	mtspr	SPRN_SPRG_SCRATCH0,r10
21 	mtspr	SPRN_SPRG_SCRATCH1,r11
22 	mfspr	r10, SPRN_SPRG_THREAD
23 	.if	\handle_dar_dsisr
24 #ifdef CONFIG_40x
25 	mfspr	r11, SPRN_DEAR
26 #else
27 	mfspr	r11, SPRN_DAR
28 #endif
29 	stw	r11, DAR(r10)
30 #ifdef CONFIG_40x
31 	mfspr	r11, SPRN_ESR
32 #else
33 	mfspr	r11, SPRN_DSISR
34 #endif
35 	stw	r11, DSISR(r10)
36 	.endif
37 	mfspr	r11, SPRN_SRR0
38 	stw	r11, SRR0(r10)
39 	mfspr	r11, SPRN_SRR1		/* check whether user or kernel */
40 	stw	r11, SRR1(r10)
41 	mfcr	r10
42 	andi.	r11, r11, MSR_PR
43 .endm
44 
45 .macro EXCEPTION_PROLOG_1
46 	mtspr	SPRN_SPRG_SCRATCH2,r1
47 	subi	r1, r1, INT_FRAME_SIZE		/* use r1 if kernel */
48 	beq	1f
49 	mfspr	r1,SPRN_SPRG_THREAD
50 	lwz	r1,TASK_STACK-THREAD(r1)
51 	addi	r1, r1, THREAD_SIZE - INT_FRAME_SIZE
52 1:
53 #ifdef CONFIG_VMAP_STACK
54 	mtcrf	0x3f, r1
55 	bt	32 - THREAD_ALIGN_SHIFT, vmap_stack_overflow
56 #endif
57 .endm
58 
59 .macro EXCEPTION_PROLOG_2 trapno name handle_dar_dsisr=0
60 #ifdef CONFIG_PPC_8xx
61 	.if	\handle_dar_dsisr
62 	li	r11, RPN_PATTERN
63 	mtspr	SPRN_DAR, r11	/* Tag DAR, to be used in DTLB Error */
64 	.endif
65 #endif
66 	LOAD_REG_IMMEDIATE(r11, MSR_KERNEL & ~MSR_RI) /* re-enable MMU */
67 	mtspr	SPRN_SRR1, r11
68 	lis	r11, 1f@h
69 	ori	r11, r11, 1f@l
70 	mtspr	SPRN_SRR0, r11
71 	mfspr	r11, SPRN_SPRG_SCRATCH2
72 	rfi
73 
74 	.text
75 \name\()_virt:
76 1:
77 	stw	r11,GPR1(r1)
78 	stw	r11,0(r1)
79 	mr	r11, r1
80 	stw	r10,_CCR(r11)		/* save registers */
81 	stw	r12,GPR12(r11)
82 	stw	r9,GPR9(r11)
83 	mfspr	r10,SPRN_SPRG_SCRATCH0
84 	mfspr	r12,SPRN_SPRG_SCRATCH1
85 	stw	r10,GPR10(r11)
86 	stw	r12,GPR11(r11)
87 	mflr	r10
88 	stw	r10,_LINK(r11)
89 	mfspr	r12, SPRN_SPRG_THREAD
90 	tovirt(r12, r12)
91 	.if	\handle_dar_dsisr
92 	lwz	r10, DAR(r12)
93 	stw	r10, _DAR(r11)
94 	lwz	r10, DSISR(r12)
95 	stw	r10, _DSISR(r11)
96 	.endif
97 	lwz	r9, SRR1(r12)
98 	lwz	r12, SRR0(r12)
99 #ifdef CONFIG_40x
100 	rlwinm	r9,r9,0,14,12		/* clear MSR_WE (necessary?) */
101 #elif defined(CONFIG_PPC_8xx)
102 	mtspr	SPRN_EID, r2		/* Set MSR_RI */
103 #else
104 	li	r10, MSR_KERNEL		/* can take exceptions */
105 	mtmsr	r10			/* (except for mach check in rtas) */
106 #endif
107 	COMMON_EXCEPTION_PROLOG_END \trapno
108 _ASM_NOKPROBE_SYMBOL(\name\()_virt)
109 .endm
110 
111 .macro COMMON_EXCEPTION_PROLOG_END trapno
112 	stw	r0,GPR0(r1)
113 	lis	r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
114 	addi	r10,r10,STACK_FRAME_REGS_MARKER@l
115 	stw	r10,8(r1)
116 	li	r10, \trapno
117 	stw	r10,_TRAP(r1)
118 	SAVE_4GPRS(3, r1)
119 	SAVE_2GPRS(7, r1)
120 	SAVE_NVGPRS(r1)
121 	stw	r2,GPR2(r1)
122 	stw	r12,_NIP(r1)
123 	stw	r9,_MSR(r1)
124 	mfctr	r10
125 	mfspr	r2,SPRN_SPRG_THREAD
126 	stw	r10,_CTR(r1)
127 	tovirt(r2, r2)
128 	mfspr	r10,SPRN_XER
129 	addi	r2, r2, -THREAD
130 	stw	r10,_XER(r1)
131 	addi	r3,r1,STACK_FRAME_OVERHEAD
132 .endm
133 
134 .macro prepare_transfer_to_handler
135 #ifdef CONFIG_PPC_BOOK3S_32
136 	andi.	r12,r9,MSR_PR
137 	bne	777f
138 	bl	prepare_transfer_to_handler
139 777:
140 #endif
141 .endm
142 
143 .macro SYSCALL_ENTRY trapno
144 	mfspr	r9, SPRN_SRR1
145 	mfspr	r10, SPRN_SRR0
146 	LOAD_REG_IMMEDIATE(r11, MSR_KERNEL)		/* can take exceptions */
147 	lis	r12, 1f@h
148 	ori	r12, r12, 1f@l
149 	mtspr	SPRN_SRR1, r11
150 	mtspr	SPRN_SRR0, r12
151 	mfspr	r12,SPRN_SPRG_THREAD
152 	mr	r11, r1
153 	lwz	r1,TASK_STACK-THREAD(r12)
154 	tovirt(r12, r12)
155 	addi	r1, r1, THREAD_SIZE - INT_FRAME_SIZE
156 	rfi
157 1:
158 	stw	r11,GPR1(r1)
159 	stw	r11,0(r1)
160 	mr	r11, r1
161 	stw	r10,_NIP(r11)
162 	mflr	r10
163 	stw	r10, _LINK(r11)
164 	mfcr	r10
165 	rlwinm	r10,r10,0,4,2	/* Clear SO bit in CR */
166 	stw	r10,_CCR(r11)		/* save registers */
167 #ifdef CONFIG_40x
168 	rlwinm	r9,r9,0,14,12		/* clear MSR_WE (necessary?) */
169 #endif
170 	lis	r10,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
171 	stw	r2,GPR2(r11)
172 	addi	r10,r10,STACK_FRAME_REGS_MARKER@l
173 	stw	r9,_MSR(r11)
174 	li	r2, \trapno
175 	stw	r10,8(r11)
176 	stw	r2,_TRAP(r11)
177 	SAVE_GPR(0, r11)
178 	SAVE_4GPRS(3, r11)
179 	SAVE_2GPRS(7, r11)
180 	addi	r2,r12,-THREAD
181 	b	transfer_to_syscall		/* jump to handler */
182 .endm
183 
184 /*
185  * Note: code which follows this uses cr0.eq (set if from kernel),
186  * r11, r12 (SRR0), and r9 (SRR1).
187  *
188  * Note2: once we have set r1 we are in a position to take exceptions
189  * again, and we could thus set MSR:RI at that point.
190  */
191 
192 /*
193  * Exception vectors.
194  */
195 #ifdef CONFIG_PPC_BOOK3S
196 #define	START_EXCEPTION(n, label)		\
197 	__HEAD;					\
198 	. = n;					\
199 	DO_KVM n;				\
200 label:
201 
202 #else
203 #define	START_EXCEPTION(n, label)		\
204 	__HEAD;					\
205 	. = n;					\
206 label:
207 
208 #endif
209 
210 #define EXCEPTION(n, label, hdlr)		\
211 	START_EXCEPTION(n, label)		\
212 	EXCEPTION_PROLOG n label;		\
213 	prepare_transfer_to_handler;		\
214 	bl	hdlr;				\
215 	b	interrupt_return
216 
217 .macro vmap_stack_overflow_exception
218 	__HEAD
219 vmap_stack_overflow:
220 #ifdef CONFIG_SMP
221 	mfspr	r1, SPRN_SPRG_THREAD
222 	lwz	r1, TASK_CPU - THREAD(r1)
223 	slwi	r1, r1, 3
224 	addis	r1, r1, emergency_ctx@ha
225 #else
226 	lis	r1, emergency_ctx@ha
227 #endif
228 	lwz	r1, emergency_ctx@l(r1)
229 	addi	r1, r1, THREAD_SIZE - INT_FRAME_SIZE
230 	EXCEPTION_PROLOG_2 0 vmap_stack_overflow
231 	prepare_transfer_to_handler
232 	bl	stack_overflow_exception
233 	b	interrupt_return
234 .endm
235 
236 #endif /* __HEAD_32_H__ */
237