xref: /illumos-gate/usr/src/uts/sun4u/opl/ml/drmach_asm.S (revision 5d9d9091f564c198a760790b0bfa72c44e17912b)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * This file is through cpp before being used as
29 * an inline.  It contains support routines used
30 * only by DR for the copy-rename sequence.
31 */
32
33#include "assym.h"
34#include "drmach_offsets.h"
35
36#include <sys/asm_linkage.h>
37#include <sys/param.h>
38#include <sys/privregs.h>
39#include <sys/spitregs.h>
40#include <sys/mmu.h>
41#include <sys/machthread.h>
42#include <sys/pte.h>
43#include <sys/stack.h>
44#include <sys/vis.h>
45#include <sys/intreg.h>
46#include <sys/cheetahregs.h>
47#include <sys/drmach.h>
48#include <sys/sbd_ioctl.h>
49
50/*
51 * turn off speculative mode to prevent unwanted memory access
52 * when we are in the FMEM loops
53 */
54
55#define	FJSV_SPECULATIVE_OFF(reg, tmp1, tmp2)				\
56	rdpr	%pstate, reg						;\
57	andn	reg, PSTATE_IE, tmp1					;\
58	wrpr	%g0, tmp1, %pstate					;\
59	ldxa	[%g0]ASI_MCNTL, tmp1					;\
60	set	1, tmp2							;\
61	sllx	tmp2, MCNTL_SPECULATIVE_SHIFT, tmp2						;\
62	or	tmp1, tmp2, tmp1					;\
63	stxa	tmp1, [%g0]ASI_MCNTL					;\
64	membar #Sync
65
66
67	.align  8
68	ENTRY_NP(drmach_fmem_loop_script)
69	/* turn off speculative mode */
70	FJSV_SPECULATIVE_OFF(%o5, %o3, %o4);
71
72	/* read the critical region to get everything in the cache */
73	mov	%o0, %o3
740:
75	ldx	[%o3], %o4
76	sub	%o1, 8, %o1
77	brnz	%o1, 0b
78	 add	%o3, 8, %o3
79
80	/* clear L2_CTRL_UGE_TRAP error bit */
81	mov	ASI_L2_CTRL_RW_ADDR, %o1
82	ldxa	[%o1]ASI_L2_CTRL, %o3
83	sethi	%hi(ASI_L2_CTRL_UGE_TRAP), %o4
84	btst	%o3, %o4
85	bz,pn	%xcc, 1f
86	 nop
87	stxa	%o4, [%o1]ASI_L2_CTRL
88
89	/* now tell the master CPU that we are ready */
901:
91	set	FMEM_LOOP_FMEM_READY, %o3
92	stb	%o3, [%o2]
93	membar #Sync
94	ba	 5f
95	 nop
96
97	/*
98	 * note that we branch to 5f, which branches right back to 2 here.
99	 * The trick is that when that branch instruction has already been
100	 * patched to a branch to itself - an infinite loop.
101	 * The master thread will patch it back to "ba 2b" when it
102	 * completes.
103	 */
104
105	/* Once we are back, we first check if there has been any
106	 * L2_CTRL_UGE_TRAP errors, if so we have to fail the
107	 * operation.  This will cause a panic because the system
108	 * is already in inconsistent state.
109	 */
1102:
111	mov	ASI_L2_CTRL_RW_ADDR, %o3
112	ldxa	[%o3]ASI_L2_CTRL, %o3
113	sethi	%hi(ASI_L2_CTRL_UGE_TRAP), %o4
114	btst	%o3, %o4
115	bz,pn	%xcc, 3f
116	 mov	%g0, %o4
117	set	EOPL_FMEM_HW_ERROR, %o4
118
119	/* set error code and stat code */
1203:
121	set	FMEM_LOOP_DONE, %o3
122	stb	%o3, [%o2]
123
124	/* turn on speculative mode again */
125	ldxa	[%g0]ASI_MCNTL, %o0
126	set	1, %o1
127	sllx	%o1, MCNTL_SPECULATIVE_SHIFT, %o1
128	andn	%o0, %o1, %o0
129	ba	4f
130	 nop
131.align 32
1324:
133	stxa	%o0, [%g0]ASI_MCNTL
134	membar	#Sync
135	wrpr	%g0, %o5, %pstate
136	retl
137	 mov	%o4, %o0
138.align 8
1395:
140	ALTENTRY(drmach_fmem_loop_script_rtn)
141	/*
142	 * busy wait will affect sibling strands so
143	 * we put sleep instruction in the delay slot
144	 */
145	ba	2b
146.word	 0x81b01060
147	SET_SIZE(drmach_fmem_loop_script)
148
149	.align  8
150	ENTRY_NP(drmach_flush_icache)
151	stxa	%g0, [%g0]ASI_ALL_FLUSH_L1I
152	membar	#Sync
153	retl
154	 nop
155	SET_SIZE(drmach_flush_icache)
156
157.align 32
158	ENTRY_NP(drmach_fmem_exec_script)
159	/* turn off speculative mode */
160	FJSV_SPECULATIVE_OFF(%o5, %o3, %o4);
161	/* save locals to save area */
162	add	%o0, SAVE_LOCAL, %o2
163	stx	%l0, [%o2+8*0]
164	stx	%l1, [%o2+8*1]
165	stx	%l2, [%o2+8*2]
166	stx	%l3, [%o2+8*3]
167	stx	%l4, [%o2+8*4]
168	stx	%l5, [%o2+8*5]
169	stx	%l6, [%o2+8*6]
170	stx	%l7, [%o2+8*7]
171	mov	%o5, %l6
172	/* l7 is set only when FMEM cmd is issued to SCF */
173	mov	%g0, %l7
174
175	/* read the critical region to put everything in the cache */
176	mov	%o0, %o2
1770:
178	ldx	[%o2], %o4
179	sub	%o1, 8, %o1
180	brnz	%o1, 0b
181	 add	%o2, 8, %o2
182	ba	4f
183	 nop
184
185	/* we branch to 4f but eventually we branch back here to finish up */
1861:
187	mov	%l6, %o5
188	/*
189	 * save some registers for debugging
190	 * l0 - SCF_REG_BASE
191	 * l1 - SCF_TD
192	 * l2 - SCF_TD + 8
193	 * l5 - DELAY
194	 */
195	add	%o0, SAVE_LOG, %o1
196	stx	%l0, [%o1+8*0]
197	stx	%l1, [%o1+8*1]
198	stx	%l2, [%o1+8*2]
199	stx	%l5, [%o1+8*3]
200
201	add	%o0, FMEM_ISSUED, %o1
202	st	%l7, [%o1]
203
204	/* Check for L2_CTRL_UGE_TRAP error */
205	mov	ASI_L2_CTRL_RW_ADDR, %l0
206	ldxa	[%l0]ASI_L2_CTRL, %l1
207	sethi	%hi(ASI_L2_CTRL_UGE_TRAP), %l2
208	btst	%l1, %l2
209	bz,pn	%xcc, 2f
210	 nop
211	set	EOPL_FMEM_HW_ERROR, %o4
2122:
213	/* restore all locals */
214	add	%o0, SAVE_LOCAL, %o1
215	ldx	[%o1+8*0], %l0
216	ldx	[%o1+8*1], %l1
217	ldx	[%o1+8*2], %l2
218	ldx	[%o1+8*3], %l3
219	ldx	[%o1+8*4], %l4
220	ldx	[%o1+8*5], %l5
221	ldx	[%o1+8*6], %l6
222	ldx	[%o1+8*7], %l7
223
224	/* turn on speculative mode */
225	ldxa	[%g0]ASI_MCNTL, %o1
226	set	1, %o2
227	sllx	%o2, MCNTL_SPECULATIVE_SHIFT, %o2
228	andn	%o1, %o2, %o1
229	ba	3f
230	 nop
231.align 32
2323:
233	stxa	%o1, [%g0]ASI_MCNTL
234	membar	#Sync
235	/* return error code here */
236	mov	%o4, %o0
237	retl
238	 wrpr	%g0, %o5, %pstate
239
240	/* clear L2_CTRL_UGE_TRAP error bit */
2414:
242	mov	ASI_L2_CTRL_RW_ADDR, %l0
243	ldxa	[%l0]ASI_L2_CTRL, %l1
244	sethi	%hi(ASI_L2_CTRL_UGE_TRAP), %l2
245	btst	%l1, %l2
246	bz,pn	%xcc, 5f
247	 nop
248	stxa	%l2, [%l0]ASI_L2_CTRL
2495:
250	/* set up the register locations and parameters */
251	ldx	[%o0 + SCF_REG_BASE], %l0
252	ldx	[%o0 + SCF_TD], %l1
253	ldx	[%o0 + SCF_TD+8], %l2
254	ldx	[%o0 + DELAY], %l5
255
256	/* check if SCF is ONLINE */
257	add	%l0, SCF_STATUS_EX, %o1
258	lduwa	[%o1]ASI_IO, %o2
259	sethi	%hi(SCF_STATUS_EX_ONLINE), %o3
260	btst	%o2, %o3
261	bne	%xcc, 6f
262	 nop
263	set	EOPL_FMEM_SCF_OFFLINE, %o4
264	ba	1b
265	 nop
266
267	/* check if SCF is busy */
268	add	%l0, SCF_COMMAND, %o1
269	lduha	[%o1]ASI_IO, %o2
270	sethi	%hi(SCF_CMD_BUSY), %o3
271	btst	%o2, %o3
272	be	%xcc, 6f
273	 nop
274	set	EOPL_FMEM_SCF_BUSY, %o4
275	ba	1b
276	 nop
277
278	/* clear STATUS bit */
2796:
280	add	%l0, SCF_STATUS, %o1
281	lduha	[%o1]ASI_IO, %o2
282	sethi	%hi(SCF_STATUS_READY), %o3
283	btst	%o2, %o3
284	be	%xcc, 7f
285	 nop
286	stha	%o3, [%o1]ASI_IO
287
288	/* clear CMD_COMPLETE bit */
2897:
290	mov	SCF_STATUS_CMD_COMPLETE, %o3
291	btst	%o2, %o3
292	be,a	%xcc, 8f
293	 nop
294	stha	%o3, [%o1]ASI_IO
2958:
296	add	%l0, (SCF_TDATA+0xe), %o1
297	mov	%l2, %o4
298	mov	SCF_RETRY_CNT, %o5
299
300	sethi	%hi(0xffff), %l2
301	or	%l2, %lo(0xffff), %l2
302
303	and	%o4, %l2, %o3
304
305	/*
306	 * o1 points to SCFBASE.SCF_TDATA[0xe]
307	 * l0 points to SCFBASE
308	 * crticial->SCF_TD[0] = source board #
309	 * crticial->SCF_TD[1] = target board #
310	 * l1 = critical->SCF_TD[0 - 7]
311	 * l2 = 0xffff
312	 * o4 = critical->SCF_TD[8 - 15]
313	 * o3 = (*o4) & 0xffff
314
315	/*
316	 * Because there is no parity protection on the ebus
317	 * we read the data back after the write to verify
318	 * we write 2 bytes at a time.
319	 * If the data read is not the same as data written
320	 * we retry up to a limit of SCF_RETRY_CNT
321	 */
3229:
323	stha	%o3, [%o1]ASI_IO
324	lduha	[%o1]ASI_IO, %o2
325	sub	%o5, 1, %o5
326	brnz	%o5, 7f
327	 nop
328	set	EOPL_FMEM_RETRY_OUT, %o4
329	ba	1b
330	 nop
3317:
332	cmp	%o2, %o3
333	bne,a	9b
334	 nop
335
336	sub	%o1, %l0, %o2
337	cmp	%o2, (SCF_TDATA+0x8)
338	bne	%xcc, 2f
339	 srlx	%o4, 16, %o4
340	mov	%l1, %o4
341
342	/* if we have reach TDATA+8, we switch to l1 */
343	/* XXX: Why we need 2 loops??? */
3442:
345	sub	%o1, 2, %o1
346	mov	SCF_RETRY_CNT, %o5
347	and	%o4, %l2, %o3
348
349	sub	%o1, %l0, %o2
350	cmp	%o2, (SCF_TDATA)
351	bge,a	9b
352	 nop
353
354	/* if we reach TDATA, we are done */
355
356	/* read from SCF back to our buffer for debugging */
357	add	%l0, (SCF_TDATA), %o1
358	ldxa	[%o1]ASI_IO, %o2
359	stx	%o2, [%o0+SCF_TD]
360
361	add	%l0, (SCF_TDATA+8), %o1
362	ldxa	[%o1]ASI_IO, %o2
363	stx	%o2, [%o0+SCF_TD+8]
364
365	/* The following code conforms to the FMEM
366	   sequence (4) as described in the Columbus2
367	   logical spec section 4.6
368	*/
369
370	/* read from SCF SB INFO register */
371	sethi	%hi(SCF_SB_INFO_OFFSET), %o2
372	or	%o2, %lo(SCF_SB_INFO_OFFSET), %o2
373	add	%l0, %o2, %o1
374	lduba	[%o1]ASI_IO, %o2
375
376	/* If BUSY bit is set, abort */
377	or	%g0, (SCF_SB_INFO_BUSY), %o1
378	btst	%o1, %o2
379	set	EOPL_FMEM_SCF_BUSY, %o4
380	bne	1b
381	 nop
382
383	rd	STICK, %l1
384	add	%l5, %l1, %l5
385
386	/* Now tell SCF to do it */
387	add	%l0, SCF_COMMAND, %o1
388
389	/* 0x10A6 is the magic command */
390	sethi	%hi(0x10A6), %o2
391	or	%o2, %lo(0x10A6), %o2
392	stha	%o2, [%o1]ASI_IO
393
394	mov	1, %l7			! FMEM is issued
395
396	add	%l0, SCF_STATUS, %o1
397	sethi	%hi(SCF_STATUS_READY), %o2
398	mov	SCF_STATUS_CMD_COMPLETE, %o3
399
400	/* read STATUS_READY bit and clear it only if it is set */
401	/* XXX: this STATUS_READY checking seems meaningless */
4023:
403	lduha	[%o1]ASI_IO, %o4
404	btst	%o2, %o4
405	be	%xcc, 4f		! STATUS_READY is not set
406	 nop
407	stha	%o2, [%o1]ASI_IO	! Clear if the bit is set
408
409	/* check CMD_COMPLETE bit and clear */
4104:
411	btst	%o3, %o4
412	be	%xcc, 5f		! CMD_COMPLETE is not set
413	 nop
414	stha	%o3, [%o1]ASI_IO	! Now we are done and clear it
415	ba	%xcc, 6f
416	 mov	ESBD_NOERROR, %o4
417
418	/* timeout delay checking */
4195:
420	rd	STICK, %l2
421	cmp	%l5, %l2
422	bge	%xcc, 3b
423	 nop
424	set	EOPL_FMEM_TIMEOUT, %o4
425
426	/* we are done or timed out */
4276:
428	ba,a	1b
429	 nop
430	SET_SIZE(drmach_fmem_exec_script)
431
432	ENTRY_NP(drmach_fmem_exec_script_end)
433	nop
434	SET_SIZE(drmach_fmem_exec_script_end)
435
436	ENTRY_NP(patch_inst)
437	ldx	[%o0], %o2
438	casx	[%o0], %o2, %o1
439	flush	%o0
440	membar #Sync
441	ldx	[%o0], %o2
442	retl
443	 mov	%o2, %o0
444	SET_SIZE(patch_inst)
445
446	ENTRY_NP(drmach_sys_trap)
447	mov	-1, %g4
448	set	sys_trap, %g5
449	jmp	%g5
450	 nop
451	SET_SIZE(drmach_sys_trap)
452
453	ENTRY_NP(drmach_get_stick)
454	retl
455	rd	STICK, %o0
456	SET_SIZE(drmach_get_stick)
457
458	ENTRY_NP(drmach_flush)
459	mov	%o0, %o2
4600:
461	flush	%o2
462	sub	%o1, 8, %o1
463	brnz	%o1, 0b
464	 add	%o2, 8, %o2
465	retl
466	 nop
467	SET_SIZE(drmach_flush)
468