/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright 2018, IBM Corporation. * * This file contains general idle entry/exit functions to save * and restore stack and NVGPRs which allows C code to call idle * states that lose GPRs, and it will return transparently with * SRR1 wakeup reason return value. * * The platform / CPU caller must ensure SPRs and any other non-GPR * state is saved and restored correctly, handle KVM, interrupts, etc. */ #include <asm/ppc_asm.h> #include <asm/asm-offsets.h> #include <asm/ppc-opcode.h> #include <asm/cpuidle.h> #include <asm/thread_info.h> /* TLF_NAPPING */ #ifdef CONFIG_PPC_P7_NAP /* * Desired PSSCR in r3 * * No state will be lost regardless of wakeup mechanism (interrupt or NIA). * * An EC=0 type wakeup will return with a value of 0. SRESET wakeup (which can * happen with xscom SRESET and possibly MCE) may clobber volatiles except LR, * and must blr, to return to caller with r3 set according to caller's expected * return code (for Book3S/64 that is SRR1). */ _GLOBAL(isa300_idle_stop_noloss) mtspr SPRN_PSSCR,r3 PPC_STOP li r3,0 blr /* * Desired PSSCR in r3 * * GPRs may be lost, so they are saved here. Wakeup is by interrupt only. * The SRESET wakeup returns to this function's caller by calling * idle_return_gpr_loss with r3 set to desired return value. * * A wakeup without GPR loss may alteratively be handled as in * isa300_idle_stop_noloss and blr directly, as an optimisation. * * The caller is responsible for saving/restoring SPRs, MSR, timebase, * etc. */ _GLOBAL(isa300_idle_stop_mayloss) mtspr SPRN_PSSCR,r3 std r1,PACAR1(r13) mflr r4 mfcr r5 /* * Use the stack red zone rather than a new frame for saving regs since * in the case of no GPR loss the wakeup code branches directly back to * the caller without deallocating the stack frame first. */ std r2,-8*1(r1) std r14,-8*2(r1) std r15,-8*3(r1) std r16,-8*4(r1) std r17,-8*5(r1) std r18,-8*6(r1) std r19,-8*7(r1) std r20,-8*8(r1) std r21,-8*9(r1) std r22,-8*10(r1) std r23,-8*11(r1) std r24,-8*12(r1) std r25,-8*13(r1) std r26,-8*14(r1) std r27,-8*15(r1) std r28,-8*16(r1) std r29,-8*17(r1) std r30,-8*18(r1) std r31,-8*19(r1) std r4,-8*20(r1) std r5,-8*21(r1) /* 168 bytes */ PPC_STOP b . /* catch bugs */ /* * Desired return value in r3 * * The idle wakeup SRESET interrupt can call this after calling * to return to the idle sleep function caller with r3 as the return code. * * This must not be used if idle was entered via a _noloss function (use * a simple blr instead). */ _GLOBAL(idle_return_gpr_loss) ld r1,PACAR1(r13) ld r4,-8*20(r1) ld r5,-8*21(r1) mtlr r4 mtcr r5 /* * KVM nap requires r2 to be saved, rather than just restoring it * from PACATOC. This could be avoided for that less common case * if KVM saved its r2. */ ld r2,-8*1(r1) ld r14,-8*2(r1) ld r15,-8*3(r1) ld r16,-8*4(r1) ld r17,-8*5(r1) ld r18,-8*6(r1) ld r19,-8*7(r1) ld r20,-8*8(r1) ld r21,-8*9(r1) ld r22,-8*10(r1) ld r23,-8*11(r1) ld r24,-8*12(r1) ld r25,-8*13(r1) ld r26,-8*14(r1) ld r27,-8*15(r1) ld r28,-8*16(r1) ld r29,-8*17(r1) ld r30,-8*18(r1) ld r31,-8*19(r1) blr /* * This is the sequence required to execute idle instructions, as * specified in ISA v2.07 (and earlier). MSR[IR] and MSR[DR] must be 0. * We have to store a GPR somewhere, ptesync, then reload it, and create * a false dependency on the result of the load. It doesn't matter which * GPR we store, or where we store it. We have already stored r2 to the * stack at -8(r1) in isa206_idle_insn_mayloss, so use that. */ #define IDLE_STATE_ENTER_SEQ_NORET(IDLE_INST) \ /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \ std r2,-8(r1); \ ptesync; \ ld r2,-8(r1); \ 236: cmpd cr0,r2,r2; \ bne 236b; \ IDLE_INST; \ b . /* catch bugs */ /* * Desired instruction type in r3 * * GPRs may be lost, so they are saved here. Wakeup is by interrupt only. * The SRESET wakeup returns to this function's caller by calling * idle_return_gpr_loss with r3 set to desired return value. * * A wakeup without GPR loss may alteratively be handled as in * isa300_idle_stop_noloss and blr directly, as an optimisation. * * The caller is responsible for saving/restoring SPRs, MSR, timebase, * etc. * * This must be called in real-mode (MSR_IDLE). */ _GLOBAL(isa206_idle_insn_mayloss) std r1,PACAR1(r13) mflr r4 mfcr r5 /* * Use the stack red zone rather than a new frame for saving regs since * in the case of no GPR loss the wakeup code branches directly back to * the caller without deallocating the stack frame first. */ std r2,-8*1(r1) std r14,-8*2(r1) std r15,-8*3(r1) std r16,-8*4(r1) std r17,-8*5(r1) std r18,-8*6(r1) std r19,-8*7(r1) std r20,-8*8(r1) std r21,-8*9(r1) std r22,-8*10(r1) std r23,-8*11(r1) std r24,-8*12(r1) std r25,-8*13(r1) std r26,-8*14(r1) std r27,-8*15(r1) std r28,-8*16(r1) std r29,-8*17(r1) std r30,-8*18(r1) std r31,-8*19(r1) std r4,-8*20(r1) std r5,-8*21(r1) cmpwi r3,PNV_THREAD_NAP bne 1f IDLE_STATE_ENTER_SEQ_NORET(PPC_NAP) 1: cmpwi r3,PNV_THREAD_SLEEP bne 2f IDLE_STATE_ENTER_SEQ_NORET(PPC_SLEEP) 2: IDLE_STATE_ENTER_SEQ_NORET(PPC_WINKLE) #endif #ifdef CONFIG_PPC_970_NAP _GLOBAL(power4_idle_nap) LOAD_REG_IMMEDIATE(r7, MSR_KERNEL|MSR_EE|MSR_POW) ld r9,PACA_THREAD_INFO(r13) ld r8,TI_LOCAL_FLAGS(r9) ori r8,r8,_TLF_NAPPING std r8,TI_LOCAL_FLAGS(r9) /* * NAPPING bit is set, from this point onward power4_fixup_nap * will cause exceptions to return to power4_idle_nap_return. */ 1: sync isync mtmsrd r7 isync b 1b .globl power4_idle_nap_return power4_idle_nap_return: blr #endif