xref: /illumos-gate/usr/src/uts/sun4u/cpu/opl_olympus_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 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Assembly code support for the Olympus-C module
26 */
27
28#include "assym.h"
29
30#include <sys/asm_linkage.h>
31#include <sys/mmu.h>
32#include <vm/hat_sfmmu.h>
33#include <sys/machparam.h>
34#include <sys/machcpuvar.h>
35#include <sys/machthread.h>
36#include <sys/machtrap.h>
37#include <sys/privregs.h>
38#include <sys/asm_linkage.h>
39#include <sys/trap.h>
40#include <sys/opl_olympus_regs.h>
41#include <sys/opl_module.h>
42#include <sys/xc_impl.h>
43#include <sys/intreg.h>
44#include <sys/async.h>
45#include <sys/clock.h>
46#include <sys/cmpregs.h>
47
48#ifdef TRAPTRACE
49#include <sys/traptrace.h>
50#endif /* TRAPTRACE */
51
52/*
53 * Macro that flushes the entire Ecache.
54 *
55 * arg1 = ecache size
56 * arg2 = ecache linesize
57 * arg3 = ecache flush address - Not used for olympus-C
58 */
59#define	ECACHE_FLUSHALL(arg1, arg2, arg3, tmp1)				\
60	mov	ASI_L2_CTRL_U2_FLUSH, arg1;				\
61	mov	ASI_L2_CTRL_RW_ADDR, arg2;				\
62	stxa	arg1, [arg2]ASI_L2_CTRL
63
64/*
65 * SPARC64-VI MMU and Cache operations.
66 */
67
68	ENTRY_NP(vtag_flushpage)
69	/*
70	 * flush page from the tlb
71	 *
72	 * %o0 = vaddr
73	 * %o1 = sfmmup
74	 */
75	rdpr	%pstate, %o5
76#ifdef DEBUG
77	PANIC_IF_INTR_DISABLED_PSTR(%o5, opl_di_l3, %g1)
78#endif /* DEBUG */
79	/*
80	 * disable ints
81	 */
82	andn	%o5, PSTATE_IE, %o4
83	wrpr	%o4, 0, %pstate
84
85	/*
86	 * Then, blow out the tlb
87	 * Interrupts are disabled to prevent the primary ctx register
88	 * from changing underneath us.
89	 */
90	sethi   %hi(ksfmmup), %o3
91        ldx     [%o3 + %lo(ksfmmup)], %o3
92        cmp     %o3, %o1
93        bne,pt   %xcc, 1f			! if not kernel as, go to 1
94	  sethi	%hi(FLUSH_ADDR), %o3
95	/*
96	 * For Kernel demaps use primary. type = page implicitly
97	 */
98	stxa	%g0, [%o0]ASI_DTLB_DEMAP	/* dmmu flush for KCONTEXT */
99	stxa	%g0, [%o0]ASI_ITLB_DEMAP	/* immu flush for KCONTEXT */
100	flush	%o3
101	retl
102	  wrpr	%g0, %o5, %pstate		/* enable interrupts */
1031:
104	/*
105	 * User demap.  We need to set the primary context properly.
106	 * Secondary context cannot be used for SPARC64-VI IMMU.
107	 * %o0 = vaddr
108	 * %o1 = sfmmup
109	 * %o3 = FLUSH_ADDR
110	 */
111	SFMMU_CPU_CNUM(%o1, %g1, %g2)		! %g1 = sfmmu cnum on this CPU
112
113	ldub	[%o1 + SFMMU_CEXT], %o4		! %o4 = sfmmup->sfmmu_cext
114	sll	%o4, CTXREG_EXT_SHIFT, %o4
115	or	%g1, %o4, %g1			! %g1 = primary pgsz | cnum
116
117	wrpr	%g0, 1, %tl
118	set	MMU_PCONTEXT, %o4
119	or	DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %o0, %o0
120	ldxa	[%o4]ASI_DMMU, %o2		! %o2 = save old ctxnum
121	srlx	%o2, CTXREG_NEXT_SHIFT, %o1	! need to preserve nucleus pgsz
122	sllx	%o1, CTXREG_NEXT_SHIFT, %o1	! %o1 = nucleus pgsz
123	or	%g1, %o1, %g1			! %g1 = nucleus pgsz | primary pgsz | cnum
124	stxa	%g1, [%o4]ASI_DMMU		! wr new ctxum
125
126	stxa	%g0, [%o0]ASI_DTLB_DEMAP
127	stxa	%g0, [%o0]ASI_ITLB_DEMAP
128	stxa	%o2, [%o4]ASI_DMMU		/* restore old ctxnum */
129	flush	%o3
130	wrpr	%g0, 0, %tl
131
132	retl
133	wrpr	%g0, %o5, %pstate		/* enable interrupts */
134	SET_SIZE(vtag_flushpage)
135
136
137	ENTRY_NP2(vtag_flushall, demap_all)
138	/*
139	 * flush the tlb
140	 */
141	sethi	%hi(FLUSH_ADDR), %o3
142	set	DEMAP_ALL_TYPE, %g1
143	stxa	%g0, [%g1]ASI_DTLB_DEMAP
144	stxa	%g0, [%g1]ASI_ITLB_DEMAP
145	flush	%o3
146	retl
147	nop
148	SET_SIZE(demap_all)
149	SET_SIZE(vtag_flushall)
150
151
152	ENTRY_NP(vtag_flushpage_tl1)
153	/*
154	 * x-trap to flush page from tlb and tsb
155	 *
156	 * %g1 = vaddr, zero-extended on 32-bit kernel
157	 * %g2 = sfmmup
158	 *
159	 * assumes TSBE_TAG = 0
160	 */
161	srln	%g1, MMU_PAGESHIFT, %g1
162
163	sethi   %hi(ksfmmup), %g3
164        ldx     [%g3 + %lo(ksfmmup)], %g3
165        cmp     %g3, %g2
166        bne,pt	%xcc, 1f                        ! if not kernel as, go to 1
167	  slln	%g1, MMU_PAGESHIFT, %g1		/* g1 = vaddr */
168
169	/* We need to demap in the kernel context */
170	or	DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1
171	stxa	%g0, [%g1]ASI_DTLB_DEMAP
172	stxa	%g0, [%g1]ASI_ITLB_DEMAP
173	retry
1741:
175	/* We need to demap in a user context */
176	or	DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1
177
178	SFMMU_CPU_CNUM(%g2, %g6, %g3)	! %g6 = sfmmu cnum on this CPU
179
180	ldub	[%g2 + SFMMU_CEXT], %g4		! %g4 = sfmmup->cext
181	sll	%g4, CTXREG_EXT_SHIFT, %g4
182	or	%g6, %g4, %g6			! %g6 = primary pgsz | cnum
183
184	set	MMU_PCONTEXT, %g4
185	ldxa	[%g4]ASI_DMMU, %g5		! %g5 = save old ctxnum
186	srlx	%g5, CTXREG_NEXT_SHIFT, %g2	! %g2 = nucleus pgsz
187	sllx	%g2, CTXREG_NEXT_SHIFT, %g2	! preserve nucleus pgsz
188	or	%g6, %g2, %g6			! %g6 = nucleus pgsz | primary pgsz | cnum
189	stxa	%g6, [%g4]ASI_DMMU		! wr new ctxum
190	stxa	%g0, [%g1]ASI_DTLB_DEMAP
191	stxa	%g0, [%g1]ASI_ITLB_DEMAP
192	stxa	%g5, [%g4]ASI_DMMU		! restore old ctxnum
193	retry
194	SET_SIZE(vtag_flushpage_tl1)
195
196
197	ENTRY_NP(vtag_flush_pgcnt_tl1)
198	/*
199	 * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb
200	 *
201	 * %g1 = vaddr, zero-extended on 32-bit kernel
202	 * %g2 = <sfmmup58|pgcnt6>
203	 *
204	 * NOTE: this handler relies on the fact that no
205	 *	interrupts or traps can occur during the loop
206	 *	issuing the TLB_DEMAP operations. It is assumed
207	 *	that interrupts are disabled and this code is
208	 *	fetching from the kernel locked text address.
209	 *
210	 * assumes TSBE_TAG = 0
211	 */
212	set	SFMMU_PGCNT_MASK, %g4
213	and	%g4, %g2, %g3			/* g3 = pgcnt - 1 */
214	add	%g3, 1, %g3			/* g3 = pgcnt */
215
216	andn	%g2, SFMMU_PGCNT_MASK, %g2	/* g2 = sfmmup */
217	srln	%g1, MMU_PAGESHIFT, %g1
218
219	sethi   %hi(ksfmmup), %g4
220        ldx     [%g4 + %lo(ksfmmup)], %g4
221        cmp     %g4, %g2
222        bne,pn   %xcc, 1f			/* if not kernel as, go to 1 */
223	  slln	%g1, MMU_PAGESHIFT, %g1		/* g1 = vaddr */
224
225	/* We need to demap in the kernel context */
226	or	DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1
227	set	MMU_PAGESIZE, %g2		/* g2 = pgsize */
228	sethi   %hi(FLUSH_ADDR), %g5
2294:
230	stxa	%g0, [%g1]ASI_DTLB_DEMAP
231	stxa	%g0, [%g1]ASI_ITLB_DEMAP
232	flush	%g5				! flush required by immu
233
234	deccc	%g3				/* decr pgcnt */
235	bnz,pt	%icc,4b
236	  add	%g1, %g2, %g1			/* next page */
237	retry
2381:
239	/*
240	 * We need to demap in a user context
241	 *
242	 * g2 = sfmmup
243	 * g3 = pgcnt
244	 */
245	SFMMU_CPU_CNUM(%g2, %g5, %g6)		! %g5 = sfmmu cnum on this CPU
246
247	or	DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1
248
249	ldub	[%g2 + SFMMU_CEXT], %g4		! %g4 = sfmmup->cext
250	sll	%g4, CTXREG_EXT_SHIFT, %g4
251	or	%g5, %g4, %g5
252
253	set	MMU_PCONTEXT, %g4
254	ldxa	[%g4]ASI_DMMU, %g6		/* rd old ctxnum */
255	srlx	%g6, CTXREG_NEXT_SHIFT, %g2	/* %g2 = nucleus pgsz */
256	sllx	%g2, CTXREG_NEXT_SHIFT, %g2	/* preserve nucleus pgsz */
257	or	%g5, %g2, %g5			/* %g5 = nucleus pgsz | primary pgsz | cnum */
258	stxa	%g5, [%g4]ASI_DMMU		/* wr new ctxum */
259
260	set	MMU_PAGESIZE, %g2		/* g2 = pgsize */
261	sethi   %hi(FLUSH_ADDR), %g5
2623:
263	stxa	%g0, [%g1]ASI_DTLB_DEMAP
264	stxa	%g0, [%g1]ASI_ITLB_DEMAP
265	flush	%g5				! flush required by immu
266
267	deccc	%g3				/* decr pgcnt */
268	bnz,pt	%icc,3b
269	  add	%g1, %g2, %g1			/* next page */
270
271	stxa	%g6, [%g4]ASI_DMMU		/* restore old ctxnum */
272	retry
273	SET_SIZE(vtag_flush_pgcnt_tl1)
274
275
276	ENTRY_NP(vtag_flushall_tl1)
277	/*
278	 * x-trap to flush tlb
279	 */
280	set	DEMAP_ALL_TYPE, %g4
281	stxa	%g0, [%g4]ASI_DTLB_DEMAP
282	stxa	%g0, [%g4]ASI_ITLB_DEMAP
283	retry
284	SET_SIZE(vtag_flushall_tl1)
285
286
287/*
288 * VAC (virtual address conflict) does not apply to OPL.
289 * VAC resolution is managed by the Olympus processor hardware.
290 * As a result, all OPL VAC flushing routines are no-ops.
291 */
292
293	ENTRY(vac_flushpage)
294	retl
295	  nop
296	SET_SIZE(vac_flushpage)
297
298	ENTRY_NP(vac_flushpage_tl1)
299	retry
300	SET_SIZE(vac_flushpage_tl1)
301
302
303	ENTRY(vac_flushcolor)
304	retl
305	 nop
306	SET_SIZE(vac_flushcolor)
307
308
309
310	ENTRY(vac_flushcolor_tl1)
311	retry
312	SET_SIZE(vac_flushcolor_tl1)
313
314/*
315 * Determine whether or not the IDSR is busy.
316 * Entry: no arguments
317 * Returns: 1 if busy, 0 otherwise
318 */
319	ENTRY(idsr_busy)
320	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %g1
321	clr	%o0
322	btst	IDSR_BUSY, %g1
323	bz,a,pt	%xcc, 1f
324	mov	1, %o0
3251:
326	retl
327	nop
328	SET_SIZE(idsr_busy)
329
330	.global _dispatch_status_busy
331_dispatch_status_busy:
332	.asciz	"ASI_INTR_DISPATCH_STATUS error: busy"
333	.align	4
334
335/*
336 * Setup interrupt dispatch data registers
337 * Entry:
338 *	%o0 - function or inumber to call
339 *	%o1, %o2 - arguments (2 uint64_t's)
340 */
341	.seg "text"
342
343	ENTRY(init_mondo)
344#ifdef DEBUG
345	!
346	! IDSR should not be busy at the moment
347	!
348	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %g1
349	btst	IDSR_BUSY, %g1
350	bz,pt	%xcc, 1f
351	nop
352	sethi	%hi(_dispatch_status_busy), %o0
353	call	panic
354	or	%o0, %lo(_dispatch_status_busy), %o0
355#endif /* DEBUG */
356
357	ALTENTRY(init_mondo_nocheck)
358	!
359	! interrupt vector dispatch data reg 0
360	!
3611:
362	mov	IDDR_0, %g1
363	mov	IDDR_1, %g2
364	mov	IDDR_2, %g3
365	stxa	%o0, [%g1]ASI_INTR_DISPATCH
366
367	!
368	! interrupt vector dispatch data reg 1
369	!
370	stxa	%o1, [%g2]ASI_INTR_DISPATCH
371
372	!
373	! interrupt vector dispatch data reg 2
374	!
375	stxa	%o2, [%g3]ASI_INTR_DISPATCH
376
377	membar	#Sync
378	retl
379	nop
380	SET_SIZE(init_mondo_nocheck)
381	SET_SIZE(init_mondo)
382
383
384/*
385 * Ship mondo to aid using busy/nack pair bn
386 */
387	ENTRY_NP(shipit)
388	sll	%o0, IDCR_PID_SHIFT, %g1	! IDCR<23:14> = agent id
389	sll	%o1, IDCR_BN_SHIFT, %g2		! IDCR<28:24> = b/n pair
390	or	%g1, IDCR_OFFSET, %g1		! IDCR<13:0> = 0x70
391	or	%g1, %g2, %g1
392	stxa	%g0, [%g1]ASI_INTR_DISPATCH	! interrupt vector dispatch
393	membar	#Sync
394	retl
395	nop
396	SET_SIZE(shipit)
397
398
399/*
400 * flush_instr_mem:
401 *	Flush 1 page of the I-$ starting at vaddr
402 * 	%o0 vaddr
403 *	%o1 bytes to be flushed
404 *
405 * SPARC64-VI maintains consistency of the on-chip Instruction Cache with
406 * the stores from all processors so that a FLUSH instruction is only needed
407 * to ensure pipeline is consistent. This means a single flush is sufficient at
408 * the end of a sequence of stores that updates the instruction stream to
409 * ensure correct operation.
410 */
411
412	ENTRY(flush_instr_mem)
413	flush	%o0			! address irrelevant
414	retl
415	nop
416	SET_SIZE(flush_instr_mem)
417
418
419/*
420 * flush_ecache:
421 *	%o0 - 64 bit physical address
422 *	%o1 - ecache size
423 *	%o2 - ecache linesize
424 */
425
426	ENTRY(flush_ecache)
427
428	/*
429	 * Flush the entire Ecache.
430	 */
431	ECACHE_FLUSHALL(%o1, %o2, %o0, %o4)
432	retl
433	nop
434	SET_SIZE(flush_ecache)
435
436	/*
437	 * I/D cache flushing is not needed for OPL processors
438	 */
439	ENTRY(kdi_flush_idcache)
440	retl
441	nop
442	SET_SIZE(kdi_flush_idcache)
443
444#ifdef	TRAPTRACE
445/*
446 * Simplified trap trace macro for OPL. Adapted from us3.
447 */
448#define	OPL_TRAPTRACE(ptr, scr1, scr2, label)			\
449	CPU_INDEX(scr1, ptr);					\
450	sll	scr1, TRAPTR_SIZE_SHIFT, scr1;			\
451	set	trap_trace_ctl, ptr;				\
452	add	ptr, scr1, scr1;				\
453	ld	[scr1 + TRAPTR_LIMIT], ptr;			\
454	tst	ptr;						\
455	be,pn	%icc, label##1;				\
456	 ldx	[scr1 + TRAPTR_PBASE], ptr;			\
457	ld	[scr1 + TRAPTR_OFFSET], scr1;			\
458	add	ptr, scr1, ptr;					\
459	rd	%asi, scr2;					\
460	wr	%g0, TRAPTR_ASI, %asi;				\
461	rd	STICK, scr1;					\
462	stxa    scr1, [ptr + TRAP_ENT_TICK]%asi;		\
463	rdpr	%tl, scr1;					\
464	stha    scr1, [ptr + TRAP_ENT_TL]%asi;			\
465	rdpr	%tt, scr1;					\
466	stha	scr1, [ptr + TRAP_ENT_TT]%asi;			\
467	rdpr	%tpc, scr1;					\
468	stna    scr1, [ptr + TRAP_ENT_TPC]%asi;			\
469	rdpr	%tstate, scr1;					\
470	stxa	scr1, [ptr + TRAP_ENT_TSTATE]%asi;		\
471	stna    %sp, [ptr + TRAP_ENT_SP]%asi;			\
472	stna    %g0, [ptr + TRAP_ENT_TR]%asi;			\
473	stna    %g0, [ptr + TRAP_ENT_F1]%asi;			\
474	stna    %g0, [ptr + TRAP_ENT_F2]%asi;			\
475	stna    %g0, [ptr + TRAP_ENT_F3]%asi;			\
476	stna    %g0, [ptr + TRAP_ENT_F4]%asi;			\
477	wr	%g0, scr2, %asi;				\
478	CPU_INDEX(ptr, scr1);					\
479	sll	ptr, TRAPTR_SIZE_SHIFT, ptr;			\
480	set	trap_trace_ctl, scr1;				\
481	add	scr1, ptr, ptr;					\
482	ld	[ptr + TRAPTR_OFFSET], scr1;			\
483	ld	[ptr + TRAPTR_LIMIT], scr2;			\
484	st	scr1, [ptr + TRAPTR_LAST_OFFSET];		\
485	add	scr1, TRAP_ENT_SIZE, scr1;			\
486	sub	scr2, TRAP_ENT_SIZE, scr2;			\
487	cmp	scr1, scr2;					\
488	movge	%icc, 0, scr1;					\
489	st	scr1, [ptr + TRAPTR_OFFSET];			\
490label##1:
491#endif	/* TRAPTRACE */
492
493
494
495/*
496 * Macros facilitating error handling.
497 */
498
499/*
500 * Save alternative global registers reg1, reg2, reg3
501 * to scratchpad registers 1, 2, 3 respectively.
502 */
503#define	OPL_SAVE_GLOBAL(reg1, reg2, reg3)	\
504	stxa	reg1, [%g0]ASI_SCRATCHPAD		;\
505	mov	OPL_SCRATCHPAD_SAVE_AG2, reg1	;\
506	stxa	reg2, [reg1]ASI_SCRATCHPAD		;\
507	mov	OPL_SCRATCHPAD_SAVE_AG3, reg1	;\
508	stxa	reg3, [reg1]ASI_SCRATCHPAD
509
510/*
511 * Restore alternative global registers reg1, reg2, reg3
512 * from scratchpad registers 1, 2, 3 respectively.
513 */
514#define	OPL_RESTORE_GLOBAL(reg1, reg2, reg3)			\
515	mov	OPL_SCRATCHPAD_SAVE_AG3, reg1			;\
516	ldxa	[reg1]ASI_SCRATCHPAD, reg3				;\
517	mov	OPL_SCRATCHPAD_SAVE_AG2, reg1			;\
518	ldxa	[reg1]ASI_SCRATCHPAD, reg2				;\
519	ldxa	[%g0]ASI_SCRATCHPAD, reg1
520
521/*
522 * Logs value `val' into the member `offset' of a structure
523 * at physical address `pa'
524 */
525#define	LOG_REG(pa, offset, val)				\
526	add	pa, offset, pa					;\
527	stxa	val, [pa]ASI_MEM
528
529#define	FLUSH_ALL_TLB(tmp1)					\
530	set	DEMAP_ALL_TYPE, tmp1				;\
531	stxa	%g0, [tmp1]ASI_ITLB_DEMAP			;\
532	stxa	%g0, [tmp1]ASI_DTLB_DEMAP			;\
533	sethi	%hi(FLUSH_ADDR), tmp1				;\
534	flush	tmp1
535
536/*
537 * Extracts the Physaddr to Logging Buffer field of the OPL_SCRATCHPAD_ERRLOG
538 * scratch register by zeroing all other fields. Result is in pa.
539 */
540#define	LOG_ADDR(pa)							\
541	mov	OPL_SCRATCHPAD_ERRLOG, pa				;\
542	ldxa	[pa]ASI_SCRATCHPAD, pa					;\
543	sllx	pa, 64-ERRLOG_REG_EIDR_SHIFT, pa			;\
544	srlx	pa, 64-ERRLOG_REG_EIDR_SHIFT+ERRLOG_REG_ERR_SHIFT, pa	;\
545	sllx	pa, ERRLOG_REG_ERR_SHIFT, pa
546
547/*
548 * Advance the per-cpu error log buffer pointer to the next
549 * ERRLOG_SZ entry, making sure that it will modulo (wraparound)
550 * ERRLOG_BUFSIZ boundary. The args logpa, bufmask, tmp are
551 * unused input registers for this macro.
552 *
553 * Algorithm:
554 * 1. logpa = contents of errorlog scratchpad register
555 * 2. bufmask = ERRLOG_BUFSIZ - 1
556 * 3. tmp = logpa & ~(bufmask)     (tmp is now logbase)
557 * 4. logpa += ERRLOG_SZ
558 * 5. logpa = logpa & bufmask      (get new offset to logbase)
559 * 4. logpa = tmp | logpa
560 * 7. write logpa back into errorlog scratchpad register
561 *
562 * new logpa = (logpa & ~bufmask) | ((logpa + ERRLOG_SZ) & bufmask)
563 *
564 */
565#define	UPDATE_LOGADD(logpa, bufmask, tmp)			\
566	set	OPL_SCRATCHPAD_ERRLOG, tmp			;\
567	ldxa	[tmp]ASI_SCRATCHPAD, logpa			;\
568	set	(ERRLOG_BUFSZ-1), bufmask			;\
569	andn	logpa, bufmask, tmp				;\
570	add	logpa, ERRLOG_SZ, logpa				;\
571	and	logpa, bufmask, logpa				;\
572	or	tmp, logpa, logpa				;\
573	set	OPL_SCRATCHPAD_ERRLOG, tmp			;\
574	stxa	logpa, [tmp]ASI_SCRATCHPAD
575
576/* Log error status registers into the log buffer */
577#define	LOG_SYNC_REG(sfsr, sfar, tmp)				\
578	LOG_ADDR(tmp)						;\
579	LOG_REG(tmp, LOG_SFSR_OFF, sfsr)			;\
580	LOG_ADDR(tmp)						;\
581	mov	tmp, sfsr					;\
582	LOG_REG(tmp, LOG_SFAR_OFF, sfar)			;\
583	rd	STICK, sfar					;\
584	mov	sfsr, tmp					;\
585	LOG_REG(tmp, LOG_STICK_OFF, sfar)			;\
586	rdpr	%tl, tmp					;\
587	sllx	tmp, 32, sfar					;\
588	rdpr	%tt, tmp					;\
589	or	sfar, tmp, sfar					;\
590	mov	sfsr, tmp					;\
591	LOG_REG(tmp, LOG_TL_OFF, sfar)				;\
592	set	OPL_SCRATCHPAD_ERRLOG, tmp			;\
593	ldxa	[tmp]ASI_SCRATCHPAD, sfar			;\
594	mov	sfsr, tmp					;\
595	LOG_REG(tmp, LOG_ASI3_OFF, sfar)			;\
596	rdpr	%tpc, sfar					;\
597	mov	sfsr, tmp					;\
598	LOG_REG(tmp, LOG_TPC_OFF, sfar)				;\
599	UPDATE_LOGADD(sfsr, sfar, tmp)
600
601#define	LOG_UGER_REG(uger, tmp, tmp2)				\
602	LOG_ADDR(tmp)						;\
603	mov	tmp, tmp2					;\
604	LOG_REG(tmp2, LOG_UGER_OFF, uger)			;\
605	mov	tmp, uger					;\
606	rd	STICK, tmp2					;\
607	LOG_REG(tmp, LOG_STICK_OFF, tmp2)			;\
608	rdpr	%tl, tmp					;\
609	sllx	tmp, 32, tmp2					;\
610	rdpr	%tt, tmp					;\
611	or	tmp2, tmp, tmp2					;\
612	mov	uger, tmp					;\
613	LOG_REG(tmp, LOG_TL_OFF, tmp2)				;\
614	set	OPL_SCRATCHPAD_ERRLOG, tmp2			;\
615	ldxa	[tmp2]ASI_SCRATCHPAD, tmp2				;\
616	mov	uger, tmp					;\
617	LOG_REG(tmp, LOG_ASI3_OFF, tmp2)			;\
618	rdpr	%tstate, tmp2					;\
619	mov	uger, tmp					;\
620	LOG_REG(tmp, LOG_TSTATE_OFF, tmp2)			;\
621	rdpr	%tpc, tmp2					;\
622	mov	uger, tmp					;\
623	LOG_REG(tmp, LOG_TPC_OFF, tmp2)				;\
624	UPDATE_LOGADD(uger, tmp, tmp2)
625
626/*
627 * Scrub the STICK_COMPARE register to clear error by updating
628 * it to a reasonable value for interrupt generation.
629 * Ensure that we observe the CPU_ENABLE flag so that we
630 * don't accidentally enable TICK interrupt in STICK_COMPARE
631 * i.e. no clock interrupt will be generated if CPU_ENABLE flag
632 * is off.
633 */
634#define	UPDATE_STICK_COMPARE(tmp1, tmp2)			\
635	CPU_ADDR(tmp1, tmp2)					;\
636	lduh	[tmp1 + CPU_FLAGS], tmp2			;\
637	andcc	tmp2, CPU_ENABLE, %g0 				;\
638	set	OPL_UGER_STICK_DIFF, tmp2			;\
639	rd	STICK, tmp1					;\
640	add	tmp1, tmp2, tmp1				;\
641	mov	1, tmp2						;\
642	sllx	tmp2, TICKINT_DIS_SHFT, tmp2			;\
643	or	tmp1, tmp2, tmp2				;\
644	movnz	%xcc, tmp1, tmp2				;\
645	wr	tmp2, %g0, STICK_COMPARE
646
647/*
648 * Reset registers that may be corrupted by IAUG_CRE error.
649 * To update interrupt handling related registers force the
650 * clock interrupt.
651 */
652#define	IAG_CRE(tmp1, tmp2)					\
653	set	OPL_SCRATCHPAD_ERRLOG, tmp1			;\
654	ldxa	[tmp1]ASI_SCRATCHPAD, tmp1			;\
655	srlx	tmp1, ERRLOG_REG_EIDR_SHIFT, tmp1		;\
656	set	ERRLOG_REG_EIDR_MASK, tmp2			;\
657	and	tmp1, tmp2, tmp1				;\
658	stxa	tmp1, [%g0]ASI_EIDR				;\
659	wr	%g0, 0, SOFTINT					;\
660	sethi	%hi(hres_last_tick), tmp1			;\
661	ldx	[tmp1 + %lo(hres_last_tick)], tmp1		;\
662	set	OPL_UGER_STICK_DIFF, tmp2			;\
663	add	tmp1, tmp2, tmp1				;\
664	wr	tmp1, %g0, STICK				;\
665	UPDATE_STICK_COMPARE(tmp1, tmp2)
666
667
668#define	CLEAR_FPREGS(tmp)					\
669	wr	%g0, FPRS_FEF, %fprs				;\
670	wr	%g0, %g0, %gsr					;\
671	sethi	%hi(opl_clr_freg), tmp				;\
672	or	tmp, %lo(opl_clr_freg), tmp			;\
673	ldx	[tmp], %fsr					;\
674	fzero	 %d0						;\
675	fzero	 %d2						;\
676	fzero	 %d4						;\
677	fzero	 %d6						;\
678	fzero	 %d8						;\
679	fzero	 %d10						;\
680	fzero	 %d12						;\
681	fzero	 %d14						;\
682	fzero	 %d16						;\
683	fzero	 %d18						;\
684	fzero	 %d20						;\
685	fzero	 %d22						;\
686	fzero	 %d24						;\
687	fzero	 %d26						;\
688	fzero	 %d28						;\
689	fzero	 %d30						;\
690	fzero	 %d32						;\
691	fzero	 %d34						;\
692	fzero	 %d36						;\
693	fzero	 %d38						;\
694	fzero	 %d40						;\
695	fzero	 %d42						;\
696	fzero	 %d44						;\
697	fzero	 %d46						;\
698	fzero	 %d48						;\
699	fzero	 %d50						;\
700	fzero	 %d52						;\
701	fzero	 %d54						;\
702	fzero	 %d56						;\
703	fzero	 %d58						;\
704	fzero	 %d60						;\
705	fzero	 %d62						;\
706	wr	%g0, %g0, %fprs
707
708#define	CLEAR_GLOBALS()						\
709	mov	%g0, %g1					;\
710	mov	%g0, %g2					;\
711	mov	%g0, %g3					;\
712	mov	%g0, %g4					;\
713	mov	%g0, %g5					;\
714	mov	%g0, %g6					;\
715	mov	%g0, %g7
716
717/*
718 * We do not clear the alternative globals here because they
719 * are scratch registers, i.e. there is no code that reads from
720 * them without write to them firstly. In other words every
721 * read always follows write that makes extra write to the
722 * alternative globals unnecessary.
723 */
724#define	CLEAR_GEN_REGS(tmp1, label)				\
725	set	TSTATE_KERN, tmp1				;\
726	wrpr	%g0, tmp1, %tstate				;\
727	mov	%g0, %y						;\
728	mov	%g0, %asi					;\
729	mov	%g0, %ccr					;\
730	mov	%g0, %l0					;\
731	mov	%g0, %l1					;\
732	mov	%g0, %l2					;\
733	mov	%g0, %l3					;\
734	mov	%g0, %l4					;\
735	mov	%g0, %l5					;\
736	mov	%g0, %l6					;\
737	mov	%g0, %l7					;\
738	mov	%g0, %i0					;\
739	mov	%g0, %i1					;\
740	mov	%g0, %i2					;\
741	mov	%g0, %i3					;\
742	mov	%g0, %i4					;\
743	mov	%g0, %i5					;\
744	mov	%g0, %i6					;\
745	mov	%g0, %i7					;\
746	mov	%g0, %o1					;\
747	mov	%g0, %o2					;\
748	mov	%g0, %o3					;\
749	mov	%g0, %o4					;\
750	mov	%g0, %o5					;\
751	mov	%g0, %o6					;\
752	mov	%g0, %o7					;\
753	mov	%g0, %o0					;\
754	mov	%g0, %g4					;\
755	mov	%g0, %g5					;\
756	mov	%g0, %g6					;\
757	mov	%g0, %g7					;\
758	rdpr	%tl, tmp1					;\
759	cmp	tmp1, 1						;\
760	be,pt	%xcc, label##1					;\
761	 rdpr	%pstate, tmp1					;\
762	wrpr	tmp1, PSTATE_AG|PSTATE_IG, %pstate		;\
763	CLEAR_GLOBALS()						;\
764	rdpr	%pstate, tmp1					;\
765	wrpr	tmp1, PSTATE_IG|PSTATE_MG, %pstate		;\
766	CLEAR_GLOBALS()						;\
767	rdpr	%pstate, tmp1					;\
768	wrpr	tmp1, PSTATE_MG|PSTATE_AG, %pstate		;\
769	ba,pt	%xcc, label##2					;\
770	 nop							;\
771label##1:							;\
772	wrpr	tmp1, PSTATE_AG, %pstate			;\
773	CLEAR_GLOBALS()						;\
774	rdpr	%pstate, tmp1					;\
775	wrpr	tmp1, PSTATE_AG, %pstate			;\
776label##2:
777
778
779/*
780 * Reset all window related registers
781 */
782#define	RESET_WINREG(tmp)					\
783	sethi	%hi(nwin_minus_one), tmp			;\
784	ld	[tmp + %lo(nwin_minus_one)], tmp		;\
785	wrpr	%g0, tmp, %cwp					;\
786	wrpr	%g0, tmp, %cleanwin				;\
787	sub	tmp, 1, tmp					;\
788	wrpr	%g0, tmp, %cansave				;\
789	wrpr	%g0, %g0, %canrestore				;\
790	wrpr	%g0, %g0, %otherwin				;\
791	wrpr	%g0, PIL_MAX, %pil				;\
792	wrpr	%g0, WSTATE_KERN, %wstate
793
794
795#define	RESET_PREV_TSTATE(tmp1, tmp2, label)			\
796	rdpr	%tl, tmp1					;\
797	subcc	tmp1, 1, tmp1					;\
798	bz,pt	%xcc, label##1					;\
799	 nop							;\
800	wrpr	tmp1, %g0, %tl					;\
801	set	TSTATE_KERN, tmp2				;\
802	wrpr	tmp2, %g0, %tstate				;\
803	wrpr	%g0, %g0, %tpc					;\
804	wrpr	%g0, %g0, %tnpc					;\
805	add	tmp1, 1, tmp1					;\
806	wrpr	tmp1, %g0, %tl					;\
807label##1:
808
809
810/*
811 * %pstate, %pc, %npc are propagated to %tstate, %tpc, %tnpc,
812 * and we reset these regiseter here.
813 */
814#define	RESET_CUR_TSTATE(tmp)					\
815	set	TSTATE_KERN, tmp				;\
816	wrpr	%g0, tmp, %tstate				;\
817	wrpr	%g0, 0, %tpc					;\
818	wrpr	%g0, 0, %tnpc					;\
819	RESET_WINREG(tmp)
820
821/*
822 * In case of urgent errors some MMU registers may be
823 * corrupted, so we set here some reasonable values for
824 * them. Note that resetting MMU registers also reset the context
825 * info, we will need to reset the window registers to prevent
826 * spill/fill that depends on context info for correct behaviour.
827 * Note that the TLBs must be flushed before programming the context
828 * registers.
829 */
830
831#define	RESET_MMU_REGS(tmp1, tmp2, tmp3)			\
832	FLUSH_ALL_TLB(tmp1)					;\
833	set	MMU_PCONTEXT, tmp1				;\
834	sethi	%hi(kcontextreg), tmp2				;\
835	ldx	[tmp2 + %lo(kcontextreg)], tmp2			;\
836	stxa	tmp2, [tmp1]ASI_DMMU				;\
837	set	MMU_SCONTEXT, tmp1				;\
838	stxa	tmp2, [tmp1]ASI_DMMU				;\
839	sethi	%hi(ktsb_base), tmp1				;\
840	ldx	[tmp1 + %lo(ktsb_base)], tmp2			;\
841	mov	MMU_TSB, tmp3					;\
842	stxa	tmp2, [tmp3]ASI_IMMU				;\
843	stxa	tmp2, [tmp3]ASI_DMMU				;\
844	membar	#Sync						;\
845	RESET_WINREG(tmp1)
846
847#define	RESET_TSB_TAGPTR(tmp)					\
848	set	MMU_TAG_ACCESS, tmp				;\
849	stxa	%g0, [tmp]ASI_IMMU				;\
850	stxa	%g0, [tmp]ASI_DMMU				;\
851	membar	#Sync
852
853/*
854 * In case of errors in the MMU_TSB_PREFETCH registers we have to
855 * reset them. We can use "0" as the reset value, this way we set
856 * the "V" bit of the registers to 0, which will disable the prefetch
857 * so the values of the other fields are irrelevant.
858 */
859#define	RESET_TSB_PREFETCH(tmp)			\
860	set	VA_UTSBPREF_8K, tmp 		;\
861	stxa	%g0, [tmp]ASI_ITSB_PREFETCH	;\
862	set	VA_UTSBPREF_4M, tmp 		;\
863	stxa	%g0, [tmp]ASI_ITSB_PREFETCH	;\
864	set	VA_KTSBPREF_8K, tmp 		;\
865	stxa	%g0, [tmp]ASI_ITSB_PREFETCH	;\
866	set	VA_KTSBPREF_4M, tmp 		;\
867	stxa	%g0, [tmp]ASI_ITSB_PREFETCH	;\
868	set	VA_UTSBPREF_8K, tmp 		;\
869	stxa	%g0, [tmp]ASI_DTSB_PREFETCH	;\
870	set	VA_UTSBPREF_4M, tmp 		;\
871	stxa	%g0, [tmp]ASI_DTSB_PREFETCH	;\
872	set	VA_KTSBPREF_8K, tmp 		;\
873	stxa	%g0, [tmp]ASI_DTSB_PREFETCH	;\
874	set	VA_KTSBPREF_4M, tmp 		;\
875	stxa	%g0, [tmp]ASI_DTSB_PREFETCH
876
877/*
878 * In case of errors in the MMU_SHARED_CONTEXT register we have to
879 * reset its value. We can use "0" as the reset value, it will put
880 * 0 in the IV field disabling the shared context support, and
881 * making values of all the other fields of the register irrelevant.
882 */
883#define	RESET_SHARED_CTXT(tmp)			\
884	set	MMU_SHARED_CONTEXT, tmp		;\
885	stxa	%g0, [tmp]ASI_DMMU
886
887/*
888 * RESET_TO_PRIV()
889 *
890 * In many cases, we need to force the thread into privilege mode because
891 * privilege mode is only thing in which the system continue to work
892 * due to undeterminable user mode information that come from register
893 * corruption.
894 *
895 *  - opl_uger_ctxt
896 *    If the error is secondary TSB related register parity, we have no idea
897 *    what value is supposed to be for it.
898 *
899 *  The below three cases %tstate is not accessible until it is overwritten
900 *  with some value, so we have no clue if the thread was running on user mode
901 *  or not
902 *   - opl_uger_pstate
903 *     If the error is %pstate parity, it propagates to %tstate.
904 *   - opl_uger_tstate
905 *     No need to say the reason
906 *   - opl_uger_r
907 *     If the error is %ccr or %asi parity, it propagates to %tstate
908 *
909 * For the above four cases, user mode info may not be available for
910 * sys_trap() and user_trap() to work consistently. So we have to force
911 * the thread into privilege mode.
912 *
913 * Forcing the thread to privilege mode requires forcing
914 * regular %g7 to be CPU_THREAD. Because if it was running on user mode,
915 * %g7 will be set in user_trap(). Also since the %sp may be in
916 * an inconsistent state, we need to do a stack reset and switch to
917 * something we know i.e. current thread's kernel stack.
918 * We also reset the window registers and MMU registers just to
919 * make sure.
920 *
921 * To set regular %g7, we need to clear PSTATE_AG bit and need to
922 * use one local register. Note that we are panicking and will never
923 * unwind back so it is ok to clobber a local.
924 *
925 * If the thread was running in user mode, the %tpc value itself might be
926 * within the range of OBP addresses. %tpc must be forced to be zero to prevent
927 * sys_trap() from going to prom_trap()
928 *
929 */
930#define	RESET_TO_PRIV(tmp, tmp1, tmp2, local)			\
931	RESET_MMU_REGS(tmp, tmp1, tmp2)				;\
932	CPU_ADDR(tmp, tmp1)					;\
933	ldx	[tmp + CPU_THREAD], local			;\
934	ldx	[local + T_STACK], tmp				;\
935	sub	tmp, STACK_BIAS, %sp				;\
936	rdpr	%pstate, tmp					;\
937	wrpr	tmp, PSTATE_AG, %pstate				;\
938	mov	local, %g7					;\
939	rdpr	%pstate, local					;\
940	wrpr	local, PSTATE_AG, %pstate			;\
941	wrpr	%g0, 1, %tl					;\
942	set	TSTATE_KERN, tmp				;\
943	rdpr	%cwp, tmp1					;\
944	or	tmp, tmp1, tmp					;\
945	wrpr	tmp, %g0, %tstate				;\
946	wrpr	%g0, %tpc
947
948
949/*
950 * We normally don't expect CE traps since we disable the
951 * 0x63 trap reporting at the start of day. There is a
952 * small window before we disable them, so let check for
953 * it. Otherwise, panic.
954 */
955
956	.align	128
957	ENTRY_NP(ce_err)
958	mov	AFSR_ECR, %g1
959	ldxa	[%g1]ASI_ECR, %g1
960	andcc	%g1, ASI_ECR_RTE_UE | ASI_ECR_RTE_CEDG, %g0
961	bz,pn	%xcc, 1f
962	 nop
963	retry
9641:
965	/*
966	 * We did disabled the 0x63 trap reporting.
967	 * This shouldn't happen - panic.
968	 */
969	set	trap, %g1
970	rdpr	%tt, %g3
971	sethi	%hi(sys_trap), %g5
972	jmp	%g5 + %lo(sys_trap)
973	sub	%g0, 1, %g4
974	SET_SIZE(ce_err)
975
976
977/*
978 * We don't use trap for CE detection.
979 */
980	ENTRY_NP(ce_err_tl1)
981	set	trap, %g1
982	rdpr	%tt, %g3
983	sethi	%hi(sys_trap), %g5
984	jmp	%g5 + %lo(sys_trap)
985	sub	%g0, 1, %g4
986	SET_SIZE(ce_err_tl1)
987
988
989/*
990 * async_err is the default handler for IAE/DAE traps.
991 * For OPL, we patch in the right handler at start of day.
992 * But if a IAE/DAE trap get generated before the handler
993 * is patched, panic.
994 */
995	ENTRY_NP(async_err)
996	set	trap, %g1
997	rdpr	%tt, %g3
998	sethi	%hi(sys_trap), %g5
999	jmp	%g5 + %lo(sys_trap)
1000	sub	%g0, 1, %g4
1001	SET_SIZE(async_err)
1002
1003	.seg	".data"
1004	.global	opl_clr_freg
1005	.global opl_cpu0_err_log
1006
1007	.align	16
1008opl_clr_freg:
1009	.word	0
1010	.align	16
1011
1012	.align	MMU_PAGESIZE
1013opl_cpu0_err_log:
1014	.skip	MMU_PAGESIZE
1015
1016/*
1017 * Common synchronous error trap handler (tt=0xA, 0x32)
1018 * All TL=0 and TL>0 0xA and 0x32 traps vector to this handler.
1019 * The error handling can be best summarized as follows:
1020 * 0. Do TRAPTRACE if enabled.
1021 * 1. Save globals %g1, %g2 & %g3 onto the scratchpad regs.
1022 * 2. The SFSR register is read and verified as valid by checking
1023 *    SFSR.FV bit being set. If the SFSR.FV is not set, the
1024 *    error cases cannot be decoded/determined and the SFPAR
1025 *    register that contain the physical faultaddr is also
1026 *    not valid. Also the SPFAR is only valid for UE/TO/BERR error
1027 *    cases. Assuming the SFSR.FV is valid:
1028 *    - BERR(bus error)/TO(timeout)/UE case
1029 *      If any of these error cases are detected, read the SFPAR
1030 *      to get the faultaddress. Generate ereport.
1031 *    - TLB Parity case (only recoverable case)
1032 *      For DAE, read SFAR for the faultaddress. For IAE,
1033 *	use %tpc for faultaddress (SFAR is not valid in IAE)
1034 *	Flush all the tlbs.
1035 *	Subtract one from the recoverable error count stored in
1036 *	the error log scratch register. If the threshold limit
1037 *	is reached (zero) - generate ereport. Else
1038 *	restore globals and retry (no ereport is generated).
1039 *    - TLB Multiple hits
1040 *	For DAE, read SFAR for the faultaddress. For IAE,
1041 *	use %tpc for faultaddress (SFAR is not valid in IAE).
1042 *	Flush all tlbs and generate ereport.
1043 * 3. TL=0 and TL>0 considerations
1044 *    - Since both TL=0 & TL>1 traps are made to vector into
1045 *      the same handler, the underlying assumption/design here is
1046 *      that any nested error condition (if happens) occurs only
1047 *	in the handler and the system is assumed to eventually
1048 *      Red-mode. With this philosophy in mind, the recoverable
1049 *      TLB Parity error case never check the TL level before it
1050 *      retry. Note that this is ok for the TL>1 case (assuming we
1051 *	don't have a nested error) since we always save the globals
1052 *      %g1, %g2 & %g3 whenever we enter this trap handler.
1053 *    - Additional TL=0 vs TL>1 handling includes:
1054 *      - For UE error occuring under TL>1, special handling
1055 *        is added to prevent the unlikely chance of a cpu-lockup
1056 *        when a UE was originally detected in user stack and
1057 *        the spill trap handler taken from sys_trap() so happened
1058 *        to reference the same UE location. Under the above
1059 *        condition (TL>1 and UE error), paranoid code is added
1060 *        to reset window regs so that spill traps can't happen
1061 *        during the unwind back to TL=0 handling.
1062 *        Note that we can do that because we are not returning
1063 *	  back.
1064 * 4. Ereport generation.
1065 *    - Ereport generation is performed when we unwind to the TL=0
1066 *      handling code via sys_trap(). on_trap()/lofault protection
1067 *      will apply there.
1068 *
1069 */
1070	ENTRY_NP(opl_sync_trap)
1071#ifdef	TRAPTRACE
1072	OPL_TRAPTRACE(%g1, %g2, %g3, opl_sync_trap_lb)
1073	rdpr	%tt, %g1
1074#endif	/* TRAPTRACE */
1075	cmp	%g1, T_INSTR_ERROR
1076	bne,pt	%xcc, 0f
1077	 mov	MMU_SFSR, %g3
1078	ldxa	[%g3]ASI_IMMU, %g1	! IAE trap case tt = 0xa
1079	andcc	%g1, SFSR_FV, %g0
1080	bz,a,pn %xcc, 2f		! Branch if SFSR is invalid and
1081	 rdpr	%tpc, %g2		! use %tpc for faultaddr instead
1082
1083	sethi	%hi(SFSR_UE|SFSR_BERR|SFSR_TO), %g3
1084	andcc	%g1, %g3, %g0		! Check for UE/BERR/TO errors
1085	bz,a,pt %xcc, 1f		! Branch if not UE/BERR/TO and
1086	 rdpr	%tpc, %g2		! use %tpc as faultaddr
1087	set	OPL_MMU_SFPAR, %g3	! In the UE/BERR/TO cases, use
1088	ba,pt	%xcc, 2f		! SFPAR as faultaddr
1089	 ldxa	[%g3]ASI_IMMU, %g2
10900:
1091	ldxa	[%g3]ASI_DMMU, %g1	! DAE trap case tt = 0x32
1092	andcc	%g1, SFSR_FV, %g0
1093	bnz,pt  %xcc, 7f		! branch if SFSR.FV is valid
1094	 mov	MMU_SFAR, %g2		! set %g2 to use SFAR
1095	ba,pt	%xcc, 2f		! SFSR.FV is not valid, read SFAR
1096	 ldxa	[%g2]ASI_DMMU, %g2	! for faultaddr
10977:
1098	sethi  %hi(SFSR_UE|SFSR_BERR|SFSR_TO), %g3
1099	andcc	%g1, %g3, %g0		! Check UE/BERR/TO for valid SFPAR
1100	movnz	%xcc, OPL_MMU_SFPAR, %g2 ! Use SFPAR instead of SFAR for
1101	ldxa	[%g2]ASI_DMMU, %g2	! faultaddr
11021:
1103	sethi	%hi(SFSR_TLB_PRT), %g3
1104	andcc	%g1, %g3, %g0
1105	bz,pt	%xcc, 8f		! branch for TLB multi-hit check
1106	 nop
1107	/*
1108	 * This is the TLB parity error case and it is the
1109	 * only retryable error case.
1110	 * Only %g1, %g2 and %g3 are allowed
1111	 */
1112	FLUSH_ALL_TLB(%g3)
1113	set	OPL_SCRATCHPAD_ERRLOG, %g3
1114	ldxa	[%g3]ASI_SCRATCHPAD, %g3		! Read errlog scratchreg
1115	and	%g3, ERRLOG_REG_NUMERR_MASK, %g3! Extract the error count
1116	subcc	%g3, 1, %g0			! Subtract one from the count
1117	bz,pn	%xcc, 2f		! too many TLB parity errs in a certain
1118	 nop				! period, branch to generate ereport
1119	LOG_SYNC_REG(%g1, %g2, %g3)	! Record into the error log
1120	set	OPL_SCRATCHPAD_ERRLOG, %g3
1121	ldxa	[%g3]ASI_SCRATCHPAD, %g2
1122	sub	%g2, 1, %g2		! decrement error counter by 1
1123	stxa	%g2, [%g3]ASI_SCRATCHPAD	! update the errlog scratchreg
1124	OPL_RESTORE_GLOBAL(%g1, %g2, %g3)
1125	retry
11268:
1127	sethi	%hi(SFSR_TLB_MUL), %g3
1128	andcc	%g1, %g3, %g0
1129	bz,pt	%xcc, 2f		! check for the TLB multi-hit errors
1130	 nop
1131	FLUSH_ALL_TLB(%g3)
11322:
1133	/*
1134	 * non-retryable error handling
1135	 * now we can use other registers since
1136	 * we will not be returning back
1137	 */
1138	mov	%g1, %g5		! %g5 = SFSR
1139	mov	%g2, %g6		! %g6 = SFPAR or SFAR/tpc
1140	LOG_SYNC_REG(%g1, %g2, %g3)	! Record into the error log
1141
1142	/*
1143	 * Special case for UE on user stack.
1144	 * There is a possibility that the same error may come back here
1145	 * by touching the same UE in spill trap handler taken from
1146	 * sys_trap(). It ends up with an infinite loop causing a cpu lockup.
1147	 * Conditions for this handling this case are:
1148	 * - SFSR_FV is valid and SFSR_UE is set
1149	 * - we are at TL > 1
1150	 * If the above conditions are true,  we force %cansave to be a
1151	 * big number to prevent spill trap in sys_trap(). Note that
1152	 * we will not be returning back.
1153	 */
1154	rdpr	%tt, %g4		! %g4 == ttype
1155	rdpr	%tl, %g1		! %g1 == tl
1156	cmp	%g1, 1			! Check if TL == 1
1157	be,pt	%xcc, 3f		! branch if we came from TL=0
1158	 nop
1159	andcc	%g5, SFSR_FV, %g0	! see if SFSR.FV is valid
1160	bz,pn	%xcc, 4f		! branch, checking UE is meaningless
1161	sethi	%hi(SFSR_UE), %g2
1162	andcc	%g5, %g2, %g0		! check for UE
1163	bz,pt	%xcc, 4f		! branch if not UE
1164	 nop
1165	RESET_WINREG(%g1)		! reset windows to prevent spills
11664:
1167	RESET_USER_RTT_REGS(%g2, %g3, opl_sync_trap_resetskip)
1168opl_sync_trap_resetskip:
1169	mov	%g5, %g3		! pass SFSR to the 3rd arg
1170	mov	%g6, %g2		! pass SFAR to the 2nd arg
1171	set	opl_cpu_isync_tl1_error, %g1
1172	set	opl_cpu_dsync_tl1_error, %g6
1173	cmp	%g4, T_INSTR_ERROR
1174	movne	%icc, %g6, %g1
1175	ba,pt	%icc, 6f
1176	nop
11773:
1178	mov	%g5, %g3		! pass SFSR to the 3rd arg
1179	mov	%g6, %g2		! pass SFAR to the 2nd arg
1180	set	opl_cpu_isync_tl0_error, %g1
1181	set	opl_cpu_dsync_tl0_error, %g6
1182	cmp	%g4, T_INSTR_ERROR
1183	movne	%icc, %g6, %g1
11846:
1185	sethi	%hi(sys_trap), %g5
1186	jmp	%g5 + %lo(sys_trap)
1187	 mov	PIL_15, %g4
1188	SET_SIZE(opl_sync_trap)
1189
1190/*
1191 * Common Urgent error trap handler (tt=0x40)
1192 * All TL=0 and TL>0 0x40 traps vector to this handler.
1193 * The error handling can be best summarized as follows:
1194 * 1. Read the Urgent error status register (UGERSR)
1195 *    Faultaddress is N/A here and it is not collected.
1196 * 2. Check to see if we have a multiple errors case
1197 *    If so, we enable WEAK_ED (weak error detection) bit
1198 *    to prevent any potential error storms and branch directly
1199 *    to generate ereport. (we don't decode/handle individual
1200 *    error cases when we get a multiple error situation)
1201 * 3. Now look for the recoverable error cases which include
1202 *    IUG_DTLB, IUG_ITLB or COREERR errors. If any of the
1203 *    recoverable errors are detected, do the following:
1204 *    - Flush all tlbs.
1205 *    - Verify that we came from TL=0, if not, generate
1206 *      ereport. Note that the reason we don't recover
1207 *      at TL>0 is because the AGs might be corrupted or
1208 *      inconsistent. We can't save/restore them into
1209 *      the scratchpad regs like we did for opl_sync_trap().
1210 *    - Check the INSTEND[5:4] bits in the UGERSR. If the
1211 *      value is 0x3 (11b), this error is not recoverable.
1212 *      Generate ereport.
1213 *    - Subtract one from the recoverable error count stored in
1214 *      the error log scratch register. If the threshold limit
1215 *      is reached (zero) - generate ereport.
1216 *    - If the count is within the limit, update the count
1217 *      in the error log register (subtract one). Log the error
1218 *      info in the log buffer. Capture traptrace if enabled.
1219 *      Retry (no ereport generated)
1220 * 4. The rest of the error cases are unrecoverable and will
1221 *    be handled according (flushing regs, etc as required).
1222 *    For details on these error cases (UGER_CRE, UGER_CTXT, etc..)
1223 *    consult the OPL cpu/mem philosophy doc.
1224 *    Ereport will be generated for these errors.
1225 * 5. Ereport generation.
1226 *    - Ereport generation for urgent error trap always
1227 *      result in a panic when we unwind to the TL=0 handling
1228 *      code via sys_trap(). on_trap()/lofault protection do
1229 *      not apply there.
1230 */
1231	ENTRY_NP(opl_uger_trap)
1232	set	ASI_UGERSR, %g2
1233	ldxa	[%g2]ASI_AFSR, %g1		! Read the UGERSR reg
1234
1235	set	UGESR_MULTI, %g2
1236	andcc	%g1, %g2, %g0			! Check for Multi-errs
1237	bz,pt	%xcc, opl_uger_is_recover	! branch if not Multi-errs
1238	 nop
1239	set	AFSR_ECR, %g2
1240	ldxa	[%g2]ASI_AFSR, %g3		! Enable Weak error
1241	or	%g3, ASI_ECR_WEAK_ED, %g3	! detect mode to prevent
1242	stxa	%g3, [%g2]ASI_AFSR		! potential error storms
1243	ba	%xcc, opl_uger_panic1
1244	 nop
1245
1246opl_uger_is_recover:
1247	set	UGESR_CAN_RECOVER, %g2		! Check for recoverable
1248	andcc	%g1, %g2, %g0			! errors i.e.IUG_DTLB,
1249	bz,pt	%xcc, opl_uger_cre		! IUG_ITLB or COREERR
1250	 nop
1251
1252	/*
1253	 * Fall thru to handle recoverable case
1254	 * Need to do the following additional checks to determine
1255	 * if this is indeed recoverable.
1256	 * 1. Error trap came from TL=0 and
1257	 * 2. INSTEND[5:4] bits in UGERSR is not 0x3
1258	 * 3. Recoverable error count limit not reached
1259	 *
1260	 */
1261	FLUSH_ALL_TLB(%g3)
1262	rdpr	%tl, %g3		! Read TL
1263	cmp	%g3, 1			! Check if we came from TL=0
1264	bne,pt	%xcc, opl_uger_panic	! branch if came from TL>0
1265	 nop
1266	srlx	%g1, 4, %g2		! shift INSTEND[5:4] -> [1:0]
1267	and	%g2, 3, %g2		! extract the shifted [1:0] bits
1268	cmp	%g2, 3			! check if INSTEND is recoverable
1269	be,pt   %xcc, opl_uger_panic	! panic if ([1:0] = 11b)
1270	 nop
1271	set	OPL_SCRATCHPAD_ERRLOG, %g3
1272	ldxa	[%g3]ASI_SCRATCHPAD, %g2		! Read errlog scratch reg
1273	and	%g2, ERRLOG_REG_NUMERR_MASK, %g3! Extract error count and
1274	subcc	%g3, 1, %g3			! subtract one from it
1275	bz,pt   %xcc, opl_uger_panic	! If count reached zero, too many
1276	 nop				! errors, branch to generate ereport
1277	sub	%g2, 1, %g2			! Subtract one from the count
1278	set	OPL_SCRATCHPAD_ERRLOG, %g3	! and write back the updated
1279	stxa	%g2, [%g3]ASI_SCRATCHPAD		! count into the errlog reg
1280	LOG_UGER_REG(%g1, %g2, %g3)		! Log the error info
1281#ifdef	TRAPTRACE
1282	OPL_TRAPTRACE(%g1, %g2, %g3, opl_uger_trap_lb)
1283#endif	/* TRAPTRACE */
1284	retry					! retry - no ereport
1285
1286	/*
1287	 * Process the rest of the unrecoverable error cases
1288	 * All error cases below ultimately branch to either
1289	 * opl_uger_panic or opl_uger_panic1.
1290	 * opl_uger_panic1 is the same as opl_uger_panic except
1291	 * for the additional execution of the RESET_TO_PRIV()
1292	 * macro that does a heavy handed reset. Read the
1293	 * comments for RESET_TO_PRIV() macro for more info.
1294	 */
1295opl_uger_cre:
1296	set	UGESR_IAUG_CRE, %g2
1297	andcc	%g1, %g2, %g0
1298	bz,pt	%xcc, opl_uger_ctxt
1299	 nop
1300	IAG_CRE(%g2, %g3)
1301	set	AFSR_ECR, %g2
1302	ldxa	[%g2]ASI_AFSR, %g3
1303	or	%g3, ASI_ECR_WEAK_ED, %g3
1304	stxa	%g3, [%g2]ASI_AFSR
1305	ba	%xcc, opl_uger_panic
1306	 nop
1307
1308opl_uger_ctxt:
1309	set	UGESR_IAUG_TSBCTXT, %g2
1310	andcc	%g1, %g2, %g0
1311	bz,pt	%xcc, opl_uger_tsbp
1312	 nop
1313	GET_CPU_IMPL(%g2)
1314	cmp	%g2, JUPITER_IMPL
1315	bne	%xcc, 1f
1316	  nop
1317	RESET_SHARED_CTXT(%g2)
13181:
1319	RESET_MMU_REGS(%g2, %g3, %g4)
1320	ba	%xcc, opl_uger_panic
1321	 nop
1322
1323opl_uger_tsbp:
1324	set	UGESR_IUG_TSBP, %g2
1325	andcc	%g1, %g2, %g0
1326	bz,pt	%xcc, opl_uger_pstate
1327	 nop
1328	GET_CPU_IMPL(%g2)
1329	cmp	%g2, JUPITER_IMPL
1330	bne	%xcc, 1f
1331	  nop
1332	RESET_TSB_PREFETCH(%g2)
13331:
1334	RESET_TSB_TAGPTR(%g2)
1335
1336	/*
1337	 * IUG_TSBP error may corrupt MMU registers
1338	 * Reset them here.
1339	 */
1340	RESET_MMU_REGS(%g2, %g3, %g4)
1341	ba	%xcc, opl_uger_panic
1342	 nop
1343
1344opl_uger_pstate:
1345	set	UGESR_IUG_PSTATE, %g2
1346	andcc	%g1, %g2, %g0
1347	bz,pt	%xcc, opl_uger_tstate
1348	 nop
1349	RESET_CUR_TSTATE(%g2)
1350	ba	%xcc, opl_uger_panic1
1351	 nop
1352
1353opl_uger_tstate:
1354	set	UGESR_IUG_TSTATE, %g2
1355	andcc	%g1, %g2, %g0
1356	bz,pt	%xcc, opl_uger_f
1357	 nop
1358	RESET_PREV_TSTATE(%g2, %g3, opl_uger_tstate_1)
1359	ba	%xcc, opl_uger_panic1
1360	 nop
1361
1362opl_uger_f:
1363	set	UGESR_IUG_F, %g2
1364	andcc	%g1, %g2, %g0
1365	bz,pt	%xcc, opl_uger_r
1366	 nop
1367	CLEAR_FPREGS(%g2)
1368	ba	%xcc, opl_uger_panic
1369	 nop
1370
1371opl_uger_r:
1372	set	UGESR_IUG_R, %g2
1373	andcc	%g1, %g2, %g0
1374	bz,pt	%xcc, opl_uger_panic1
1375	 nop
1376	CLEAR_GEN_REGS(%g2, opl_uger_r_1)
1377	ba	%xcc, opl_uger_panic1
1378	 nop
1379
1380opl_uger_panic:
1381	mov	%g1, %g2			! %g2 = arg #1
1382	LOG_UGER_REG(%g1, %g3, %g4)
1383	ba	%xcc, opl_uger_panic_cmn
1384	 nop
1385
1386opl_uger_panic1:
1387	mov	%g1, %g2			! %g2 = arg #1
1388	LOG_UGER_REG(%g1, %g3, %g4)
1389	RESET_TO_PRIV(%g1, %g3, %g4, %l0)
1390
1391	/*
1392	 * Set up the argument for sys_trap.
1393	 * %g2 = arg #1 already set above
1394	 */
1395opl_uger_panic_cmn:
1396	RESET_USER_RTT_REGS(%g4, %g5, opl_uger_panic_resetskip)
1397opl_uger_panic_resetskip:
1398	rdpr	%tl, %g3			! arg #2
1399	set	opl_cpu_urgent_error, %g1	! pc
1400	sethi	%hi(sys_trap), %g5
1401	jmp	%g5 + %lo(sys_trap)
1402	 mov	PIL_15, %g4
1403	SET_SIZE(opl_uger_trap)
1404
1405/*
1406 * OPL ta3 support (note please, that win_reg
1407 * area size for each cpu is 2^7 bytes)
1408 */
1409
1410#define	RESTORE_WREGS(tmp1, tmp2)		\
1411	CPU_INDEX(tmp1, tmp2)			;\
1412	sethi	%hi(opl_ta3_save), tmp2		;\
1413	ldx	[tmp2 +%lo(opl_ta3_save)], tmp2	;\
1414	sllx	tmp1, 7, tmp1			;\
1415	add	tmp2, tmp1, tmp2		;\
1416	ldx	[tmp2 + 0], %l0			;\
1417	ldx	[tmp2 + 8], %l1			;\
1418	ldx	[tmp2 + 16], %l2		;\
1419	ldx	[tmp2 + 24], %l3		;\
1420	ldx	[tmp2 + 32], %l4		;\
1421	ldx	[tmp2 + 40], %l5		;\
1422	ldx	[tmp2 + 48], %l6		;\
1423	ldx	[tmp2 + 56], %l7		;\
1424	ldx	[tmp2 + 64], %i0		;\
1425	ldx	[tmp2 + 72], %i1		;\
1426	ldx	[tmp2 + 80], %i2		;\
1427	ldx	[tmp2 + 88], %i3		;\
1428	ldx	[tmp2 + 96], %i4		;\
1429	ldx	[tmp2 + 104], %i5		;\
1430	ldx	[tmp2 + 112], %i6		;\
1431	ldx	[tmp2 + 120], %i7
1432
1433#define	SAVE_WREGS(tmp1, tmp2)			\
1434	CPU_INDEX(tmp1, tmp2)			;\
1435	sethi	%hi(opl_ta3_save), tmp2		;\
1436	ldx	[tmp2 +%lo(opl_ta3_save)], tmp2	;\
1437	sllx	tmp1, 7, tmp1			;\
1438	add	tmp2, tmp1, tmp2		;\
1439	stx	%l0, [tmp2 + 0] 		;\
1440	stx	%l1, [tmp2 + 8] 		;\
1441	stx	%l2, [tmp2 + 16] 		;\
1442	stx	%l3, [tmp2 + 24]		;\
1443	stx	%l4, [tmp2 + 32]		;\
1444	stx	%l5, [tmp2 + 40]		;\
1445	stx	%l6, [tmp2 + 48] 		;\
1446	stx	%l7, [tmp2 + 56]		;\
1447	stx	%i0, [tmp2 + 64]		;\
1448	stx	%i1, [tmp2 + 72]		;\
1449	stx	%i2, [tmp2 + 80]		;\
1450	stx	%i3, [tmp2 + 88]		;\
1451	stx	%i4, [tmp2 + 96]		;\
1452	stx	%i5, [tmp2 + 104]		;\
1453	stx	%i6, [tmp2 + 112]		;\
1454	stx	%i7, [tmp2 + 120]
1455
1456
1457/*
1458 * The purpose of this function is to make sure that the restore
1459 * instruction after the flushw does not cause a fill trap. The sun4u
1460 * fill trap handler can not handle a tlb fault of an unmapped stack
1461 * except at the restore instruction at user_rtt. On OPL systems the
1462 * stack can get unmapped between the flushw and restore instructions
1463 * since multiple strands share the tlb.
1464 */
1465	ENTRY_NP(opl_ta3_trap)
1466	set	trap, %g1
1467	mov	T_FLUSHW, %g3
1468	sub	%g0, 1, %g4
1469	rdpr	%cwp, %g5
1470	SAVE_WREGS(%g2, %g6)
1471	save
1472	flushw
1473	rdpr	%cwp, %g6
1474	wrpr	%g5, %cwp
1475	RESTORE_WREGS(%g2, %g5)
1476	wrpr	%g6, %cwp
1477	restored
1478	restore
1479
1480	ba,a    fast_trap_done
1481	SET_SIZE(opl_ta3_trap)
1482
1483	ENTRY_NP(opl_cleanw_subr)
1484	set	trap, %g1
1485	mov	T_FLUSHW, %g3
1486	sub	%g0, 1, %g4
1487	rdpr	%cwp, %g5
1488	SAVE_WREGS(%g2, %g6)
1489	save
1490	flushw
1491	rdpr	%cwp, %g6
1492	wrpr	%g5, %cwp
1493	RESTORE_WREGS(%g2, %g5)
1494	wrpr	%g6, %cwp
1495	restored
1496	restore
1497	jmp	%g7
1498	  nop
1499	SET_SIZE(opl_cleanw_subr)
1500
1501/*
1502 * The actual trap handler for tt=0x0a, and tt=0x32
1503 */
1504	ENTRY_NP(opl_serr_instr)
1505	OPL_SAVE_GLOBAL(%g1,%g2,%g3)
1506	sethi   %hi(opl_sync_trap), %g3
1507	jmp	%g3 + %lo(opl_sync_trap)
1508	 rdpr    %tt, %g1
1509	.align  32
1510	SET_SIZE(opl_serr_instr)
1511
1512/*
1513 * The actual trap handler for tt=0x40
1514 */
1515	ENTRY_NP(opl_ugerr_instr)
1516	sethi   %hi(opl_uger_trap), %g3
1517	jmp	%g3 + %lo(opl_uger_trap)
1518	 nop
1519	.align  32
1520	SET_SIZE(opl_ugerr_instr)
1521
1522/*
1523 * The actual trap handler for tt=0x103 (flushw)
1524 */
1525	ENTRY_NP(opl_ta3_instr)
1526	sethi   %hi(opl_ta3_trap), %g3
1527	jmp	%g3 + %lo(opl_ta3_trap)
1528	 nop
1529	.align  32
1530	SET_SIZE(opl_ta3_instr)
1531
1532/*
1533 * The patch for the .clean_windows code
1534 */
1535	ENTRY_NP(opl_ta4_instr)
1536	sethi   %hi(opl_cleanw_subr), %g3
1537	add	%g3, %lo(opl_cleanw_subr), %g3
1538	jmpl	%g3, %g7
1539	  add	%g7, 8, %g7
1540	nop
1541	nop
1542	nop
1543	SET_SIZE(opl_ta4_instr)
1544
1545	ENTRY_NP(stick_timestamp)
1546	rd	STICK, %g1	! read stick reg
1547	sllx	%g1, 1, %g1
1548	srlx	%g1, 1, %g1	! clear npt bit
1549
1550	retl
1551	stx	%g1, [%o0]	! store the timestamp
1552	SET_SIZE(stick_timestamp)
1553
1554
1555	ENTRY_NP(stick_adj)
1556	rdpr	%pstate, %g1		! save processor state
1557	andn	%g1, PSTATE_IE, %g3
1558	ba	1f			! cache align stick adj
1559	wrpr	%g0, %g3, %pstate	! turn off interrupts
1560
1561	.align	16
15621:	nop
1563
1564	rd	STICK, %g4		! read stick reg
1565	add	%g4, %o0, %o1		! adjust stick with skew
1566	wr	%o1, %g0, STICK		! write stick reg
1567
1568	retl
1569	wrpr	%g1, %pstate		! restore processor state
1570	SET_SIZE(stick_adj)
1571
1572	ENTRY_NP(kdi_get_stick)
1573	rd	STICK, %g1
1574	stx	%g1, [%o0]
1575	retl
1576	mov	%g0, %o0
1577	SET_SIZE(kdi_get_stick)
1578
1579	ENTRY(dtrace_blksuword32)
1580	save	%sp, -SA(MINFRAME + 4), %sp
1581
1582	rdpr	%pstate, %l1
1583	andn	%l1, PSTATE_IE, %l2		! disable interrupts to
1584	wrpr	%g0, %l2, %pstate		! protect our FPU diddling
1585
1586	rd	%fprs, %l0
1587	andcc	%l0, FPRS_FEF, %g0
1588	bz,a,pt	%xcc, 1f			! if the fpu is disabled
1589	wr	%g0, FPRS_FEF, %fprs		! ... enable the fpu
1590
1591	st	%f0, [%fp + STACK_BIAS - 4]	! save %f0 to the stack
15921:
1593	set	0f, %l5
1594	/*
1595	 * We're about to write a block full or either total garbage
1596	 * (not kernel data, don't worry) or user floating-point data
1597	 * (so it only _looks_ like garbage).
1598	 */
1599	ld	[%i1], %f0			! modify the block
1600	membar	#Sync
1601	stn	%l5, [THREAD_REG + T_LOFAULT]	! set up the lofault handler
1602	stda	%d0, [%i0]ASI_BLK_COMMIT_S	! store the modified block
1603	membar	#Sync
1604	flush	%i0				! flush instruction pipeline
1605	stn	%g0, [THREAD_REG + T_LOFAULT]	! remove the lofault handler
1606
1607	bz,a,pt	%xcc, 1f
1608	wr	%g0, %l0, %fprs			! restore %fprs
1609
1610	ld	[%fp + STACK_BIAS - 4], %f0	! restore %f0
16111:
1612
1613	wrpr	%g0, %l1, %pstate		! restore interrupts
1614
1615	ret
1616	restore	%g0, %g0, %o0
1617
16180:
1619	membar	#Sync
1620	stn	%g0, [THREAD_REG + T_LOFAULT]	! remove the lofault handler
1621
1622	bz,a,pt	%xcc, 1f
1623	wr	%g0, %l0, %fprs			! restore %fprs
1624
1625	ld	[%fp + STACK_BIAS - 4], %f0	! restore %f0
16261:
1627
1628	wrpr	%g0, %l1, %pstate		! restore interrupts
1629
1630	/*
1631	 * If tryagain is set (%i2) we tail-call dtrace_blksuword32_err()
1632	 * which deals with watchpoints. Otherwise, just return -1.
1633	 */
1634	brnz,pt	%i2, 1f
1635	nop
1636	ret
1637	restore	%g0, -1, %o0
16381:
1639	call	dtrace_blksuword32_err
1640	restore
1641
1642	SET_SIZE(dtrace_blksuword32)
1643
1644	ENTRY_NP(ras_cntr_reset)
1645	set	OPL_SCRATCHPAD_ERRLOG, %o1
1646	ldxa	[%o1]ASI_SCRATCHPAD, %o0
1647	or	%o0, ERRLOG_REG_NUMERR_MASK, %o0
1648	retl
1649	 stxa	%o0, [%o1]ASI_SCRATCHPAD
1650	SET_SIZE(ras_cntr_reset)
1651
1652	ENTRY_NP(opl_error_setup)
1653	/*
1654	 * Initialize the error log scratchpad register
1655	 */
1656	ldxa	[%g0]ASI_EIDR, %o2
1657	sethi	%hi(ERRLOG_REG_EIDR_MASK), %o1
1658	or	%o1, %lo(ERRLOG_REG_EIDR_MASK), %o1
1659	and	%o2, %o1, %o3
1660	sllx	%o3, ERRLOG_REG_EIDR_SHIFT, %o2
1661	or	%o2, %o0, %o3
1662	or	%o3, ERRLOG_REG_NUMERR_MASK, %o0
1663	set	OPL_SCRATCHPAD_ERRLOG, %o1
1664	stxa	%o0, [%o1]ASI_SCRATCHPAD
1665	/*
1666	 * Disable all restrainable error traps
1667	 */
1668	mov	AFSR_ECR, %o1
1669	ldxa	[%o1]ASI_AFSR, %o0
1670	andn	%o0, ASI_ECR_RTE_UE|ASI_ECR_RTE_CEDG, %o0
1671	retl
1672	  stxa	%o0, [%o1]ASI_AFSR
1673	SET_SIZE(opl_error_setup)
1674
1675	ENTRY_NP(cpu_early_feature_init)
1676	/*
1677	 * Enable MMU translating multiple page sizes for
1678	 * sITLB and sDTLB.
1679	 */
1680        mov	LSU_MCNTL, %o0
1681        ldxa	[%o0] ASI_MCNTL, %o1
1682        or	%o1, MCNTL_MPG_SITLB | MCNTL_MPG_SDTLB, %o1
1683          stxa	%o1, [%o0] ASI_MCNTL
1684	/*
1685	 * Demap all previous entries.
1686	 */
1687	sethi	%hi(FLUSH_ADDR), %o1
1688	set	DEMAP_ALL_TYPE, %o0
1689	stxa	%g0, [%o0]ASI_DTLB_DEMAP
1690	stxa	%g0, [%o0]ASI_ITLB_DEMAP
1691	retl
1692	  flush	%o1
1693	SET_SIZE(cpu_early_feature_init)
1694
1695/*
1696 * This function is called for each (enabled) CPU. We use it to
1697 * initialize error handling related registers.
1698 */
1699	ENTRY(cpu_feature_init)
1700	!
1701	! get the device_id and store the device_id
1702	! in the appropriate cpunodes structure
1703	! given the cpus index
1704	!
1705	CPU_INDEX(%o0, %o1)
1706	mulx %o0, CPU_NODE_SIZE, %o0
1707	set  cpunodes + DEVICE_ID, %o1
1708	ldxa [%g0] ASI_DEVICE_SERIAL_ID, %o2
1709	stx  %o2, [%o0 + %o1]
1710	!
1711	! initialize CPU registers
1712	!
1713	ba	opl_cpu_reg_init
1714	nop
1715	SET_SIZE(cpu_feature_init)
1716
1717	/*
1718	 * Clear the NPT (non-privileged trap) bit in the %tick/%stick
1719	 * registers. In an effort to make the change in the
1720	 * tick/stick counter as consistent as possible, we disable
1721	 * all interrupts while we're changing the registers. We also
1722	 * ensure that the read and write instructions are in the same
1723	 * line in the instruction cache.
1724	 */
1725	ENTRY_NP(cpu_clearticknpt)
1726	rdpr	%pstate, %g1		/* save processor state */
1727	andn	%g1, PSTATE_IE, %g3	/* turn off */
1728	wrpr	%g0, %g3, %pstate	/*   interrupts */
1729	rdpr	%tick, %g2		/* get tick register */
1730	brgez,pn %g2, 1f		/* if NPT bit off, we're done */
1731	mov	1, %g3			/* create mask */
1732	sllx	%g3, 63, %g3		/*   for NPT bit */
1733	ba,a,pt	%xcc, 2f
1734	.align	8			/* Ensure rd/wr in same i$ line */
17352:
1736	rdpr	%tick, %g2		/* get tick register */
1737	wrpr	%g3, %g2, %tick		/* write tick register, */
1738					/*   clearing NPT bit   */
17391:
1740	rd	STICK, %g2		/* get stick register */
1741	brgez,pn %g2, 3f		/* if NPT bit off, we're done */
1742	mov	1, %g3			/* create mask */
1743	sllx	%g3, 63, %g3		/*   for NPT bit */
1744	ba,a,pt	%xcc, 4f
1745	.align	8			/* Ensure rd/wr in same i$ line */
17464:
1747	rd	STICK, %g2		/* get stick register */
1748	wr	%g3, %g2, STICK		/* write stick register, */
1749					/*   clearing NPT bit   */
17503:
1751	jmp	%g4 + 4
1752	wrpr	%g0, %g1, %pstate	/* restore processor state */
1753
1754	SET_SIZE(cpu_clearticknpt)
1755
1756	/*
1757	 * Halt the current strand with the suspend instruction.
1758	 * The compiler/asm currently does not support this suspend
1759	 * instruction mnemonic, use byte code for now.
1760	 */
1761	ENTRY_NP(cpu_halt_cpu)
1762	.word   0x81b01040
1763	retl
1764	nop
1765	SET_SIZE(cpu_halt_cpu)
1766
1767	/*
1768	 * Pause the current strand with the sleep instruction.
1769	 * The compiler/asm currently does not support this sleep
1770	 * instruction mnemonic, use byte code for now.
1771	 */
1772	ENTRY_NP(cpu_smt_pause)
1773	.word   0x81b01060
1774	retl
1775	nop
1776	SET_SIZE(cpu_smt_pause)
1777