1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Copyright 2018, IBM Corporation. 4 * 5 * This file contains general idle entry/exit functions to save 6 * and restore stack and NVGPRs which allows C code to call idle 7 * states that lose GPRs, and it will return transparently with 8 * SRR1 wakeup reason return value. 9 * 10 * The platform / CPU caller must ensure SPRs and any other non-GPR 11 * state is saved and restored correctly, handle KVM, interrupts, etc. 12 */ 13 14 #include <asm/ppc_asm.h> 15 #include <asm/asm-offsets.h> 16 #include <asm/ppc-opcode.h> 17 #include <asm/cpuidle.h> 18 #include <asm/thread_info.h> /* TLF_NAPPING */ 19 20 #ifdef CONFIG_PPC_P7_NAP 21 /* 22 * Desired PSSCR in r3 23 * 24 * No state will be lost regardless of wakeup mechanism (interrupt or NIA). 25 * 26 * An EC=0 type wakeup will return with a value of 0. SRESET wakeup (which can 27 * happen with xscom SRESET and possibly MCE) may clobber volatiles except LR, 28 * and must blr, to return to caller with r3 set according to caller's expected 29 * return code (for Book3S/64 that is SRR1). 30 */ 31 _GLOBAL(isa300_idle_stop_noloss) 32 mtspr SPRN_PSSCR,r3 33 PPC_STOP 34 li r3,0 35 blr 36 37 /* 38 * Desired PSSCR in r3 39 * 40 * GPRs may be lost, so they are saved here. Wakeup is by interrupt only. 41 * The SRESET wakeup returns to this function's caller by calling 42 * idle_return_gpr_loss with r3 set to desired return value. 43 * 44 * A wakeup without GPR loss may alteratively be handled as in 45 * isa300_idle_stop_noloss and blr directly, as an optimisation. 46 * 47 * The caller is responsible for saving/restoring SPRs, MSR, timebase, 48 * etc. 49 */ 50 _GLOBAL(isa300_idle_stop_mayloss) 51 mtspr SPRN_PSSCR,r3 52 std r1,PACAR1(r13) 53 mflr r4 54 mfcr r5 55 /* 56 * Use the stack red zone rather than a new frame for saving regs since 57 * in the case of no GPR loss the wakeup code branches directly back to 58 * the caller without deallocating the stack frame first. 59 */ 60 std r2,-8*1(r1) 61 std r14,-8*2(r1) 62 std r15,-8*3(r1) 63 std r16,-8*4(r1) 64 std r17,-8*5(r1) 65 std r18,-8*6(r1) 66 std r19,-8*7(r1) 67 std r20,-8*8(r1) 68 std r21,-8*9(r1) 69 std r22,-8*10(r1) 70 std r23,-8*11(r1) 71 std r24,-8*12(r1) 72 std r25,-8*13(r1) 73 std r26,-8*14(r1) 74 std r27,-8*15(r1) 75 std r28,-8*16(r1) 76 std r29,-8*17(r1) 77 std r30,-8*18(r1) 78 std r31,-8*19(r1) 79 std r4,-8*20(r1) 80 std r5,-8*21(r1) 81 /* 168 bytes */ 82 PPC_STOP 83 b . /* catch bugs */ 84 85 /* 86 * Desired return value in r3 87 * 88 * The idle wakeup SRESET interrupt can call this after calling 89 * to return to the idle sleep function caller with r3 as the return code. 90 * 91 * This must not be used if idle was entered via a _noloss function (use 92 * a simple blr instead). 93 */ 94 _GLOBAL(idle_return_gpr_loss) 95 ld r1,PACAR1(r13) 96 ld r4,-8*20(r1) 97 ld r5,-8*21(r1) 98 mtlr r4 99 mtcr r5 100 /* 101 * KVM nap requires r2 to be saved, rather than just restoring it 102 * from PACATOC. This could be avoided for that less common case 103 * if KVM saved its r2. 104 */ 105 ld r2,-8*1(r1) 106 ld r14,-8*2(r1) 107 ld r15,-8*3(r1) 108 ld r16,-8*4(r1) 109 ld r17,-8*5(r1) 110 ld r18,-8*6(r1) 111 ld r19,-8*7(r1) 112 ld r20,-8*8(r1) 113 ld r21,-8*9(r1) 114 ld r22,-8*10(r1) 115 ld r23,-8*11(r1) 116 ld r24,-8*12(r1) 117 ld r25,-8*13(r1) 118 ld r26,-8*14(r1) 119 ld r27,-8*15(r1) 120 ld r28,-8*16(r1) 121 ld r29,-8*17(r1) 122 ld r30,-8*18(r1) 123 ld r31,-8*19(r1) 124 blr 125 126 /* 127 * This is the sequence required to execute idle instructions, as 128 * specified in ISA v2.07 (and earlier). MSR[IR] and MSR[DR] must be 0. 129 * We have to store a GPR somewhere, ptesync, then reload it, and create 130 * a false dependency on the result of the load. It doesn't matter which 131 * GPR we store, or where we store it. We have already stored r2 to the 132 * stack at -8(r1) in isa206_idle_insn_mayloss, so use that. 133 */ 134 #define IDLE_STATE_ENTER_SEQ_NORET(IDLE_INST) \ 135 /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \ 136 std r2,-8(r1); \ 137 ptesync; \ 138 ld r2,-8(r1); \ 139 236: cmpd cr0,r2,r2; \ 140 bne 236b; \ 141 IDLE_INST; \ 142 b . /* catch bugs */ 143 144 /* 145 * Desired instruction type in r3 146 * 147 * GPRs may be lost, so they are saved here. Wakeup is by interrupt only. 148 * The SRESET wakeup returns to this function's caller by calling 149 * idle_return_gpr_loss with r3 set to desired return value. 150 * 151 * A wakeup without GPR loss may alteratively be handled as in 152 * isa300_idle_stop_noloss and blr directly, as an optimisation. 153 * 154 * The caller is responsible for saving/restoring SPRs, MSR, timebase, 155 * etc. 156 * 157 * This must be called in real-mode (MSR_IDLE). 158 */ 159 _GLOBAL(isa206_idle_insn_mayloss) 160 std r1,PACAR1(r13) 161 mflr r4 162 mfcr r5 163 /* 164 * Use the stack red zone rather than a new frame for saving regs since 165 * in the case of no GPR loss the wakeup code branches directly back to 166 * the caller without deallocating the stack frame first. 167 */ 168 std r2,-8*1(r1) 169 std r14,-8*2(r1) 170 std r15,-8*3(r1) 171 std r16,-8*4(r1) 172 std r17,-8*5(r1) 173 std r18,-8*6(r1) 174 std r19,-8*7(r1) 175 std r20,-8*8(r1) 176 std r21,-8*9(r1) 177 std r22,-8*10(r1) 178 std r23,-8*11(r1) 179 std r24,-8*12(r1) 180 std r25,-8*13(r1) 181 std r26,-8*14(r1) 182 std r27,-8*15(r1) 183 std r28,-8*16(r1) 184 std r29,-8*17(r1) 185 std r30,-8*18(r1) 186 std r31,-8*19(r1) 187 std r4,-8*20(r1) 188 std r5,-8*21(r1) 189 cmpwi r3,PNV_THREAD_NAP 190 bne 1f 191 IDLE_STATE_ENTER_SEQ_NORET(PPC_NAP) 192 1: cmpwi r3,PNV_THREAD_SLEEP 193 bne 2f 194 IDLE_STATE_ENTER_SEQ_NORET(PPC_SLEEP) 195 2: IDLE_STATE_ENTER_SEQ_NORET(PPC_WINKLE) 196 #endif 197 198 #ifdef CONFIG_PPC_970_NAP 199 _GLOBAL(power4_idle_nap) 200 LOAD_REG_IMMEDIATE(r7, MSR_KERNEL|MSR_EE|MSR_POW) 201 ld r9,PACA_THREAD_INFO(r13) 202 ld r8,TI_LOCAL_FLAGS(r9) 203 ori r8,r8,_TLF_NAPPING 204 std r8,TI_LOCAL_FLAGS(r9) 205 /* 206 * NAPPING bit is set, from this point onward power4_fixup_nap 207 * will cause exceptions to return to power4_idle_nap_return. 208 */ 209 1: sync 210 isync 211 mtmsrd r7 212 isync 213 b 1b 214 215 .globl power4_idle_nap_return 216 power4_idle_nap_return: 217 blr 218 #endif
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.