1/*
2 *  Copyright 2018, IBM Corporation.
3 *
4 *  This program is free software; you can redistribute it and/or
5 *  modify it under the terms of the GNU General Public License
6 *  as published by the Free Software Foundation; either version
7 *  2 of the License, or (at your option) any later version.
8 *
9 *  This file contains general idle entry/exit functions to save
10 *  and restore stack and NVGPRs which allows C code to call idle
11 *  states that lose GPRs, and it will return transparently with
12 *  SRR1 wakeup reason return value.
13 *
14 *  The platform / CPU caller must ensure SPRs and any other non-GPR
15 *  state is saved and restored correctly, handle KVM, interrupts, etc.
16 */
17
18#include <asm/ppc_asm.h>
19#include <asm/asm-offsets.h>
20#include <asm/ppc-opcode.h>
21#include <asm/cpuidle.h>
22
23/*
24 * Desired PSSCR in r3
25 *
26 * No state will be lost regardless of wakeup mechanism (interrupt or NIA).
27 *
28 * An EC=0 type wakeup will return with a value of 0. SRESET wakeup (which can
29 * happen with xscom SRESET and possibly MCE) may clobber volatiles except LR,
30 * and must blr, to return to caller with r3 set according to caller's expected
31 * return code (for Book3S/64 that is SRR1).
32 */
33_GLOBAL(isa300_idle_stop_noloss)
34	mtspr 	SPRN_PSSCR,r3
35	PPC_STOP
36	li	r3,0
37	blr
38
39/*
40 * Desired PSSCR in r3
41 *
42 * GPRs may be lost, so they are saved here. Wakeup is by interrupt only.
43 * The SRESET wakeup returns to this function's caller by calling
44 * idle_return_gpr_loss with r3 set to desired return value.
45 *
46 * A wakeup without GPR loss may alteratively be handled as in
47 * isa300_idle_stop_noloss and blr directly, as an optimisation.
48 *
49 * The caller is responsible for saving/restoring SPRs, MSR, timebase,
50 * etc.
51 */
52_GLOBAL(isa300_idle_stop_mayloss)
53	mtspr 	SPRN_PSSCR,r3
54	std	r1,PACAR1(r13)
55	mflr	r4
56	mfcr	r5
57	/* use stack red zone rather than a new frame for saving regs */
58	std	r2,-8*0(r1)
59	std	r14,-8*1(r1)
60	std	r15,-8*2(r1)
61	std	r16,-8*3(r1)
62	std	r17,-8*4(r1)
63	std	r18,-8*5(r1)
64	std	r19,-8*6(r1)
65	std	r20,-8*7(r1)
66	std	r21,-8*8(r1)
67	std	r22,-8*9(r1)
68	std	r23,-8*10(r1)
69	std	r24,-8*11(r1)
70	std	r25,-8*12(r1)
71	std	r26,-8*13(r1)
72	std	r27,-8*14(r1)
73	std	r28,-8*15(r1)
74	std	r29,-8*16(r1)
75	std	r30,-8*17(r1)
76	std	r31,-8*18(r1)
77	std	r4,-8*19(r1)
78	std	r5,-8*20(r1)
79	/* 168 bytes */
80	PPC_STOP
81	b	.	/* catch bugs */
82
83/*
84 * Desired return value in r3
85 *
86 * The idle wakeup SRESET interrupt can call this after calling
87 * to return to the idle sleep function caller with r3 as the return code.
88 *
89 * This must not be used if idle was entered via a _noloss function (use
90 * a simple blr instead).
91 */
92_GLOBAL(idle_return_gpr_loss)
93	ld	r1,PACAR1(r13)
94	ld	r4,-8*19(r1)
95	ld	r5,-8*20(r1)
96	mtlr	r4
97	mtcr	r5
98	/*
99	 * KVM nap requires r2 to be saved, rather than just restoring it
100	 * from PACATOC. This could be avoided for that less common case
101	 * if KVM saved its r2.
102	 */
103	ld	r2,-8*0(r1)
104	ld	r14,-8*1(r1)
105	ld	r15,-8*2(r1)
106	ld	r16,-8*3(r1)
107	ld	r17,-8*4(r1)
108	ld	r18,-8*5(r1)
109	ld	r19,-8*6(r1)
110	ld	r20,-8*7(r1)
111	ld	r21,-8*8(r1)
112	ld	r22,-8*9(r1)
113	ld	r23,-8*10(r1)
114	ld	r24,-8*11(r1)
115	ld	r25,-8*12(r1)
116	ld	r26,-8*13(r1)
117	ld	r27,-8*14(r1)
118	ld	r28,-8*15(r1)
119	ld	r29,-8*16(r1)
120	ld	r30,-8*17(r1)
121	ld	r31,-8*18(r1)
122	blr
123
124/*
125 * This is the sequence required to execute idle instructions, as
126 * specified in ISA v2.07 (and earlier). MSR[IR] and MSR[DR] must be 0.
127 *
128 * The 0(r1) slot is used to save r2 in isa206, so use that here.
129 */
130#define IDLE_STATE_ENTER_SEQ_NORET(IDLE_INST)			\
131	/* Magic NAP/SLEEP/WINKLE mode enter sequence */	\
132	std	r2,0(r1);					\
133	ptesync;						\
134	ld	r2,0(r1);					\
135236:	cmpd	cr0,r2,r2;					\
136	bne	236b;						\
137	IDLE_INST;						\
138	b	.	/* catch bugs */
139
140/*
141 * Desired instruction type in r3
142 *
143 * GPRs may be lost, so they are saved here. Wakeup is by interrupt only.
144 * The SRESET wakeup returns to this function's caller by calling
145 * idle_return_gpr_loss with r3 set to desired return value.
146 *
147 * A wakeup without GPR loss may alteratively be handled as in
148 * isa300_idle_stop_noloss and blr directly, as an optimisation.
149 *
150 * The caller is responsible for saving/restoring SPRs, MSR, timebase,
151 * etc.
152 *
153 * This must be called in real-mode (MSR_IDLE).
154 */
155_GLOBAL(isa206_idle_insn_mayloss)
156	std	r1,PACAR1(r13)
157	mflr	r4
158	mfcr	r5
159	/* use stack red zone rather than a new frame for saving regs */
160	std	r2,-8*0(r1)
161	std	r14,-8*1(r1)
162	std	r15,-8*2(r1)
163	std	r16,-8*3(r1)
164	std	r17,-8*4(r1)
165	std	r18,-8*5(r1)
166	std	r19,-8*6(r1)
167	std	r20,-8*7(r1)
168	std	r21,-8*8(r1)
169	std	r22,-8*9(r1)
170	std	r23,-8*10(r1)
171	std	r24,-8*11(r1)
172	std	r25,-8*12(r1)
173	std	r26,-8*13(r1)
174	std	r27,-8*14(r1)
175	std	r28,-8*15(r1)
176	std	r29,-8*16(r1)
177	std	r30,-8*17(r1)
178	std	r31,-8*18(r1)
179	std	r4,-8*19(r1)
180	std	r5,-8*20(r1)
181	cmpwi	r3,PNV_THREAD_NAP
182	bne	1f
183	IDLE_STATE_ENTER_SEQ_NORET(PPC_NAP)
1841:	cmpwi	r3,PNV_THREAD_SLEEP
185	bne	2f
186	IDLE_STATE_ENTER_SEQ_NORET(PPC_SLEEP)
1872:	IDLE_STATE_ENTER_SEQ_NORET(PPC_WINKLE)
188
189