1/* Copyright 2013-2014 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * 	http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <asm-utils.h>
18#include <asm-offsets.h>
19#include <processor.h>
20#include <stack.h>
21
22#define OLD_BINUTILS 1
23
24	.section ".text","ax"
25	.balign	0x10
26
27.global enable_machine_check
28enable_machine_check:
29	mflr	%r0
30	bcl	20,31,$+4
310:	mflr	%r3
32	addi	%r3,%r3,(1f - 0b)
33	mtspr	SPR_HSRR0,%r3
34	mfmsr	%r3
35	ori	%r3,%r3,MSR_ME
36	mtspr	SPR_HSRR1,%r3
37	hrfid
381:	mtlr	%r0
39	blr
40
41.global disable_machine_check
42disable_machine_check:
43	mflr	%r0
44	bcl	20,31,$+4
450:	mflr	%r3
46	addi	%r3,%r3,(1f - 0b)
47	mtspr	SPR_HSRR0,%r3
48	mfmsr	%r3
49	li	%r4,MSR_ME
50	andc	%r3,%r3,%r4
51	mtspr	SPR_HSRR1,%r3
52	hrfid
531:	mtlr	%r0
54	blr
55
56	/* void set_hid0(unsigned long hid0) */
57.global set_hid0
58set_hid0:
59	sync
60	mtspr	SPR_HID0,%r3
61	mfspr	%r3,SPR_HID0
62	mfspr	%r3,SPR_HID0
63	mfspr	%r3,SPR_HID0
64	mfspr	%r3,SPR_HID0
65	mfspr	%r3,SPR_HID0
66	mfspr	%r3,SPR_HID0
67	isync
68	blr
69
70.global __trigger_attn
71__trigger_attn:
72	sync
73	isync
74	attn
75	blr
76
77#ifdef STACK_CHECK_ENABLED
78.global _mcount
79_mcount:
80	mr	%r3,%r1
81	mflr	%r4
82	b	__mcount_stack_check
83#endif
84
85	.global cleanup_local_tlb
86cleanup_local_tlb:
87	/* Clean the TLB */
88	li	%r3,512
89	mtctr	%r3
90	li	%r4,0xc00		/* IS field = 0b11 */
91	ptesync
921:	tlbiel	%r4
93	addi	%r4,%r4,0x1000
94	bdnz	1b
95	ptesync
96	blr
97
98	.global cleanup_global_tlb
99cleanup_global_tlb:
100
101	/* Only supported on P9 for now */
102	mfspr	%r3,SPR_PVR
103	srdi	%r3,%r3,16
104	cmpwi	cr0,%r3,PVR_TYPE_P9
105	beq	cr0,1f
106	cmpwi	cr0,%r3,PVR_TYPE_P9P
107	beq	cr0,1f
108	blr
109
110	/* Sync out previous updates */
1111:	ptesync
112
113#ifndef OLD_BINUTILS
114	.machine "power9"
115#endif
116	/* Lead RB with IS=11 */
117	li	%r3,3
118	sldi	%r3,%r3,10
119	li	%r0,0
120
121	/* Blow up radix partition scoped translations */
122#ifdef OLD_BINUTILS
123	.long   0x7c0b1a64
124#else
125	tlbie	%r3, %r0 /* rs */, 2 /* ric */, 1 /* prs */, 1 /* r */
126#endif
127	eieio
128	tlbsync
129	ptesync
130#ifdef OLD_BINUTILS
131	.long   0x7c091a64
132#else
133	tlbie	%r3, %r0 /* rs */, 2 /* ric */, 0 /* prs */, 1 /* r */
134#endif
135	eieio
136	tlbsync
137	ptesync
138
139	/* Blow up hash partition scoped translations */
140#ifdef OLD_BINUTILS
141	.long   0x7c0a1a64
142#else
143	tlbie	%r3, %r0 /* rs */, 2 /* ric */, 1 /* prs */, 0 /* r */
144#endif
145	eieio
146	tlbsync
147	ptesync
148#ifdef OLD_BINUTILS
149	.long   0x7c081a64
150#else
151	tlbie	%r3, %r0 /* rs */, 2 /* ric */, 0 /* prs */, 0 /* r */
152#endif
153	eieio
154	tlbsync
155	ptesync
156
157	blr
158
159
160/* Power management instructions */
161#define PPC_INST_NAP		.long 0x4c000364
162#define PPC_INST_SLEEP		.long 0x4c0003a4
163#define PPC_INST_RVWINKLE	.long 0x4c0003e4
164
165#define PPC_INST_STOP		.long 0x4c0002e4
166
167#define SAVE_GPR(reg,sp)	std %r##reg,STACK_GPR##reg(sp)
168#define REST_GPR(reg,sp)	ld %r##reg,STACK_GPR##reg(sp)
169
170pm_save_regs:
171	SAVE_GPR(2,%r1)
172	SAVE_GPR(14,%r1)
173	SAVE_GPR(15,%r1)
174	SAVE_GPR(16,%r1)
175	SAVE_GPR(17,%r1)
176	SAVE_GPR(18,%r1)
177	SAVE_GPR(19,%r1)
178	SAVE_GPR(20,%r1)
179	SAVE_GPR(21,%r1)
180	SAVE_GPR(22,%r1)
181	SAVE_GPR(23,%r1)
182	SAVE_GPR(24,%r1)
183	SAVE_GPR(25,%r1)
184	SAVE_GPR(26,%r1)
185	SAVE_GPR(27,%r1)
186	SAVE_GPR(28,%r1)
187	SAVE_GPR(29,%r1)
188	SAVE_GPR(30,%r1)
189	SAVE_GPR(31,%r1)
190	mfcr	%r4
191	mfxer	%r5
192	mfspr	%r6,SPR_HSPRG0
193	mfspr	%r7,SPR_HSPRG1
194	stw	%r4,STACK_CR(%r1)
195	stw	%r5,STACK_XER(%r1)
196	std	%r6,STACK_GPR0(%r1)
197	std	%r7,STACK_GPR1(%r1)
198	blr
199
200.global enter_p8_pm_state
201enter_p8_pm_state:
202	/* Before entering map or rvwinkle, we create a stack frame
203	 * and save our non-volatile registers.
204	 *
205	 * We also save these SPRs:
206	 *
207	 *  - HSPRG0	in GPR0 slot
208	 *  - HSPRG1	in GPR1 slot
209	 *
210	 *  - xxx TODO: HIDs
211	 *  - TODO: Mask MSR:ME during the process
212	 *
213	 * On entry, r3 indicates:
214	 *
215	 *    0 = nap
216	 *    1 = rvwinkle
217	 */
218	mflr	%r0
219	std	%r0,16(%r1)
220	stdu	%r1,-STACK_FRAMESIZE(%r1)
221
222	bl	pm_save_regs
223
224	/* Save stack pointer in struct cpu_thread */
225	std	%r1,CPUTHREAD_SAVE_R1(%r13)
226
227	/* Winkle or nap ? */
228	cmpli	%cr0,0,%r3,0
229	bne	1f
230
231	/* nap sequence */
232	ptesync
2330:	ld	%r0,CPUTHREAD_SAVE_R1(%r13)
234	cmpd	cr0,%r0,%r0
235	bne	0b
236	PPC_INST_NAP
237	b	.
238
239	/* rvwinkle sequence */
2401:	ptesync
2410:	ld	%r0,CPUTHREAD_SAVE_R1(%r13)
242	cmpd	cr0,%r0,%r0
243	bne	0b
244	PPC_INST_RVWINKLE
245	b	.
246
247.global enter_p9_pm_lite_state
248enter_p9_pm_lite_state:
249	mtspr	SPR_PSSCR,%r3
250	PPC_INST_STOP
251	blr
252
253.global enter_p9_pm_state
254enter_p9_pm_state:
255	mflr	%r0
256	std	%r0,16(%r1)
257	stdu	%r1,-STACK_FRAMESIZE(%r1)
258
259	bl	pm_save_regs
260
261	/* Save stack pointer in struct cpu_thread */
262	std	%r1,CPUTHREAD_SAVE_R1(%r13)
263
264	mtspr	SPR_PSSCR,%r3
265	PPC_INST_STOP
266	b	.
267