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