xref: /openbmc/linux/arch/powerpc/kernel/idle_book3s.S (revision 762f99f4f3cb41a775b5157dd761217beba65873)
12874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
283289f90SShreyas B. Prabhu/*
310d91611SNicholas Piggin *  Copyright 2018, IBM Corporation.
483289f90SShreyas B. Prabhu *
510d91611SNicholas Piggin *  This file contains general idle entry/exit functions to save
610d91611SNicholas Piggin *  and restore stack and NVGPRs which allows C code to call idle
710d91611SNicholas Piggin *  states that lose GPRs, and it will return transparently with
810d91611SNicholas Piggin *  SRR1 wakeup reason return value.
910d91611SNicholas Piggin *
1010d91611SNicholas Piggin *  The platform / CPU caller must ensure SPRs and any other non-GPR
1110d91611SNicholas Piggin *  state is saved and restored correctly, handle KVM, interrupts, etc.
1283289f90SShreyas B. Prabhu */
1383289f90SShreyas B. Prabhu
1483289f90SShreyas B. Prabhu#include <asm/ppc_asm.h>
1583289f90SShreyas B. Prabhu#include <asm/asm-offsets.h>
1683289f90SShreyas B. Prabhu#include <asm/ppc-opcode.h>
1783289f90SShreyas B. Prabhu#include <asm/cpuidle.h>
18ed0bc98fSNicholas Piggin#include <asm/thread_info.h> /* TLF_NAPPING */
1983289f90SShreyas B. Prabhu
20ed0bc98fSNicholas Piggin#ifdef CONFIG_PPC_P7_NAP
2183289f90SShreyas B. Prabhu/*
2210d91611SNicholas Piggin * Desired PSSCR in r3
23e1c1cfedSGautham R. Shenoy *
2410d91611SNicholas Piggin * No state will be lost regardless of wakeup mechanism (interrupt or NIA).
2583289f90SShreyas B. Prabhu *
2610d91611SNicholas Piggin * An EC=0 type wakeup will return with a value of 0. SRESET wakeup (which can
2710d91611SNicholas Piggin * happen with xscom SRESET and possibly MCE) may clobber volatiles except LR,
2810d91611SNicholas Piggin * and must blr, to return to caller with r3 set according to caller's expected
2910d91611SNicholas Piggin * return code (for Book3S/64 that is SRR1).
3083289f90SShreyas B. Prabhu */
3110d91611SNicholas Piggin_GLOBAL(isa300_idle_stop_noloss)
3210d91611SNicholas Piggin	mtspr 	SPRN_PSSCR,r3
3310d91611SNicholas Piggin	PPC_STOP
3410d91611SNicholas Piggin	li	r3,0
3510d91611SNicholas Piggin	blr
3610d91611SNicholas Piggin
3710d91611SNicholas Piggin/*
3810d91611SNicholas Piggin * Desired PSSCR in r3
3910d91611SNicholas Piggin *
4010d91611SNicholas Piggin * GPRs may be lost, so they are saved here. Wakeup is by interrupt only.
4110d91611SNicholas Piggin * The SRESET wakeup returns to this function's caller by calling
4210d91611SNicholas Piggin * idle_return_gpr_loss with r3 set to desired return value.
4310d91611SNicholas Piggin *
4410d91611SNicholas Piggin * A wakeup without GPR loss may alteratively be handled as in
4510d91611SNicholas Piggin * isa300_idle_stop_noloss and blr directly, as an optimisation.
4610d91611SNicholas Piggin *
4710d91611SNicholas Piggin * The caller is responsible for saving/restoring SPRs, MSR, timebase,
4810d91611SNicholas Piggin * etc.
4983289f90SShreyas B. Prabhu */
5010d91611SNicholas Piggin_GLOBAL(isa300_idle_stop_mayloss)
5110d91611SNicholas Piggin	mtspr 	SPRN_PSSCR,r3
5283289f90SShreyas B. Prabhu	std	r1,PACAR1(r13)
5310d91611SNicholas Piggin	mflr	r4
5410d91611SNicholas Piggin	mfcr	r5
5573287caaSChristopher M. Riedl	/*
5673287caaSChristopher M. Riedl	 * Use the stack red zone rather than a new frame for saving regs since
5773287caaSChristopher M. Riedl	 * in the case of no GPR loss the wakeup code branches directly back to
5873287caaSChristopher M. Riedl	 * the caller without deallocating the stack frame first.
5973287caaSChristopher M. Riedl	 */
6073287caaSChristopher M. Riedl	std	r2,-8*1(r1)
6173287caaSChristopher M. Riedl	std	r14,-8*2(r1)
6273287caaSChristopher M. Riedl	std	r15,-8*3(r1)
6373287caaSChristopher M. Riedl	std	r16,-8*4(r1)
6473287caaSChristopher M. Riedl	std	r17,-8*5(r1)
6573287caaSChristopher M. Riedl	std	r18,-8*6(r1)
6673287caaSChristopher M. Riedl	std	r19,-8*7(r1)
6773287caaSChristopher M. Riedl	std	r20,-8*8(r1)
6873287caaSChristopher M. Riedl	std	r21,-8*9(r1)
6973287caaSChristopher M. Riedl	std	r22,-8*10(r1)
7073287caaSChristopher M. Riedl	std	r23,-8*11(r1)
7173287caaSChristopher M. Riedl	std	r24,-8*12(r1)
7273287caaSChristopher M. Riedl	std	r25,-8*13(r1)
7373287caaSChristopher M. Riedl	std	r26,-8*14(r1)
7473287caaSChristopher M. Riedl	std	r27,-8*15(r1)
7573287caaSChristopher M. Riedl	std	r28,-8*16(r1)
7673287caaSChristopher M. Riedl	std	r29,-8*17(r1)
7773287caaSChristopher M. Riedl	std	r30,-8*18(r1)
7873287caaSChristopher M. Riedl	std	r31,-8*19(r1)
7973287caaSChristopher M. Riedl	std	r4,-8*20(r1)
8073287caaSChristopher M. Riedl	std	r5,-8*21(r1)
8110d91611SNicholas Piggin	/* 168 bytes */
8210d91611SNicholas Piggin	PPC_STOP
8310d91611SNicholas Piggin	b	.	/* catch bugs */
8483289f90SShreyas B. Prabhu
8583289f90SShreyas B. Prabhu/*
8610d91611SNicholas Piggin * Desired return value in r3
8710d91611SNicholas Piggin *
8810d91611SNicholas Piggin * The idle wakeup SRESET interrupt can call this after calling
8910d91611SNicholas Piggin * to return to the idle sleep function caller with r3 as the return code.
9010d91611SNicholas Piggin *
9110d91611SNicholas Piggin * This must not be used if idle was entered via a _noloss function (use
9210d91611SNicholas Piggin * a simple blr instead).
9372b0d51dSNicholas Piggin */
9410d91611SNicholas Piggin_GLOBAL(idle_return_gpr_loss)
9510d91611SNicholas Piggin	ld	r1,PACAR1(r13)
9673287caaSChristopher M. Riedl	ld	r4,-8*20(r1)
9773287caaSChristopher M. Riedl	ld	r5,-8*21(r1)
9810d91611SNicholas Piggin	mtlr	r4
9910d91611SNicholas Piggin	mtcr	r5
10072b0d51dSNicholas Piggin	/*
10110d91611SNicholas Piggin	 * KVM nap requires r2 to be saved, rather than just restoring it
10210d91611SNicholas Piggin	 * from PACATOC. This could be avoided for that less common case
10310d91611SNicholas Piggin	 * if KVM saved its r2.
10483289f90SShreyas B. Prabhu	 */
10573287caaSChristopher M. Riedl	ld	r2,-8*1(r1)
10673287caaSChristopher M. Riedl	ld	r14,-8*2(r1)
10773287caaSChristopher M. Riedl	ld	r15,-8*3(r1)
10873287caaSChristopher M. Riedl	ld	r16,-8*4(r1)
10973287caaSChristopher M. Riedl	ld	r17,-8*5(r1)
11073287caaSChristopher M. Riedl	ld	r18,-8*6(r1)
11173287caaSChristopher M. Riedl	ld	r19,-8*7(r1)
11273287caaSChristopher M. Riedl	ld	r20,-8*8(r1)
11373287caaSChristopher M. Riedl	ld	r21,-8*9(r1)
11473287caaSChristopher M. Riedl	ld	r22,-8*10(r1)
11573287caaSChristopher M. Riedl	ld	r23,-8*11(r1)
11673287caaSChristopher M. Riedl	ld	r24,-8*12(r1)
11773287caaSChristopher M. Riedl	ld	r25,-8*13(r1)
11873287caaSChristopher M. Riedl	ld	r26,-8*14(r1)
11973287caaSChristopher M. Riedl	ld	r27,-8*15(r1)
12073287caaSChristopher M. Riedl	ld	r28,-8*16(r1)
12173287caaSChristopher M. Riedl	ld	r29,-8*17(r1)
12273287caaSChristopher M. Riedl	ld	r30,-8*18(r1)
12373287caaSChristopher M. Riedl	ld	r31,-8*19(r1)
12410d91611SNicholas Piggin	blr
12583289f90SShreyas B. Prabhu
126aafc8a83SNicholas Piggin/*
127aafc8a83SNicholas Piggin * This is the sequence required to execute idle instructions, as
128aafc8a83SNicholas Piggin * specified in ISA v2.07 (and earlier). MSR[IR] and MSR[DR] must be 0.
129*496c5fe2SMichael Ellerman * We have to store a GPR somewhere, ptesync, then reload it, and create
130*496c5fe2SMichael Ellerman * a false dependency on the result of the load. It doesn't matter which
131*496c5fe2SMichael Ellerman * GPR we store, or where we store it. We have already stored r2 to the
132*496c5fe2SMichael Ellerman * stack at -8(r1) in isa206_idle_insn_mayloss, so use that.
133aafc8a83SNicholas Piggin */
13465dbbe81SNicholas Piggin#define IDLE_STATE_ENTER_SEQ_NORET(IDLE_INST)			\
135aafc8a83SNicholas Piggin	/* Magic NAP/SLEEP/WINKLE mode enter sequence */	\
136*496c5fe2SMichael Ellerman	std	r2,-8(r1);					\
137aafc8a83SNicholas Piggin	ptesync;						\
138*496c5fe2SMichael Ellerman	ld	r2,-8(r1);					\
13910d91611SNicholas Piggin236:	cmpd	cr0,r2,r2;					\
140aafc8a83SNicholas Piggin	bne	236b;						\
14110d91611SNicholas Piggin	IDLE_INST;						\
14210d91611SNicholas Piggin	b	.	/* catch bugs */
14383289f90SShreyas B. Prabhu
14483289f90SShreyas B. Prabhu/*
14510d91611SNicholas Piggin * Desired instruction type in r3
146a67cc594SMichael Ellerman *
14710d91611SNicholas Piggin * GPRs may be lost, so they are saved here. Wakeup is by interrupt only.
14810d91611SNicholas Piggin * The SRESET wakeup returns to this function's caller by calling
14910d91611SNicholas Piggin * idle_return_gpr_loss with r3 set to desired return value.
150a67cc594SMichael Ellerman *
15110d91611SNicholas Piggin * A wakeup without GPR loss may alteratively be handled as in
15210d91611SNicholas Piggin * isa300_idle_stop_noloss and blr directly, as an optimisation.
153d0b791c0SMichael Ellerman *
15410d91611SNicholas Piggin * The caller is responsible for saving/restoring SPRs, MSR, timebase,
15510d91611SNicholas Piggin * etc.
15610d91611SNicholas Piggin *
15710d91611SNicholas Piggin * This must be called in real-mode (MSR_IDLE).
158bcef83a0SShreyas B. Prabhu */
15910d91611SNicholas Piggin_GLOBAL(isa206_idle_insn_mayloss)
16010d91611SNicholas Piggin	std	r1,PACAR1(r13)
16110d91611SNicholas Piggin	mflr	r4
16210d91611SNicholas Piggin	mfcr	r5
16373287caaSChristopher M. Riedl	/*
16473287caaSChristopher M. Riedl	 * Use the stack red zone rather than a new frame for saving regs since
16573287caaSChristopher M. Riedl	 * in the case of no GPR loss the wakeup code branches directly back to
16673287caaSChristopher M. Riedl	 * the caller without deallocating the stack frame first.
16773287caaSChristopher M. Riedl	 */
16873287caaSChristopher M. Riedl	std	r2,-8*1(r1)
16973287caaSChristopher M. Riedl	std	r14,-8*2(r1)
17073287caaSChristopher M. Riedl	std	r15,-8*3(r1)
17173287caaSChristopher M. Riedl	std	r16,-8*4(r1)
17273287caaSChristopher M. Riedl	std	r17,-8*5(r1)
17373287caaSChristopher M. Riedl	std	r18,-8*6(r1)
17473287caaSChristopher M. Riedl	std	r19,-8*7(r1)
17573287caaSChristopher M. Riedl	std	r20,-8*8(r1)
17673287caaSChristopher M. Riedl	std	r21,-8*9(r1)
17773287caaSChristopher M. Riedl	std	r22,-8*10(r1)
17873287caaSChristopher M. Riedl	std	r23,-8*11(r1)
17973287caaSChristopher M. Riedl	std	r24,-8*12(r1)
18073287caaSChristopher M. Riedl	std	r25,-8*13(r1)
18173287caaSChristopher M. Riedl	std	r26,-8*14(r1)
18273287caaSChristopher M. Riedl	std	r27,-8*15(r1)
18373287caaSChristopher M. Riedl	std	r28,-8*16(r1)
18473287caaSChristopher M. Riedl	std	r29,-8*17(r1)
18573287caaSChristopher M. Riedl	std	r30,-8*18(r1)
18673287caaSChristopher M. Riedl	std	r31,-8*19(r1)
18773287caaSChristopher M. Riedl	std	r4,-8*20(r1)
18873287caaSChristopher M. Riedl	std	r5,-8*21(r1)
18910d91611SNicholas Piggin	cmpwi	r3,PNV_THREAD_NAP
190a67cc594SMichael Ellerman	bne	1f
19110d91611SNicholas Piggin	IDLE_STATE_ENTER_SEQ_NORET(PPC_NAP)
19210d91611SNicholas Piggin1:	cmpwi	r3,PNV_THREAD_SLEEP
1930d7720a2SNicholas Piggin	bne	2f
19410d91611SNicholas Piggin	IDLE_STATE_ENTER_SEQ_NORET(PPC_SLEEP)
19510d91611SNicholas Piggin2:	IDLE_STATE_ENTER_SEQ_NORET(PPC_WINKLE)
196ed0bc98fSNicholas Piggin#endif
1970d7720a2SNicholas Piggin
198ed0bc98fSNicholas Piggin#ifdef CONFIG_PPC_970_NAP
199ed0bc98fSNicholas Piggin_GLOBAL(power4_idle_nap)
200ed0bc98fSNicholas Piggin	LOAD_REG_IMMEDIATE(r7, MSR_KERNEL|MSR_EE|MSR_POW)
201ed0bc98fSNicholas Piggin	ld	r9,PACA_THREAD_INFO(r13)
202ed0bc98fSNicholas Piggin	ld	r8,TI_LOCAL_FLAGS(r9)
203ed0bc98fSNicholas Piggin	ori	r8,r8,_TLF_NAPPING
204ed0bc98fSNicholas Piggin	std	r8,TI_LOCAL_FLAGS(r9)
205ed0bc98fSNicholas Piggin	/*
206ed0bc98fSNicholas Piggin	 * NAPPING bit is set, from this point onward power4_fixup_nap
207ed0bc98fSNicholas Piggin	 * will cause exceptions to return to power4_idle_nap_return.
208ed0bc98fSNicholas Piggin	 */
209ed0bc98fSNicholas Piggin1:	sync
210ed0bc98fSNicholas Piggin	isync
211ed0bc98fSNicholas Piggin	mtmsrd	r7
212ed0bc98fSNicholas Piggin	isync
213ed0bc98fSNicholas Piggin	b	1b
21498db179aSNicholas Piggin
21598db179aSNicholas Piggin	.globl power4_idle_nap_return
21698db179aSNicholas Pigginpower4_idle_nap_return:
21798db179aSNicholas Piggin	blr
218ed0bc98fSNicholas Piggin#endif
219