162306a36Sopenharmony_ci#include <asm/asm-offsets.h>
262306a36Sopenharmony_ci#include <asm/bug.h>
362306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
462306a36Sopenharmony_ci#include <asm/exception-64s.h>
562306a36Sopenharmony_ci#else
662306a36Sopenharmony_ci#include <asm/exception-64e.h>
762306a36Sopenharmony_ci#endif
862306a36Sopenharmony_ci#include <asm/feature-fixups.h>
962306a36Sopenharmony_ci#include <asm/head-64.h>
1062306a36Sopenharmony_ci#include <asm/hw_irq.h>
1162306a36Sopenharmony_ci#include <asm/kup.h>
1262306a36Sopenharmony_ci#include <asm/mmu.h>
1362306a36Sopenharmony_ci#include <asm/ppc_asm.h>
1462306a36Sopenharmony_ci#include <asm/ptrace.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	.align 7
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci.macro DEBUG_SRR_VALID srr
1962306a36Sopenharmony_ci#ifdef CONFIG_PPC_RFI_SRR_DEBUG
2062306a36Sopenharmony_ci	.ifc \srr,srr
2162306a36Sopenharmony_ci	mfspr	r11,SPRN_SRR0
2262306a36Sopenharmony_ci	ld	r12,_NIP(r1)
2362306a36Sopenharmony_ci	clrrdi  r11,r11,2
2462306a36Sopenharmony_ci	clrrdi  r12,r12,2
2562306a36Sopenharmony_ci100:	tdne	r11,r12
2662306a36Sopenharmony_ci	EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
2762306a36Sopenharmony_ci	mfspr	r11,SPRN_SRR1
2862306a36Sopenharmony_ci	ld	r12,_MSR(r1)
2962306a36Sopenharmony_ci100:	tdne	r11,r12
3062306a36Sopenharmony_ci	EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
3162306a36Sopenharmony_ci	.else
3262306a36Sopenharmony_ci	mfspr	r11,SPRN_HSRR0
3362306a36Sopenharmony_ci	ld	r12,_NIP(r1)
3462306a36Sopenharmony_ci	clrrdi  r11,r11,2
3562306a36Sopenharmony_ci	clrrdi  r12,r12,2
3662306a36Sopenharmony_ci100:	tdne	r11,r12
3762306a36Sopenharmony_ci	EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
3862306a36Sopenharmony_ci	mfspr	r11,SPRN_HSRR1
3962306a36Sopenharmony_ci	ld	r12,_MSR(r1)
4062306a36Sopenharmony_ci100:	tdne	r11,r12
4162306a36Sopenharmony_ci	EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE)
4262306a36Sopenharmony_ci	.endif
4362306a36Sopenharmony_ci#endif
4462306a36Sopenharmony_ci.endm
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
4762306a36Sopenharmony_ci.macro system_call_vectored name trapnr
4862306a36Sopenharmony_ci	.globl system_call_vectored_\name
4962306a36Sopenharmony_cisystem_call_vectored_\name:
5062306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(system_call_vectored_\name)
5162306a36Sopenharmony_ci	SCV_INTERRUPT_TO_KERNEL
5262306a36Sopenharmony_ci	mr	r10,r1
5362306a36Sopenharmony_ci	ld	r1,PACAKSAVE(r13)
5462306a36Sopenharmony_ci	std	r10,0(r1)
5562306a36Sopenharmony_ci	std	r11,_LINK(r1)
5662306a36Sopenharmony_ci	std	r11,_NIP(r1)	/* Saved LR is also the next instruction */
5762306a36Sopenharmony_ci	std	r12,_MSR(r1)
5862306a36Sopenharmony_ci	std	r0,GPR0(r1)
5962306a36Sopenharmony_ci	std	r10,GPR1(r1)
6062306a36Sopenharmony_ci	std	r2,GPR2(r1)
6162306a36Sopenharmony_ci	LOAD_PACA_TOC()
6262306a36Sopenharmony_ci	mfcr	r12
6362306a36Sopenharmony_ci	li	r11,0
6462306a36Sopenharmony_ci	/* Save syscall parameters in r3-r8 */
6562306a36Sopenharmony_ci	SAVE_GPRS(3, 8, r1)
6662306a36Sopenharmony_ci	/* Zero r9-r12, this should only be required when restoring all GPRs */
6762306a36Sopenharmony_ci	std	r11,GPR9(r1)
6862306a36Sopenharmony_ci	std	r11,GPR10(r1)
6962306a36Sopenharmony_ci	std	r11,GPR11(r1)
7062306a36Sopenharmony_ci	std	r11,GPR12(r1)
7162306a36Sopenharmony_ci	std	r9,GPR13(r1)
7262306a36Sopenharmony_ci	SAVE_NVGPRS(r1)
7362306a36Sopenharmony_ci	std	r11,_XER(r1)
7462306a36Sopenharmony_ci	std	r11,_CTR(r1)
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	li	r11,\trapnr
7762306a36Sopenharmony_ci	std	r11,_TRAP(r1)
7862306a36Sopenharmony_ci	std	r12,_CCR(r1)
7962306a36Sopenharmony_ci	std	r3,ORIG_GPR3(r1)
8062306a36Sopenharmony_ci	LOAD_REG_IMMEDIATE(r11, STACK_FRAME_REGS_MARKER)
8162306a36Sopenharmony_ci	std	r11,STACK_INT_FRAME_MARKER(r1)		/* "regs" marker */
8262306a36Sopenharmony_ci	/* Calling convention has r3 = regs, r4 = orig r0 */
8362306a36Sopenharmony_ci	addi	r3,r1,STACK_INT_FRAME_REGS
8462306a36Sopenharmony_ci	mr	r4,r0
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ciBEGIN_FTR_SECTION
8762306a36Sopenharmony_ci	HMT_MEDIUM
8862306a36Sopenharmony_ciEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	/*
9162306a36Sopenharmony_ci	 * scv enters with MSR[EE]=1 and is immediately considered soft-masked.
9262306a36Sopenharmony_ci	 * The entry vector already sets PACAIRQSOFTMASK to IRQS_ALL_DISABLED,
9362306a36Sopenharmony_ci	 * and interrupts may be masked and pending already.
9462306a36Sopenharmony_ci	 * system_call_exception() will call trace_hardirqs_off() which means
9562306a36Sopenharmony_ci	 * interrupts could already have been blocked before trace_hardirqs_off,
9662306a36Sopenharmony_ci	 * but this is the best we can do.
9762306a36Sopenharmony_ci	 */
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	/*
10062306a36Sopenharmony_ci	 * Zero user registers to prevent influencing speculative execution
10162306a36Sopenharmony_ci	 * state of kernel code.
10262306a36Sopenharmony_ci	 */
10362306a36Sopenharmony_ci	SANITIZE_SYSCALL_GPRS()
10462306a36Sopenharmony_ci	bl	CFUNC(system_call_exception)
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci.Lsyscall_vectored_\name\()_exit:
10762306a36Sopenharmony_ci	addi	r4,r1,STACK_INT_FRAME_REGS
10862306a36Sopenharmony_ci	li	r5,1 /* scv */
10962306a36Sopenharmony_ci	bl	CFUNC(syscall_exit_prepare)
11062306a36Sopenharmony_ci	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
11162306a36Sopenharmony_ci.Lsyscall_vectored_\name\()_rst_start:
11262306a36Sopenharmony_ci	lbz	r11,PACAIRQHAPPENED(r13)
11362306a36Sopenharmony_ci	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
11462306a36Sopenharmony_ci	bne-	syscall_vectored_\name\()_restart
11562306a36Sopenharmony_ci	li	r11,IRQS_ENABLED
11662306a36Sopenharmony_ci	stb	r11,PACAIRQSOFTMASK(r13)
11762306a36Sopenharmony_ci	li	r11,0
11862306a36Sopenharmony_ci	stb	r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	ld	r2,_CCR(r1)
12162306a36Sopenharmony_ci	ld	r4,_NIP(r1)
12262306a36Sopenharmony_ci	ld	r5,_MSR(r1)
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ciBEGIN_FTR_SECTION
12562306a36Sopenharmony_ci	stdcx.	r0,0,r1			/* to clear the reservation */
12662306a36Sopenharmony_ciEND_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ciBEGIN_FTR_SECTION
12962306a36Sopenharmony_ci	HMT_MEDIUM_LOW
13062306a36Sopenharmony_ciEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	SANITIZE_RESTORE_NVGPRS()
13362306a36Sopenharmony_ci	cmpdi	r3,0
13462306a36Sopenharmony_ci	bne	.Lsyscall_vectored_\name\()_restore_regs
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	/* rfscv returns with LR->NIA and CTR->MSR */
13762306a36Sopenharmony_ci	mtlr	r4
13862306a36Sopenharmony_ci	mtctr	r5
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	/* Could zero these as per ABI, but we may consider a stricter ABI
14162306a36Sopenharmony_ci	 * which preserves these if libc implementations can benefit, so
14262306a36Sopenharmony_ci	 * restore them for now until further measurement is done. */
14362306a36Sopenharmony_ci	REST_GPR(0, r1)
14462306a36Sopenharmony_ci	REST_GPRS(4, 8, r1)
14562306a36Sopenharmony_ci	/* Zero volatile regs that may contain sensitive kernel data */
14662306a36Sopenharmony_ci	ZEROIZE_GPRS(9, 12)
14762306a36Sopenharmony_ci	mtspr	SPRN_XER,r0
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	/*
15062306a36Sopenharmony_ci	 * We don't need to restore AMR on the way back to userspace for KUAP.
15162306a36Sopenharmony_ci	 * The value of AMR only matters while we're in the kernel.
15262306a36Sopenharmony_ci	 */
15362306a36Sopenharmony_ci	mtcr	r2
15462306a36Sopenharmony_ci	REST_GPRS(2, 3, r1)
15562306a36Sopenharmony_ci	REST_GPR(13, r1)
15662306a36Sopenharmony_ci	REST_GPR(1, r1)
15762306a36Sopenharmony_ci	RFSCV_TO_USER
15862306a36Sopenharmony_ci	b	.	/* prevent speculative execution */
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci.Lsyscall_vectored_\name\()_restore_regs:
16162306a36Sopenharmony_ci	mtspr	SPRN_SRR0,r4
16262306a36Sopenharmony_ci	mtspr	SPRN_SRR1,r5
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	ld	r3,_CTR(r1)
16562306a36Sopenharmony_ci	ld	r4,_LINK(r1)
16662306a36Sopenharmony_ci	ld	r5,_XER(r1)
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	HANDLER_RESTORE_NVGPRS()
16962306a36Sopenharmony_ci	REST_GPR(0, r1)
17062306a36Sopenharmony_ci	mtcr	r2
17162306a36Sopenharmony_ci	mtctr	r3
17262306a36Sopenharmony_ci	mtlr	r4
17362306a36Sopenharmony_ci	mtspr	SPRN_XER,r5
17462306a36Sopenharmony_ci	REST_GPRS(2, 13, r1)
17562306a36Sopenharmony_ci	REST_GPR(1, r1)
17662306a36Sopenharmony_ci	RFI_TO_USER
17762306a36Sopenharmony_ci.Lsyscall_vectored_\name\()_rst_end:
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_cisyscall_vectored_\name\()_restart:
18062306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(syscall_vectored_\name\()_restart)
18162306a36Sopenharmony_ci	GET_PACA(r13)
18262306a36Sopenharmony_ci	ld	r1,PACA_EXIT_SAVE_R1(r13)
18362306a36Sopenharmony_ci	LOAD_PACA_TOC()
18462306a36Sopenharmony_ci	ld	r3,RESULT(r1)
18562306a36Sopenharmony_ci	addi	r4,r1,STACK_INT_FRAME_REGS
18662306a36Sopenharmony_ci	li	r11,IRQS_ALL_DISABLED
18762306a36Sopenharmony_ci	stb	r11,PACAIRQSOFTMASK(r13)
18862306a36Sopenharmony_ci	bl	CFUNC(syscall_exit_restart)
18962306a36Sopenharmony_ci	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
19062306a36Sopenharmony_ci	b	.Lsyscall_vectored_\name\()_rst_start
19162306a36Sopenharmony_ci1:
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ciSOFT_MASK_TABLE(.Lsyscall_vectored_\name\()_rst_start, 1b)
19462306a36Sopenharmony_ciRESTART_TABLE(.Lsyscall_vectored_\name\()_rst_start, .Lsyscall_vectored_\name\()_rst_end, syscall_vectored_\name\()_restart)
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci.endm
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cisystem_call_vectored common 0x3000
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci/*
20162306a36Sopenharmony_ci * We instantiate another entry copy for the SIGILL variant, with TRAP=0x7ff0
20262306a36Sopenharmony_ci * which is tested by system_call_exception when r0 is -1 (as set by vector
20362306a36Sopenharmony_ci * entry code).
20462306a36Sopenharmony_ci */
20562306a36Sopenharmony_cisystem_call_vectored sigill 0x7ff0
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci#endif /* CONFIG_PPC_BOOK3S */
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	.balign IFETCH_ALIGN_BYTES
21062306a36Sopenharmony_ci	.globl system_call_common_real
21162306a36Sopenharmony_cisystem_call_common_real:
21262306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(system_call_common_real)
21362306a36Sopenharmony_ci	ld	r10,PACAKMSR(r13)	/* get MSR value for kernel */
21462306a36Sopenharmony_ci	mtmsrd	r10
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	.balign IFETCH_ALIGN_BYTES
21762306a36Sopenharmony_ci	.globl system_call_common
21862306a36Sopenharmony_cisystem_call_common:
21962306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(system_call_common)
22062306a36Sopenharmony_ci	mr	r10,r1
22162306a36Sopenharmony_ci	ld	r1,PACAKSAVE(r13)
22262306a36Sopenharmony_ci	std	r10,0(r1)
22362306a36Sopenharmony_ci	std	r11,_NIP(r1)
22462306a36Sopenharmony_ci	std	r12,_MSR(r1)
22562306a36Sopenharmony_ci	std	r0,GPR0(r1)
22662306a36Sopenharmony_ci	std	r10,GPR1(r1)
22762306a36Sopenharmony_ci	std	r2,GPR2(r1)
22862306a36Sopenharmony_ci#ifdef CONFIG_PPC_E500
22962306a36Sopenharmony_ciSTART_BTB_FLUSH_SECTION
23062306a36Sopenharmony_ci	BTB_FLUSH(r10)
23162306a36Sopenharmony_ciEND_BTB_FLUSH_SECTION
23262306a36Sopenharmony_ci#endif
23362306a36Sopenharmony_ci	LOAD_PACA_TOC()
23462306a36Sopenharmony_ci	mfcr	r12
23562306a36Sopenharmony_ci	li	r11,0
23662306a36Sopenharmony_ci	/* Save syscall parameters in r3-r8 */
23762306a36Sopenharmony_ci	SAVE_GPRS(3, 8, r1)
23862306a36Sopenharmony_ci	/* Zero r9-r12, this should only be required when restoring all GPRs */
23962306a36Sopenharmony_ci	std	r11,GPR9(r1)
24062306a36Sopenharmony_ci	std	r11,GPR10(r1)
24162306a36Sopenharmony_ci	std	r11,GPR11(r1)
24262306a36Sopenharmony_ci	std	r11,GPR12(r1)
24362306a36Sopenharmony_ci	std	r9,GPR13(r1)
24462306a36Sopenharmony_ci	SAVE_NVGPRS(r1)
24562306a36Sopenharmony_ci	std	r11,_XER(r1)
24662306a36Sopenharmony_ci	std	r11,_CTR(r1)
24762306a36Sopenharmony_ci	mflr	r10
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	/*
25062306a36Sopenharmony_ci	 * This clears CR0.SO (bit 28), which is the error indication on
25162306a36Sopenharmony_ci	 * return from this system call.
25262306a36Sopenharmony_ci	 */
25362306a36Sopenharmony_ci	rldimi	r12,r11,28,(63-28)
25462306a36Sopenharmony_ci	li	r11,0xc00
25562306a36Sopenharmony_ci	std	r10,_LINK(r1)
25662306a36Sopenharmony_ci	std	r11,_TRAP(r1)
25762306a36Sopenharmony_ci	std	r12,_CCR(r1)
25862306a36Sopenharmony_ci	std	r3,ORIG_GPR3(r1)
25962306a36Sopenharmony_ci	LOAD_REG_IMMEDIATE(r11, STACK_FRAME_REGS_MARKER)
26062306a36Sopenharmony_ci	std	r11,STACK_INT_FRAME_MARKER(r1)		/* "regs" marker */
26162306a36Sopenharmony_ci	/* Calling convention has r3 = regs, r4 = orig r0 */
26262306a36Sopenharmony_ci	addi	r3,r1,STACK_INT_FRAME_REGS
26362306a36Sopenharmony_ci	mr	r4,r0
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
26662306a36Sopenharmony_ci	li	r11,1
26762306a36Sopenharmony_ci	stb	r11,PACASRR_VALID(r13)
26862306a36Sopenharmony_ci#endif
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/*
27162306a36Sopenharmony_ci	 * We always enter kernel from userspace with irq soft-mask enabled and
27262306a36Sopenharmony_ci	 * nothing pending. system_call_exception() will call
27362306a36Sopenharmony_ci	 * trace_hardirqs_off().
27462306a36Sopenharmony_ci	 */
27562306a36Sopenharmony_ci	li	r11,IRQS_ALL_DISABLED
27662306a36Sopenharmony_ci	stb	r11,PACAIRQSOFTMASK(r13)
27762306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
27862306a36Sopenharmony_ci	li	r12,-1 /* Set MSR_EE and MSR_RI */
27962306a36Sopenharmony_ci	mtmsrd	r12,1
28062306a36Sopenharmony_ci#else
28162306a36Sopenharmony_ci	wrteei	1
28262306a36Sopenharmony_ci#endif
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/*
28562306a36Sopenharmony_ci	 * Zero user registers to prevent influencing speculative execution
28662306a36Sopenharmony_ci	 * state of kernel code.
28762306a36Sopenharmony_ci	 */
28862306a36Sopenharmony_ci	SANITIZE_SYSCALL_GPRS()
28962306a36Sopenharmony_ci	bl	CFUNC(system_call_exception)
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci.Lsyscall_exit:
29262306a36Sopenharmony_ci	addi	r4,r1,STACK_INT_FRAME_REGS
29362306a36Sopenharmony_ci	li	r5,0 /* !scv */
29462306a36Sopenharmony_ci	bl	CFUNC(syscall_exit_prepare)
29562306a36Sopenharmony_ci	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
29662306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
29762306a36Sopenharmony_ci.Lsyscall_rst_start:
29862306a36Sopenharmony_ci	lbz	r11,PACAIRQHAPPENED(r13)
29962306a36Sopenharmony_ci	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
30062306a36Sopenharmony_ci	bne-	syscall_restart
30162306a36Sopenharmony_ci#endif
30262306a36Sopenharmony_ci	li	r11,IRQS_ENABLED
30362306a36Sopenharmony_ci	stb	r11,PACAIRQSOFTMASK(r13)
30462306a36Sopenharmony_ci	li	r11,0
30562306a36Sopenharmony_ci	stb	r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	ld	r2,_CCR(r1)
30862306a36Sopenharmony_ci	ld	r6,_LINK(r1)
30962306a36Sopenharmony_ci	mtlr	r6
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
31262306a36Sopenharmony_ci	lbz	r4,PACASRR_VALID(r13)
31362306a36Sopenharmony_ci	cmpdi	r4,0
31462306a36Sopenharmony_ci	bne	1f
31562306a36Sopenharmony_ci	li	r4,0
31662306a36Sopenharmony_ci	stb	r4,PACASRR_VALID(r13)
31762306a36Sopenharmony_ci#endif
31862306a36Sopenharmony_ci	ld	r4,_NIP(r1)
31962306a36Sopenharmony_ci	ld	r5,_MSR(r1)
32062306a36Sopenharmony_ci	mtspr	SPRN_SRR0,r4
32162306a36Sopenharmony_ci	mtspr	SPRN_SRR1,r5
32262306a36Sopenharmony_ci1:
32362306a36Sopenharmony_ci	DEBUG_SRR_VALID srr
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ciBEGIN_FTR_SECTION
32662306a36Sopenharmony_ci	stdcx.	r0,0,r1			/* to clear the reservation */
32762306a36Sopenharmony_ciEND_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	SANITIZE_RESTORE_NVGPRS()
33062306a36Sopenharmony_ci	cmpdi	r3,0
33162306a36Sopenharmony_ci	bne	.Lsyscall_restore_regs
33262306a36Sopenharmony_ci	/* Zero volatile regs that may contain sensitive kernel data */
33362306a36Sopenharmony_ci	ZEROIZE_GPR(0)
33462306a36Sopenharmony_ci	ZEROIZE_GPRS(4, 12)
33562306a36Sopenharmony_ci	mtctr	r0
33662306a36Sopenharmony_ci	mtspr	SPRN_XER,r0
33762306a36Sopenharmony_ci.Lsyscall_restore_regs_cont:
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ciBEGIN_FTR_SECTION
34062306a36Sopenharmony_ci	HMT_MEDIUM_LOW
34162306a36Sopenharmony_ciEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	/*
34462306a36Sopenharmony_ci	 * We don't need to restore AMR on the way back to userspace for KUAP.
34562306a36Sopenharmony_ci	 * The value of AMR only matters while we're in the kernel.
34662306a36Sopenharmony_ci	 */
34762306a36Sopenharmony_ci	mtcr	r2
34862306a36Sopenharmony_ci	REST_GPRS(2, 3, r1)
34962306a36Sopenharmony_ci	REST_GPR(13, r1)
35062306a36Sopenharmony_ci	REST_GPR(1, r1)
35162306a36Sopenharmony_ci	RFI_TO_USER
35262306a36Sopenharmony_ci	b	.	/* prevent speculative execution */
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci.Lsyscall_restore_regs:
35562306a36Sopenharmony_ci	ld	r3,_CTR(r1)
35662306a36Sopenharmony_ci	ld	r4,_XER(r1)
35762306a36Sopenharmony_ci	HANDLER_RESTORE_NVGPRS()
35862306a36Sopenharmony_ci	mtctr	r3
35962306a36Sopenharmony_ci	mtspr	SPRN_XER,r4
36062306a36Sopenharmony_ci	REST_GPR(0, r1)
36162306a36Sopenharmony_ci	REST_GPRS(4, 12, r1)
36262306a36Sopenharmony_ci	b	.Lsyscall_restore_regs_cont
36362306a36Sopenharmony_ci.Lsyscall_rst_end:
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
36662306a36Sopenharmony_cisyscall_restart:
36762306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(syscall_restart)
36862306a36Sopenharmony_ci	GET_PACA(r13)
36962306a36Sopenharmony_ci	ld	r1,PACA_EXIT_SAVE_R1(r13)
37062306a36Sopenharmony_ci	LOAD_PACA_TOC()
37162306a36Sopenharmony_ci	ld	r3,RESULT(r1)
37262306a36Sopenharmony_ci	addi	r4,r1,STACK_INT_FRAME_REGS
37362306a36Sopenharmony_ci	li	r11,IRQS_ALL_DISABLED
37462306a36Sopenharmony_ci	stb	r11,PACAIRQSOFTMASK(r13)
37562306a36Sopenharmony_ci	bl	CFUNC(syscall_exit_restart)
37662306a36Sopenharmony_ci	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
37762306a36Sopenharmony_ci	b	.Lsyscall_rst_start
37862306a36Sopenharmony_ci1:
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ciSOFT_MASK_TABLE(.Lsyscall_rst_start, 1b)
38162306a36Sopenharmony_ciRESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, syscall_restart)
38262306a36Sopenharmony_ci#endif
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	/*
38562306a36Sopenharmony_ci	 * If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not
38662306a36Sopenharmony_ci	 * touched, no exit work created, then this can be used.
38762306a36Sopenharmony_ci	 */
38862306a36Sopenharmony_ci	.balign IFETCH_ALIGN_BYTES
38962306a36Sopenharmony_ci	.globl fast_interrupt_return_srr
39062306a36Sopenharmony_cifast_interrupt_return_srr:
39162306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(fast_interrupt_return_srr)
39262306a36Sopenharmony_ci	kuap_check_amr r3, r4
39362306a36Sopenharmony_ci	ld	r5,_MSR(r1)
39462306a36Sopenharmony_ci	andi.	r0,r5,MSR_PR
39562306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
39662306a36Sopenharmony_ci	beq	1f
39762306a36Sopenharmony_ci	kuap_user_restore r3, r4
39862306a36Sopenharmony_ci	b	.Lfast_user_interrupt_return_srr
39962306a36Sopenharmony_ci1:	kuap_kernel_restore r3, r4
40062306a36Sopenharmony_ci	andi.	r0,r5,MSR_RI
40162306a36Sopenharmony_ci	li	r3,0 /* 0 return value, no EMULATE_STACK_STORE */
40262306a36Sopenharmony_ci	bne+	.Lfast_kernel_interrupt_return_srr
40362306a36Sopenharmony_ci	addi	r3,r1,STACK_INT_FRAME_REGS
40462306a36Sopenharmony_ci	bl	CFUNC(unrecoverable_exception)
40562306a36Sopenharmony_ci	b	. /* should not get here */
40662306a36Sopenharmony_ci#else
40762306a36Sopenharmony_ci	bne	.Lfast_user_interrupt_return_srr
40862306a36Sopenharmony_ci	b	.Lfast_kernel_interrupt_return_srr
40962306a36Sopenharmony_ci#endif
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci.macro interrupt_return_macro srr
41262306a36Sopenharmony_ci	.balign IFETCH_ALIGN_BYTES
41362306a36Sopenharmony_ci	.globl interrupt_return_\srr
41462306a36Sopenharmony_ciinterrupt_return_\srr\():
41562306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\())
41662306a36Sopenharmony_ci	ld	r4,_MSR(r1)
41762306a36Sopenharmony_ci	andi.	r0,r4,MSR_PR
41862306a36Sopenharmony_ci	beq	interrupt_return_\srr\()_kernel
41962306a36Sopenharmony_ciinterrupt_return_\srr\()_user: /* make backtraces match the _kernel variant */
42062306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_user)
42162306a36Sopenharmony_ci	addi	r3,r1,STACK_INT_FRAME_REGS
42262306a36Sopenharmony_ci	bl	CFUNC(interrupt_exit_user_prepare)
42362306a36Sopenharmony_ci#ifndef CONFIG_INTERRUPT_SANITIZE_REGISTERS
42462306a36Sopenharmony_ci	cmpdi	r3,0
42562306a36Sopenharmony_ci	bne-	.Lrestore_nvgprs_\srr
42662306a36Sopenharmony_ci.Lrestore_nvgprs_\srr\()_cont:
42762306a36Sopenharmony_ci#endif
42862306a36Sopenharmony_ci	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
42962306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
43062306a36Sopenharmony_ci.Linterrupt_return_\srr\()_user_rst_start:
43162306a36Sopenharmony_ci	lbz	r11,PACAIRQHAPPENED(r13)
43262306a36Sopenharmony_ci	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
43362306a36Sopenharmony_ci	bne-	interrupt_return_\srr\()_user_restart
43462306a36Sopenharmony_ci#endif
43562306a36Sopenharmony_ci	li	r11,IRQS_ENABLED
43662306a36Sopenharmony_ci	stb	r11,PACAIRQSOFTMASK(r13)
43762306a36Sopenharmony_ci	li	r11,0
43862306a36Sopenharmony_ci	stb	r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci.Lfast_user_interrupt_return_\srr\():
44162306a36Sopenharmony_ci	SANITIZE_RESTORE_NVGPRS()
44262306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
44362306a36Sopenharmony_ci	.ifc \srr,srr
44462306a36Sopenharmony_ci	lbz	r4,PACASRR_VALID(r13)
44562306a36Sopenharmony_ci	.else
44662306a36Sopenharmony_ci	lbz	r4,PACAHSRR_VALID(r13)
44762306a36Sopenharmony_ci	.endif
44862306a36Sopenharmony_ci	cmpdi	r4,0
44962306a36Sopenharmony_ci	li	r4,0
45062306a36Sopenharmony_ci	bne	1f
45162306a36Sopenharmony_ci#endif
45262306a36Sopenharmony_ci	ld	r11,_NIP(r1)
45362306a36Sopenharmony_ci	ld	r12,_MSR(r1)
45462306a36Sopenharmony_ci	.ifc \srr,srr
45562306a36Sopenharmony_ci	mtspr	SPRN_SRR0,r11
45662306a36Sopenharmony_ci	mtspr	SPRN_SRR1,r12
45762306a36Sopenharmony_ci1:
45862306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
45962306a36Sopenharmony_ci	stb	r4,PACASRR_VALID(r13)
46062306a36Sopenharmony_ci#endif
46162306a36Sopenharmony_ci	.else
46262306a36Sopenharmony_ci	mtspr	SPRN_HSRR0,r11
46362306a36Sopenharmony_ci	mtspr	SPRN_HSRR1,r12
46462306a36Sopenharmony_ci1:
46562306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
46662306a36Sopenharmony_ci	stb	r4,PACAHSRR_VALID(r13)
46762306a36Sopenharmony_ci#endif
46862306a36Sopenharmony_ci	.endif
46962306a36Sopenharmony_ci	DEBUG_SRR_VALID \srr
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
47262306a36Sopenharmony_ci	lbz	r4,PACAIRQSOFTMASK(r13)
47362306a36Sopenharmony_ci	tdnei	r4,IRQS_ENABLED
47462306a36Sopenharmony_ci#endif
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ciBEGIN_FTR_SECTION
47762306a36Sopenharmony_ci	ld	r10,_PPR(r1)
47862306a36Sopenharmony_ci	mtspr	SPRN_PPR,r10
47962306a36Sopenharmony_ciEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ciBEGIN_FTR_SECTION
48262306a36Sopenharmony_ci	stdcx.	r0,0,r1		/* to clear the reservation */
48362306a36Sopenharmony_ciFTR_SECTION_ELSE
48462306a36Sopenharmony_ci	ldarx	r0,0,r1
48562306a36Sopenharmony_ciALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	ld	r3,_CCR(r1)
48862306a36Sopenharmony_ci	ld	r4,_LINK(r1)
48962306a36Sopenharmony_ci	ld	r5,_CTR(r1)
49062306a36Sopenharmony_ci	ld	r6,_XER(r1)
49162306a36Sopenharmony_ci	li	r0,0
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	REST_GPRS(7, 13, r1)
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	mtcr	r3
49662306a36Sopenharmony_ci	mtlr	r4
49762306a36Sopenharmony_ci	mtctr	r5
49862306a36Sopenharmony_ci	mtspr	SPRN_XER,r6
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	REST_GPRS(2, 6, r1)
50162306a36Sopenharmony_ci	REST_GPR(0, r1)
50262306a36Sopenharmony_ci	REST_GPR(1, r1)
50362306a36Sopenharmony_ci	.ifc \srr,srr
50462306a36Sopenharmony_ci	RFI_TO_USER
50562306a36Sopenharmony_ci	.else
50662306a36Sopenharmony_ci	HRFI_TO_USER
50762306a36Sopenharmony_ci	.endif
50862306a36Sopenharmony_ci	b	.	/* prevent speculative execution */
50962306a36Sopenharmony_ci.Linterrupt_return_\srr\()_user_rst_end:
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci#ifndef CONFIG_INTERRUPT_SANITIZE_REGISTERS
51262306a36Sopenharmony_ci.Lrestore_nvgprs_\srr\():
51362306a36Sopenharmony_ci	REST_NVGPRS(r1)
51462306a36Sopenharmony_ci	b	.Lrestore_nvgprs_\srr\()_cont
51562306a36Sopenharmony_ci#endif
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
51862306a36Sopenharmony_ciinterrupt_return_\srr\()_user_restart:
51962306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_user_restart)
52062306a36Sopenharmony_ci	GET_PACA(r13)
52162306a36Sopenharmony_ci	ld	r1,PACA_EXIT_SAVE_R1(r13)
52262306a36Sopenharmony_ci	LOAD_PACA_TOC()
52362306a36Sopenharmony_ci	addi	r3,r1,STACK_INT_FRAME_REGS
52462306a36Sopenharmony_ci	li	r11,IRQS_ALL_DISABLED
52562306a36Sopenharmony_ci	stb	r11,PACAIRQSOFTMASK(r13)
52662306a36Sopenharmony_ci	bl	CFUNC(interrupt_exit_user_restart)
52762306a36Sopenharmony_ci	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
52862306a36Sopenharmony_ci	b	.Linterrupt_return_\srr\()_user_rst_start
52962306a36Sopenharmony_ci1:
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ciSOFT_MASK_TABLE(.Linterrupt_return_\srr\()_user_rst_start, 1b)
53262306a36Sopenharmony_ciRESTART_TABLE(.Linterrupt_return_\srr\()_user_rst_start, .Linterrupt_return_\srr\()_user_rst_end, interrupt_return_\srr\()_user_restart)
53362306a36Sopenharmony_ci#endif
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	.balign IFETCH_ALIGN_BYTES
53662306a36Sopenharmony_ciinterrupt_return_\srr\()_kernel:
53762306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel)
53862306a36Sopenharmony_ci	addi	r3,r1,STACK_INT_FRAME_REGS
53962306a36Sopenharmony_ci	bl	CFUNC(interrupt_exit_kernel_prepare)
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
54262306a36Sopenharmony_ci.Linterrupt_return_\srr\()_kernel_rst_start:
54362306a36Sopenharmony_ci	ld	r11,SOFTE(r1)
54462306a36Sopenharmony_ci	cmpwi	r11,IRQS_ENABLED
54562306a36Sopenharmony_ci	stb	r11,PACAIRQSOFTMASK(r13)
54662306a36Sopenharmony_ci	beq	.Linterrupt_return_\srr\()_soft_enabled
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	/*
54962306a36Sopenharmony_ci	 * Returning to soft-disabled context.
55062306a36Sopenharmony_ci	 * Check if a MUST_HARD_MASK interrupt has become pending, in which
55162306a36Sopenharmony_ci	 * case we need to disable MSR[EE] in the return context.
55262306a36Sopenharmony_ci	 *
55362306a36Sopenharmony_ci	 * The MSR[EE] check catches among other things the short incoherency
55462306a36Sopenharmony_ci	 * in hard_irq_disable() between clearing MSR[EE] and setting
55562306a36Sopenharmony_ci	 * PACA_IRQ_HARD_DIS.
55662306a36Sopenharmony_ci	 */
55762306a36Sopenharmony_ci	ld	r12,_MSR(r1)
55862306a36Sopenharmony_ci	andi.	r10,r12,MSR_EE
55962306a36Sopenharmony_ci	beq	.Lfast_kernel_interrupt_return_\srr\() // EE already disabled
56062306a36Sopenharmony_ci	lbz	r11,PACAIRQHAPPENED(r13)
56162306a36Sopenharmony_ci	andi.	r10,r11,PACA_IRQ_MUST_HARD_MASK
56262306a36Sopenharmony_ci	bne	1f // HARD_MASK is pending
56362306a36Sopenharmony_ci	// No HARD_MASK pending, clear possible HARD_DIS set by interrupt
56462306a36Sopenharmony_ci	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
56562306a36Sopenharmony_ci	stb	r11,PACAIRQHAPPENED(r13)
56662306a36Sopenharmony_ci	b	.Lfast_kernel_interrupt_return_\srr\()
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci1:	/* Must clear MSR_EE from _MSR */
57062306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
57162306a36Sopenharmony_ci	li	r10,0
57262306a36Sopenharmony_ci	/* Clear valid before changing _MSR */
57362306a36Sopenharmony_ci	.ifc \srr,srr
57462306a36Sopenharmony_ci	stb	r10,PACASRR_VALID(r13)
57562306a36Sopenharmony_ci	.else
57662306a36Sopenharmony_ci	stb	r10,PACAHSRR_VALID(r13)
57762306a36Sopenharmony_ci	.endif
57862306a36Sopenharmony_ci#endif
57962306a36Sopenharmony_ci	xori	r12,r12,MSR_EE
58062306a36Sopenharmony_ci	std	r12,_MSR(r1)
58162306a36Sopenharmony_ci	b	.Lfast_kernel_interrupt_return_\srr\()
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci.Linterrupt_return_\srr\()_soft_enabled:
58462306a36Sopenharmony_ci	/*
58562306a36Sopenharmony_ci	 * In the soft-enabled case, need to double-check that we have no
58662306a36Sopenharmony_ci	 * pending interrupts that might have come in before we reached the
58762306a36Sopenharmony_ci	 * restart section of code, and restart the exit so those can be
58862306a36Sopenharmony_ci	 * handled.
58962306a36Sopenharmony_ci	 *
59062306a36Sopenharmony_ci	 * If there are none, it is be possible that the interrupt still
59162306a36Sopenharmony_ci	 * has PACA_IRQ_HARD_DIS set, which needs to be cleared for the
59262306a36Sopenharmony_ci	 * interrupted context. This clear will not clobber a new pending
59362306a36Sopenharmony_ci	 * interrupt coming in, because we're in the restart section, so
59462306a36Sopenharmony_ci	 * such would return to the restart location.
59562306a36Sopenharmony_ci	 */
59662306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
59762306a36Sopenharmony_ci	lbz	r11,PACAIRQHAPPENED(r13)
59862306a36Sopenharmony_ci	andi.	r11,r11,(~PACA_IRQ_HARD_DIS)@l
59962306a36Sopenharmony_ci	bne-	interrupt_return_\srr\()_kernel_restart
60062306a36Sopenharmony_ci#endif
60162306a36Sopenharmony_ci	li	r11,0
60262306a36Sopenharmony_ci	stb	r11,PACAIRQHAPPENED(r13) // clear the possible HARD_DIS
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci.Lfast_kernel_interrupt_return_\srr\():
60562306a36Sopenharmony_ci	SANITIZE_RESTORE_NVGPRS()
60662306a36Sopenharmony_ci	cmpdi	cr1,r3,0
60762306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
60862306a36Sopenharmony_ci	.ifc \srr,srr
60962306a36Sopenharmony_ci	lbz	r4,PACASRR_VALID(r13)
61062306a36Sopenharmony_ci	.else
61162306a36Sopenharmony_ci	lbz	r4,PACAHSRR_VALID(r13)
61262306a36Sopenharmony_ci	.endif
61362306a36Sopenharmony_ci	cmpdi	r4,0
61462306a36Sopenharmony_ci	li	r4,0
61562306a36Sopenharmony_ci	bne	1f
61662306a36Sopenharmony_ci#endif
61762306a36Sopenharmony_ci	ld	r11,_NIP(r1)
61862306a36Sopenharmony_ci	ld	r12,_MSR(r1)
61962306a36Sopenharmony_ci	.ifc \srr,srr
62062306a36Sopenharmony_ci	mtspr	SPRN_SRR0,r11
62162306a36Sopenharmony_ci	mtspr	SPRN_SRR1,r12
62262306a36Sopenharmony_ci1:
62362306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
62462306a36Sopenharmony_ci	stb	r4,PACASRR_VALID(r13)
62562306a36Sopenharmony_ci#endif
62662306a36Sopenharmony_ci	.else
62762306a36Sopenharmony_ci	mtspr	SPRN_HSRR0,r11
62862306a36Sopenharmony_ci	mtspr	SPRN_HSRR1,r12
62962306a36Sopenharmony_ci1:
63062306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
63162306a36Sopenharmony_ci	stb	r4,PACAHSRR_VALID(r13)
63262306a36Sopenharmony_ci#endif
63362306a36Sopenharmony_ci	.endif
63462306a36Sopenharmony_ci	DEBUG_SRR_VALID \srr
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ciBEGIN_FTR_SECTION
63762306a36Sopenharmony_ci	stdcx.	r0,0,r1		/* to clear the reservation */
63862306a36Sopenharmony_ciFTR_SECTION_ELSE
63962306a36Sopenharmony_ci	ldarx	r0,0,r1
64062306a36Sopenharmony_ciALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	ld	r3,_LINK(r1)
64362306a36Sopenharmony_ci	ld	r4,_CTR(r1)
64462306a36Sopenharmony_ci	ld	r5,_XER(r1)
64562306a36Sopenharmony_ci	ld	r6,_CCR(r1)
64662306a36Sopenharmony_ci	li	r0,0
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	REST_GPRS(7, 12, r1)
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	mtlr	r3
65162306a36Sopenharmony_ci	mtctr	r4
65262306a36Sopenharmony_ci	mtspr	SPRN_XER,r5
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	/*
65562306a36Sopenharmony_ci	 * Leaving a stale STACK_FRAME_REGS_MARKER on the stack can confuse
65662306a36Sopenharmony_ci	 * the reliable stack unwinder later on. Clear it.
65762306a36Sopenharmony_ci	 */
65862306a36Sopenharmony_ci	std	r0,STACK_INT_FRAME_MARKER(r1)
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	REST_GPRS(2, 5, r1)
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	bne-	cr1,1f /* emulate stack store */
66362306a36Sopenharmony_ci	mtcr	r6
66462306a36Sopenharmony_ci	REST_GPR(6, r1)
66562306a36Sopenharmony_ci	REST_GPR(0, r1)
66662306a36Sopenharmony_ci	REST_GPR(1, r1)
66762306a36Sopenharmony_ci	.ifc \srr,srr
66862306a36Sopenharmony_ci	RFI_TO_KERNEL
66962306a36Sopenharmony_ci	.else
67062306a36Sopenharmony_ci	HRFI_TO_KERNEL
67162306a36Sopenharmony_ci	.endif
67262306a36Sopenharmony_ci	b	.	/* prevent speculative execution */
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci1:	/*
67562306a36Sopenharmony_ci	 * Emulate stack store with update. New r1 value was already calculated
67662306a36Sopenharmony_ci	 * and updated in our interrupt regs by emulate_loadstore, but we can't
67762306a36Sopenharmony_ci	 * store the previous value of r1 to the stack before re-loading our
67862306a36Sopenharmony_ci	 * registers from it, otherwise they could be clobbered.  Use
67962306a36Sopenharmony_ci	 * PACA_EXGEN as temporary storage to hold the store data, as
68062306a36Sopenharmony_ci	 * interrupts are disabled here so it won't be clobbered.
68162306a36Sopenharmony_ci	 */
68262306a36Sopenharmony_ci	mtcr	r6
68362306a36Sopenharmony_ci	std	r9,PACA_EXGEN+0(r13)
68462306a36Sopenharmony_ci	addi	r9,r1,INT_FRAME_SIZE /* get original r1 */
68562306a36Sopenharmony_ci	REST_GPR(6, r1)
68662306a36Sopenharmony_ci	REST_GPR(0, r1)
68762306a36Sopenharmony_ci	REST_GPR(1, r1)
68862306a36Sopenharmony_ci	std	r9,0(r1) /* perform store component of stdu */
68962306a36Sopenharmony_ci	ld	r9,PACA_EXGEN+0(r13)
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	.ifc \srr,srr
69262306a36Sopenharmony_ci	RFI_TO_KERNEL
69362306a36Sopenharmony_ci	.else
69462306a36Sopenharmony_ci	HRFI_TO_KERNEL
69562306a36Sopenharmony_ci	.endif
69662306a36Sopenharmony_ci	b	.	/* prevent speculative execution */
69762306a36Sopenharmony_ci.Linterrupt_return_\srr\()_kernel_rst_end:
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
70062306a36Sopenharmony_ciinterrupt_return_\srr\()_kernel_restart:
70162306a36Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel_restart)
70262306a36Sopenharmony_ci	GET_PACA(r13)
70362306a36Sopenharmony_ci	ld	r1,PACA_EXIT_SAVE_R1(r13)
70462306a36Sopenharmony_ci	LOAD_PACA_TOC()
70562306a36Sopenharmony_ci	addi	r3,r1,STACK_INT_FRAME_REGS
70662306a36Sopenharmony_ci	li	r11,IRQS_ALL_DISABLED
70762306a36Sopenharmony_ci	stb	r11,PACAIRQSOFTMASK(r13)
70862306a36Sopenharmony_ci	bl	CFUNC(interrupt_exit_kernel_restart)
70962306a36Sopenharmony_ci	std	r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */
71062306a36Sopenharmony_ci	b	.Linterrupt_return_\srr\()_kernel_rst_start
71162306a36Sopenharmony_ci1:
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ciSOFT_MASK_TABLE(.Linterrupt_return_\srr\()_kernel_rst_start, 1b)
71462306a36Sopenharmony_ciRESTART_TABLE(.Linterrupt_return_\srr\()_kernel_rst_start, .Linterrupt_return_\srr\()_kernel_rst_end, interrupt_return_\srr\()_kernel_restart)
71562306a36Sopenharmony_ci#endif
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci.endm
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ciinterrupt_return_macro srr
72062306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
72162306a36Sopenharmony_ciinterrupt_return_macro hsrr
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci	.globl __end_soft_masked
72462306a36Sopenharmony_ci__end_soft_masked:
72562306a36Sopenharmony_ciDEFINE_FIXED_SYMBOL(__end_soft_masked, text)
72662306a36Sopenharmony_ci#endif /* CONFIG_PPC_BOOK3S */
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
72962306a36Sopenharmony_ci_GLOBAL(ret_from_fork_scv)
73062306a36Sopenharmony_ci	bl	CFUNC(schedule_tail)
73162306a36Sopenharmony_ci	HANDLER_RESTORE_NVGPRS()
73262306a36Sopenharmony_ci	li	r3,0	/* fork() return value */
73362306a36Sopenharmony_ci	b	.Lsyscall_vectored_common_exit
73462306a36Sopenharmony_ci#endif
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci_GLOBAL(ret_from_fork)
73762306a36Sopenharmony_ci	bl	CFUNC(schedule_tail)
73862306a36Sopenharmony_ci	HANDLER_RESTORE_NVGPRS()
73962306a36Sopenharmony_ci	li	r3,0	/* fork() return value */
74062306a36Sopenharmony_ci	b	.Lsyscall_exit
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci_GLOBAL(ret_from_kernel_user_thread)
74362306a36Sopenharmony_ci	bl	CFUNC(schedule_tail)
74462306a36Sopenharmony_ci	mtctr	r14
74562306a36Sopenharmony_ci	mr	r3,r15
74662306a36Sopenharmony_ci#ifdef CONFIG_PPC64_ELF_ABI_V2
74762306a36Sopenharmony_ci	mr	r12,r14
74862306a36Sopenharmony_ci#endif
74962306a36Sopenharmony_ci	bctrl
75062306a36Sopenharmony_ci	li	r3,0
75162306a36Sopenharmony_ci	/*
75262306a36Sopenharmony_ci	 * It does not matter whether this returns via the scv or sc path
75362306a36Sopenharmony_ci	 * because it returns as execve() and therefore has no calling ABI
75462306a36Sopenharmony_ci	 * (i.e., it sets registers according to the exec()ed entry point).
75562306a36Sopenharmony_ci	 */
75662306a36Sopenharmony_ci	b	.Lsyscall_exit
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci_GLOBAL(start_kernel_thread)
75962306a36Sopenharmony_ci	bl	CFUNC(schedule_tail)
76062306a36Sopenharmony_ci	mtctr	r14
76162306a36Sopenharmony_ci	mr	r3,r15
76262306a36Sopenharmony_ci#ifdef CONFIG_PPC64_ELF_ABI_V2
76362306a36Sopenharmony_ci	mr	r12,r14
76462306a36Sopenharmony_ci#endif
76562306a36Sopenharmony_ci	bctrl
76662306a36Sopenharmony_ci	/*
76762306a36Sopenharmony_ci	 * This must not return. We actually want to BUG here, not WARN,
76862306a36Sopenharmony_ci	 * because BUG will exit the process which is what the kernel thread
76962306a36Sopenharmony_ci	 * should have done, which may give some hope of continuing.
77062306a36Sopenharmony_ci	 */
77162306a36Sopenharmony_ci100:	trap
77262306a36Sopenharmony_ci	EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,0
773