1838ee286SNicholas Piggin/* SPDX-License-Identifier: GPL-2.0-or-later */ 2838ee286SNicholas Piggin 3838ee286SNicholas Piggin#include <asm/asm-offsets.h> 4838ee286SNicholas Piggin#include <asm/bug.h> 5838ee286SNicholas Piggin#include <asm/page.h> 6838ee286SNicholas Piggin#include <asm/ppc_asm.h> 7838ee286SNicholas Piggin 8838ee286SNicholas Piggin/* 9838ee286SNicholas Piggin * RTAS is called with MSR IR, DR, EE disabled, and LR in the return address. 10838ee286SNicholas Piggin * 11838ee286SNicholas Piggin * Note: r3 is an input parameter to rtas, so don't trash it... 12838ee286SNicholas Piggin */ 13838ee286SNicholas Piggin 14838ee286SNicholas Piggin#ifdef CONFIG_PPC32 15838ee286SNicholas Piggin_GLOBAL(enter_rtas) 16838ee286SNicholas Piggin stwu r1,-INT_FRAME_SIZE(r1) 17838ee286SNicholas Piggin mflr r0 18838ee286SNicholas Piggin stw r0,INT_FRAME_SIZE+4(r1) 19838ee286SNicholas Piggin LOAD_REG_ADDR(r4, rtas) 20838ee286SNicholas Piggin lis r6,1f@ha /* physical return address for rtas */ 21838ee286SNicholas Piggin addi r6,r6,1f@l 22838ee286SNicholas Piggin tophys(r6,r6) 23838ee286SNicholas Piggin lwz r8,RTASENTRY(r4) 24838ee286SNicholas Piggin lwz r4,RTASBASE(r4) 25838ee286SNicholas Piggin mfmsr r9 26838ee286SNicholas Piggin stw r9,8(r1) 27838ee286SNicholas Piggin li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR) 28838ee286SNicholas Piggin mtlr r6 29838ee286SNicholas Piggin stw r1, THREAD + RTAS_SP(r2) 30838ee286SNicholas Piggin mtspr SPRN_SRR0,r8 31838ee286SNicholas Piggin mtspr SPRN_SRR1,r9 32838ee286SNicholas Piggin rfi 33838ee286SNicholas Piggin1: 34838ee286SNicholas Piggin lis r8, 1f@h 35838ee286SNicholas Piggin ori r8, r8, 1f@l 36838ee286SNicholas Piggin LOAD_REG_IMMEDIATE(r9,MSR_KERNEL) 37838ee286SNicholas Piggin mtspr SPRN_SRR0,r8 38838ee286SNicholas Piggin mtspr SPRN_SRR1,r9 39838ee286SNicholas Piggin rfi /* Reactivate MMU translation */ 40838ee286SNicholas Piggin1: 41838ee286SNicholas Piggin lwz r8,INT_FRAME_SIZE+4(r1) /* get return address */ 42838ee286SNicholas Piggin lwz r9,8(r1) /* original msr value */ 43838ee286SNicholas Piggin addi r1,r1,INT_FRAME_SIZE 44838ee286SNicholas Piggin li r0,0 45838ee286SNicholas Piggin stw r0, THREAD + RTAS_SP(r2) 46838ee286SNicholas Piggin mtlr r8 47838ee286SNicholas Piggin mtmsr r9 48838ee286SNicholas Piggin blr /* return to caller */ 49838ee286SNicholas Piggin_ASM_NOKPROBE_SYMBOL(enter_rtas) 50838ee286SNicholas Piggin 51838ee286SNicholas Piggin#else /* CONFIG_PPC32 */ 52838ee286SNicholas Piggin#include <asm/exception-64s.h> 53838ee286SNicholas Piggin 54838ee286SNicholas Piggin/* 55838ee286SNicholas Piggin * 32-bit rtas on 64-bit machines has the additional problem that RTAS may 56838ee286SNicholas Piggin * not preserve the upper parts of registers it uses. 57838ee286SNicholas Piggin */ 58838ee286SNicholas Piggin_GLOBAL(enter_rtas) 59838ee286SNicholas Piggin mflr r0 60838ee286SNicholas Piggin std r0,16(r1) 61838ee286SNicholas Piggin stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */ 62838ee286SNicholas Piggin 63838ee286SNicholas Piggin /* Because RTAS is running in 32b mode, it clobbers the high order half 64838ee286SNicholas Piggin * of all registers that it saves. We therefore save those registers 655c86bd02SNicholas Piggin * RTAS might touch to the stack. (r0, r3-r12 are caller saved) 66838ee286SNicholas Piggin */ 67838ee286SNicholas Piggin SAVE_GPR(2, r1) /* Save the TOC */ 68838ee286SNicholas Piggin SAVE_NVGPRS(r1) /* Save the non-volatiles */ 69838ee286SNicholas Piggin 70838ee286SNicholas Piggin mfcr r4 71838ee286SNicholas Piggin std r4,_CCR(r1) 72838ee286SNicholas Piggin mfctr r5 73838ee286SNicholas Piggin std r5,_CTR(r1) 74838ee286SNicholas Piggin mfspr r6,SPRN_XER 75838ee286SNicholas Piggin std r6,_XER(r1) 76838ee286SNicholas Piggin mfdar r7 77838ee286SNicholas Piggin std r7,_DAR(r1) 78838ee286SNicholas Piggin mfdsisr r8 79838ee286SNicholas Piggin std r8,_DSISR(r1) 80838ee286SNicholas Piggin 81838ee286SNicholas Piggin /* Temporary workaround to clear CR until RTAS can be modified to 82838ee286SNicholas Piggin * ignore all bits. 83838ee286SNicholas Piggin */ 84838ee286SNicholas Piggin li r0,0 85838ee286SNicholas Piggin mtcr r0 86838ee286SNicholas Piggin 87838ee286SNicholas Piggin mfmsr r6 88838ee286SNicholas Piggin 89838ee286SNicholas Piggin /* Unfortunately, the stack pointer and the MSR are also clobbered, 90838ee286SNicholas Piggin * so they are saved in the PACA which allows us to restore 91838ee286SNicholas Piggin * our original state after RTAS returns. 92838ee286SNicholas Piggin */ 93838ee286SNicholas Piggin std r1,PACAR1(r13) 94838ee286SNicholas Piggin std r6,PACASAVEDMSR(r13) 95838ee286SNicholas Piggin 96838ee286SNicholas Piggin /* Setup our real return addr */ 97838ee286SNicholas Piggin LOAD_REG_ADDR(r4,rtas_return_loc) 98838ee286SNicholas Piggin clrldi r4,r4,2 /* convert to realmode address */ 99838ee286SNicholas Piggin mtlr r4 100838ee286SNicholas Piggin 101838ee286SNicholas Piggin__enter_rtas: 102838ee286SNicholas Piggin LOAD_REG_ADDR(r4, rtas) 103838ee286SNicholas Piggin ld r5,RTASENTRY(r4) /* get the rtas->entry value */ 104838ee286SNicholas Piggin ld r4,RTASBASE(r4) /* get the rtas->base value */ 105838ee286SNicholas Piggin 106838ee286SNicholas Piggin /* 107838ee286SNicholas Piggin * RTAS runs in 32-bit big endian real mode, but leave MSR[RI] on as we 108838ee286SNicholas Piggin * may hit NMI (SRESET or MCE) while in RTAS. RTAS should disable RI in 109838ee286SNicholas Piggin * its critical regions (as specified in PAPR+ section 7.2.1). MSR[S] 110838ee286SNicholas Piggin * is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if 111838ee286SNicholas Piggin * MSR[S] is set, it will remain when entering RTAS. 112*91926d8bSMichael Ellerman * If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV 113*91926d8bSMichael Ellerman * from the saved MSR value and insert into the value RTAS will use. 114838ee286SNicholas Piggin */ 115*91926d8bSMichael Ellerman extrdi r0, r6, 1, 63 - MSR_HV_LG 116838ee286SNicholas Piggin LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI) 117*91926d8bSMichael Ellerman insrdi r6, r0, 1, 63 - MSR_HV_LG 118838ee286SNicholas Piggin 119838ee286SNicholas Piggin li r0,0 120838ee286SNicholas Piggin mtmsrd r0,1 /* disable RI before using SRR0/1 */ 121838ee286SNicholas Piggin 122838ee286SNicholas Piggin mtspr SPRN_SRR0,r5 123838ee286SNicholas Piggin mtspr SPRN_SRR1,r6 124838ee286SNicholas Piggin RFI_TO_KERNEL 125838ee286SNicholas Piggin b . /* prevent speculative execution */ 126838ee286SNicholas Pigginrtas_return_loc: 127838ee286SNicholas Piggin FIXUP_ENDIAN 128838ee286SNicholas Piggin 129014b2e89SNicholas Piggin /* Set SF before anything. */ 130014b2e89SNicholas Piggin LOAD_REG_IMMEDIATE(r6, MSR_KERNEL & ~(MSR_IR|MSR_DR)) 131838ee286SNicholas Piggin mtmsrd r6 132838ee286SNicholas Piggin 133838ee286SNicholas Piggin /* relocation is off at this point */ 1345c86bd02SNicholas Piggin GET_PACA(r13) 135838ee286SNicholas Piggin 136838ee286SNicholas Piggin bcl 20,31,$+4 137838ee286SNicholas Piggin0: mflr r3 138838ee286SNicholas Piggin ld r3,(1f-0b)(r3) /* get &rtas_restore_regs */ 139838ee286SNicholas Piggin 1405c86bd02SNicholas Piggin ld r1,PACAR1(r13) /* Restore our SP */ 1415c86bd02SNicholas Piggin ld r4,PACASAVEDMSR(r13) /* Restore our MSR */ 142838ee286SNicholas Piggin 143838ee286SNicholas Piggin mtspr SPRN_SRR0,r3 144838ee286SNicholas Piggin mtspr SPRN_SRR1,r4 145838ee286SNicholas Piggin RFI_TO_KERNEL 146838ee286SNicholas Piggin b . /* prevent speculative execution */ 14707940b4bSNicholas Piggin_ASM_NOKPROBE_SYMBOL(enter_rtas) 148838ee286SNicholas Piggin_ASM_NOKPROBE_SYMBOL(__enter_rtas) 149838ee286SNicholas Piggin_ASM_NOKPROBE_SYMBOL(rtas_return_loc) 150838ee286SNicholas Piggin 151838ee286SNicholas Piggin .align 3 152838ee286SNicholas Piggin1: .8byte rtas_restore_regs 153838ee286SNicholas Piggin 154838ee286SNicholas Pigginrtas_restore_regs: 155838ee286SNicholas Piggin /* relocation is on at this point */ 156838ee286SNicholas Piggin REST_GPR(2, r1) /* Restore the TOC */ 157838ee286SNicholas Piggin REST_NVGPRS(r1) /* Restore the non-volatiles */ 158838ee286SNicholas Piggin 159838ee286SNicholas Piggin ld r4,_CCR(r1) 160838ee286SNicholas Piggin mtcr r4 161838ee286SNicholas Piggin ld r5,_CTR(r1) 162838ee286SNicholas Piggin mtctr r5 163838ee286SNicholas Piggin ld r6,_XER(r1) 164838ee286SNicholas Piggin mtspr SPRN_XER,r6 165838ee286SNicholas Piggin ld r7,_DAR(r1) 166838ee286SNicholas Piggin mtdar r7 167838ee286SNicholas Piggin ld r8,_DSISR(r1) 168838ee286SNicholas Piggin mtdsisr r8 169838ee286SNicholas Piggin 170838ee286SNicholas Piggin addi r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */ 171838ee286SNicholas Piggin ld r0,16(r1) /* get return address */ 172838ee286SNicholas Piggin 173838ee286SNicholas Piggin mtlr r0 174838ee286SNicholas Piggin blr /* return to caller */ 175838ee286SNicholas Piggin 176838ee286SNicholas Piggin#endif /* CONFIG_PPC32 */ 177