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