xref: /titanic_44/usr/src/uts/sun4u/opl/ml/drmach_asm.s (revision 49b225e1cfa7bbf7738d4df0a03f18e3283426eb)
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 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * This file is through cpp before being used as
28 * an inline.  It contains support routines used
29 * only by DR for the copy-rename sequence.
30 */
31
32#if defined(lint)
33#include <sys/types.h>
34#else
35#include "assym.h"
36#include "drmach_offsets.h"
37#endif /* lint */
38
39#include <sys/asm_linkage.h>
40#include <sys/param.h>
41#include <sys/privregs.h>
42#include <sys/spitregs.h>
43#include <sys/mmu.h>
44#include <sys/machthread.h>
45#include <sys/pte.h>
46#include <sys/stack.h>
47#include <sys/vis.h>
48#include <sys/intreg.h>
49#include <sys/cheetahregs.h>
50#include <sys/drmach.h>
51#include <sys/sbd_ioctl.h>
52
53#if !defined(lint)
54
55/*
56 * turn off speculative mode to prevent unwanted memory access
57 * when we are in the FMEM loops
58 */
59
60#define	FJSV_SPECULATIVE_OFF(reg, tmp1, tmp2)				\
61	rdpr	%pstate, reg						;\
62	andn	reg, PSTATE_IE, tmp1					;\
63	wrpr	%g0, tmp1, %pstate					;\
64	ldxa	[%g0]ASI_MCNTL, tmp1					;\
65	set	1, tmp2							;\
66	sllx	tmp2, MCNTL_SPECULATIVE_SHIFT, tmp2						;\
67	or	tmp1, tmp2, tmp1					;\
68	stxa	tmp1, [%g0]ASI_MCNTL					;\
69	membar #Sync
70#endif
71
72
73#if defined(lint)
74/*ARGSUSED*/
75void
76drmach_fmem_loop_script(caddr_t critical, int size, caddr_t stat)
77{ return; }
78#else /* lint */
79	.align  8
80	ENTRY_NP(drmach_fmem_loop_script)
81	/* turn off speculative mode */
82	FJSV_SPECULATIVE_OFF(%o5, %o3, %o4);
83
84	/* read the critical region to get everything in the cache */
85	mov	%o0, %o3
860:
87	ldx	[%o3], %o4
88	sub	%o1, 8, %o1
89	brnz	%o1, 0b
90	 add	%o3, 8, %o3
91
92	/* clear L2_CTRL_UGE_TRAP error bit */
93	mov	ASI_L2_CTRL_RW_ADDR, %o1
94	ldxa	[%o1]ASI_L2_CTRL, %o3
95	sethi	%hi(ASI_L2_CTRL_UGE_TRAP), %o4
96	btst	%o3, %o4
97	bz,pn	%xcc, 1f
98	 nop
99	stxa	%o4, [%o1]ASI_L2_CTRL
100
101	/* now tell the master CPU that we are ready */
1021:
103	set	FMEM_LOOP_FMEM_READY, %o3
104	stb	%o3, [%o2]
105	membar #Sync
106	ba	 5f
107	 nop
108
109	/*
110	 * note that we branch to 5f, which branches right back to 2 here.
111	 * The trick is that when that branch instruction has already been
112	 * patched to a branch to itself - an infinite loop.
113	 * The master thread will patch it back to "ba 2b" when it
114	 * completes.
115	 */
116
117	/* Once we are back, we first check if there has been any
118	 * L2_CTRL_UGE_TRAP errors, if so we have to fail the
119	 * operation.  This will cause a panic because the system
120	 * is already in inconsistent state.
121	 */
1222:
123	mov	ASI_L2_CTRL_RW_ADDR, %o3
124	ldxa	[%o3]ASI_L2_CTRL, %o3
125	sethi	%hi(ASI_L2_CTRL_UGE_TRAP), %o4
126	btst	%o3, %o4
127	bz,pn	%xcc, 3f
128	 mov	%g0, %o4
129	set	EOPL_FMEM_HW_ERROR, %o4
130
131	/* set error code and stat code */
1323:
133	set	FMEM_LOOP_DONE, %o3
134	stb	%o3, [%o2]
135
136	/* turn on speculative mode again */
137	ldxa	[%g0]ASI_MCNTL, %o0
138	set	1, %o1
139	sllx	%o1, MCNTL_SPECULATIVE_SHIFT, %o1
140	andn	%o0, %o1, %o0
141	ba	4f
142	 nop
143.align 32
1444:
145	stxa	%o0, [%g0]ASI_MCNTL
146	membar	#Sync
147	wrpr	%g0, %o5, %pstate
148	retl
149	 mov	%o4, %o0
150.align 8
1515:
152	ALTENTRY(drmach_fmem_loop_script_rtn)
153	/*
154	 * busy wait will affect sibling strands so
155	 * we put sleep instruction in the delay slot
156	 */
157	ba	2b
158.word	 0x81b01060
159	SET_SIZE(drmach_fmem_loop_script)
160#endif /* lint */
161
162#if defined(lint)
163/*ARGSUSED*/
164void
165drmach_flush_icache(void)
166{ return; }
167#else /* lint */
168	.align  8
169	ENTRY_NP(drmach_flush_icache)
170	stxa	%g0, [%g0]ASI_ALL_FLUSH_L1I
171	membar	#Sync
172	retl
173	 nop
174	SET_SIZE(drmach_flush_icache)
175#endif
176
177#if defined(lint)
178/*ARGSUSED*/
179int
180drmach_fmem_exec_script(caddr_t critical, int size)
181{ return (0); }
182#else /* lint */
183.align 32
184	ENTRY_NP(drmach_fmem_exec_script)
185	/* turn off speculative mode */
186	FJSV_SPECULATIVE_OFF(%o5, %o3, %o4);
187	/* save locals to save area */
188	add	%o0, SAVE_LOCAL, %o2
189	stx	%l0, [%o2+8*0]
190	stx	%l1, [%o2+8*1]
191	stx	%l2, [%o2+8*2]
192	stx	%l3, [%o2+8*3]
193	stx	%l4, [%o2+8*4]
194	stx	%l5, [%o2+8*5]
195	stx	%l6, [%o2+8*6]
196	stx	%l7, [%o2+8*7]
197	mov	%o5, %l6
198	/* l7 is set only when FMEM cmd is issued to SCF */
199	mov	%g0, %l7
200
201	/* read the critical region to put everything in the cache */
202	mov	%o0, %o2
2030:
204	ldx	[%o2], %o4
205	sub	%o1, 8, %o1
206	brnz	%o1, 0b
207	 add	%o2, 8, %o2
208	ba	4f
209	 nop
210
211	/* we branch to 4f but eventually we branch back here to finish up */
2121:
213	mov	%l6, %o5
214	/*
215	 * save some registers for debugging
216	 * l0 - SCF_REG_BASE
217	 * l1 - SCF_TD
218	 * l2 - SCF_TD + 8
219	 * l5 - DELAY
220	 */
221	add	%o0, SAVE_LOG, %o1
222	stx	%l0, [%o1+8*0]
223	stx	%l1, [%o1+8*1]
224	stx	%l2, [%o1+8*2]
225	stx	%l5, [%o1+8*3]
226
227	add	%o0, FMEM_ISSUED, %o1
228	st	%l7, [%o1]
229
230	/* Check for L2_CTRL_UGE_TRAP error */
231	mov	ASI_L2_CTRL_RW_ADDR, %l0
232	ldxa	[%l0]ASI_L2_CTRL, %l1
233	sethi	%hi(ASI_L2_CTRL_UGE_TRAP), %l2
234	btst	%l1, %l2
235	bz,pn	%xcc, 2f
236	 nop
237	set	EOPL_FMEM_HW_ERROR, %o4
2382:
239	/* restore all locals */
240	add	%o0, SAVE_LOCAL, %o1
241	ldx	[%o1+8*0], %l0
242	ldx	[%o1+8*1], %l1
243	ldx	[%o1+8*2], %l2
244	ldx	[%o1+8*3], %l3
245	ldx	[%o1+8*4], %l4
246	ldx	[%o1+8*5], %l5
247	ldx	[%o1+8*6], %l6
248	ldx	[%o1+8*7], %l7
249
250	/* turn on speculative mode */
251	ldxa	[%g0]ASI_MCNTL, %o1
252	set	1, %o2
253	sllx	%o2, MCNTL_SPECULATIVE_SHIFT, %o2
254	andn	%o1, %o2, %o1
255	ba	3f
256	 nop
257.align 32
2583:
259	stxa	%o1, [%g0]ASI_MCNTL
260	membar	#Sync
261	/* return error code here */
262	mov	%o4, %o0
263	retl
264	 wrpr	%g0, %o5, %pstate
265
266	/* clear L2_CTRL_UGE_TRAP error bit */
2674:
268	mov	ASI_L2_CTRL_RW_ADDR, %l0
269	ldxa	[%l0]ASI_L2_CTRL, %l1
270	sethi	%hi(ASI_L2_CTRL_UGE_TRAP), %l2
271	btst	%l1, %l2
272	bz,pn	%xcc, 5f
273	 nop
274	stxa	%l2, [%l0]ASI_L2_CTRL
2755:
276	/* set up the register locations and parameters */
277	ldx	[%o0 + SCF_REG_BASE], %l0
278	ldx	[%o0 + SCF_TD], %l1
279	ldx	[%o0 + SCF_TD+8], %l2
280	ldx	[%o0 + DELAY], %l5
281
282	/* check if SCF is ONLINE */
283	add	%l0, SCF_STATUS_EX, %o1
284	lduwa	[%o1]ASI_IO, %o2
285	sethi	%hi(SCF_STATUS_EX_ONLINE), %o3
286	btst	%o2, %o3
287	bne	%xcc, 6f
288	 nop
289	set	EOPL_FMEM_SCF_OFFLINE, %o4
290	ba	1b
291	 nop
292
293	/* check if SCF is busy */
294	add	%l0, SCF_COMMAND, %o1
295	lduha	[%o1]ASI_IO, %o2
296	sethi	%hi(SCF_CMD_BUSY), %o3
297	btst	%o2, %o3
298	be	%xcc, 6f
299	 nop
300	set	EOPL_FMEM_SCF_BUSY, %o4
301	ba	1b
302	 nop
303
304	/* clear STATUS bit */
3056:
306	add	%l0, SCF_STATUS, %o1
307	lduha	[%o1]ASI_IO, %o2
308	sethi	%hi(SCF_STATUS_READY), %o3
309	btst	%o2, %o3
310	be	%xcc, 7f
311	 nop
312	stha	%o3, [%o1]ASI_IO
313
314	/* clear CMD_COMPLETE bit */
3157:
316	mov	SCF_STATUS_CMD_COMPLETE, %o3
317	btst	%o2, %o3
318	be,a	%xcc, 8f
319	 nop
320	stha	%o3, [%o1]ASI_IO
3218:
322	add	%l0, (SCF_TDATA+0xe), %o1
323	mov	%l2, %o4
324	mov	SCF_RETRY_CNT, %o5
325
326	sethi	%hi(0xffff), %l2
327	or	%l2, %lo(0xffff), %l2
328
329	and	%o4, %l2, %o3
330
331	/*
332	 * o1 points to SCFBASE.SCF_TDATA[0xe]
333	 * l0 points to SCFBASE
334	 * crticial->SCF_TD[0] = source board #
335	 * crticial->SCF_TD[1] = target board #
336	 * l1 = critical->SCF_TD[0 - 7]
337	 * l2 = 0xffff
338	 * o4 = critical->SCF_TD[8 - 15]
339	 * o3 = (*o4) & 0xffff
340
341	/*
342	 * Because there is no parity protection on the ebus
343	 * we read the data back after the write to verify
344	 * we write 2 bytes at a time.
345	 * If the data read is not the same as data written
346	 * we retry up to a limit of SCF_RETRY_CNT
347	 */
3489:
349	stha	%o3, [%o1]ASI_IO
350	lduha	[%o1]ASI_IO, %o2
351	sub	%o5, 1, %o5
352	brnz	%o5, 7f
353	 nop
354	set	EOPL_FMEM_RETRY_OUT, %o4
355	ba	1b
356	 nop
3577:
358	cmp	%o2, %o3
359	bne,a	9b
360	 nop
361
362	sub	%o1, %l0, %o2
363	cmp	%o2, (SCF_TDATA+0x8)
364	bne	%xcc, 2f
365	 srlx	%o4, 16, %o4
366	mov	%l1, %o4
367
368	/* if we have reach TDATA+8, we switch to l1 */
369	/* XXX: Why we need 2 loops??? */
3702:
371	sub	%o1, 2, %o1
372	mov	SCF_RETRY_CNT, %o5
373	and	%o4, %l2, %o3
374
375	sub	%o1, %l0, %o2
376	cmp	%o2, (SCF_TDATA)
377	bge,a	9b
378	 nop
379
380	/* if we reach TDATA, we are done */
381
382	/* read from SCF back to our buffer for debugging */
383	add	%l0, (SCF_TDATA), %o1
384	ldxa	[%o1]ASI_IO, %o2
385	stx	%o2, [%o0+SCF_TD]
386
387	add	%l0, (SCF_TDATA+8), %o1
388	ldxa	[%o1]ASI_IO, %o2
389	stx	%o2, [%o0+SCF_TD+8]
390
391	/* The following code conforms to the FMEM
392	   sequence (4) as described in the Columbus2
393	   logical spec section 4.6
394	*/
395
396	/* read from SCF SB INFO register */
397	sethi	%hi(SCF_SB_INFO_OFFSET), %o2
398	or	%o2, %lo(SCF_SB_INFO_OFFSET), %o2
399	add	%l0, %o2, %o1
400	lduba	[%o1]ASI_IO, %o2
401
402	/* If BUSY bit is set, abort */
403	or	%g0, (SCF_SB_INFO_BUSY), %o1
404	btst	%o1, %o2
405	set	EOPL_FMEM_SCF_BUSY, %o4
406	bne	1b
407	 nop
408
409	rd	STICK, %l1
410	add	%l5, %l1, %l5
411
412	/* Now tell SCF to do it */
413	add	%l0, SCF_COMMAND, %o1
414
415	/* 0x10A6 is the magic command */
416	sethi	%hi(0x10A6), %o2
417	or	%o2, %lo(0x10A6), %o2
418	stha	%o2, [%o1]ASI_IO
419
420	mov	1, %l7			! FMEM is issued
421
422	add	%l0, SCF_STATUS, %o1
423	sethi	%hi(SCF_STATUS_READY), %o2
424	mov	SCF_STATUS_CMD_COMPLETE, %o3
425
426	/* read STATUS_READY bit and clear it only if it is set */
427	/* XXX: this STATUS_READY checking seems meaningless */
4283:
429	lduha	[%o1]ASI_IO, %o4
430	btst	%o2, %o4
431	be	%xcc, 4f		! STATUS_READY is not set
432	 nop
433	stha	%o2, [%o1]ASI_IO	! Clear if the bit is set
434
435	/* check CMD_COMPLETE bit and clear */
4364:
437	btst	%o3, %o4
438	be	%xcc, 5f		! CMD_COMPLETE is not set
439	 nop
440	stha	%o3, [%o1]ASI_IO	! Now we are done and clear it
441	ba	%xcc, 6f
442	 mov	ESBD_NOERROR, %o4
443
444	/* timeout delay checking */
4455:
446	rd	STICK, %l2
447	cmp	%l5, %l2
448	bge	%xcc, 3b
449	 nop
450	set	EOPL_FMEM_TIMEOUT, %o4
451
452	/* we are done or timed out */
4536:
454	ba,a	1b
455	 nop
456	SET_SIZE(drmach_fmem_exec_script)
457#endif /* lint */
458
459#if defined(lint)
460/*ARGSUSED*/
461void
462drmach_fmem_exec_script_end(caddr_t critical, int size)
463{ return; }
464#else /* lint */
465	ENTRY_NP(drmach_fmem_exec_script_end)
466	nop
467	SET_SIZE(drmach_fmem_exec_script_end)
468#endif /* lint */
469
470#if defined(lint)
471uint64_t
472patch_inst(uint64_t *x, uint64_t y)
473{
474	*x = y;
475	return (0);
476}
477
478#else   /* lint */
479
480	ENTRY_NP(patch_inst)
481	ldx	[%o0], %o2
482	casx	[%o0], %o2, %o1
483	flush	%o0
484	membar #Sync
485	ldx	[%o0], %o2
486	retl
487	 mov	%o2, %o0
488	SET_SIZE(patch_inst)
489
490#endif /* lint */
491
492#if defined(lint)
493void
494drmach_sys_trap()
495{
496}
497#else   /* lint */
498	ENTRY_NP(drmach_sys_trap)
499	mov	-1, %g4
500	set	sys_trap, %g5
501	jmp	%g5
502	 nop
503	SET_SIZE(drmach_sys_trap)
504#endif /* lint */
505
506#if defined(lint)
507uint64_t
508drmach_get_stick()
509{
510	return (0);
511}
512#else   /* lint */
513	ENTRY_NP(drmach_get_stick)
514	retl
515	rd	STICK, %o0
516	SET_SIZE(drmach_get_stick)
517#endif /* lint */
518
519#if defined(lint)
520/*ARGSUSED*/
521void
522drmach_flush(void)
523{}
524
525#else /* lint */
526	ENTRY_NP(drmach_flush)
527	mov	%o0, %o2
5280:
529	flush	%o2
530	sub	%o1, 8, %o1
531	brnz	%o1, 0b
532	 add	%o2, 8, %o2
533	retl
534	 nop
535	SET_SIZE(drmach_flush)
536#endif /* lint */
537