1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 3 #include <asm/asm-offsets.h> 4 #include <asm/bug.h> 5 #include <asm/page.h> 6 #include <asm/ppc_asm.h> 7 8 /* 9 * RTAS is called with MSR IR, DR, EE disabled, and LR in the return address. 10 * 11 * Note: r3 is an input parameter to rtas, so don't trash it... 12 */ 13 14 #ifdef CONFIG_PPC32 15 _GLOBAL(enter_rtas) 16 stwu r1,-INT_FRAME_SIZE(r1) 17 mflr r0 18 stw r0,INT_FRAME_SIZE+4(r1) 19 LOAD_REG_ADDR(r4, rtas) 20 lis r6,1f@ha /* physical return address for rtas */ 21 addi r6,r6,1f@l 22 tophys(r6,r6) 23 lwz r8,RTASENTRY(r4) 24 lwz r4,RTASBASE(r4) 25 mfmsr r9 26 stw r9,8(r1) 27 li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR) 28 mtlr r6 29 stw r1, THREAD + RTAS_SP(r2) 30 mtspr SPRN_SRR0,r8 31 mtspr SPRN_SRR1,r9 32 rfi 33 1: 34 lis r8, 1f@h 35 ori r8, r8, 1f@l 36 LOAD_REG_IMMEDIATE(r9,MSR_KERNEL) 37 mtspr SPRN_SRR0,r8 38 mtspr SPRN_SRR1,r9 39 rfi /* Reactivate MMU translation */ 40 1: 41 lwz r8,INT_FRAME_SIZE+4(r1) /* get return address */ 42 lwz r9,8(r1) /* original msr value */ 43 addi r1,r1,INT_FRAME_SIZE 44 li r0,0 45 stw r0, THREAD + RTAS_SP(r2) 46 mtlr r8 47 mtmsr r9 48 blr /* return to caller */ 49 _ASM_NOKPROBE_SYMBOL(enter_rtas) 50 51 #else /* CONFIG_PPC32 */ 52 #include <asm/exception-64s.h> 53 54 /* 55 * 32-bit rtas on 64-bit machines has the additional problem that RTAS may 56 * not preserve the upper parts of registers it uses. 57 */ 58 _GLOBAL(enter_rtas) 59 mflr r0 60 std r0,16(r1) 61 stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */ 62 63 /* Because RTAS is running in 32b mode, it clobbers the high order half 64 * of all registers that it saves. We therefore save those registers 65 * RTAS might touch to the stack. (r0, r3-r12 are caller saved) 66 */ 67 SAVE_GPR(2, r1) /* Save the TOC */ 68 SAVE_NVGPRS(r1) /* Save the non-volatiles */ 69 70 mfcr r4 71 std r4,_CCR(r1) 72 mfctr r5 73 std r5,_CTR(r1) 74 mfspr r6,SPRN_XER 75 std r6,_XER(r1) 76 mfdar r7 77 std r7,_DAR(r1) 78 mfdsisr r8 79 std r8,_DSISR(r1) 80 81 /* Temporary workaround to clear CR until RTAS can be modified to 82 * ignore all bits. 83 */ 84 li r0,0 85 mtcr r0 86 87 mfmsr r6 88 89 /* Unfortunately, the stack pointer and the MSR are also clobbered, 90 * so they are saved in the PACA which allows us to restore 91 * our original state after RTAS returns. 92 */ 93 std r1,PACAR1(r13) 94 std r6,PACASAVEDMSR(r13) 95 96 /* Setup our real return addr */ 97 LOAD_REG_ADDR(r4,rtas_return_loc) 98 clrldi r4,r4,2 /* convert to realmode address */ 99 mtlr r4 100 101 __enter_rtas: 102 LOAD_REG_ADDR(r4, rtas) 103 ld r5,RTASENTRY(r4) /* get the rtas->entry value */ 104 ld r4,RTASBASE(r4) /* get the rtas->base value */ 105 106 /* 107 * RTAS runs in 32-bit big endian real mode, but leave MSR[RI] on as we 108 * may hit NMI (SRESET or MCE) while in RTAS. RTAS should disable RI in 109 * its critical regions (as specified in PAPR+ section 7.2.1). MSR[S] 110 * is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if 111 * MSR[S] is set, it will remain when entering RTAS. 112 * If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV 113 * from the saved MSR value and insert into the value RTAS will use. 114 */ 115 extrdi r0, r6, 1, 63 - MSR_HV_LG 116 LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI) 117 insrdi r6, r0, 1, 63 - MSR_HV_LG 118 119 li r0,0 120 mtmsrd r0,1 /* disable RI before using SRR0/1 */ 121 122 mtspr SPRN_SRR0,r5 123 mtspr SPRN_SRR1,r6 124 RFI_TO_KERNEL 125 b . /* prevent speculative execution */ 126 rtas_return_loc: 127 FIXUP_ENDIAN 128 129 /* Set SF before anything. */ 130 LOAD_REG_IMMEDIATE(r6, MSR_KERNEL & ~(MSR_IR|MSR_DR)) 131 mtmsrd r6 132 133 /* relocation is off at this point */ 134 GET_PACA(r13) 135 136 bcl 20,31,$+4 137 0: mflr r3 138 ld r3,(1f-0b)(r3) /* get &rtas_restore_regs */ 139 140 ld r1,PACAR1(r13) /* Restore our SP */ 141 ld r4,PACASAVEDMSR(r13) /* Restore our MSR */ 142 143 mtspr SPRN_SRR0,r3 144 mtspr SPRN_SRR1,r4 145 RFI_TO_KERNEL 146 b . /* prevent speculative execution */ 147 _ASM_NOKPROBE_SYMBOL(enter_rtas) 148 _ASM_NOKPROBE_SYMBOL(__enter_rtas) 149 _ASM_NOKPROBE_SYMBOL(rtas_return_loc) 150 151 .align 3 152 1: .8byte rtas_restore_regs 153 154 rtas_restore_regs: 155 /* relocation is on at this point */ 156 REST_GPR(2, r1) /* Restore the TOC */ 157 REST_NVGPRS(r1) /* Restore the non-volatiles */ 158 159 ld r4,_CCR(r1) 160 mtcr r4 161 ld r5,_CTR(r1) 162 mtctr r5 163 ld r6,_XER(r1) 164 mtspr SPRN_XER,r6 165 ld r7,_DAR(r1) 166 mtdar r7 167 ld r8,_DSISR(r1) 168 mtdsisr r8 169 170 addi r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */ 171 ld r0,16(r1) /* get return address */ 172 173 mtlr r0 174 blr /* return to caller */ 175 176 #endif /* CONFIG_PPC32 */
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.