xref: /openbmc/linux/arch/powerpc/kernel/interrupt_64.S (revision dd152f70bdc1b91445b10c65ac874b90c93fb3b5)
1e754f4d1SNicholas Piggin#include <asm/asm-offsets.h>
2e754f4d1SNicholas Piggin#include <asm/bug.h>
3e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
4e754f4d1SNicholas Piggin#include <asm/exception-64s.h>
5e754f4d1SNicholas Piggin#else
6e754f4d1SNicholas Piggin#include <asm/exception-64e.h>
7e754f4d1SNicholas Piggin#endif
8e754f4d1SNicholas Piggin#include <asm/feature-fixups.h>
9e754f4d1SNicholas Piggin#include <asm/head-64.h>
10e754f4d1SNicholas Piggin#include <asm/hw_irq.h>
11e754f4d1SNicholas Piggin#include <asm/kup.h>
12e754f4d1SNicholas Piggin#include <asm/mmu.h>
13e754f4d1SNicholas Piggin#include <asm/ppc_asm.h>
14e754f4d1SNicholas Piggin#include <asm/ptrace.h>
15e754f4d1SNicholas Piggin#include <asm/tm.h>
16e754f4d1SNicholas Piggin
17e754f4d1SNicholas Piggin	.section	".toc","aw"
18e754f4d1SNicholas PigginSYS_CALL_TABLE:
19e754f4d1SNicholas Piggin	.tc sys_call_table[TC],sys_call_table
20e754f4d1SNicholas Piggin
21e754f4d1SNicholas Piggin#ifdef CONFIG_COMPAT
22e754f4d1SNicholas PigginCOMPAT_SYS_CALL_TABLE:
23e754f4d1SNicholas Piggin	.tc compat_sys_call_table[TC],compat_sys_call_table
24e754f4d1SNicholas Piggin#endif
25e754f4d1SNicholas Piggin	.previous
26e754f4d1SNicholas Piggin
27e754f4d1SNicholas Piggin	.align 7
28e754f4d1SNicholas Piggin
29e754f4d1SNicholas Piggin.macro DEBUG_SRR_VALID srr
30e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_RFI_SRR_DEBUG
31e754f4d1SNicholas Piggin	.ifc \srr,srr
32e754f4d1SNicholas Piggin	mfspr	r11,SPRN_SRR0
33e754f4d1SNicholas Piggin	ld	r12,_NIP(r1)
34e754f4d1SNicholas Piggin100:	tdne	r11,r12
35e754f4d1SNicholas Piggin	EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
36e754f4d1SNicholas Piggin	mfspr	r11,SPRN_SRR1
37e754f4d1SNicholas Piggin	ld	r12,_MSR(r1)
38e754f4d1SNicholas Piggin100:	tdne	r11,r12
39e754f4d1SNicholas Piggin	EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
40e754f4d1SNicholas Piggin	.else
41e754f4d1SNicholas Piggin	mfspr	r11,SPRN_HSRR0
42e754f4d1SNicholas Piggin	ld	r12,_NIP(r1)
43e754f4d1SNicholas Piggin100:	tdne	r11,r12
44e754f4d1SNicholas Piggin	EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
45e754f4d1SNicholas Piggin	mfspr	r11,SPRN_HSRR1
46e754f4d1SNicholas Piggin	ld	r12,_MSR(r1)
47e754f4d1SNicholas Piggin100:	tdne	r11,r12
48e754f4d1SNicholas Piggin	EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
49e754f4d1SNicholas Piggin	.endif
50e754f4d1SNicholas Piggin#endif
51e754f4d1SNicholas Piggin.endm
52e754f4d1SNicholas Piggin
53e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
54e754f4d1SNicholas Piggin.macro system_call_vectored name trapnr
55e754f4d1SNicholas Piggin	.globl system_call_vectored_\name
56e754f4d1SNicholas Pigginsystem_call_vectored_\name:
57e754f4d1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(system_call_vectored_\name)
58e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
59e754f4d1SNicholas PigginBEGIN_FTR_SECTION
60e754f4d1SNicholas Piggin	extrdi.	r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */
61e754f4d1SNicholas Piggin	bne	.Ltabort_syscall
62e754f4d1SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_TM)
63e754f4d1SNicholas Piggin#endif
64e754f4d1SNicholas Piggin	SCV_INTERRUPT_TO_KERNEL
65e754f4d1SNicholas Piggin	mr	r10,r1
66e754f4d1SNicholas Piggin	ld	r1,PACAKSAVE(r13)
67e754f4d1SNicholas Piggin	std	r10,0(r1)
68e754f4d1SNicholas Piggin	std	r11,_NIP(r1)
69e754f4d1SNicholas Piggin	std	r12,_MSR(r1)
70e754f4d1SNicholas Piggin	std	r0,GPR0(r1)
71e754f4d1SNicholas Piggin	std	r10,GPR1(r1)
72e754f4d1SNicholas Piggin	std	r2,GPR2(r1)
73e754f4d1SNicholas Piggin	ld	r2,PACATOC(r13)
74e754f4d1SNicholas Piggin	mfcr	r12
75e754f4d1SNicholas Piggin	li	r11,0
76e754f4d1SNicholas Piggin	/* Can we avoid saving r3-r8 in common case? */
77e754f4d1SNicholas Piggin	std	r3,GPR3(r1)
78e754f4d1SNicholas Piggin	std	r4,GPR4(r1)
79e754f4d1SNicholas Piggin	std	r5,GPR5(r1)
80e754f4d1SNicholas Piggin	std	r6,GPR6(r1)
81e754f4d1SNicholas Piggin	std	r7,GPR7(r1)
82e754f4d1SNicholas Piggin	std	r8,GPR8(r1)
83e754f4d1SNicholas Piggin	/* Zero r9-r12, this should only be required when restoring all GPRs */
84e754f4d1SNicholas Piggin	std	r11,GPR9(r1)
85e754f4d1SNicholas Piggin	std	r11,GPR10(r1)
86e754f4d1SNicholas Piggin	std	r11,GPR11(r1)
87e754f4d1SNicholas Piggin	std	r11,GPR12(r1)
88e754f4d1SNicholas Piggin	std	r9,GPR13(r1)
89e754f4d1SNicholas Piggin	SAVE_NVGPRS(r1)
90e754f4d1SNicholas Piggin	std	r11,_XER(r1)
91e754f4d1SNicholas Piggin	std	r11,_LINK(r1)
92e754f4d1SNicholas Piggin	std	r11,_CTR(r1)
93e754f4d1SNicholas Piggin
94e754f4d1SNicholas Piggin	li	r11,\trapnr
95e754f4d1SNicholas Piggin	std	r11,_TRAP(r1)
96e754f4d1SNicholas Piggin	std	r12,_CCR(r1)
97e754f4d1SNicholas Piggin	addi	r10,r1,STACK_FRAME_OVERHEAD
98e754f4d1SNicholas Piggin	ld	r11,exception_marker@toc(r2)
99e754f4d1SNicholas Piggin	std	r11,-16(r10)		/* "regshere" marker */
100e754f4d1SNicholas Piggin
101e754f4d1SNicholas PigginBEGIN_FTR_SECTION
102e754f4d1SNicholas Piggin	HMT_MEDIUM
103e754f4d1SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
104e754f4d1SNicholas Piggin
105e754f4d1SNicholas Piggin	/*
106e754f4d1SNicholas Piggin	 * scv enters with MSR[EE]=1 and is immediately considered soft-masked.
107e754f4d1SNicholas Piggin	 * The entry vector already sets PACAIRQSOFTMASK to IRQS_ALL_DISABLED,
108e754f4d1SNicholas Piggin	 * and interrupts may be masked and pending already.
109e754f4d1SNicholas Piggin	 * system_call_exception() will call trace_hardirqs_off() which means
110e754f4d1SNicholas Piggin	 * interrupts could already have been blocked before trace_hardirqs_off,
111e754f4d1SNicholas Piggin	 * but this is the best we can do.
112e754f4d1SNicholas Piggin	 */
113e754f4d1SNicholas Piggin
114e754f4d1SNicholas Piggin	/* Calling convention has r9 = orig r0, r10 = regs */
115e754f4d1SNicholas Piggin	mr	r9,r0
116e754f4d1SNicholas Piggin	bl	system_call_exception
117e754f4d1SNicholas Piggin
118e754f4d1SNicholas Piggin.Lsyscall_vectored_\name\()_exit:
119e754f4d1SNicholas Piggin	addi    r4,r1,STACK_FRAME_OVERHEAD
120e754f4d1SNicholas Piggin	li	r5,1 /* scv */
121e754f4d1SNicholas Piggin	bl	syscall_exit_prepare
122e754f4d1SNicholas Piggin
123e754f4d1SNicholas Piggin	ld	r2,_CCR(r1)
124e754f4d1SNicholas Piggin	ld	r4,_NIP(r1)
125e754f4d1SNicholas Piggin	ld	r5,_MSR(r1)
126e754f4d1SNicholas Piggin
127e754f4d1SNicholas PigginBEGIN_FTR_SECTION
128e754f4d1SNicholas Piggin	stdcx.	r0,0,r1			/* to clear the reservation */
129e754f4d1SNicholas PigginEND_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
130e754f4d1SNicholas Piggin
131e754f4d1SNicholas PigginBEGIN_FTR_SECTION
132e754f4d1SNicholas Piggin	HMT_MEDIUM_LOW
133e754f4d1SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
134e754f4d1SNicholas Piggin
135e754f4d1SNicholas Piggin	cmpdi	r3,0
136e754f4d1SNicholas Piggin	bne	.Lsyscall_vectored_\name\()_restore_regs
137e754f4d1SNicholas Piggin
138e754f4d1SNicholas Piggin	/* rfscv returns with LR->NIA and CTR->MSR */
139e754f4d1SNicholas Piggin	mtlr	r4
140e754f4d1SNicholas Piggin	mtctr	r5
141e754f4d1SNicholas Piggin
142e754f4d1SNicholas Piggin	/* Could zero these as per ABI, but we may consider a stricter ABI
143e754f4d1SNicholas Piggin	 * which preserves these if libc implementations can benefit, so
144e754f4d1SNicholas Piggin	 * restore them for now until further measurement is done. */
145e754f4d1SNicholas Piggin	ld	r0,GPR0(r1)
146e754f4d1SNicholas Piggin	ld	r4,GPR4(r1)
147e754f4d1SNicholas Piggin	ld	r5,GPR5(r1)
148e754f4d1SNicholas Piggin	ld	r6,GPR6(r1)
149e754f4d1SNicholas Piggin	ld	r7,GPR7(r1)
150e754f4d1SNicholas Piggin	ld	r8,GPR8(r1)
151e754f4d1SNicholas Piggin	/* Zero volatile regs that may contain sensitive kernel data */
152e754f4d1SNicholas Piggin	li	r9,0
153e754f4d1SNicholas Piggin	li	r10,0
154e754f4d1SNicholas Piggin	li	r11,0
155e754f4d1SNicholas Piggin	li	r12,0
156e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r0
157e754f4d1SNicholas Piggin
158e754f4d1SNicholas Piggin	/*
159e754f4d1SNicholas Piggin	 * We don't need to restore AMR on the way back to userspace for KUAP.
160e754f4d1SNicholas Piggin	 * The value of AMR only matters while we're in the kernel.
161e754f4d1SNicholas Piggin	 */
162e754f4d1SNicholas Piggin	mtcr	r2
163e754f4d1SNicholas Piggin	ld	r2,GPR2(r1)
164e754f4d1SNicholas Piggin	ld	r3,GPR3(r1)
165e754f4d1SNicholas Piggin	ld	r13,GPR13(r1)
166e754f4d1SNicholas Piggin	ld	r1,GPR1(r1)
167e754f4d1SNicholas Piggin	RFSCV_TO_USER
168e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
169e754f4d1SNicholas Piggin
170e754f4d1SNicholas Piggin.Lsyscall_vectored_\name\()_restore_regs:
171e754f4d1SNicholas Piggin	li	r3,0
172e754f4d1SNicholas Piggin	mtmsrd	r3,1
173e754f4d1SNicholas Piggin	mtspr	SPRN_SRR0,r4
174e754f4d1SNicholas Piggin	mtspr	SPRN_SRR1,r5
175e754f4d1SNicholas Piggin
176e754f4d1SNicholas Piggin	ld	r3,_CTR(r1)
177e754f4d1SNicholas Piggin	ld	r4,_LINK(r1)
178e754f4d1SNicholas Piggin	ld	r5,_XER(r1)
179e754f4d1SNicholas Piggin
180e754f4d1SNicholas Piggin	REST_NVGPRS(r1)
181e754f4d1SNicholas Piggin	ld	r0,GPR0(r1)
182e754f4d1SNicholas Piggin	mtcr	r2
183e754f4d1SNicholas Piggin	mtctr	r3
184e754f4d1SNicholas Piggin	mtlr	r4
185e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r5
186e754f4d1SNicholas Piggin	REST_10GPRS(2, r1)
187e754f4d1SNicholas Piggin	REST_2GPRS(12, r1)
188e754f4d1SNicholas Piggin	ld	r1,GPR1(r1)
189e754f4d1SNicholas Piggin	RFI_TO_USER
190e754f4d1SNicholas Piggin.endm
191e754f4d1SNicholas Piggin
192e754f4d1SNicholas Pigginsystem_call_vectored common 0x3000
193e754f4d1SNicholas Piggin/*
194e754f4d1SNicholas Piggin * We instantiate another entry copy for the SIGILL variant, with TRAP=0x7ff0
195e754f4d1SNicholas Piggin * which is tested by system_call_exception when r0 is -1 (as set by vector
196e754f4d1SNicholas Piggin * entry code).
197e754f4d1SNicholas Piggin */
198e754f4d1SNicholas Pigginsystem_call_vectored sigill 0x7ff0
199e754f4d1SNicholas Piggin
200e754f4d1SNicholas Piggin
201e754f4d1SNicholas Piggin/*
202e754f4d1SNicholas Piggin * Entered via kernel return set up by kernel/sstep.c, must match entry regs
203e754f4d1SNicholas Piggin */
204e754f4d1SNicholas Piggin	.globl system_call_vectored_emulate
205e754f4d1SNicholas Pigginsystem_call_vectored_emulate:
206e754f4d1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(system_call_vectored_emulate)
207e754f4d1SNicholas Piggin	li	r10,IRQS_ALL_DISABLED
208e754f4d1SNicholas Piggin	stb	r10,PACAIRQSOFTMASK(r13)
209e754f4d1SNicholas Piggin	b	system_call_vectored_common
210e754f4d1SNicholas Piggin#endif
211e754f4d1SNicholas Piggin
212e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
213e754f4d1SNicholas Piggin	.globl system_call_common_real
214e754f4d1SNicholas Pigginsystem_call_common_real:
215e754f4d1SNicholas Piggin	ld	r10,PACAKMSR(r13)	/* get MSR value for kernel */
216e754f4d1SNicholas Piggin	mtmsrd	r10
217e754f4d1SNicholas Piggin
218e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
219e754f4d1SNicholas Piggin	.globl system_call_common
220e754f4d1SNicholas Pigginsystem_call_common:
221e754f4d1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(system_call_common)
222e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
223e754f4d1SNicholas PigginBEGIN_FTR_SECTION
224e754f4d1SNicholas Piggin	extrdi.	r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */
225e754f4d1SNicholas Piggin	bne	.Ltabort_syscall
226e754f4d1SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_TM)
227e754f4d1SNicholas Piggin#endif
228e754f4d1SNicholas Piggin	mr	r10,r1
229e754f4d1SNicholas Piggin	ld	r1,PACAKSAVE(r13)
230e754f4d1SNicholas Piggin	std	r10,0(r1)
231e754f4d1SNicholas Piggin	std	r11,_NIP(r1)
232e754f4d1SNicholas Piggin	std	r12,_MSR(r1)
233e754f4d1SNicholas Piggin	std	r0,GPR0(r1)
234e754f4d1SNicholas Piggin	std	r10,GPR1(r1)
235e754f4d1SNicholas Piggin	std	r2,GPR2(r1)
236e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_FSL_BOOK3E
237e754f4d1SNicholas PigginSTART_BTB_FLUSH_SECTION
238e754f4d1SNicholas Piggin	BTB_FLUSH(r10)
239e754f4d1SNicholas PigginEND_BTB_FLUSH_SECTION
240e754f4d1SNicholas Piggin#endif
241e754f4d1SNicholas Piggin	ld	r2,PACATOC(r13)
242e754f4d1SNicholas Piggin	mfcr	r12
243e754f4d1SNicholas Piggin	li	r11,0
244e754f4d1SNicholas Piggin	/* Can we avoid saving r3-r8 in common case? */
245e754f4d1SNicholas Piggin	std	r3,GPR3(r1)
246e754f4d1SNicholas Piggin	std	r4,GPR4(r1)
247e754f4d1SNicholas Piggin	std	r5,GPR5(r1)
248e754f4d1SNicholas Piggin	std	r6,GPR6(r1)
249e754f4d1SNicholas Piggin	std	r7,GPR7(r1)
250e754f4d1SNicholas Piggin	std	r8,GPR8(r1)
251e754f4d1SNicholas Piggin	/* Zero r9-r12, this should only be required when restoring all GPRs */
252e754f4d1SNicholas Piggin	std	r11,GPR9(r1)
253e754f4d1SNicholas Piggin	std	r11,GPR10(r1)
254e754f4d1SNicholas Piggin	std	r11,GPR11(r1)
255e754f4d1SNicholas Piggin	std	r11,GPR12(r1)
256e754f4d1SNicholas Piggin	std	r9,GPR13(r1)
257e754f4d1SNicholas Piggin	SAVE_NVGPRS(r1)
258e754f4d1SNicholas Piggin	std	r11,_XER(r1)
259e754f4d1SNicholas Piggin	std	r11,_CTR(r1)
260e754f4d1SNicholas Piggin	mflr	r10
261e754f4d1SNicholas Piggin
262e754f4d1SNicholas Piggin	/*
263e754f4d1SNicholas Piggin	 * This clears CR0.SO (bit 28), which is the error indication on
264e754f4d1SNicholas Piggin	 * return from this system call.
265e754f4d1SNicholas Piggin	 */
266e754f4d1SNicholas Piggin	rldimi	r12,r11,28,(63-28)
267e754f4d1SNicholas Piggin	li	r11,0xc00
268e754f4d1SNicholas Piggin	std	r10,_LINK(r1)
269e754f4d1SNicholas Piggin	std	r11,_TRAP(r1)
270e754f4d1SNicholas Piggin	std	r12,_CCR(r1)
271e754f4d1SNicholas Piggin	addi	r10,r1,STACK_FRAME_OVERHEAD
272e754f4d1SNicholas Piggin	ld	r11,exception_marker@toc(r2)
273e754f4d1SNicholas Piggin	std	r11,-16(r10)		/* "regshere" marker */
274e754f4d1SNicholas Piggin
275e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
276e754f4d1SNicholas Piggin	li	r11,1
277e754f4d1SNicholas Piggin	stb	r11,PACASRR_VALID(r13)
278e754f4d1SNicholas Piggin#endif
279e754f4d1SNicholas Piggin
280e754f4d1SNicholas Piggin	/*
281e754f4d1SNicholas Piggin	 * We always enter kernel from userspace with irq soft-mask enabled and
282e754f4d1SNicholas Piggin	 * nothing pending. system_call_exception() will call
283e754f4d1SNicholas Piggin	 * trace_hardirqs_off().
284e754f4d1SNicholas Piggin	 */
285e754f4d1SNicholas Piggin	li	r11,IRQS_ALL_DISABLED
286*dd152f70SNicholas Piggin	li	r12,-1 /* Set MSR_EE and MSR_RI */
287e754f4d1SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
288*dd152f70SNicholas Piggin	mtmsrd	r12,1
289e754f4d1SNicholas Piggin
290e754f4d1SNicholas Piggin	/* Calling convention has r9 = orig r0, r10 = regs */
291e754f4d1SNicholas Piggin	mr	r9,r0
292e754f4d1SNicholas Piggin	bl	system_call_exception
293e754f4d1SNicholas Piggin
294e754f4d1SNicholas Piggin.Lsyscall_exit:
295e754f4d1SNicholas Piggin	addi    r4,r1,STACK_FRAME_OVERHEAD
296e754f4d1SNicholas Piggin	li	r5,0 /* !scv */
297e754f4d1SNicholas Piggin	bl	syscall_exit_prepare
298e754f4d1SNicholas Piggin
299e754f4d1SNicholas Piggin	ld	r2,_CCR(r1)
300e754f4d1SNicholas Piggin	ld	r6,_LINK(r1)
301e754f4d1SNicholas Piggin	mtlr	r6
302e754f4d1SNicholas Piggin
303e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
304e754f4d1SNicholas Piggin	lbz	r4,PACASRR_VALID(r13)
305e754f4d1SNicholas Piggin	cmpdi	r4,0
306e754f4d1SNicholas Piggin	bne	1f
307e754f4d1SNicholas Piggin	li	r4,0
308e754f4d1SNicholas Piggin	stb	r4,PACASRR_VALID(r13)
309e754f4d1SNicholas Piggin#endif
310e754f4d1SNicholas Piggin	ld	r4,_NIP(r1)
311e754f4d1SNicholas Piggin	ld	r5,_MSR(r1)
312e754f4d1SNicholas Piggin	mtspr	SPRN_SRR0,r4
313e754f4d1SNicholas Piggin	mtspr	SPRN_SRR1,r5
314e754f4d1SNicholas Piggin1:
315e754f4d1SNicholas Piggin	DEBUG_SRR_VALID srr
316e754f4d1SNicholas Piggin
317e754f4d1SNicholas PigginBEGIN_FTR_SECTION
318e754f4d1SNicholas Piggin	stdcx.	r0,0,r1			/* to clear the reservation */
319e754f4d1SNicholas PigginEND_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
320e754f4d1SNicholas Piggin
321e754f4d1SNicholas Piggin	cmpdi	r3,0
322e754f4d1SNicholas Piggin	bne	.Lsyscall_restore_regs
323e754f4d1SNicholas Piggin	/* Zero volatile regs that may contain sensitive kernel data */
324e754f4d1SNicholas Piggin	li	r0,0
325e754f4d1SNicholas Piggin	li	r4,0
326e754f4d1SNicholas Piggin	li	r5,0
327e754f4d1SNicholas Piggin	li	r6,0
328e754f4d1SNicholas Piggin	li	r7,0
329e754f4d1SNicholas Piggin	li	r8,0
330e754f4d1SNicholas Piggin	li	r9,0
331e754f4d1SNicholas Piggin	li	r10,0
332e754f4d1SNicholas Piggin	li	r11,0
333e754f4d1SNicholas Piggin	li	r12,0
334e754f4d1SNicholas Piggin	mtctr	r0
335e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r0
336e754f4d1SNicholas Piggin.Lsyscall_restore_regs_cont:
337e754f4d1SNicholas Piggin
338e754f4d1SNicholas PigginBEGIN_FTR_SECTION
339e754f4d1SNicholas Piggin	HMT_MEDIUM_LOW
340e754f4d1SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
341e754f4d1SNicholas Piggin
342e754f4d1SNicholas Piggin	/*
343e754f4d1SNicholas Piggin	 * We don't need to restore AMR on the way back to userspace for KUAP.
344e754f4d1SNicholas Piggin	 * The value of AMR only matters while we're in the kernel.
345e754f4d1SNicholas Piggin	 */
346e754f4d1SNicholas Piggin	mtcr	r2
347e754f4d1SNicholas Piggin	ld	r2,GPR2(r1)
348e754f4d1SNicholas Piggin	ld	r3,GPR3(r1)
349e754f4d1SNicholas Piggin	ld	r13,GPR13(r1)
350e754f4d1SNicholas Piggin	ld	r1,GPR1(r1)
351e754f4d1SNicholas Piggin	RFI_TO_USER
352e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
353e754f4d1SNicholas Piggin
354e754f4d1SNicholas Piggin.Lsyscall_restore_regs:
355e754f4d1SNicholas Piggin	ld	r3,_CTR(r1)
356e754f4d1SNicholas Piggin	ld	r4,_XER(r1)
357e754f4d1SNicholas Piggin	REST_NVGPRS(r1)
358e754f4d1SNicholas Piggin	mtctr	r3
359e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r4
360e754f4d1SNicholas Piggin	ld	r0,GPR0(r1)
361e754f4d1SNicholas Piggin	REST_8GPRS(4, r1)
362e754f4d1SNicholas Piggin	ld	r12,GPR12(r1)
363e754f4d1SNicholas Piggin	b	.Lsyscall_restore_regs_cont
364e754f4d1SNicholas Piggin
365e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
366e754f4d1SNicholas Piggin.Ltabort_syscall:
367e754f4d1SNicholas Piggin	/* Firstly we need to enable TM in the kernel */
368e754f4d1SNicholas Piggin	mfmsr	r10
369e754f4d1SNicholas Piggin	li	r9, 1
370e754f4d1SNicholas Piggin	rldimi	r10, r9, MSR_TM_LG, 63-MSR_TM_LG
371e754f4d1SNicholas Piggin	mtmsrd	r10, 0
372e754f4d1SNicholas Piggin
373e754f4d1SNicholas Piggin	/* tabort, this dooms the transaction, nothing else */
374e754f4d1SNicholas Piggin	li	r9, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)
375e754f4d1SNicholas Piggin	TABORT(R9)
376e754f4d1SNicholas Piggin
377e754f4d1SNicholas Piggin	/*
378e754f4d1SNicholas Piggin	 * Return directly to userspace. We have corrupted user register state,
379e754f4d1SNicholas Piggin	 * but userspace will never see that register state. Execution will
380e754f4d1SNicholas Piggin	 * resume after the tbegin of the aborted transaction with the
381e754f4d1SNicholas Piggin	 * checkpointed register state.
382e754f4d1SNicholas Piggin	 */
383e754f4d1SNicholas Piggin	li	r9, MSR_RI
384e754f4d1SNicholas Piggin	andc	r10, r10, r9
385e754f4d1SNicholas Piggin	mtmsrd	r10, 1
386e754f4d1SNicholas Piggin	mtspr	SPRN_SRR0, r11
387e754f4d1SNicholas Piggin	mtspr	SPRN_SRR1, r12
388e754f4d1SNicholas Piggin	RFI_TO_USER
389e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
390e754f4d1SNicholas Piggin#endif
391e754f4d1SNicholas Piggin
392e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
393e754f4d1SNicholas Piggin_GLOBAL(ret_from_fork_scv)
394e754f4d1SNicholas Piggin	bl	schedule_tail
395e754f4d1SNicholas Piggin	REST_NVGPRS(r1)
396e754f4d1SNicholas Piggin	li	r3,0	/* fork() return value */
397e754f4d1SNicholas Piggin	b	.Lsyscall_vectored_common_exit
398e754f4d1SNicholas Piggin#endif
399e754f4d1SNicholas Piggin
400e754f4d1SNicholas Piggin_GLOBAL(ret_from_fork)
401e754f4d1SNicholas Piggin	bl	schedule_tail
402e754f4d1SNicholas Piggin	REST_NVGPRS(r1)
403e754f4d1SNicholas Piggin	li	r3,0	/* fork() return value */
404e754f4d1SNicholas Piggin	b	.Lsyscall_exit
405e754f4d1SNicholas Piggin
406e754f4d1SNicholas Piggin_GLOBAL(ret_from_kernel_thread)
407e754f4d1SNicholas Piggin	bl	schedule_tail
408e754f4d1SNicholas Piggin	REST_NVGPRS(r1)
409e754f4d1SNicholas Piggin	mtctr	r14
410e754f4d1SNicholas Piggin	mr	r3,r15
411e754f4d1SNicholas Piggin#ifdef PPC64_ELF_ABI_v2
412e754f4d1SNicholas Piggin	mr	r12,r14
413e754f4d1SNicholas Piggin#endif
414e754f4d1SNicholas Piggin	bctrl
415e754f4d1SNicholas Piggin	li	r3,0
416e754f4d1SNicholas Piggin	b	.Lsyscall_exit
417e754f4d1SNicholas Piggin
418e754f4d1SNicholas Piggin	/*
419e754f4d1SNicholas Piggin	 * If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not
420e754f4d1SNicholas Piggin	 * touched, no exit work created, then this can be used.
421e754f4d1SNicholas Piggin	 */
422e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
423e754f4d1SNicholas Piggin	.globl fast_interrupt_return_srr
424e754f4d1SNicholas Pigginfast_interrupt_return_srr:
425e754f4d1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(fast_interrupt_return_srr)
426e754f4d1SNicholas Piggin	kuap_check_amr r3, r4
427e754f4d1SNicholas Piggin	ld	r5,_MSR(r1)
428e754f4d1SNicholas Piggin	andi.	r0,r5,MSR_PR
429e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
430e754f4d1SNicholas Piggin	bne	.Lfast_user_interrupt_return_amr_srr
431e754f4d1SNicholas Piggin	kuap_kernel_restore r3, r4
432e754f4d1SNicholas Piggin	andi.	r0,r5,MSR_RI
433e754f4d1SNicholas Piggin	li	r3,0 /* 0 return value, no EMULATE_STACK_STORE */
434e754f4d1SNicholas Piggin	bne+	.Lfast_kernel_interrupt_return_srr
435e754f4d1SNicholas Piggin	addi	r3,r1,STACK_FRAME_OVERHEAD
436e754f4d1SNicholas Piggin	bl	unrecoverable_exception
437e754f4d1SNicholas Piggin	b	. /* should not get here */
438e754f4d1SNicholas Piggin#else
439e754f4d1SNicholas Piggin	bne	.Lfast_user_interrupt_return_srr
440e754f4d1SNicholas Piggin	b	.Lfast_kernel_interrupt_return_srr
441e754f4d1SNicholas Piggin#endif
442e754f4d1SNicholas Piggin
443e754f4d1SNicholas Piggin.macro interrupt_return_macro srr
444e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
445e754f4d1SNicholas Piggin	.globl interrupt_return_\srr
446e754f4d1SNicholas Piggininterrupt_return_\srr\():
447e754f4d1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\())
448e754f4d1SNicholas Piggin	ld	r4,_MSR(r1)
449e754f4d1SNicholas Piggin	andi.	r0,r4,MSR_PR
450e754f4d1SNicholas Piggin	beq	.Lkernel_interrupt_return_\srr
451e754f4d1SNicholas Piggin	addi	r3,r1,STACK_FRAME_OVERHEAD
452e754f4d1SNicholas Piggin	bl	interrupt_exit_user_prepare
453e754f4d1SNicholas Piggin	cmpdi	r3,0
454e754f4d1SNicholas Piggin	bne-	.Lrestore_nvgprs_\srr
455e754f4d1SNicholas Piggin
456e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
457e754f4d1SNicholas Piggin.Lfast_user_interrupt_return_amr_\srr\():
458e754f4d1SNicholas Piggin	kuap_user_restore r3, r4
459e754f4d1SNicholas Piggin#endif
460e754f4d1SNicholas Piggin.Lfast_user_interrupt_return_\srr\():
461e754f4d1SNicholas Piggin
462e754f4d1SNicholas PigginBEGIN_FTR_SECTION
463e754f4d1SNicholas Piggin	ld	r10,_PPR(r1)
464e754f4d1SNicholas Piggin	mtspr	SPRN_PPR,r10
465e754f4d1SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
466e754f4d1SNicholas Piggin
467e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
468e754f4d1SNicholas Piggin	.ifc \srr,srr
469e754f4d1SNicholas Piggin	lbz	r4,PACASRR_VALID(r13)
470e754f4d1SNicholas Piggin	.else
471e754f4d1SNicholas Piggin	lbz	r4,PACAHSRR_VALID(r13)
472e754f4d1SNicholas Piggin	.endif
473e754f4d1SNicholas Piggin	cmpdi	r4,0
474e754f4d1SNicholas Piggin	li	r4,0
475e754f4d1SNicholas Piggin	bne	1f
476e754f4d1SNicholas Piggin#endif
477e754f4d1SNicholas Piggin	ld	r11,_NIP(r1)
478e754f4d1SNicholas Piggin	ld	r12,_MSR(r1)
479e754f4d1SNicholas Piggin	.ifc \srr,srr
480e754f4d1SNicholas Piggin	mtspr	SPRN_SRR0,r11
481e754f4d1SNicholas Piggin	mtspr	SPRN_SRR1,r12
482e754f4d1SNicholas Piggin1:
483e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
484e754f4d1SNicholas Piggin	stb	r4,PACASRR_VALID(r13)
485e754f4d1SNicholas Piggin#endif
486e754f4d1SNicholas Piggin	.else
487e754f4d1SNicholas Piggin	mtspr	SPRN_HSRR0,r11
488e754f4d1SNicholas Piggin	mtspr	SPRN_HSRR1,r12
489e754f4d1SNicholas Piggin1:
490e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
491e754f4d1SNicholas Piggin	stb	r4,PACAHSRR_VALID(r13)
492e754f4d1SNicholas Piggin#endif
493e754f4d1SNicholas Piggin	.endif
494e754f4d1SNicholas Piggin	DEBUG_SRR_VALID \srr
495e754f4d1SNicholas Piggin
496e754f4d1SNicholas PigginBEGIN_FTR_SECTION
497e754f4d1SNicholas Piggin	stdcx.	r0,0,r1		/* to clear the reservation */
498e754f4d1SNicholas PigginFTR_SECTION_ELSE
499e754f4d1SNicholas Piggin	ldarx	r0,0,r1
500e754f4d1SNicholas PigginALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
501e754f4d1SNicholas Piggin
502e754f4d1SNicholas Piggin	ld	r3,_CCR(r1)
503e754f4d1SNicholas Piggin	ld	r4,_LINK(r1)
504e754f4d1SNicholas Piggin	ld	r5,_CTR(r1)
505e754f4d1SNicholas Piggin	ld	r6,_XER(r1)
506e754f4d1SNicholas Piggin	li	r0,0
507e754f4d1SNicholas Piggin
508e754f4d1SNicholas Piggin	REST_4GPRS(7, r1)
509e754f4d1SNicholas Piggin	REST_2GPRS(11, r1)
510e754f4d1SNicholas Piggin	REST_GPR(13, r1)
511e754f4d1SNicholas Piggin
512e754f4d1SNicholas Piggin	mtcr	r3
513e754f4d1SNicholas Piggin	mtlr	r4
514e754f4d1SNicholas Piggin	mtctr	r5
515e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r6
516e754f4d1SNicholas Piggin
517e754f4d1SNicholas Piggin	REST_4GPRS(2, r1)
518e754f4d1SNicholas Piggin	REST_GPR(6, r1)
519e754f4d1SNicholas Piggin	REST_GPR(0, r1)
520e754f4d1SNicholas Piggin	REST_GPR(1, r1)
521e754f4d1SNicholas Piggin	.ifc \srr,srr
522e754f4d1SNicholas Piggin	RFI_TO_USER
523e754f4d1SNicholas Piggin	.else
524e754f4d1SNicholas Piggin	HRFI_TO_USER
525e754f4d1SNicholas Piggin	.endif
526e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
527e754f4d1SNicholas Piggin
528e754f4d1SNicholas Piggin.Lrestore_nvgprs_\srr\():
529e754f4d1SNicholas Piggin	REST_NVGPRS(r1)
530e754f4d1SNicholas Piggin	b	.Lfast_user_interrupt_return_\srr
531e754f4d1SNicholas Piggin
532e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
533e754f4d1SNicholas Piggin.Lkernel_interrupt_return_\srr\():
534e754f4d1SNicholas Piggin	addi	r3,r1,STACK_FRAME_OVERHEAD
535e754f4d1SNicholas Piggin	bl	interrupt_exit_kernel_prepare
536e754f4d1SNicholas Piggin
537e754f4d1SNicholas Piggin.Lfast_kernel_interrupt_return_\srr\():
538e754f4d1SNicholas Piggin	cmpdi	cr1,r3,0
539e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
540e754f4d1SNicholas Piggin	.ifc \srr,srr
541e754f4d1SNicholas Piggin	lbz	r4,PACASRR_VALID(r13)
542e754f4d1SNicholas Piggin	.else
543e754f4d1SNicholas Piggin	lbz	r4,PACAHSRR_VALID(r13)
544e754f4d1SNicholas Piggin	.endif
545e754f4d1SNicholas Piggin	cmpdi	r4,0
546e754f4d1SNicholas Piggin	li	r4,0
547e754f4d1SNicholas Piggin	bne	1f
548e754f4d1SNicholas Piggin#endif
549e754f4d1SNicholas Piggin	ld	r11,_NIP(r1)
550e754f4d1SNicholas Piggin	ld	r12,_MSR(r1)
551e754f4d1SNicholas Piggin	.ifc \srr,srr
552e754f4d1SNicholas Piggin	mtspr	SPRN_SRR0,r11
553e754f4d1SNicholas Piggin	mtspr	SPRN_SRR1,r12
554e754f4d1SNicholas Piggin1:
555e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
556e754f4d1SNicholas Piggin	stb	r4,PACASRR_VALID(r13)
557e754f4d1SNicholas Piggin#endif
558e754f4d1SNicholas Piggin	.else
559e754f4d1SNicholas Piggin	mtspr	SPRN_HSRR0,r11
560e754f4d1SNicholas Piggin	mtspr	SPRN_HSRR1,r12
561e754f4d1SNicholas Piggin1:
562e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
563e754f4d1SNicholas Piggin	stb	r4,PACAHSRR_VALID(r13)
564e754f4d1SNicholas Piggin#endif
565e754f4d1SNicholas Piggin	.endif
566e754f4d1SNicholas Piggin	DEBUG_SRR_VALID \srr
567e754f4d1SNicholas Piggin
568e754f4d1SNicholas PigginBEGIN_FTR_SECTION
569e754f4d1SNicholas Piggin	stdcx.	r0,0,r1		/* to clear the reservation */
570e754f4d1SNicholas PigginFTR_SECTION_ELSE
571e754f4d1SNicholas Piggin	ldarx	r0,0,r1
572e754f4d1SNicholas PigginALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
573e754f4d1SNicholas Piggin
574e754f4d1SNicholas Piggin	ld	r3,_LINK(r1)
575e754f4d1SNicholas Piggin	ld	r4,_CTR(r1)
576e754f4d1SNicholas Piggin	ld	r5,_XER(r1)
577e754f4d1SNicholas Piggin	ld	r6,_CCR(r1)
578e754f4d1SNicholas Piggin	li	r0,0
579e754f4d1SNicholas Piggin
580e754f4d1SNicholas Piggin	REST_4GPRS(7, r1)
581e754f4d1SNicholas Piggin	REST_2GPRS(11, r1)
582e754f4d1SNicholas Piggin
583e754f4d1SNicholas Piggin	mtlr	r3
584e754f4d1SNicholas Piggin	mtctr	r4
585e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r5
586e754f4d1SNicholas Piggin
587e754f4d1SNicholas Piggin	/*
588e754f4d1SNicholas Piggin	 * Leaving a stale exception_marker on the stack can confuse
589e754f4d1SNicholas Piggin	 * the reliable stack unwinder later on. Clear it.
590e754f4d1SNicholas Piggin	 */
591e754f4d1SNicholas Piggin	std	r0,STACK_FRAME_OVERHEAD-16(r1)
592e754f4d1SNicholas Piggin
593e754f4d1SNicholas Piggin	REST_4GPRS(2, r1)
594e754f4d1SNicholas Piggin
595e754f4d1SNicholas Piggin	bne-	cr1,1f /* emulate stack store */
596e754f4d1SNicholas Piggin	mtcr	r6
597e754f4d1SNicholas Piggin	REST_GPR(6, r1)
598e754f4d1SNicholas Piggin	REST_GPR(0, r1)
599e754f4d1SNicholas Piggin	REST_GPR(1, r1)
600e754f4d1SNicholas Piggin	.ifc \srr,srr
601e754f4d1SNicholas Piggin	RFI_TO_KERNEL
602e754f4d1SNicholas Piggin	.else
603e754f4d1SNicholas Piggin	HRFI_TO_KERNEL
604e754f4d1SNicholas Piggin	.endif
605e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
606e754f4d1SNicholas Piggin
607e754f4d1SNicholas Piggin1:	/*
608e754f4d1SNicholas Piggin	 * Emulate stack store with update. New r1 value was already calculated
609e754f4d1SNicholas Piggin	 * and updated in our interrupt regs by emulate_loadstore, but we can't
610e754f4d1SNicholas Piggin	 * store the previous value of r1 to the stack before re-loading our
611e754f4d1SNicholas Piggin	 * registers from it, otherwise they could be clobbered.  Use
612e754f4d1SNicholas Piggin	 * PACA_EXGEN as temporary storage to hold the store data, as
613e754f4d1SNicholas Piggin	 * interrupts are disabled here so it won't be clobbered.
614e754f4d1SNicholas Piggin	 */
615e754f4d1SNicholas Piggin	mtcr	r6
616e754f4d1SNicholas Piggin	std	r9,PACA_EXGEN+0(r13)
617e754f4d1SNicholas Piggin	addi	r9,r1,INT_FRAME_SIZE /* get original r1 */
618e754f4d1SNicholas Piggin	REST_GPR(6, r1)
619e754f4d1SNicholas Piggin	REST_GPR(0, r1)
620e754f4d1SNicholas Piggin	REST_GPR(1, r1)
621e754f4d1SNicholas Piggin	std	r9,0(r1) /* perform store component of stdu */
622e754f4d1SNicholas Piggin	ld	r9,PACA_EXGEN+0(r13)
623e754f4d1SNicholas Piggin
624e754f4d1SNicholas Piggin	.ifc \srr,srr
625e754f4d1SNicholas Piggin	RFI_TO_KERNEL
626e754f4d1SNicholas Piggin	.else
627e754f4d1SNicholas Piggin	HRFI_TO_KERNEL
628e754f4d1SNicholas Piggin	.endif
629e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
630e754f4d1SNicholas Piggin.endm
631e754f4d1SNicholas Piggin
632e754f4d1SNicholas Piggininterrupt_return_macro srr
633e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
634e754f4d1SNicholas Piggininterrupt_return_macro hsrr
635e754f4d1SNicholas Piggin#endif
636