xref: /titanic_52/usr/src/uts/sun4u/cpu/opl_olympus_asm.s (revision c9d93b537520c235a6d4a0af53b9bf07cf3390e9)
125cf1a30Sjl139090/*
225cf1a30Sjl139090 * CDDL HEADER START
325cf1a30Sjl139090 *
425cf1a30Sjl139090 * The contents of this file are subject to the terms of the
525cf1a30Sjl139090 * Common Development and Distribution License (the "License").
625cf1a30Sjl139090 * You may not use this file except in compliance with the License.
725cf1a30Sjl139090 *
825cf1a30Sjl139090 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
925cf1a30Sjl139090 * or http://www.opensolaris.org/os/licensing.
1025cf1a30Sjl139090 * See the License for the specific language governing permissions
1125cf1a30Sjl139090 * and limitations under the License.
1225cf1a30Sjl139090 *
1325cf1a30Sjl139090 * When distributing Covered Code, include this CDDL HEADER in each
1425cf1a30Sjl139090 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1525cf1a30Sjl139090 * If applicable, add the following below this CDDL HEADER, with the
1625cf1a30Sjl139090 * fields enclosed by brackets "[]" replaced with your own identifying
1725cf1a30Sjl139090 * information: Portions Copyright [yyyy] [name of copyright owner]
1825cf1a30Sjl139090 *
1925cf1a30Sjl139090 * CDDL HEADER END
2025cf1a30Sjl139090 */
2125cf1a30Sjl139090/*
22*c9d93b53SJames Anderson * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2325cf1a30Sjl139090 * Use is subject to license terms.
2425cf1a30Sjl139090 *
2525cf1a30Sjl139090 * Assembly code support for the Olympus-C module
2625cf1a30Sjl139090 */
2725cf1a30Sjl139090
2825cf1a30Sjl139090#if !defined(lint)
2925cf1a30Sjl139090#include "assym.h"
3025cf1a30Sjl139090#endif	/* lint */
3125cf1a30Sjl139090
3225cf1a30Sjl139090#include <sys/asm_linkage.h>
3325cf1a30Sjl139090#include <sys/mmu.h>
3425cf1a30Sjl139090#include <vm/hat_sfmmu.h>
3525cf1a30Sjl139090#include <sys/machparam.h>
3625cf1a30Sjl139090#include <sys/machcpuvar.h>
3725cf1a30Sjl139090#include <sys/machthread.h>
3825cf1a30Sjl139090#include <sys/machtrap.h>
3925cf1a30Sjl139090#include <sys/privregs.h>
4025cf1a30Sjl139090#include <sys/asm_linkage.h>
4125cf1a30Sjl139090#include <sys/trap.h>
4225cf1a30Sjl139090#include <sys/opl_olympus_regs.h>
4325cf1a30Sjl139090#include <sys/opl_module.h>
4425cf1a30Sjl139090#include <sys/xc_impl.h>
4525cf1a30Sjl139090#include <sys/intreg.h>
4625cf1a30Sjl139090#include <sys/async.h>
4725cf1a30Sjl139090#include <sys/clock.h>
4825cf1a30Sjl139090#include <sys/cmpregs.h>
4925cf1a30Sjl139090
5025cf1a30Sjl139090#ifdef TRAPTRACE
5125cf1a30Sjl139090#include <sys/traptrace.h>
5225cf1a30Sjl139090#endif /* TRAPTRACE */
5325cf1a30Sjl139090
5425cf1a30Sjl139090/*
5525cf1a30Sjl139090 * Macro that flushes the entire Ecache.
5625cf1a30Sjl139090 *
5725cf1a30Sjl139090 * arg1 = ecache size
5825cf1a30Sjl139090 * arg2 = ecache linesize
5925cf1a30Sjl139090 * arg3 = ecache flush address - Not used for olympus-C
6025cf1a30Sjl139090 */
6125cf1a30Sjl139090#define	ECACHE_FLUSHALL(arg1, arg2, arg3, tmp1)				\
6225cf1a30Sjl139090	mov	ASI_L2_CTRL_U2_FLUSH, arg1;				\
6325cf1a30Sjl139090	mov	ASI_L2_CTRL_RW_ADDR, arg2;				\
6425cf1a30Sjl139090	stxa	arg1, [arg2]ASI_L2_CTRL
6525cf1a30Sjl139090
6625cf1a30Sjl139090/*
6725cf1a30Sjl139090 * SPARC64-VI MMU and Cache operations.
6825cf1a30Sjl139090 */
6925cf1a30Sjl139090
7025cf1a30Sjl139090#if defined(lint)
7125cf1a30Sjl139090
7225cf1a30Sjl139090/* ARGSUSED */
7325cf1a30Sjl139090void
741e2e7a75Shuahvtag_flushpage(caddr_t vaddr, uint64_t sfmmup)
7525cf1a30Sjl139090{}
7625cf1a30Sjl139090
7725cf1a30Sjl139090#else	/* lint */
7825cf1a30Sjl139090
7925cf1a30Sjl139090	ENTRY_NP(vtag_flushpage)
8025cf1a30Sjl139090	/*
8125cf1a30Sjl139090	 * flush page from the tlb
8225cf1a30Sjl139090	 *
8325cf1a30Sjl139090	 * %o0 = vaddr
841e2e7a75Shuah	 * %o1 = sfmmup
8525cf1a30Sjl139090	 */
8625cf1a30Sjl139090	rdpr	%pstate, %o5
8725cf1a30Sjl139090#ifdef DEBUG
881e2e7a75Shuah	PANIC_IF_INTR_DISABLED_PSTR(%o5, opl_di_l3, %g1)
8925cf1a30Sjl139090#endif /* DEBUG */
9025cf1a30Sjl139090	/*
9125cf1a30Sjl139090	 * disable ints
9225cf1a30Sjl139090	 */
9325cf1a30Sjl139090	andn	%o5, PSTATE_IE, %o4
9425cf1a30Sjl139090	wrpr	%o4, 0, %pstate
9525cf1a30Sjl139090
9625cf1a30Sjl139090	/*
9725cf1a30Sjl139090	 * Then, blow out the tlb
9825cf1a30Sjl139090	 * Interrupts are disabled to prevent the primary ctx register
9925cf1a30Sjl139090	 * from changing underneath us.
10025cf1a30Sjl139090	 */
1011e2e7a75Shuah	sethi   %hi(ksfmmup), %o3
1021e2e7a75Shuah        ldx     [%o3 + %lo(ksfmmup)], %o3
1031e2e7a75Shuah        cmp     %o3, %o1
1041e2e7a75Shuah        bne,pt   %xcc, 1f			! if not kernel as, go to 1
10525cf1a30Sjl139090	  sethi	%hi(FLUSH_ADDR), %o3
10625cf1a30Sjl139090	/*
1071e2e7a75Shuah	 * For Kernel demaps use primary. type = page implicitly
10825cf1a30Sjl139090	 */
10925cf1a30Sjl139090	stxa	%g0, [%o0]ASI_DTLB_DEMAP	/* dmmu flush for KCONTEXT */
11025cf1a30Sjl139090	stxa	%g0, [%o0]ASI_ITLB_DEMAP	/* immu flush for KCONTEXT */
11125cf1a30Sjl139090	flush	%o3
1121e2e7a75Shuah	retl
1131e2e7a75Shuah	  wrpr	%g0, %o5, %pstate		/* enable interrupts */
11425cf1a30Sjl1390901:
11525cf1a30Sjl139090	/*
11625cf1a30Sjl139090	 * User demap.  We need to set the primary context properly.
11725cf1a30Sjl139090	 * Secondary context cannot be used for SPARC64-VI IMMU.
11825cf1a30Sjl139090	 * %o0 = vaddr
1191e2e7a75Shuah	 * %o1 = sfmmup
12025cf1a30Sjl139090	 * %o3 = FLUSH_ADDR
12125cf1a30Sjl139090	 */
1221e2e7a75Shuah	SFMMU_CPU_CNUM(%o1, %g1, %g2)		! %g1 = sfmmu cnum on this CPU
1231e2e7a75Shuah
1241e2e7a75Shuah	ldub	[%o1 + SFMMU_CEXT], %o4		! %o4 = sfmmup->sfmmu_cext
12525cf1a30Sjl139090	sll	%o4, CTXREG_EXT_SHIFT, %o4
126febcc4a5Sjimand	or	%g1, %o4, %g1			! %g1 = primary pgsz | cnum
1271e2e7a75Shuah
12825cf1a30Sjl139090	wrpr	%g0, 1, %tl
12925cf1a30Sjl139090	set	MMU_PCONTEXT, %o4
13025cf1a30Sjl139090	or	DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %o0, %o0
1311e2e7a75Shuah	ldxa	[%o4]ASI_DMMU, %o2		! %o2 = save old ctxnum
132febcc4a5Sjimand	srlx	%o2, CTXREG_NEXT_SHIFT, %o1	! need to preserve nucleus pgsz
133febcc4a5Sjimand	sllx	%o1, CTXREG_NEXT_SHIFT, %o1	! %o1 = nucleus pgsz
134febcc4a5Sjimand	or	%g1, %o1, %g1			! %g1 = nucleus pgsz | primary pgsz | cnum
1351e2e7a75Shuah	stxa	%g1, [%o4]ASI_DMMU		! wr new ctxum
1361e2e7a75Shuah
13725cf1a30Sjl139090	stxa	%g0, [%o0]ASI_DTLB_DEMAP
13825cf1a30Sjl139090	stxa	%g0, [%o0]ASI_ITLB_DEMAP
13925cf1a30Sjl139090	stxa	%o2, [%o4]ASI_DMMU		/* restore old ctxnum */
14025cf1a30Sjl139090	flush	%o3
14125cf1a30Sjl139090	wrpr	%g0, 0, %tl
1421e2e7a75Shuah
14325cf1a30Sjl139090	retl
14425cf1a30Sjl139090	wrpr	%g0, %o5, %pstate		/* enable interrupts */
14525cf1a30Sjl139090	SET_SIZE(vtag_flushpage)
14625cf1a30Sjl139090
14725cf1a30Sjl139090#endif	/* lint */
14825cf1a30Sjl139090
14925cf1a30Sjl139090
15025cf1a30Sjl139090#if defined(lint)
15125cf1a30Sjl139090
15225cf1a30Sjl139090void
15325cf1a30Sjl139090vtag_flushall(void)
15425cf1a30Sjl139090{}
15525cf1a30Sjl139090
15625cf1a30Sjl139090#else	/* lint */
15725cf1a30Sjl139090
15825cf1a30Sjl139090	ENTRY_NP2(vtag_flushall, demap_all)
15925cf1a30Sjl139090	/*
16025cf1a30Sjl139090	 * flush the tlb
16125cf1a30Sjl139090	 */
16225cf1a30Sjl139090	sethi	%hi(FLUSH_ADDR), %o3
16325cf1a30Sjl139090	set	DEMAP_ALL_TYPE, %g1
16425cf1a30Sjl139090	stxa	%g0, [%g1]ASI_DTLB_DEMAP
16525cf1a30Sjl139090	stxa	%g0, [%g1]ASI_ITLB_DEMAP
16625cf1a30Sjl139090	flush	%o3
16725cf1a30Sjl139090	retl
16825cf1a30Sjl139090	nop
16925cf1a30Sjl139090	SET_SIZE(demap_all)
17025cf1a30Sjl139090	SET_SIZE(vtag_flushall)
17125cf1a30Sjl139090
17225cf1a30Sjl139090#endif	/* lint */
17325cf1a30Sjl139090
17425cf1a30Sjl139090
17525cf1a30Sjl139090#if defined(lint)
17625cf1a30Sjl139090
17725cf1a30Sjl139090/* ARGSUSED */
17825cf1a30Sjl139090void
1791e2e7a75Shuahvtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup)
18025cf1a30Sjl139090{}
18125cf1a30Sjl139090
18225cf1a30Sjl139090#else	/* lint */
18325cf1a30Sjl139090
18425cf1a30Sjl139090	ENTRY_NP(vtag_flushpage_tl1)
18525cf1a30Sjl139090	/*
18625cf1a30Sjl139090	 * x-trap to flush page from tlb and tsb
18725cf1a30Sjl139090	 *
18825cf1a30Sjl139090	 * %g1 = vaddr, zero-extended on 32-bit kernel
1891e2e7a75Shuah	 * %g2 = sfmmup
19025cf1a30Sjl139090	 *
19125cf1a30Sjl139090	 * assumes TSBE_TAG = 0
19225cf1a30Sjl139090	 */
19325cf1a30Sjl139090	srln	%g1, MMU_PAGESHIFT, %g1
1941e2e7a75Shuah
1951e2e7a75Shuah	sethi   %hi(ksfmmup), %g3
1961e2e7a75Shuah        ldx     [%g3 + %lo(ksfmmup)], %g3
1971e2e7a75Shuah        cmp     %g3, %g2
1981e2e7a75Shuah        bne,pt	%xcc, 1f                        ! if not kernel as, go to 1
19925cf1a30Sjl139090	  slln	%g1, MMU_PAGESHIFT, %g1		/* g1 = vaddr */
20025cf1a30Sjl139090
20125cf1a30Sjl139090	/* We need to demap in the kernel context */
20225cf1a30Sjl139090	or	DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1
20325cf1a30Sjl139090	stxa	%g0, [%g1]ASI_DTLB_DEMAP
20425cf1a30Sjl139090	stxa	%g0, [%g1]ASI_ITLB_DEMAP
20525cf1a30Sjl139090	retry
20625cf1a30Sjl1390901:
20725cf1a30Sjl139090	/* We need to demap in a user context */
20825cf1a30Sjl139090	or	DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1
2091e2e7a75Shuah
2101e2e7a75Shuah	SFMMU_CPU_CNUM(%g2, %g6, %g3)	! %g6 = sfmmu cnum on this CPU
2111e2e7a75Shuah
2121e2e7a75Shuah	ldub	[%g2 + SFMMU_CEXT], %g4		! %g4 = sfmmup->cext
21325cf1a30Sjl139090	sll	%g4, CTXREG_EXT_SHIFT, %g4
214febcc4a5Sjimand	or	%g6, %g4, %g6			! %g6 = primary pgsz | cnum
21525cf1a30Sjl139090
21625cf1a30Sjl139090	set	MMU_PCONTEXT, %g4
217febcc4a5Sjimand	ldxa	[%g4]ASI_DMMU, %g5		! %g5 = save old ctxnum
218febcc4a5Sjimand	srlx	%g5, CTXREG_NEXT_SHIFT, %g2	! %g2 = nucleus pgsz
219febcc4a5Sjimand	sllx	%g2, CTXREG_NEXT_SHIFT, %g2	! preserve nucleus pgsz
220febcc4a5Sjimand	or	%g6, %g2, %g6			! %g6 = nucleus pgsz | primary pgsz | cnum
221febcc4a5Sjimand	stxa	%g6, [%g4]ASI_DMMU		! wr new ctxum
22225cf1a30Sjl139090	stxa	%g0, [%g1]ASI_DTLB_DEMAP
22325cf1a30Sjl139090	stxa	%g0, [%g1]ASI_ITLB_DEMAP
224febcc4a5Sjimand	stxa	%g5, [%g4]ASI_DMMU		! restore old ctxnum
22525cf1a30Sjl139090	retry
22625cf1a30Sjl139090	SET_SIZE(vtag_flushpage_tl1)
22725cf1a30Sjl139090
22825cf1a30Sjl139090#endif	/* lint */
22925cf1a30Sjl139090
2301e2e7a75Shuah
23125cf1a30Sjl139090#if defined(lint)
23225cf1a30Sjl139090
23325cf1a30Sjl139090/* ARGSUSED */
23425cf1a30Sjl139090void
2351e2e7a75Shuahvtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt)
23625cf1a30Sjl139090{}
23725cf1a30Sjl139090
23825cf1a30Sjl139090#else	/* lint */
23925cf1a30Sjl139090
24025cf1a30Sjl139090	ENTRY_NP(vtag_flush_pgcnt_tl1)
24125cf1a30Sjl139090	/*
24225cf1a30Sjl139090	 * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb
24325cf1a30Sjl139090	 *
24425cf1a30Sjl139090	 * %g1 = vaddr, zero-extended on 32-bit kernel
2451e2e7a75Shuah	 * %g2 = <sfmmup58|pgcnt6>
24625cf1a30Sjl139090	 *
24725cf1a30Sjl139090	 * NOTE: this handler relies on the fact that no
24825cf1a30Sjl139090	 *	interrupts or traps can occur during the loop
24925cf1a30Sjl139090	 *	issuing the TLB_DEMAP operations. It is assumed
25025cf1a30Sjl139090	 *	that interrupts are disabled and this code is
25125cf1a30Sjl139090	 *	fetching from the kernel locked text address.
25225cf1a30Sjl139090	 *
25325cf1a30Sjl139090	 * assumes TSBE_TAG = 0
25425cf1a30Sjl139090	 */
2551e2e7a75Shuah	set	SFMMU_PGCNT_MASK, %g4
2561e2e7a75Shuah	and	%g4, %g2, %g3			/* g3 = pgcnt - 1 */
2571e2e7a75Shuah	add	%g3, 1, %g3			/* g3 = pgcnt */
2581e2e7a75Shuah
2591e2e7a75Shuah	andn	%g2, SFMMU_PGCNT_MASK, %g2	/* g2 = sfmmup */
26025cf1a30Sjl139090	srln	%g1, MMU_PAGESHIFT, %g1
2611e2e7a75Shuah
2621e2e7a75Shuah	sethi   %hi(ksfmmup), %g4
2631e2e7a75Shuah        ldx     [%g4 + %lo(ksfmmup)], %g4
2641e2e7a75Shuah        cmp     %g4, %g2
2651e2e7a75Shuah        bne,pn   %xcc, 1f			/* if not kernel as, go to 1 */
26625cf1a30Sjl139090	  slln	%g1, MMU_PAGESHIFT, %g1		/* g1 = vaddr */
26725cf1a30Sjl139090
26825cf1a30Sjl139090	/* We need to demap in the kernel context */
26925cf1a30Sjl139090	or	DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1
27025cf1a30Sjl139090	set	MMU_PAGESIZE, %g2		/* g2 = pgsize */
2711e2e7a75Shuah	sethi   %hi(FLUSH_ADDR), %g5
27225cf1a30Sjl1390904:
27325cf1a30Sjl139090	stxa	%g0, [%g1]ASI_DTLB_DEMAP
27425cf1a30Sjl139090	stxa	%g0, [%g1]ASI_ITLB_DEMAP
2751e2e7a75Shuah	flush	%g5				! flush required by immu
2761e2e7a75Shuah
27725cf1a30Sjl139090	deccc	%g3				/* decr pgcnt */
27825cf1a30Sjl139090	bnz,pt	%icc,4b
27925cf1a30Sjl139090	  add	%g1, %g2, %g1			/* next page */
28025cf1a30Sjl139090	retry
28125cf1a30Sjl1390901:
2821e2e7a75Shuah	/*
2831e2e7a75Shuah	 * We need to demap in a user context
2841e2e7a75Shuah	 *
2851e2e7a75Shuah	 * g2 = sfmmup
2861e2e7a75Shuah	 * g3 = pgcnt
2871e2e7a75Shuah	 */
2881e2e7a75Shuah	SFMMU_CPU_CNUM(%g2, %g5, %g6)		! %g5 = sfmmu cnum on this CPU
2891e2e7a75Shuah
29025cf1a30Sjl139090	or	DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1
2911e2e7a75Shuah
2921e2e7a75Shuah	ldub	[%g2 + SFMMU_CEXT], %g4		! %g4 = sfmmup->cext
29325cf1a30Sjl139090	sll	%g4, CTXREG_EXT_SHIFT, %g4
2941e2e7a75Shuah	or	%g5, %g4, %g5
29525cf1a30Sjl139090
29625cf1a30Sjl139090	set	MMU_PCONTEXT, %g4
2971e2e7a75Shuah	ldxa	[%g4]ASI_DMMU, %g6		/* rd old ctxnum */
298febcc4a5Sjimand	srlx	%g6, CTXREG_NEXT_SHIFT, %g2	/* %g2 = nucleus pgsz */
299febcc4a5Sjimand	sllx	%g2, CTXREG_NEXT_SHIFT, %g2	/* preserve nucleus pgsz */
300febcc4a5Sjimand	or	%g5, %g2, %g5			/* %g5 = nucleus pgsz | primary pgsz | cnum */
3011e2e7a75Shuah	stxa	%g5, [%g4]ASI_DMMU		/* wr new ctxum */
30225cf1a30Sjl139090
30325cf1a30Sjl139090	set	MMU_PAGESIZE, %g2		/* g2 = pgsize */
3041e2e7a75Shuah	sethi   %hi(FLUSH_ADDR), %g5
30525cf1a30Sjl1390903:
30625cf1a30Sjl139090	stxa	%g0, [%g1]ASI_DTLB_DEMAP
30725cf1a30Sjl139090	stxa	%g0, [%g1]ASI_ITLB_DEMAP
3081e2e7a75Shuah	flush	%g5				! flush required by immu
3091e2e7a75Shuah
31025cf1a30Sjl139090	deccc	%g3				/* decr pgcnt */
31125cf1a30Sjl139090	bnz,pt	%icc,3b
31225cf1a30Sjl139090	  add	%g1, %g2, %g1			/* next page */
31325cf1a30Sjl139090
3141e2e7a75Shuah	stxa	%g6, [%g4]ASI_DMMU		/* restore old ctxnum */
31525cf1a30Sjl139090	retry
31625cf1a30Sjl139090	SET_SIZE(vtag_flush_pgcnt_tl1)
31725cf1a30Sjl139090
31825cf1a30Sjl139090#endif	/* lint */
31925cf1a30Sjl139090
32025cf1a30Sjl139090
32125cf1a30Sjl139090#if defined(lint)
32225cf1a30Sjl139090
32325cf1a30Sjl139090/*ARGSUSED*/
32425cf1a30Sjl139090void
32525cf1a30Sjl139090vtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2)
32625cf1a30Sjl139090{}
32725cf1a30Sjl139090
32825cf1a30Sjl139090#else	/* lint */
32925cf1a30Sjl139090
33025cf1a30Sjl139090	ENTRY_NP(vtag_flushall_tl1)
33125cf1a30Sjl139090	/*
33225cf1a30Sjl139090	 * x-trap to flush tlb
33325cf1a30Sjl139090	 */
33425cf1a30Sjl139090	set	DEMAP_ALL_TYPE, %g4
33525cf1a30Sjl139090	stxa	%g0, [%g4]ASI_DTLB_DEMAP
33625cf1a30Sjl139090	stxa	%g0, [%g4]ASI_ITLB_DEMAP
33725cf1a30Sjl139090	retry
33825cf1a30Sjl139090	SET_SIZE(vtag_flushall_tl1)
33925cf1a30Sjl139090
34025cf1a30Sjl139090#endif	/* lint */
34125cf1a30Sjl139090
34225cf1a30Sjl139090
34325cf1a30Sjl139090/*
34425cf1a30Sjl139090 * VAC (virtual address conflict) does not apply to OPL.
34525cf1a30Sjl139090 * VAC resolution is managed by the Olympus processor hardware.
34625cf1a30Sjl139090 * As a result, all OPL VAC flushing routines are no-ops.
34725cf1a30Sjl139090 */
34825cf1a30Sjl139090
34925cf1a30Sjl139090#if defined(lint)
35025cf1a30Sjl139090
35125cf1a30Sjl139090/* ARGSUSED */
35225cf1a30Sjl139090void
35325cf1a30Sjl139090vac_flushpage(pfn_t pfnum, int vcolor)
35425cf1a30Sjl139090{}
35525cf1a30Sjl139090
35625cf1a30Sjl139090#else	/* lint */
35725cf1a30Sjl139090
35825cf1a30Sjl139090	ENTRY(vac_flushpage)
35925cf1a30Sjl139090	retl
36025cf1a30Sjl139090	  nop
36125cf1a30Sjl139090	SET_SIZE(vac_flushpage)
36225cf1a30Sjl139090
36325cf1a30Sjl139090#endif	/* lint */
36425cf1a30Sjl139090
36525cf1a30Sjl139090#if defined(lint)
36625cf1a30Sjl139090
36725cf1a30Sjl139090/* ARGSUSED */
36825cf1a30Sjl139090void
36925cf1a30Sjl139090vac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor)
37025cf1a30Sjl139090{}
37125cf1a30Sjl139090
37225cf1a30Sjl139090#else	/* lint */
37325cf1a30Sjl139090
37425cf1a30Sjl139090	ENTRY_NP(vac_flushpage_tl1)
37525cf1a30Sjl139090	retry
37625cf1a30Sjl139090	SET_SIZE(vac_flushpage_tl1)
37725cf1a30Sjl139090
37825cf1a30Sjl139090#endif	/* lint */
37925cf1a30Sjl139090
38025cf1a30Sjl139090
38125cf1a30Sjl139090#if defined(lint)
38225cf1a30Sjl139090
38325cf1a30Sjl139090/* ARGSUSED */
38425cf1a30Sjl139090void
38525cf1a30Sjl139090vac_flushcolor(int vcolor, pfn_t pfnum)
38625cf1a30Sjl139090{}
38725cf1a30Sjl139090
38825cf1a30Sjl139090#else	/* lint */
38925cf1a30Sjl139090
39025cf1a30Sjl139090	ENTRY(vac_flushcolor)
39125cf1a30Sjl139090	retl
39225cf1a30Sjl139090	 nop
39325cf1a30Sjl139090	SET_SIZE(vac_flushcolor)
39425cf1a30Sjl139090
39525cf1a30Sjl139090#endif  /* lint */
39625cf1a30Sjl139090
39725cf1a30Sjl139090
39825cf1a30Sjl139090
39925cf1a30Sjl139090#if defined(lint)
40025cf1a30Sjl139090
40125cf1a30Sjl139090/* ARGSUSED */
40225cf1a30Sjl139090void
40325cf1a30Sjl139090vac_flushcolor_tl1(uint64_t vcolor, uint64_t pfnum)
40425cf1a30Sjl139090{}
40525cf1a30Sjl139090
40625cf1a30Sjl139090#else	/* lint */
40725cf1a30Sjl139090
40825cf1a30Sjl139090	ENTRY(vac_flushcolor_tl1)
40925cf1a30Sjl139090	retry
41025cf1a30Sjl139090	SET_SIZE(vac_flushcolor_tl1)
41125cf1a30Sjl139090
41225cf1a30Sjl139090#endif	/* lint */
41325cf1a30Sjl139090
41425cf1a30Sjl139090#if defined(lint)
41525cf1a30Sjl139090
41625cf1a30Sjl139090int
41725cf1a30Sjl139090idsr_busy(void)
41825cf1a30Sjl139090{
41925cf1a30Sjl139090	return (0);
42025cf1a30Sjl139090}
42125cf1a30Sjl139090
42225cf1a30Sjl139090#else	/* lint */
42325cf1a30Sjl139090
42425cf1a30Sjl139090/*
42525cf1a30Sjl139090 * Determine whether or not the IDSR is busy.
42625cf1a30Sjl139090 * Entry: no arguments
42725cf1a30Sjl139090 * Returns: 1 if busy, 0 otherwise
42825cf1a30Sjl139090 */
42925cf1a30Sjl139090	ENTRY(idsr_busy)
43025cf1a30Sjl139090	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %g1
43125cf1a30Sjl139090	clr	%o0
43225cf1a30Sjl139090	btst	IDSR_BUSY, %g1
43325cf1a30Sjl139090	bz,a,pt	%xcc, 1f
43425cf1a30Sjl139090	mov	1, %o0
43525cf1a30Sjl1390901:
43625cf1a30Sjl139090	retl
43725cf1a30Sjl139090	nop
43825cf1a30Sjl139090	SET_SIZE(idsr_busy)
43925cf1a30Sjl139090
44025cf1a30Sjl139090#endif	/* lint */
44125cf1a30Sjl139090
44225cf1a30Sjl139090#if defined(lint)
44325cf1a30Sjl139090
44425cf1a30Sjl139090/* ARGSUSED */
44525cf1a30Sjl139090void
44625cf1a30Sjl139090init_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2)
44725cf1a30Sjl139090{}
44825cf1a30Sjl139090
44925cf1a30Sjl139090/* ARGSUSED */
45025cf1a30Sjl139090void
45125cf1a30Sjl139090init_mondo_nocheck(xcfunc_t *func, uint64_t arg1, uint64_t arg2)
45225cf1a30Sjl139090{}
45325cf1a30Sjl139090
45425cf1a30Sjl139090#else	/* lint */
45525cf1a30Sjl139090
45625cf1a30Sjl139090	.global _dispatch_status_busy
45725cf1a30Sjl139090_dispatch_status_busy:
45825cf1a30Sjl139090	.asciz	"ASI_INTR_DISPATCH_STATUS error: busy"
45925cf1a30Sjl139090	.align	4
46025cf1a30Sjl139090
46125cf1a30Sjl139090/*
46225cf1a30Sjl139090 * Setup interrupt dispatch data registers
46325cf1a30Sjl139090 * Entry:
46425cf1a30Sjl139090 *	%o0 - function or inumber to call
46525cf1a30Sjl139090 *	%o1, %o2 - arguments (2 uint64_t's)
46625cf1a30Sjl139090 */
46725cf1a30Sjl139090	.seg "text"
46825cf1a30Sjl139090
46925cf1a30Sjl139090	ENTRY(init_mondo)
47025cf1a30Sjl139090#ifdef DEBUG
47125cf1a30Sjl139090	!
47225cf1a30Sjl139090	! IDSR should not be busy at the moment
47325cf1a30Sjl139090	!
47425cf1a30Sjl139090	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %g1
47525cf1a30Sjl139090	btst	IDSR_BUSY, %g1
47625cf1a30Sjl139090	bz,pt	%xcc, 1f
47725cf1a30Sjl139090	nop
47825cf1a30Sjl139090	sethi	%hi(_dispatch_status_busy), %o0
47925cf1a30Sjl139090	call	panic
48025cf1a30Sjl139090	or	%o0, %lo(_dispatch_status_busy), %o0
48125cf1a30Sjl139090#endif /* DEBUG */
48225cf1a30Sjl139090
48325cf1a30Sjl139090	ALTENTRY(init_mondo_nocheck)
48425cf1a30Sjl139090	!
48525cf1a30Sjl139090	! interrupt vector dispatch data reg 0
48625cf1a30Sjl139090	!
48725cf1a30Sjl1390901:
48825cf1a30Sjl139090	mov	IDDR_0, %g1
48925cf1a30Sjl139090	mov	IDDR_1, %g2
49025cf1a30Sjl139090	mov	IDDR_2, %g3
49125cf1a30Sjl139090	stxa	%o0, [%g1]ASI_INTR_DISPATCH
49225cf1a30Sjl139090
49325cf1a30Sjl139090	!
49425cf1a30Sjl139090	! interrupt vector dispatch data reg 1
49525cf1a30Sjl139090	!
49625cf1a30Sjl139090	stxa	%o1, [%g2]ASI_INTR_DISPATCH
49725cf1a30Sjl139090
49825cf1a30Sjl139090	!
49925cf1a30Sjl139090	! interrupt vector dispatch data reg 2
50025cf1a30Sjl139090	!
50125cf1a30Sjl139090	stxa	%o2, [%g3]ASI_INTR_DISPATCH
50225cf1a30Sjl139090
50325cf1a30Sjl139090	membar	#Sync
50425cf1a30Sjl139090	retl
50525cf1a30Sjl139090	nop
50625cf1a30Sjl139090	SET_SIZE(init_mondo_nocheck)
50725cf1a30Sjl139090	SET_SIZE(init_mondo)
50825cf1a30Sjl139090
50925cf1a30Sjl139090#endif	/* lint */
51025cf1a30Sjl139090
51125cf1a30Sjl139090
51225cf1a30Sjl139090#if defined(lint)
51325cf1a30Sjl139090
51425cf1a30Sjl139090/* ARGSUSED */
51525cf1a30Sjl139090void
51625cf1a30Sjl139090shipit(int upaid, int bn)
51725cf1a30Sjl139090{ return; }
51825cf1a30Sjl139090
51925cf1a30Sjl139090#else	/* lint */
52025cf1a30Sjl139090
52125cf1a30Sjl139090/*
52225cf1a30Sjl139090 * Ship mondo to aid using busy/nack pair bn
52325cf1a30Sjl139090 */
52425cf1a30Sjl139090	ENTRY_NP(shipit)
52525cf1a30Sjl139090	sll	%o0, IDCR_PID_SHIFT, %g1	! IDCR<23:14> = agent id
52625cf1a30Sjl139090	sll	%o1, IDCR_BN_SHIFT, %g2		! IDCR<28:24> = b/n pair
52725cf1a30Sjl139090	or	%g1, IDCR_OFFSET, %g1		! IDCR<13:0> = 0x70
52825cf1a30Sjl139090	or	%g1, %g2, %g1
52925cf1a30Sjl139090	stxa	%g0, [%g1]ASI_INTR_DISPATCH	! interrupt vector dispatch
53025cf1a30Sjl139090	membar	#Sync
53125cf1a30Sjl139090	retl
53225cf1a30Sjl139090	nop
53325cf1a30Sjl139090	SET_SIZE(shipit)
53425cf1a30Sjl139090
53525cf1a30Sjl139090#endif	/* lint */
53625cf1a30Sjl139090
53725cf1a30Sjl139090
53825cf1a30Sjl139090#if defined(lint)
53925cf1a30Sjl139090
54025cf1a30Sjl139090/* ARGSUSED */
54125cf1a30Sjl139090void
54225cf1a30Sjl139090flush_instr_mem(caddr_t vaddr, size_t len)
54325cf1a30Sjl139090{}
54425cf1a30Sjl139090
54525cf1a30Sjl139090#else	/* lint */
54625cf1a30Sjl139090
54725cf1a30Sjl139090/*
54825cf1a30Sjl139090 * flush_instr_mem:
54925cf1a30Sjl139090 *	Flush 1 page of the I-$ starting at vaddr
55025cf1a30Sjl139090 * 	%o0 vaddr
55125cf1a30Sjl139090 *	%o1 bytes to be flushed
55225cf1a30Sjl139090 *
55325cf1a30Sjl139090 * SPARC64-VI maintains consistency of the on-chip Instruction Cache with
55425cf1a30Sjl139090 * the stores from all processors so that a FLUSH instruction is only needed
55525cf1a30Sjl139090 * to ensure pipeline is consistent. This means a single flush is sufficient at
55625cf1a30Sjl139090 * the end of a sequence of stores that updates the instruction stream to
55725cf1a30Sjl139090 * ensure correct operation.
55825cf1a30Sjl139090 */
55925cf1a30Sjl139090
56025cf1a30Sjl139090	ENTRY(flush_instr_mem)
56163360950Smp204432	flush	%o0			! address irrelevant
56225cf1a30Sjl139090	retl
56325cf1a30Sjl139090	nop
56425cf1a30Sjl139090	SET_SIZE(flush_instr_mem)
56525cf1a30Sjl139090
56625cf1a30Sjl139090#endif	/* lint */
56725cf1a30Sjl139090
56825cf1a30Sjl139090
56925cf1a30Sjl139090/*
57025cf1a30Sjl139090 * flush_ecache:
57125cf1a30Sjl139090 *	%o0 - 64 bit physical address
57225cf1a30Sjl139090 *	%o1 - ecache size
57325cf1a30Sjl139090 *	%o2 - ecache linesize
57425cf1a30Sjl139090 */
57525cf1a30Sjl139090#if defined(lint)
57625cf1a30Sjl139090
57725cf1a30Sjl139090/*ARGSUSED*/
57825cf1a30Sjl139090void
57925cf1a30Sjl139090flush_ecache(uint64_t physaddr, size_t ecache_size, size_t ecache_linesize)
58025cf1a30Sjl139090{}
58125cf1a30Sjl139090
58225cf1a30Sjl139090#else /* !lint */
58325cf1a30Sjl139090
58425cf1a30Sjl139090	ENTRY(flush_ecache)
58525cf1a30Sjl139090
58625cf1a30Sjl139090	/*
58725cf1a30Sjl139090	 * Flush the entire Ecache.
58825cf1a30Sjl139090	 */
58925cf1a30Sjl139090	ECACHE_FLUSHALL(%o1, %o2, %o0, %o4)
59025cf1a30Sjl139090	retl
59125cf1a30Sjl139090	nop
59225cf1a30Sjl139090	SET_SIZE(flush_ecache)
59325cf1a30Sjl139090
59425cf1a30Sjl139090#endif /* lint */
59525cf1a30Sjl139090
59625cf1a30Sjl139090#if defined(lint)
59725cf1a30Sjl139090
59825cf1a30Sjl139090/*ARGSUSED*/
59925cf1a30Sjl139090void
60025cf1a30Sjl139090kdi_flush_idcache(int dcache_size, int dcache_lsize, int icache_size,
60125cf1a30Sjl139090    int icache_lsize)
60225cf1a30Sjl139090{
60325cf1a30Sjl139090}
60425cf1a30Sjl139090
60525cf1a30Sjl139090#else	/* lint */
60625cf1a30Sjl139090
60725cf1a30Sjl139090	/*
60825cf1a30Sjl139090	 * I/D cache flushing is not needed for OPL processors
60925cf1a30Sjl139090	 */
61025cf1a30Sjl139090	ENTRY(kdi_flush_idcache)
61125cf1a30Sjl139090	retl
61225cf1a30Sjl139090	nop
61325cf1a30Sjl139090	SET_SIZE(kdi_flush_idcache)
61425cf1a30Sjl139090
61525cf1a30Sjl139090#endif	/* lint */
61625cf1a30Sjl139090
61725cf1a30Sjl139090#ifdef	TRAPTRACE
61825cf1a30Sjl139090/*
61925cf1a30Sjl139090 * Simplified trap trace macro for OPL. Adapted from us3.
62025cf1a30Sjl139090 */
62125cf1a30Sjl139090#define	OPL_TRAPTRACE(ptr, scr1, scr2, label)			\
62225cf1a30Sjl139090	CPU_INDEX(scr1, ptr);					\
62325cf1a30Sjl139090	sll	scr1, TRAPTR_SIZE_SHIFT, scr1;			\
62425cf1a30Sjl139090	set	trap_trace_ctl, ptr;				\
62525cf1a30Sjl139090	add	ptr, scr1, scr1;				\
62625cf1a30Sjl139090	ld	[scr1 + TRAPTR_LIMIT], ptr;			\
62725cf1a30Sjl139090	tst	ptr;						\
62825cf1a30Sjl139090	be,pn	%icc, label/**/1;				\
62925cf1a30Sjl139090	 ldx	[scr1 + TRAPTR_PBASE], ptr;			\
63025cf1a30Sjl139090	ld	[scr1 + TRAPTR_OFFSET], scr1;			\
63125cf1a30Sjl139090	add	ptr, scr1, ptr;					\
63225cf1a30Sjl139090	rd	%asi, scr2;					\
63325cf1a30Sjl139090	wr	%g0, TRAPTR_ASI, %asi;				\
63425cf1a30Sjl139090	rd	STICK, scr1;					\
63525cf1a30Sjl139090	stxa    scr1, [ptr + TRAP_ENT_TICK]%asi;		\
63625cf1a30Sjl139090	rdpr	%tl, scr1;					\
63725cf1a30Sjl139090	stha    scr1, [ptr + TRAP_ENT_TL]%asi;			\
63825cf1a30Sjl139090	rdpr	%tt, scr1;					\
63925cf1a30Sjl139090	stha	scr1, [ptr + TRAP_ENT_TT]%asi;			\
64025cf1a30Sjl139090	rdpr	%tpc, scr1;					\
64125cf1a30Sjl139090	stna    scr1, [ptr + TRAP_ENT_TPC]%asi;			\
64225cf1a30Sjl139090	rdpr	%tstate, scr1;					\
64325cf1a30Sjl139090	stxa	scr1, [ptr + TRAP_ENT_TSTATE]%asi;		\
64425cf1a30Sjl139090	stna    %sp, [ptr + TRAP_ENT_SP]%asi;			\
64525cf1a30Sjl139090	stna    %g0, [ptr + TRAP_ENT_TR]%asi;			\
64625cf1a30Sjl139090	stna    %g0, [ptr + TRAP_ENT_F1]%asi;			\
64725cf1a30Sjl139090	stna    %g0, [ptr + TRAP_ENT_F2]%asi;			\
64825cf1a30Sjl139090	stna    %g0, [ptr + TRAP_ENT_F3]%asi;			\
64925cf1a30Sjl139090	stna    %g0, [ptr + TRAP_ENT_F4]%asi;			\
65025cf1a30Sjl139090	wr	%g0, scr2, %asi;				\
65125cf1a30Sjl139090	CPU_INDEX(ptr, scr1);					\
65225cf1a30Sjl139090	sll	ptr, TRAPTR_SIZE_SHIFT, ptr;			\
65325cf1a30Sjl139090	set	trap_trace_ctl, scr1;				\
65425cf1a30Sjl139090	add	scr1, ptr, ptr;					\
65525cf1a30Sjl139090	ld	[ptr + TRAPTR_OFFSET], scr1;			\
65625cf1a30Sjl139090	ld	[ptr + TRAPTR_LIMIT], scr2;			\
65725cf1a30Sjl139090	st	scr1, [ptr + TRAPTR_LAST_OFFSET];		\
65825cf1a30Sjl139090	add	scr1, TRAP_ENT_SIZE, scr1;			\
65925cf1a30Sjl139090	sub	scr2, TRAP_ENT_SIZE, scr2;			\
66025cf1a30Sjl139090	cmp	scr1, scr2;					\
66125cf1a30Sjl139090	movge	%icc, 0, scr1;					\
66225cf1a30Sjl139090	st	scr1, [ptr + TRAPTR_OFFSET];			\
66325cf1a30Sjl139090label/**/1:
66425cf1a30Sjl139090#endif	/* TRAPTRACE */
66525cf1a30Sjl139090
66625cf1a30Sjl139090
66725cf1a30Sjl139090
66825cf1a30Sjl139090/*
66925cf1a30Sjl139090 * Macros facilitating error handling.
67025cf1a30Sjl139090 */
67125cf1a30Sjl139090
67225cf1a30Sjl139090/*
67325cf1a30Sjl139090 * Save alternative global registers reg1, reg2, reg3
67425cf1a30Sjl139090 * to scratchpad registers 1, 2, 3 respectively.
67525cf1a30Sjl139090 */
67625cf1a30Sjl139090#define	OPL_SAVE_GLOBAL(reg1, reg2, reg3)	\
67725cf1a30Sjl139090	stxa	reg1, [%g0]ASI_SCRATCHPAD		;\
67825cf1a30Sjl139090	mov	OPL_SCRATCHPAD_SAVE_AG2, reg1	;\
67925cf1a30Sjl139090	stxa	reg2, [reg1]ASI_SCRATCHPAD		;\
68025cf1a30Sjl139090	mov	OPL_SCRATCHPAD_SAVE_AG3, reg1	;\
68125cf1a30Sjl139090	stxa	reg3, [reg1]ASI_SCRATCHPAD
68225cf1a30Sjl139090
68325cf1a30Sjl139090/*
68425cf1a30Sjl139090 * Restore alternative global registers reg1, reg2, reg3
68525cf1a30Sjl139090 * from scratchpad registers 1, 2, 3 respectively.
68625cf1a30Sjl139090 */
68725cf1a30Sjl139090#define	OPL_RESTORE_GLOBAL(reg1, reg2, reg3)			\
68825cf1a30Sjl139090	mov	OPL_SCRATCHPAD_SAVE_AG3, reg1			;\
68925cf1a30Sjl139090	ldxa	[reg1]ASI_SCRATCHPAD, reg3				;\
69025cf1a30Sjl139090	mov	OPL_SCRATCHPAD_SAVE_AG2, reg1			;\
69125cf1a30Sjl139090	ldxa	[reg1]ASI_SCRATCHPAD, reg2				;\
69225cf1a30Sjl139090	ldxa	[%g0]ASI_SCRATCHPAD, reg1
69325cf1a30Sjl139090
69425cf1a30Sjl139090/*
69525cf1a30Sjl139090 * Logs value `val' into the member `offset' of a structure
69625cf1a30Sjl139090 * at physical address `pa'
69725cf1a30Sjl139090 */
69825cf1a30Sjl139090#define	LOG_REG(pa, offset, val)				\
69925cf1a30Sjl139090	add	pa, offset, pa					;\
70025cf1a30Sjl139090	stxa	val, [pa]ASI_MEM
70125cf1a30Sjl139090
70225cf1a30Sjl139090#define	FLUSH_ALL_TLB(tmp1)					\
70325cf1a30Sjl139090	set	DEMAP_ALL_TYPE, tmp1				;\
70425cf1a30Sjl139090	stxa	%g0, [tmp1]ASI_ITLB_DEMAP			;\
70525cf1a30Sjl139090	stxa	%g0, [tmp1]ASI_DTLB_DEMAP			;\
70625cf1a30Sjl139090	sethi	%hi(FLUSH_ADDR), tmp1				;\
70725cf1a30Sjl139090	flush	tmp1
70825cf1a30Sjl139090
70925cf1a30Sjl139090/*
71025cf1a30Sjl139090 * Extracts the Physaddr to Logging Buffer field of the OPL_SCRATCHPAD_ERRLOG
71125cf1a30Sjl139090 * scratch register by zeroing all other fields. Result is in pa.
71225cf1a30Sjl139090 */
71325cf1a30Sjl139090#define	LOG_ADDR(pa)							\
71425cf1a30Sjl139090	mov	OPL_SCRATCHPAD_ERRLOG, pa				;\
71525cf1a30Sjl139090	ldxa	[pa]ASI_SCRATCHPAD, pa					;\
71625cf1a30Sjl139090	sllx	pa, 64-ERRLOG_REG_EIDR_SHIFT, pa			;\
71725cf1a30Sjl139090	srlx	pa, 64-ERRLOG_REG_EIDR_SHIFT+ERRLOG_REG_ERR_SHIFT, pa	;\
71825cf1a30Sjl139090	sllx	pa, ERRLOG_REG_ERR_SHIFT, pa
71925cf1a30Sjl139090
72025cf1a30Sjl139090/*
72125cf1a30Sjl139090 * Advance the per-cpu error log buffer pointer to the next
72225cf1a30Sjl139090 * ERRLOG_SZ entry, making sure that it will modulo (wraparound)
72325cf1a30Sjl139090 * ERRLOG_BUFSIZ boundary. The args logpa, bufmask, tmp are
72425cf1a30Sjl139090 * unused input registers for this macro.
72525cf1a30Sjl139090 *
72625cf1a30Sjl139090 * Algorithm:
72725cf1a30Sjl139090 * 1. logpa = contents of errorlog scratchpad register
72825cf1a30Sjl139090 * 2. bufmask = ERRLOG_BUFSIZ - 1
72925cf1a30Sjl139090 * 3. tmp = logpa & ~(bufmask)     (tmp is now logbase)
73025cf1a30Sjl139090 * 4. logpa += ERRLOG_SZ
73125cf1a30Sjl139090 * 5. logpa = logpa & bufmask      (get new offset to logbase)
73225cf1a30Sjl139090 * 4. logpa = tmp | logpa
73325cf1a30Sjl139090 * 7. write logpa back into errorlog scratchpad register
73425cf1a30Sjl139090 *
73525cf1a30Sjl139090 * new logpa = (logpa & ~bufmask) | ((logpa + ERRLOG_SZ) & bufmask)
73625cf1a30Sjl139090 *
73725cf1a30Sjl139090 */
73825cf1a30Sjl139090#define	UPDATE_LOGADD(logpa, bufmask, tmp)			\
73925cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, tmp			;\
74025cf1a30Sjl139090	ldxa	[tmp]ASI_SCRATCHPAD, logpa				;\
74125cf1a30Sjl139090	set	(ERRLOG_BUFSZ-1), bufmask			;\
74225cf1a30Sjl139090	andn	logpa, bufmask, tmp				;\
74325cf1a30Sjl139090	add	logpa, ERRLOG_SZ, logpa				;\
74425cf1a30Sjl139090	and	logpa, bufmask, logpa				;\
74525cf1a30Sjl139090	or	tmp, logpa, logpa				;\
74625cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, tmp			;\
74725cf1a30Sjl139090	stxa	logpa, [tmp]ASI_SCRATCHPAD
74825cf1a30Sjl139090
74925cf1a30Sjl139090/* Log error status registers into the log buffer */
75025cf1a30Sjl139090#define	LOG_SYNC_REG(sfsr, sfar, tmp)				\
75125cf1a30Sjl139090	LOG_ADDR(tmp)						;\
75225cf1a30Sjl139090	LOG_REG(tmp, LOG_SFSR_OFF, sfsr)			;\
75325cf1a30Sjl139090	LOG_ADDR(tmp)						;\
75425cf1a30Sjl139090	mov	tmp, sfsr					;\
75525cf1a30Sjl139090	LOG_REG(tmp, LOG_SFAR_OFF, sfar)			;\
75625cf1a30Sjl139090	rd	STICK, sfar					;\
75725cf1a30Sjl139090	mov	sfsr, tmp					;\
75825cf1a30Sjl139090	LOG_REG(tmp, LOG_STICK_OFF, sfar)			;\
75925cf1a30Sjl139090	rdpr	%tl, tmp					;\
76025cf1a30Sjl139090	sllx	tmp, 32, sfar					;\
76125cf1a30Sjl139090	rdpr	%tt, tmp					;\
76225cf1a30Sjl139090	or	sfar, tmp, sfar					;\
76325cf1a30Sjl139090	mov	sfsr, tmp					;\
76425cf1a30Sjl139090	LOG_REG(tmp, LOG_TL_OFF, sfar)				;\
76525cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, tmp			;\
76625cf1a30Sjl139090	ldxa	[tmp]ASI_SCRATCHPAD, sfar				;\
76725cf1a30Sjl139090	mov	sfsr, tmp					;\
76825cf1a30Sjl139090	LOG_REG(tmp, LOG_ASI3_OFF, sfar)			;\
76925cf1a30Sjl139090	rdpr	%tpc, sfar					;\
77025cf1a30Sjl139090	mov	sfsr, tmp					;\
77125cf1a30Sjl139090	LOG_REG(tmp, LOG_TPC_OFF, sfar)				;\
77225cf1a30Sjl139090	UPDATE_LOGADD(sfsr, sfar, tmp)
77325cf1a30Sjl139090
77425cf1a30Sjl139090#define	LOG_UGER_REG(uger, tmp, tmp2)				\
77525cf1a30Sjl139090	LOG_ADDR(tmp)						;\
77625cf1a30Sjl139090	mov	tmp, tmp2					;\
77725cf1a30Sjl139090	LOG_REG(tmp2, LOG_UGER_OFF, uger)			;\
77825cf1a30Sjl139090	mov	tmp, uger					;\
77925cf1a30Sjl139090	rd	STICK, tmp2					;\
78025cf1a30Sjl139090	LOG_REG(tmp, LOG_STICK_OFF, tmp2)			;\
78125cf1a30Sjl139090	rdpr	%tl, tmp					;\
78225cf1a30Sjl139090	sllx	tmp, 32, tmp2					;\
78325cf1a30Sjl139090	rdpr	%tt, tmp					;\
78425cf1a30Sjl139090	or	tmp2, tmp, tmp2					;\
78525cf1a30Sjl139090	mov	uger, tmp					;\
78625cf1a30Sjl139090	LOG_REG(tmp, LOG_TL_OFF, tmp2)				;\
78725cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, tmp2			;\
78825cf1a30Sjl139090	ldxa	[tmp2]ASI_SCRATCHPAD, tmp2				;\
78925cf1a30Sjl139090	mov	uger, tmp					;\
79025cf1a30Sjl139090	LOG_REG(tmp, LOG_ASI3_OFF, tmp2)			;\
79125cf1a30Sjl139090	rdpr	%tstate, tmp2					;\
79225cf1a30Sjl139090	mov	uger, tmp					;\
79325cf1a30Sjl139090	LOG_REG(tmp, LOG_TSTATE_OFF, tmp2)			;\
79425cf1a30Sjl139090	rdpr	%tpc, tmp2					;\
79525cf1a30Sjl139090	mov	uger, tmp					;\
79625cf1a30Sjl139090	LOG_REG(tmp, LOG_TPC_OFF, tmp2)				;\
79725cf1a30Sjl139090	UPDATE_LOGADD(uger, tmp, tmp2)
79825cf1a30Sjl139090
79925cf1a30Sjl139090/*
80025cf1a30Sjl139090 * Scrub the STICK_COMPARE register to clear error by updating
80125cf1a30Sjl139090 * it to a reasonable value for interrupt generation.
80225cf1a30Sjl139090 * Ensure that we observe the CPU_ENABLE flag so that we
80325cf1a30Sjl139090 * don't accidentally enable TICK interrupt in STICK_COMPARE
80425cf1a30Sjl139090 * i.e. no clock interrupt will be generated if CPU_ENABLE flag
80525cf1a30Sjl139090 * is off.
80625cf1a30Sjl139090 */
80725cf1a30Sjl139090#define	UPDATE_STICK_COMPARE(tmp1, tmp2)			\
80825cf1a30Sjl139090	CPU_ADDR(tmp1, tmp2)					;\
80925cf1a30Sjl139090	lduh	[tmp1 + CPU_FLAGS], tmp2			;\
81025cf1a30Sjl139090	andcc	tmp2, CPU_ENABLE, %g0 				;\
81125cf1a30Sjl139090	set	OPL_UGER_STICK_DIFF, tmp2			;\
81225cf1a30Sjl139090	rd	STICK, tmp1					;\
81325cf1a30Sjl139090	add	tmp1, tmp2, tmp1				;\
81425cf1a30Sjl139090	mov	1, tmp2						;\
81525cf1a30Sjl139090	sllx	tmp2, TICKINT_DIS_SHFT, tmp2			;\
81625cf1a30Sjl139090	or	tmp1, tmp2, tmp2				;\
81725cf1a30Sjl139090	movnz	%xcc, tmp1, tmp2				;\
81825cf1a30Sjl139090	wr	tmp2, %g0, STICK_COMPARE
81925cf1a30Sjl139090
82025cf1a30Sjl139090/*
82125cf1a30Sjl139090 * Reset registers that may be corrupted by IAUG_CRE error.
82225cf1a30Sjl139090 * To update interrupt handling related registers force the
82325cf1a30Sjl139090 * clock interrupt.
82425cf1a30Sjl139090 */
82525cf1a30Sjl139090#define	IAG_CRE(tmp1, tmp2)					\
82625cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, tmp1			;\
82725cf1a30Sjl139090	ldxa	[tmp1]ASI_SCRATCHPAD, tmp1				;\
82825cf1a30Sjl139090	srlx	tmp1, ERRLOG_REG_EIDR_SHIFT, tmp1		;\
82925cf1a30Sjl139090	set	ERRLOG_REG_EIDR_MASK, tmp2			;\
83025cf1a30Sjl139090	and	tmp1, tmp2, tmp1				;\
83125cf1a30Sjl139090	stxa	tmp1, [%g0]ASI_EIDR				;\
83225cf1a30Sjl139090	wr	%g0, 0, SOFTINT					;\
83325cf1a30Sjl139090	sethi	%hi(hres_last_tick), tmp1			;\
83425cf1a30Sjl139090	ldx	[tmp1 + %lo(hres_last_tick)], tmp1		;\
83525cf1a30Sjl139090	set	OPL_UGER_STICK_DIFF, tmp2			;\
83625cf1a30Sjl139090	add	tmp1, tmp2, tmp1				;\
83725cf1a30Sjl139090	wr	tmp1, %g0, STICK				;\
83825cf1a30Sjl139090	UPDATE_STICK_COMPARE(tmp1, tmp2)
83925cf1a30Sjl139090
84025cf1a30Sjl139090
84125cf1a30Sjl139090#define	CLEAR_FPREGS(tmp)					\
84225cf1a30Sjl139090	wr	%g0, FPRS_FEF, %fprs				;\
84325cf1a30Sjl139090	wr	%g0, %g0, %gsr					;\
84425cf1a30Sjl139090	sethi	%hi(opl_clr_freg), tmp				;\
84525cf1a30Sjl139090	or	tmp, %lo(opl_clr_freg), tmp			;\
84625cf1a30Sjl139090	ldx	[tmp], %fsr					;\
84725cf1a30Sjl139090	fzero	 %d0						;\
84825cf1a30Sjl139090	fzero	 %d2						;\
84925cf1a30Sjl139090	fzero	 %d4						;\
85025cf1a30Sjl139090	fzero	 %d6						;\
85125cf1a30Sjl139090	fzero	 %d8						;\
85225cf1a30Sjl139090	fzero	 %d10						;\
85325cf1a30Sjl139090	fzero	 %d12						;\
85425cf1a30Sjl139090	fzero	 %d14						;\
85525cf1a30Sjl139090	fzero	 %d16						;\
85625cf1a30Sjl139090	fzero	 %d18						;\
85725cf1a30Sjl139090	fzero	 %d20						;\
85825cf1a30Sjl139090	fzero	 %d22						;\
85925cf1a30Sjl139090	fzero	 %d24						;\
86025cf1a30Sjl139090	fzero	 %d26						;\
86125cf1a30Sjl139090	fzero	 %d28						;\
86225cf1a30Sjl139090	fzero	 %d30						;\
86325cf1a30Sjl139090	fzero	 %d32						;\
86425cf1a30Sjl139090	fzero	 %d34						;\
86525cf1a30Sjl139090	fzero	 %d36						;\
86625cf1a30Sjl139090	fzero	 %d38						;\
86725cf1a30Sjl139090	fzero	 %d40						;\
86825cf1a30Sjl139090	fzero	 %d42						;\
86925cf1a30Sjl139090	fzero	 %d44						;\
87025cf1a30Sjl139090	fzero	 %d46						;\
87125cf1a30Sjl139090	fzero	 %d48						;\
87225cf1a30Sjl139090	fzero	 %d50						;\
87325cf1a30Sjl139090	fzero	 %d52						;\
87425cf1a30Sjl139090	fzero	 %d54						;\
87525cf1a30Sjl139090	fzero	 %d56						;\
87625cf1a30Sjl139090	fzero	 %d58						;\
87725cf1a30Sjl139090	fzero	 %d60						;\
87825cf1a30Sjl139090	fzero	 %d62						;\
87925cf1a30Sjl139090	wr	%g0, %g0, %fprs
88025cf1a30Sjl139090
88125cf1a30Sjl139090#define	CLEAR_GLOBALS()						\
88225cf1a30Sjl139090	mov	%g0, %g1					;\
88325cf1a30Sjl139090	mov	%g0, %g2					;\
88425cf1a30Sjl139090	mov	%g0, %g3					;\
88525cf1a30Sjl139090	mov	%g0, %g4					;\
88625cf1a30Sjl139090	mov	%g0, %g5					;\
88725cf1a30Sjl139090	mov	%g0, %g6					;\
88825cf1a30Sjl139090	mov	%g0, %g7
88925cf1a30Sjl139090
89025cf1a30Sjl139090/*
89125cf1a30Sjl139090 * We do not clear the alternative globals here because they
89225cf1a30Sjl139090 * are scratch registers, i.e. there is no code that reads from
89325cf1a30Sjl139090 * them without write to them firstly. In other words every
89425cf1a30Sjl139090 * read always follows write that makes extra write to the
89525cf1a30Sjl139090 * alternative globals unnecessary.
89625cf1a30Sjl139090 */
89725cf1a30Sjl139090#define	CLEAR_GEN_REGS(tmp1, label)				\
89825cf1a30Sjl139090	set	TSTATE_KERN, tmp1				;\
89925cf1a30Sjl139090	wrpr	%g0, tmp1, %tstate				;\
90025cf1a30Sjl139090	mov	%g0, %y						;\
90125cf1a30Sjl139090	mov	%g0, %asi					;\
90225cf1a30Sjl139090	mov	%g0, %ccr					;\
90325cf1a30Sjl139090	mov	%g0, %l0					;\
90425cf1a30Sjl139090	mov	%g0, %l1					;\
90525cf1a30Sjl139090	mov	%g0, %l2					;\
90625cf1a30Sjl139090	mov	%g0, %l3					;\
90725cf1a30Sjl139090	mov	%g0, %l4					;\
90825cf1a30Sjl139090	mov	%g0, %l5					;\
90925cf1a30Sjl139090	mov	%g0, %l6					;\
91025cf1a30Sjl139090	mov	%g0, %l7					;\
91125cf1a30Sjl139090	mov	%g0, %i0					;\
91225cf1a30Sjl139090	mov	%g0, %i1					;\
91325cf1a30Sjl139090	mov	%g0, %i2					;\
91425cf1a30Sjl139090	mov	%g0, %i3					;\
91525cf1a30Sjl139090	mov	%g0, %i4					;\
91625cf1a30Sjl139090	mov	%g0, %i5					;\
91725cf1a30Sjl139090	mov	%g0, %i6					;\
91825cf1a30Sjl139090	mov	%g0, %i7					;\
91925cf1a30Sjl139090	mov	%g0, %o1					;\
92025cf1a30Sjl139090	mov	%g0, %o2					;\
92125cf1a30Sjl139090	mov	%g0, %o3					;\
92225cf1a30Sjl139090	mov	%g0, %o4					;\
92325cf1a30Sjl139090	mov	%g0, %o5					;\
92425cf1a30Sjl139090	mov	%g0, %o6					;\
92525cf1a30Sjl139090	mov	%g0, %o7					;\
92625cf1a30Sjl139090	mov	%g0, %o0					;\
92725cf1a30Sjl139090	mov	%g0, %g4					;\
92825cf1a30Sjl139090	mov	%g0, %g5					;\
92925cf1a30Sjl139090	mov	%g0, %g6					;\
93025cf1a30Sjl139090	mov	%g0, %g7					;\
93125cf1a30Sjl139090	rdpr	%tl, tmp1					;\
93225cf1a30Sjl139090	cmp	tmp1, 1						;\
93325cf1a30Sjl139090	be,pt	%xcc, label/**/1				;\
93425cf1a30Sjl139090	 rdpr	%pstate, tmp1					;\
93525cf1a30Sjl139090	wrpr	tmp1, PSTATE_AG|PSTATE_IG, %pstate		;\
93625cf1a30Sjl139090	CLEAR_GLOBALS()						;\
93725cf1a30Sjl139090	rdpr	%pstate, tmp1					;\
93825cf1a30Sjl139090	wrpr	tmp1, PSTATE_IG|PSTATE_MG, %pstate		;\
93925cf1a30Sjl139090	CLEAR_GLOBALS()						;\
94025cf1a30Sjl139090	rdpr	%pstate, tmp1					;\
94125cf1a30Sjl139090	wrpr	tmp1, PSTATE_MG|PSTATE_AG, %pstate		;\
94225cf1a30Sjl139090	ba,pt	%xcc, label/**/2				;\
94325cf1a30Sjl139090	 nop							;\
94425cf1a30Sjl139090label/**/1:							;\
94525cf1a30Sjl139090	wrpr	tmp1, PSTATE_AG, %pstate			;\
94625cf1a30Sjl139090	CLEAR_GLOBALS()						;\
94725cf1a30Sjl139090	rdpr	%pstate, tmp1					;\
94825cf1a30Sjl139090	wrpr	tmp1, PSTATE_AG, %pstate			;\
94925cf1a30Sjl139090label/**/2:
95025cf1a30Sjl139090
95125cf1a30Sjl139090
95225cf1a30Sjl139090/*
95325cf1a30Sjl139090 * Reset all window related registers
95425cf1a30Sjl139090 */
95525cf1a30Sjl139090#define	RESET_WINREG(tmp)					\
95625cf1a30Sjl139090	sethi	%hi(nwin_minus_one), tmp			;\
95725cf1a30Sjl139090	ld	[tmp + %lo(nwin_minus_one)], tmp		;\
95825cf1a30Sjl139090	wrpr	%g0, tmp, %cwp					;\
95925cf1a30Sjl139090	wrpr	%g0, tmp, %cleanwin				;\
96025cf1a30Sjl139090	sub	tmp, 1, tmp					;\
96125cf1a30Sjl139090	wrpr	%g0, tmp, %cansave				;\
96225cf1a30Sjl139090	wrpr	%g0, %g0, %canrestore				;\
96325cf1a30Sjl139090	wrpr	%g0, %g0, %otherwin				;\
96425cf1a30Sjl139090	wrpr	%g0, PIL_MAX, %pil				;\
96525cf1a30Sjl139090	wrpr	%g0, WSTATE_KERN, %wstate
96625cf1a30Sjl139090
96725cf1a30Sjl139090
96825cf1a30Sjl139090#define	RESET_PREV_TSTATE(tmp1, tmp2, label)			\
96925cf1a30Sjl139090	rdpr	%tl, tmp1					;\
97025cf1a30Sjl139090	subcc	tmp1, 1, tmp1					;\
97125cf1a30Sjl139090	bz,pt	%xcc, label/**/1				;\
97225cf1a30Sjl139090	 nop							;\
97325cf1a30Sjl139090	wrpr	tmp1, %g0, %tl					;\
97425cf1a30Sjl139090	set	TSTATE_KERN, tmp2				;\
97525cf1a30Sjl139090	wrpr	tmp2, %g0, %tstate				;\
97625cf1a30Sjl139090	wrpr	%g0, %g0, %tpc					;\
97725cf1a30Sjl139090	wrpr	%g0, %g0, %tnpc					;\
97825cf1a30Sjl139090	add	tmp1, 1, tmp1					;\
97925cf1a30Sjl139090	wrpr	tmp1, %g0, %tl					;\
98025cf1a30Sjl139090label/**/1:
98125cf1a30Sjl139090
98225cf1a30Sjl139090
98325cf1a30Sjl139090/*
98425cf1a30Sjl139090 * %pstate, %pc, %npc are propagated to %tstate, %tpc, %tnpc,
98525cf1a30Sjl139090 * and we reset these regiseter here.
98625cf1a30Sjl139090 */
98725cf1a30Sjl139090#define	RESET_CUR_TSTATE(tmp)					\
98825cf1a30Sjl139090	set	TSTATE_KERN, tmp				;\
98925cf1a30Sjl139090	wrpr	%g0, tmp, %tstate				;\
99025cf1a30Sjl139090	wrpr	%g0, 0, %tpc					;\
99125cf1a30Sjl139090	wrpr	%g0, 0, %tnpc					;\
99225cf1a30Sjl139090	RESET_WINREG(tmp)
99325cf1a30Sjl139090
99425cf1a30Sjl139090/*
99525cf1a30Sjl139090 * In case of urgent errors some MMU registers may be
99625cf1a30Sjl139090 * corrupted, so we set here some reasonable values for
997f7832c8dShyw * them. Note that resetting MMU registers also reset the context
998f7832c8dShyw * info, we will need to reset the window registers to prevent
9993cbfd4cfSjimand * spill/fill that depends on context info for correct behaviour.
10003cbfd4cfSjimand * Note that the TLBs must be flushed before programming the context
10013cbfd4cfSjimand * registers.
100225cf1a30Sjl139090 */
100325cf1a30Sjl139090
100425cf1a30Sjl139090#if !defined(lint)
100525cf1a30Sjl139090#define	RESET_MMU_REGS(tmp1, tmp2, tmp3)			\
10063cbfd4cfSjimand	FLUSH_ALL_TLB(tmp1)					;\
100725cf1a30Sjl139090	set	MMU_PCONTEXT, tmp1				;\
10083cbfd4cfSjimand	sethi	%hi(kcontextreg), tmp2				;\
10093cbfd4cfSjimand	ldx	[tmp2 + %lo(kcontextreg)], tmp2			;\
10103cbfd4cfSjimand	stxa	tmp2, [tmp1]ASI_DMMU				;\
101125cf1a30Sjl139090	set	MMU_SCONTEXT, tmp1				;\
10123cbfd4cfSjimand	stxa	tmp2, [tmp1]ASI_DMMU				;\
101325cf1a30Sjl139090	sethi	%hi(ktsb_base), tmp1				;\
101425cf1a30Sjl139090	ldx	[tmp1 + %lo(ktsb_base)], tmp2			;\
101525cf1a30Sjl139090	mov	MMU_TSB, tmp3					;\
101625cf1a30Sjl139090	stxa	tmp2, [tmp3]ASI_IMMU				;\
101725cf1a30Sjl139090	stxa	tmp2, [tmp3]ASI_DMMU				;\
1018f7832c8dShyw	membar	#Sync						;\
1019f7832c8dShyw	RESET_WINREG(tmp1)
102025cf1a30Sjl139090
102125cf1a30Sjl139090#define	RESET_TSB_TAGPTR(tmp)					\
102225cf1a30Sjl139090	set	MMU_TAG_ACCESS, tmp				;\
102325cf1a30Sjl139090	stxa	%g0, [tmp]ASI_IMMU				;\
102425cf1a30Sjl139090	stxa	%g0, [tmp]ASI_DMMU				;\
102525cf1a30Sjl139090	membar	#Sync
102625cf1a30Sjl139090#endif /* lint */
102725cf1a30Sjl139090
102825cf1a30Sjl139090/*
1029e98fafb9Sjl139090 * In case of errors in the MMU_TSB_PREFETCH registers we have to
1030e98fafb9Sjl139090 * reset them. We can use "0" as the reset value, this way we set
1031e98fafb9Sjl139090 * the "V" bit of the registers to 0, which will disable the prefetch
1032e98fafb9Sjl139090 * so the values of the other fields are irrelevant.
1033e98fafb9Sjl139090 */
1034e98fafb9Sjl139090#if !defined(lint)
1035e98fafb9Sjl139090#define	RESET_TSB_PREFETCH(tmp)			\
1036e98fafb9Sjl139090	set	VA_UTSBPREF_8K, tmp 		;\
1037e98fafb9Sjl139090	stxa	%g0, [tmp]ASI_ITSB_PREFETCH	;\
1038e98fafb9Sjl139090	set	VA_UTSBPREF_4M, tmp 		;\
1039e98fafb9Sjl139090	stxa	%g0, [tmp]ASI_ITSB_PREFETCH	;\
1040e98fafb9Sjl139090	set	VA_KTSBPREF_8K, tmp 		;\
1041e98fafb9Sjl139090	stxa	%g0, [tmp]ASI_ITSB_PREFETCH	;\
1042e98fafb9Sjl139090	set	VA_KTSBPREF_4M, tmp 		;\
1043e98fafb9Sjl139090	stxa	%g0, [tmp]ASI_ITSB_PREFETCH	;\
1044e98fafb9Sjl139090	set	VA_UTSBPREF_8K, tmp 		;\
1045e98fafb9Sjl139090	stxa	%g0, [tmp]ASI_DTSB_PREFETCH	;\
1046e98fafb9Sjl139090	set	VA_UTSBPREF_4M, tmp 		;\
1047e98fafb9Sjl139090	stxa	%g0, [tmp]ASI_DTSB_PREFETCH	;\
1048e98fafb9Sjl139090	set	VA_KTSBPREF_8K, tmp 		;\
1049e98fafb9Sjl139090	stxa	%g0, [tmp]ASI_DTSB_PREFETCH	;\
1050e98fafb9Sjl139090	set	VA_KTSBPREF_4M, tmp 		;\
1051e98fafb9Sjl139090	stxa	%g0, [tmp]ASI_DTSB_PREFETCH
1052e98fafb9Sjl139090#endif /* lint */
1053e98fafb9Sjl139090
1054e98fafb9Sjl139090/*
1055e98fafb9Sjl139090 * In case of errors in the MMU_SHARED_CONTEXT register we have to
1056e98fafb9Sjl139090 * reset its value. We can use "0" as the reset value, it will put
1057e98fafb9Sjl139090 * 0 in the IV field disabling the shared context support, and
1058e98fafb9Sjl139090 * making values of all the other fields of the register irrelevant.
1059e98fafb9Sjl139090 */
1060e98fafb9Sjl139090#if !defined(lint)
1061e98fafb9Sjl139090#define	RESET_SHARED_CTXT(tmp)			\
1062e98fafb9Sjl139090	set	MMU_SHARED_CONTEXT, tmp		;\
1063e98fafb9Sjl139090	stxa	%g0, [tmp]ASI_DMMU
1064e98fafb9Sjl139090#endif /* lint */
1065e98fafb9Sjl139090
1066e98fafb9Sjl139090/*
106725cf1a30Sjl139090 * RESET_TO_PRIV()
106825cf1a30Sjl139090 *
106925cf1a30Sjl139090 * In many cases, we need to force the thread into privilege mode because
107025cf1a30Sjl139090 * privilege mode is only thing in which the system continue to work
107125cf1a30Sjl139090 * due to undeterminable user mode information that come from register
107225cf1a30Sjl139090 * corruption.
107325cf1a30Sjl139090 *
107425cf1a30Sjl139090 *  - opl_uger_ctxt
107525cf1a30Sjl139090 *    If the error is secondary TSB related register parity, we have no idea
107625cf1a30Sjl139090 *    what value is supposed to be for it.
107725cf1a30Sjl139090 *
107825cf1a30Sjl139090 *  The below three cases %tstate is not accessible until it is overwritten
107925cf1a30Sjl139090 *  with some value, so we have no clue if the thread was running on user mode
108025cf1a30Sjl139090 *  or not
108125cf1a30Sjl139090 *   - opl_uger_pstate
108225cf1a30Sjl139090 *     If the error is %pstate parity, it propagates to %tstate.
108325cf1a30Sjl139090 *   - opl_uger_tstate
108425cf1a30Sjl139090 *     No need to say the reason
108525cf1a30Sjl139090 *   - opl_uger_r
108625cf1a30Sjl139090 *     If the error is %ccr or %asi parity, it propagates to %tstate
108725cf1a30Sjl139090 *
108825cf1a30Sjl139090 * For the above four cases, user mode info may not be available for
108925cf1a30Sjl139090 * sys_trap() and user_trap() to work consistently. So we have to force
109025cf1a30Sjl139090 * the thread into privilege mode.
109125cf1a30Sjl139090 *
109225cf1a30Sjl139090 * Forcing the thread to privilege mode requires forcing
109325cf1a30Sjl139090 * regular %g7 to be CPU_THREAD. Because if it was running on user mode,
109425cf1a30Sjl139090 * %g7 will be set in user_trap(). Also since the %sp may be in
109525cf1a30Sjl139090 * an inconsistent state, we need to do a stack reset and switch to
109625cf1a30Sjl139090 * something we know i.e. current thread's kernel stack.
109725cf1a30Sjl139090 * We also reset the window registers and MMU registers just to
109825cf1a30Sjl139090 * make sure.
109925cf1a30Sjl139090 *
110025cf1a30Sjl139090 * To set regular %g7, we need to clear PSTATE_AG bit and need to
110125cf1a30Sjl139090 * use one local register. Note that we are panicking and will never
110225cf1a30Sjl139090 * unwind back so it is ok to clobber a local.
110325cf1a30Sjl139090 *
110425cf1a30Sjl139090 * If the thread was running in user mode, the %tpc value itself might be
110525cf1a30Sjl139090 * within the range of OBP addresses. %tpc must be forced to be zero to prevent
110625cf1a30Sjl139090 * sys_trap() from going to prom_trap()
110725cf1a30Sjl139090 *
110825cf1a30Sjl139090 */
110925cf1a30Sjl139090#define	RESET_TO_PRIV(tmp, tmp1, tmp2, local)			\
111025cf1a30Sjl139090	RESET_MMU_REGS(tmp, tmp1, tmp2)				;\
111125cf1a30Sjl139090	CPU_ADDR(tmp, tmp1)					;\
111225cf1a30Sjl139090	ldx	[tmp + CPU_THREAD], local			;\
111325cf1a30Sjl139090	ldx	[local + T_STACK], tmp				;\
111425cf1a30Sjl139090	sub	tmp, STACK_BIAS, %sp				;\
111525cf1a30Sjl139090	rdpr	%pstate, tmp					;\
111625cf1a30Sjl139090	wrpr	tmp, PSTATE_AG, %pstate				;\
111725cf1a30Sjl139090	mov	local, %g7					;\
111825cf1a30Sjl139090	rdpr	%pstate, local					;\
111925cf1a30Sjl139090	wrpr	local, PSTATE_AG, %pstate			;\
112025cf1a30Sjl139090	wrpr	%g0, 1, %tl					;\
112125cf1a30Sjl139090	set	TSTATE_KERN, tmp				;\
112225cf1a30Sjl139090	rdpr	%cwp, tmp1					;\
112325cf1a30Sjl139090	or	tmp, tmp1, tmp					;\
112425cf1a30Sjl139090	wrpr	tmp, %g0, %tstate				;\
112525cf1a30Sjl139090	wrpr	%g0, %tpc
112625cf1a30Sjl139090
112725cf1a30Sjl139090
112825cf1a30Sjl139090#if defined(lint)
112925cf1a30Sjl139090
113025cf1a30Sjl139090void
113125cf1a30Sjl139090ce_err(void)
113225cf1a30Sjl139090{}
113325cf1a30Sjl139090
113425cf1a30Sjl139090#else	/* lint */
113525cf1a30Sjl139090
113625cf1a30Sjl139090/*
113725cf1a30Sjl139090 * We normally don't expect CE traps since we disable the
113825cf1a30Sjl139090 * 0x63 trap reporting at the start of day. There is a
113925cf1a30Sjl139090 * small window before we disable them, so let check for
114025cf1a30Sjl139090 * it. Otherwise, panic.
114125cf1a30Sjl139090 */
114225cf1a30Sjl139090
114325cf1a30Sjl139090	.align	128
114425cf1a30Sjl139090	ENTRY_NP(ce_err)
114525cf1a30Sjl139090	mov	AFSR_ECR, %g1
114625cf1a30Sjl139090	ldxa	[%g1]ASI_ECR, %g1
114725cf1a30Sjl139090	andcc	%g1, ASI_ECR_RTE_UE | ASI_ECR_RTE_CEDG, %g0
114825cf1a30Sjl139090	bz,pn	%xcc, 1f
114925cf1a30Sjl139090	 nop
115025cf1a30Sjl139090	retry
115125cf1a30Sjl1390901:
115225cf1a30Sjl139090	/*
115325cf1a30Sjl139090	 * We did disabled the 0x63 trap reporting.
115425cf1a30Sjl139090	 * This shouldn't happen - panic.
115525cf1a30Sjl139090	 */
115625cf1a30Sjl139090	set	trap, %g1
115725cf1a30Sjl139090	rdpr	%tt, %g3
115825cf1a30Sjl139090	sethi	%hi(sys_trap), %g5
115925cf1a30Sjl139090	jmp	%g5 + %lo(sys_trap)
116025cf1a30Sjl139090	sub	%g0, 1, %g4
116125cf1a30Sjl139090	SET_SIZE(ce_err)
116225cf1a30Sjl139090
116325cf1a30Sjl139090#endif	/* lint */
116425cf1a30Sjl139090
116525cf1a30Sjl139090
116625cf1a30Sjl139090#if defined(lint)
116725cf1a30Sjl139090
116825cf1a30Sjl139090void
116925cf1a30Sjl139090ce_err_tl1(void)
117025cf1a30Sjl139090{}
117125cf1a30Sjl139090
117225cf1a30Sjl139090#else	/* lint */
117325cf1a30Sjl139090
117425cf1a30Sjl139090/*
117525cf1a30Sjl139090 * We don't use trap for CE detection.
117625cf1a30Sjl139090 */
117725cf1a30Sjl139090	ENTRY_NP(ce_err_tl1)
117825cf1a30Sjl139090	set	trap, %g1
117925cf1a30Sjl139090	rdpr	%tt, %g3
118025cf1a30Sjl139090	sethi	%hi(sys_trap), %g5
118125cf1a30Sjl139090	jmp	%g5 + %lo(sys_trap)
118225cf1a30Sjl139090	sub	%g0, 1, %g4
118325cf1a30Sjl139090	SET_SIZE(ce_err_tl1)
118425cf1a30Sjl139090
118525cf1a30Sjl139090#endif	/* lint */
118625cf1a30Sjl139090
118725cf1a30Sjl139090
118825cf1a30Sjl139090#if defined(lint)
118925cf1a30Sjl139090
119025cf1a30Sjl139090void
119125cf1a30Sjl139090async_err(void)
119225cf1a30Sjl139090{}
119325cf1a30Sjl139090
119425cf1a30Sjl139090#else	/* lint */
119525cf1a30Sjl139090
119625cf1a30Sjl139090/*
119725cf1a30Sjl139090 * async_err is the default handler for IAE/DAE traps.
119825cf1a30Sjl139090 * For OPL, we patch in the right handler at start of day.
119925cf1a30Sjl139090 * But if a IAE/DAE trap get generated before the handler
120025cf1a30Sjl139090 * is patched, panic.
120125cf1a30Sjl139090 */
120225cf1a30Sjl139090	ENTRY_NP(async_err)
120325cf1a30Sjl139090	set	trap, %g1
120425cf1a30Sjl139090	rdpr	%tt, %g3
120525cf1a30Sjl139090	sethi	%hi(sys_trap), %g5
120625cf1a30Sjl139090	jmp	%g5 + %lo(sys_trap)
120725cf1a30Sjl139090	sub	%g0, 1, %g4
120825cf1a30Sjl139090	SET_SIZE(async_err)
120925cf1a30Sjl139090
121025cf1a30Sjl139090#endif	/* lint */
121125cf1a30Sjl139090
121225cf1a30Sjl139090#if defined(lint)
121325cf1a30Sjl139090void
121425cf1a30Sjl139090opl_sync_trap(void)
121525cf1a30Sjl139090{}
121625cf1a30Sjl139090#else	/* lint */
121725cf1a30Sjl139090
121825cf1a30Sjl139090	.seg	".data"
121925cf1a30Sjl139090	.global	opl_clr_freg
122025cf1a30Sjl139090	.global opl_cpu0_err_log
122125cf1a30Sjl139090
122225cf1a30Sjl139090	.align	16
122325cf1a30Sjl139090opl_clr_freg:
122425cf1a30Sjl139090	.word	0
122525cf1a30Sjl139090	.align	16
122625cf1a30Sjl139090
122725cf1a30Sjl139090	.align	MMU_PAGESIZE
122825cf1a30Sjl139090opl_cpu0_err_log:
122925cf1a30Sjl139090	.skip	MMU_PAGESIZE
123025cf1a30Sjl139090
123125cf1a30Sjl139090/*
123225cf1a30Sjl139090 * Common synchronous error trap handler (tt=0xA, 0x32)
123325cf1a30Sjl139090 * All TL=0 and TL>0 0xA and 0x32 traps vector to this handler.
123425cf1a30Sjl139090 * The error handling can be best summarized as follows:
123525cf1a30Sjl139090 * 0. Do TRAPTRACE if enabled.
123625cf1a30Sjl139090 * 1. Save globals %g1, %g2 & %g3 onto the scratchpad regs.
123725cf1a30Sjl139090 * 2. The SFSR register is read and verified as valid by checking
123825cf1a30Sjl139090 *    SFSR.FV bit being set. If the SFSR.FV is not set, the
123925cf1a30Sjl139090 *    error cases cannot be decoded/determined and the SFPAR
124025cf1a30Sjl139090 *    register that contain the physical faultaddr is also
124125cf1a30Sjl139090 *    not valid. Also the SPFAR is only valid for UE/TO/BERR error
124225cf1a30Sjl139090 *    cases. Assuming the SFSR.FV is valid:
124325cf1a30Sjl139090 *    - BERR(bus error)/TO(timeout)/UE case
124425cf1a30Sjl139090 *      If any of these error cases are detected, read the SFPAR
124525cf1a30Sjl139090 *      to get the faultaddress. Generate ereport.
124625cf1a30Sjl139090 *    - TLB Parity case (only recoverable case)
124725cf1a30Sjl139090 *      For DAE, read SFAR for the faultaddress. For IAE,
124825cf1a30Sjl139090 *	use %tpc for faultaddress (SFAR is not valid in IAE)
124925cf1a30Sjl139090 *	Flush all the tlbs.
125025cf1a30Sjl139090 *	Subtract one from the recoverable error count stored in
125125cf1a30Sjl139090 *	the error log scratch register. If the threshold limit
125225cf1a30Sjl139090 *	is reached (zero) - generate ereport. Else
125325cf1a30Sjl139090 *	restore globals and retry (no ereport is generated).
125425cf1a30Sjl139090 *    - TLB Multiple hits
125525cf1a30Sjl139090 *	For DAE, read SFAR for the faultaddress. For IAE,
125625cf1a30Sjl139090 *	use %tpc for faultaddress (SFAR is not valid in IAE).
125725cf1a30Sjl139090 *	Flush all tlbs and generate ereport.
125825cf1a30Sjl139090 * 3. TL=0 and TL>0 considerations
125925cf1a30Sjl139090 *    - Since both TL=0 & TL>1 traps are made to vector into
126025cf1a30Sjl139090 *      the same handler, the underlying assumption/design here is
126125cf1a30Sjl139090 *      that any nested error condition (if happens) occurs only
126225cf1a30Sjl139090 *	in the handler and the system is assumed to eventually
126325cf1a30Sjl139090 *      Red-mode. With this philosophy in mind, the recoverable
126425cf1a30Sjl139090 *      TLB Parity error case never check the TL level before it
126525cf1a30Sjl139090 *      retry. Note that this is ok for the TL>1 case (assuming we
126625cf1a30Sjl139090 *	don't have a nested error) since we always save the globals
126725cf1a30Sjl139090 *      %g1, %g2 & %g3 whenever we enter this trap handler.
126825cf1a30Sjl139090 *    - Additional TL=0 vs TL>1 handling includes:
126925cf1a30Sjl139090 *      - For UE error occuring under TL>1, special handling
127025cf1a30Sjl139090 *        is added to prevent the unlikely chance of a cpu-lockup
127125cf1a30Sjl139090 *        when a UE was originally detected in user stack and
127225cf1a30Sjl139090 *        the spill trap handler taken from sys_trap() so happened
127325cf1a30Sjl139090 *        to reference the same UE location. Under the above
127425cf1a30Sjl139090 *        condition (TL>1 and UE error), paranoid code is added
127525cf1a30Sjl139090 *        to reset window regs so that spill traps can't happen
127625cf1a30Sjl139090 *        during the unwind back to TL=0 handling.
127725cf1a30Sjl139090 *        Note that we can do that because we are not returning
127825cf1a30Sjl139090 *	  back.
127925cf1a30Sjl139090 * 4. Ereport generation.
128025cf1a30Sjl139090 *    - Ereport generation is performed when we unwind to the TL=0
128125cf1a30Sjl139090 *      handling code via sys_trap(). on_trap()/lofault protection
128225cf1a30Sjl139090 *      will apply there.
128325cf1a30Sjl139090 *
128425cf1a30Sjl139090 */
128525cf1a30Sjl139090	ENTRY_NP(opl_sync_trap)
128625cf1a30Sjl139090#ifdef	TRAPTRACE
128725cf1a30Sjl139090	OPL_TRAPTRACE(%g1, %g2, %g3, opl_sync_trap_lb)
128825cf1a30Sjl139090	rdpr	%tt, %g1
128925cf1a30Sjl139090#endif	/* TRAPTRACE */
129025cf1a30Sjl139090	cmp	%g1, T_INSTR_ERROR
129125cf1a30Sjl139090	bne,pt	%xcc, 0f
129225cf1a30Sjl139090	 mov	MMU_SFSR, %g3
129325cf1a30Sjl139090	ldxa	[%g3]ASI_IMMU, %g1	! IAE trap case tt = 0xa
129425cf1a30Sjl139090	andcc	%g1, SFSR_FV, %g0
129525cf1a30Sjl139090	bz,a,pn %xcc, 2f		! Branch if SFSR is invalid and
129625cf1a30Sjl139090	 rdpr	%tpc, %g2		! use %tpc for faultaddr instead
129725cf1a30Sjl139090
129825cf1a30Sjl139090	sethi	%hi(SFSR_UE|SFSR_BERR|SFSR_TO), %g3
129925cf1a30Sjl139090	andcc	%g1, %g3, %g0		! Check for UE/BERR/TO errors
130025cf1a30Sjl139090	bz,a,pt %xcc, 1f		! Branch if not UE/BERR/TO and
130125cf1a30Sjl139090	 rdpr	%tpc, %g2		! use %tpc as faultaddr
130225cf1a30Sjl139090	set	OPL_MMU_SFPAR, %g3	! In the UE/BERR/TO cases, use
130325cf1a30Sjl139090	ba,pt	%xcc, 2f		! SFPAR as faultaddr
130425cf1a30Sjl139090	 ldxa	[%g3]ASI_IMMU, %g2
130525cf1a30Sjl1390900:
130625cf1a30Sjl139090	ldxa	[%g3]ASI_DMMU, %g1	! DAE trap case tt = 0x32
130725cf1a30Sjl139090	andcc	%g1, SFSR_FV, %g0
130825cf1a30Sjl139090	bnz,pt  %xcc, 7f		! branch if SFSR.FV is valid
130925cf1a30Sjl139090	 mov	MMU_SFAR, %g2		! set %g2 to use SFAR
131025cf1a30Sjl139090	ba,pt	%xcc, 2f		! SFSR.FV is not valid, read SFAR
131125cf1a30Sjl139090	 ldxa	[%g2]ASI_DMMU, %g2	! for faultaddr
131225cf1a30Sjl1390907:
131325cf1a30Sjl139090	sethi  %hi(SFSR_UE|SFSR_BERR|SFSR_TO), %g3
131425cf1a30Sjl139090	andcc	%g1, %g3, %g0		! Check UE/BERR/TO for valid SFPAR
131525cf1a30Sjl139090	movnz	%xcc, OPL_MMU_SFPAR, %g2 ! Use SFPAR instead of SFAR for
131625cf1a30Sjl139090	ldxa	[%g2]ASI_DMMU, %g2	! faultaddr
131725cf1a30Sjl1390901:
131825cf1a30Sjl139090	sethi	%hi(SFSR_TLB_PRT), %g3
131925cf1a30Sjl139090	andcc	%g1, %g3, %g0
132025cf1a30Sjl139090	bz,pt	%xcc, 8f		! branch for TLB multi-hit check
132125cf1a30Sjl139090	 nop
132225cf1a30Sjl139090	/*
132325cf1a30Sjl139090	 * This is the TLB parity error case and it is the
132425cf1a30Sjl139090	 * only retryable error case.
132525cf1a30Sjl139090	 * Only %g1, %g2 and %g3 are allowed
132625cf1a30Sjl139090	 */
132725cf1a30Sjl139090	FLUSH_ALL_TLB(%g3)
132825cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, %g3
132925cf1a30Sjl139090	ldxa	[%g3]ASI_SCRATCHPAD, %g3		! Read errlog scratchreg
133025cf1a30Sjl139090	and	%g3, ERRLOG_REG_NUMERR_MASK, %g3! Extract the error count
133125cf1a30Sjl139090	subcc	%g3, 1, %g0			! Subtract one from the count
133225cf1a30Sjl139090	bz,pn	%xcc, 2f		! too many TLB parity errs in a certain
133325cf1a30Sjl139090	 nop				! period, branch to generate ereport
133425cf1a30Sjl139090	LOG_SYNC_REG(%g1, %g2, %g3)	! Record into the error log
133525cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, %g3
133625cf1a30Sjl139090	ldxa	[%g3]ASI_SCRATCHPAD, %g2
133725cf1a30Sjl139090	sub	%g2, 1, %g2		! decrement error counter by 1
133825cf1a30Sjl139090	stxa	%g2, [%g3]ASI_SCRATCHPAD	! update the errlog scratchreg
133925cf1a30Sjl139090	OPL_RESTORE_GLOBAL(%g1, %g2, %g3)
134025cf1a30Sjl139090	retry
134125cf1a30Sjl1390908:
134225cf1a30Sjl139090	sethi	%hi(SFSR_TLB_MUL), %g3
134325cf1a30Sjl139090	andcc	%g1, %g3, %g0
134425cf1a30Sjl139090	bz,pt	%xcc, 2f		! check for the TLB multi-hit errors
134525cf1a30Sjl139090	 nop
134625cf1a30Sjl139090	FLUSH_ALL_TLB(%g3)
134725cf1a30Sjl1390902:
134825cf1a30Sjl139090	/*
134925cf1a30Sjl139090	 * non-retryable error handling
135025cf1a30Sjl139090	 * now we can use other registers since
135125cf1a30Sjl139090	 * we will not be returning back
135225cf1a30Sjl139090	 */
135325cf1a30Sjl139090	mov	%g1, %g5		! %g5 = SFSR
135425cf1a30Sjl139090	mov	%g2, %g6		! %g6 = SFPAR or SFAR/tpc
135525cf1a30Sjl139090	LOG_SYNC_REG(%g1, %g2, %g3)	! Record into the error log
135625cf1a30Sjl139090
135725cf1a30Sjl139090	/*
135825cf1a30Sjl139090	 * Special case for UE on user stack.
135925cf1a30Sjl139090	 * There is a possibility that the same error may come back here
136025cf1a30Sjl139090	 * by touching the same UE in spill trap handler taken from
136125cf1a30Sjl139090	 * sys_trap(). It ends up with an infinite loop causing a cpu lockup.
136225cf1a30Sjl139090	 * Conditions for this handling this case are:
136325cf1a30Sjl139090	 * - SFSR_FV is valid and SFSR_UE is set
136425cf1a30Sjl139090	 * - we are at TL > 1
136525cf1a30Sjl139090	 * If the above conditions are true,  we force %cansave to be a
136625cf1a30Sjl139090	 * big number to prevent spill trap in sys_trap(). Note that
136725cf1a30Sjl139090	 * we will not be returning back.
136825cf1a30Sjl139090	 */
136925cf1a30Sjl139090	rdpr	%tt, %g4		! %g4 == ttype
137025cf1a30Sjl139090	rdpr	%tl, %g1		! %g1 == tl
137125cf1a30Sjl139090	cmp	%g1, 1			! Check if TL == 1
137225cf1a30Sjl139090	be,pt	%xcc, 3f		! branch if we came from TL=0
137325cf1a30Sjl139090	 nop
137425cf1a30Sjl139090	andcc	%g5, SFSR_FV, %g0	! see if SFSR.FV is valid
137525cf1a30Sjl139090	bz,pn	%xcc, 4f		! branch, checking UE is meaningless
137625cf1a30Sjl139090	sethi	%hi(SFSR_UE), %g2
137725cf1a30Sjl139090	andcc	%g5, %g2, %g0		! check for UE
137825cf1a30Sjl139090	bz,pt	%xcc, 4f		! branch if not UE
137925cf1a30Sjl139090	 nop
138025cf1a30Sjl139090	RESET_WINREG(%g1)		! reset windows to prevent spills
138125cf1a30Sjl1390904:
13822dd3029aSjimand	RESET_USER_RTT_REGS(%g2, %g3, opl_sync_trap_resetskip)
13832dd3029aSjimandopl_sync_trap_resetskip:
138425cf1a30Sjl139090	mov	%g5, %g3		! pass SFSR to the 3rd arg
138525cf1a30Sjl139090	mov	%g6, %g2		! pass SFAR to the 2nd arg
138625cf1a30Sjl139090	set	opl_cpu_isync_tl1_error, %g1
138725cf1a30Sjl139090	set	opl_cpu_dsync_tl1_error, %g6
138825cf1a30Sjl139090	cmp	%g4, T_INSTR_ERROR
138925cf1a30Sjl139090	movne	%icc, %g6, %g1
139025cf1a30Sjl139090	ba,pt	%icc, 6f
139125cf1a30Sjl139090	nop
139225cf1a30Sjl1390903:
139325cf1a30Sjl139090	mov	%g5, %g3		! pass SFSR to the 3rd arg
139425cf1a30Sjl139090	mov	%g6, %g2		! pass SFAR to the 2nd arg
139525cf1a30Sjl139090	set	opl_cpu_isync_tl0_error, %g1
139625cf1a30Sjl139090	set	opl_cpu_dsync_tl0_error, %g6
139725cf1a30Sjl139090	cmp	%g4, T_INSTR_ERROR
139825cf1a30Sjl139090	movne	%icc, %g6, %g1
139925cf1a30Sjl1390906:
140025cf1a30Sjl139090	sethi	%hi(sys_trap), %g5
140125cf1a30Sjl139090	jmp	%g5 + %lo(sys_trap)
140225cf1a30Sjl139090	 mov	PIL_15, %g4
140325cf1a30Sjl139090	SET_SIZE(opl_sync_trap)
140425cf1a30Sjl139090#endif	/* lint */
140525cf1a30Sjl139090
140625cf1a30Sjl139090#if defined(lint)
140725cf1a30Sjl139090void
140825cf1a30Sjl139090opl_uger_trap(void)
140925cf1a30Sjl139090{}
141025cf1a30Sjl139090#else	/* lint */
141125cf1a30Sjl139090/*
141225cf1a30Sjl139090 * Common Urgent error trap handler (tt=0x40)
141325cf1a30Sjl139090 * All TL=0 and TL>0 0x40 traps vector to this handler.
141425cf1a30Sjl139090 * The error handling can be best summarized as follows:
141525cf1a30Sjl139090 * 1. Read the Urgent error status register (UGERSR)
141625cf1a30Sjl139090 *    Faultaddress is N/A here and it is not collected.
141725cf1a30Sjl139090 * 2. Check to see if we have a multiple errors case
141825cf1a30Sjl139090 *    If so, we enable WEAK_ED (weak error detection) bit
141925cf1a30Sjl139090 *    to prevent any potential error storms and branch directly
142025cf1a30Sjl139090 *    to generate ereport. (we don't decode/handle individual
142125cf1a30Sjl139090 *    error cases when we get a multiple error situation)
142225cf1a30Sjl139090 * 3. Now look for the recoverable error cases which include
142325cf1a30Sjl139090 *    IUG_DTLB, IUG_ITLB or COREERR errors. If any of the
142425cf1a30Sjl139090 *    recoverable errors are detected, do the following:
142525cf1a30Sjl139090 *    - Flush all tlbs.
142625cf1a30Sjl139090 *    - Verify that we came from TL=0, if not, generate
142725cf1a30Sjl139090 *      ereport. Note that the reason we don't recover
142825cf1a30Sjl139090 *      at TL>0 is because the AGs might be corrupted or
142925cf1a30Sjl139090 *      inconsistent. We can't save/restore them into
143025cf1a30Sjl139090 *      the scratchpad regs like we did for opl_sync_trap().
143125cf1a30Sjl139090 *    - Check the INSTEND[5:4] bits in the UGERSR. If the
143225cf1a30Sjl139090 *      value is 0x3 (11b), this error is not recoverable.
143325cf1a30Sjl139090 *      Generate ereport.
143425cf1a30Sjl139090 *    - Subtract one from the recoverable error count stored in
143525cf1a30Sjl139090 *      the error log scratch register. If the threshold limit
143625cf1a30Sjl139090 *      is reached (zero) - generate ereport.
143725cf1a30Sjl139090 *    - If the count is within the limit, update the count
143825cf1a30Sjl139090 *      in the error log register (subtract one). Log the error
143925cf1a30Sjl139090 *      info in the log buffer. Capture traptrace if enabled.
144025cf1a30Sjl139090 *      Retry (no ereport generated)
144125cf1a30Sjl139090 * 4. The rest of the error cases are unrecoverable and will
144225cf1a30Sjl139090 *    be handled according (flushing regs, etc as required).
144325cf1a30Sjl139090 *    For details on these error cases (UGER_CRE, UGER_CTXT, etc..)
144425cf1a30Sjl139090 *    consult the OPL cpu/mem philosophy doc.
144525cf1a30Sjl139090 *    Ereport will be generated for these errors.
144625cf1a30Sjl139090 * 5. Ereport generation.
144725cf1a30Sjl139090 *    - Ereport generation for urgent error trap always
144825cf1a30Sjl139090 *      result in a panic when we unwind to the TL=0 handling
144925cf1a30Sjl139090 *      code via sys_trap(). on_trap()/lofault protection do
145025cf1a30Sjl139090 *      not apply there.
145125cf1a30Sjl139090 */
145225cf1a30Sjl139090	ENTRY_NP(opl_uger_trap)
145325cf1a30Sjl139090	set	ASI_UGERSR, %g2
145425cf1a30Sjl139090	ldxa	[%g2]ASI_AFSR, %g1		! Read the UGERSR reg
145525cf1a30Sjl139090
145625cf1a30Sjl139090	set	UGESR_MULTI, %g2
145725cf1a30Sjl139090	andcc	%g1, %g2, %g0			! Check for Multi-errs
145825cf1a30Sjl139090	bz,pt	%xcc, opl_uger_is_recover	! branch if not Multi-errs
145925cf1a30Sjl139090	 nop
146025cf1a30Sjl139090	set	AFSR_ECR, %g2
146125cf1a30Sjl139090	ldxa	[%g2]ASI_AFSR, %g3		! Enable Weak error
146225cf1a30Sjl139090	or	%g3, ASI_ECR_WEAK_ED, %g3	! detect mode to prevent
146325cf1a30Sjl139090	stxa	%g3, [%g2]ASI_AFSR		! potential error storms
146425cf1a30Sjl139090	ba	%xcc, opl_uger_panic1
146525cf1a30Sjl139090	 nop
146625cf1a30Sjl139090
146725cf1a30Sjl139090opl_uger_is_recover:
146825cf1a30Sjl139090	set	UGESR_CAN_RECOVER, %g2		! Check for recoverable
146925cf1a30Sjl139090	andcc	%g1, %g2, %g0			! errors i.e.IUG_DTLB,
147025cf1a30Sjl139090	bz,pt	%xcc, opl_uger_cre		! IUG_ITLB or COREERR
147125cf1a30Sjl139090	 nop
147225cf1a30Sjl139090
147325cf1a30Sjl139090	/*
147425cf1a30Sjl139090	 * Fall thru to handle recoverable case
147525cf1a30Sjl139090	 * Need to do the following additional checks to determine
147625cf1a30Sjl139090	 * if this is indeed recoverable.
147725cf1a30Sjl139090	 * 1. Error trap came from TL=0 and
147825cf1a30Sjl139090	 * 2. INSTEND[5:4] bits in UGERSR is not 0x3
147925cf1a30Sjl139090	 * 3. Recoverable error count limit not reached
148025cf1a30Sjl139090	 *
148125cf1a30Sjl139090	 */
148225cf1a30Sjl139090	FLUSH_ALL_TLB(%g3)
148325cf1a30Sjl139090	rdpr	%tl, %g3		! Read TL
148425cf1a30Sjl139090	cmp	%g3, 1			! Check if we came from TL=0
148525cf1a30Sjl139090	bne,pt	%xcc, opl_uger_panic	! branch if came from TL>0
148625cf1a30Sjl139090	 nop
148725cf1a30Sjl139090	srlx	%g1, 4, %g2		! shift INSTEND[5:4] -> [1:0]
148825cf1a30Sjl139090	and	%g2, 3, %g2		! extract the shifted [1:0] bits
148925cf1a30Sjl139090	cmp	%g2, 3			! check if INSTEND is recoverable
149025cf1a30Sjl139090	be,pt   %xcc, opl_uger_panic	! panic if ([1:0] = 11b)
149125cf1a30Sjl139090	 nop
149225cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, %g3
149325cf1a30Sjl139090	ldxa	[%g3]ASI_SCRATCHPAD, %g2		! Read errlog scratch reg
149425cf1a30Sjl139090	and	%g2, ERRLOG_REG_NUMERR_MASK, %g3! Extract error count and
149525cf1a30Sjl139090	subcc	%g3, 1, %g3			! subtract one from it
149625cf1a30Sjl139090	bz,pt   %xcc, opl_uger_panic	! If count reached zero, too many
149725cf1a30Sjl139090	 nop				! errors, branch to generate ereport
149825cf1a30Sjl139090	sub	%g2, 1, %g2			! Subtract one from the count
149925cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, %g3	! and write back the updated
150025cf1a30Sjl139090	stxa	%g2, [%g3]ASI_SCRATCHPAD		! count into the errlog reg
150125cf1a30Sjl139090	LOG_UGER_REG(%g1, %g2, %g3)		! Log the error info
150225cf1a30Sjl139090#ifdef	TRAPTRACE
150325cf1a30Sjl139090	OPL_TRAPTRACE(%g1, %g2, %g3, opl_uger_trap_lb)
150425cf1a30Sjl139090#endif	/* TRAPTRACE */
150525cf1a30Sjl139090	retry					! retry - no ereport
150625cf1a30Sjl139090
150725cf1a30Sjl139090	/*
150825cf1a30Sjl139090	 * Process the rest of the unrecoverable error cases
150925cf1a30Sjl139090	 * All error cases below ultimately branch to either
151025cf1a30Sjl139090	 * opl_uger_panic or opl_uger_panic1.
151125cf1a30Sjl139090	 * opl_uger_panic1 is the same as opl_uger_panic except
151225cf1a30Sjl139090	 * for the additional execution of the RESET_TO_PRIV()
151325cf1a30Sjl139090	 * macro that does a heavy handed reset. Read the
151425cf1a30Sjl139090	 * comments for RESET_TO_PRIV() macro for more info.
151525cf1a30Sjl139090	 */
151625cf1a30Sjl139090opl_uger_cre:
151725cf1a30Sjl139090	set	UGESR_IAUG_CRE, %g2
151825cf1a30Sjl139090	andcc	%g1, %g2, %g0
151925cf1a30Sjl139090	bz,pt	%xcc, opl_uger_ctxt
152025cf1a30Sjl139090	 nop
152125cf1a30Sjl139090	IAG_CRE(%g2, %g3)
152225cf1a30Sjl139090	set	AFSR_ECR, %g2
152325cf1a30Sjl139090	ldxa	[%g2]ASI_AFSR, %g3
152425cf1a30Sjl139090	or	%g3, ASI_ECR_WEAK_ED, %g3
152525cf1a30Sjl139090	stxa	%g3, [%g2]ASI_AFSR
152625cf1a30Sjl139090	ba	%xcc, opl_uger_panic
152725cf1a30Sjl139090	 nop
152825cf1a30Sjl139090
152925cf1a30Sjl139090opl_uger_ctxt:
153025cf1a30Sjl139090	set	UGESR_IAUG_TSBCTXT, %g2
153125cf1a30Sjl139090	andcc	%g1, %g2, %g0
153225cf1a30Sjl139090	bz,pt	%xcc, opl_uger_tsbp
153325cf1a30Sjl139090	 nop
1534e98fafb9Sjl139090	GET_CPU_IMPL(%g2)
1535e98fafb9Sjl139090	cmp	%g2, JUPITER_IMPL
1536e98fafb9Sjl139090	bne	%xcc, 1f
1537e98fafb9Sjl139090	  nop
1538e98fafb9Sjl139090	RESET_SHARED_CTXT(%g2)
1539e98fafb9Sjl1390901:
154025cf1a30Sjl139090	RESET_MMU_REGS(%g2, %g3, %g4)
154125cf1a30Sjl139090	ba	%xcc, opl_uger_panic
154225cf1a30Sjl139090	 nop
154325cf1a30Sjl139090
154425cf1a30Sjl139090opl_uger_tsbp:
154525cf1a30Sjl139090	set	UGESR_IUG_TSBP, %g2
154625cf1a30Sjl139090	andcc	%g1, %g2, %g0
154725cf1a30Sjl139090	bz,pt	%xcc, opl_uger_pstate
154825cf1a30Sjl139090	 nop
1549e98fafb9Sjl139090	GET_CPU_IMPL(%g2)
1550e98fafb9Sjl139090	cmp	%g2, JUPITER_IMPL
1551e98fafb9Sjl139090	bne	%xcc, 1f
1552e98fafb9Sjl139090	  nop
1553e98fafb9Sjl139090	RESET_TSB_PREFETCH(%g2)
1554e98fafb9Sjl1390901:
155525cf1a30Sjl139090	RESET_TSB_TAGPTR(%g2)
1556f7832c8dShyw
1557f7832c8dShyw	/*
1558f7832c8dShyw	 * IUG_TSBP error may corrupt MMU registers
1559f7832c8dShyw	 * Reset them here.
1560f7832c8dShyw	 */
1561f7832c8dShyw	RESET_MMU_REGS(%g2, %g3, %g4)
156225cf1a30Sjl139090	ba	%xcc, opl_uger_panic
156325cf1a30Sjl139090	 nop
156425cf1a30Sjl139090
156525cf1a30Sjl139090opl_uger_pstate:
156625cf1a30Sjl139090	set	UGESR_IUG_PSTATE, %g2
156725cf1a30Sjl139090	andcc	%g1, %g2, %g0
156825cf1a30Sjl139090	bz,pt	%xcc, opl_uger_tstate
156925cf1a30Sjl139090	 nop
157025cf1a30Sjl139090	RESET_CUR_TSTATE(%g2)
157125cf1a30Sjl139090	ba	%xcc, opl_uger_panic1
157225cf1a30Sjl139090	 nop
157325cf1a30Sjl139090
157425cf1a30Sjl139090opl_uger_tstate:
157525cf1a30Sjl139090	set	UGESR_IUG_TSTATE, %g2
157625cf1a30Sjl139090	andcc	%g1, %g2, %g0
157725cf1a30Sjl139090	bz,pt	%xcc, opl_uger_f
157825cf1a30Sjl139090	 nop
157925cf1a30Sjl139090	RESET_PREV_TSTATE(%g2, %g3, opl_uger_tstate_1)
158025cf1a30Sjl139090	ba	%xcc, opl_uger_panic1
158125cf1a30Sjl139090	 nop
158225cf1a30Sjl139090
158325cf1a30Sjl139090opl_uger_f:
158425cf1a30Sjl139090	set	UGESR_IUG_F, %g2
158525cf1a30Sjl139090	andcc	%g1, %g2, %g0
158625cf1a30Sjl139090	bz,pt	%xcc, opl_uger_r
158725cf1a30Sjl139090	 nop
158825cf1a30Sjl139090	CLEAR_FPREGS(%g2)
158925cf1a30Sjl139090	ba	%xcc, opl_uger_panic
159025cf1a30Sjl139090	 nop
159125cf1a30Sjl139090
159225cf1a30Sjl139090opl_uger_r:
159325cf1a30Sjl139090	set	UGESR_IUG_R, %g2
159425cf1a30Sjl139090	andcc	%g1, %g2, %g0
159525cf1a30Sjl139090	bz,pt	%xcc, opl_uger_panic1
159625cf1a30Sjl139090	 nop
159725cf1a30Sjl139090	CLEAR_GEN_REGS(%g2, opl_uger_r_1)
159825cf1a30Sjl139090	ba	%xcc, opl_uger_panic1
159925cf1a30Sjl139090	 nop
160025cf1a30Sjl139090
160125cf1a30Sjl139090opl_uger_panic:
160225cf1a30Sjl139090	mov	%g1, %g2			! %g2 = arg #1
160325cf1a30Sjl139090	LOG_UGER_REG(%g1, %g3, %g4)
160425cf1a30Sjl139090	ba	%xcc, opl_uger_panic_cmn
160525cf1a30Sjl139090	 nop
160625cf1a30Sjl139090
160725cf1a30Sjl139090opl_uger_panic1:
160825cf1a30Sjl139090	mov	%g1, %g2			! %g2 = arg #1
160925cf1a30Sjl139090	LOG_UGER_REG(%g1, %g3, %g4)
161025cf1a30Sjl139090	RESET_TO_PRIV(%g1, %g3, %g4, %l0)
161125cf1a30Sjl139090
161225cf1a30Sjl139090	/*
161325cf1a30Sjl139090	 * Set up the argument for sys_trap.
161425cf1a30Sjl139090	 * %g2 = arg #1 already set above
161525cf1a30Sjl139090	 */
161625cf1a30Sjl139090opl_uger_panic_cmn:
16172dd3029aSjimand	RESET_USER_RTT_REGS(%g4, %g5, opl_uger_panic_resetskip)
16182dd3029aSjimandopl_uger_panic_resetskip:
161925cf1a30Sjl139090	rdpr	%tl, %g3			! arg #2
162025cf1a30Sjl139090	set	opl_cpu_urgent_error, %g1	! pc
162125cf1a30Sjl139090	sethi	%hi(sys_trap), %g5
162225cf1a30Sjl139090	jmp	%g5 + %lo(sys_trap)
162325cf1a30Sjl139090	 mov	PIL_15, %g4
162425cf1a30Sjl139090	SET_SIZE(opl_uger_trap)
162525cf1a30Sjl139090#endif	/* lint */
162625cf1a30Sjl139090
162725cf1a30Sjl139090#if defined(lint)
162850eff769Smb158278void
162950eff769Smb158278opl_ta3_trap(void)
163050eff769Smb158278{}
163150eff769Smb158278void
163250eff769Smb158278opl_cleanw_subr(void)
163350eff769Smb158278{}
163450eff769Smb158278#else	/* lint */
163550eff769Smb158278/*
163650eff769Smb158278 * OPL ta3 support (note please, that win_reg
163750eff769Smb158278 * area size for each cpu is 2^7 bytes)
163850eff769Smb158278 */
163950eff769Smb158278
164050eff769Smb158278#define	RESTORE_WREGS(tmp1, tmp2)		\
164150eff769Smb158278	CPU_INDEX(tmp1, tmp2)			;\
164250eff769Smb158278	sethi	%hi(opl_ta3_save), tmp2		;\
164350eff769Smb158278	ldx	[tmp2 +%lo(opl_ta3_save)], tmp2	;\
164450eff769Smb158278	sllx	tmp1, 7, tmp1			;\
164550eff769Smb158278	add	tmp2, tmp1, tmp2		;\
164650eff769Smb158278	ldx	[tmp2 + 0], %l0			;\
164750eff769Smb158278	ldx	[tmp2 + 8], %l1			;\
164850eff769Smb158278	ldx	[tmp2 + 16], %l2		;\
164950eff769Smb158278	ldx	[tmp2 + 24], %l3		;\
165050eff769Smb158278	ldx	[tmp2 + 32], %l4		;\
165150eff769Smb158278	ldx	[tmp2 + 40], %l5		;\
165250eff769Smb158278	ldx	[tmp2 + 48], %l6		;\
165350eff769Smb158278	ldx	[tmp2 + 56], %l7		;\
165450eff769Smb158278	ldx	[tmp2 + 64], %i0		;\
165550eff769Smb158278	ldx	[tmp2 + 72], %i1		;\
165650eff769Smb158278	ldx	[tmp2 + 80], %i2		;\
165750eff769Smb158278	ldx	[tmp2 + 88], %i3		;\
165850eff769Smb158278	ldx	[tmp2 + 96], %i4		;\
165950eff769Smb158278	ldx	[tmp2 + 104], %i5		;\
166050eff769Smb158278	ldx	[tmp2 + 112], %i6		;\
166150eff769Smb158278	ldx	[tmp2 + 120], %i7
166250eff769Smb158278
166350eff769Smb158278#define	SAVE_WREGS(tmp1, tmp2)			\
166450eff769Smb158278	CPU_INDEX(tmp1, tmp2)			;\
166550eff769Smb158278	sethi	%hi(opl_ta3_save), tmp2		;\
166650eff769Smb158278	ldx	[tmp2 +%lo(opl_ta3_save)], tmp2	;\
166750eff769Smb158278	sllx	tmp1, 7, tmp1			;\
166850eff769Smb158278	add	tmp2, tmp1, tmp2		;\
166950eff769Smb158278	stx	%l0, [tmp2 + 0] 		;\
167050eff769Smb158278	stx	%l1, [tmp2 + 8] 		;\
167150eff769Smb158278	stx	%l2, [tmp2 + 16] 		;\
167250eff769Smb158278	stx	%l3, [tmp2 + 24]		;\
167350eff769Smb158278	stx	%l4, [tmp2 + 32]		;\
167450eff769Smb158278	stx	%l5, [tmp2 + 40]		;\
167550eff769Smb158278	stx	%l6, [tmp2 + 48] 		;\
167650eff769Smb158278	stx	%l7, [tmp2 + 56]		;\
167750eff769Smb158278	stx	%i0, [tmp2 + 64]		;\
167850eff769Smb158278	stx	%i1, [tmp2 + 72]		;\
167950eff769Smb158278	stx	%i2, [tmp2 + 80]		;\
168050eff769Smb158278	stx	%i3, [tmp2 + 88]		;\
168150eff769Smb158278	stx	%i4, [tmp2 + 96]		;\
168250eff769Smb158278	stx	%i5, [tmp2 + 104]		;\
168350eff769Smb158278	stx	%i6, [tmp2 + 112]		;\
168450eff769Smb158278	stx	%i7, [tmp2 + 120]
168550eff769Smb158278
168650eff769Smb158278
168750eff769Smb158278/*
168850eff769Smb158278 * The purpose of this function is to make sure that the restore
168950eff769Smb158278 * instruction after the flushw does not cause a fill trap. The sun4u
169050eff769Smb158278 * fill trap handler can not handle a tlb fault of an unmapped stack
169150eff769Smb158278 * except at the restore instruction at user_rtt. On OPL systems the
169250eff769Smb158278 * stack can get unmapped between the flushw and restore instructions
169350eff769Smb158278 * since multiple strands share the tlb.
169450eff769Smb158278 */
169550eff769Smb158278	ENTRY_NP(opl_ta3_trap)
169650eff769Smb158278	set	trap, %g1
169750eff769Smb158278	mov	T_FLUSHW, %g3
169850eff769Smb158278	sub	%g0, 1, %g4
169950eff769Smb158278	rdpr	%cwp, %g5
170050eff769Smb158278	SAVE_WREGS(%g2, %g6)
170150eff769Smb158278	save
170250eff769Smb158278	flushw
170350eff769Smb158278	rdpr	%cwp, %g6
170450eff769Smb158278	wrpr	%g5, %cwp
170550eff769Smb158278	RESTORE_WREGS(%g2, %g5)
170650eff769Smb158278	wrpr	%g6, %cwp
170750eff769Smb158278	restored
170850eff769Smb158278	restore
170950eff769Smb158278
171050eff769Smb158278	ba,a    fast_trap_done
171150eff769Smb158278	SET_SIZE(opl_ta3_trap)
171250eff769Smb158278
171350eff769Smb158278	ENTRY_NP(opl_cleanw_subr)
171450eff769Smb158278	set	trap, %g1
171550eff769Smb158278	mov	T_FLUSHW, %g3
171650eff769Smb158278	sub	%g0, 1, %g4
171750eff769Smb158278	rdpr	%cwp, %g5
171850eff769Smb158278	SAVE_WREGS(%g2, %g6)
171950eff769Smb158278	save
172050eff769Smb158278	flushw
172150eff769Smb158278	rdpr	%cwp, %g6
172250eff769Smb158278	wrpr	%g5, %cwp
172350eff769Smb158278	RESTORE_WREGS(%g2, %g5)
172450eff769Smb158278	wrpr	%g6, %cwp
172550eff769Smb158278	restored
172650eff769Smb158278	restore
172750eff769Smb158278	jmp	%g7
172850eff769Smb158278	  nop
172950eff769Smb158278	SET_SIZE(opl_cleanw_subr)
173050eff769Smb158278#endif	/* lint */
173150eff769Smb158278
173250eff769Smb158278#if defined(lint)
173325cf1a30Sjl139090
173425cf1a30Sjl139090void
173525cf1a30Sjl139090opl_serr_instr(void)
173625cf1a30Sjl139090{}
173725cf1a30Sjl139090
173825cf1a30Sjl139090#else	/* lint */
173925cf1a30Sjl139090/*
174025cf1a30Sjl139090 * The actual trap handler for tt=0x0a, and tt=0x32
174125cf1a30Sjl139090 */
174225cf1a30Sjl139090	ENTRY_NP(opl_serr_instr)
174325cf1a30Sjl139090	OPL_SAVE_GLOBAL(%g1,%g2,%g3)
174425cf1a30Sjl139090	sethi   %hi(opl_sync_trap), %g3
174525cf1a30Sjl139090	jmp	%g3 + %lo(opl_sync_trap)
174625cf1a30Sjl139090	 rdpr    %tt, %g1
174725cf1a30Sjl139090	.align  32
174825cf1a30Sjl139090	SET_SIZE(opl_serr_instr)
174925cf1a30Sjl139090
175025cf1a30Sjl139090#endif	/* lint */
175125cf1a30Sjl139090
175225cf1a30Sjl139090#if defined(lint)
175325cf1a30Sjl139090
175425cf1a30Sjl139090void
175525cf1a30Sjl139090opl_ugerr_instr(void)
175625cf1a30Sjl139090{}
175725cf1a30Sjl139090
175825cf1a30Sjl139090#else	/* lint */
175925cf1a30Sjl139090/*
176025cf1a30Sjl139090 * The actual trap handler for tt=0x40
176125cf1a30Sjl139090 */
176225cf1a30Sjl139090	ENTRY_NP(opl_ugerr_instr)
176325cf1a30Sjl139090	sethi   %hi(opl_uger_trap), %g3
176425cf1a30Sjl139090	jmp	%g3 + %lo(opl_uger_trap)
176525cf1a30Sjl139090	 nop
176625cf1a30Sjl139090	.align  32
176725cf1a30Sjl139090	SET_SIZE(opl_ugerr_instr)
176825cf1a30Sjl139090
176925cf1a30Sjl139090#endif	/* lint */
177025cf1a30Sjl139090
177125cf1a30Sjl139090#if defined(lint)
177250eff769Smb158278
177350eff769Smb158278void
177450eff769Smb158278opl_ta3_instr(void)
177550eff769Smb158278{}
177650eff769Smb158278
177750eff769Smb158278#else	/* lint */
177850eff769Smb158278/*
177950eff769Smb158278 * The actual trap handler for tt=0x103 (flushw)
178050eff769Smb158278 */
178150eff769Smb158278	ENTRY_NP(opl_ta3_instr)
178250eff769Smb158278	sethi   %hi(opl_ta3_trap), %g3
178350eff769Smb158278	jmp	%g3 + %lo(opl_ta3_trap)
178450eff769Smb158278	 nop
178550eff769Smb158278	.align  32
178650eff769Smb158278	SET_SIZE(opl_ta3_instr)
178750eff769Smb158278
178850eff769Smb158278#endif	/* lint */
178950eff769Smb158278
179050eff769Smb158278#if defined(lint)
179150eff769Smb158278
179250eff769Smb158278void
179350eff769Smb158278opl_ta4_instr(void)
179450eff769Smb158278{}
179550eff769Smb158278
179650eff769Smb158278#else	/* lint */
179750eff769Smb158278/*
179850eff769Smb158278 * The patch for the .clean_windows code
179950eff769Smb158278 */
180050eff769Smb158278	ENTRY_NP(opl_ta4_instr)
180150eff769Smb158278	sethi   %hi(opl_cleanw_subr), %g3
180250eff769Smb158278	add	%g3, %lo(opl_cleanw_subr), %g3
180350eff769Smb158278	jmpl	%g3, %g7
180450eff769Smb158278	  add	%g7, 8, %g7
180550eff769Smb158278	nop
180650eff769Smb158278	nop
180750eff769Smb158278	nop
180850eff769Smb158278	SET_SIZE(opl_ta4_instr)
180950eff769Smb158278
181050eff769Smb158278#endif	/* lint */
181150eff769Smb158278
181250eff769Smb158278#if defined(lint)
181325cf1a30Sjl139090/*
181425cf1a30Sjl139090 *  Get timestamp (stick).
181525cf1a30Sjl139090 */
181625cf1a30Sjl139090/* ARGSUSED */
181725cf1a30Sjl139090void
181825cf1a30Sjl139090stick_timestamp(int64_t *ts)
181925cf1a30Sjl139090{
182025cf1a30Sjl139090}
182125cf1a30Sjl139090
182225cf1a30Sjl139090#else	/* lint */
182325cf1a30Sjl139090
182425cf1a30Sjl139090	ENTRY_NP(stick_timestamp)
182525cf1a30Sjl139090	rd	STICK, %g1	! read stick reg
182625cf1a30Sjl139090	sllx	%g1, 1, %g1
182725cf1a30Sjl139090	srlx	%g1, 1, %g1	! clear npt bit
182825cf1a30Sjl139090
182925cf1a30Sjl139090	retl
183025cf1a30Sjl139090	stx	%g1, [%o0]	! store the timestamp
183125cf1a30Sjl139090	SET_SIZE(stick_timestamp)
183225cf1a30Sjl139090
183325cf1a30Sjl139090#endif	/* lint */
183425cf1a30Sjl139090
183525cf1a30Sjl139090
183625cf1a30Sjl139090#if defined(lint)
183725cf1a30Sjl139090/*
183825cf1a30Sjl139090 * Set STICK adjusted by skew.
183925cf1a30Sjl139090 */
184025cf1a30Sjl139090/* ARGSUSED */
184125cf1a30Sjl139090void
184225cf1a30Sjl139090stick_adj(int64_t skew)
184325cf1a30Sjl139090{
184425cf1a30Sjl139090}
184525cf1a30Sjl139090
184625cf1a30Sjl139090#else	/* lint */
184725cf1a30Sjl139090
184825cf1a30Sjl139090	ENTRY_NP(stick_adj)
184925cf1a30Sjl139090	rdpr	%pstate, %g1		! save processor state
185025cf1a30Sjl139090	andn	%g1, PSTATE_IE, %g3
185125cf1a30Sjl139090	ba	1f			! cache align stick adj
185225cf1a30Sjl139090	wrpr	%g0, %g3, %pstate	! turn off interrupts
185325cf1a30Sjl139090
185425cf1a30Sjl139090	.align	16
185525cf1a30Sjl1390901:	nop
185625cf1a30Sjl139090
185725cf1a30Sjl139090	rd	STICK, %g4		! read stick reg
185825cf1a30Sjl139090	add	%g4, %o0, %o1		! adjust stick with skew
185925cf1a30Sjl139090	wr	%o1, %g0, STICK		! write stick reg
186025cf1a30Sjl139090
186125cf1a30Sjl139090	retl
186225cf1a30Sjl139090	wrpr	%g1, %pstate		! restore processor state
186325cf1a30Sjl139090	SET_SIZE(stick_adj)
186425cf1a30Sjl139090
186525cf1a30Sjl139090#endif	/* lint */
186625cf1a30Sjl139090
186725cf1a30Sjl139090#if defined(lint)
186825cf1a30Sjl139090/*
186925cf1a30Sjl139090 * Debugger-specific stick retrieval
187025cf1a30Sjl139090 */
187125cf1a30Sjl139090/*ARGSUSED*/
187225cf1a30Sjl139090int
187325cf1a30Sjl139090kdi_get_stick(uint64_t *stickp)
187425cf1a30Sjl139090{
187525cf1a30Sjl139090	return (0);
187625cf1a30Sjl139090}
187725cf1a30Sjl139090
187825cf1a30Sjl139090#else	/* lint */
187925cf1a30Sjl139090
188025cf1a30Sjl139090	ENTRY_NP(kdi_get_stick)
188125cf1a30Sjl139090	rd	STICK, %g1
188225cf1a30Sjl139090	stx	%g1, [%o0]
188325cf1a30Sjl139090	retl
188425cf1a30Sjl139090	mov	%g0, %o0
188525cf1a30Sjl139090	SET_SIZE(kdi_get_stick)
188625cf1a30Sjl139090
188725cf1a30Sjl139090#endif	/* lint */
188825cf1a30Sjl139090
188925cf1a30Sjl139090#if defined(lint)
189025cf1a30Sjl139090
189125cf1a30Sjl139090/*ARGSUSED*/
189225cf1a30Sjl139090int
189325cf1a30Sjl139090dtrace_blksuword32(uintptr_t addr, uint32_t *data, int tryagain)
189425cf1a30Sjl139090{ return (0); }
189525cf1a30Sjl139090
189625cf1a30Sjl139090#else
189725cf1a30Sjl139090
189825cf1a30Sjl139090	ENTRY(dtrace_blksuword32)
189925cf1a30Sjl139090	save	%sp, -SA(MINFRAME + 4), %sp
190025cf1a30Sjl139090
190125cf1a30Sjl139090	rdpr	%pstate, %l1
190225cf1a30Sjl139090	andn	%l1, PSTATE_IE, %l2		! disable interrupts to
190325cf1a30Sjl139090	wrpr	%g0, %l2, %pstate		! protect our FPU diddling
190425cf1a30Sjl139090
190525cf1a30Sjl139090	rd	%fprs, %l0
190625cf1a30Sjl139090	andcc	%l0, FPRS_FEF, %g0
190725cf1a30Sjl139090	bz,a,pt	%xcc, 1f			! if the fpu is disabled
190825cf1a30Sjl139090	wr	%g0, FPRS_FEF, %fprs		! ... enable the fpu
190925cf1a30Sjl139090
191025cf1a30Sjl139090	st	%f0, [%fp + STACK_BIAS - 4]	! save %f0 to the stack
191125cf1a30Sjl1390901:
191225cf1a30Sjl139090	set	0f, %l5
191325cf1a30Sjl139090	/*
191425cf1a30Sjl139090	 * We're about to write a block full or either total garbage
191525cf1a30Sjl139090	 * (not kernel data, don't worry) or user floating-point data
191625cf1a30Sjl139090	 * (so it only _looks_ like garbage).
191725cf1a30Sjl139090	 */
191825cf1a30Sjl139090	ld	[%i1], %f0			! modify the block
191925cf1a30Sjl139090	membar	#Sync
192025cf1a30Sjl139090	stn	%l5, [THREAD_REG + T_LOFAULT]	! set up the lofault handler
192125cf1a30Sjl139090	stda	%d0, [%i0]ASI_BLK_COMMIT_S	! store the modified block
192225cf1a30Sjl139090	membar	#Sync
1923f7832c8dShyw	flush	%i0				! flush instruction pipeline
192425cf1a30Sjl139090	stn	%g0, [THREAD_REG + T_LOFAULT]	! remove the lofault handler
192525cf1a30Sjl139090
192625cf1a30Sjl139090	bz,a,pt	%xcc, 1f
192725cf1a30Sjl139090	wr	%g0, %l0, %fprs			! restore %fprs
192825cf1a30Sjl139090
192925cf1a30Sjl139090	ld	[%fp + STACK_BIAS - 4], %f0	! restore %f0
193025cf1a30Sjl1390901:
193125cf1a30Sjl139090
193225cf1a30Sjl139090	wrpr	%g0, %l1, %pstate		! restore interrupts
193325cf1a30Sjl139090
193425cf1a30Sjl139090	ret
193525cf1a30Sjl139090	restore	%g0, %g0, %o0
193625cf1a30Sjl139090
193725cf1a30Sjl1390900:
193825cf1a30Sjl139090	membar	#Sync
193925cf1a30Sjl139090	stn	%g0, [THREAD_REG + T_LOFAULT]	! remove the lofault handler
194025cf1a30Sjl139090
194125cf1a30Sjl139090	bz,a,pt	%xcc, 1f
194225cf1a30Sjl139090	wr	%g0, %l0, %fprs			! restore %fprs
194325cf1a30Sjl139090
194425cf1a30Sjl139090	ld	[%fp + STACK_BIAS - 4], %f0	! restore %f0
194525cf1a30Sjl1390901:
194625cf1a30Sjl139090
194725cf1a30Sjl139090	wrpr	%g0, %l1, %pstate		! restore interrupts
194825cf1a30Sjl139090
194925cf1a30Sjl139090	/*
195025cf1a30Sjl139090	 * If tryagain is set (%i2) we tail-call dtrace_blksuword32_err()
195125cf1a30Sjl139090	 * which deals with watchpoints. Otherwise, just return -1.
195225cf1a30Sjl139090	 */
195325cf1a30Sjl139090	brnz,pt	%i2, 1f
195425cf1a30Sjl139090	nop
195525cf1a30Sjl139090	ret
195625cf1a30Sjl139090	restore	%g0, -1, %o0
195725cf1a30Sjl1390901:
195825cf1a30Sjl139090	call	dtrace_blksuword32_err
195925cf1a30Sjl139090	restore
196025cf1a30Sjl139090
196125cf1a30Sjl139090	SET_SIZE(dtrace_blksuword32)
196225cf1a30Sjl139090#endif /* lint */
196325cf1a30Sjl139090
196425cf1a30Sjl139090#if defined(lint)
196525cf1a30Sjl139090/*ARGSUSED*/
196625cf1a30Sjl139090void
196725cf1a30Sjl139090ras_cntr_reset(void *arg)
196825cf1a30Sjl139090{
196925cf1a30Sjl139090}
197025cf1a30Sjl139090#else
197125cf1a30Sjl139090	ENTRY_NP(ras_cntr_reset)
197225cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, %o1
197325cf1a30Sjl139090	ldxa	[%o1]ASI_SCRATCHPAD, %o0
197425cf1a30Sjl139090	or	%o0, ERRLOG_REG_NUMERR_MASK, %o0
197525cf1a30Sjl139090	retl
197625cf1a30Sjl139090	 stxa	%o0, [%o1]ASI_SCRATCHPAD
197725cf1a30Sjl139090	SET_SIZE(ras_cntr_reset)
197825cf1a30Sjl139090#endif /* lint */
197925cf1a30Sjl139090
198025cf1a30Sjl139090#if defined(lint)
198125cf1a30Sjl139090/* ARGSUSED */
198225cf1a30Sjl139090void
198325cf1a30Sjl139090opl_error_setup(uint64_t cpu_err_log_pa)
198425cf1a30Sjl139090{
198525cf1a30Sjl139090}
198625cf1a30Sjl139090
198725cf1a30Sjl139090#else	/* lint */
198825cf1a30Sjl139090	ENTRY_NP(opl_error_setup)
198925cf1a30Sjl139090	/*
199025cf1a30Sjl139090	 * Initialize the error log scratchpad register
199125cf1a30Sjl139090	 */
199225cf1a30Sjl139090	ldxa	[%g0]ASI_EIDR, %o2
199325cf1a30Sjl139090	sethi	%hi(ERRLOG_REG_EIDR_MASK), %o1
199425cf1a30Sjl139090	or	%o1, %lo(ERRLOG_REG_EIDR_MASK), %o1
199525cf1a30Sjl139090	and	%o2, %o1, %o3
199625cf1a30Sjl139090	sllx	%o3, ERRLOG_REG_EIDR_SHIFT, %o2
199725cf1a30Sjl139090	or	%o2, %o0, %o3
199825cf1a30Sjl139090	or	%o3, ERRLOG_REG_NUMERR_MASK, %o0
199925cf1a30Sjl139090	set	OPL_SCRATCHPAD_ERRLOG, %o1
200025cf1a30Sjl139090	stxa	%o0, [%o1]ASI_SCRATCHPAD
200125cf1a30Sjl139090	/*
200225cf1a30Sjl139090	 * Disable all restrainable error traps
200325cf1a30Sjl139090	 */
200425cf1a30Sjl139090	mov	AFSR_ECR, %o1
200525cf1a30Sjl139090	ldxa	[%o1]ASI_AFSR, %o0
200625cf1a30Sjl139090	andn	%o0, ASI_ECR_RTE_UE|ASI_ECR_RTE_CEDG, %o0
200725cf1a30Sjl139090	retl
200825cf1a30Sjl139090	  stxa	%o0, [%o1]ASI_AFSR
200925cf1a30Sjl139090	SET_SIZE(opl_error_setup)
201025cf1a30Sjl139090#endif /* lint */
201125cf1a30Sjl139090
201225cf1a30Sjl139090#if defined(lint)
201325cf1a30Sjl139090/* ARGSUSED */
201425cf1a30Sjl139090void
2015*c9d93b53SJames Andersoncpu_early_feature_init(void)
201625cf1a30Sjl139090{
201725cf1a30Sjl139090}
201825cf1a30Sjl139090#else	/* lint */
2019*c9d93b53SJames Anderson	ENTRY_NP(cpu_early_feature_init)
202025cf1a30Sjl139090	/*
202125cf1a30Sjl139090	 * Enable MMU translating multiple page sizes for
202225cf1a30Sjl139090	 * sITLB and sDTLB.
202325cf1a30Sjl139090	 */
202425cf1a30Sjl139090        mov	LSU_MCNTL, %o0
202525cf1a30Sjl139090        ldxa	[%o0] ASI_MCNTL, %o1
202625cf1a30Sjl139090        or	%o1, MCNTL_MPG_SITLB | MCNTL_MPG_SDTLB, %o1
202725cf1a30Sjl139090          stxa	%o1, [%o0] ASI_MCNTL
2028*c9d93b53SJames Anderson	/*
2029*c9d93b53SJames Anderson	 * Demap all previous entries.
2030*c9d93b53SJames Anderson	 */
2031*c9d93b53SJames Anderson	sethi	%hi(FLUSH_ADDR), %o1
2032*c9d93b53SJames Anderson	set	DEMAP_ALL_TYPE, %o0
2033*c9d93b53SJames Anderson	stxa	%g0, [%o0]ASI_DTLB_DEMAP
2034*c9d93b53SJames Anderson	stxa	%g0, [%o0]ASI_ITLB_DEMAP
2035*c9d93b53SJames Anderson	retl
2036*c9d93b53SJames Anderson	  flush	%o1
2037*c9d93b53SJames Anderson	SET_SIZE(cpu_early_feature_init)
203825cf1a30Sjl139090#endif /* lint */
203925cf1a30Sjl139090
204025cf1a30Sjl139090#if	defined(lint)
204125cf1a30Sjl139090/*
204225cf1a30Sjl139090 * This function is called for each (enabled) CPU. We use it to
204325cf1a30Sjl139090 * initialize error handling related registers.
204425cf1a30Sjl139090 */
204525cf1a30Sjl139090/*ARGSUSED*/
204625cf1a30Sjl139090void
204725cf1a30Sjl139090cpu_feature_init(void)
204825cf1a30Sjl139090{}
204925cf1a30Sjl139090#else	/* lint */
205025cf1a30Sjl139090	ENTRY(cpu_feature_init)
205125cf1a30Sjl139090	!
205225cf1a30Sjl139090	! get the device_id and store the device_id
205325cf1a30Sjl139090	! in the appropriate cpunodes structure
205425cf1a30Sjl139090	! given the cpus index
205525cf1a30Sjl139090	!
205625cf1a30Sjl139090	CPU_INDEX(%o0, %o1)
205725cf1a30Sjl139090	mulx %o0, CPU_NODE_SIZE, %o0
205825cf1a30Sjl139090	set  cpunodes + DEVICE_ID, %o1
205925cf1a30Sjl139090	ldxa [%g0] ASI_DEVICE_SERIAL_ID, %o2
206025cf1a30Sjl139090	stx  %o2, [%o0 + %o1]
206125cf1a30Sjl139090	!
206225cf1a30Sjl139090	! initialize CPU registers
206325cf1a30Sjl139090	!
206425cf1a30Sjl139090	ba	opl_cpu_reg_init
206525cf1a30Sjl139090	nop
206625cf1a30Sjl139090	SET_SIZE(cpu_feature_init)
206725cf1a30Sjl139090#endif	/* lint */
206825cf1a30Sjl139090
206925cf1a30Sjl139090#if defined(lint)
207025cf1a30Sjl139090
207125cf1a30Sjl139090void
207225cf1a30Sjl139090cpu_cleartickpnt(void)
207325cf1a30Sjl139090{}
207425cf1a30Sjl139090
207525cf1a30Sjl139090#else	/* lint */
207625cf1a30Sjl139090	/*
207725cf1a30Sjl139090	 * Clear the NPT (non-privileged trap) bit in the %tick/%stick
207825cf1a30Sjl139090	 * registers. In an effort to make the change in the
207925cf1a30Sjl139090	 * tick/stick counter as consistent as possible, we disable
208025cf1a30Sjl139090	 * all interrupts while we're changing the registers. We also
208125cf1a30Sjl139090	 * ensure that the read and write instructions are in the same
208225cf1a30Sjl139090	 * line in the instruction cache.
208325cf1a30Sjl139090	 */
208425cf1a30Sjl139090	ENTRY_NP(cpu_clearticknpt)
208525cf1a30Sjl139090	rdpr	%pstate, %g1		/* save processor state */
208625cf1a30Sjl139090	andn	%g1, PSTATE_IE, %g3	/* turn off */
208725cf1a30Sjl139090	wrpr	%g0, %g3, %pstate	/*   interrupts */
208825cf1a30Sjl139090	rdpr	%tick, %g2		/* get tick register */
208925cf1a30Sjl139090	brgez,pn %g2, 1f		/* if NPT bit off, we're done */
209025cf1a30Sjl139090	mov	1, %g3			/* create mask */
209125cf1a30Sjl139090	sllx	%g3, 63, %g3		/*   for NPT bit */
209225cf1a30Sjl139090	ba,a,pt	%xcc, 2f
209325cf1a30Sjl139090	.align	8			/* Ensure rd/wr in same i$ line */
209425cf1a30Sjl1390902:
209525cf1a30Sjl139090	rdpr	%tick, %g2		/* get tick register */
209625cf1a30Sjl139090	wrpr	%g3, %g2, %tick		/* write tick register, */
209725cf1a30Sjl139090					/*   clearing NPT bit   */
209825cf1a30Sjl1390901:
209925cf1a30Sjl139090	rd	STICK, %g2		/* get stick register */
210025cf1a30Sjl139090	brgez,pn %g2, 3f		/* if NPT bit off, we're done */
210125cf1a30Sjl139090	mov	1, %g3			/* create mask */
210225cf1a30Sjl139090	sllx	%g3, 63, %g3		/*   for NPT bit */
210325cf1a30Sjl139090	ba,a,pt	%xcc, 4f
210425cf1a30Sjl139090	.align	8			/* Ensure rd/wr in same i$ line */
210525cf1a30Sjl1390904:
210625cf1a30Sjl139090	rd	STICK, %g2		/* get stick register */
210725cf1a30Sjl139090	wr	%g3, %g2, STICK		/* write stick register, */
210825cf1a30Sjl139090					/*   clearing NPT bit   */
210925cf1a30Sjl1390903:
211025cf1a30Sjl139090	jmp	%g4 + 4
211125cf1a30Sjl139090	wrpr	%g0, %g1, %pstate	/* restore processor state */
211225cf1a30Sjl139090
211325cf1a30Sjl139090	SET_SIZE(cpu_clearticknpt)
211425cf1a30Sjl139090
211525cf1a30Sjl139090#endif	/* lint */
211625cf1a30Sjl139090
211725cf1a30Sjl139090#if defined(lint)
211825cf1a30Sjl139090
211925cf1a30Sjl139090void
212025cf1a30Sjl139090cpu_halt_cpu(void)
212125cf1a30Sjl139090{}
212225cf1a30Sjl139090
212325cf1a30Sjl139090void
212425cf1a30Sjl139090cpu_smt_pause(void)
212525cf1a30Sjl139090{}
212625cf1a30Sjl139090
212725cf1a30Sjl139090#else	/* lint */
212825cf1a30Sjl139090
212925cf1a30Sjl139090	/*
213025cf1a30Sjl139090	 * Halt the current strand with the suspend instruction.
213125cf1a30Sjl139090	 * The compiler/asm currently does not support this suspend
213225cf1a30Sjl139090	 * instruction mnemonic, use byte code for now.
213325cf1a30Sjl139090	 */
213425cf1a30Sjl139090	ENTRY_NP(cpu_halt_cpu)
213525cf1a30Sjl139090	.word   0x81b01040
213625cf1a30Sjl139090	retl
213725cf1a30Sjl139090	nop
213825cf1a30Sjl139090	SET_SIZE(cpu_halt_cpu)
213925cf1a30Sjl139090
214025cf1a30Sjl139090	/*
214125cf1a30Sjl139090	 * Pause the current strand with the sleep instruction.
214225cf1a30Sjl139090	 * The compiler/asm currently does not support this sleep
214325cf1a30Sjl139090	 * instruction mnemonic, use byte code for now.
214425cf1a30Sjl139090	 */
214525cf1a30Sjl139090	ENTRY_NP(cpu_smt_pause)
214625cf1a30Sjl139090	.word   0x81b01060
214725cf1a30Sjl139090	retl
214825cf1a30Sjl139090	nop
214925cf1a30Sjl139090	SET_SIZE(cpu_smt_pause)
215025cf1a30Sjl139090
215125cf1a30Sjl139090#endif	/* lint */
2152