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