xref: /titanic_50/usr/src/uts/sun4u/cpu/spitfire_asm.s (revision 2dd3029adb4864ebca3dd9cd6dad5fc4d38abff6)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51e2e7a75Shuah * Common Development and Distribution License (the "License").
61e2e7a75Shuah * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate/*
22*2dd3029aSjimand * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate#if !defined(lint)
297c478bd9Sstevel@tonic-gate#include "assym.h"
307c478bd9Sstevel@tonic-gate#endif	/* lint */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
337c478bd9Sstevel@tonic-gate#include <sys/mmu.h>
347c478bd9Sstevel@tonic-gate#include <vm/hat_sfmmu.h>
357c478bd9Sstevel@tonic-gate#include <sys/machparam.h>
367c478bd9Sstevel@tonic-gate#include <sys/machcpuvar.h>
377c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
387c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
397c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
407c478bd9Sstevel@tonic-gate#include <sys/machasi.h>
417c478bd9Sstevel@tonic-gate#include <sys/trap.h>
427c478bd9Sstevel@tonic-gate#include <sys/spitregs.h>
437c478bd9Sstevel@tonic-gate#include <sys/xc_impl.h>
447c478bd9Sstevel@tonic-gate#include <sys/intreg.h>
457c478bd9Sstevel@tonic-gate#include <sys/async.h>
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
487c478bd9Sstevel@tonic-gate#include <sys/traptrace.h>
497c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate#ifndef	lint
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate/* BEGIN CSTYLED */
547c478bd9Sstevel@tonic-gate#define	DCACHE_FLUSHPAGE(arg1, arg2, tmp1, tmp2, tmp3)			\
557c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_LSU, tmp1					;\
567c478bd9Sstevel@tonic-gate	btst	LSU_DC, tmp1		/* is dcache enabled? */	;\
577c478bd9Sstevel@tonic-gate	bz,pn	%icc, 1f						;\
587c478bd9Sstevel@tonic-gate	sethi	%hi(dcache_linesize), tmp1				;\
597c478bd9Sstevel@tonic-gate	ld	[tmp1 + %lo(dcache_linesize)], tmp1			;\
607c478bd9Sstevel@tonic-gate	sethi	%hi(dflush_type), tmp2					;\
617c478bd9Sstevel@tonic-gate	ld	[tmp2 + %lo(dflush_type)], tmp2				;\
627c478bd9Sstevel@tonic-gate	cmp	tmp2, FLUSHPAGE_TYPE					;\
637c478bd9Sstevel@tonic-gate	be,pt	%icc, 2f						;\
647c478bd9Sstevel@tonic-gate	sllx	arg1, SF_DC_VBIT_SHIFT, arg1	/* tag to compare */	;\
657c478bd9Sstevel@tonic-gate	sethi	%hi(dcache_size), tmp3					;\
667c478bd9Sstevel@tonic-gate	ld	[tmp3 + %lo(dcache_size)], tmp3				;\
677c478bd9Sstevel@tonic-gate	cmp	tmp2, FLUSHMATCH_TYPE					;\
687c478bd9Sstevel@tonic-gate	be,pt	%icc, 3f						;\
697c478bd9Sstevel@tonic-gate	nop								;\
707c478bd9Sstevel@tonic-gate	/*								\
717c478bd9Sstevel@tonic-gate	 * flushtype = FLUSHALL_TYPE, flush the whole thing		\
727c478bd9Sstevel@tonic-gate	 * tmp3 = cache size						\
737c478bd9Sstevel@tonic-gate	 * tmp1 = cache line size					\
747c478bd9Sstevel@tonic-gate	 */								\
757c478bd9Sstevel@tonic-gate	sub	tmp3, tmp1, tmp2					;\
767c478bd9Sstevel@tonic-gate4:									\
777c478bd9Sstevel@tonic-gate	stxa	%g0, [tmp2]ASI_DC_TAG					;\
787c478bd9Sstevel@tonic-gate	membar	#Sync							;\
797c478bd9Sstevel@tonic-gate	cmp	%g0, tmp2						;\
807c478bd9Sstevel@tonic-gate	bne,pt	%icc, 4b						;\
817c478bd9Sstevel@tonic-gate	sub	tmp2, tmp1, tmp2					;\
827c478bd9Sstevel@tonic-gate	ba,pt	%icc, 1f						;\
837c478bd9Sstevel@tonic-gate	nop								;\
847c478bd9Sstevel@tonic-gate	/*								\
857c478bd9Sstevel@tonic-gate	 * flushtype = FLUSHPAGE_TYPE					\
867c478bd9Sstevel@tonic-gate	 * arg1 = tag to compare against				\
877c478bd9Sstevel@tonic-gate	 * arg2 = virtual color						\
887c478bd9Sstevel@tonic-gate	 * tmp1 = cache line size					\
897c478bd9Sstevel@tonic-gate	 * tmp2 = tag from cache					\
907c478bd9Sstevel@tonic-gate	 * tmp3 = counter						\
917c478bd9Sstevel@tonic-gate	 */								\
927c478bd9Sstevel@tonic-gate2:									\
937c478bd9Sstevel@tonic-gate	set	MMU_PAGESIZE, tmp3					;\
947c478bd9Sstevel@tonic-gate	sllx	arg2, MMU_PAGESHIFT, arg2  /* color to dcache page */	;\
957c478bd9Sstevel@tonic-gate	sub	tmp3, tmp1, tmp3					;\
967c478bd9Sstevel@tonic-gate4:									\
977c478bd9Sstevel@tonic-gate	ldxa	[arg2 + tmp3]ASI_DC_TAG, tmp2	/* read tag */		;\
987c478bd9Sstevel@tonic-gate	btst	SF_DC_VBIT_MASK, tmp2					;\
997c478bd9Sstevel@tonic-gate	bz,pn	%icc, 5f	  /* branch if no valid sub-blocks */	;\
1007c478bd9Sstevel@tonic-gate	andn	tmp2, SF_DC_VBIT_MASK, tmp2	/* clear out v bits */	;\
1017c478bd9Sstevel@tonic-gate	cmp	tmp2, arg1						;\
1027c478bd9Sstevel@tonic-gate	bne,pn	%icc, 5f			/* br if tag miss */	;\
1037c478bd9Sstevel@tonic-gate	nop								;\
1047c478bd9Sstevel@tonic-gate	stxa	%g0, [arg2 + tmp3]ASI_DC_TAG				;\
1057c478bd9Sstevel@tonic-gate	membar	#Sync							;\
1067c478bd9Sstevel@tonic-gate5:									\
1077c478bd9Sstevel@tonic-gate	cmp	%g0, tmp3						;\
1087c478bd9Sstevel@tonic-gate	bnz,pt	%icc, 4b		/* branch if not done */	;\
1097c478bd9Sstevel@tonic-gate	sub	tmp3, tmp1, tmp3					;\
1107c478bd9Sstevel@tonic-gate	ba,pt	%icc, 1f						;\
1117c478bd9Sstevel@tonic-gate	nop								;\
1127c478bd9Sstevel@tonic-gate	/*								\
1137c478bd9Sstevel@tonic-gate	 * flushtype = FLUSHMATCH_TYPE					\
1147c478bd9Sstevel@tonic-gate	 * arg1 = tag to compare against				\
1157c478bd9Sstevel@tonic-gate	 * tmp1 = cache line size					\
1167c478bd9Sstevel@tonic-gate	 * tmp3 = cache size						\
1177c478bd9Sstevel@tonic-gate	 * arg2 = counter						\
1187c478bd9Sstevel@tonic-gate	 * tmp2 = cache tag						\
1197c478bd9Sstevel@tonic-gate	 */								\
1207c478bd9Sstevel@tonic-gate3:									\
1217c478bd9Sstevel@tonic-gate	sub	tmp3, tmp1, arg2					;\
1227c478bd9Sstevel@tonic-gate4:									\
1237c478bd9Sstevel@tonic-gate	ldxa	[arg2]ASI_DC_TAG, tmp2		/* read tag */		;\
1247c478bd9Sstevel@tonic-gate	btst	SF_DC_VBIT_MASK, tmp2					;\
1257c478bd9Sstevel@tonic-gate	bz,pn	%icc, 5f		/* br if no valid sub-blocks */	;\
1267c478bd9Sstevel@tonic-gate	andn	tmp2, SF_DC_VBIT_MASK, tmp2	/* clear out v bits */	;\
1277c478bd9Sstevel@tonic-gate	cmp	tmp2, arg1						;\
1287c478bd9Sstevel@tonic-gate	bne,pn	%icc, 5f		/* branch if tag miss */	;\
1297c478bd9Sstevel@tonic-gate	nop								;\
1307c478bd9Sstevel@tonic-gate	stxa	%g0, [arg2]ASI_DC_TAG					;\
1317c478bd9Sstevel@tonic-gate	membar	#Sync							;\
1327c478bd9Sstevel@tonic-gate5:									\
1337c478bd9Sstevel@tonic-gate	cmp	%g0, arg2						;\
1347c478bd9Sstevel@tonic-gate	bne,pt	%icc, 4b		/* branch if not done */	;\
1357c478bd9Sstevel@tonic-gate	sub	arg2, tmp1, arg2					;\
1367c478bd9Sstevel@tonic-gate1:
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate/*
1397c478bd9Sstevel@tonic-gate * macro that flushes the entire dcache color
1407c478bd9Sstevel@tonic-gate */
1417c478bd9Sstevel@tonic-gate#define	DCACHE_FLUSHCOLOR(arg, tmp1, tmp2)				\
1427c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_LSU, tmp1;					\
1437c478bd9Sstevel@tonic-gate	btst	LSU_DC, tmp1;		/* is dcache enabled? */	\
1447c478bd9Sstevel@tonic-gate	bz,pn	%icc, 1f;						\
1457c478bd9Sstevel@tonic-gate	sethi	%hi(dcache_linesize), tmp1;				\
1467c478bd9Sstevel@tonic-gate	ld	[tmp1 + %lo(dcache_linesize)], tmp1;			\
1477c478bd9Sstevel@tonic-gate	set	MMU_PAGESIZE, tmp2;					\
1487c478bd9Sstevel@tonic-gate	/*								\
1497c478bd9Sstevel@tonic-gate	 * arg = virtual color						\
1507c478bd9Sstevel@tonic-gate	 * tmp2 = page size						\
1517c478bd9Sstevel@tonic-gate	 * tmp1 = cache line size					\
1527c478bd9Sstevel@tonic-gate	 */								\
1537c478bd9Sstevel@tonic-gate	sllx	arg, MMU_PAGESHIFT, arg; /* color to dcache page */	\
1547c478bd9Sstevel@tonic-gate	sub	tmp2, tmp1, tmp2;					\
1557c478bd9Sstevel@tonic-gate2:									\
1567c478bd9Sstevel@tonic-gate	stxa	%g0, [arg + tmp2]ASI_DC_TAG;				\
1577c478bd9Sstevel@tonic-gate	membar	#Sync;							\
1587c478bd9Sstevel@tonic-gate	cmp	%g0, tmp2;						\
1597c478bd9Sstevel@tonic-gate	bne,pt	%icc, 2b;						\
1607c478bd9Sstevel@tonic-gate	sub	tmp2, tmp1, tmp2;					\
1617c478bd9Sstevel@tonic-gate1:
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate/*
1647c478bd9Sstevel@tonic-gate * macro that flushes the entire dcache
1657c478bd9Sstevel@tonic-gate */
1667c478bd9Sstevel@tonic-gate#define	DCACHE_FLUSHALL(size, linesize, tmp)				\
1677c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_LSU, tmp;					\
1687c478bd9Sstevel@tonic-gate	btst	LSU_DC, tmp;		/* is dcache enabled? */	\
1697c478bd9Sstevel@tonic-gate	bz,pn	%icc, 1f;						\
1707c478bd9Sstevel@tonic-gate									\
1717c478bd9Sstevel@tonic-gate	sub	size, linesize, tmp;					\
1727c478bd9Sstevel@tonic-gate2:									\
1737c478bd9Sstevel@tonic-gate	stxa	%g0, [tmp]ASI_DC_TAG;					\
1747c478bd9Sstevel@tonic-gate	membar	#Sync;							\
1757c478bd9Sstevel@tonic-gate	cmp	%g0, tmp;						\
1767c478bd9Sstevel@tonic-gate	bne,pt	%icc, 2b;						\
1777c478bd9Sstevel@tonic-gate	sub	tmp, linesize, tmp;					\
1787c478bd9Sstevel@tonic-gate1:
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate/*
1817c478bd9Sstevel@tonic-gate * macro that flushes the entire icache
1827c478bd9Sstevel@tonic-gate */
1837c478bd9Sstevel@tonic-gate#define	ICACHE_FLUSHALL(size, linesize, tmp)				\
1847c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_LSU, tmp;					\
1857c478bd9Sstevel@tonic-gate	btst	LSU_IC, tmp;						\
1867c478bd9Sstevel@tonic-gate	bz,pn	%icc, 1f;						\
1877c478bd9Sstevel@tonic-gate									\
1887c478bd9Sstevel@tonic-gate	sub	size, linesize, tmp;					\
1897c478bd9Sstevel@tonic-gate2:									\
1907c478bd9Sstevel@tonic-gate	stxa	%g0, [tmp]ASI_IC_TAG;					\
1917c478bd9Sstevel@tonic-gate	membar	#Sync;							\
1927c478bd9Sstevel@tonic-gate	cmp	%g0, tmp;						\
1937c478bd9Sstevel@tonic-gate	bne,pt	%icc, 2b;						\
1947c478bd9Sstevel@tonic-gate	sub	tmp, linesize, tmp;					\
1957c478bd9Sstevel@tonic-gate1:
1967c478bd9Sstevel@tonic-gate
1971e2e7a75Shuah#ifdef SF_ERRATA_32
1981e2e7a75Shuah#define SF_WORKAROUND(tmp1, tmp2)                               \
1991e2e7a75Shuah        sethi   %hi(FLUSH_ADDR), tmp2                           ;\
2001e2e7a75Shuah        set     MMU_PCONTEXT, tmp1                              ;\
2011e2e7a75Shuah        stxa    %g0, [tmp1]ASI_DMMU                             ;\
2021e2e7a75Shuah        flush   tmp2                                            ;
2031e2e7a75Shuah#else
2041e2e7a75Shuah#define SF_WORKAROUND(tmp1, tmp2)
2051e2e7a75Shuah#endif /* SF_ERRATA_32 */
2061e2e7a75Shuah
2071e2e7a75Shuah/*
2081e2e7a75Shuah * arg1 = vaddr
2091e2e7a75Shuah * arg2 = ctxnum
2101e2e7a75Shuah *      - disable interrupts and clear address mask
2111e2e7a75Shuah *        to access 64 bit physaddr
2121e2e7a75Shuah *      - Blow out the TLB, flush user page.
2131e2e7a75Shuah *        . use secondary context.
2141e2e7a75Shuah */
2151e2e7a75Shuah#define VTAG_FLUSHUPAGE(lbl, arg1, arg2, tmp1, tmp2, tmp3, tmp4) \
2161e2e7a75Shuah        rdpr    %pstate, tmp1                                   ;\
2171e2e7a75Shuah        andn    tmp1, PSTATE_IE, tmp2				;\
2181e2e7a75Shuah        wrpr    tmp2, 0, %pstate                                ;\
2191e2e7a75Shuah        sethi   %hi(FLUSH_ADDR), tmp2                           ;\
2201e2e7a75Shuah        set     MMU_SCONTEXT, tmp3                              ;\
2211e2e7a75Shuah        ldxa    [tmp3]ASI_DMMU, tmp4                            ;\
2221e2e7a75Shuah        or      DEMAP_SECOND | DEMAP_PAGE_TYPE, arg1, arg1      ;\
2231e2e7a75Shuah        cmp     tmp4, arg2                                      ;\
2241e2e7a75Shuah        be,a,pt %icc, lbl/**/4                                  ;\
2251e2e7a75Shuah          nop                                                   ;\
2261e2e7a75Shuah        stxa    arg2, [tmp3]ASI_DMMU                            ;\
2271e2e7a75Shuahlbl/**/4:                                                       ;\
2281e2e7a75Shuah        stxa    %g0, [arg1]ASI_DTLB_DEMAP                       ;\
2291e2e7a75Shuah        stxa    %g0, [arg1]ASI_ITLB_DEMAP                       ;\
2301e2e7a75Shuah        flush   tmp2                                            ;\
2311e2e7a75Shuah        be,a,pt %icc, lbl/**/5                                  ;\
2321e2e7a75Shuah          nop                                                   ;\
2331e2e7a75Shuah        stxa    tmp4, [tmp3]ASI_DMMU                            ;\
2341e2e7a75Shuah        flush   tmp2                                            ;\
2351e2e7a75Shuahlbl/**/5:                                                       ;\
2361e2e7a75Shuah        wrpr    %g0, tmp1, %pstate
2371e2e7a75Shuah
2381e2e7a75Shuah
2391e2e7a75Shuah/*
2401e2e7a75Shuah * macro that flushes all the user entries in dtlb
2411e2e7a75Shuah * arg1 = dtlb entries
2421e2e7a75Shuah *	- Before first compare:
2431e2e7a75Shuah *              tmp4 = tte
2441e2e7a75Shuah *              tmp5 = vaddr
2451e2e7a75Shuah *              tmp6 = cntxnum
2461e2e7a75Shuah */
2471e2e7a75Shuah#define DTLB_FLUSH_UNLOCKED_UCTXS(lbl, arg1, tmp1, tmp2, tmp3, \
2481e2e7a75Shuah                                tmp4, tmp5, tmp6) \
2491e2e7a75Shuahlbl/**/0:                                                       ;\
2501e2e7a75Shuah        sllx    arg1, 3, tmp3                                   ;\
2511e2e7a75Shuah        SF_WORKAROUND(tmp1, tmp2)                               ;\
2521e2e7a75Shuah        ldxa    [tmp3]ASI_DTLB_ACCESS, tmp4                     ;\
2531e2e7a75Shuah        srlx    tmp4, 6, tmp4                                   ;\
2541e2e7a75Shuah        andcc   tmp4, 1, %g0                                    ;\
2551e2e7a75Shuah        bnz,pn  %xcc, lbl/**/1                                  ;\
2561e2e7a75Shuah        srlx    tmp4, 57, tmp4                                  ;\
2571e2e7a75Shuah        andcc   tmp4, 1, %g0                                    ;\
2581e2e7a75Shuah        beq,pn  %xcc, lbl/**/1                                  ;\
2591e2e7a75Shuah          nop                                                   ;\
2601e2e7a75Shuah        set     TAGREAD_CTX_MASK, tmp1                          ;\
2611e2e7a75Shuah        ldxa    [tmp3]ASI_DTLB_TAGREAD, tmp2                    ;\
2621e2e7a75Shuah        and     tmp2, tmp1, tmp6                                ;\
2631e2e7a75Shuah        andn    tmp2, tmp1, tmp5                                ;\
2641e2e7a75Shuah	set	KCONTEXT, tmp4					;\
2651e2e7a75Shuah	cmp	tmp6, tmp4					;\
2661e2e7a75Shuah	be	lbl/**/1					;\
2671e2e7a75Shuah	  nop							;\
2681e2e7a75Shuah        VTAG_FLUSHUPAGE(VD/**/lbl, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\
2691e2e7a75Shuahlbl/**/1:                                                       ;\
2701e2e7a75Shuah        brgz,pt arg1, lbl/**/0                                  ;\
2711e2e7a75Shuah          sub     arg1, 1, arg1
2721e2e7a75Shuah
2731e2e7a75Shuah
2741e2e7a75Shuah/*
2751e2e7a75Shuah * macro that flushes all the user entries in itlb
2761e2e7a75Shuah * arg1 = itlb entries
2771e2e7a75Shuah *      - Before first compare:
2781e2e7a75Shuah *              tmp4 = tte
2791e2e7a75Shuah *              tmp5 = vaddr
2801e2e7a75Shuah *              tmp6 = cntxnum
2811e2e7a75Shuah */
2821e2e7a75Shuah#define ITLB_FLUSH_UNLOCKED_UCTXS(lbl, arg1, tmp1, tmp2, tmp3, \
2831e2e7a75Shuah                                tmp4, tmp5, tmp6) \
2841e2e7a75Shuahlbl/**/0:                                                       ;\
2851e2e7a75Shuah        sllx    arg1, 3, tmp3                                   ;\
2861e2e7a75Shuah        SF_WORKAROUND(tmp1, tmp2)                               ;\
2871e2e7a75Shuah        ldxa    [tmp3]ASI_ITLB_ACCESS, tmp4                     ;\
2881e2e7a75Shuah        srlx    tmp4, 6, tmp4                                   ;\
2891e2e7a75Shuah        andcc   tmp4, 1, %g0                                    ;\
2901e2e7a75Shuah        bnz,pn  %xcc, lbl/**/1                                  ;\
2911e2e7a75Shuah        srlx    tmp4, 57, tmp4                                  ;\
2921e2e7a75Shuah        andcc   tmp4, 1, %g0                                    ;\
2931e2e7a75Shuah        beq,pn  %xcc, lbl/**/1                                  ;\
2941e2e7a75Shuah          nop                                                   ;\
2951e2e7a75Shuah        set     TAGREAD_CTX_MASK, tmp1                          ;\
2961e2e7a75Shuah        ldxa    [tmp3]ASI_ITLB_TAGREAD, tmp2                    ;\
2971e2e7a75Shuah        and     tmp2, tmp1, tmp6                                ;\
2981e2e7a75Shuah        andn    tmp2, tmp1, tmp5                                ;\
2991e2e7a75Shuah	set	KCONTEXT, tmp4					;\
3001e2e7a75Shuah	cmp	tmp6, tmp4					;\
3011e2e7a75Shuah	be	lbl/**/1					;\
3021e2e7a75Shuah	  nop							;\
3031e2e7a75Shuah        VTAG_FLUSHUPAGE(VI/**/lbl, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\
3041e2e7a75Shuahlbl/**/1:                                                       ;\
3051e2e7a75Shuah        brgz,pt arg1, lbl/**/0                                  ;\
3061e2e7a75Shuah        sub     arg1, 1, arg1
3071e2e7a75Shuah
3081e2e7a75Shuah
3091e2e7a75Shuah
3107c478bd9Sstevel@tonic-gate/*
3117c478bd9Sstevel@tonic-gate * Macro for getting to offset from 'cpu_private' ptr. The 'cpu_private'
3127c478bd9Sstevel@tonic-gate * ptr is in the machcpu structure.
3137c478bd9Sstevel@tonic-gate * r_or_s:	Register or symbol off offset from 'cpu_private' ptr.
3147c478bd9Sstevel@tonic-gate * scr1:	Scratch, ptr is returned in this register.
3157c478bd9Sstevel@tonic-gate * scr2:	Scratch
3167c478bd9Sstevel@tonic-gate */
3177c478bd9Sstevel@tonic-gate#define GET_CPU_PRIVATE_PTR(r_or_s, scr1, scr2, label)		\
3187c478bd9Sstevel@tonic-gate	CPU_ADDR(scr1, scr2);						\
3197c478bd9Sstevel@tonic-gate	ldn	[scr1 + CPU_PRIVATE], scr1; 				\
3207c478bd9Sstevel@tonic-gate	cmp	scr1, 0; 						\
3217c478bd9Sstevel@tonic-gate	be	label;							\
3227c478bd9Sstevel@tonic-gate	 nop; 								\
3237c478bd9Sstevel@tonic-gate	add	scr1, r_or_s, scr1;  					\
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate#ifdef HUMMINGBIRD
3267c478bd9Sstevel@tonic-gate/*
3277c478bd9Sstevel@tonic-gate * UltraSPARC-IIe processor supports both 4-way set associative and
3287c478bd9Sstevel@tonic-gate * direct map E$. For performance reasons, we flush E$ by placing it
3297c478bd9Sstevel@tonic-gate * in direct map mode for data load/store and restore the state after
3307c478bd9Sstevel@tonic-gate * we are done flushing it. Keep interrupts off while flushing in this
3317c478bd9Sstevel@tonic-gate * manner.
3327c478bd9Sstevel@tonic-gate *
3337c478bd9Sstevel@tonic-gate * We flush the entire ecache by starting at one end and loading each
3347c478bd9Sstevel@tonic-gate * successive ecache line for the 2*ecache-size range. We have to repeat
3357c478bd9Sstevel@tonic-gate * the flush operation to guarantee that the entire ecache has been
3367c478bd9Sstevel@tonic-gate * flushed.
3377c478bd9Sstevel@tonic-gate *
3387c478bd9Sstevel@tonic-gate * For flushing a specific physical address, we start at the aliased
3397c478bd9Sstevel@tonic-gate * address and load at set-size stride, wrapping around at 2*ecache-size
3407c478bd9Sstevel@tonic-gate * boundary and skipping the physical address being flushed. It takes
3417c478bd9Sstevel@tonic-gate * 10 loads to guarantee that the physical address has been flushed.
3427c478bd9Sstevel@tonic-gate */
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate#define	HB_ECACHE_FLUSH_CNT	2
3457c478bd9Sstevel@tonic-gate#define	HB_PHYS_FLUSH_CNT	10	/* #loads to flush specific paddr */
3467c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD */
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate/* END CSTYLED */
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate#endif	/* !lint */
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate/*
3537c478bd9Sstevel@tonic-gate * Spitfire MMU and Cache operations.
3547c478bd9Sstevel@tonic-gate */
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate#if defined(lint)
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3597c478bd9Sstevel@tonic-gatevoid
3601e2e7a75Shuahvtag_flushpage(caddr_t vaddr, uint64_t sfmmup)
3617c478bd9Sstevel@tonic-gate{}
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3647c478bd9Sstevel@tonic-gatevoid
3657c478bd9Sstevel@tonic-gatevtag_flushall(void)
3667c478bd9Sstevel@tonic-gate{}
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3697c478bd9Sstevel@tonic-gatevoid
3701e2e7a75Shuahvtag_flushall_uctxs(void)
3717c478bd9Sstevel@tonic-gate{}
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3747c478bd9Sstevel@tonic-gatevoid
3751e2e7a75Shuahvtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup)
3767c478bd9Sstevel@tonic-gate{}
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3797c478bd9Sstevel@tonic-gatevoid
3801e2e7a75Shuahvtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt)
3817c478bd9Sstevel@tonic-gate{}
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3847c478bd9Sstevel@tonic-gatevoid
3857c478bd9Sstevel@tonic-gatevtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2)
3867c478bd9Sstevel@tonic-gate{}
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3897c478bd9Sstevel@tonic-gatevoid
3907c478bd9Sstevel@tonic-gatevac_flushpage(pfn_t pfnum, int vcolor)
3917c478bd9Sstevel@tonic-gate{}
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3947c478bd9Sstevel@tonic-gatevoid
3957c478bd9Sstevel@tonic-gatevac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor)
3967c478bd9Sstevel@tonic-gate{}
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate/*ARGSUSED*/
3997c478bd9Sstevel@tonic-gatevoid
4007c478bd9Sstevel@tonic-gateinit_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2)
4017c478bd9Sstevel@tonic-gate{}
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4047c478bd9Sstevel@tonic-gatevoid
4057c478bd9Sstevel@tonic-gateinit_mondo_nocheck(xcfunc_t *func, uint64_t arg1, uint64_t arg2)
4067c478bd9Sstevel@tonic-gate{}
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4097c478bd9Sstevel@tonic-gatevoid
4107c478bd9Sstevel@tonic-gateflush_instr_mem(caddr_t vaddr, size_t len)
4117c478bd9Sstevel@tonic-gate{}
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4147c478bd9Sstevel@tonic-gatevoid
4157c478bd9Sstevel@tonic-gateflush_ecache(uint64_t physaddr, size_t size, size_t linesize)
4167c478bd9Sstevel@tonic-gate{}
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4197c478bd9Sstevel@tonic-gatevoid
4207c478bd9Sstevel@tonic-gateget_ecache_dtag(uint32_t ecache_idx, uint64_t *ecache_data,
4217c478bd9Sstevel@tonic-gate		uint64_t *ecache_tag, uint64_t *oafsr, uint64_t *acc_afsr)
4227c478bd9Sstevel@tonic-gate{}
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate/* ARGSUSED */
4257c478bd9Sstevel@tonic-gateuint64_t
4267c478bd9Sstevel@tonic-gateget_ecache_tag(uint32_t id, uint64_t *nafsr, uint64_t *acc_afsr)
4277c478bd9Sstevel@tonic-gate{
4287c478bd9Sstevel@tonic-gate	return ((uint64_t)0);
4297c478bd9Sstevel@tonic-gate}
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate/* ARGSUSED */
4327c478bd9Sstevel@tonic-gateuint64_t
4337c478bd9Sstevel@tonic-gatecheck_ecache_line(uint32_t id, uint64_t *acc_afsr)
4347c478bd9Sstevel@tonic-gate{
4357c478bd9Sstevel@tonic-gate	return ((uint64_t)0);
4367c478bd9Sstevel@tonic-gate}
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4397c478bd9Sstevel@tonic-gatevoid
4407c478bd9Sstevel@tonic-gatekdi_flush_idcache(int dcache_size, int dcache_lsize,
4417c478bd9Sstevel@tonic-gate    int icache_size, int icache_lsize)
4427c478bd9Sstevel@tonic-gate{}
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate#else	/* lint */
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate	ENTRY_NP(vtag_flushpage)
4477c478bd9Sstevel@tonic-gate	/*
4487c478bd9Sstevel@tonic-gate	 * flush page from the tlb
4497c478bd9Sstevel@tonic-gate	 *
4507c478bd9Sstevel@tonic-gate	 * %o0 = vaddr
4511e2e7a75Shuah	 * %o1 = sfmmup
4527c478bd9Sstevel@tonic-gate	 */
4537c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o5
4547c478bd9Sstevel@tonic-gate#ifdef DEBUG
4551e2e7a75Shuah	PANIC_IF_INTR_DISABLED_PSTR(%o5, sfdi_label1, %g1)
4567c478bd9Sstevel@tonic-gate#endif /* DEBUG */
4577c478bd9Sstevel@tonic-gate	/*
4587c478bd9Sstevel@tonic-gate	 * disable ints
4597c478bd9Sstevel@tonic-gate	 */
4607c478bd9Sstevel@tonic-gate	andn	%o5, PSTATE_IE, %o4
4617c478bd9Sstevel@tonic-gate	wrpr	%o4, 0, %pstate
4627c478bd9Sstevel@tonic-gate
4637c478bd9Sstevel@tonic-gate	/*
4647c478bd9Sstevel@tonic-gate	 * Then, blow out the tlb
4657c478bd9Sstevel@tonic-gate	 * Interrupts are disabled to prevent the secondary ctx register
4667c478bd9Sstevel@tonic-gate	 * from changing underneath us.
4677c478bd9Sstevel@tonic-gate	 */
4681e2e7a75Shuah	sethi   %hi(ksfmmup), %o3
4691e2e7a75Shuah        ldx     [%o3 + %lo(ksfmmup)], %o3
4701e2e7a75Shuah        cmp     %o3, %o1
4711e2e7a75Shuah        bne,pt   %xcc, 1f			! if not kernel as, go to 1
4727c478bd9Sstevel@tonic-gate	  sethi	%hi(FLUSH_ADDR), %o3
4737c478bd9Sstevel@tonic-gate	/*
4747c478bd9Sstevel@tonic-gate	 * For KCONTEXT demaps use primary. type = page implicitly
4757c478bd9Sstevel@tonic-gate	 */
4767c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]ASI_DTLB_DEMAP	/* dmmu flush for KCONTEXT */
4777c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]ASI_ITLB_DEMAP	/* immu flush for KCONTEXT */
4787c478bd9Sstevel@tonic-gate	flush	%o3
4791e2e7a75Shuah	b	5f
4801e2e7a75Shuah	  nop
4817c478bd9Sstevel@tonic-gate1:
4827c478bd9Sstevel@tonic-gate	/*
4837c478bd9Sstevel@tonic-gate	 * User demap.  We need to set the secondary context properly.
4847c478bd9Sstevel@tonic-gate	 * %o0 = vaddr
4851e2e7a75Shuah	 * %o1 = sfmmup
4867c478bd9Sstevel@tonic-gate	 * %o3 = FLUSH_ADDR
4877c478bd9Sstevel@tonic-gate	 */
4881e2e7a75Shuah	SFMMU_CPU_CNUM(%o1, %g1, %g2)	/* %g1 = sfmmu cnum on this CPU */
4891e2e7a75Shuah
4907c478bd9Sstevel@tonic-gate	set	MMU_SCONTEXT, %o4
4917c478bd9Sstevel@tonic-gate	ldxa	[%o4]ASI_DMMU, %o2		/* rd old ctxnum */
4927c478bd9Sstevel@tonic-gate	or	DEMAP_SECOND | DEMAP_PAGE_TYPE, %o0, %o0
4931e2e7a75Shuah	cmp	%o2, %g1
4941e2e7a75Shuah	be,pt	%icc, 4f
4957c478bd9Sstevel@tonic-gate	  nop
4961e2e7a75Shuah	stxa	%g1, [%o4]ASI_DMMU		/* wr new ctxum */
4977c478bd9Sstevel@tonic-gate4:
4987c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]ASI_DTLB_DEMAP
4997c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]ASI_ITLB_DEMAP
5007c478bd9Sstevel@tonic-gate	flush	%o3
5011e2e7a75Shuah	be,pt	%icc, 5f
5027c478bd9Sstevel@tonic-gate	  nop
5037c478bd9Sstevel@tonic-gate	stxa	%o2, [%o4]ASI_DMMU		/* restore old ctxnum */
5047c478bd9Sstevel@tonic-gate	flush	%o3
5057c478bd9Sstevel@tonic-gate5:
5067c478bd9Sstevel@tonic-gate	retl
5077c478bd9Sstevel@tonic-gate	  wrpr	%g0, %o5, %pstate		/* enable interrupts */
5087c478bd9Sstevel@tonic-gate	SET_SIZE(vtag_flushpage)
5097c478bd9Sstevel@tonic-gate
5107c478bd9Sstevel@tonic-gate        .seg    ".text"
5117c478bd9Sstevel@tonic-gate.flushallmsg:
5127c478bd9Sstevel@tonic-gate        .asciz  "sfmmu_asm: unimplemented flush operation"
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate        ENTRY_NP(vtag_flushall)
5157c478bd9Sstevel@tonic-gate        sethi   %hi(.flushallmsg), %o0
5167c478bd9Sstevel@tonic-gate        call    panic
5177c478bd9Sstevel@tonic-gate          or    %o0, %lo(.flushallmsg), %o0
5187c478bd9Sstevel@tonic-gate        SET_SIZE(vtag_flushall)
5197c478bd9Sstevel@tonic-gate
5201e2e7a75Shuah	ENTRY_NP(vtag_flushall_uctxs)
5211e2e7a75Shuah	/*
5221e2e7a75Shuah	 * flush entire DTLB/ITLB.
5231e2e7a75Shuah	 */
5241e2e7a75Shuah	CPU_INDEX(%g1, %g2)
5251e2e7a75Shuah	mulx	%g1, CPU_NODE_SIZE, %g1
5261e2e7a75Shuah	set	cpunodes, %g2
5271e2e7a75Shuah	add	%g1, %g2, %g1
5281e2e7a75Shuah	lduh	[%g1 + ITLB_SIZE], %g2		! %g2 = # entries in ITLB
5291e2e7a75Shuah	lduh	[%g1 + DTLB_SIZE], %g1		! %g1 = # entries in DTLB
5301e2e7a75Shuah	sub	%g2, 1, %g2			! %g2 = # entries in ITLB - 1
5311e2e7a75Shuah	sub	%g1, 1, %g1			! %g1 = # entries in DTLB - 1
5321e2e7a75Shuah
5331e2e7a75Shuah        !
5341e2e7a75Shuah        ! Flush itlb's
5351e2e7a75Shuah        !
5361e2e7a75Shuah        ITLB_FLUSH_UNLOCKED_UCTXS(I, %g2, %g3, %g4, %o2, %o3, %o4, %o5)
5371e2e7a75Shuah
5381e2e7a75Shuah	!
5391e2e7a75Shuah        ! Flush dtlb's
5401e2e7a75Shuah        !
5411e2e7a75Shuah        DTLB_FLUSH_UNLOCKED_UCTXS(D, %g1, %g3, %g4, %o2, %o3, %o4, %o5)
5421e2e7a75Shuah
5431e2e7a75Shuah	membar  #Sync
5441e2e7a75Shuah	retl
5451e2e7a75Shuah	  nop
5461e2e7a75Shuah
5471e2e7a75Shuah	SET_SIZE(vtag_flushall_uctxs)
5481e2e7a75Shuah
5497c478bd9Sstevel@tonic-gate	ENTRY_NP(vtag_flushpage_tl1)
5507c478bd9Sstevel@tonic-gate	/*
5517c478bd9Sstevel@tonic-gate	 * x-trap to flush page from tlb and tsb
5527c478bd9Sstevel@tonic-gate	 *
5537c478bd9Sstevel@tonic-gate	 * %g1 = vaddr, zero-extended on 32-bit kernel
5541e2e7a75Shuah	 * %g2 = sfmmup
5557c478bd9Sstevel@tonic-gate	 *
5567c478bd9Sstevel@tonic-gate	 * assumes TSBE_TAG = 0
5577c478bd9Sstevel@tonic-gate	 */
5587c478bd9Sstevel@tonic-gate	srln	%g1, MMU_PAGESHIFT, %g1
5597c478bd9Sstevel@tonic-gate	slln	%g1, MMU_PAGESHIFT, %g1			/* g1 = vaddr */
5601e2e7a75Shuah
5611e2e7a75Shuah	SFMMU_CPU_CNUM(%g2, %g3, %g4)   /* %g3 = sfmmu cnum on this CPU */
5621e2e7a75Shuah
5637c478bd9Sstevel@tonic-gate	/* We need to set the secondary context properly. */
5647c478bd9Sstevel@tonic-gate	set	MMU_SCONTEXT, %g4
5657c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_DMMU, %g5		/* rd old ctxnum */
5667c478bd9Sstevel@tonic-gate	or	DEMAP_SECOND | DEMAP_PAGE_TYPE, %g1, %g1
5671e2e7a75Shuah	stxa	%g3, [%g4]ASI_DMMU		/* wr new ctxum */
5687c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_DTLB_DEMAP
5697c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_ITLB_DEMAP
5707c478bd9Sstevel@tonic-gate	stxa	%g5, [%g4]ASI_DMMU		/* restore old ctxnum */
5717c478bd9Sstevel@tonic-gate	membar #Sync
5727c478bd9Sstevel@tonic-gate	retry
5737c478bd9Sstevel@tonic-gate	SET_SIZE(vtag_flushpage_tl1)
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate	ENTRY_NP(vtag_flush_pgcnt_tl1)
5767c478bd9Sstevel@tonic-gate	/*
5777c478bd9Sstevel@tonic-gate	 * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb
5787c478bd9Sstevel@tonic-gate	 *
5797c478bd9Sstevel@tonic-gate	 * %g1 = vaddr, zero-extended on 32-bit kernel
5801e2e7a75Shuah	 * %g2 = <sfmmup58 | pgcnt6>
5817c478bd9Sstevel@tonic-gate	 *
5827c478bd9Sstevel@tonic-gate	 * NOTE: this handler relies on the fact that no
5837c478bd9Sstevel@tonic-gate	 *	interrupts or traps can occur during the loop
5847c478bd9Sstevel@tonic-gate	 *	issuing the TLB_DEMAP operations. It is assumed
5857c478bd9Sstevel@tonic-gate	 *	that interrupts are disabled and this code is
5867c478bd9Sstevel@tonic-gate	 *	fetching from the kernel locked text address.
5877c478bd9Sstevel@tonic-gate	 *
5887c478bd9Sstevel@tonic-gate	 * assumes TSBE_TAG = 0
5897c478bd9Sstevel@tonic-gate	 */
5907c478bd9Sstevel@tonic-gate	srln	%g1, MMU_PAGESHIFT, %g1
5917c478bd9Sstevel@tonic-gate	slln	%g1, MMU_PAGESHIFT, %g1		/* g1 = vaddr */
5927c478bd9Sstevel@tonic-gate	or	DEMAP_SECOND | DEMAP_PAGE_TYPE, %g1, %g1
5931e2e7a75Shuah
5941e2e7a75Shuah	set	SFMMU_PGCNT_MASK, %g4
5951e2e7a75Shuah	and	%g4, %g2, %g3			/* g3 = pgcnt - 1 */
5961e2e7a75Shuah	add	%g3, 1, %g3			/* g3 = pgcnt */
5971e2e7a75Shuah
5981e2e7a75Shuah	andn	%g2, SFMMU_PGCNT_MASK, %g2	/* g2 = sfmmup */
5991e2e7a75Shuah
6001e2e7a75Shuah	SFMMU_CPU_CNUM(%g2, %g5, %g6)   ! %g5 = sfmmu cnum on this CPU
6011e2e7a75Shuah
6027c478bd9Sstevel@tonic-gate	/* We need to set the secondary context properly. */
6037c478bd9Sstevel@tonic-gate	set	MMU_SCONTEXT, %g4
6041e2e7a75Shuah	ldxa	[%g4]ASI_DMMU, %g6		/* read old ctxnum */
6051e2e7a75Shuah	stxa	%g5, [%g4]ASI_DMMU		/* write new ctxum */
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate	set	MMU_PAGESIZE, %g2		/* g2 = pgsize */
6081e2e7a75Shuah	sethi	 %hi(FLUSH_ADDR), %g5
6097c478bd9Sstevel@tonic-gate1:
6107c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_DTLB_DEMAP
6117c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_ITLB_DEMAP
6121e2e7a75Shuah	flush	%g5
6137c478bd9Sstevel@tonic-gate	deccc	%g3				/* decr pgcnt */
6147c478bd9Sstevel@tonic-gate	bnz,pt	%icc,1b
6157c478bd9Sstevel@tonic-gate	  add	%g1, %g2, %g1			/* go to nextpage */
6167c478bd9Sstevel@tonic-gate
6171e2e7a75Shuah	stxa	%g6, [%g4]ASI_DMMU		/* restore old ctxnum */
6187c478bd9Sstevel@tonic-gate	membar #Sync
6197c478bd9Sstevel@tonic-gate	retry
6207c478bd9Sstevel@tonic-gate	SET_SIZE(vtag_flush_pgcnt_tl1)
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate	! Not implemented on US1/US2
6237c478bd9Sstevel@tonic-gate	ENTRY_NP(vtag_flushall_tl1)
6247c478bd9Sstevel@tonic-gate	retry
6257c478bd9Sstevel@tonic-gate	SET_SIZE(vtag_flushall_tl1)
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate/*
6287c478bd9Sstevel@tonic-gate * vac_flushpage(pfnum, color)
6297c478bd9Sstevel@tonic-gate *	Flush 1 8k page of the D-$ with physical page = pfnum
6307c478bd9Sstevel@tonic-gate *	Algorithm:
6317c478bd9Sstevel@tonic-gate *		The spitfire dcache is a 16k direct mapped virtual indexed,
6327c478bd9Sstevel@tonic-gate *		physically tagged cache.  Given the pfnum we read all cache
6337c478bd9Sstevel@tonic-gate *		lines for the corresponding page in the cache (determined by
6347c478bd9Sstevel@tonic-gate *		the color).  Each cache line is compared with
6357c478bd9Sstevel@tonic-gate *		the tag created from the pfnum. If the tags match we flush
6367c478bd9Sstevel@tonic-gate *		the line.
6377c478bd9Sstevel@tonic-gate */
6387c478bd9Sstevel@tonic-gate	.seg	".data"
6397c478bd9Sstevel@tonic-gate	.align	8
6407c478bd9Sstevel@tonic-gate	.global	dflush_type
6417c478bd9Sstevel@tonic-gatedflush_type:
6427c478bd9Sstevel@tonic-gate	.word	FLUSHPAGE_TYPE
6437c478bd9Sstevel@tonic-gate	.seg	".text"
6447c478bd9Sstevel@tonic-gate
6457c478bd9Sstevel@tonic-gate	ENTRY(vac_flushpage)
6467c478bd9Sstevel@tonic-gate	/*
6477c478bd9Sstevel@tonic-gate	 * flush page from the d$
6487c478bd9Sstevel@tonic-gate	 *
6497c478bd9Sstevel@tonic-gate	 * %o0 = pfnum, %o1 = color
6507c478bd9Sstevel@tonic-gate	 */
6517c478bd9Sstevel@tonic-gate	DCACHE_FLUSHPAGE(%o0, %o1, %o2, %o3, %o4)
6527c478bd9Sstevel@tonic-gate	retl
6537c478bd9Sstevel@tonic-gate	nop
6547c478bd9Sstevel@tonic-gate	SET_SIZE(vac_flushpage)
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate	ENTRY_NP(vac_flushpage_tl1)
6577c478bd9Sstevel@tonic-gate	/*
6587c478bd9Sstevel@tonic-gate	 * x-trap to flush page from the d$
6597c478bd9Sstevel@tonic-gate	 *
6607c478bd9Sstevel@tonic-gate	 * %g1 = pfnum, %g2 = color
6617c478bd9Sstevel@tonic-gate	 */
6627c478bd9Sstevel@tonic-gate	DCACHE_FLUSHPAGE(%g1, %g2, %g3, %g4, %g5)
6637c478bd9Sstevel@tonic-gate	retry
6647c478bd9Sstevel@tonic-gate	SET_SIZE(vac_flushpage_tl1)
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate	ENTRY(vac_flushcolor)
6677c478bd9Sstevel@tonic-gate	/*
6687c478bd9Sstevel@tonic-gate	 * %o0 = vcolor
6697c478bd9Sstevel@tonic-gate	 */
6707c478bd9Sstevel@tonic-gate	DCACHE_FLUSHCOLOR(%o0, %o1, %o2)
6717c478bd9Sstevel@tonic-gate	retl
6727c478bd9Sstevel@tonic-gate	  nop
6737c478bd9Sstevel@tonic-gate	SET_SIZE(vac_flushcolor)
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate	ENTRY(vac_flushcolor_tl1)
6767c478bd9Sstevel@tonic-gate	/*
6777c478bd9Sstevel@tonic-gate	 * %g1 = vcolor
6787c478bd9Sstevel@tonic-gate	 */
6797c478bd9Sstevel@tonic-gate	DCACHE_FLUSHCOLOR(%g1, %g2, %g3)
6807c478bd9Sstevel@tonic-gate	retry
6817c478bd9Sstevel@tonic-gate	SET_SIZE(vac_flushcolor_tl1)
6827c478bd9Sstevel@tonic-gate
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate	.global _dispatch_status_busy
6857c478bd9Sstevel@tonic-gate_dispatch_status_busy:
6867c478bd9Sstevel@tonic-gate	.asciz	"ASI_INTR_DISPATCH_STATUS error: busy"
6877c478bd9Sstevel@tonic-gate	.align	4
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate/*
6907c478bd9Sstevel@tonic-gate * Determine whether or not the IDSR is busy.
6917c478bd9Sstevel@tonic-gate * Entry: no arguments
6927c478bd9Sstevel@tonic-gate * Returns: 1 if busy, 0 otherwise
6937c478bd9Sstevel@tonic-gate */
6947c478bd9Sstevel@tonic-gate	ENTRY(idsr_busy)
6957c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %g1
6967c478bd9Sstevel@tonic-gate	clr	%o0
6977c478bd9Sstevel@tonic-gate	btst	IDSR_BUSY, %g1
6987c478bd9Sstevel@tonic-gate	bz,a,pt	%xcc, 1f
6997c478bd9Sstevel@tonic-gate	mov	1, %o0
7007c478bd9Sstevel@tonic-gate1:
7017c478bd9Sstevel@tonic-gate	retl
7027c478bd9Sstevel@tonic-gate	nop
7037c478bd9Sstevel@tonic-gate	SET_SIZE(idsr_busy)
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate/*
7067c478bd9Sstevel@tonic-gate * Setup interrupt dispatch data registers
7077c478bd9Sstevel@tonic-gate * Entry:
7087c478bd9Sstevel@tonic-gate *	%o0 - function or inumber to call
7097c478bd9Sstevel@tonic-gate *	%o1, %o2 - arguments (2 uint64_t's)
7107c478bd9Sstevel@tonic-gate */
7117c478bd9Sstevel@tonic-gate	.seg "text"
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate	ENTRY(init_mondo)
7147c478bd9Sstevel@tonic-gate#ifdef DEBUG
7157c478bd9Sstevel@tonic-gate	!
7167c478bd9Sstevel@tonic-gate	! IDSR should not be busy at the moment
7177c478bd9Sstevel@tonic-gate	!
7187c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %g1
7197c478bd9Sstevel@tonic-gate	btst	IDSR_BUSY, %g1
7207c478bd9Sstevel@tonic-gate	bz,pt	%xcc, 1f
7217c478bd9Sstevel@tonic-gate	nop
7227c478bd9Sstevel@tonic-gate
7237c478bd9Sstevel@tonic-gate	sethi	%hi(_dispatch_status_busy), %o0
7247c478bd9Sstevel@tonic-gate	call	panic
7257c478bd9Sstevel@tonic-gate	or	%o0, %lo(_dispatch_status_busy), %o0
7267c478bd9Sstevel@tonic-gate#endif /* DEBUG */
7277c478bd9Sstevel@tonic-gate
7287c478bd9Sstevel@tonic-gate	ALTENTRY(init_mondo_nocheck)
7297c478bd9Sstevel@tonic-gate	!
7307c478bd9Sstevel@tonic-gate	! interrupt vector dispach data reg 0
7317c478bd9Sstevel@tonic-gate	!
7327c478bd9Sstevel@tonic-gate1:
7337c478bd9Sstevel@tonic-gate	mov	IDDR_0, %g1
7347c478bd9Sstevel@tonic-gate	mov	IDDR_1, %g2
7357c478bd9Sstevel@tonic-gate	mov	IDDR_2, %g3
7367c478bd9Sstevel@tonic-gate	stxa	%o0, [%g1]ASI_INTR_DISPATCH
7377c478bd9Sstevel@tonic-gate
7387c478bd9Sstevel@tonic-gate	!
7397c478bd9Sstevel@tonic-gate	! interrupt vector dispach data reg 1
7407c478bd9Sstevel@tonic-gate	!
7417c478bd9Sstevel@tonic-gate	stxa	%o1, [%g2]ASI_INTR_DISPATCH
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate	!
7447c478bd9Sstevel@tonic-gate	! interrupt vector dispach data reg 2
7457c478bd9Sstevel@tonic-gate	!
7467c478bd9Sstevel@tonic-gate	stxa	%o2, [%g3]ASI_INTR_DISPATCH
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate	retl
7497c478bd9Sstevel@tonic-gate	membar	#Sync			! allowed to be in the delay slot
7507c478bd9Sstevel@tonic-gate	SET_SIZE(init_mondo)
7517c478bd9Sstevel@tonic-gate
7527c478bd9Sstevel@tonic-gate/*
7537c478bd9Sstevel@tonic-gate * Ship mondo to upaid
7547c478bd9Sstevel@tonic-gate */
7557c478bd9Sstevel@tonic-gate	ENTRY_NP(shipit)
7567c478bd9Sstevel@tonic-gate	sll	%o0, IDCR_PID_SHIFT, %g1	! IDCR<18:14> = upa id
7577c478bd9Sstevel@tonic-gate	or	%g1, IDCR_OFFSET, %g1		! IDCR<13:0> = 0x70
7587c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_INTR_DISPATCH	! interrupt vector dispatch
7597c478bd9Sstevel@tonic-gate#if defined(SF_ERRATA_54)
7607c478bd9Sstevel@tonic-gate	membar	#Sync				! store must occur before load
7617c478bd9Sstevel@tonic-gate	mov	0x20, %g3			! UDBH Control Register Read
7627c478bd9Sstevel@tonic-gate	ldxa	[%g3]ASI_SDB_INTR_R, %g0
7637c478bd9Sstevel@tonic-gate#endif
7647c478bd9Sstevel@tonic-gate	retl
7657c478bd9Sstevel@tonic-gate	membar	#Sync
7667c478bd9Sstevel@tonic-gate	SET_SIZE(shipit)
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gate/*
7707c478bd9Sstevel@tonic-gate * flush_instr_mem:
7717c478bd9Sstevel@tonic-gate *	Flush a portion of the I-$ starting at vaddr
7727c478bd9Sstevel@tonic-gate * 	%o0 vaddr
7737c478bd9Sstevel@tonic-gate *	%o1 bytes to be flushed
7747c478bd9Sstevel@tonic-gate */
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate	ENTRY(flush_instr_mem)
7777c478bd9Sstevel@tonic-gate	membar	#StoreStore				! Ensure the stores
7787c478bd9Sstevel@tonic-gate							! are globally visible
7797c478bd9Sstevel@tonic-gate1:
7807c478bd9Sstevel@tonic-gate	flush	%o0
7817c478bd9Sstevel@tonic-gate	subcc	%o1, ICACHE_FLUSHSZ, %o1		! bytes = bytes-0x20
7827c478bd9Sstevel@tonic-gate	bgu,pt	%ncc, 1b
7837c478bd9Sstevel@tonic-gate	add	%o0, ICACHE_FLUSHSZ, %o0		! vaddr = vaddr+0x20
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate	retl
7867c478bd9Sstevel@tonic-gate	nop
7877c478bd9Sstevel@tonic-gate	SET_SIZE(flush_instr_mem)
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate/*
7907c478bd9Sstevel@tonic-gate * flush_ecache:
7917c478bd9Sstevel@tonic-gate * Flush the entire e$ using displacement flush by reading through a
7927c478bd9Sstevel@tonic-gate * physically contiguous area. We use mmu bypass asi (ASI_MEM) while
7937c478bd9Sstevel@tonic-gate * reading this physical address range so that data doesn't go to d$.
7947c478bd9Sstevel@tonic-gate * incoming arguments:
7957c478bd9Sstevel@tonic-gate *	%o0 - 64 bit physical address
7967c478bd9Sstevel@tonic-gate *	%o1 - size of address range to read
7977c478bd9Sstevel@tonic-gate *	%o2 - ecache linesize
7987c478bd9Sstevel@tonic-gate */
7997c478bd9Sstevel@tonic-gate	ENTRY(flush_ecache)
8007c478bd9Sstevel@tonic-gate#ifndef HUMMINGBIRD
8017c478bd9Sstevel@tonic-gate	b	2f
8027c478bd9Sstevel@tonic-gate	  nop
8037c478bd9Sstevel@tonic-gate1:
8047c478bd9Sstevel@tonic-gate	ldxa	[%o0 + %o1]ASI_MEM, %g0	! start reading from physaddr + size
8057c478bd9Sstevel@tonic-gate2:
8067c478bd9Sstevel@tonic-gate	subcc	%o1, %o2, %o1
8077c478bd9Sstevel@tonic-gate	bcc,a,pt %ncc, 1b
8087c478bd9Sstevel@tonic-gate	  nop
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate#else /* HUMMINGBIRD */
8117c478bd9Sstevel@tonic-gate	/*
8127c478bd9Sstevel@tonic-gate	 * UltraSPARC-IIe processor supports both 4-way set associative
8137c478bd9Sstevel@tonic-gate	 * and direct map E$. For performance reasons, we flush E$ by
8147c478bd9Sstevel@tonic-gate	 * placing it in direct map mode for data load/store and restore
8157c478bd9Sstevel@tonic-gate	 * the state after we are done flushing it. It takes 2 iterations
8167c478bd9Sstevel@tonic-gate	 * to guarantee that the entire ecache has been flushed.
8177c478bd9Sstevel@tonic-gate	 *
8187c478bd9Sstevel@tonic-gate	 * Keep the interrupts disabled while flushing E$ in this manner.
8197c478bd9Sstevel@tonic-gate	 */
8207c478bd9Sstevel@tonic-gate	rdpr	%pstate, %g4		! current pstate (restored later)
8217c478bd9Sstevel@tonic-gate	andn	%g4, PSTATE_IE, %g5
8227c478bd9Sstevel@tonic-gate	wrpr	%g0, %g5, %pstate	! disable interrupts
8237c478bd9Sstevel@tonic-gate
8247c478bd9Sstevel@tonic-gate	! Place E$ in direct map mode for data access
8257c478bd9Sstevel@tonic-gate	or	%g0, 1, %g5
8267c478bd9Sstevel@tonic-gate	sllx	%g5, HB_UPA_DMAP_DATA_BIT, %g5
8277c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_UPA_CONFIG, %g1 ! current UPA config (restored later)
8287c478bd9Sstevel@tonic-gate	or	%g1, %g5, %g5
8297c478bd9Sstevel@tonic-gate	membar	#Sync
8307c478bd9Sstevel@tonic-gate	stxa	%g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access
8317c478bd9Sstevel@tonic-gate	membar	#Sync
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate	! flush entire ecache HB_ECACHE_FLUSH_CNT times
8347c478bd9Sstevel@tonic-gate	mov	HB_ECACHE_FLUSH_CNT-1, %g5
8357c478bd9Sstevel@tonic-gate2:
8367c478bd9Sstevel@tonic-gate	sub	%o1, %o2, %g3		! start from last entry
8377c478bd9Sstevel@tonic-gate1:
8387c478bd9Sstevel@tonic-gate	ldxa	[%o0 + %g3]ASI_MEM, %g0	! start reading from physaddr + size
8397c478bd9Sstevel@tonic-gate	subcc	%g3, %o2, %g3
8407c478bd9Sstevel@tonic-gate	bgeu,a,pt %ncc, 1b
8417c478bd9Sstevel@tonic-gate	  nop
8427c478bd9Sstevel@tonic-gate	brgz,a,pt %g5, 2b
8437c478bd9Sstevel@tonic-gate	  dec	%g5
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate	membar	#Sync
8467c478bd9Sstevel@tonic-gate	stxa	%g1, [%g0]ASI_UPA_CONFIG ! restore UPA config reg
8477c478bd9Sstevel@tonic-gate	membar	#Sync
8487c478bd9Sstevel@tonic-gate	wrpr	%g0, %g4, %pstate	! restore earlier pstate
8497c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD */
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate	retl
8527c478bd9Sstevel@tonic-gate	nop
8537c478bd9Sstevel@tonic-gate	SET_SIZE(flush_ecache)
8547c478bd9Sstevel@tonic-gate
8557c478bd9Sstevel@tonic-gate/*
8567c478bd9Sstevel@tonic-gate * void kdi_flush_idcache(int dcache_size, int dcache_linesize,
8577c478bd9Sstevel@tonic-gate *			int icache_size, int icache_linesize)
8587c478bd9Sstevel@tonic-gate */
8597c478bd9Sstevel@tonic-gate	ENTRY(kdi_flush_idcache)
8607c478bd9Sstevel@tonic-gate	DCACHE_FLUSHALL(%o0, %o1, %g1)
8617c478bd9Sstevel@tonic-gate	ICACHE_FLUSHALL(%o2, %o3, %g1)
8627c478bd9Sstevel@tonic-gate	membar	#Sync
8637c478bd9Sstevel@tonic-gate	retl
8647c478bd9Sstevel@tonic-gate	nop
8657c478bd9Sstevel@tonic-gate	SET_SIZE(kdi_flush_idcache)
8667c478bd9Sstevel@tonic-gate
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate/*
8697c478bd9Sstevel@tonic-gate * void get_ecache_dtag(uint32_t ecache_idx, uint64_t *data, uint64_t *tag,
8707c478bd9Sstevel@tonic-gate * 			uint64_t *oafsr, uint64_t *acc_afsr)
8717c478bd9Sstevel@tonic-gate *
8727c478bd9Sstevel@tonic-gate * Get ecache data and tag.  The ecache_idx argument is assumed to be aligned
8737c478bd9Sstevel@tonic-gate * on a 64-byte boundary.  The corresponding AFSR value is also read for each
8747c478bd9Sstevel@tonic-gate * 8 byte ecache data obtained. The ecache data is assumed to be a pointer
8757c478bd9Sstevel@tonic-gate * to an array of 16 uint64_t's (e$data & afsr value).  The action to read the
8767c478bd9Sstevel@tonic-gate * data and tag should be atomic to make sense.  We will be executing at PIL15
8777c478bd9Sstevel@tonic-gate * and will disable IE, so nothing can occur between the two reads.  We also
8787c478bd9Sstevel@tonic-gate * assume that the execution of this code does not interfere with what we are
8797c478bd9Sstevel@tonic-gate * reading - not really possible, but we'll live with it for now.
8807c478bd9Sstevel@tonic-gate * We also pass the old AFSR value before clearing it, and caller will take
8817c478bd9Sstevel@tonic-gate * appropriate actions if the important bits are non-zero.
8827c478bd9Sstevel@tonic-gate *
8837c478bd9Sstevel@tonic-gate * If the caller wishes to track the AFSR in cases where the CP bit is
8847c478bd9Sstevel@tonic-gate * set, an address should be passed in for acc_afsr.  Otherwise, this
8857c478bd9Sstevel@tonic-gate * argument may be null.
8867c478bd9Sstevel@tonic-gate *
8877c478bd9Sstevel@tonic-gate * Register Usage:
8887c478bd9Sstevel@tonic-gate * i0: In: 32-bit e$ index
8897c478bd9Sstevel@tonic-gate * i1: In: addr of e$ data
8907c478bd9Sstevel@tonic-gate * i2: In: addr of e$ tag
8917c478bd9Sstevel@tonic-gate * i3: In: addr of old afsr
8927c478bd9Sstevel@tonic-gate * i4: In: addr of accumulated afsr - may be null
8937c478bd9Sstevel@tonic-gate */
8947c478bd9Sstevel@tonic-gate	ENTRY(get_ecache_dtag)
8957c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp
8967c478bd9Sstevel@tonic-gate	or	%g0, 1, %l4
8977c478bd9Sstevel@tonic-gate	sllx	%l4, 39, %l4	! set bit 39 for e$ data access
8987c478bd9Sstevel@tonic-gate	or	%i0, %l4, %g6	! %g6 = e$ addr for data read
8997c478bd9Sstevel@tonic-gate	sllx	%l4, 1, %l4	! set bit 40 for e$ tag access
9007c478bd9Sstevel@tonic-gate	or	%i0, %l4, %l4	! %l4 = e$ addr for tag read
9017c478bd9Sstevel@tonic-gate
9027c478bd9Sstevel@tonic-gate	rdpr    %pstate, %i5
9037c478bd9Sstevel@tonic-gate	andn    %i5, PSTATE_IE | PSTATE_AM, %i0
9047c478bd9Sstevel@tonic-gate	wrpr    %i0, %g0, %pstate       ! clear IE, AM bits
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate	ldxa    [%g0]ASI_ESTATE_ERR, %g1
9077c478bd9Sstevel@tonic-gate	stxa    %g0, [%g0]ASI_ESTATE_ERR        ! disable errors
9087c478bd9Sstevel@tonic-gate	membar  #Sync
9097c478bd9Sstevel@tonic-gate
9107c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %i0      ! grab the old-afsr before tag read
9117c478bd9Sstevel@tonic-gate	stx     %i0, [%i3]		! write back the old-afsr
9127c478bd9Sstevel@tonic-gate
9137c478bd9Sstevel@tonic-gate	ldxa    [%l4]ASI_EC_R, %g0      ! read tag into E$ tag reg
9147c478bd9Sstevel@tonic-gate	ldxa    [%g0]ASI_EC_DIAG, %i0   ! read tag from E$ tag reg
9157c478bd9Sstevel@tonic-gate	stx     %i0, [%i2]              ! write back tag result
9167c478bd9Sstevel@tonic-gate
9177c478bd9Sstevel@tonic-gate	clr	%i2			! loop count
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate	brz	%i4, 1f			! acc_afsr == NULL?
9207c478bd9Sstevel@tonic-gate	  ldxa	[%g0]ASI_AFSR, %i0      ! grab the old-afsr before clearing
9217c478bd9Sstevel@tonic-gate	srlx	%i0, P_AFSR_CP_SHIFT, %l0
9227c478bd9Sstevel@tonic-gate	btst	1, %l0
9237c478bd9Sstevel@tonic-gate	bz	1f
9247c478bd9Sstevel@tonic-gate	  nop
9257c478bd9Sstevel@tonic-gate	ldx	[%i4], %g4
9267c478bd9Sstevel@tonic-gate	or	%g4, %i0, %g4		! aggregate AFSR in cpu private
9277c478bd9Sstevel@tonic-gate	stx	%g4, [%i4]
9287c478bd9Sstevel@tonic-gate1:
9297c478bd9Sstevel@tonic-gate	stxa    %i0, [%g0]ASI_AFSR	! clear AFSR
9307c478bd9Sstevel@tonic-gate	membar  #Sync
9317c478bd9Sstevel@tonic-gate	ldxa    [%g6]ASI_EC_R, %i0      ! read the 8byte E$data
9327c478bd9Sstevel@tonic-gate	stx     %i0, [%i1]              ! save the E$data
9337c478bd9Sstevel@tonic-gate	add     %g6, 8, %g6
9347c478bd9Sstevel@tonic-gate	add     %i1, 8, %i1
9357c478bd9Sstevel@tonic-gate	ldxa    [%g0]ASI_AFSR, %i0      ! read AFSR for this 16byte read
9367c478bd9Sstevel@tonic-gate	srlx	%i0, P_AFSR_CP_SHIFT, %l0
9377c478bd9Sstevel@tonic-gate	btst	1, %l0
9387c478bd9Sstevel@tonic-gate	bz	2f
9397c478bd9Sstevel@tonic-gate	  stx     %i0, [%i1]		! save the AFSR
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate	brz	%i4, 2f			! acc_afsr == NULL?
9427c478bd9Sstevel@tonic-gate	  nop
9437c478bd9Sstevel@tonic-gate	ldx	[%i4], %g4
9447c478bd9Sstevel@tonic-gate	or	%g4, %i0, %g4		! aggregate AFSR in cpu private
9457c478bd9Sstevel@tonic-gate	stx	%g4, [%i4]
9467c478bd9Sstevel@tonic-gate2:
9477c478bd9Sstevel@tonic-gate	add     %i2, 8, %i2
9487c478bd9Sstevel@tonic-gate	cmp     %i2, 64
9497c478bd9Sstevel@tonic-gate	bl,a    1b
9507c478bd9Sstevel@tonic-gate	  add     %i1, 8, %i1
9517c478bd9Sstevel@tonic-gate	stxa    %i0, [%g0]ASI_AFSR              ! clear AFSR
9527c478bd9Sstevel@tonic-gate	membar  #Sync
9537c478bd9Sstevel@tonic-gate	stxa    %g1, [%g0]ASI_ESTATE_ERR        ! restore error enable
9547c478bd9Sstevel@tonic-gate	membar  #Sync
9557c478bd9Sstevel@tonic-gate	wrpr    %g0, %i5, %pstate
9567c478bd9Sstevel@tonic-gate	ret
9577c478bd9Sstevel@tonic-gate	  restore
9587c478bd9Sstevel@tonic-gate	SET_SIZE(get_ecache_dtag)
9597c478bd9Sstevel@tonic-gate#endif /* lint */
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate#if defined(lint)
9627c478bd9Sstevel@tonic-gate/*
9637c478bd9Sstevel@tonic-gate * The ce_err function handles trap type 0x63 (corrected_ECC_error) at tl=0.
9647c478bd9Sstevel@tonic-gate * Steps: 1. GET AFSR  2. Get AFAR <40:4> 3. Get datapath error status
9657c478bd9Sstevel@tonic-gate *	  4. Clear datapath error bit(s) 5. Clear AFSR error bit
9667c478bd9Sstevel@tonic-gate *	  6. package data in %g2 and %g3 7. call cpu_ce_error vis sys_trap
9677c478bd9Sstevel@tonic-gate * %g2: [ 52:43 UDB lower | 42:33 UDB upper | 32:0 afsr ] - arg #3/arg #1
9687c478bd9Sstevel@tonic-gate * %g3: [ 40:4 afar ] - sys_trap->have_win: arg #4/arg #2
9697c478bd9Sstevel@tonic-gate */
9707c478bd9Sstevel@tonic-gatevoid
9717c478bd9Sstevel@tonic-gatece_err(void)
9727c478bd9Sstevel@tonic-gate{}
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gatevoid
9757c478bd9Sstevel@tonic-gatece_err_tl1(void)
9767c478bd9Sstevel@tonic-gate{}
9777c478bd9Sstevel@tonic-gate
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate/*
9807c478bd9Sstevel@tonic-gate * The async_err function handles trap types 0x0A (instruction_access_error)
9817c478bd9Sstevel@tonic-gate * and 0x32 (data_access_error) at TL = 0 and TL > 0.  When we branch here,
9827c478bd9Sstevel@tonic-gate * %g5 will have the trap type (with 0x200 set if we're at TL > 0).
9837c478bd9Sstevel@tonic-gate *
9847c478bd9Sstevel@tonic-gate * Steps: 1. Get AFSR 2. Get AFAR <40:4> 3. If not UE error skip UDP registers.
9857c478bd9Sstevel@tonic-gate *	  4. Else get and clear datapath error bit(s) 4. Clear AFSR error bits
9867c478bd9Sstevel@tonic-gate *	  6. package data in %g2 and %g3 7. disable all cpu errors, because
9877c478bd9Sstevel@tonic-gate *	  trap is likely to be fatal 8. call cpu_async_error vis sys_trap
9887c478bd9Sstevel@tonic-gate *
9897c478bd9Sstevel@tonic-gate * %g3: [ 63:53 tt | 52:43 UDB_L | 42:33 UDB_U | 32:0 afsr ] - arg #3/arg #1
9907c478bd9Sstevel@tonic-gate * %g2: [ 40:4 afar ] - sys_trap->have_win: arg #4/arg #2
9917c478bd9Sstevel@tonic-gate */
9927c478bd9Sstevel@tonic-gatevoid
9937c478bd9Sstevel@tonic-gateasync_err(void)
9947c478bd9Sstevel@tonic-gate{}
9957c478bd9Sstevel@tonic-gate
9967c478bd9Sstevel@tonic-gate/*
9977c478bd9Sstevel@tonic-gate * The clr_datapath function clears any error bits set in the UDB regs.
9987c478bd9Sstevel@tonic-gate */
9997c478bd9Sstevel@tonic-gatevoid
10007c478bd9Sstevel@tonic-gateclr_datapath(void)
10017c478bd9Sstevel@tonic-gate{}
10027c478bd9Sstevel@tonic-gate
10037c478bd9Sstevel@tonic-gate/*
10047c478bd9Sstevel@tonic-gate * The get_udb_errors() function gets the current value of the
10057c478bd9Sstevel@tonic-gate * Datapath Error Registers.
10067c478bd9Sstevel@tonic-gate */
10077c478bd9Sstevel@tonic-gate/*ARGSUSED*/
10087c478bd9Sstevel@tonic-gatevoid
10097c478bd9Sstevel@tonic-gateget_udb_errors(uint64_t *udbh, uint64_t *udbl)
10107c478bd9Sstevel@tonic-gate{
10117c478bd9Sstevel@tonic-gate	*udbh = 0;
10127c478bd9Sstevel@tonic-gate	*udbl = 0;
10137c478bd9Sstevel@tonic-gate}
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate#else 	/* lint */
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate	ENTRY_NP(ce_err)
10187c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %g3	! save afsr in g3
10197c478bd9Sstevel@tonic-gate
10207c478bd9Sstevel@tonic-gate	!
10217c478bd9Sstevel@tonic-gate	! Check for a UE... From Kevin.Normoyle:
10227c478bd9Sstevel@tonic-gate	! We try to switch to the trap for the UE, but since that's
10237c478bd9Sstevel@tonic-gate	! a hardware pipeline, we might get to the CE trap before we
10247c478bd9Sstevel@tonic-gate	! can switch. The UDB and AFSR registers will have both the
10257c478bd9Sstevel@tonic-gate	! UE and CE bits set but the UDB syndrome and the AFAR will be
10267c478bd9Sstevel@tonic-gate	! for the UE.
10277c478bd9Sstevel@tonic-gate	!
10287c478bd9Sstevel@tonic-gate	or	%g0, 1, %g1		! put 1 in g1
10297c478bd9Sstevel@tonic-gate	sllx	%g1, 21, %g1		! shift left to <21> afsr UE
10307c478bd9Sstevel@tonic-gate	andcc	%g1, %g3, %g0		! check for UE in afsr
10317c478bd9Sstevel@tonic-gate	bnz	async_err		! handle the UE, not the CE
10327c478bd9Sstevel@tonic-gate	  or	%g0, 0x63, %g5		! pass along the CE ttype
10337c478bd9Sstevel@tonic-gate	!
10347c478bd9Sstevel@tonic-gate	! Disable further CE traps to avoid recursion (stack overflow)
10357c478bd9Sstevel@tonic-gate	! and staying above XCALL_PIL for extended periods.
10367c478bd9Sstevel@tonic-gate	!
10377c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g2
10387c478bd9Sstevel@tonic-gate	andn	%g2, 0x1, %g2		! clear bit 0 - CEEN
10397c478bd9Sstevel@tonic-gate	stxa	%g2, [%g0]ASI_ESTATE_ERR
10407c478bd9Sstevel@tonic-gate	membar	#Sync			! required
10417c478bd9Sstevel@tonic-gate	!
10427c478bd9Sstevel@tonic-gate	! handle the CE
10437c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFAR, %g2	! save afar in g2
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate	set	P_DER_H, %g4		! put P_DER_H in g4
10467c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_SDB_INTR_R, %g5 ! read sdb upper half into g5
10477c478bd9Sstevel@tonic-gate	or	%g0, 1, %g6		! put 1 in g6
10487c478bd9Sstevel@tonic-gate	sllx	%g6, 8, %g6		! shift g6 to <8> sdb CE
10497c478bd9Sstevel@tonic-gate	andcc	%g5, %g6, %g1		! check for CE in upper half
10507c478bd9Sstevel@tonic-gate	sllx	%g5, 33, %g5		! shift upper bits to <42:33>
10517c478bd9Sstevel@tonic-gate	or	%g3, %g5, %g3		! or with afsr bits
10527c478bd9Sstevel@tonic-gate	bz,a	1f			! no error, goto 1f
10537c478bd9Sstevel@tonic-gate	  nop
10547c478bd9Sstevel@tonic-gate	stxa	%g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg error bit
10557c478bd9Sstevel@tonic-gate	membar	#Sync			! membar sync required
10567c478bd9Sstevel@tonic-gate1:
10577c478bd9Sstevel@tonic-gate	set	P_DER_L, %g4		! put P_DER_L in g4
10587c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_SDB_INTR_R, %g5 ! read sdb lower half into g6
10597c478bd9Sstevel@tonic-gate	andcc	%g5, %g6, %g1		! check for CE in lower half
10607c478bd9Sstevel@tonic-gate	sllx	%g5, 43, %g5		! shift upper bits to <52:43>
10617c478bd9Sstevel@tonic-gate	or	%g3, %g5, %g3		! or with afsr bits
10627c478bd9Sstevel@tonic-gate	bz,a	2f			! no error, goto 2f
10637c478bd9Sstevel@tonic-gate	  nop
10647c478bd9Sstevel@tonic-gate	stxa	%g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg error bit
10657c478bd9Sstevel@tonic-gate	membar	#Sync			! membar sync required
10667c478bd9Sstevel@tonic-gate2:
10677c478bd9Sstevel@tonic-gate	or	%g0, 1, %g4		! put 1 in g4
10687c478bd9Sstevel@tonic-gate	sllx	%g4, 20, %g4		! shift left to <20> afsr CE
10697c478bd9Sstevel@tonic-gate	stxa	%g4, [%g0]ASI_AFSR	! use g4 to clear afsr CE error
10707c478bd9Sstevel@tonic-gate	membar	#Sync			! membar sync required
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate	set	cpu_ce_error, %g1	! put *cpu_ce_error() in g1
10737c478bd9Sstevel@tonic-gate	rdpr	%pil, %g6		! read pil into %g6
10747c478bd9Sstevel@tonic-gate	subcc	%g6, PIL_15, %g0
10757c478bd9Sstevel@tonic-gate	  movneg	%icc, PIL_14, %g4 ! run at pil 14 unless already at 15
10767c478bd9Sstevel@tonic-gate	sethi	%hi(sys_trap), %g5
10777c478bd9Sstevel@tonic-gate	jmp	%g5 + %lo(sys_trap)	! goto sys_trap
10787c478bd9Sstevel@tonic-gate	  movge	%icc, PIL_15, %g4	! already at pil 15
10797c478bd9Sstevel@tonic-gate	SET_SIZE(ce_err)
10807c478bd9Sstevel@tonic-gate
10817c478bd9Sstevel@tonic-gate	ENTRY_NP(ce_err_tl1)
10827c478bd9Sstevel@tonic-gate#ifndef	TRAPTRACE
10837c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %g7
10847c478bd9Sstevel@tonic-gate	stxa	%g7, [%g0]ASI_AFSR
10857c478bd9Sstevel@tonic-gate	membar	#Sync
10867c478bd9Sstevel@tonic-gate	retry
10877c478bd9Sstevel@tonic-gate#else
10887c478bd9Sstevel@tonic-gate	set	ce_trap_tl1, %g1
10897c478bd9Sstevel@tonic-gate	sethi	%hi(dis_err_panic1), %g4
10907c478bd9Sstevel@tonic-gate	jmp	%g4 + %lo(dis_err_panic1)
10917c478bd9Sstevel@tonic-gate	nop
10927c478bd9Sstevel@tonic-gate#endif
10937c478bd9Sstevel@tonic-gate	SET_SIZE(ce_err_tl1)
10947c478bd9Sstevel@tonic-gate
10957c478bd9Sstevel@tonic-gate#ifdef	TRAPTRACE
10967c478bd9Sstevel@tonic-gate.celevel1msg:
10977c478bd9Sstevel@tonic-gate	.asciz	"Softerror with trap tracing at tl1: AFAR 0x%08x.%08x AFSR 0x%08x.%08x";
10987c478bd9Sstevel@tonic-gate
10997c478bd9Sstevel@tonic-gate	ENTRY_NP(ce_trap_tl1)
11007c478bd9Sstevel@tonic-gate	! upper 32 bits of AFSR already in o3
11017c478bd9Sstevel@tonic-gate	mov	%o4, %o0		! save AFAR upper 32 bits
11027c478bd9Sstevel@tonic-gate	mov	%o2, %o4		! lower 32 bits of AFSR
11037c478bd9Sstevel@tonic-gate	mov	%o1, %o2		! lower 32 bits of AFAR
11047c478bd9Sstevel@tonic-gate	mov	%o0, %o1		! upper 32 bits of AFAR
11057c478bd9Sstevel@tonic-gate	set	.celevel1msg, %o0
11067c478bd9Sstevel@tonic-gate	call	panic
11077c478bd9Sstevel@tonic-gate	nop
11087c478bd9Sstevel@tonic-gate	SET_SIZE(ce_trap_tl1)
11097c478bd9Sstevel@tonic-gate#endif
11107c478bd9Sstevel@tonic-gate
11117c478bd9Sstevel@tonic-gate	!
11127c478bd9Sstevel@tonic-gate	! async_err is the assembly glue code to get us from the actual trap
11137c478bd9Sstevel@tonic-gate	! into the CPU module's C error handler.  Note that we also branch
11147c478bd9Sstevel@tonic-gate	! here from ce_err() above.
11157c478bd9Sstevel@tonic-gate	!
11167c478bd9Sstevel@tonic-gate	ENTRY_NP(async_err)
11177c478bd9Sstevel@tonic-gate	stxa	%g0, [%g0]ASI_ESTATE_ERR ! disable ecc and other cpu errors
11187c478bd9Sstevel@tonic-gate	membar	#Sync			! membar sync required
11197c478bd9Sstevel@tonic-gate
11207c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %g3	! save afsr in g3
11217c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFAR, %g2	! save afar in g2
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate	sllx	%g5, 53, %g5		! move ttype to <63:53>
11247c478bd9Sstevel@tonic-gate	or	%g3, %g5, %g3		! or to afsr in g3
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate	or	%g0, 1, %g1		! put 1 in g1
11277c478bd9Sstevel@tonic-gate	sllx	%g1, 21, %g1		! shift left to <21> afsr UE
11287c478bd9Sstevel@tonic-gate	andcc	%g1, %g3, %g0		! check for UE in afsr
11297c478bd9Sstevel@tonic-gate	bz,a,pn %icc, 2f		! if !UE skip sdb read/clear
11307c478bd9Sstevel@tonic-gate	  nop
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate	set	P_DER_H, %g4		! put P_DER_H in g4
11337c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_SDB_INTR_R, %g5 ! read sdb upper half into 56
11347c478bd9Sstevel@tonic-gate	or	%g0, 1, %g6		! put 1 in g6
11357c478bd9Sstevel@tonic-gate	sllx	%g6, 9, %g6		! shift g6 to <9> sdb UE
11367c478bd9Sstevel@tonic-gate	andcc	%g5, %g6, %g1		! check for UE in upper half
11377c478bd9Sstevel@tonic-gate	sllx	%g5, 33, %g5		! shift upper bits to <42:33>
11387c478bd9Sstevel@tonic-gate	or	%g3, %g5, %g3		! or with afsr bits
11397c478bd9Sstevel@tonic-gate	bz,a	1f			! no error, goto 1f
11407c478bd9Sstevel@tonic-gate	  nop
11417c478bd9Sstevel@tonic-gate	stxa	%g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg UE error bit
11427c478bd9Sstevel@tonic-gate	membar	#Sync			! membar sync required
11437c478bd9Sstevel@tonic-gate1:
11447c478bd9Sstevel@tonic-gate	set	P_DER_L, %g4		! put P_DER_L in g4
11457c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_SDB_INTR_R, %g5 ! read sdb lower half into g5
11467c478bd9Sstevel@tonic-gate	andcc	%g5, %g6, %g1		! check for UE in lower half
11477c478bd9Sstevel@tonic-gate	sllx	%g5, 43, %g5		! shift upper bits to <52:43>
11487c478bd9Sstevel@tonic-gate	or	%g3, %g5, %g3		! or with afsr bits
11497c478bd9Sstevel@tonic-gate	bz,a	2f			! no error, goto 2f
11507c478bd9Sstevel@tonic-gate	  nop
11517c478bd9Sstevel@tonic-gate	stxa	%g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg UE error bit
11527c478bd9Sstevel@tonic-gate	membar	#Sync			! membar sync required
11537c478bd9Sstevel@tonic-gate2:
11547c478bd9Sstevel@tonic-gate	stxa	%g3, [%g0]ASI_AFSR	! clear all the sticky bits
11557c478bd9Sstevel@tonic-gate	membar	#Sync			! membar sync required
11567c478bd9Sstevel@tonic-gate
1157*2dd3029aSjimand	RESET_USER_RTT_REGS(%g4, %g5, async_err_resetskip)
1158*2dd3029aSjimandasync_err_resetskip:
11598f230a59Sbs21162
11607c478bd9Sstevel@tonic-gate	set	cpu_async_error, %g1	! put cpu_async_error in g1
11617c478bd9Sstevel@tonic-gate	sethi	%hi(sys_trap), %g5
11627c478bd9Sstevel@tonic-gate	jmp	%g5 + %lo(sys_trap)	! goto sys_trap
11637c478bd9Sstevel@tonic-gate	  or	%g0, PIL_15, %g4	! run at pil 15
11647c478bd9Sstevel@tonic-gate	SET_SIZE(async_err)
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate	ENTRY_NP(dis_err_panic1)
11677c478bd9Sstevel@tonic-gate	stxa	%g0, [%g0]ASI_ESTATE_ERR ! disable all error traps
11687c478bd9Sstevel@tonic-gate	membar	#Sync
11697c478bd9Sstevel@tonic-gate	! save destination routine is in g1
11707c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFAR, %g2	! read afar
11717c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %g3	! read afsr
11727c478bd9Sstevel@tonic-gate	set	P_DER_H, %g4		! put P_DER_H in g4
11737c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_SDB_INTR_R, %g5 ! read sdb upper half into g5
11747c478bd9Sstevel@tonic-gate	sllx	%g5, 33, %g5		! shift upper bits to <42:33>
11757c478bd9Sstevel@tonic-gate	or	%g3, %g5, %g3		! or with afsr bits
11767c478bd9Sstevel@tonic-gate	set	P_DER_L, %g4		! put P_DER_L in g4
11777c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_SDB_INTR_R, %g5 ! read sdb lower half into g5
11787c478bd9Sstevel@tonic-gate	sllx	%g5, 43, %g5		! shift upper bits to <52:43>
11797c478bd9Sstevel@tonic-gate	or	%g3, %g5, %g3		! or with afsr bits
11808f230a59Sbs21162
1181*2dd3029aSjimand	RESET_USER_RTT_REGS(%g4, %g5, dis_err_panic1_resetskip)
1182*2dd3029aSjimanddis_err_panic1_resetskip:
11838f230a59Sbs21162
11847c478bd9Sstevel@tonic-gate	sethi	%hi(sys_trap), %g5
11857c478bd9Sstevel@tonic-gate	jmp	%g5 + %lo(sys_trap)	! goto sys_trap
11867c478bd9Sstevel@tonic-gate	  sub	%g0, 1, %g4
11877c478bd9Sstevel@tonic-gate	SET_SIZE(dis_err_panic1)
11887c478bd9Sstevel@tonic-gate
11897c478bd9Sstevel@tonic-gate	ENTRY(clr_datapath)
11907c478bd9Sstevel@tonic-gate	set	P_DER_H, %o4			! put P_DER_H in o4
11917c478bd9Sstevel@tonic-gate	ldxa	[%o4]ASI_SDB_INTR_R, %o5	! read sdb upper half into o3
11927c478bd9Sstevel@tonic-gate	or	%g0, 0x3, %o2			! put 0x3 in o2
11937c478bd9Sstevel@tonic-gate	sllx	%o2, 8, %o2			! shift o2 to <9:8> sdb
11947c478bd9Sstevel@tonic-gate	andcc	%o5, %o2, %o1			! check for UE,CE in upper half
11957c478bd9Sstevel@tonic-gate	bz,a	1f				! no error, goto 1f
11967c478bd9Sstevel@tonic-gate	  nop
11977c478bd9Sstevel@tonic-gate	stxa	%o1, [%o4]ASI_SDB_INTR_W	! clear sdb reg UE,CE error bits
11987c478bd9Sstevel@tonic-gate	membar	#Sync				! membar sync required
11997c478bd9Sstevel@tonic-gate1:
12007c478bd9Sstevel@tonic-gate	set	P_DER_L, %o4			! put P_DER_L in o4
12017c478bd9Sstevel@tonic-gate	ldxa	[%o4]ASI_SDB_INTR_R, %o5	! read sdb lower half into o5
12027c478bd9Sstevel@tonic-gate	andcc	%o5, %o2, %o1			! check for UE,CE in lower half
12037c478bd9Sstevel@tonic-gate	bz,a	2f				! no error, goto 2f
12047c478bd9Sstevel@tonic-gate	  nop
12057c478bd9Sstevel@tonic-gate	stxa	%o1, [%o4]ASI_SDB_INTR_W	! clear sdb reg UE,CE error bits
12067c478bd9Sstevel@tonic-gate	membar	#Sync
12077c478bd9Sstevel@tonic-gate2:
12087c478bd9Sstevel@tonic-gate	retl
12097c478bd9Sstevel@tonic-gate	  nop
12107c478bd9Sstevel@tonic-gate	SET_SIZE(clr_datapath)
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate	ENTRY(get_udb_errors)
12137c478bd9Sstevel@tonic-gate	set	P_DER_H, %o3
12147c478bd9Sstevel@tonic-gate	ldxa	[%o3]ASI_SDB_INTR_R, %o2
12157c478bd9Sstevel@tonic-gate	stx	%o2, [%o0]
12167c478bd9Sstevel@tonic-gate	set	P_DER_L, %o3
12177c478bd9Sstevel@tonic-gate	ldxa	[%o3]ASI_SDB_INTR_R, %o2
12187c478bd9Sstevel@tonic-gate	retl
12197c478bd9Sstevel@tonic-gate	  stx	%o2, [%o1]
12207c478bd9Sstevel@tonic-gate	SET_SIZE(get_udb_errors)
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate#endif /* lint */
12237c478bd9Sstevel@tonic-gate
12247c478bd9Sstevel@tonic-gate#if defined(lint)
12257c478bd9Sstevel@tonic-gate/*
12267c478bd9Sstevel@tonic-gate * The itlb_rd_entry and dtlb_rd_entry functions return the tag portion of the
12277c478bd9Sstevel@tonic-gate * tte, the virtual address, and the ctxnum of the specified tlb entry.  They
12287c478bd9Sstevel@tonic-gate * should only be used in places where you have no choice but to look at the
12297c478bd9Sstevel@tonic-gate * tlb itself.
12307c478bd9Sstevel@tonic-gate *
12317c478bd9Sstevel@tonic-gate * Note: These two routines are required by the Estar "cpr" loadable module.
12327c478bd9Sstevel@tonic-gate */
12337c478bd9Sstevel@tonic-gate/*ARGSUSED*/
12347c478bd9Sstevel@tonic-gatevoid
12357c478bd9Sstevel@tonic-gateitlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag)
12367c478bd9Sstevel@tonic-gate{}
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate/*ARGSUSED*/
12397c478bd9Sstevel@tonic-gatevoid
12407c478bd9Sstevel@tonic-gatedtlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag)
12417c478bd9Sstevel@tonic-gate{}
12427c478bd9Sstevel@tonic-gate#else 	/* lint */
12437c478bd9Sstevel@tonic-gate/*
12447c478bd9Sstevel@tonic-gate * NB - In Spitfire cpus, when reading a tte from the hardware, we
12457c478bd9Sstevel@tonic-gate * need to clear [42-41] because the general definitions in pte.h
12467c478bd9Sstevel@tonic-gate * define the PA to be [42-13] whereas Spitfire really uses [40-13].
12477c478bd9Sstevel@tonic-gate * When cloning these routines for other cpus the "andn" below is not
12487c478bd9Sstevel@tonic-gate * necessary.
12497c478bd9Sstevel@tonic-gate */
12507c478bd9Sstevel@tonic-gate	ENTRY_NP(itlb_rd_entry)
12517c478bd9Sstevel@tonic-gate	sllx	%o0, 3, %o0
12527c478bd9Sstevel@tonic-gate#if defined(SF_ERRATA_32)
12537c478bd9Sstevel@tonic-gate	sethi	%hi(FLUSH_ADDR), %g2
12547c478bd9Sstevel@tonic-gate	set	MMU_PCONTEXT, %g1
12557c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_DMMU			! KCONTEXT
12567c478bd9Sstevel@tonic-gate	flush	%g2
12577c478bd9Sstevel@tonic-gate#endif
12587c478bd9Sstevel@tonic-gate	ldxa	[%o0]ASI_ITLB_ACCESS, %g1
12597c478bd9Sstevel@tonic-gate	set	TTE_SPITFIRE_PFNHI_CLEAR, %g2		! spitfire only
12607c478bd9Sstevel@tonic-gate	sllx	%g2, TTE_SPITFIRE_PFNHI_SHIFT, %g2	! see comment above
12617c478bd9Sstevel@tonic-gate	andn	%g1, %g2, %g1				! for details
12627c478bd9Sstevel@tonic-gate	stx	%g1, [%o1]
12637c478bd9Sstevel@tonic-gate	ldxa	[%o0]ASI_ITLB_TAGREAD, %g2
12647c478bd9Sstevel@tonic-gate	set	TAGREAD_CTX_MASK, %o4
12657c478bd9Sstevel@tonic-gate	andn	%g2, %o4, %o5
12667c478bd9Sstevel@tonic-gate	retl
12677c478bd9Sstevel@tonic-gate	  stx	%o5, [%o2]
12687c478bd9Sstevel@tonic-gate	SET_SIZE(itlb_rd_entry)
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate	ENTRY_NP(dtlb_rd_entry)
12717c478bd9Sstevel@tonic-gate	sllx	%o0, 3, %o0
12727c478bd9Sstevel@tonic-gate#if defined(SF_ERRATA_32)
12737c478bd9Sstevel@tonic-gate	sethi	%hi(FLUSH_ADDR), %g2
12747c478bd9Sstevel@tonic-gate	set	MMU_PCONTEXT, %g1
12757c478bd9Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_DMMU			! KCONTEXT
12767c478bd9Sstevel@tonic-gate	flush	%g2
12777c478bd9Sstevel@tonic-gate#endif
12787c478bd9Sstevel@tonic-gate	ldxa	[%o0]ASI_DTLB_ACCESS, %g1
12797c478bd9Sstevel@tonic-gate	set	TTE_SPITFIRE_PFNHI_CLEAR, %g2		! spitfire only
12807c478bd9Sstevel@tonic-gate	sllx	%g2, TTE_SPITFIRE_PFNHI_SHIFT, %g2	! see comment above
12817c478bd9Sstevel@tonic-gate	andn	%g1, %g2, %g1				! itlb_rd_entry
12827c478bd9Sstevel@tonic-gate	stx	%g1, [%o1]
12837c478bd9Sstevel@tonic-gate	ldxa	[%o0]ASI_DTLB_TAGREAD, %g2
12847c478bd9Sstevel@tonic-gate	set	TAGREAD_CTX_MASK, %o4
12857c478bd9Sstevel@tonic-gate	andn	%g2, %o4, %o5
12867c478bd9Sstevel@tonic-gate	retl
12877c478bd9Sstevel@tonic-gate	  stx	%o5, [%o2]
12887c478bd9Sstevel@tonic-gate	SET_SIZE(dtlb_rd_entry)
12897c478bd9Sstevel@tonic-gate#endif /* lint */
12907c478bd9Sstevel@tonic-gate
12917c478bd9Sstevel@tonic-gate#if defined(lint)
12927c478bd9Sstevel@tonic-gate
12937c478bd9Sstevel@tonic-gate/*
12947c478bd9Sstevel@tonic-gate * routines to get and set the LSU register
12957c478bd9Sstevel@tonic-gate */
12967c478bd9Sstevel@tonic-gateuint64_t
12977c478bd9Sstevel@tonic-gateget_lsu(void)
12987c478bd9Sstevel@tonic-gate{
12997c478bd9Sstevel@tonic-gate	return ((uint64_t)0);
13007c478bd9Sstevel@tonic-gate}
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate/*ARGSUSED*/
13037c478bd9Sstevel@tonic-gatevoid
13047c478bd9Sstevel@tonic-gateset_lsu(uint64_t lsu)
13057c478bd9Sstevel@tonic-gate{}
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate#else /* lint */
13087c478bd9Sstevel@tonic-gate
13097c478bd9Sstevel@tonic-gate	ENTRY(set_lsu)
13107c478bd9Sstevel@tonic-gate	stxa	%o0, [%g0]ASI_LSU		! store to LSU
13117c478bd9Sstevel@tonic-gate	retl
13127c478bd9Sstevel@tonic-gate	membar	#Sync
13137c478bd9Sstevel@tonic-gate	SET_SIZE(set_lsu)
13147c478bd9Sstevel@tonic-gate
13157c478bd9Sstevel@tonic-gate	ENTRY(get_lsu)
13167c478bd9Sstevel@tonic-gate	retl
13177c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_LSU, %o0		! load LSU
13187c478bd9Sstevel@tonic-gate	SET_SIZE(get_lsu)
13197c478bd9Sstevel@tonic-gate
13207c478bd9Sstevel@tonic-gate#endif /* lint */
13217c478bd9Sstevel@tonic-gate
13227c478bd9Sstevel@tonic-gate#ifndef lint
13237c478bd9Sstevel@tonic-gate	/*
13247c478bd9Sstevel@tonic-gate	 * Clear the NPT (non-privileged trap) bit in the %tick
13257c478bd9Sstevel@tonic-gate	 * registers. In an effort to make the change in the
13267c478bd9Sstevel@tonic-gate	 * tick counter as consistent as possible, we disable
13277c478bd9Sstevel@tonic-gate	 * all interrupts while we're changing the registers. We also
13287c478bd9Sstevel@tonic-gate	 * ensure that the read and write instructions are in the same
13297c478bd9Sstevel@tonic-gate	 * line in the instruction cache.
13307c478bd9Sstevel@tonic-gate	 */
13317c478bd9Sstevel@tonic-gate	ENTRY_NP(cpu_clearticknpt)
13327c478bd9Sstevel@tonic-gate	rdpr	%pstate, %g1		/* save processor state */
13337c478bd9Sstevel@tonic-gate	andn	%g1, PSTATE_IE, %g3	/* turn off */
13347c478bd9Sstevel@tonic-gate	wrpr	%g0, %g3, %pstate	/*   interrupts */
13357c478bd9Sstevel@tonic-gate	rdpr	%tick, %g2		/* get tick register */
13367c478bd9Sstevel@tonic-gate	brgez,pn %g2, 1f		/* if NPT bit off, we're done */
13377c478bd9Sstevel@tonic-gate	mov	1, %g3			/* create mask */
13387c478bd9Sstevel@tonic-gate	sllx	%g3, 63, %g3		/*   for NPT bit */
13397c478bd9Sstevel@tonic-gate	ba,a,pt	%xcc, 2f
13407c478bd9Sstevel@tonic-gate	.align	64			/* Align to I$ boundary */
13417c478bd9Sstevel@tonic-gate2:
13427c478bd9Sstevel@tonic-gate	rdpr	%tick, %g2		/* get tick register */
13437c478bd9Sstevel@tonic-gate	wrpr	%g3, %g2, %tick		/* write tick register, */
13447c478bd9Sstevel@tonic-gate					/*   clearing NPT bit   */
13457c478bd9Sstevel@tonic-gate#if defined(BB_ERRATA_1)
13467c478bd9Sstevel@tonic-gate	rdpr	%tick, %g0		/* read (s)tick (BB_ERRATA_1) */
13477c478bd9Sstevel@tonic-gate#endif
13487c478bd9Sstevel@tonic-gate1:
13497c478bd9Sstevel@tonic-gate	jmp	%g4 + 4
13507c478bd9Sstevel@tonic-gate	wrpr	%g0, %g1, %pstate	/* restore processor state */
13517c478bd9Sstevel@tonic-gate	SET_SIZE(cpu_clearticknpt)
13527c478bd9Sstevel@tonic-gate
13537c478bd9Sstevel@tonic-gate	/*
13547c478bd9Sstevel@tonic-gate	 * get_ecache_tag()
13557c478bd9Sstevel@tonic-gate	 * Register Usage:
13567c478bd9Sstevel@tonic-gate	 * %o0: In: 32-bit E$ index
13577c478bd9Sstevel@tonic-gate	 *      Out: 64-bit E$ tag value
13587c478bd9Sstevel@tonic-gate	 * %o1: In: 64-bit AFSR value after clearing sticky bits
13597c478bd9Sstevel@tonic-gate	 * %o2: In: address of cpu private afsr storage
13607c478bd9Sstevel@tonic-gate	 */
13617c478bd9Sstevel@tonic-gate	ENTRY(get_ecache_tag)
13627c478bd9Sstevel@tonic-gate	or	%g0, 1, %o4
13637c478bd9Sstevel@tonic-gate	sllx	%o4, 40, %o4			! set bit 40 for e$ tag access
13647c478bd9Sstevel@tonic-gate	or	%o0, %o4, %o4			! %o4 = e$ addr for tag read
13657c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o5
13667c478bd9Sstevel@tonic-gate	andn	%o5, PSTATE_IE | PSTATE_AM, %o0
13677c478bd9Sstevel@tonic-gate	wrpr	%o0, %g0, %pstate		! clear IE, AM bits
13687c478bd9Sstevel@tonic-gate
13697c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g1
13707c478bd9Sstevel@tonic-gate	stxa	%g0, [%g0]ASI_ESTATE_ERR	! Turn off Error enable
13717c478bd9Sstevel@tonic-gate	membar	#Sync
13727c478bd9Sstevel@tonic-gate
13737c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %o0
13747c478bd9Sstevel@tonic-gate	srlx	%o0, P_AFSR_CP_SHIFT, %o3
13757c478bd9Sstevel@tonic-gate	btst	1, %o3
13767c478bd9Sstevel@tonic-gate	bz	1f
13777c478bd9Sstevel@tonic-gate	  nop
13787c478bd9Sstevel@tonic-gate	ldx	[%o2], %g4
13797c478bd9Sstevel@tonic-gate	or	%g4, %o0, %g4			! aggregate AFSR in cpu private
13807c478bd9Sstevel@tonic-gate	stx	%g4, [%o2]
13817c478bd9Sstevel@tonic-gate1:
13827c478bd9Sstevel@tonic-gate	stxa	%o0, [%g0]ASI_AFSR		! clear AFSR
13837c478bd9Sstevel@tonic-gate	membar  #Sync
13847c478bd9Sstevel@tonic-gate
13857c478bd9Sstevel@tonic-gate	ldxa	[%o4]ASI_EC_R, %g0
13867c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_EC_DIAG, %o0		! read tag from e$ tag reg
13877c478bd9Sstevel@tonic-gate
13887c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %o3
13897c478bd9Sstevel@tonic-gate	srlx	%o3, P_AFSR_CP_SHIFT, %o4
13907c478bd9Sstevel@tonic-gate	btst	1, %o4
13917c478bd9Sstevel@tonic-gate	bz	2f
13927c478bd9Sstevel@tonic-gate	  stx	%o3, [%o1]			! AFSR after sticky clear
13937c478bd9Sstevel@tonic-gate	ldx	[%o2], %g4
13947c478bd9Sstevel@tonic-gate	or	%g4, %o3, %g4			! aggregate AFSR in cpu private
13957c478bd9Sstevel@tonic-gate	stx	%g4, [%o2]
13967c478bd9Sstevel@tonic-gate2:
13977c478bd9Sstevel@tonic-gate	membar	#Sync
13987c478bd9Sstevel@tonic-gate
13997c478bd9Sstevel@tonic-gate	stxa	%g1, [%g0]ASI_ESTATE_ERR	! Turn error enable back on
14007c478bd9Sstevel@tonic-gate	membar	#Sync
14017c478bd9Sstevel@tonic-gate	retl
14027c478bd9Sstevel@tonic-gate	wrpr	%g0, %o5, %pstate
14037c478bd9Sstevel@tonic-gate	SET_SIZE(get_ecache_tag)
14047c478bd9Sstevel@tonic-gate
14057c478bd9Sstevel@tonic-gate	/*
14067c478bd9Sstevel@tonic-gate	 * check_ecache_line()
14077c478bd9Sstevel@tonic-gate	 * Register Usage:
14087c478bd9Sstevel@tonic-gate	 * %o0: In: 32-bit E$ index
14097c478bd9Sstevel@tonic-gate	 *      Out: 64-bit accumulated AFSR
14107c478bd9Sstevel@tonic-gate	 * %o1: In: address of cpu private afsr storage
14117c478bd9Sstevel@tonic-gate	 */
14127c478bd9Sstevel@tonic-gate	ENTRY(check_ecache_line)
14137c478bd9Sstevel@tonic-gate	or	%g0, 1, %o4
14147c478bd9Sstevel@tonic-gate	sllx	%o4, 39, %o4			! set bit 39 for e$ data access
14157c478bd9Sstevel@tonic-gate	or	%o0, %o4, %o4		 	! %o4 = e$ addr for data read
14167c478bd9Sstevel@tonic-gate
14177c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o5
14187c478bd9Sstevel@tonic-gate	andn	%o5, PSTATE_IE | PSTATE_AM, %o0
14197c478bd9Sstevel@tonic-gate	wrpr	%o0, %g0, %pstate		! clear IE, AM bits
14207c478bd9Sstevel@tonic-gate
14217c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g1
14227c478bd9Sstevel@tonic-gate	stxa	%g0, [%g0]ASI_ESTATE_ERR 	! Turn off Error enable
14237c478bd9Sstevel@tonic-gate	membar	#Sync
14247c478bd9Sstevel@tonic-gate
14257c478bd9Sstevel@tonic-gate	ldxa 	[%g0]ASI_AFSR, %o0
14267c478bd9Sstevel@tonic-gate	srlx	%o0, P_AFSR_CP_SHIFT, %o2
14277c478bd9Sstevel@tonic-gate	btst	1, %o2
14287c478bd9Sstevel@tonic-gate	bz	1f
14297c478bd9Sstevel@tonic-gate	  clr	%o2				! loop count
14307c478bd9Sstevel@tonic-gate	ldx	[%o1], %o3
14317c478bd9Sstevel@tonic-gate	or	%o3, %o0, %o3			! aggregate AFSR in cpu private
14327c478bd9Sstevel@tonic-gate	stx	%o3, [%o1]
14337c478bd9Sstevel@tonic-gate1:
14347c478bd9Sstevel@tonic-gate	stxa    %o0, [%g0]ASI_AFSR              ! clear AFSR
14357c478bd9Sstevel@tonic-gate	membar	#Sync
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate2:
14387c478bd9Sstevel@tonic-gate	ldxa	[%o4]ASI_EC_R, %g0		! Read the E$ data 8bytes each
14397c478bd9Sstevel@tonic-gate	add	%o2, 1, %o2
14407c478bd9Sstevel@tonic-gate	cmp	%o2, 8
14417c478bd9Sstevel@tonic-gate	bl,a 	2b
14427c478bd9Sstevel@tonic-gate	  add	%o4, 8, %o4
14437c478bd9Sstevel@tonic-gate
14447c478bd9Sstevel@tonic-gate	membar	#Sync
14457c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %o0		! read accumulated AFSR
14467c478bd9Sstevel@tonic-gate	srlx	%o0, P_AFSR_CP_SHIFT, %o2
14477c478bd9Sstevel@tonic-gate	btst	1, %o2
14487c478bd9Sstevel@tonic-gate	bz	3f
14497c478bd9Sstevel@tonic-gate	  nop
14507c478bd9Sstevel@tonic-gate	ldx	[%o1], %o3
14517c478bd9Sstevel@tonic-gate	or	%o3, %o0, %o3			! aggregate AFSR in cpu private
14527c478bd9Sstevel@tonic-gate	stx	%o3, [%o1]
14537c478bd9Sstevel@tonic-gate3:
14547c478bd9Sstevel@tonic-gate	stxa	%o0, [%g0]ASI_AFSR		! clear AFSR
14557c478bd9Sstevel@tonic-gate	membar	#Sync
14567c478bd9Sstevel@tonic-gate	stxa	%g1, [%g0]ASI_ESTATE_ERR	! Turn error enable back on
14577c478bd9Sstevel@tonic-gate	membar	#Sync
14587c478bd9Sstevel@tonic-gate	retl
14597c478bd9Sstevel@tonic-gate	wrpr	%g0, %o5, %pstate
14607c478bd9Sstevel@tonic-gate	SET_SIZE(check_ecache_line)
14617c478bd9Sstevel@tonic-gate#endif /* lint */
14627c478bd9Sstevel@tonic-gate
14637c478bd9Sstevel@tonic-gate#if defined(lint)
14647c478bd9Sstevel@tonic-gateuint64_t
14657c478bd9Sstevel@tonic-gateread_and_clear_afsr()
14667c478bd9Sstevel@tonic-gate{
14677c478bd9Sstevel@tonic-gate	return ((uint64_t)0);
14687c478bd9Sstevel@tonic-gate}
14697c478bd9Sstevel@tonic-gate#else	/* lint */
14707c478bd9Sstevel@tonic-gate	ENTRY(read_and_clear_afsr)
14717c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %o0
14727c478bd9Sstevel@tonic-gate	retl
14737c478bd9Sstevel@tonic-gate	  stxa	%o0, [%g0]ASI_AFSR		! clear AFSR
14747c478bd9Sstevel@tonic-gate	SET_SIZE(read_and_clear_afsr)
14757c478bd9Sstevel@tonic-gate#endif	/* lint */
14767c478bd9Sstevel@tonic-gate
14777c478bd9Sstevel@tonic-gate#if defined(lint)
14787c478bd9Sstevel@tonic-gate/* ARGSUSED */
14797c478bd9Sstevel@tonic-gatevoid
14807c478bd9Sstevel@tonic-gatescrubphys(uint64_t paddr, int ecache_size)
14817c478bd9Sstevel@tonic-gate{
14827c478bd9Sstevel@tonic-gate}
14837c478bd9Sstevel@tonic-gate
14847c478bd9Sstevel@tonic-gate#else	/* lint */
14857c478bd9Sstevel@tonic-gate
14867c478bd9Sstevel@tonic-gate/*
14877c478bd9Sstevel@tonic-gate * scrubphys - Pass in the aligned physical memory address that you want
14887c478bd9Sstevel@tonic-gate * to scrub, along with the ecache size.
14897c478bd9Sstevel@tonic-gate *
14907c478bd9Sstevel@tonic-gate *	1) Displacement flush the E$ line corresponding to %addr.
14917c478bd9Sstevel@tonic-gate *	   The first ldxa guarantees that the %addr is no longer in
14927c478bd9Sstevel@tonic-gate *	   M, O, or E (goes to I or S (if instruction fetch also happens).
14937c478bd9Sstevel@tonic-gate *	2) "Write" the data using a CAS %addr,%g0,%g0.
14947c478bd9Sstevel@tonic-gate *	   The casxa guarantees a transition from I to M or S to M.
14957c478bd9Sstevel@tonic-gate *	3) Displacement flush the E$ line corresponding to %addr.
14967c478bd9Sstevel@tonic-gate *	   The second ldxa pushes the M line out of the ecache, into the
14977c478bd9Sstevel@tonic-gate *	   writeback buffers, on the way to memory.
14987c478bd9Sstevel@tonic-gate *	4) The "membar #Sync" pushes the cache line out of the writeback
14997c478bd9Sstevel@tonic-gate *	   buffers onto the bus, on the way to dram finally.
15007c478bd9Sstevel@tonic-gate *
15017c478bd9Sstevel@tonic-gate * This is a modified version of the algorithm suggested by Gary Lauterbach.
15027c478bd9Sstevel@tonic-gate * In theory the CAS %addr,%g0,%g0 is supposed to mark the addr's cache line
15037c478bd9Sstevel@tonic-gate * as modified, but then we found out that for spitfire, if it misses in the
15047c478bd9Sstevel@tonic-gate * E$ it will probably install as an M, but if it hits in the E$, then it
15057c478bd9Sstevel@tonic-gate * will stay E, if the store doesn't happen. So the first displacement flush
15067c478bd9Sstevel@tonic-gate * should ensure that the CAS will miss in the E$.  Arrgh.
15077c478bd9Sstevel@tonic-gate */
15087c478bd9Sstevel@tonic-gate
15097c478bd9Sstevel@tonic-gate	ENTRY(scrubphys)
15107c478bd9Sstevel@tonic-gate	or	%o1, %g0, %o2	! put ecache size in %o2
15117c478bd9Sstevel@tonic-gate#ifndef HUMMINGBIRD
15127c478bd9Sstevel@tonic-gate	xor	%o0, %o2, %o1	! calculate alias address
15137c478bd9Sstevel@tonic-gate	add	%o2, %o2, %o3	! 2 * ecachesize in case
15147c478bd9Sstevel@tonic-gate				! addr == ecache_flushaddr
15157c478bd9Sstevel@tonic-gate	sub	%o3, 1, %o3	! -1 == mask
15167c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1	! and with xor'd address
15177c478bd9Sstevel@tonic-gate	set	ecache_flushaddr, %o3
15187c478bd9Sstevel@tonic-gate	ldx	[%o3], %o3
15197c478bd9Sstevel@tonic-gate
15207c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o4
15217c478bd9Sstevel@tonic-gate	andn	%o4, PSTATE_IE | PSTATE_AM, %o5
15227c478bd9Sstevel@tonic-gate	wrpr	%o5, %g0, %pstate	! clear IE, AM bits
15237c478bd9Sstevel@tonic-gate
15247c478bd9Sstevel@tonic-gate	ldxa	[%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
15257c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
15267c478bd9Sstevel@tonic-gate	ldxa	[%o1 + %o3]ASI_MEM, %g0	! load ecache_flushaddr + alias
15277c478bd9Sstevel@tonic-gate
15287c478bd9Sstevel@tonic-gate#else /* HUMMINGBIRD */
15297c478bd9Sstevel@tonic-gate	/*
15307c478bd9Sstevel@tonic-gate	 * UltraSPARC-IIe processor supports both 4-way set associative
15317c478bd9Sstevel@tonic-gate	 * and direct map E$. We need to reconfigure E$ to direct map
15327c478bd9Sstevel@tonic-gate	 * mode for data load/store before displacement flush. Also, we
15337c478bd9Sstevel@tonic-gate	 * need to flush all 4 sets of the E$ to ensure that the physaddr
15347c478bd9Sstevel@tonic-gate	 * has been flushed. Keep the interrupts disabled while flushing
15357c478bd9Sstevel@tonic-gate	 * E$ in this manner.
15367c478bd9Sstevel@tonic-gate	 *
15377c478bd9Sstevel@tonic-gate	 * For flushing a specific physical address, we start at the
15387c478bd9Sstevel@tonic-gate	 * aliased address and load at set-size stride, wrapping around
15397c478bd9Sstevel@tonic-gate	 * at 2*ecache-size boundary and skipping fault physical address.
15407c478bd9Sstevel@tonic-gate	 * It takes 10 loads to guarantee that the physical address has
15417c478bd9Sstevel@tonic-gate	 * been flushed.
15427c478bd9Sstevel@tonic-gate	 *
15437c478bd9Sstevel@tonic-gate	 * Usage:
15447c478bd9Sstevel@tonic-gate	 *	%o0	physaddr
15457c478bd9Sstevel@tonic-gate	 *	%o5	physaddr - ecache_flushaddr
15467c478bd9Sstevel@tonic-gate	 *	%g1	UPA config (restored later)
15477c478bd9Sstevel@tonic-gate	 *	%g2	E$ set size
15487c478bd9Sstevel@tonic-gate	 *	%g3	E$ flush address range mask (i.e. 2 * E$ -1)
15497c478bd9Sstevel@tonic-gate	 *	%g4	#loads to flush phys address
15507c478bd9Sstevel@tonic-gate	 *	%g5	temp
15517c478bd9Sstevel@tonic-gate	 */
15527c478bd9Sstevel@tonic-gate
15537c478bd9Sstevel@tonic-gate	sethi	%hi(ecache_associativity), %g5
15547c478bd9Sstevel@tonic-gate	ld	[%g5 + %lo(ecache_associativity)], %g5
15557c478bd9Sstevel@tonic-gate	udivx	%o2, %g5, %g2	! set size (i.e. ecache_size/#sets)
15567c478bd9Sstevel@tonic-gate	xor	%o0, %o2, %o1	! calculate alias address
15577c478bd9Sstevel@tonic-gate	add	%o2, %o2, %g3	! 2 * ecachesize in case
15587c478bd9Sstevel@tonic-gate				! addr == ecache_flushaddr
15597c478bd9Sstevel@tonic-gate	sub	%g3, 1, %g3	! 2 * ecachesize -1 == mask
15607c478bd9Sstevel@tonic-gate	and	%o1, %g3, %o1	! and with xor'd address
15617c478bd9Sstevel@tonic-gate	sethi	%hi(ecache_flushaddr), %o3
15627c478bd9Sstevel@tonic-gate	ldx	[%o3 + %lo(ecache_flushaddr)], %o3
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o4
15657c478bd9Sstevel@tonic-gate	andn	%o4, PSTATE_IE | PSTATE_AM, %o5
15667c478bd9Sstevel@tonic-gate	wrpr	%o5, %g0, %pstate	! clear IE, AM bits
15677c478bd9Sstevel@tonic-gate
15687c478bd9Sstevel@tonic-gate	! Place E$ in direct map mode for data access
15697c478bd9Sstevel@tonic-gate	or	%g0, 1, %g5
15707c478bd9Sstevel@tonic-gate	sllx	%g5, HB_UPA_DMAP_DATA_BIT, %g5
15717c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_UPA_CONFIG, %g1 ! current UPA config (restored later)
15727c478bd9Sstevel@tonic-gate	or	%g1, %g5, %g5
15737c478bd9Sstevel@tonic-gate	membar	#Sync
15747c478bd9Sstevel@tonic-gate	stxa	%g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access
15757c478bd9Sstevel@tonic-gate	membar	#Sync
15767c478bd9Sstevel@tonic-gate
15777c478bd9Sstevel@tonic-gate	! Displace cache line from each set of E$ starting at the
15787c478bd9Sstevel@tonic-gate	! aliased address. at set-size stride, wrapping at 2*ecache_size
15797c478bd9Sstevel@tonic-gate	! and skipping load from physaddr. We need 10 loads to flush the
15807c478bd9Sstevel@tonic-gate	! physaddr from E$.
15817c478bd9Sstevel@tonic-gate	mov	HB_PHYS_FLUSH_CNT-1, %g4 ! #loads to flush phys addr
15827c478bd9Sstevel@tonic-gate	sub	%o0, %o3, %o5		! physaddr - ecache_flushaddr
15837c478bd9Sstevel@tonic-gate	or	%o1, %g0, %g5		! starting aliased offset
15847c478bd9Sstevel@tonic-gate2:
15857c478bd9Sstevel@tonic-gate	ldxa	[%g5 + %o3]ASI_MEM, %g0	! load ecache_flushaddr + alias
15867c478bd9Sstevel@tonic-gate1:
15877c478bd9Sstevel@tonic-gate	add	%g5, %g2, %g5		! calculate offset in next set
15887c478bd9Sstevel@tonic-gate	and	%g5, %g3, %g5		! force offset within aliased range
15897c478bd9Sstevel@tonic-gate	cmp	%g5, %o5		! skip loads from physaddr
15907c478bd9Sstevel@tonic-gate	be,pn %ncc, 1b
15917c478bd9Sstevel@tonic-gate	  nop
15927c478bd9Sstevel@tonic-gate	brgz,pt	%g4, 2b
15937c478bd9Sstevel@tonic-gate	  dec	%g4
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
15967c478bd9Sstevel@tonic-gate
15977c478bd9Sstevel@tonic-gate	! Flush %o0 from ecahe again.
15987c478bd9Sstevel@tonic-gate	! Need single displacement flush at offset %o1 this time as
15997c478bd9Sstevel@tonic-gate	! the E$ is already in direct map mode.
16007c478bd9Sstevel@tonic-gate	ldxa	[%o1 + %o3]ASI_MEM, %g0	! load ecache_flushaddr + alias
16017c478bd9Sstevel@tonic-gate
16027c478bd9Sstevel@tonic-gate	membar	#Sync
16037c478bd9Sstevel@tonic-gate	stxa	%g1, [%g0]ASI_UPA_CONFIG ! restore UPA config (DM bits)
16047c478bd9Sstevel@tonic-gate	membar	#Sync
16057c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD */
16067c478bd9Sstevel@tonic-gate	wrpr	%g0, %o4, %pstate	! restore earlier pstate register value
16077c478bd9Sstevel@tonic-gate
16087c478bd9Sstevel@tonic-gate	retl
16097c478bd9Sstevel@tonic-gate	membar	#Sync			! move the data out of the load buffer
16107c478bd9Sstevel@tonic-gate	SET_SIZE(scrubphys)
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate#endif	/* lint */
16137c478bd9Sstevel@tonic-gate
16147c478bd9Sstevel@tonic-gate#if defined(lint)
16157c478bd9Sstevel@tonic-gate
16167c478bd9Sstevel@tonic-gate/*
16177c478bd9Sstevel@tonic-gate * clearphys - Pass in the aligned physical memory address that you want
16187c478bd9Sstevel@tonic-gate * to push out, as a 64 byte block of zeros, from the ecache zero-filled.
16197c478bd9Sstevel@tonic-gate * Since this routine does not bypass the ecache, it is possible that
16207c478bd9Sstevel@tonic-gate * it could generate a UE error while trying to clear the a bad line.
16217c478bd9Sstevel@tonic-gate * This routine clears and restores the error enable flag.
16227c478bd9Sstevel@tonic-gate * TBD - Hummingbird may need similar protection
16237c478bd9Sstevel@tonic-gate */
16247c478bd9Sstevel@tonic-gate/* ARGSUSED */
16257c478bd9Sstevel@tonic-gatevoid
16267c478bd9Sstevel@tonic-gateclearphys(uint64_t paddr, int ecache_size, int ecache_linesize)
16277c478bd9Sstevel@tonic-gate{
16287c478bd9Sstevel@tonic-gate}
16297c478bd9Sstevel@tonic-gate
16307c478bd9Sstevel@tonic-gate#else	/* lint */
16317c478bd9Sstevel@tonic-gate
16327c478bd9Sstevel@tonic-gate	ENTRY(clearphys)
16337c478bd9Sstevel@tonic-gate	or	%o2, %g0, %o3	! ecache linesize
16347c478bd9Sstevel@tonic-gate	or	%o1, %g0, %o2	! ecache size
16357c478bd9Sstevel@tonic-gate#ifndef HUMMINGBIRD
16367c478bd9Sstevel@tonic-gate	or	%o3, %g0, %o4	! save ecache linesize
16377c478bd9Sstevel@tonic-gate	xor	%o0, %o2, %o1	! calculate alias address
16387c478bd9Sstevel@tonic-gate	add	%o2, %o2, %o3	! 2 * ecachesize
16397c478bd9Sstevel@tonic-gate	sub	%o3, 1, %o3	! -1 == mask
16407c478bd9Sstevel@tonic-gate	and	%o1, %o3, %o1	! and with xor'd address
16417c478bd9Sstevel@tonic-gate	set	ecache_flushaddr, %o3
16427c478bd9Sstevel@tonic-gate	ldx	[%o3], %o3
16437c478bd9Sstevel@tonic-gate	or	%o4, %g0, %o2	! saved ecache linesize
16447c478bd9Sstevel@tonic-gate
16457c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o4
16467c478bd9Sstevel@tonic-gate	andn	%o4, PSTATE_IE | PSTATE_AM, %o5
16477c478bd9Sstevel@tonic-gate	wrpr	%o5, %g0, %pstate	! clear IE, AM bits
16487c478bd9Sstevel@tonic-gate
16497c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g1
16507c478bd9Sstevel@tonic-gate	stxa	%g0, [%g0]ASI_ESTATE_ERR	! disable errors
16517c478bd9Sstevel@tonic-gate	membar	#Sync
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate	! need to put zeros in the cache line before displacing it
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate	sub	%o2, 8, %o2	! get offset of last double word in ecache line
16567c478bd9Sstevel@tonic-gate1:
16577c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0 + %o2]ASI_MEM	! put zeros in the ecache line
16587c478bd9Sstevel@tonic-gate	sub	%o2, 8, %o2
16597c478bd9Sstevel@tonic-gate	brgez,a,pt %o2, 1b
16607c478bd9Sstevel@tonic-gate	nop
16617c478bd9Sstevel@tonic-gate	ldxa	[%o1 + %o3]ASI_MEM, %g0	! load ecache_flushaddr + alias
16627c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
16637c478bd9Sstevel@tonic-gate	ldxa	[%o1 + %o3]ASI_MEM, %g0	! load ecache_flushaddr + alias
16647c478bd9Sstevel@tonic-gate
16657c478bd9Sstevel@tonic-gate	stxa	%g1, [%g0]ASI_ESTATE_ERR	! restore error enable
16667c478bd9Sstevel@tonic-gate	membar	#Sync
16677c478bd9Sstevel@tonic-gate
16687c478bd9Sstevel@tonic-gate#else /* HUMMINGBIRD... */
16697c478bd9Sstevel@tonic-gate	/*
16707c478bd9Sstevel@tonic-gate	 * UltraSPARC-IIe processor supports both 4-way set associative
16717c478bd9Sstevel@tonic-gate	 * and direct map E$. We need to reconfigure E$ to direct map
16727c478bd9Sstevel@tonic-gate	 * mode for data load/store before displacement flush. Also, we
16737c478bd9Sstevel@tonic-gate	 * need to flush all 4 sets of the E$ to ensure that the physaddr
16747c478bd9Sstevel@tonic-gate	 * has been flushed. Keep the interrupts disabled while flushing
16757c478bd9Sstevel@tonic-gate	 * E$ in this manner.
16767c478bd9Sstevel@tonic-gate	 *
16777c478bd9Sstevel@tonic-gate	 * For flushing a specific physical address, we start at the
16787c478bd9Sstevel@tonic-gate	 * aliased address and load at set-size stride, wrapping around
16797c478bd9Sstevel@tonic-gate	 * at 2*ecache-size boundary and skipping fault physical address.
16807c478bd9Sstevel@tonic-gate	 * It takes 10 loads to guarantee that the physical address has
16817c478bd9Sstevel@tonic-gate	 * been flushed.
16827c478bd9Sstevel@tonic-gate	 *
16837c478bd9Sstevel@tonic-gate	 * Usage:
16847c478bd9Sstevel@tonic-gate	 *	%o0	physaddr
16857c478bd9Sstevel@tonic-gate	 *	%o5	physaddr - ecache_flushaddr
16867c478bd9Sstevel@tonic-gate	 *	%g1	UPA config (restored later)
16877c478bd9Sstevel@tonic-gate	 *	%g2	E$ set size
16887c478bd9Sstevel@tonic-gate	 *	%g3	E$ flush address range mask (i.e. 2 * E$ -1)
16897c478bd9Sstevel@tonic-gate	 *	%g4	#loads to flush phys address
16907c478bd9Sstevel@tonic-gate	 *	%g5	temp
16917c478bd9Sstevel@tonic-gate	 */
16927c478bd9Sstevel@tonic-gate
16937c478bd9Sstevel@tonic-gate	or	%o3, %g0, %o4	! save ecache linesize
16947c478bd9Sstevel@tonic-gate	sethi	%hi(ecache_associativity), %g5
16957c478bd9Sstevel@tonic-gate	ld	[%g5 + %lo(ecache_associativity)], %g5
16967c478bd9Sstevel@tonic-gate	udivx	%o2, %g5, %g2	! set size (i.e. ecache_size/#sets)
16977c478bd9Sstevel@tonic-gate
16987c478bd9Sstevel@tonic-gate	xor	%o0, %o2, %o1	! calculate alias address
16997c478bd9Sstevel@tonic-gate	add	%o2, %o2, %g3	! 2 * ecachesize
17007c478bd9Sstevel@tonic-gate	sub	%g3, 1, %g3	! 2 * ecachesize -1 == mask
17017c478bd9Sstevel@tonic-gate	and	%o1, %g3, %o1	! and with xor'd address
17027c478bd9Sstevel@tonic-gate	sethi	%hi(ecache_flushaddr), %o3
17037c478bd9Sstevel@tonic-gate	ldx	[%o3 +%lo(ecache_flushaddr)], %o3
17047c478bd9Sstevel@tonic-gate	or	%o4, %g0, %o2	! saved ecache linesize
17057c478bd9Sstevel@tonic-gate
17067c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o4
17077c478bd9Sstevel@tonic-gate	andn	%o4, PSTATE_IE | PSTATE_AM, %o5
17087c478bd9Sstevel@tonic-gate	wrpr	%o5, %g0, %pstate	! clear IE, AM bits
17097c478bd9Sstevel@tonic-gate
17107c478bd9Sstevel@tonic-gate	! Place E$ in direct map mode for data access
17117c478bd9Sstevel@tonic-gate	or	%g0, 1, %g5
17127c478bd9Sstevel@tonic-gate	sllx	%g5, HB_UPA_DMAP_DATA_BIT, %g5
17137c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_UPA_CONFIG, %g1 ! current UPA config (restored later)
17147c478bd9Sstevel@tonic-gate	or	%g1, %g5, %g5
17157c478bd9Sstevel@tonic-gate	membar	#Sync
17167c478bd9Sstevel@tonic-gate	stxa	%g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access
17177c478bd9Sstevel@tonic-gate	membar	#Sync
17187c478bd9Sstevel@tonic-gate
17197c478bd9Sstevel@tonic-gate	! need to put zeros in the cache line before displacing it
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate	sub	%o2, 8, %o2	! get offset of last double word in ecache line
17227c478bd9Sstevel@tonic-gate1:
17237c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0 + %o2]ASI_MEM	! put zeros in the ecache line
17247c478bd9Sstevel@tonic-gate	sub	%o2, 8, %o2
17257c478bd9Sstevel@tonic-gate	brgez,a,pt %o2, 1b
17267c478bd9Sstevel@tonic-gate	nop
17277c478bd9Sstevel@tonic-gate
17287c478bd9Sstevel@tonic-gate	! Displace cache line from each set of E$ starting at the
17297c478bd9Sstevel@tonic-gate	! aliased address. at set-size stride, wrapping at 2*ecache_size
17307c478bd9Sstevel@tonic-gate	! and skipping load from physaddr. We need 10 loads to flush the
17317c478bd9Sstevel@tonic-gate	! physaddr from E$.
17327c478bd9Sstevel@tonic-gate	mov	HB_PHYS_FLUSH_CNT-1, %g4 ! #loads to flush phys addr
17337c478bd9Sstevel@tonic-gate	sub	%o0, %o3, %o5		! physaddr - ecache_flushaddr
17347c478bd9Sstevel@tonic-gate	or	%o1, %g0, %g5		! starting offset
17357c478bd9Sstevel@tonic-gate2:
17367c478bd9Sstevel@tonic-gate	ldxa	[%g5 + %o3]ASI_MEM, %g0	! load ecache_flushaddr + alias
17377c478bd9Sstevel@tonic-gate3:
17387c478bd9Sstevel@tonic-gate	add	%g5, %g2, %g5		! calculate offset in next set
17397c478bd9Sstevel@tonic-gate	and	%g5, %g3, %g5		! force offset within aliased range
17407c478bd9Sstevel@tonic-gate	cmp	%g5, %o5		! skip loads from physaddr
17417c478bd9Sstevel@tonic-gate	be,pn %ncc, 3b
17427c478bd9Sstevel@tonic-gate	  nop
17437c478bd9Sstevel@tonic-gate	brgz,pt	%g4, 2b
17447c478bd9Sstevel@tonic-gate	  dec	%g4
17457c478bd9Sstevel@tonic-gate
17467c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
17477c478bd9Sstevel@tonic-gate
17487c478bd9Sstevel@tonic-gate	! Flush %o0 from ecahe again.
17497c478bd9Sstevel@tonic-gate	! Need single displacement flush at offset %o1 this time as
17507c478bd9Sstevel@tonic-gate	! the E$ is already in direct map mode.
17517c478bd9Sstevel@tonic-gate	ldxa	[%o1 + %o3]ASI_MEM, %g0	! load ecache_flushaddr + alias
17527c478bd9Sstevel@tonic-gate
17537c478bd9Sstevel@tonic-gate	membar	#Sync
17547c478bd9Sstevel@tonic-gate	stxa	%g1, [%g0]ASI_UPA_CONFIG ! restore UPA config (DM bits)
17557c478bd9Sstevel@tonic-gate	membar	#Sync
17567c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD... */
17577c478bd9Sstevel@tonic-gate
17587c478bd9Sstevel@tonic-gate	retl
17597c478bd9Sstevel@tonic-gate	wrpr	%g0, %o4, %pstate	! restore earlier pstate register value
17607c478bd9Sstevel@tonic-gate	SET_SIZE(clearphys)
17617c478bd9Sstevel@tonic-gate
17627c478bd9Sstevel@tonic-gate#endif	/* lint */
17637c478bd9Sstevel@tonic-gate
17647c478bd9Sstevel@tonic-gate#if defined(lint)
17657c478bd9Sstevel@tonic-gate/* ARGSUSED */
17667c478bd9Sstevel@tonic-gatevoid
17677c478bd9Sstevel@tonic-gateflushecacheline(uint64_t paddr, int ecache_size)
17687c478bd9Sstevel@tonic-gate{
17697c478bd9Sstevel@tonic-gate}
17707c478bd9Sstevel@tonic-gate
17717c478bd9Sstevel@tonic-gate#else	/* lint */
17727c478bd9Sstevel@tonic-gate/*
17737c478bd9Sstevel@tonic-gate * flushecacheline - This is a simpler version of scrubphys
17747c478bd9Sstevel@tonic-gate * which simply does a displacement flush of the line in
17757c478bd9Sstevel@tonic-gate * question. This routine is mainly used in handling async
17767c478bd9Sstevel@tonic-gate * errors where we want to get rid of a bad line in ecache.
17777c478bd9Sstevel@tonic-gate * Note that if the line is modified and it has suffered
17787c478bd9Sstevel@tonic-gate * data corruption - we are guarantee that the hw will write
17797c478bd9Sstevel@tonic-gate * a UE back to mark the page poisoned.
17807c478bd9Sstevel@tonic-gate */
17817c478bd9Sstevel@tonic-gate        ENTRY(flushecacheline)
17827c478bd9Sstevel@tonic-gate        or      %o1, %g0, %o2   ! put ecache size in %o2
17837c478bd9Sstevel@tonic-gate#ifndef HUMMINGBIRD
17847c478bd9Sstevel@tonic-gate        xor     %o0, %o2, %o1   ! calculate alias address
17857c478bd9Sstevel@tonic-gate        add     %o2, %o2, %o3   ! 2 * ecachesize in case
17867c478bd9Sstevel@tonic-gate                                ! addr == ecache_flushaddr
17877c478bd9Sstevel@tonic-gate        sub     %o3, 1, %o3     ! -1 == mask
17887c478bd9Sstevel@tonic-gate        and     %o1, %o3, %o1   ! and with xor'd address
17897c478bd9Sstevel@tonic-gate        set     ecache_flushaddr, %o3
17907c478bd9Sstevel@tonic-gate        ldx     [%o3], %o3
17917c478bd9Sstevel@tonic-gate
17927c478bd9Sstevel@tonic-gate        rdpr    %pstate, %o4
17937c478bd9Sstevel@tonic-gate        andn    %o4, PSTATE_IE | PSTATE_AM, %o5
17947c478bd9Sstevel@tonic-gate        wrpr    %o5, %g0, %pstate       ! clear IE, AM bits
17957c478bd9Sstevel@tonic-gate
17967c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g1
17977c478bd9Sstevel@tonic-gate	stxa	%g0, [%g0]ASI_ESTATE_ERR	! disable errors
17987c478bd9Sstevel@tonic-gate	membar	#Sync
17997c478bd9Sstevel@tonic-gate
18007c478bd9Sstevel@tonic-gate        ldxa    [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias
18017c478bd9Sstevel@tonic-gate	membar	#Sync
18027c478bd9Sstevel@tonic-gate	stxa	%g1, [%g0]ASI_ESTATE_ERR	! restore error enable
18037c478bd9Sstevel@tonic-gate        membar  #Sync
18047c478bd9Sstevel@tonic-gate#else /* HUMMINGBIRD */
18057c478bd9Sstevel@tonic-gate	/*
18067c478bd9Sstevel@tonic-gate	 * UltraSPARC-IIe processor supports both 4-way set associative
18077c478bd9Sstevel@tonic-gate	 * and direct map E$. We need to reconfigure E$ to direct map
18087c478bd9Sstevel@tonic-gate	 * mode for data load/store before displacement flush. Also, we
18097c478bd9Sstevel@tonic-gate	 * need to flush all 4 sets of the E$ to ensure that the physaddr
18107c478bd9Sstevel@tonic-gate	 * has been flushed. Keep the interrupts disabled while flushing
18117c478bd9Sstevel@tonic-gate	 * E$ in this manner.
18127c478bd9Sstevel@tonic-gate	 *
18137c478bd9Sstevel@tonic-gate	 * For flushing a specific physical address, we start at the
18147c478bd9Sstevel@tonic-gate	 * aliased address and load at set-size stride, wrapping around
18157c478bd9Sstevel@tonic-gate	 * at 2*ecache-size boundary and skipping fault physical address.
18167c478bd9Sstevel@tonic-gate	 * It takes 10 loads to guarantee that the physical address has
18177c478bd9Sstevel@tonic-gate	 * been flushed.
18187c478bd9Sstevel@tonic-gate	 *
18197c478bd9Sstevel@tonic-gate	 * Usage:
18207c478bd9Sstevel@tonic-gate	 *	%o0	physaddr
18217c478bd9Sstevel@tonic-gate	 *	%o5	physaddr - ecache_flushaddr
18227c478bd9Sstevel@tonic-gate	 *	%g1	error enable register
18237c478bd9Sstevel@tonic-gate	 *	%g2	E$ set size
18247c478bd9Sstevel@tonic-gate	 *	%g3	E$ flush address range mask (i.e. 2 * E$ -1)
18257c478bd9Sstevel@tonic-gate	 *	%g4	UPA config (restored later)
18267c478bd9Sstevel@tonic-gate	 *	%g5	temp
18277c478bd9Sstevel@tonic-gate	 */
18287c478bd9Sstevel@tonic-gate
18297c478bd9Sstevel@tonic-gate	sethi	%hi(ecache_associativity), %g5
18307c478bd9Sstevel@tonic-gate	ld	[%g5 + %lo(ecache_associativity)], %g5
18317c478bd9Sstevel@tonic-gate	udivx	%o2, %g5, %g2	! set size (i.e. ecache_size/#sets)
18327c478bd9Sstevel@tonic-gate	xor	%o0, %o2, %o1	! calculate alias address
18337c478bd9Sstevel@tonic-gate	add	%o2, %o2, %g3	! 2 * ecachesize in case
18347c478bd9Sstevel@tonic-gate				! addr == ecache_flushaddr
18357c478bd9Sstevel@tonic-gate	sub	%g3, 1, %g3	! 2 * ecachesize -1 == mask
18367c478bd9Sstevel@tonic-gate	and	%o1, %g3, %o1	! and with xor'd address
18377c478bd9Sstevel@tonic-gate	sethi	%hi(ecache_flushaddr), %o3
18387c478bd9Sstevel@tonic-gate	ldx	[%o3 + %lo(ecache_flushaddr)], %o3
18397c478bd9Sstevel@tonic-gate
18407c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o4
18417c478bd9Sstevel@tonic-gate	andn	%o4, PSTATE_IE | PSTATE_AM, %o5
18427c478bd9Sstevel@tonic-gate	wrpr	%o5, %g0, %pstate	! clear IE, AM bits
18437c478bd9Sstevel@tonic-gate
18447c478bd9Sstevel@tonic-gate	! Place E$ in direct map mode for data access
18457c478bd9Sstevel@tonic-gate	or	%g0, 1, %g5
18467c478bd9Sstevel@tonic-gate	sllx	%g5, HB_UPA_DMAP_DATA_BIT, %g5
18477c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_UPA_CONFIG, %g4 ! current UPA config (restored later)
18487c478bd9Sstevel@tonic-gate	or	%g4, %g5, %g5
18497c478bd9Sstevel@tonic-gate	membar	#Sync
18507c478bd9Sstevel@tonic-gate	stxa	%g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access
18517c478bd9Sstevel@tonic-gate	membar	#Sync
18527c478bd9Sstevel@tonic-gate
18537c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g1
18547c478bd9Sstevel@tonic-gate	stxa	%g0, [%g0]ASI_ESTATE_ERR	! disable errors
18557c478bd9Sstevel@tonic-gate	membar	#Sync
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate	! Displace cache line from each set of E$ starting at the
18587c478bd9Sstevel@tonic-gate	! aliased address. at set-size stride, wrapping at 2*ecache_size
18597c478bd9Sstevel@tonic-gate	! and skipping load from physaddr. We need 10 loads to flush the
18607c478bd9Sstevel@tonic-gate	! physaddr from E$.
18617c478bd9Sstevel@tonic-gate	mov	HB_PHYS_FLUSH_CNT-1, %g5 ! #loads to flush physaddr
18627c478bd9Sstevel@tonic-gate	sub	%o0, %o3, %o5		! physaddr - ecache_flushaddr
18637c478bd9Sstevel@tonic-gate2:
18647c478bd9Sstevel@tonic-gate	ldxa	[%o1 + %o3]ASI_MEM, %g0	! load ecache_flushaddr + alias
18657c478bd9Sstevel@tonic-gate3:
18667c478bd9Sstevel@tonic-gate	add	%o1, %g2, %o1		! calculate offset in next set
18677c478bd9Sstevel@tonic-gate	and	%o1, %g3, %o1		! force offset within aliased range
18687c478bd9Sstevel@tonic-gate	cmp	%o1, %o5		! skip loads from physaddr
18697c478bd9Sstevel@tonic-gate	be,pn %ncc, 3b
18707c478bd9Sstevel@tonic-gate	  nop
18717c478bd9Sstevel@tonic-gate	brgz,pt	%g5, 2b
18727c478bd9Sstevel@tonic-gate	  dec	%g5
18737c478bd9Sstevel@tonic-gate
18747c478bd9Sstevel@tonic-gate	membar	#Sync
18757c478bd9Sstevel@tonic-gate	stxa	%g1, [%g0]ASI_ESTATE_ERR	! restore error enable
18767c478bd9Sstevel@tonic-gate        membar  #Sync
18777c478bd9Sstevel@tonic-gate
18787c478bd9Sstevel@tonic-gate	stxa	%g4, [%g0]ASI_UPA_CONFIG ! restore UPA config (DM bits)
18797c478bd9Sstevel@tonic-gate	membar	#Sync
18807c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD */
18817c478bd9Sstevel@tonic-gate        retl
18827c478bd9Sstevel@tonic-gate        wrpr    %g0, %o4, %pstate
18837c478bd9Sstevel@tonic-gate        SET_SIZE(flushecacheline)
18847c478bd9Sstevel@tonic-gate
18857c478bd9Sstevel@tonic-gate#endif	/* lint */
18867c478bd9Sstevel@tonic-gate
18877c478bd9Sstevel@tonic-gate#if defined(lint)
18887c478bd9Sstevel@tonic-gate/* ARGSUSED */
18897c478bd9Sstevel@tonic-gatevoid
18907c478bd9Sstevel@tonic-gateecache_scrubreq_tl1(uint64_t inum, uint64_t dummy)
18917c478bd9Sstevel@tonic-gate{
18927c478bd9Sstevel@tonic-gate}
18937c478bd9Sstevel@tonic-gate
18947c478bd9Sstevel@tonic-gate#else	/* lint */
18957c478bd9Sstevel@tonic-gate/*
18967c478bd9Sstevel@tonic-gate * ecache_scrubreq_tl1 is the crosstrap handler called at ecache_calls_a_sec Hz
18977c478bd9Sstevel@tonic-gate * from the clock CPU.  It atomically increments the outstanding request
18987c478bd9Sstevel@tonic-gate * counter and, if there was not already an outstanding request,
1899b0fc0e77Sgovinda * branches to setsoftint_tl1 to enqueue an intr_vec for the given inum.
19007c478bd9Sstevel@tonic-gate */
19017c478bd9Sstevel@tonic-gate
19027c478bd9Sstevel@tonic-gate	! Register usage:
19037c478bd9Sstevel@tonic-gate	!
19047c478bd9Sstevel@tonic-gate	! Arguments:
19057c478bd9Sstevel@tonic-gate	! %g1 - inum
19067c478bd9Sstevel@tonic-gate	!
19077c478bd9Sstevel@tonic-gate	! Internal:
19087c478bd9Sstevel@tonic-gate	! %g2, %g3, %g5 - scratch
19097c478bd9Sstevel@tonic-gate	! %g4 - ptr. to spitfire_scrub_misc ec_scrub_outstanding.
19107c478bd9Sstevel@tonic-gate	! %g6 - setsoftint_tl1 address
19117c478bd9Sstevel@tonic-gate
19127c478bd9Sstevel@tonic-gate	ENTRY_NP(ecache_scrubreq_tl1)
19137c478bd9Sstevel@tonic-gate	set	SFPR_SCRUB_MISC + EC_SCRUB_OUTSTANDING, %g2
19147c478bd9Sstevel@tonic-gate	GET_CPU_PRIVATE_PTR(%g2, %g4, %g5, 1f);
19157c478bd9Sstevel@tonic-gate	ld	[%g4], %g2		! cpu's ec_scrub_outstanding.
19167c478bd9Sstevel@tonic-gate	set	setsoftint_tl1, %g6
19177c478bd9Sstevel@tonic-gate	!
19187c478bd9Sstevel@tonic-gate	! no need to use atomic instructions for the following
19197c478bd9Sstevel@tonic-gate	! increment - we're at tl1
19207c478bd9Sstevel@tonic-gate	!
19217c478bd9Sstevel@tonic-gate	add	%g2, 0x1, %g3
1922b0fc0e77Sgovinda	brnz,pn	%g2, 1f			! no need to enqueue more intr_vec
19237c478bd9Sstevel@tonic-gate	  st	%g3, [%g4]		! delay - store incremented counter
1924b0fc0e77Sgovinda	jmp	%g6			! setsoftint_tl1(%g1) - queue intr_vec
19257c478bd9Sstevel@tonic-gate	  nop
19267c478bd9Sstevel@tonic-gate	! not reached
19277c478bd9Sstevel@tonic-gate1:
19287c478bd9Sstevel@tonic-gate	retry
19297c478bd9Sstevel@tonic-gate	SET_SIZE(ecache_scrubreq_tl1)
19307c478bd9Sstevel@tonic-gate
19317c478bd9Sstevel@tonic-gate#endif	/* lint */
19327c478bd9Sstevel@tonic-gate
19337c478bd9Sstevel@tonic-gate#if defined(lint)
19347c478bd9Sstevel@tonic-gate/*ARGSUSED*/
19357c478bd9Sstevel@tonic-gatevoid
19367c478bd9Sstevel@tonic-gatewrite_ec_tag_parity(uint32_t id)
19377c478bd9Sstevel@tonic-gate{}
19387c478bd9Sstevel@tonic-gate#else /* lint */
19397c478bd9Sstevel@tonic-gate
19407c478bd9Sstevel@tonic-gate	/*
19417c478bd9Sstevel@tonic-gate         * write_ec_tag_parity(), which zero's the ecache tag,
19427c478bd9Sstevel@tonic-gate         * marks the state as invalid and writes good parity to the tag.
19437c478bd9Sstevel@tonic-gate         * Input %o1= 32 bit E$ index
19447c478bd9Sstevel@tonic-gate         */
19457c478bd9Sstevel@tonic-gate        ENTRY(write_ec_tag_parity)
19467c478bd9Sstevel@tonic-gate        or      %g0, 1, %o4
19477c478bd9Sstevel@tonic-gate        sllx    %o4, 39, %o4                    ! set bit 40 for e$ tag access
19487c478bd9Sstevel@tonic-gate        or      %o0, %o4, %o4                 ! %o4 = ecache addr for tag write
19497c478bd9Sstevel@tonic-gate
19507c478bd9Sstevel@tonic-gate        rdpr    %pstate, %o5
19517c478bd9Sstevel@tonic-gate        andn    %o5, PSTATE_IE | PSTATE_AM, %o1
19527c478bd9Sstevel@tonic-gate        wrpr    %o1, %g0, %pstate               ! clear IE, AM bits
19537c478bd9Sstevel@tonic-gate
19547c478bd9Sstevel@tonic-gate        ldxa    [%g0]ASI_ESTATE_ERR, %g1
19557c478bd9Sstevel@tonic-gate        stxa    %g0, [%g0]ASI_ESTATE_ERR        ! Turn off Error enable
19567c478bd9Sstevel@tonic-gate        membar  #Sync
19577c478bd9Sstevel@tonic-gate
19587c478bd9Sstevel@tonic-gate        ba      1f
19597c478bd9Sstevel@tonic-gate         nop
19607c478bd9Sstevel@tonic-gate	/*
19617c478bd9Sstevel@tonic-gate         * Align on the ecache boundary in order to force
19627c478bd9Sstevel@tonic-gate         * ciritical code section onto the same ecache line.
19637c478bd9Sstevel@tonic-gate         */
19647c478bd9Sstevel@tonic-gate         .align 64
19657c478bd9Sstevel@tonic-gate
19667c478bd9Sstevel@tonic-gate1:
19677c478bd9Sstevel@tonic-gate        set     S_EC_PARITY, %o3         	! clear tag, state invalid
19687c478bd9Sstevel@tonic-gate        sllx    %o3, S_ECPAR_SHIFT, %o3   	! and with good tag parity
19697c478bd9Sstevel@tonic-gate        stxa    %o3, [%g0]ASI_EC_DIAG           ! update with the above info
19707c478bd9Sstevel@tonic-gate        stxa    %g0, [%o4]ASI_EC_W
19717c478bd9Sstevel@tonic-gate        membar  #Sync
19727c478bd9Sstevel@tonic-gate
19737c478bd9Sstevel@tonic-gate        stxa    %g1, [%g0]ASI_ESTATE_ERR        ! Turn error enable back on
19747c478bd9Sstevel@tonic-gate        membar  #Sync
19757c478bd9Sstevel@tonic-gate        retl
19767c478bd9Sstevel@tonic-gate        wrpr    %g0, %o5, %pstate
19777c478bd9Sstevel@tonic-gate        SET_SIZE(write_ec_tag_parity)
19787c478bd9Sstevel@tonic-gate
19797c478bd9Sstevel@tonic-gate#endif /* lint */
19807c478bd9Sstevel@tonic-gate
19817c478bd9Sstevel@tonic-gate#if defined(lint)
19827c478bd9Sstevel@tonic-gate/*ARGSUSED*/
19837c478bd9Sstevel@tonic-gatevoid
19847c478bd9Sstevel@tonic-gatewrite_hb_ec_tag_parity(uint32_t id)
19857c478bd9Sstevel@tonic-gate{}
19867c478bd9Sstevel@tonic-gate#else /* lint */
19877c478bd9Sstevel@tonic-gate
19887c478bd9Sstevel@tonic-gate	/*
19897c478bd9Sstevel@tonic-gate         * write_hb_ec_tag_parity(), which zero's the ecache tag,
19907c478bd9Sstevel@tonic-gate         * marks the state as invalid and writes good parity to the tag.
19917c478bd9Sstevel@tonic-gate         * Input %o1= 32 bit E$ index
19927c478bd9Sstevel@tonic-gate         */
19937c478bd9Sstevel@tonic-gate        ENTRY(write_hb_ec_tag_parity)
19947c478bd9Sstevel@tonic-gate        or      %g0, 1, %o4
19957c478bd9Sstevel@tonic-gate        sllx    %o4, 39, %o4                    ! set bit 40 for e$ tag access
19967c478bd9Sstevel@tonic-gate        or      %o0, %o4, %o4               ! %o4 = ecache addr for tag write
19977c478bd9Sstevel@tonic-gate
19987c478bd9Sstevel@tonic-gate        rdpr    %pstate, %o5
19997c478bd9Sstevel@tonic-gate        andn    %o5, PSTATE_IE | PSTATE_AM, %o1
20007c478bd9Sstevel@tonic-gate        wrpr    %o1, %g0, %pstate               ! clear IE, AM bits
20017c478bd9Sstevel@tonic-gate
20027c478bd9Sstevel@tonic-gate        ldxa    [%g0]ASI_ESTATE_ERR, %g1
20037c478bd9Sstevel@tonic-gate        stxa    %g0, [%g0]ASI_ESTATE_ERR        ! Turn off Error enable
20047c478bd9Sstevel@tonic-gate        membar  #Sync
20057c478bd9Sstevel@tonic-gate
20067c478bd9Sstevel@tonic-gate        ba      1f
20077c478bd9Sstevel@tonic-gate         nop
20087c478bd9Sstevel@tonic-gate	/*
20097c478bd9Sstevel@tonic-gate         * Align on the ecache boundary in order to force
20107c478bd9Sstevel@tonic-gate         * ciritical code section onto the same ecache line.
20117c478bd9Sstevel@tonic-gate         */
20127c478bd9Sstevel@tonic-gate         .align 64
20137c478bd9Sstevel@tonic-gate1:
20147c478bd9Sstevel@tonic-gate#ifdef HUMMINGBIRD
20157c478bd9Sstevel@tonic-gate        set     HB_EC_PARITY, %o3         	! clear tag, state invalid
20167c478bd9Sstevel@tonic-gate        sllx    %o3, HB_ECPAR_SHIFT, %o3   	! and with good tag parity
20177c478bd9Sstevel@tonic-gate#else /* !HUMMINGBIRD */
20187c478bd9Sstevel@tonic-gate        set     SB_EC_PARITY, %o3         	! clear tag, state invalid
20197c478bd9Sstevel@tonic-gate        sllx    %o3, SB_ECPAR_SHIFT, %o3   	! and with good tag parity
20207c478bd9Sstevel@tonic-gate#endif /* !HUMMINGBIRD */
20217c478bd9Sstevel@tonic-gate
20227c478bd9Sstevel@tonic-gate        stxa    %o3, [%g0]ASI_EC_DIAG           ! update with the above info
20237c478bd9Sstevel@tonic-gate        stxa    %g0, [%o4]ASI_EC_W
20247c478bd9Sstevel@tonic-gate        membar  #Sync
20257c478bd9Sstevel@tonic-gate
20267c478bd9Sstevel@tonic-gate        stxa    %g1, [%g0]ASI_ESTATE_ERR        ! Turn error enable back on
20277c478bd9Sstevel@tonic-gate        membar  #Sync
20287c478bd9Sstevel@tonic-gate        retl
20297c478bd9Sstevel@tonic-gate        wrpr    %g0, %o5, %pstate
20307c478bd9Sstevel@tonic-gate        SET_SIZE(write_hb_ec_tag_parity)
20317c478bd9Sstevel@tonic-gate
20327c478bd9Sstevel@tonic-gate#endif /* lint */
20337c478bd9Sstevel@tonic-gate
20347c478bd9Sstevel@tonic-gate#define	VIS_BLOCKSIZE		64
20357c478bd9Sstevel@tonic-gate
20367c478bd9Sstevel@tonic-gate#if defined(lint)
20377c478bd9Sstevel@tonic-gate
20387c478bd9Sstevel@tonic-gate/*ARGSUSED*/
20397c478bd9Sstevel@tonic-gateint
20407c478bd9Sstevel@tonic-gatedtrace_blksuword32(uintptr_t addr, uint32_t *data, int tryagain)
20417c478bd9Sstevel@tonic-gate{ return (0); }
20427c478bd9Sstevel@tonic-gate
20437c478bd9Sstevel@tonic-gate#else
20447c478bd9Sstevel@tonic-gate
20457c478bd9Sstevel@tonic-gate	ENTRY(dtrace_blksuword32)
20467c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME + 4), %sp
20477c478bd9Sstevel@tonic-gate
20487c478bd9Sstevel@tonic-gate	rdpr	%pstate, %l1
20497c478bd9Sstevel@tonic-gate	andn	%l1, PSTATE_IE, %l2		! disable interrupts to
20507c478bd9Sstevel@tonic-gate	wrpr	%g0, %l2, %pstate		! protect our FPU diddling
20517c478bd9Sstevel@tonic-gate
20527c478bd9Sstevel@tonic-gate	rd	%fprs, %l0
20537c478bd9Sstevel@tonic-gate	andcc	%l0, FPRS_FEF, %g0
20547c478bd9Sstevel@tonic-gate	bz,a,pt	%xcc, 1f			! if the fpu is disabled
20557c478bd9Sstevel@tonic-gate	wr	%g0, FPRS_FEF, %fprs		! ... enable the fpu
20567c478bd9Sstevel@tonic-gate
20577c478bd9Sstevel@tonic-gate	st	%f0, [%fp + STACK_BIAS - 4]	! save %f0 to the stack
20587c478bd9Sstevel@tonic-gate1:
20597c478bd9Sstevel@tonic-gate	set	0f, %l5
20607c478bd9Sstevel@tonic-gate        /*
20617c478bd9Sstevel@tonic-gate         * We're about to write a block full or either total garbage
20627c478bd9Sstevel@tonic-gate         * (not kernel data, don't worry) or user floating-point data
20637c478bd9Sstevel@tonic-gate         * (so it only _looks_ like garbage).
20647c478bd9Sstevel@tonic-gate         */
20657c478bd9Sstevel@tonic-gate	ld	[%i1], %f0			! modify the block
20667c478bd9Sstevel@tonic-gate	membar	#Sync
20677c478bd9Sstevel@tonic-gate	stn	%l5, [THREAD_REG + T_LOFAULT]	! set up the lofault handler
20687c478bd9Sstevel@tonic-gate	stda	%d0, [%i0]ASI_BLK_COMMIT_S	! store the modified block
20697c478bd9Sstevel@tonic-gate	membar	#Sync
20707c478bd9Sstevel@tonic-gate	stn	%g0, [THREAD_REG + T_LOFAULT]	! remove the lofault handler
20717c478bd9Sstevel@tonic-gate
20727c478bd9Sstevel@tonic-gate	bz,a,pt	%xcc, 1f
20737c478bd9Sstevel@tonic-gate	wr	%g0, %l0, %fprs			! restore %fprs
20747c478bd9Sstevel@tonic-gate
20757c478bd9Sstevel@tonic-gate	ld	[%fp + STACK_BIAS - 4], %f0	! restore %f0
20767c478bd9Sstevel@tonic-gate1:
20777c478bd9Sstevel@tonic-gate
20787c478bd9Sstevel@tonic-gate	wrpr	%g0, %l1, %pstate		! restore interrupts
20797c478bd9Sstevel@tonic-gate
20807c478bd9Sstevel@tonic-gate	ret
20817c478bd9Sstevel@tonic-gate	restore	%g0, %g0, %o0
20827c478bd9Sstevel@tonic-gate
20837c478bd9Sstevel@tonic-gate0:
20847c478bd9Sstevel@tonic-gate	membar	#Sync
20857c478bd9Sstevel@tonic-gate	stn	%g0, [THREAD_REG + T_LOFAULT]	! remove the lofault handler
20867c478bd9Sstevel@tonic-gate
20877c478bd9Sstevel@tonic-gate	bz,a,pt	%xcc, 1f
20887c478bd9Sstevel@tonic-gate	wr	%g0, %l0, %fprs			! restore %fprs
20897c478bd9Sstevel@tonic-gate
20907c478bd9Sstevel@tonic-gate	ld	[%fp + STACK_BIAS - 4], %f0	! restore %f0
20917c478bd9Sstevel@tonic-gate1:
20927c478bd9Sstevel@tonic-gate
20937c478bd9Sstevel@tonic-gate	wrpr	%g0, %l1, %pstate		! restore interrupts
20947c478bd9Sstevel@tonic-gate
20957c478bd9Sstevel@tonic-gate	/*
20967c478bd9Sstevel@tonic-gate	 * If tryagain is set (%i2) we tail-call dtrace_blksuword32_err()
20977c478bd9Sstevel@tonic-gate	 * which deals with watchpoints. Otherwise, just return -1.
20987c478bd9Sstevel@tonic-gate	 */
20997c478bd9Sstevel@tonic-gate	brnz,pt	%i2, 1f
21007c478bd9Sstevel@tonic-gate	nop
21017c478bd9Sstevel@tonic-gate	ret
21027c478bd9Sstevel@tonic-gate	restore	%g0, -1, %o0
21037c478bd9Sstevel@tonic-gate1:
21047c478bd9Sstevel@tonic-gate	call	dtrace_blksuword32_err
21057c478bd9Sstevel@tonic-gate	restore
21067c478bd9Sstevel@tonic-gate
21077c478bd9Sstevel@tonic-gate	SET_SIZE(dtrace_blksuword32)
21087c478bd9Sstevel@tonic-gate
21097c478bd9Sstevel@tonic-gate#endif /* lint */
2110