xref: /openbmc/linux/arch/powerpc/kernel/interrupt_64.S (revision c595db6d7c8bcf87ef42204391fa890e5950e566)
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
16e754f4d1SNicholas Piggin	.align 7
17e754f4d1SNicholas Piggin
18e754f4d1SNicholas Piggin.macro DEBUG_SRR_VALID srr
19e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_RFI_SRR_DEBUG
20e754f4d1SNicholas Piggin	.ifc \srr,srr
21e754f4d1SNicholas Piggin	mfspr	r11,SPRN_SRR0
22e754f4d1SNicholas Piggin	ld	r12,_NIP(r1)
23aee101d7SNicholas Piggin	clrrdi  r11,r11,2
24314f6c23SMichael Ellerman	clrrdi  r12,r12,2
25e754f4d1SNicholas Piggin100:	tdne	r11,r12
26fd1eaaaaSMichael Ellerman	EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
27e754f4d1SNicholas Piggin	mfspr	r11,SPRN_SRR1
28e754f4d1SNicholas Piggin	ld	r12,_MSR(r1)
29e754f4d1SNicholas Piggin100:	tdne	r11,r12
30fd1eaaaaSMichael Ellerman	EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
31e754f4d1SNicholas Piggin	.else
32e754f4d1SNicholas Piggin	mfspr	r11,SPRN_HSRR0
33e754f4d1SNicholas Piggin	ld	r12,_NIP(r1)
34aee101d7SNicholas Piggin	clrrdi  r11,r11,2
35314f6c23SMichael Ellerman	clrrdi  r12,r12,2
36e754f4d1SNicholas Piggin100:	tdne	r11,r12
37fd1eaaaaSMichael Ellerman	EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
38e754f4d1SNicholas Piggin	mfspr	r11,SPRN_HSRR1
39e754f4d1SNicholas Piggin	ld	r12,_MSR(r1)
40e754f4d1SNicholas Piggin100:	tdne	r11,r12
41fd1eaaaaSMichael Ellerman	EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
42e754f4d1SNicholas Piggin	.endif
43e754f4d1SNicholas Piggin#endif
44e754f4d1SNicholas Piggin.endm
45e754f4d1SNicholas Piggin
46e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
47e754f4d1SNicholas Piggin.macro system_call_vectored name trapnr
48e754f4d1SNicholas Piggin	.globl system_call_vectored_\name
49e754f4d1SNicholas Pigginsystem_call_vectored_\name:
50e754f4d1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(system_call_vectored_\name)
51e754f4d1SNicholas Piggin	SCV_INTERRUPT_TO_KERNEL
52e754f4d1SNicholas Piggin	mr	r10,r1
53e754f4d1SNicholas Piggin	ld	r1,PACAKSAVE(r13)
54e754f4d1SNicholas Piggin	std	r10,0(r1)
55*1b5181cbSNaveen N Rao	std	r11,_LINK(r1)
56*1b5181cbSNaveen N Rao	std	r11,_NIP(r1)	/* Saved LR is also the next instruction */
57e754f4d1SNicholas Piggin	std	r12,_MSR(r1)
58e754f4d1SNicholas Piggin	std	r0,GPR0(r1)
59e754f4d1SNicholas Piggin	std	r10,GPR1(r1)
60e754f4d1SNicholas Piggin	std	r2,GPR2(r1)
618e93fb33SNicholas Piggin	LOAD_PACA_TOC()
62e754f4d1SNicholas Piggin	mfcr	r12
63e754f4d1SNicholas Piggin	li	r11,0
64f8971c62SRohan McLure	/* Save syscall parameters in r3-r8 */
652b1dac4bSRohan McLure	SAVE_GPRS(3, 8, r1)
66e754f4d1SNicholas Piggin	/* Zero r9-r12, this should only be required when restoring all GPRs */
67e754f4d1SNicholas Piggin	std	r11,GPR9(r1)
68e754f4d1SNicholas Piggin	std	r11,GPR10(r1)
69e754f4d1SNicholas Piggin	std	r11,GPR11(r1)
70e754f4d1SNicholas Piggin	std	r11,GPR12(r1)
71e754f4d1SNicholas Piggin	std	r9,GPR13(r1)
72e754f4d1SNicholas Piggin	SAVE_NVGPRS(r1)
73e754f4d1SNicholas Piggin	std	r11,_XER(r1)
74e754f4d1SNicholas Piggin	std	r11,_CTR(r1)
75e754f4d1SNicholas Piggin
76e754f4d1SNicholas Piggin	li	r11,\trapnr
77e754f4d1SNicholas Piggin	std	r11,_TRAP(r1)
78e754f4d1SNicholas Piggin	std	r12,_CCR(r1)
792c27d4a4SRohan McLure	std	r3,ORIG_GPR3(r1)
80d2e8ff9fSNicholas Piggin	LOAD_REG_IMMEDIATE(r11, STACK_FRAME_REGS_MARKER)
81d2e8ff9fSNicholas Piggin	std	r11,STACK_INT_FRAME_MARKER(r1)		/* "regs" marker */
82f8971c62SRohan McLure	/* Calling convention has r3 = regs, r4 = orig r0 */
83c03be0a3SNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
84f8971c62SRohan McLure	mr	r4,r0
85e754f4d1SNicholas Piggin
86e754f4d1SNicholas PigginBEGIN_FTR_SECTION
87e754f4d1SNicholas Piggin	HMT_MEDIUM
88e754f4d1SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
89e754f4d1SNicholas Piggin
90e754f4d1SNicholas Piggin	/*
91e754f4d1SNicholas Piggin	 * scv enters with MSR[EE]=1 and is immediately considered soft-masked.
92e754f4d1SNicholas Piggin	 * The entry vector already sets PACAIRQSOFTMASK to IRQS_ALL_DISABLED,
93e754f4d1SNicholas Piggin	 * and interrupts may be masked and pending already.
94e754f4d1SNicholas Piggin	 * system_call_exception() will call trace_hardirqs_off() which means
95e754f4d1SNicholas Piggin	 * interrupts could already have been blocked before trace_hardirqs_off,
96e754f4d1SNicholas Piggin	 * but this is the best we can do.
97e754f4d1SNicholas Piggin	 */
98e754f4d1SNicholas Piggin
991df45d78SRohan McLure	/*
1001df45d78SRohan McLure	 * Zero user registers to prevent influencing speculative execution
1011df45d78SRohan McLure	 * state of kernel code.
1021df45d78SRohan McLure	 */
1031df45d78SRohan McLure	SANITIZE_SYSCALL_GPRS()
1044e991e3cSNicholas Piggin	bl	CFUNC(system_call_exception)
105e754f4d1SNicholas Piggin
106e754f4d1SNicholas Piggin.Lsyscall_vectored_\name\()_exit:
107c03be0a3SNicholas Piggin	addi	r4,r1,STACK_INT_FRAME_REGS
108e754f4d1SNicholas Piggin	li	r5,1 /* scv */
1094e991e3cSNicholas Piggin	bl	CFUNC(syscall_exit_prepare)
11013799748SNicholas Piggin	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
11113799748SNicholas Piggin.Lsyscall_vectored_\name\()_rst_start:
11213799748SNicholas Piggin	lbz	r11,PACAIRQHAPPENED(r13)
11313799748SNicholas Piggin	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
11413799748SNicholas Piggin	bne-	syscall_vectored_\name\()_restart
11513799748SNicholas Piggin	li	r11,IRQS_ENABLED
11613799748SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
11713799748SNicholas Piggin	li	r11,0
11813799748SNicholas Piggin	stb	r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
119e754f4d1SNicholas Piggin
120e754f4d1SNicholas Piggin	ld	r2,_CCR(r1)
121e754f4d1SNicholas Piggin	ld	r4,_NIP(r1)
122e754f4d1SNicholas Piggin	ld	r5,_MSR(r1)
123e754f4d1SNicholas Piggin
124e754f4d1SNicholas PigginBEGIN_FTR_SECTION
125e754f4d1SNicholas Piggin	stdcx.	r0,0,r1			/* to clear the reservation */
126e754f4d1SNicholas PigginEND_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
127e754f4d1SNicholas Piggin
128e754f4d1SNicholas PigginBEGIN_FTR_SECTION
129e754f4d1SNicholas Piggin	HMT_MEDIUM_LOW
130e754f4d1SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
131e754f4d1SNicholas Piggin
1321df45d78SRohan McLure	SANITIZE_RESTORE_NVGPRS()
133e754f4d1SNicholas Piggin	cmpdi	r3,0
134e754f4d1SNicholas Piggin	bne	.Lsyscall_vectored_\name\()_restore_regs
135e754f4d1SNicholas Piggin
136e754f4d1SNicholas Piggin	/* rfscv returns with LR->NIA and CTR->MSR */
137e754f4d1SNicholas Piggin	mtlr	r4
138e754f4d1SNicholas Piggin	mtctr	r5
139e754f4d1SNicholas Piggin
140e754f4d1SNicholas Piggin	/* Could zero these as per ABI, but we may consider a stricter ABI
141e754f4d1SNicholas Piggin	 * which preserves these if libc implementations can benefit, so
142e754f4d1SNicholas Piggin	 * restore them for now until further measurement is done. */
1432b1dac4bSRohan McLure	REST_GPR(0, r1)
1442b1dac4bSRohan McLure	REST_GPRS(4, 8, r1)
145e754f4d1SNicholas Piggin	/* Zero volatile regs that may contain sensitive kernel data */
1462b1dac4bSRohan McLure	ZEROIZE_GPRS(9, 12)
147e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r0
148e754f4d1SNicholas Piggin
149e754f4d1SNicholas Piggin	/*
150e754f4d1SNicholas Piggin	 * We don't need to restore AMR on the way back to userspace for KUAP.
151e754f4d1SNicholas Piggin	 * The value of AMR only matters while we're in the kernel.
152e754f4d1SNicholas Piggin	 */
153e754f4d1SNicholas Piggin	mtcr	r2
154aebd1fb4SNicholas Piggin	REST_GPRS(2, 3, r1)
155aebd1fb4SNicholas Piggin	REST_GPR(13, r1)
156aebd1fb4SNicholas Piggin	REST_GPR(1, r1)
157e754f4d1SNicholas Piggin	RFSCV_TO_USER
158e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
159e754f4d1SNicholas Piggin
160e754f4d1SNicholas Piggin.Lsyscall_vectored_\name\()_restore_regs:
161e754f4d1SNicholas Piggin	mtspr	SPRN_SRR0,r4
162e754f4d1SNicholas Piggin	mtspr	SPRN_SRR1,r5
163e754f4d1SNicholas Piggin
164e754f4d1SNicholas Piggin	ld	r3,_CTR(r1)
165e754f4d1SNicholas Piggin	ld	r4,_LINK(r1)
166e754f4d1SNicholas Piggin	ld	r5,_XER(r1)
167e754f4d1SNicholas Piggin
1681df45d78SRohan McLure	HANDLER_RESTORE_NVGPRS()
1692b1dac4bSRohan McLure	REST_GPR(0, r1)
170e754f4d1SNicholas Piggin	mtcr	r2
171e754f4d1SNicholas Piggin	mtctr	r3
172e754f4d1SNicholas Piggin	mtlr	r4
173e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r5
174aebd1fb4SNicholas Piggin	REST_GPRS(2, 13, r1)
175aebd1fb4SNicholas Piggin	REST_GPR(1, r1)
176e754f4d1SNicholas Piggin	RFI_TO_USER
17713799748SNicholas Piggin.Lsyscall_vectored_\name\()_rst_end:
17813799748SNicholas Piggin
17913799748SNicholas Pigginsyscall_vectored_\name\()_restart:
18098798f33SNicholas Piggin_ASM_NOKPROBE_SYMBOL(syscall_vectored_\name\()_restart)
18113799748SNicholas Piggin	GET_PACA(r13)
18213799748SNicholas Piggin	ld	r1,PACA_EXIT_SAVE_R1(r13)
1838e93fb33SNicholas Piggin	LOAD_PACA_TOC()
18413799748SNicholas Piggin	ld	r3,RESULT(r1)
185c03be0a3SNicholas Piggin	addi	r4,r1,STACK_INT_FRAME_REGS
18613799748SNicholas Piggin	li	r11,IRQS_ALL_DISABLED
18713799748SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
1884e991e3cSNicholas Piggin	bl	CFUNC(syscall_exit_restart)
18913799748SNicholas Piggin	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
19013799748SNicholas Piggin	b	.Lsyscall_vectored_\name\()_rst_start
191325678fdSNicholas Piggin1:
19213799748SNicholas Piggin
193325678fdSNicholas PigginSOFT_MASK_TABLE(.Lsyscall_vectored_\name\()_rst_start, 1b)
19413799748SNicholas PigginRESTART_TABLE(.Lsyscall_vectored_\name\()_rst_start, .Lsyscall_vectored_\name\()_rst_end, syscall_vectored_\name\()_restart)
19513799748SNicholas Piggin
196e754f4d1SNicholas Piggin.endm
197e754f4d1SNicholas Piggin
198e754f4d1SNicholas Pigginsystem_call_vectored common 0x3000
19913799748SNicholas Piggin
200e754f4d1SNicholas Piggin/*
201e754f4d1SNicholas Piggin * We instantiate another entry copy for the SIGILL variant, with TRAP=0x7ff0
202e754f4d1SNicholas Piggin * which is tested by system_call_exception when r0 is -1 (as set by vector
203e754f4d1SNicholas Piggin * entry code).
204e754f4d1SNicholas Piggin */
205e754f4d1SNicholas Pigginsystem_call_vectored sigill 0x7ff0
206e754f4d1SNicholas Piggin
2079b69d48cSNicholas Piggin#endif /* CONFIG_PPC_BOOK3S */
208e754f4d1SNicholas Piggin
209e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
210e754f4d1SNicholas Piggin	.globl system_call_common_real
211e754f4d1SNicholas Pigginsystem_call_common_real:
21298798f33SNicholas Piggin_ASM_NOKPROBE_SYMBOL(system_call_common_real)
213e754f4d1SNicholas Piggin	ld	r10,PACAKMSR(r13)	/* get MSR value for kernel */
214e754f4d1SNicholas Piggin	mtmsrd	r10
215e754f4d1SNicholas Piggin
216e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
217e754f4d1SNicholas Piggin	.globl system_call_common
218e754f4d1SNicholas Pigginsystem_call_common:
219e754f4d1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(system_call_common)
220e754f4d1SNicholas Piggin	mr	r10,r1
221e754f4d1SNicholas Piggin	ld	r1,PACAKSAVE(r13)
222e754f4d1SNicholas Piggin	std	r10,0(r1)
223e754f4d1SNicholas Piggin	std	r11,_NIP(r1)
224e754f4d1SNicholas Piggin	std	r12,_MSR(r1)
225e754f4d1SNicholas Piggin	std	r0,GPR0(r1)
226e754f4d1SNicholas Piggin	std	r10,GPR1(r1)
227e754f4d1SNicholas Piggin	std	r2,GPR2(r1)
2283e731858SChristophe Leroy#ifdef CONFIG_PPC_E500
229e754f4d1SNicholas PigginSTART_BTB_FLUSH_SECTION
230e754f4d1SNicholas Piggin	BTB_FLUSH(r10)
231e754f4d1SNicholas PigginEND_BTB_FLUSH_SECTION
232e754f4d1SNicholas Piggin#endif
2338e93fb33SNicholas Piggin	LOAD_PACA_TOC()
234e754f4d1SNicholas Piggin	mfcr	r12
235e754f4d1SNicholas Piggin	li	r11,0
236f8971c62SRohan McLure	/* Save syscall parameters in r3-r8 */
2372b1dac4bSRohan McLure	SAVE_GPRS(3, 8, r1)
238e754f4d1SNicholas Piggin	/* Zero r9-r12, this should only be required when restoring all GPRs */
239e754f4d1SNicholas Piggin	std	r11,GPR9(r1)
240e754f4d1SNicholas Piggin	std	r11,GPR10(r1)
241e754f4d1SNicholas Piggin	std	r11,GPR11(r1)
242e754f4d1SNicholas Piggin	std	r11,GPR12(r1)
243e754f4d1SNicholas Piggin	std	r9,GPR13(r1)
244e754f4d1SNicholas Piggin	SAVE_NVGPRS(r1)
245e754f4d1SNicholas Piggin	std	r11,_XER(r1)
246e754f4d1SNicholas Piggin	std	r11,_CTR(r1)
247e754f4d1SNicholas Piggin	mflr	r10
248e754f4d1SNicholas Piggin
249e754f4d1SNicholas Piggin	/*
250e754f4d1SNicholas Piggin	 * This clears CR0.SO (bit 28), which is the error indication on
251e754f4d1SNicholas Piggin	 * return from this system call.
252e754f4d1SNicholas Piggin	 */
253e754f4d1SNicholas Piggin	rldimi	r12,r11,28,(63-28)
254e754f4d1SNicholas Piggin	li	r11,0xc00
255e754f4d1SNicholas Piggin	std	r10,_LINK(r1)
256e754f4d1SNicholas Piggin	std	r11,_TRAP(r1)
257e754f4d1SNicholas Piggin	std	r12,_CCR(r1)
2582c27d4a4SRohan McLure	std	r3,ORIG_GPR3(r1)
259d2e8ff9fSNicholas Piggin	LOAD_REG_IMMEDIATE(r11, STACK_FRAME_REGS_MARKER)
260d2e8ff9fSNicholas Piggin	std	r11,STACK_INT_FRAME_MARKER(r1)		/* "regs" marker */
261f8971c62SRohan McLure	/* Calling convention has r3 = regs, r4 = orig r0 */
262c03be0a3SNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
263f8971c62SRohan McLure	mr	r4,r0
264e754f4d1SNicholas Piggin
265e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
266e754f4d1SNicholas Piggin	li	r11,1
267e754f4d1SNicholas Piggin	stb	r11,PACASRR_VALID(r13)
268e754f4d1SNicholas Piggin#endif
269e754f4d1SNicholas Piggin
270e754f4d1SNicholas Piggin	/*
271e754f4d1SNicholas Piggin	 * We always enter kernel from userspace with irq soft-mask enabled and
272e754f4d1SNicholas Piggin	 * nothing pending. system_call_exception() will call
273e754f4d1SNicholas Piggin	 * trace_hardirqs_off().
274e754f4d1SNicholas Piggin	 */
275e754f4d1SNicholas Piggin	li	r11,IRQS_ALL_DISABLED
276e754f4d1SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
2771df3af6dSNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
2781df3af6dSNicholas Piggin	li	r12,-1 /* Set MSR_EE and MSR_RI */
279dd152f70SNicholas Piggin	mtmsrd	r12,1
2801df3af6dSNicholas Piggin#else
2811df3af6dSNicholas Piggin	wrteei	1
2821df3af6dSNicholas Piggin#endif
283e754f4d1SNicholas Piggin
2841df45d78SRohan McLure	/*
2851df45d78SRohan McLure	 * Zero user registers to prevent influencing speculative execution
2861df45d78SRohan McLure	 * state of kernel code.
2871df45d78SRohan McLure	 */
2881df45d78SRohan McLure	SANITIZE_SYSCALL_GPRS()
2894e991e3cSNicholas Piggin	bl	CFUNC(system_call_exception)
290e754f4d1SNicholas Piggin
291e754f4d1SNicholas Piggin.Lsyscall_exit:
292c03be0a3SNicholas Piggin	addi	r4,r1,STACK_INT_FRAME_REGS
293e754f4d1SNicholas Piggin	li	r5,0 /* !scv */
2944e991e3cSNicholas Piggin	bl	CFUNC(syscall_exit_prepare)
29513799748SNicholas Piggin	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
2969b69d48cSNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
29713799748SNicholas Piggin.Lsyscall_rst_start:
29813799748SNicholas Piggin	lbz	r11,PACAIRQHAPPENED(r13)
29913799748SNicholas Piggin	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
30013799748SNicholas Piggin	bne-	syscall_restart
3019b69d48cSNicholas Piggin#endif
30213799748SNicholas Piggin	li	r11,IRQS_ENABLED
30313799748SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
30413799748SNicholas Piggin	li	r11,0
30513799748SNicholas Piggin	stb	r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
306e754f4d1SNicholas Piggin
307e754f4d1SNicholas Piggin	ld	r2,_CCR(r1)
308e754f4d1SNicholas Piggin	ld	r6,_LINK(r1)
309e754f4d1SNicholas Piggin	mtlr	r6
310e754f4d1SNicholas Piggin
311e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
312e754f4d1SNicholas Piggin	lbz	r4,PACASRR_VALID(r13)
313e754f4d1SNicholas Piggin	cmpdi	r4,0
314e754f4d1SNicholas Piggin	bne	1f
315e754f4d1SNicholas Piggin	li	r4,0
316e754f4d1SNicholas Piggin	stb	r4,PACASRR_VALID(r13)
317e754f4d1SNicholas Piggin#endif
318e754f4d1SNicholas Piggin	ld	r4,_NIP(r1)
319e754f4d1SNicholas Piggin	ld	r5,_MSR(r1)
320e754f4d1SNicholas Piggin	mtspr	SPRN_SRR0,r4
321e754f4d1SNicholas Piggin	mtspr	SPRN_SRR1,r5
322e754f4d1SNicholas Piggin1:
323e754f4d1SNicholas Piggin	DEBUG_SRR_VALID srr
324e754f4d1SNicholas Piggin
325e754f4d1SNicholas PigginBEGIN_FTR_SECTION
326e754f4d1SNicholas Piggin	stdcx.	r0,0,r1			/* to clear the reservation */
327e754f4d1SNicholas PigginEND_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
328e754f4d1SNicholas Piggin
3291df45d78SRohan McLure	SANITIZE_RESTORE_NVGPRS()
330e754f4d1SNicholas Piggin	cmpdi	r3,0
331e754f4d1SNicholas Piggin	bne	.Lsyscall_restore_regs
332e754f4d1SNicholas Piggin	/* Zero volatile regs that may contain sensitive kernel data */
3332b1dac4bSRohan McLure	ZEROIZE_GPR(0)
3342b1dac4bSRohan McLure	ZEROIZE_GPRS(4, 12)
335e754f4d1SNicholas Piggin	mtctr	r0
336e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r0
337e754f4d1SNicholas Piggin.Lsyscall_restore_regs_cont:
338e754f4d1SNicholas Piggin
339e754f4d1SNicholas PigginBEGIN_FTR_SECTION
340e754f4d1SNicholas Piggin	HMT_MEDIUM_LOW
341e754f4d1SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
342e754f4d1SNicholas Piggin
343e754f4d1SNicholas Piggin	/*
344e754f4d1SNicholas Piggin	 * We don't need to restore AMR on the way back to userspace for KUAP.
345e754f4d1SNicholas Piggin	 * The value of AMR only matters while we're in the kernel.
346e754f4d1SNicholas Piggin	 */
347e754f4d1SNicholas Piggin	mtcr	r2
348aebd1fb4SNicholas Piggin	REST_GPRS(2, 3, r1)
349aebd1fb4SNicholas Piggin	REST_GPR(13, r1)
350aebd1fb4SNicholas Piggin	REST_GPR(1, 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)
3571df45d78SRohan McLure	HANDLER_RESTORE_NVGPRS()
358e754f4d1SNicholas Piggin	mtctr	r3
359e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r4
3602b1dac4bSRohan McLure	REST_GPR(0, r1)
361aebd1fb4SNicholas Piggin	REST_GPRS(4, 12, r1)
362e754f4d1SNicholas Piggin	b	.Lsyscall_restore_regs_cont
36313799748SNicholas Piggin.Lsyscall_rst_end:
36413799748SNicholas Piggin
3659b69d48cSNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
36613799748SNicholas Pigginsyscall_restart:
36798798f33SNicholas Piggin_ASM_NOKPROBE_SYMBOL(syscall_restart)
36813799748SNicholas Piggin	GET_PACA(r13)
36913799748SNicholas Piggin	ld	r1,PACA_EXIT_SAVE_R1(r13)
3708e93fb33SNicholas Piggin	LOAD_PACA_TOC()
37113799748SNicholas Piggin	ld	r3,RESULT(r1)
372c03be0a3SNicholas Piggin	addi	r4,r1,STACK_INT_FRAME_REGS
37313799748SNicholas Piggin	li	r11,IRQS_ALL_DISABLED
37413799748SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
3754e991e3cSNicholas Piggin	bl	CFUNC(syscall_exit_restart)
37613799748SNicholas Piggin	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
37713799748SNicholas Piggin	b	.Lsyscall_rst_start
378325678fdSNicholas Piggin1:
37913799748SNicholas Piggin
380325678fdSNicholas PigginSOFT_MASK_TABLE(.Lsyscall_rst_start, 1b)
38113799748SNicholas PigginRESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, syscall_restart)
3829b69d48cSNicholas Piggin#endif
383e754f4d1SNicholas Piggin
384e754f4d1SNicholas Piggin	/*
385e754f4d1SNicholas Piggin	 * If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not
386e754f4d1SNicholas Piggin	 * touched, no exit work created, then this can be used.
387e754f4d1SNicholas Piggin	 */
388e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
389e754f4d1SNicholas Piggin	.globl fast_interrupt_return_srr
390e754f4d1SNicholas Pigginfast_interrupt_return_srr:
391e754f4d1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(fast_interrupt_return_srr)
392e754f4d1SNicholas Piggin	kuap_check_amr r3, r4
393e754f4d1SNicholas Piggin	ld	r5,_MSR(r1)
394e754f4d1SNicholas Piggin	andi.	r0,r5,MSR_PR
395e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
39613799748SNicholas Piggin	beq	1f
39713799748SNicholas Piggin	kuap_user_restore r3, r4
39813799748SNicholas Piggin	b	.Lfast_user_interrupt_return_srr
39913799748SNicholas Piggin1:	kuap_kernel_restore r3, r4
400e754f4d1SNicholas Piggin	andi.	r0,r5,MSR_RI
401e754f4d1SNicholas Piggin	li	r3,0 /* 0 return value, no EMULATE_STACK_STORE */
402e754f4d1SNicholas Piggin	bne+	.Lfast_kernel_interrupt_return_srr
403c03be0a3SNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
4044e991e3cSNicholas Piggin	bl	CFUNC(unrecoverable_exception)
405e754f4d1SNicholas Piggin	b	. /* should not get here */
406e754f4d1SNicholas Piggin#else
407e754f4d1SNicholas Piggin	bne	.Lfast_user_interrupt_return_srr
408e754f4d1SNicholas Piggin	b	.Lfast_kernel_interrupt_return_srr
409e754f4d1SNicholas Piggin#endif
410e754f4d1SNicholas Piggin
411e754f4d1SNicholas Piggin.macro interrupt_return_macro srr
412e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
413e754f4d1SNicholas Piggin	.globl interrupt_return_\srr
414e754f4d1SNicholas Piggininterrupt_return_\srr\():
415e754f4d1SNicholas Piggin_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\())
416e754f4d1SNicholas Piggin	ld	r4,_MSR(r1)
417e754f4d1SNicholas Piggin	andi.	r0,r4,MSR_PR
418c59458b0SNicholas Piggin	beq	interrupt_return_\srr\()_kernel
419c59458b0SNicholas Piggininterrupt_return_\srr\()_user: /* make backtraces match the _kernel variant */
420c59458b0SNicholas Piggin_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_user)
421c03be0a3SNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
4224e991e3cSNicholas Piggin	bl	CFUNC(interrupt_exit_user_prepare)
42375c5d6b1SRohan McLure#ifndef CONFIG_INTERRUPT_SANITIZE_REGISTERS
424e754f4d1SNicholas Piggin	cmpdi	r3,0
425e754f4d1SNicholas Piggin	bne-	.Lrestore_nvgprs_\srr
42613799748SNicholas Piggin.Lrestore_nvgprs_\srr\()_cont:
42775c5d6b1SRohan McLure#endif
42813799748SNicholas Piggin	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
4299b69d48cSNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
43013799748SNicholas Piggin.Linterrupt_return_\srr\()_user_rst_start:
43113799748SNicholas Piggin	lbz	r11,PACAIRQHAPPENED(r13)
43213799748SNicholas Piggin	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
43313799748SNicholas Piggin	bne-	interrupt_return_\srr\()_user_restart
4349b69d48cSNicholas Piggin#endif
43513799748SNicholas Piggin	li	r11,IRQS_ENABLED
43613799748SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
43713799748SNicholas Piggin	li	r11,0
43813799748SNicholas Piggin	stb	r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
439e754f4d1SNicholas Piggin
440e754f4d1SNicholas Piggin.Lfast_user_interrupt_return_\srr\():
44175c5d6b1SRohan McLure	SANITIZE_RESTORE_NVGPRS()
442e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
443e754f4d1SNicholas Piggin	.ifc \srr,srr
444e754f4d1SNicholas Piggin	lbz	r4,PACASRR_VALID(r13)
445e754f4d1SNicholas Piggin	.else
446e754f4d1SNicholas Piggin	lbz	r4,PACAHSRR_VALID(r13)
447e754f4d1SNicholas Piggin	.endif
448e754f4d1SNicholas Piggin	cmpdi	r4,0
449e754f4d1SNicholas Piggin	li	r4,0
450e754f4d1SNicholas Piggin	bne	1f
451e754f4d1SNicholas Piggin#endif
452e754f4d1SNicholas Piggin	ld	r11,_NIP(r1)
453e754f4d1SNicholas Piggin	ld	r12,_MSR(r1)
454e754f4d1SNicholas Piggin	.ifc \srr,srr
455e754f4d1SNicholas Piggin	mtspr	SPRN_SRR0,r11
456e754f4d1SNicholas Piggin	mtspr	SPRN_SRR1,r12
457e754f4d1SNicholas Piggin1:
458e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
459e754f4d1SNicholas Piggin	stb	r4,PACASRR_VALID(r13)
460e754f4d1SNicholas Piggin#endif
461e754f4d1SNicholas Piggin	.else
462e754f4d1SNicholas Piggin	mtspr	SPRN_HSRR0,r11
463e754f4d1SNicholas Piggin	mtspr	SPRN_HSRR1,r12
464e754f4d1SNicholas Piggin1:
465e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
466e754f4d1SNicholas Piggin	stb	r4,PACAHSRR_VALID(r13)
467e754f4d1SNicholas Piggin#endif
468e754f4d1SNicholas Piggin	.endif
469e754f4d1SNicholas Piggin	DEBUG_SRR_VALID \srr
470e754f4d1SNicholas Piggin
47113799748SNicholas Piggin#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
47213799748SNicholas Piggin	lbz	r4,PACAIRQSOFTMASK(r13)
47313799748SNicholas Piggin	tdnei	r4,IRQS_ENABLED
47413799748SNicholas Piggin#endif
47513799748SNicholas Piggin
47613799748SNicholas PigginBEGIN_FTR_SECTION
47713799748SNicholas Piggin	ld	r10,_PPR(r1)
47813799748SNicholas Piggin	mtspr	SPRN_PPR,r10
47913799748SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
48013799748SNicholas Piggin
481e754f4d1SNicholas PigginBEGIN_FTR_SECTION
482e754f4d1SNicholas Piggin	stdcx.	r0,0,r1		/* to clear the reservation */
483e754f4d1SNicholas PigginFTR_SECTION_ELSE
484e754f4d1SNicholas Piggin	ldarx	r0,0,r1
485e754f4d1SNicholas PigginALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
486e754f4d1SNicholas Piggin
487e754f4d1SNicholas Piggin	ld	r3,_CCR(r1)
488e754f4d1SNicholas Piggin	ld	r4,_LINK(r1)
489e754f4d1SNicholas Piggin	ld	r5,_CTR(r1)
490e754f4d1SNicholas Piggin	ld	r6,_XER(r1)
491e754f4d1SNicholas Piggin	li	r0,0
492e754f4d1SNicholas Piggin
493aebd1fb4SNicholas Piggin	REST_GPRS(7, 13, r1)
494e754f4d1SNicholas Piggin
495e754f4d1SNicholas Piggin	mtcr	r3
496e754f4d1SNicholas Piggin	mtlr	r4
497e754f4d1SNicholas Piggin	mtctr	r5
498e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r6
499e754f4d1SNicholas Piggin
500aebd1fb4SNicholas Piggin	REST_GPRS(2, 6, r1)
501e754f4d1SNicholas Piggin	REST_GPR(0, r1)
502e754f4d1SNicholas Piggin	REST_GPR(1, r1)
503e754f4d1SNicholas Piggin	.ifc \srr,srr
504e754f4d1SNicholas Piggin	RFI_TO_USER
505e754f4d1SNicholas Piggin	.else
506e754f4d1SNicholas Piggin	HRFI_TO_USER
507e754f4d1SNicholas Piggin	.endif
508e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
50913799748SNicholas Piggin.Linterrupt_return_\srr\()_user_rst_end:
510e754f4d1SNicholas Piggin
51175c5d6b1SRohan McLure#ifndef CONFIG_INTERRUPT_SANITIZE_REGISTERS
512e754f4d1SNicholas Piggin.Lrestore_nvgprs_\srr\():
513e754f4d1SNicholas Piggin	REST_NVGPRS(r1)
51413799748SNicholas Piggin	b	.Lrestore_nvgprs_\srr\()_cont
51575c5d6b1SRohan McLure#endif
51613799748SNicholas Piggin
5179b69d48cSNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
51813799748SNicholas Piggininterrupt_return_\srr\()_user_restart:
51998798f33SNicholas Piggin_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_user_restart)
52013799748SNicholas Piggin	GET_PACA(r13)
52113799748SNicholas Piggin	ld	r1,PACA_EXIT_SAVE_R1(r13)
5228e93fb33SNicholas Piggin	LOAD_PACA_TOC()
523c03be0a3SNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
52413799748SNicholas Piggin	li	r11,IRQS_ALL_DISABLED
52513799748SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
5264e991e3cSNicholas Piggin	bl	CFUNC(interrupt_exit_user_restart)
52713799748SNicholas Piggin	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
52813799748SNicholas Piggin	b	.Linterrupt_return_\srr\()_user_rst_start
529325678fdSNicholas Piggin1:
53013799748SNicholas Piggin
531325678fdSNicholas PigginSOFT_MASK_TABLE(.Linterrupt_return_\srr\()_user_rst_start, 1b)
53213799748SNicholas PigginRESTART_TABLE(.Linterrupt_return_\srr\()_user_rst_start, .Linterrupt_return_\srr\()_user_rst_end, interrupt_return_\srr\()_user_restart)
5339b69d48cSNicholas Piggin#endif
534e754f4d1SNicholas Piggin
535e754f4d1SNicholas Piggin	.balign IFETCH_ALIGN_BYTES
536c59458b0SNicholas Piggininterrupt_return_\srr\()_kernel:
537c59458b0SNicholas Piggin_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
538c03be0a3SNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
5394e991e3cSNicholas Piggin	bl	CFUNC(interrupt_exit_kernel_prepare)
540e754f4d1SNicholas Piggin
54113799748SNicholas Piggin	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
54213799748SNicholas Piggin.Linterrupt_return_\srr\()_kernel_rst_start:
54313799748SNicholas Piggin	ld	r11,SOFTE(r1)
54413799748SNicholas Piggin	cmpwi	r11,IRQS_ENABLED
54513799748SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
546e485f6c7SNicholas Piggin	beq	.Linterrupt_return_\srr\()_soft_enabled
547e485f6c7SNicholas Piggin
548e485f6c7SNicholas Piggin	/*
549e485f6c7SNicholas Piggin	 * Returning to soft-disabled context.
550e485f6c7SNicholas Piggin	 * Check if a MUST_HARD_MASK interrupt has become pending, in which
551e485f6c7SNicholas Piggin	 * case we need to disable MSR[EE] in the return context.
55265722736SNicholas Piggin	 *
55365722736SNicholas Piggin	 * The MSR[EE] check catches among other things the short incoherency
55465722736SNicholas Piggin	 * in hard_irq_disable() between clearing MSR[EE] and setting
55565722736SNicholas Piggin	 * PACA_IRQ_HARD_DIS.
556e485f6c7SNicholas Piggin	 */
557e485f6c7SNicholas Piggin	ld	r12,_MSR(r1)
558e485f6c7SNicholas Piggin	andi.	r10,r12,MSR_EE
559e485f6c7SNicholas Piggin	beq	.Lfast_kernel_interrupt_return_\srr\() // EE already disabled
560e485f6c7SNicholas Piggin	lbz	r11,PACAIRQHAPPENED(r13)
561e485f6c7SNicholas Piggin	andi.	r10,r11,PACA_IRQ_MUST_HARD_MASK
56265722736SNicholas Piggin	bne	1f // HARD_MASK is pending
56365722736SNicholas Piggin	// No HARD_MASK pending, clear possible HARD_DIS set by interrupt
56465722736SNicholas Piggin	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
56565722736SNicholas Piggin	stb	r11,PACAIRQHAPPENED(r13)
56665722736SNicholas Piggin	b	.Lfast_kernel_interrupt_return_\srr\()
567e485f6c7SNicholas Piggin
56865722736SNicholas Piggin
56965722736SNicholas Piggin1:	/* Must clear MSR_EE from _MSR */
570e485f6c7SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
571e485f6c7SNicholas Piggin	li	r10,0
572e485f6c7SNicholas Piggin	/* Clear valid before changing _MSR */
573e485f6c7SNicholas Piggin	.ifc \srr,srr
574e485f6c7SNicholas Piggin	stb	r10,PACASRR_VALID(r13)
575e485f6c7SNicholas Piggin	.else
576e485f6c7SNicholas Piggin	stb	r10,PACAHSRR_VALID(r13)
577e485f6c7SNicholas Piggin	.endif
578e485f6c7SNicholas Piggin#endif
579e485f6c7SNicholas Piggin	xori	r12,r12,MSR_EE
580e485f6c7SNicholas Piggin	std	r12,_MSR(r1)
581e485f6c7SNicholas Piggin	b	.Lfast_kernel_interrupt_return_\srr\()
582e485f6c7SNicholas Piggin
583e485f6c7SNicholas Piggin.Linterrupt_return_\srr\()_soft_enabled:
584a4cb3651SNicholas Piggin	/*
585a4cb3651SNicholas Piggin	 * In the soft-enabled case, need to double-check that we have no
586a4cb3651SNicholas Piggin	 * pending interrupts that might have come in before we reached the
587a4cb3651SNicholas Piggin	 * restart section of code, and restart the exit so those can be
588a4cb3651SNicholas Piggin	 * handled.
589a4cb3651SNicholas Piggin	 *
590a4cb3651SNicholas Piggin	 * If there are none, it is be possible that the interrupt still
591a4cb3651SNicholas Piggin	 * has PACA_IRQ_HARD_DIS set, which needs to be cleared for the
592a4cb3651SNicholas Piggin	 * interrupted context. This clear will not clobber a new pending
593a4cb3651SNicholas Piggin	 * interrupt coming in, because we're in the restart section, so
594a4cb3651SNicholas Piggin	 * such would return to the restart location.
595a4cb3651SNicholas Piggin	 */
5969b69d48cSNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
59713799748SNicholas Piggin	lbz	r11,PACAIRQHAPPENED(r13)
59813799748SNicholas Piggin	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
59913799748SNicholas Piggin	bne-	interrupt_return_\srr\()_kernel_restart
6009b69d48cSNicholas Piggin#endif
601e485f6c7SNicholas Piggin	li	r11,0
602e485f6c7SNicholas Piggin	stb	r11,PACAIRQHAPPENED(r13) // clear the possible HARD_DIS
60313799748SNicholas Piggin
604e754f4d1SNicholas Piggin.Lfast_kernel_interrupt_return_\srr\():
60575c5d6b1SRohan McLure	SANITIZE_RESTORE_NVGPRS()
606e754f4d1SNicholas Piggin	cmpdi	cr1,r3,0
607e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
608e754f4d1SNicholas Piggin	.ifc \srr,srr
609e754f4d1SNicholas Piggin	lbz	r4,PACASRR_VALID(r13)
610e754f4d1SNicholas Piggin	.else
611e754f4d1SNicholas Piggin	lbz	r4,PACAHSRR_VALID(r13)
612e754f4d1SNicholas Piggin	.endif
613e754f4d1SNicholas Piggin	cmpdi	r4,0
614e754f4d1SNicholas Piggin	li	r4,0
615e754f4d1SNicholas Piggin	bne	1f
616e754f4d1SNicholas Piggin#endif
617e754f4d1SNicholas Piggin	ld	r11,_NIP(r1)
618e754f4d1SNicholas Piggin	ld	r12,_MSR(r1)
619e754f4d1SNicholas Piggin	.ifc \srr,srr
620e754f4d1SNicholas Piggin	mtspr	SPRN_SRR0,r11
621e754f4d1SNicholas Piggin	mtspr	SPRN_SRR1,r12
622e754f4d1SNicholas Piggin1:
623e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
624e754f4d1SNicholas Piggin	stb	r4,PACASRR_VALID(r13)
625e754f4d1SNicholas Piggin#endif
626e754f4d1SNicholas Piggin	.else
627e754f4d1SNicholas Piggin	mtspr	SPRN_HSRR0,r11
628e754f4d1SNicholas Piggin	mtspr	SPRN_HSRR1,r12
629e754f4d1SNicholas Piggin1:
630e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
631e754f4d1SNicholas Piggin	stb	r4,PACAHSRR_VALID(r13)
632e754f4d1SNicholas Piggin#endif
633e754f4d1SNicholas Piggin	.endif
634e754f4d1SNicholas Piggin	DEBUG_SRR_VALID \srr
635e754f4d1SNicholas Piggin
636e754f4d1SNicholas PigginBEGIN_FTR_SECTION
637e754f4d1SNicholas Piggin	stdcx.	r0,0,r1		/* to clear the reservation */
638e754f4d1SNicholas PigginFTR_SECTION_ELSE
639e754f4d1SNicholas Piggin	ldarx	r0,0,r1
640e754f4d1SNicholas PigginALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
641e754f4d1SNicholas Piggin
642e754f4d1SNicholas Piggin	ld	r3,_LINK(r1)
643e754f4d1SNicholas Piggin	ld	r4,_CTR(r1)
644e754f4d1SNicholas Piggin	ld	r5,_XER(r1)
645e754f4d1SNicholas Piggin	ld	r6,_CCR(r1)
646e754f4d1SNicholas Piggin	li	r0,0
647e754f4d1SNicholas Piggin
648aebd1fb4SNicholas Piggin	REST_GPRS(7, 12, r1)
649e754f4d1SNicholas Piggin
650e754f4d1SNicholas Piggin	mtlr	r3
651e754f4d1SNicholas Piggin	mtctr	r4
652e754f4d1SNicholas Piggin	mtspr	SPRN_XER,r5
653e754f4d1SNicholas Piggin
654e754f4d1SNicholas Piggin	/*
65517773afdSNicholas Piggin	 * Leaving a stale STACK_FRAME_REGS_MARKER on the stack can confuse
656e754f4d1SNicholas Piggin	 * the reliable stack unwinder later on. Clear it.
657e754f4d1SNicholas Piggin	 */
658d2e8ff9fSNicholas Piggin	std	r0,STACK_INT_FRAME_MARKER(r1)
659e754f4d1SNicholas Piggin
660aebd1fb4SNicholas Piggin	REST_GPRS(2, 5, r1)
661e754f4d1SNicholas Piggin
662e754f4d1SNicholas Piggin	bne-	cr1,1f /* emulate stack store */
663e754f4d1SNicholas Piggin	mtcr	r6
664e754f4d1SNicholas Piggin	REST_GPR(6, r1)
665e754f4d1SNicholas Piggin	REST_GPR(0, r1)
666e754f4d1SNicholas Piggin	REST_GPR(1, r1)
667e754f4d1SNicholas Piggin	.ifc \srr,srr
668e754f4d1SNicholas Piggin	RFI_TO_KERNEL
669e754f4d1SNicholas Piggin	.else
670e754f4d1SNicholas Piggin	HRFI_TO_KERNEL
671e754f4d1SNicholas Piggin	.endif
672e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
673e754f4d1SNicholas Piggin
674e754f4d1SNicholas Piggin1:	/*
675e754f4d1SNicholas Piggin	 * Emulate stack store with update. New r1 value was already calculated
676e754f4d1SNicholas Piggin	 * and updated in our interrupt regs by emulate_loadstore, but we can't
677e754f4d1SNicholas Piggin	 * store the previous value of r1 to the stack before re-loading our
678e754f4d1SNicholas Piggin	 * registers from it, otherwise they could be clobbered.  Use
679e754f4d1SNicholas Piggin	 * PACA_EXGEN as temporary storage to hold the store data, as
680e754f4d1SNicholas Piggin	 * interrupts are disabled here so it won't be clobbered.
681e754f4d1SNicholas Piggin	 */
682e754f4d1SNicholas Piggin	mtcr	r6
683e754f4d1SNicholas Piggin	std	r9,PACA_EXGEN+0(r13)
684e754f4d1SNicholas Piggin	addi	r9,r1,INT_FRAME_SIZE /* get original r1 */
685e754f4d1SNicholas Piggin	REST_GPR(6, r1)
686e754f4d1SNicholas Piggin	REST_GPR(0, r1)
687e754f4d1SNicholas Piggin	REST_GPR(1, r1)
688e754f4d1SNicholas Piggin	std	r9,0(r1) /* perform store component of stdu */
689e754f4d1SNicholas Piggin	ld	r9,PACA_EXGEN+0(r13)
690e754f4d1SNicholas Piggin
691e754f4d1SNicholas Piggin	.ifc \srr,srr
692e754f4d1SNicholas Piggin	RFI_TO_KERNEL
693e754f4d1SNicholas Piggin	.else
694e754f4d1SNicholas Piggin	HRFI_TO_KERNEL
695e754f4d1SNicholas Piggin	.endif
696e754f4d1SNicholas Piggin	b	.	/* prevent speculative execution */
69713799748SNicholas Piggin.Linterrupt_return_\srr\()_kernel_rst_end:
69813799748SNicholas Piggin
6999b69d48cSNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
70013799748SNicholas Piggininterrupt_return_\srr\()_kernel_restart:
70198798f33SNicholas Piggin_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel_restart)
70213799748SNicholas Piggin	GET_PACA(r13)
70313799748SNicholas Piggin	ld	r1,PACA_EXIT_SAVE_R1(r13)
7048e93fb33SNicholas Piggin	LOAD_PACA_TOC()
705c03be0a3SNicholas Piggin	addi	r3,r1,STACK_INT_FRAME_REGS
70613799748SNicholas Piggin	li	r11,IRQS_ALL_DISABLED
70713799748SNicholas Piggin	stb	r11,PACAIRQSOFTMASK(r13)
7084e991e3cSNicholas Piggin	bl	CFUNC(interrupt_exit_kernel_restart)
70913799748SNicholas Piggin	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
71013799748SNicholas Piggin	b	.Linterrupt_return_\srr\()_kernel_rst_start
711325678fdSNicholas Piggin1:
71213799748SNicholas Piggin
713325678fdSNicholas PigginSOFT_MASK_TABLE(.Linterrupt_return_\srr\()_kernel_rst_start, 1b)
71413799748SNicholas PigginRESTART_TABLE(.Linterrupt_return_\srr\()_kernel_rst_start, .Linterrupt_return_\srr\()_kernel_rst_end, interrupt_return_\srr\()_kernel_restart)
7159b69d48cSNicholas Piggin#endif
71613799748SNicholas Piggin
717e754f4d1SNicholas Piggin.endm
718e754f4d1SNicholas Piggin
719e754f4d1SNicholas Piggininterrupt_return_macro srr
720e754f4d1SNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
721e754f4d1SNicholas Piggininterrupt_return_macro hsrr
7229d1988caSNicholas Piggin
7239d1988caSNicholas Piggin	.globl __end_soft_masked
7249d1988caSNicholas Piggin__end_soft_masked:
725d72c4a36SDaniel AxtensDEFINE_FIXED_SYMBOL(__end_soft_masked, text)
7269b69d48cSNicholas Piggin#endif /* CONFIG_PPC_BOOK3S */
72791fc46ecSNicholas Piggin
72891fc46ecSNicholas Piggin#ifdef CONFIG_PPC_BOOK3S
72991fc46ecSNicholas Piggin_GLOBAL(ret_from_fork_scv)
7304e991e3cSNicholas Piggin	bl	CFUNC(schedule_tail)
7315088a624SNicholas Piggin	HANDLER_RESTORE_NVGPRS()
73291fc46ecSNicholas Piggin	li	r3,0	/* fork() return value */
73391fc46ecSNicholas Piggin	b	.Lsyscall_vectored_common_exit
73491fc46ecSNicholas Piggin#endif
73591fc46ecSNicholas Piggin
73691fc46ecSNicholas Piggin_GLOBAL(ret_from_fork)
7374e991e3cSNicholas Piggin	bl	CFUNC(schedule_tail)
7385088a624SNicholas Piggin	HANDLER_RESTORE_NVGPRS()
73991fc46ecSNicholas Piggin	li	r3,0	/* fork() return value */
74091fc46ecSNicholas Piggin	b	.Lsyscall_exit
74191fc46ecSNicholas Piggin
742b504b6aaSNicholas Piggin_GLOBAL(ret_from_kernel_user_thread)
7434e991e3cSNicholas Piggin	bl	CFUNC(schedule_tail)
74491fc46ecSNicholas Piggin	mtctr	r14
74591fc46ecSNicholas Piggin	mr	r3,r15
7467d40aff8SChristophe Leroy#ifdef CONFIG_PPC64_ELF_ABI_V2
74791fc46ecSNicholas Piggin	mr	r12,r14
74891fc46ecSNicholas Piggin#endif
74991fc46ecSNicholas Piggin	bctrl
75091fc46ecSNicholas Piggin	li	r3,0
751d195ce46SNicholas Piggin	/*
752d195ce46SNicholas Piggin	 * It does not matter whether this returns via the scv or sc path
753d195ce46SNicholas Piggin	 * because it returns as execve() and therefore has no calling ABI
754d195ce46SNicholas Piggin	 * (i.e., it sets registers according to the exec()ed entry point).
755d195ce46SNicholas Piggin	 */
75691fc46ecSNicholas Piggin	b	.Lsyscall_exit
757b504b6aaSNicholas Piggin
758b504b6aaSNicholas Piggin_GLOBAL(start_kernel_thread)
7590c993300SNicholas Piggin	bl	CFUNC(schedule_tail)
760b504b6aaSNicholas Piggin	mtctr	r14
761b504b6aaSNicholas Piggin	mr	r3,r15
762b504b6aaSNicholas Piggin#ifdef CONFIG_PPC64_ELF_ABI_V2
763b504b6aaSNicholas Piggin	mr	r12,r14
764b504b6aaSNicholas Piggin#endif
765b504b6aaSNicholas Piggin	bctrl
766b504b6aaSNicholas Piggin	/*
767b504b6aaSNicholas Piggin	 * This must not return. We actually want to BUG here, not WARN,
768b504b6aaSNicholas Piggin	 * because BUG will exit the process which is what the kernel thread
769b504b6aaSNicholas Piggin	 * should have done, which may give some hope of continuing.
770b504b6aaSNicholas Piggin	 */
771b504b6aaSNicholas Piggin100:	trap
772b504b6aaSNicholas Piggin	EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,0
773