/* SPDX-License-Identifier: GPL-2.0-or-later */ #include <asm/asm-offsets.h>#include <asm/bug.h>#include <asm/page.h>#include <asm/ppc_asm.h> /* * RTAS is called with MSR IR, DR, EE disabled, and LR in the return address. * * Note: r3 is an input parameter to rtas, so don't trash it... */ #ifdef CONFIG_PPC32_GLOBAL(enter_rtas) stwu r1,-INT_FRAME_SIZE(r1) mflr r0 stw r0,INT_FRAME_SIZE+4(r1) LOAD_REG_ADDR(r4, rtas) lis r6,1f@ha /* physical return address for rtas */ addi r6,r6,1f@l tophys(r6,r6) lwz r8,RTASENTRY(r4) lwz r4,RTASBASE(r4) mfmsr r9 stw r9,8(r1) li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR) mtlr r6 stw r1, THREAD + RTAS_SP(r2) mtspr SPRN_SRR0,r8 mtspr SPRN_SRR1,r9 rfi1: lis r8, 1f@h ori r8, r8, 1f@l LOAD_REG_IMMEDIATE(r9,MSR_KERNEL) mtspr SPRN_SRR0,r8 mtspr SPRN_SRR1,r9 rfi /* Reactivate MMU translation */1: lwz r8,INT_FRAME_SIZE+4(r1) /* get return address */ lwz r9,8(r1) /* original msr value */ addi r1,r1,INT_FRAME_SIZE li r0,0 stw r0, THREAD + RTAS_SP(r2) mtlr r8 mtmsr r9 blr /* return to caller */_ASM_NOKPROBE_SYMBOL(enter_rtas) #else /* CONFIG_PPC32 */#include <asm/exception-64s.h> /* * 32-bit rtas on 64-bit machines has the additional problem that RTAS may * not preserve the upper parts of registers it uses. */_GLOBAL(enter_rtas) mflr r0 std r0,16(r1) stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */ /* Because RTAS is running in 32b mode, it clobbers the high order half * of all registers that it saves. We therefore save those registers * RTAS might touch to the stack. (r0, r3-r12 are caller saved) */ SAVE_GPR(2, r1) /* Save the TOC */ SAVE_NVGPRS(r1) /* Save the non-volatiles */ mfcr r4 std r4,_CCR(r1) mfctr r5 std r5,_CTR(r1) mfspr r6,SPRN_XER std r6,_XER(r1) mfdar r7 std r7,_DAR(r1) mfdsisr r8 std r8,_DSISR(r1) /* Temporary workaround to clear CR until RTAS can be modified to * ignore all bits. */ li r0,0 mtcr r0 mfmsr r6 /* Unfortunately, the stack pointer and the MSR are also clobbered, * so they are saved in the PACA which allows us to restore * our original state after RTAS returns. */ std r1,PACAR1(r13) std r6,PACASAVEDMSR(r13) /* Setup our real return addr */ LOAD_REG_ADDR(r4,rtas_return_loc) clrldi r4,r4,2 /* convert to realmode address */ mtlr r4 __enter_rtas: LOAD_REG_ADDR(r4, rtas) ld r5,RTASENTRY(r4) /* get the rtas->entry value */ ld r4,RTASBASE(r4) /* get the rtas->base value */ /* * RTAS runs in 32-bit big endian real mode, but leave MSR[RI] on as we * may hit NMI (SRESET or MCE) while in RTAS. RTAS should disable RI in * its critical regions (as specified in PAPR+ section 7.2.1). MSR[S] * is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if * MSR[S] is set, it will remain when entering RTAS. * If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV * from the saved MSR value and insert into the value RTAS will use. */ extrdi r0, r6, 1, 63 - MSR_HV_LG LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI) insrdi r6, r0, 1, 63 - MSR_HV_LG li r0,0 mtmsrd r0,1 /* disable RI before using SRR0/1 */ mtspr SPRN_SRR0,r5 mtspr SPRN_SRR1,r6 RFI_TO_KERNEL b . /* prevent speculative execution */rtas_return_loc: FIXUP_ENDIAN /* Set SF before anything. */ LOAD_REG_IMMEDIATE(r6, MSR_KERNEL & ~(MSR_IR|MSR_DR)) mtmsrd r6 /* relocation is off at this point */ GET_PACA(r13) bcl 20,31,$+40: mflr r3 ld r3,(1f-0b)(r3) /* get &rtas_restore_regs */ ld r1,PACAR1(r13) /* Restore our SP */ ld r4,PACASAVEDMSR(r13) /* Restore our MSR */ mtspr SPRN_SRR0,r3 mtspr SPRN_SRR1,r4 RFI_TO_KERNEL b . /* prevent speculative execution */_ASM_NOKPROBE_SYMBOL(enter_rtas)_ASM_NOKPROBE_SYMBOL(__enter_rtas)_ASM_NOKPROBE_SYMBOL(rtas_return_loc) .align 31: .8byte rtas_restore_regs rtas_restore_regs: /* relocation is on at this point */ REST_GPR(2, r1) /* Restore the TOC */ REST_NVGPRS(r1) /* Restore the non-volatiles */ ld r4,_CCR(r1) mtcr r4 ld r5,_CTR(r1) mtctr r5 ld r6,_XER(r1) mtspr SPRN_XER,r6 ld r7,_DAR(r1) mtdar r7 ld r8,_DSISR(r1) mtdsisr r8 addi r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */ ld r0,16(r1) /* get return address */ mtlr r0 blr /* return to caller */ #endif /* CONFIG_PPC32 */
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <asm/asm-offsets.h>
#include <asm/bug.h>
#include <asm/page.h>
#include <asm/ppc_asm.h>
/*
* RTAS is called with MSR IR, DR, EE disabled, and LR in the return address.
*
* Note: r3 is an input parameter to rtas, so don't trash it...
*/
#ifdef CONFIG_PPC32
_GLOBAL(enter_rtas)
stwu r1,-INT_FRAME_SIZE(r1)
mflr r0
stw r0,INT_FRAME_SIZE+4(r1)
LOAD_REG_ADDR(r4, rtas)
lis r6,1f@ha /* physical return address for rtas */
addi r6,r6,1f@l
tophys(r6,r6)
lwz r8,RTASENTRY(r4)
lwz r4,RTASBASE(r4)
mfmsr r9
stw r9,8(r1)
li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
mtlr r6
stw r1, THREAD + RTAS_SP(r2)
mtspr SPRN_SRR0,r8
mtspr SPRN_SRR1,r9
rfi
1:
lis r8, 1f@h
ori r8, r8, 1f@l
LOAD_REG_IMMEDIATE(r9,MSR_KERNEL)
mtspr SPRN_SRR0,r8
mtspr SPRN_SRR1,r9
rfi /* Reactivate MMU translation */
1:
lwz r8,INT_FRAME_SIZE+4(r1) /* get return address */
lwz r9,8(r1) /* original msr value */
addi r1,r1,INT_FRAME_SIZE
li r0,0
stw r0, THREAD + RTAS_SP(r2)
mtlr r8
mtmsr r9
blr /* return to caller */
_ASM_NOKPROBE_SYMBOL(enter_rtas)
#else /* CONFIG_PPC32 */
#include <asm/exception-64s.h>
/*
* 32-bit rtas on 64-bit machines has the additional problem that RTAS may
* not preserve the upper parts of registers it uses.
*/
_GLOBAL(enter_rtas)
mflr r0
std r0,16(r1)
stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */
/* Because RTAS is running in 32b mode, it clobbers the high order half
* of all registers that it saves. We therefore save those registers
* RTAS might touch to the stack. (r0, r3-r12 are caller saved)
*/
SAVE_GPR(2, r1) /* Save the TOC */
SAVE_NVGPRS(r1) /* Save the non-volatiles */
mfcr r4
std r4,_CCR(r1)
mfctr r5
std r5,_CTR(r1)
mfspr r6,SPRN_XER
std r6,_XER(r1)
mfdar r7
std r7,_DAR(r1)
mfdsisr r8
std r8,_DSISR(r1)
/* Temporary workaround to clear CR until RTAS can be modified to
* ignore all bits.
*/
li r0,0
mtcr r0
mfmsr r6
/* Unfortunately, the stack pointer and the MSR are also clobbered,
* so they are saved in the PACA which allows us to restore
* our original state after RTAS returns.
*/
std r1,PACAR1(r13)
std r6,PACASAVEDMSR(r13)
/* Setup our real return addr */
LOAD_REG_ADDR(r4,rtas_return_loc)
clrldi r4,r4,2 /* convert to realmode address */
mtlr r4
__enter_rtas:
LOAD_REG_ADDR(r4, rtas)
ld r5,RTASENTRY(r4) /* get the rtas->entry value */
ld r4,RTASBASE(r4) /* get the rtas->base value */
/*
* RTAS runs in 32-bit big endian real mode, but leave MSR[RI] on as we
* may hit NMI (SRESET or MCE) while in RTAS. RTAS should disable RI in
* its critical regions (as specified in PAPR+ section 7.2.1). MSR[S]
* is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if
* MSR[S] is set, it will remain when entering RTAS.
* If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV
* from the saved MSR value and insert into the value RTAS will use.
*/
extrdi r0, r6, 1, 63 - MSR_HV_LG
LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)
insrdi r6, r0, 1, 63 - MSR_HV_LG
li r0,0
mtmsrd r0,1 /* disable RI before using SRR0/1 */
mtspr SPRN_SRR0,r5
mtspr SPRN_SRR1,r6
RFI_TO_KERNEL
b . /* prevent speculative execution */
rtas_return_loc:
FIXUP_ENDIAN
/* Set SF before anything. */
LOAD_REG_IMMEDIATE(r6, MSR_KERNEL & ~(MSR_IR|MSR_DR))
mtmsrd r6
/* relocation is off at this point */
GET_PACA(r13)
bcl 20,31,$+4
0: mflr r3
ld r3,(1f-0b)(r3) /* get &rtas_restore_regs */
ld r1,PACAR1(r13) /* Restore our SP */
ld r4,PACASAVEDMSR(r13) /* Restore our MSR */
mtspr SPRN_SRR0,r3
mtspr SPRN_SRR1,r4
RFI_TO_KERNEL
b . /* prevent speculative execution */
_ASM_NOKPROBE_SYMBOL(enter_rtas)
_ASM_NOKPROBE_SYMBOL(__enter_rtas)
_ASM_NOKPROBE_SYMBOL(rtas_return_loc)
.align 3
1: .8byte rtas_restore_regs
rtas_restore_regs:
/* relocation is on at this point */
REST_GPR(2, r1) /* Restore the TOC */
REST_NVGPRS(r1) /* Restore the non-volatiles */
ld r4,_CCR(r1)
mtcr r4
ld r5,_CTR(r1)
mtctr r5
ld r6,_XER(r1)
mtspr SPRN_XER,r6
ld r7,_DAR(r1)
mtdar r7
ld r8,_DSISR(r1)
mtdsisr r8
addi r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */
ld r0,16(r1) /* get return address */
mtlr r0
blr /* return to caller */
#endif /* CONFIG_PPC32 */