xref: /titanic_51/usr/src/uts/sun4u/cpu/us3_cheetahplus_asm.s (revision 9ed9f144ac29a6173508aefa548ecef987c91231)
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
57bebe46cSjc25722 * Common Development and Distribution License (the "License").
67bebe46cSjc25722 * 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/*
227bebe46cSjc25722 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate *
257c478bd9Sstevel@tonic-gate * Assembly code support for the Cheetah+ module
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate#if !defined(lint)
317c478bd9Sstevel@tonic-gate#include "assym.h"
327c478bd9Sstevel@tonic-gate#endif	/* lint */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
357c478bd9Sstevel@tonic-gate#include <sys/mmu.h>
367c478bd9Sstevel@tonic-gate#include <vm/hat_sfmmu.h>
377c478bd9Sstevel@tonic-gate#include <sys/machparam.h>
387c478bd9Sstevel@tonic-gate#include <sys/machcpuvar.h>
397c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
407c478bd9Sstevel@tonic-gate#include <sys/machtrap.h>
417c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
427c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
437c478bd9Sstevel@tonic-gate#include <sys/trap.h>
447c478bd9Sstevel@tonic-gate#include <sys/cheetahregs.h>
457c478bd9Sstevel@tonic-gate#include <sys/us3_module.h>
467c478bd9Sstevel@tonic-gate#include <sys/xc_impl.h>
477c478bd9Sstevel@tonic-gate#include <sys/intreg.h>
487c478bd9Sstevel@tonic-gate#include <sys/async.h>
497c478bd9Sstevel@tonic-gate#include <sys/clock.h>
507c478bd9Sstevel@tonic-gate#include <sys/cheetahasm.h>
517bebe46cSjc25722#include <sys/cmpregs.h>
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
547c478bd9Sstevel@tonic-gate#include <sys/traptrace.h>
557c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */
567c478bd9Sstevel@tonic-gate
577bebe46cSjc25722
587c478bd9Sstevel@tonic-gate#if !defined(lint)
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate/* BEGIN CSTYLED */
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate/*
637c478bd9Sstevel@tonic-gate * Cheetah+ version to reflush an Ecache line by index.
647c478bd9Sstevel@tonic-gate *
657c478bd9Sstevel@tonic-gate * By default we assume the Ecache is 2-way so we flush both
667c478bd9Sstevel@tonic-gate * ways. Even if the cache is direct-mapped no harm will come
677c478bd9Sstevel@tonic-gate * from performing the flush twice, apart from perhaps a performance
687c478bd9Sstevel@tonic-gate * penalty.
697c478bd9Sstevel@tonic-gate *
707c478bd9Sstevel@tonic-gate * XXX - scr2 not used.
717c478bd9Sstevel@tonic-gate */
727c478bd9Sstevel@tonic-gate#define	ECACHE_REFLUSH_LINE(ec_set_size, index, scr2)			\
737c478bd9Sstevel@tonic-gate	ldxa	[index]ASI_EC_DIAG, %g0;				\
747c478bd9Sstevel@tonic-gate	ldxa	[index + ec_set_size]ASI_EC_DIAG, %g0;
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate/*
777c478bd9Sstevel@tonic-gate * Cheetah+ version of ecache_flush_line.  Uses Cheetah+ Ecache Displacement
787c478bd9Sstevel@tonic-gate * Flush feature.
797c478bd9Sstevel@tonic-gate */
807c478bd9Sstevel@tonic-gate#define	ECACHE_FLUSH_LINE(physaddr, ec_set_size, scr1, scr2)		\
817c478bd9Sstevel@tonic-gate	sub	ec_set_size, 1, scr1;					\
827c478bd9Sstevel@tonic-gate	and	physaddr, scr1, scr1;					\
837c478bd9Sstevel@tonic-gate	set	CHP_ECACHE_IDX_DISP_FLUSH, scr2;			\
847c478bd9Sstevel@tonic-gate	or	scr2, scr1, scr1;					\
857c478bd9Sstevel@tonic-gate	ECACHE_REFLUSH_LINE(ec_set_size, scr1, scr2)
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate/* END CSTYLED */
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate/*
907c478bd9Sstevel@tonic-gate * Panther version to reflush a line from both the L2 cache and L3
917c478bd9Sstevel@tonic-gate * cache by the respective indexes. Flushes all ways of the line from
927c478bd9Sstevel@tonic-gate * each cache.
937c478bd9Sstevel@tonic-gate *
947c478bd9Sstevel@tonic-gate * l2_index	Index into the L2$ of the line to be flushed. This
957c478bd9Sstevel@tonic-gate *		register will not be modified by this routine.
967c478bd9Sstevel@tonic-gate * l3_index	Index into the L3$ of the line to be flushed. This
977c478bd9Sstevel@tonic-gate *		register will not be modified by this routine.
987c478bd9Sstevel@tonic-gate * scr2		scratch register.
997c478bd9Sstevel@tonic-gate * scr3		scratch register.
1007c478bd9Sstevel@tonic-gate *
1017c478bd9Sstevel@tonic-gate */
1027c478bd9Sstevel@tonic-gate#define	PN_ECACHE_REFLUSH_LINE(l2_index, l3_index, scr2, scr3)		\
1037c478bd9Sstevel@tonic-gate	set	PN_L2_MAX_SET, scr2;					\
1047c478bd9Sstevel@tonic-gate	set	PN_L2_SET_SIZE, scr3;					\
1057c478bd9Sstevel@tonic-gate1:									\
1067c478bd9Sstevel@tonic-gate	ldxa	[l2_index + scr2]ASI_L2_TAG, %g0;			\
1077c478bd9Sstevel@tonic-gate	cmp	scr2, %g0;						\
1087c478bd9Sstevel@tonic-gate	bg,a	1b;							\
1097c478bd9Sstevel@tonic-gate	  sub	scr2, scr3, scr2;					\
1107bebe46cSjc25722	mov	6, scr2;						\
1117bebe46cSjc257227:									\
1127bebe46cSjc25722	cmp	scr2, %g0;						\
1137bebe46cSjc25722	bg,a	7b;							\
1147bebe46cSjc25722	  sub	scr2, 1, scr2;						\
1157c478bd9Sstevel@tonic-gate	set	PN_L3_MAX_SET, scr2;					\
1167c478bd9Sstevel@tonic-gate	set	PN_L3_SET_SIZE, scr3;					\
1177c478bd9Sstevel@tonic-gate2:									\
1187c478bd9Sstevel@tonic-gate	ldxa	[l3_index + scr2]ASI_EC_DIAG, %g0;			\
1197c478bd9Sstevel@tonic-gate	cmp	scr2, %g0;						\
1207c478bd9Sstevel@tonic-gate	bg,a	2b;							\
1217c478bd9Sstevel@tonic-gate	  sub	scr2, scr3, scr2;
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate/*
1247c478bd9Sstevel@tonic-gate * Panther version of ecache_flush_line. Flushes the line corresponding
1257c478bd9Sstevel@tonic-gate * to physaddr from both the L2 cache and the L3 cache.
1267c478bd9Sstevel@tonic-gate *
1277c478bd9Sstevel@tonic-gate * physaddr	Input: Physical address to flush.
1287c478bd9Sstevel@tonic-gate *              Output: Physical address to flush (preserved).
1297c478bd9Sstevel@tonic-gate * l2_idx_out	Input: scratch register.
1307c478bd9Sstevel@tonic-gate *              Output: Index into the L2$ of the line to be flushed.
1317c478bd9Sstevel@tonic-gate * l3_idx_out	Input: scratch register.
1327c478bd9Sstevel@tonic-gate *              Output: Index into the L3$ of the line to be flushed.
1337c478bd9Sstevel@tonic-gate * scr3		scratch register.
1347c478bd9Sstevel@tonic-gate * scr4		scratch register.
1357c478bd9Sstevel@tonic-gate *
1367c478bd9Sstevel@tonic-gate */
1377c478bd9Sstevel@tonic-gate#define	PN_ECACHE_FLUSH_LINE(physaddr, l2_idx_out, l3_idx_out, scr3, scr4)	\
1387c478bd9Sstevel@tonic-gate	set	PN_L3_SET_SIZE, l2_idx_out;					\
1397c478bd9Sstevel@tonic-gate	sub	l2_idx_out, 1, l2_idx_out;					\
1407c478bd9Sstevel@tonic-gate	and	physaddr, l2_idx_out, l3_idx_out;				\
1417c478bd9Sstevel@tonic-gate	set	PN_L3_IDX_DISP_FLUSH, l2_idx_out;				\
1427c478bd9Sstevel@tonic-gate	or	l2_idx_out, l3_idx_out, l3_idx_out;				\
1437c478bd9Sstevel@tonic-gate	set	PN_L2_SET_SIZE, l2_idx_out;					\
1447c478bd9Sstevel@tonic-gate	sub	l2_idx_out, 1, l2_idx_out;					\
1457c478bd9Sstevel@tonic-gate	and	physaddr, l2_idx_out, l2_idx_out;				\
1467c478bd9Sstevel@tonic-gate	set	PN_L2_IDX_DISP_FLUSH, scr3;					\
1477c478bd9Sstevel@tonic-gate	or	l2_idx_out, scr3, l2_idx_out;					\
1487c478bd9Sstevel@tonic-gate	PN_ECACHE_REFLUSH_LINE(l2_idx_out, l3_idx_out, scr3, scr4)
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate#endif	/* !lint */
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate/*
1537c478bd9Sstevel@tonic-gate * Fast ECC error at TL>0 handler
1547c478bd9Sstevel@tonic-gate * We get here via trap 70 at TL>0->Software trap 0 at TL>0.  We enter
1557c478bd9Sstevel@tonic-gate * this routine with %g1 and %g2 already saved in %tpc, %tnpc and %tstate.
1567c478bd9Sstevel@tonic-gate * For a complete description of the Fast ECC at TL>0 handling see the
1577c478bd9Sstevel@tonic-gate * comment block "Cheetah/Cheetah+ Fast ECC at TL>0 trap strategy" in
1587c478bd9Sstevel@tonic-gate * us3_common_asm.s
1597c478bd9Sstevel@tonic-gate */
1607c478bd9Sstevel@tonic-gate#if defined(lint)
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gatevoid
1637c478bd9Sstevel@tonic-gatefast_ecc_tl1_err(void)
1647c478bd9Sstevel@tonic-gate{}
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate#else	/* lint */
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate	.section ".text"
1697c478bd9Sstevel@tonic-gate	.align	64
1707c478bd9Sstevel@tonic-gate	ENTRY_NP(fast_ecc_tl1_err)
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate	/*
1737c478bd9Sstevel@tonic-gate	 * This macro turns off the D$/I$ if they are on and saves their
1747c478bd9Sstevel@tonic-gate	 * original state in ch_err_tl1_tmp, saves all the %g registers in the
1757c478bd9Sstevel@tonic-gate	 * ch_err_tl1_data structure, updates the ch_err_tl1_flags and saves
1767c478bd9Sstevel@tonic-gate	 * the %tpc in ch_err_tl1_tpc.  At the end of this macro, %g1 will
1777c478bd9Sstevel@tonic-gate	 * point to the ch_err_tl1_data structure and the original D$/I$ state
1787c478bd9Sstevel@tonic-gate	 * will be saved in ch_err_tl1_tmp.  All %g registers except for %g1
1797c478bd9Sstevel@tonic-gate	 * will be available.
1807c478bd9Sstevel@tonic-gate	 */
1817c478bd9Sstevel@tonic-gate	CH_ERR_TL1_FECC_ENTER;
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate	/*
1847c478bd9Sstevel@tonic-gate	 * Get the diagnostic logout data.  %g4 must be initialized to
1857c478bd9Sstevel@tonic-gate	 * current CEEN state, %g5 must point to logout structure in
1867c478bd9Sstevel@tonic-gate	 * ch_err_tl1_data_t.  %g3 will contain the nesting count upon
1877c478bd9Sstevel@tonic-gate	 * return.
1887c478bd9Sstevel@tonic-gate	 */
1897c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g4
1907c478bd9Sstevel@tonic-gate	and	%g4, EN_REG_CEEN, %g4
1917c478bd9Sstevel@tonic-gate	add	%g1, CH_ERR_TL1_LOGOUT, %g5
1927c478bd9Sstevel@tonic-gate	DO_TL1_CPU_LOGOUT(%g3, %g2, %g4, %g5, %g6, %g3, %g4)
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate	/*
1957c478bd9Sstevel@tonic-gate	 * If the logout nesting count is exceeded, we're probably
1967c478bd9Sstevel@tonic-gate	 * not making any progress, try to panic instead.
1977c478bd9Sstevel@tonic-gate	 */
1987c478bd9Sstevel@tonic-gate	cmp	%g3, CLO_NESTING_MAX
1997c478bd9Sstevel@tonic-gate	bge	fecc_tl1_err
2007c478bd9Sstevel@tonic-gate	  nop
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate	/*
2037c478bd9Sstevel@tonic-gate	 * Save the current CEEN and NCEEN state in %g7 and turn them off
2047c478bd9Sstevel@tonic-gate	 * before flushing the Ecache.
2057c478bd9Sstevel@tonic-gate	 */
2067c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g7
2077c478bd9Sstevel@tonic-gate	andn	%g7, EN_REG_CEEN | EN_REG_NCEEN, %g5
2087c478bd9Sstevel@tonic-gate	stxa	%g5, [%g0]ASI_ESTATE_ERR
2097c478bd9Sstevel@tonic-gate	membar	#Sync
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate	/*
2127c478bd9Sstevel@tonic-gate	 * Flush the Ecache, using the largest possible cache size with the
2137c478bd9Sstevel@tonic-gate	 * smallest possible line size since we can't get the actual sizes
2147c478bd9Sstevel@tonic-gate	 * from the cpu_node due to DTLB misses.
2157c478bd9Sstevel@tonic-gate	 */
2167c478bd9Sstevel@tonic-gate	PN_L2_FLUSHALL(%g3, %g4, %g5)
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate	set	CH_ECACHE_MAX_SIZE, %g4
2197c478bd9Sstevel@tonic-gate	set	CH_ECACHE_MIN_LSIZE, %g5
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate	GET_CPU_IMPL(%g6)
2227c478bd9Sstevel@tonic-gate	cmp	%g6, PANTHER_IMPL
2237c478bd9Sstevel@tonic-gate	bne	%xcc, 2f
2247c478bd9Sstevel@tonic-gate	  nop
2257c478bd9Sstevel@tonic-gate	set	PN_L3_SIZE, %g4
2267c478bd9Sstevel@tonic-gate2:
2277c478bd9Sstevel@tonic-gate	mov	%g6, %g3
2287c478bd9Sstevel@tonic-gate	CHP_ECACHE_FLUSHALL(%g4, %g5, %g3)
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate	/*
2317c478bd9Sstevel@tonic-gate	 * Restore CEEN and NCEEN to the previous state.
2327c478bd9Sstevel@tonic-gate	 */
2337c478bd9Sstevel@tonic-gate	stxa	%g7, [%g0]ASI_ESTATE_ERR
2347c478bd9Sstevel@tonic-gate	membar	#Sync
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate	/*
2377c478bd9Sstevel@tonic-gate	 * If we turned off the D$, then flush it and turn it back on.
2387c478bd9Sstevel@tonic-gate	 */
2397c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_TMP]%asi, %g3
2407c478bd9Sstevel@tonic-gate	andcc	%g3, CH_ERR_TSTATE_DC_ON, %g0
2417c478bd9Sstevel@tonic-gate	bz	%xcc, 3f
2427c478bd9Sstevel@tonic-gate	  nop
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate	/*
2457c478bd9Sstevel@tonic-gate	 * Flush the D$.
2467c478bd9Sstevel@tonic-gate	 */
2477c478bd9Sstevel@tonic-gate	ASM_LD(%g4, dcache_size)
2487c478bd9Sstevel@tonic-gate	ASM_LD(%g5, dcache_linesize)
2497c478bd9Sstevel@tonic-gate	CH_DCACHE_FLUSHALL(%g4, %g5, %g6)
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate	/*
2527c478bd9Sstevel@tonic-gate	 * Turn the D$ back on.
2537c478bd9Sstevel@tonic-gate	 */
2547c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_DCU, %g3
2557c478bd9Sstevel@tonic-gate	or	%g3, DCU_DC, %g3
2567c478bd9Sstevel@tonic-gate	stxa	%g3, [%g0]ASI_DCU
2577c478bd9Sstevel@tonic-gate	membar	#Sync
2587c478bd9Sstevel@tonic-gate3:
2597c478bd9Sstevel@tonic-gate	/*
2607c478bd9Sstevel@tonic-gate	 * If we turned off the I$, then flush it and turn it back on.
2617c478bd9Sstevel@tonic-gate	 */
2627c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_TMP]%asi, %g3
2637c478bd9Sstevel@tonic-gate	andcc	%g3, CH_ERR_TSTATE_IC_ON, %g0
2647c478bd9Sstevel@tonic-gate	bz	%xcc, 4f
2657c478bd9Sstevel@tonic-gate	  nop
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate	/*
2687c478bd9Sstevel@tonic-gate	 * Flush the I$.  Panther has different I$ parameters, and we
2697c478bd9Sstevel@tonic-gate	 * can't access the logout I$ params without possibly generating
2707c478bd9Sstevel@tonic-gate	 * a MMU miss.
2717c478bd9Sstevel@tonic-gate	 */
2727c478bd9Sstevel@tonic-gate	GET_CPU_IMPL(%g6)
2737c478bd9Sstevel@tonic-gate	set	PN_ICACHE_SIZE, %g3
2747c478bd9Sstevel@tonic-gate	set	CH_ICACHE_SIZE, %g4
2757c478bd9Sstevel@tonic-gate	mov	CH_ICACHE_LSIZE, %g5
2767c478bd9Sstevel@tonic-gate	cmp	%g6, PANTHER_IMPL
2777c478bd9Sstevel@tonic-gate	movz	%xcc, %g3, %g4
2787c478bd9Sstevel@tonic-gate	movz	%xcc, PN_ICACHE_LSIZE, %g5
2797c478bd9Sstevel@tonic-gate	CH_ICACHE_FLUSHALL(%g4, %g5, %g6, %g3)
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate	/*
2827c478bd9Sstevel@tonic-gate	 * Turn the I$ back on.  Changing DCU_IC requires flush.
2837c478bd9Sstevel@tonic-gate	 */
2847c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_DCU, %g3
2857c478bd9Sstevel@tonic-gate	or	%g3, DCU_IC, %g3
2867c478bd9Sstevel@tonic-gate	stxa	%g3, [%g0]ASI_DCU
2877c478bd9Sstevel@tonic-gate	flush	%g0
2887c478bd9Sstevel@tonic-gate4:
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
2917c478bd9Sstevel@tonic-gate	/*
2927c478bd9Sstevel@tonic-gate	 * Get current trap trace entry physical pointer.
2937c478bd9Sstevel@tonic-gate	 */
2947c478bd9Sstevel@tonic-gate	CPU_INDEX(%g6, %g5)
2957c478bd9Sstevel@tonic-gate	sll	%g6, TRAPTR_SIZE_SHIFT, %g6
2967c478bd9Sstevel@tonic-gate	set	trap_trace_ctl, %g5
2977c478bd9Sstevel@tonic-gate	add	%g6, %g5, %g6
2987c478bd9Sstevel@tonic-gate	ld	[%g6 + TRAPTR_LIMIT], %g5
2997c478bd9Sstevel@tonic-gate	tst	%g5
3007c478bd9Sstevel@tonic-gate	be	%icc, skip_traptrace
3017c478bd9Sstevel@tonic-gate	  nop
3027c478bd9Sstevel@tonic-gate	ldx	[%g6 + TRAPTR_PBASE], %g5
3037c478bd9Sstevel@tonic-gate	ld	[%g6 + TRAPTR_OFFSET], %g4
3047c478bd9Sstevel@tonic-gate	add	%g5, %g4, %g5
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate	/*
3077c478bd9Sstevel@tonic-gate	 * Create trap trace entry.
3087c478bd9Sstevel@tonic-gate	 */
3097c478bd9Sstevel@tonic-gate	rd	%asi, %g7
3107c478bd9Sstevel@tonic-gate	wr	%g0, TRAPTR_ASI, %asi
3117c478bd9Sstevel@tonic-gate	rd	STICK, %g4
3127c478bd9Sstevel@tonic-gate	stxa	%g4, [%g5 + TRAP_ENT_TICK]%asi
3137c478bd9Sstevel@tonic-gate	rdpr	%tl, %g4
3147c478bd9Sstevel@tonic-gate	stha	%g4, [%g5 + TRAP_ENT_TL]%asi
3157c478bd9Sstevel@tonic-gate	rdpr	%tt, %g4
3167c478bd9Sstevel@tonic-gate	stha	%g4, [%g5 + TRAP_ENT_TT]%asi
3177c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g4
3187c478bd9Sstevel@tonic-gate	stna	%g4, [%g5 + TRAP_ENT_TPC]%asi
3197c478bd9Sstevel@tonic-gate	rdpr	%tstate, %g4
3207c478bd9Sstevel@tonic-gate	stxa	%g4, [%g5 + TRAP_ENT_TSTATE]%asi
3217c478bd9Sstevel@tonic-gate	stna	%sp, [%g5 + TRAP_ENT_SP]%asi
3227c478bd9Sstevel@tonic-gate	stna	%g0, [%g5 + TRAP_ENT_TR]%asi
3237c478bd9Sstevel@tonic-gate	wr	%g0, %g7, %asi
3247c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_SDW_AFAR]%asi, %g3
3257c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_SDW_AFSR]%asi, %g4
3267c478bd9Sstevel@tonic-gate	wr	%g0, TRAPTR_ASI, %asi
3277c478bd9Sstevel@tonic-gate	stna	%g3, [%g5 + TRAP_ENT_F1]%asi
3287c478bd9Sstevel@tonic-gate	stna	%g4, [%g5 + TRAP_ENT_F2]%asi
3297c478bd9Sstevel@tonic-gate	wr	%g0, %g7, %asi
3307c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_AFAR]%asi, %g3
3317c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_AFSR]%asi, %g4
3327c478bd9Sstevel@tonic-gate	wr	%g0, TRAPTR_ASI, %asi
3337c478bd9Sstevel@tonic-gate	stna	%g3, [%g5 + TRAP_ENT_F3]%asi
3347c478bd9Sstevel@tonic-gate	stna	%g4, [%g5 + TRAP_ENT_F4]%asi
3357c478bd9Sstevel@tonic-gate	wr	%g0, %g7, %asi
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate	/*
3387c478bd9Sstevel@tonic-gate	 * Advance trap trace pointer.
3397c478bd9Sstevel@tonic-gate	 */
3407c478bd9Sstevel@tonic-gate	ld	[%g6 + TRAPTR_OFFSET], %g5
3417c478bd9Sstevel@tonic-gate	ld	[%g6 + TRAPTR_LIMIT], %g4
3427c478bd9Sstevel@tonic-gate	st	%g5, [%g6 + TRAPTR_LAST_OFFSET]
3437c478bd9Sstevel@tonic-gate	add	%g5, TRAP_ENT_SIZE, %g5
3447c478bd9Sstevel@tonic-gate	sub	%g4, TRAP_ENT_SIZE, %g4
3457c478bd9Sstevel@tonic-gate	cmp	%g5, %g4
3467c478bd9Sstevel@tonic-gate	movge	%icc, 0, %g5
3477c478bd9Sstevel@tonic-gate	st	%g5, [%g6 + TRAPTR_OFFSET]
3487c478bd9Sstevel@tonic-gateskip_traptrace:
3497c478bd9Sstevel@tonic-gate#endif	/* TRAPTRACE */
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate	/*
3527c478bd9Sstevel@tonic-gate	 * If nesting count is not zero, skip all the AFSR/AFAR
3537c478bd9Sstevel@tonic-gate	 * handling and just do the necessary cache-flushing.
3547c478bd9Sstevel@tonic-gate	 */
3557c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_NEST_CNT]%asi, %g2
3567c478bd9Sstevel@tonic-gate	brnz	%g2, 6f
3577c478bd9Sstevel@tonic-gate	  nop
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate	/*
3607c478bd9Sstevel@tonic-gate	 * If a UCU or L3_UCU followed by a WDU has occurred go ahead
3617c478bd9Sstevel@tonic-gate	 * and panic since a UE will occur (on the retry) before the
362*9ed9f144Skwmc	 * UCU and WDU messages are enqueued.  On a Panther processor,
363*9ed9f144Skwmc	 * we need to also see an L3_WDU before panicking.  Note that
364*9ed9f144Skwmc	 * we avoid accessing the _EXT ASIs if not on a Panther.
3657c478bd9Sstevel@tonic-gate	 */
3667c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_SDW_AFSR]%asi, %g3
3677c478bd9Sstevel@tonic-gate	set	1, %g4
3687c478bd9Sstevel@tonic-gate	sllx	%g4, C_AFSR_UCU_SHIFT, %g4
3697c478bd9Sstevel@tonic-gate	btst	%g4, %g3		! UCU in original shadow AFSR?
3707c478bd9Sstevel@tonic-gate	bnz	%xcc, 5f
371*9ed9f144Skwmc	  nop
372*9ed9f144Skwmc	GET_CPU_IMPL(%g6)
373*9ed9f144Skwmc	cmp	%g6, PANTHER_IMPL
374*9ed9f144Skwmc	bne	%xcc, 6f		! not Panther, no UCU, skip the rest
375*9ed9f144Skwmc	  nop
3767c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_SDW_AFSR_EXT]%asi, %g3
377*9ed9f144Skwmc	btst	C_AFSR_L3_UCU, %g3	! L3_UCU in original shadow AFSR_EXT?
378*9ed9f144Skwmc	bz	%xcc, 6f		! neither UCU nor L3_UCU was seen
3797c478bd9Sstevel@tonic-gate	  nop
3807c478bd9Sstevel@tonic-gate5:
3817c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_AFSR]%asi, %g4	! original AFSR
3827c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %g3	! current AFSR
3837c478bd9Sstevel@tonic-gate	or	%g3, %g4, %g3		! %g3 = original + current AFSR
3847c478bd9Sstevel@tonic-gate	set	1, %g4
3857c478bd9Sstevel@tonic-gate	sllx	%g4, C_AFSR_WDU_SHIFT, %g4
3867c478bd9Sstevel@tonic-gate	btst	%g4, %g3		! WDU in original or current AFSR?
387*9ed9f144Skwmc	bz	%xcc, 6f                ! no WDU, skip remaining tests
3887c478bd9Sstevel@tonic-gate	  nop
389*9ed9f144Skwmc	GET_CPU_IMPL(%g6)
390*9ed9f144Skwmc	cmp	%g6, PANTHER_IMPL
391*9ed9f144Skwmc	bne	%xcc, fecc_tl1_err	! if not Panther, panic (saw UCU, WDU)
392*9ed9f144Skwmc	  nop
393*9ed9f144Skwmc	ldxa	[%g1 + CH_ERR_TL1_SDW_AFSR_EXT]%asi, %g4 ! original AFSR_EXT
394*9ed9f144Skwmc	set	ASI_AFSR_EXT_VA, %g6	! ASI of current AFSR_EXT
395*9ed9f144Skwmc	ldxa	[%g6]ASI_AFSR, %g3	! value of current AFSR_EXT
396*9ed9f144Skwmc	or	%g3, %g4, %g3		! %g3 = original + current AFSR_EXT
397*9ed9f144Skwmc	btst	C_AFSR_L3_WDU, %g3	! L3_WDU in original or current AFSR?
398*9ed9f144Skwmc	bnz	%xcc, fecc_tl1_err	! panic (saw L3_WDU and UCU or L3_UCU)
399*9ed9f144Skwmc	  nop
4007c478bd9Sstevel@tonic-gate6:
4017c478bd9Sstevel@tonic-gate	/*
4027c478bd9Sstevel@tonic-gate	 * We fall into this macro if we've successfully logged the error in
4037c478bd9Sstevel@tonic-gate	 * the ch_err_tl1_data structure and want the PIL15 softint to pick
4047c478bd9Sstevel@tonic-gate	 * it up and log it.  %g1 must point to the ch_err_tl1_data structure.
4057c478bd9Sstevel@tonic-gate	 * Restores the %g registers and issues retry.
4067c478bd9Sstevel@tonic-gate	 */
4077c478bd9Sstevel@tonic-gate	CH_ERR_TL1_EXIT;
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate	/*
4107c478bd9Sstevel@tonic-gate	 * Establish panic exit label.
4117c478bd9Sstevel@tonic-gate	 */
4127c478bd9Sstevel@tonic-gate	CH_ERR_TL1_PANIC_EXIT(fecc_tl1_err);
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate	SET_SIZE(fast_ecc_tl1_err)
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate#endif	/* lint */
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate#if defined(lint)
4207c478bd9Sstevel@tonic-gate/*
4217c478bd9Sstevel@tonic-gate * scrubphys - Pass in the aligned physical memory address
4227c478bd9Sstevel@tonic-gate * that you want to scrub, along with the ecache set size.
4237c478bd9Sstevel@tonic-gate *
4247c478bd9Sstevel@tonic-gate *	1) Displacement flush the E$ line corresponding to %addr.
4257c478bd9Sstevel@tonic-gate *	   The first ldxa guarantees that the %addr is no longer in
4267c478bd9Sstevel@tonic-gate *	   M, O, or E (goes to I or S (if instruction fetch also happens).
4277c478bd9Sstevel@tonic-gate *	2) "Write" the data using a CAS %addr,%g0,%g0.
4287c478bd9Sstevel@tonic-gate *	   The casxa guarantees a transition from I to M or S to M.
4297c478bd9Sstevel@tonic-gate *	3) Displacement flush the E$ line corresponding to %addr.
4307c478bd9Sstevel@tonic-gate *	   The second ldxa pushes the M line out of the ecache, into the
4317c478bd9Sstevel@tonic-gate *	   writeback buffers, on the way to memory.
4327c478bd9Sstevel@tonic-gate *	4) The "membar #Sync" pushes the cache line out of the writeback
4337c478bd9Sstevel@tonic-gate *	   buffers onto the bus, on the way to dram finally.
4347c478bd9Sstevel@tonic-gate *
4357c478bd9Sstevel@tonic-gate * This is a modified version of the algorithm suggested by Gary Lauterbach.
4367c478bd9Sstevel@tonic-gate * In theory the CAS %addr,%g0,%g0 is supposed to mark the addr's cache line
4377c478bd9Sstevel@tonic-gate * as modified, but then we found out that for spitfire, if it misses in the
4387c478bd9Sstevel@tonic-gate * E$ it will probably install as an M, but if it hits in the E$, then it
4397c478bd9Sstevel@tonic-gate * will stay E, if the store doesn't happen. So the first displacement flush
4407c478bd9Sstevel@tonic-gate * should ensure that the CAS will miss in the E$.  Arrgh.
4417c478bd9Sstevel@tonic-gate */
4427c478bd9Sstevel@tonic-gate/* ARGSUSED */
4437c478bd9Sstevel@tonic-gatevoid
4447c478bd9Sstevel@tonic-gatescrubphys(uint64_t paddr, int ecache_set_size)
4457c478bd9Sstevel@tonic-gate{}
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate#else	/* lint */
4487c478bd9Sstevel@tonic-gate	ENTRY(scrubphys)
4497c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o4
4507c478bd9Sstevel@tonic-gate	andn	%o4, PSTATE_IE | PSTATE_AM, %o5
4517c478bd9Sstevel@tonic-gate	wrpr	%o5, %g0, %pstate	! clear IE, AM bits
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate	GET_CPU_IMPL(%o5)		! Panther Ecache is flushed differently
4547c478bd9Sstevel@tonic-gate	cmp	%o5, PANTHER_IMPL
4557c478bd9Sstevel@tonic-gate	bne	scrubphys_1
4567c478bd9Sstevel@tonic-gate	  nop
4577c478bd9Sstevel@tonic-gate	PN_ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3, %o5)
4587c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
4597c478bd9Sstevel@tonic-gate	PN_ECACHE_REFLUSH_LINE(%o1, %o2, %o3, %o0)
4607c478bd9Sstevel@tonic-gate	b	scrubphys_2
4617c478bd9Sstevel@tonic-gate	  nop
4627c478bd9Sstevel@tonic-gatescrubphys_1:
4637c478bd9Sstevel@tonic-gate	ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3)
4647c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
4657c478bd9Sstevel@tonic-gate	ECACHE_REFLUSH_LINE(%o1, %o2, %o3)
4667c478bd9Sstevel@tonic-gatescrubphys_2:
4677c478bd9Sstevel@tonic-gate	wrpr	%g0, %o4, %pstate	! restore earlier pstate register value
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate	retl
4707c478bd9Sstevel@tonic-gate	membar	#Sync			! move the data out of the load buffer
4717c478bd9Sstevel@tonic-gate	SET_SIZE(scrubphys)
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate#endif	/* lint */
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate#if defined(lint)
4777c478bd9Sstevel@tonic-gate/*
478750ba224Sanbui * clearphys - Pass in the physical memory address of the checkblock
479750ba224Sanbui * that you want to push out, cleared with a recognizable pattern,
480750ba224Sanbui * from the ecache.
481750ba224Sanbui *
482750ba224Sanbui * To ensure that the ecc gets recalculated after the bad data is cleared,
483750ba224Sanbui * we must write out enough data to fill the w$ line (64 bytes). So we read
484750ba224Sanbui * in an entire ecache subblock's worth of data, and write it back out.
485750ba224Sanbui * Then we overwrite the 16 bytes of bad data with the pattern.
4867c478bd9Sstevel@tonic-gate */
4877c478bd9Sstevel@tonic-gate/* ARGSUSED */
4887c478bd9Sstevel@tonic-gatevoid
4897c478bd9Sstevel@tonic-gateclearphys(uint64_t paddr, int ecache_set_size, int ecache_linesize)
4907c478bd9Sstevel@tonic-gate{
4917c478bd9Sstevel@tonic-gate}
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate#else	/* lint */
4947c478bd9Sstevel@tonic-gate	ENTRY(clearphys)
4957c478bd9Sstevel@tonic-gate	/* turn off IE, AM bits */
4967c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o4
4977c478bd9Sstevel@tonic-gate	andn	%o4, PSTATE_IE | PSTATE_AM, %o5
4987c478bd9Sstevel@tonic-gate	wrpr	%o5, %g0, %pstate
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate	/* turn off NCEEN */
5017c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %o5
5027c478bd9Sstevel@tonic-gate	andn	%o5, EN_REG_NCEEN, %o3
5037c478bd9Sstevel@tonic-gate	stxa	%o3, [%g0]ASI_ESTATE_ERR
5047c478bd9Sstevel@tonic-gate	membar	#Sync
5057c478bd9Sstevel@tonic-gate
506750ba224Sanbui	/* align address passed with 64 bytes subblock size */
507750ba224Sanbui	mov	CH_ECACHE_SUBBLK_SIZE, %o2
508750ba224Sanbui	andn	%o0, (CH_ECACHE_SUBBLK_SIZE - 1), %g1
509750ba224Sanbui
510750ba224Sanbui	/* move the good data into the W$ */
5117c478bd9Sstevel@tonic-gateclearphys_1:
5127c478bd9Sstevel@tonic-gate	subcc	%o2, 8, %o2
513750ba224Sanbui	ldxa	[%g1 + %o2]ASI_MEM, %g2
5147c478bd9Sstevel@tonic-gate	bge	clearphys_1
515750ba224Sanbui	  stxa	%g2, [%g1 + %o2]ASI_MEM
516750ba224Sanbui
517750ba224Sanbui	/* now overwrite the bad data */
518750ba224Sanbui	setx	0xbadecc00badecc01, %g1, %g2
519750ba224Sanbui	stxa	%g2, [%o0]ASI_MEM
520750ba224Sanbui	mov	8, %g1
521750ba224Sanbui	stxa	%g2, [%o0 + %g1]ASI_MEM
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate	GET_CPU_IMPL(%o3)		! Panther Ecache is flushed differently
5247c478bd9Sstevel@tonic-gate	cmp	%o3, PANTHER_IMPL
5257c478bd9Sstevel@tonic-gate	bne	clearphys_2
5267c478bd9Sstevel@tonic-gate	  nop
5277c478bd9Sstevel@tonic-gate	PN_ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3, %g1)
5287c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
5297c478bd9Sstevel@tonic-gate	PN_ECACHE_REFLUSH_LINE(%o1, %o2, %o3, %o0)
5307c478bd9Sstevel@tonic-gate	b	clearphys_3
5317c478bd9Sstevel@tonic-gate	  nop
5327c478bd9Sstevel@tonic-gateclearphys_2:
5337c478bd9Sstevel@tonic-gate	ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3)
5347c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
5357c478bd9Sstevel@tonic-gate	ECACHE_REFLUSH_LINE(%o1, %o2, %o3)
5367c478bd9Sstevel@tonic-gateclearphys_3:
5377c478bd9Sstevel@tonic-gate	/* clear the AFSR */
5387c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %o1
5397c478bd9Sstevel@tonic-gate	stxa	%o1, [%g0]ASI_AFSR
5407c478bd9Sstevel@tonic-gate	membar	#Sync
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate	/* turn NCEEN back on */
5437c478bd9Sstevel@tonic-gate	stxa	%o5, [%g0]ASI_ESTATE_ERR
5447c478bd9Sstevel@tonic-gate	membar	#Sync
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate	/* return and re-enable IE and AM */
5477c478bd9Sstevel@tonic-gate	retl
5487c478bd9Sstevel@tonic-gate	  wrpr	%g0, %o4, %pstate
5497c478bd9Sstevel@tonic-gate	SET_SIZE(clearphys)
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate#endif	/* lint */
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate#if defined(lint)
5557c478bd9Sstevel@tonic-gate/*
5567c478bd9Sstevel@tonic-gate * Cheetah+ Ecache displacement flush the specified line from the E$
5577c478bd9Sstevel@tonic-gate *
5587c478bd9Sstevel@tonic-gate * For Panther, this means flushing the specified line from both the
5597c478bd9Sstevel@tonic-gate * L2 cache and L3 cache.
5607c478bd9Sstevel@tonic-gate *
5617c478bd9Sstevel@tonic-gate * Register usage:
5627c478bd9Sstevel@tonic-gate *	%o0 - 64 bit physical address for flushing
5637c478bd9Sstevel@tonic-gate *	%o1 - Ecache set size
5647c478bd9Sstevel@tonic-gate */
5657c478bd9Sstevel@tonic-gate/*ARGSUSED*/
5667c478bd9Sstevel@tonic-gatevoid
5677c478bd9Sstevel@tonic-gateecache_flush_line(uint64_t flushaddr, int ec_set_size)
5687c478bd9Sstevel@tonic-gate{
5697c478bd9Sstevel@tonic-gate}
5707c478bd9Sstevel@tonic-gate#else	/* lint */
5717c478bd9Sstevel@tonic-gate	ENTRY(ecache_flush_line)
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate	GET_CPU_IMPL(%o3)		! Panther Ecache is flushed differently
5747c478bd9Sstevel@tonic-gate	cmp	%o3, PANTHER_IMPL
5757c478bd9Sstevel@tonic-gate	bne	ecache_flush_line_1
5767c478bd9Sstevel@tonic-gate	  nop
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate	PN_ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3, %o4)
5797c478bd9Sstevel@tonic-gate	b	ecache_flush_line_2
5807c478bd9Sstevel@tonic-gate	  nop
5817c478bd9Sstevel@tonic-gateecache_flush_line_1:
5827c478bd9Sstevel@tonic-gate	ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3)
5837c478bd9Sstevel@tonic-gateecache_flush_line_2:
5847c478bd9Sstevel@tonic-gate	retl
5857c478bd9Sstevel@tonic-gate	  nop
5867c478bd9Sstevel@tonic-gate	SET_SIZE(ecache_flush_line)
5877c478bd9Sstevel@tonic-gate#endif	/* lint */
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate#if defined(lint)
5907c478bd9Sstevel@tonic-gatevoid
5917c478bd9Sstevel@tonic-gateset_afsr_ext(uint64_t afsr_ext)
5927c478bd9Sstevel@tonic-gate{
5937c478bd9Sstevel@tonic-gate	afsr_ext = afsr_ext;
5947c478bd9Sstevel@tonic-gate}
5957c478bd9Sstevel@tonic-gate#else /* lint */
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate	ENTRY(set_afsr_ext)
5987c478bd9Sstevel@tonic-gate	set	ASI_AFSR_EXT_VA, %o1
5997c478bd9Sstevel@tonic-gate	stxa	%o0, [%o1]ASI_AFSR		! afsr_ext reg
6007c478bd9Sstevel@tonic-gate	membar	#Sync
6017c478bd9Sstevel@tonic-gate	retl
6027c478bd9Sstevel@tonic-gate	nop
6037c478bd9Sstevel@tonic-gate	SET_SIZE(set_afsr_ext)
6047c478bd9Sstevel@tonic-gate
6057c478bd9Sstevel@tonic-gate#endif /* lint */
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate#if defined(lint)
6097c478bd9Sstevel@tonic-gate/*
6107c478bd9Sstevel@tonic-gate * The CPU jumps here from the MMU exception handler if an ITLB parity
6117c478bd9Sstevel@tonic-gate * error is detected and we are running on Panther.
6127c478bd9Sstevel@tonic-gate *
6137c478bd9Sstevel@tonic-gate * In this routine we collect diagnostic information and write it to our
6147c478bd9Sstevel@tonic-gate * logout structure (if possible) and clear all ITLB entries that may have
6157c478bd9Sstevel@tonic-gate * caused our parity trap.
6167c478bd9Sstevel@tonic-gate * Then we call cpu_tlb_parity_error via systrap in order to drop down to TL0
6177c478bd9Sstevel@tonic-gate * and log any error messages. As for parameters to cpu_tlb_parity_error, we
6187c478bd9Sstevel@tonic-gate * send two:
6197c478bd9Sstevel@tonic-gate *
6207c478bd9Sstevel@tonic-gate * %g2	- Contains the VA whose lookup in the ITLB caused the parity error
6217c478bd9Sstevel@tonic-gate * %g3	- Contains the tlo_info field of the pn_tlb_logout logout struct,
6227c478bd9Sstevel@tonic-gate *	  regardless of whether or not we actually used the logout struct.
6237c478bd9Sstevel@tonic-gate *
6247c478bd9Sstevel@tonic-gate * In the TL0 handler (cpu_tlb_parity_error) we will compare those two
6257c478bd9Sstevel@tonic-gate * parameters to the data contained in the logout structure in order to
6267c478bd9Sstevel@tonic-gate * determine whether the logout information is valid for this particular
6277c478bd9Sstevel@tonic-gate * error or not.
6287c478bd9Sstevel@tonic-gate */
6297c478bd9Sstevel@tonic-gatevoid
6307c478bd9Sstevel@tonic-gateitlb_parity_trap(void)
6317c478bd9Sstevel@tonic-gate{}
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate#else	/* lint */
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate	ENTRY_NP(itlb_parity_trap)
6367c478bd9Sstevel@tonic-gate	/*
6377c478bd9Sstevel@tonic-gate	 * Collect important information about the trap which will be
6387c478bd9Sstevel@tonic-gate	 * used as a parameter to the TL0 handler.
6397c478bd9Sstevel@tonic-gate	 */
6407c478bd9Sstevel@tonic-gate	wr	%g0, ASI_IMMU, %asi
6417c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g2			! VA that caused the IMMU trap
6427c478bd9Sstevel@tonic-gate	ldxa	[MMU_TAG_ACCESS_EXT]%asi, %g3	! read the trap VA page size
6437c478bd9Sstevel@tonic-gate	set	PN_ITLB_PGSZ_MASK, %g4
6447c478bd9Sstevel@tonic-gate	and	%g3, %g4, %g3
6457c478bd9Sstevel@tonic-gate	ldxa	[MMU_TAG_ACCESS]%asi, %g4
6467c478bd9Sstevel@tonic-gate	set	TAGREAD_CTX_MASK, %g5
6477c478bd9Sstevel@tonic-gate	and	%g4, %g5, %g4
6487c478bd9Sstevel@tonic-gate	or	%g4, %g3, %g3			! 'or' in the trap context and
6497c478bd9Sstevel@tonic-gate	mov	1, %g4				! add the IMMU flag to complete
6507c478bd9Sstevel@tonic-gate	sllx	%g4, PN_TLO_INFO_IMMU_SHIFT, %g4
6517c478bd9Sstevel@tonic-gate	or	%g4, %g3, %g3			! the tlo_info field for logout
6527c478bd9Sstevel@tonic-gate	stxa	%g0,[MMU_SFSR]%asi		! clear the SFSR
6537c478bd9Sstevel@tonic-gate	membar	#Sync
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate	/*
6567c478bd9Sstevel@tonic-gate	 * at this point:
6577c478bd9Sstevel@tonic-gate	 *    %g2 - contains the VA whose lookup caused the trap
6587c478bd9Sstevel@tonic-gate	 *    %g3 - contains the tlo_info field
6597c478bd9Sstevel@tonic-gate	 *
6607c478bd9Sstevel@tonic-gate	 * Next, we calculate the TLB index value for the failing VA.
6617c478bd9Sstevel@tonic-gate	 */
6627c478bd9Sstevel@tonic-gate	mov	%g2, %g4			! We need the ITLB index
6637c478bd9Sstevel@tonic-gate	set	PN_ITLB_PGSZ_MASK, %g5
6647c478bd9Sstevel@tonic-gate	and	%g3, %g5, %g5
6657c478bd9Sstevel@tonic-gate	srlx	%g5, PN_ITLB_PGSZ_SHIFT, %g5
6667c478bd9Sstevel@tonic-gate	PN_GET_TLB_INDEX(%g4, %g5)		! %g4 has the index
6677c478bd9Sstevel@tonic-gate	sllx	%g4, PN_TLB_ACC_IDX_SHIFT, %g4	! shift the index into place
6687c478bd9Sstevel@tonic-gate	set	PN_ITLB_T512, %g5
6697c478bd9Sstevel@tonic-gate	or	%g4, %g5, %g4			! and add in the TLB ID
6707c478bd9Sstevel@tonic-gate
6717c478bd9Sstevel@tonic-gate	/*
6727c478bd9Sstevel@tonic-gate	 * at this point:
6737c478bd9Sstevel@tonic-gate	 *    %g2 - contains the VA whose lookup caused the trap
6747c478bd9Sstevel@tonic-gate	 *    %g3 - contains the tlo_info field
6757c478bd9Sstevel@tonic-gate	 *    %g4 - contains the TLB access index value for the
6767c478bd9Sstevel@tonic-gate	 *          VA/PgSz in question
6777c478bd9Sstevel@tonic-gate	 *
6787c478bd9Sstevel@tonic-gate	 * Check to see if the logout structure is available.
6797c478bd9Sstevel@tonic-gate	 */
6807c478bd9Sstevel@tonic-gate	set	CHPR_TLB_LOGOUT, %g6
6817c478bd9Sstevel@tonic-gate	GET_CPU_PRIVATE_PTR(%g6, %g1, %g5, itlb_parity_trap_1)
6827c478bd9Sstevel@tonic-gate	set	LOGOUT_INVALID_U32, %g6
6837c478bd9Sstevel@tonic-gate	sllx	%g6, 32, %g6			! if our logout structure is
6847c478bd9Sstevel@tonic-gate	set	LOGOUT_INVALID_L32, %g5		! unavailable or if it is
6857c478bd9Sstevel@tonic-gate	or	%g5, %g6, %g5			! already being used, then we
6867c478bd9Sstevel@tonic-gate	ldx	[%g1 + PN_TLO_ADDR], %g6	! don't collect any diagnostic
6877c478bd9Sstevel@tonic-gate	cmp	%g6, %g5			! information before clearing
6887c478bd9Sstevel@tonic-gate	bne	itlb_parity_trap_1		! and logging the error.
6897c478bd9Sstevel@tonic-gate	  nop
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate	/*
6927c478bd9Sstevel@tonic-gate	 * Record the logout information. %g4 contains our index + TLB ID
6937c478bd9Sstevel@tonic-gate	 * for use in ASI_ITLB_ACCESS and ASI_ITLB_TAGREAD. %g1 contains
6947c478bd9Sstevel@tonic-gate	 * the pointer to our logout struct.
6957c478bd9Sstevel@tonic-gate	 */
6967c478bd9Sstevel@tonic-gate	stx	%g3, [%g1 + PN_TLO_INFO]
6977c478bd9Sstevel@tonic-gate	stx	%g2, [%g1 + PN_TLO_ADDR]
6987c478bd9Sstevel@tonic-gate	stx	%g2, [%g1 + PN_TLO_PC]		! %tpc == fault addr for IMMU
6997c478bd9Sstevel@tonic-gate
7007c478bd9Sstevel@tonic-gate	add	%g1, PN_TLO_ITLB_TTE, %g1	! move up the pointer
7017c478bd9Sstevel@tonic-gate
7027c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_ITLB_ACCESS, %g5	! read the data
7037c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + CH_TLO_TTE_DATA]	! store it away
7047c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_ITLB_TAGREAD, %g5	! read the tag
7057c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + CH_TLO_TTE_TAG]	! store it away
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate	set	PN_TLB_ACC_WAY_BIT, %g6		! same thing again for way 1
7087c478bd9Sstevel@tonic-gate	or	%g4, %g6, %g4
7097c478bd9Sstevel@tonic-gate	add	%g1, CH_TLO_TTE_SIZE, %g1	! move up the pointer
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_ITLB_ACCESS, %g5	! read the data
7127c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + CH_TLO_TTE_DATA]	! store it away
7137c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_ITLB_TAGREAD, %g5	! read the tag
7147c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + CH_TLO_TTE_TAG]	! store it away
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate	andn	%g4, %g6, %g4			! back to way 0
7177c478bd9Sstevel@tonic-gate
7187c478bd9Sstevel@tonic-gateitlb_parity_trap_1:
7197c478bd9Sstevel@tonic-gate	/*
7207c478bd9Sstevel@tonic-gate	 * at this point:
7217c478bd9Sstevel@tonic-gate	 *    %g2 - contains the VA whose lookup caused the trap
7227c478bd9Sstevel@tonic-gate	 *    %g3 - contains the tlo_info field
7237c478bd9Sstevel@tonic-gate	 *    %g4 - contains the TLB access index value for the
7247c478bd9Sstevel@tonic-gate	 *          VA/PgSz in question
7257c478bd9Sstevel@tonic-gate	 *
7267c478bd9Sstevel@tonic-gate	 * Here we will clear the errors from the TLB.
7277c478bd9Sstevel@tonic-gate	 */
7287c478bd9Sstevel@tonic-gate	set	MMU_TAG_ACCESS, %g5		! We write a TTE tag value of
7297c478bd9Sstevel@tonic-gate	stxa	%g0, [%g5]ASI_IMMU		! 0 as it will be invalid.
7307c478bd9Sstevel@tonic-gate	stxa	%g0, [%g4]ASI_ITLB_ACCESS	! Write the data and tag
7317c478bd9Sstevel@tonic-gate	membar	#Sync
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate	set	PN_TLB_ACC_WAY_BIT, %g6		! same thing again for way 1
7347c478bd9Sstevel@tonic-gate	or	%g4, %g6, %g4
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate	stxa	%g0, [%g4]ASI_ITLB_ACCESS	! Write same data and tag
7377c478bd9Sstevel@tonic-gate	membar	#Sync
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate	sethi	%hi(FLUSH_ADDR), %g6		! PRM says we need to issue a
7407c478bd9Sstevel@tonic-gate	flush   %g6				! flush after writing MMU regs
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate	/*
7437c478bd9Sstevel@tonic-gate	 * at this point:
7447c478bd9Sstevel@tonic-gate	 *    %g2 - contains the VA whose lookup caused the trap
7457c478bd9Sstevel@tonic-gate	 *    %g3 - contains the tlo_info field
7467c478bd9Sstevel@tonic-gate	 *
7477c478bd9Sstevel@tonic-gate	 * Call cpu_tlb_parity_error via systrap at PIL 14 unless we're
7487c478bd9Sstevel@tonic-gate	 * already at PIL 15.	 */
7497c478bd9Sstevel@tonic-gate	set	cpu_tlb_parity_error, %g1
7507c478bd9Sstevel@tonic-gate	rdpr	%pil, %g4
7517c478bd9Sstevel@tonic-gate	cmp	%g4, PIL_14
7527c478bd9Sstevel@tonic-gate	movl	%icc, PIL_14, %g4
7537c478bd9Sstevel@tonic-gate	ba	sys_trap
7547c478bd9Sstevel@tonic-gate	  nop
7557c478bd9Sstevel@tonic-gate	SET_SIZE(itlb_parity_trap)
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate#endif	/* lint */
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate#if defined(lint)
7607c478bd9Sstevel@tonic-gate/*
7617c478bd9Sstevel@tonic-gate * The CPU jumps here from the MMU exception handler if a DTLB parity
7627c478bd9Sstevel@tonic-gate * error is detected and we are running on Panther.
7637c478bd9Sstevel@tonic-gate *
7647c478bd9Sstevel@tonic-gate * In this routine we collect diagnostic information and write it to our
7657c478bd9Sstevel@tonic-gate * logout structure (if possible) and clear all DTLB entries that may have
7667c478bd9Sstevel@tonic-gate * caused our parity trap.
7677c478bd9Sstevel@tonic-gate * Then we call cpu_tlb_parity_error via systrap in order to drop down to TL0
7687c478bd9Sstevel@tonic-gate * and log any error messages. As for parameters to cpu_tlb_parity_error, we
7697c478bd9Sstevel@tonic-gate * send two:
7707c478bd9Sstevel@tonic-gate *
7717c478bd9Sstevel@tonic-gate * %g2	- Contains the VA whose lookup in the DTLB caused the parity error
7727c478bd9Sstevel@tonic-gate * %g3	- Contains the tlo_info field of the pn_tlb_logout logout struct,
7737c478bd9Sstevel@tonic-gate *	  regardless of whether or not we actually used the logout struct.
7747c478bd9Sstevel@tonic-gate *
7757c478bd9Sstevel@tonic-gate * In the TL0 handler (cpu_tlb_parity_error) we will compare those two
7767c478bd9Sstevel@tonic-gate * parameters to the data contained in the logout structure in order to
7777c478bd9Sstevel@tonic-gate * determine whether the logout information is valid for this particular
7787c478bd9Sstevel@tonic-gate * error or not.
7797c478bd9Sstevel@tonic-gate */
7807c478bd9Sstevel@tonic-gatevoid
7817c478bd9Sstevel@tonic-gatedtlb_parity_trap(void)
7827c478bd9Sstevel@tonic-gate{}
7837c478bd9Sstevel@tonic-gate
7847c478bd9Sstevel@tonic-gate#else	/* lint */
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate	ENTRY_NP(dtlb_parity_trap)
7877c478bd9Sstevel@tonic-gate	/*
7887c478bd9Sstevel@tonic-gate	 * Collect important information about the trap which will be
7897c478bd9Sstevel@tonic-gate	 * used as a parameter to the TL0 handler.
7907c478bd9Sstevel@tonic-gate	 */
7917c478bd9Sstevel@tonic-gate	wr	%g0, ASI_DMMU, %asi
7927c478bd9Sstevel@tonic-gate	ldxa	[MMU_SFAR]%asi, %g2		! VA that caused the IMMU trap
7937c478bd9Sstevel@tonic-gate	ldxa	[MMU_TAG_ACCESS_EXT]%asi, %g3	! read the trap VA page sizes
7947c478bd9Sstevel@tonic-gate	set	PN_DTLB_PGSZ_MASK, %g4
7957c478bd9Sstevel@tonic-gate	and	%g3, %g4, %g3
7967c478bd9Sstevel@tonic-gate	ldxa	[MMU_TAG_ACCESS]%asi, %g4
7977c478bd9Sstevel@tonic-gate	set	TAGREAD_CTX_MASK, %g5		! 'or' in the trap context
7987c478bd9Sstevel@tonic-gate	and	%g4, %g5, %g4			! to complete the tlo_info
7997c478bd9Sstevel@tonic-gate	or	%g4, %g3, %g3			! field for logout
8007c478bd9Sstevel@tonic-gate	stxa	%g0,[MMU_SFSR]%asi		! clear the SFSR
8017c478bd9Sstevel@tonic-gate	membar	#Sync
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate	/*
8047c478bd9Sstevel@tonic-gate	 * at this point:
8057c478bd9Sstevel@tonic-gate	 *    %g2 - contains the VA whose lookup caused the trap
8067c478bd9Sstevel@tonic-gate	 *    %g3 - contains the tlo_info field
8077c478bd9Sstevel@tonic-gate	 *
8087c478bd9Sstevel@tonic-gate	 * Calculate the TLB index values for the failing VA. Since the T512
8097c478bd9Sstevel@tonic-gate	 * TLBs can be configured for different page sizes, we need to find
8107c478bd9Sstevel@tonic-gate	 * the index into each one separately.
8117c478bd9Sstevel@tonic-gate	 */
8127c478bd9Sstevel@tonic-gate	mov	%g2, %g4			! First we get the DTLB_0 index
8137c478bd9Sstevel@tonic-gate	set	PN_DTLB_PGSZ0_MASK, %g5
8147c478bd9Sstevel@tonic-gate	and	%g3, %g5, %g5
8157c478bd9Sstevel@tonic-gate	srlx	%g5, PN_DTLB_PGSZ0_SHIFT, %g5
8167c478bd9Sstevel@tonic-gate	PN_GET_TLB_INDEX(%g4, %g5)		! %g4 has the DTLB_0 index
8177c478bd9Sstevel@tonic-gate	sllx	%g4, PN_TLB_ACC_IDX_SHIFT, %g4	! shift the index into place
8187c478bd9Sstevel@tonic-gate	set	PN_DTLB_T512_0, %g5
8197c478bd9Sstevel@tonic-gate	or	%g4, %g5, %g4			! and add in the TLB ID
8207c478bd9Sstevel@tonic-gate
8217c478bd9Sstevel@tonic-gate	mov	%g2, %g7			! Next we get the DTLB_1 index
8227c478bd9Sstevel@tonic-gate	set	PN_DTLB_PGSZ1_MASK, %g5
8237c478bd9Sstevel@tonic-gate	and	%g3, %g5, %g5
8247c478bd9Sstevel@tonic-gate	srlx	%g5, PN_DTLB_PGSZ1_SHIFT, %g5
8257c478bd9Sstevel@tonic-gate	PN_GET_TLB_INDEX(%g7, %g5)		! %g7 has the DTLB_1 index
8267c478bd9Sstevel@tonic-gate	sllx	%g7, PN_TLB_ACC_IDX_SHIFT, %g7	! shift the index into place
8277c478bd9Sstevel@tonic-gate	set	PN_DTLB_T512_1, %g5
8287c478bd9Sstevel@tonic-gate	or	%g7, %g5, %g7			! and add in the TLB ID
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate	/*
8317c478bd9Sstevel@tonic-gate	 * at this point:
8327c478bd9Sstevel@tonic-gate	 *    %g2 - contains the VA whose lookup caused the trap
8337c478bd9Sstevel@tonic-gate	 *    %g3 - contains the tlo_info field
8347c478bd9Sstevel@tonic-gate	 *    %g4 - contains the T512_0 access index value for the
8357c478bd9Sstevel@tonic-gate	 *          VA/PgSz in question
8367c478bd9Sstevel@tonic-gate	 *    %g7 - contains the T512_1 access index value for the
8377c478bd9Sstevel@tonic-gate	 *          VA/PgSz in question
8387c478bd9Sstevel@tonic-gate	 *
8397c478bd9Sstevel@tonic-gate	 * If this trap happened at TL>0, then we don't want to mess
8407c478bd9Sstevel@tonic-gate	 * with the normal logout struct since that could caused a TLB
8417c478bd9Sstevel@tonic-gate	 * miss.
8427c478bd9Sstevel@tonic-gate	 */
8437c478bd9Sstevel@tonic-gate	rdpr	%tl, %g6			! read current trap level
8447c478bd9Sstevel@tonic-gate	cmp	%g6, 1				! skip over the tl>1 code
8457c478bd9Sstevel@tonic-gate	ble	dtlb_parity_trap_1		! if TL <= 1.
8467c478bd9Sstevel@tonic-gate	  nop
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate	/*
8497c478bd9Sstevel@tonic-gate	 * If we are here, then the trap happened at TL>1. Simply
8507c478bd9Sstevel@tonic-gate	 * update our tlo_info field and then skip to the TLB flush
8517c478bd9Sstevel@tonic-gate	 * code.
8527c478bd9Sstevel@tonic-gate	 */
8537c478bd9Sstevel@tonic-gate	mov	1, %g6
8547c478bd9Sstevel@tonic-gate	sllx	%g6, PN_TLO_INFO_TL1_SHIFT, %g6
8557c478bd9Sstevel@tonic-gate	or	%g6, %g3, %g3
8567c478bd9Sstevel@tonic-gate	ba	dtlb_parity_trap_2
8577c478bd9Sstevel@tonic-gate	  nop
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gatedtlb_parity_trap_1:
8607c478bd9Sstevel@tonic-gate	/*
8617c478bd9Sstevel@tonic-gate	 * at this point:
8627c478bd9Sstevel@tonic-gate	 *    %g2 - contains the VA whose lookup caused the trap
8637c478bd9Sstevel@tonic-gate	 *    %g3 - contains the tlo_info field
8647c478bd9Sstevel@tonic-gate	 *    %g4 - contains the T512_0 access index value for the
8657c478bd9Sstevel@tonic-gate	 *          VA/PgSz in question
8667c478bd9Sstevel@tonic-gate	 *    %g7 - contains the T512_1 access index value for the
8677c478bd9Sstevel@tonic-gate	 *          VA/PgSz in question
8687c478bd9Sstevel@tonic-gate	 *
8697c478bd9Sstevel@tonic-gate	 * Check to see if the logout structure is available.
8707c478bd9Sstevel@tonic-gate	 */
8717c478bd9Sstevel@tonic-gate	set	CHPR_TLB_LOGOUT, %g6
8727c478bd9Sstevel@tonic-gate	GET_CPU_PRIVATE_PTR(%g6, %g1, %g5, dtlb_parity_trap_2)
8737c478bd9Sstevel@tonic-gate	set	LOGOUT_INVALID_U32, %g6
8747c478bd9Sstevel@tonic-gate	sllx	%g6, 32, %g6			! if our logout structure is
8757c478bd9Sstevel@tonic-gate	set	LOGOUT_INVALID_L32, %g5		! unavailable or if it is
8767c478bd9Sstevel@tonic-gate	or	%g5, %g6, %g5			! already being used, then we
8777c478bd9Sstevel@tonic-gate	ldx	[%g1 + PN_TLO_ADDR], %g6	! don't collect any diagnostic
8787c478bd9Sstevel@tonic-gate	cmp	%g6, %g5			! information before clearing
8797c478bd9Sstevel@tonic-gate	bne	dtlb_parity_trap_2		! and logging the error.
8807c478bd9Sstevel@tonic-gate	  nop
8817c478bd9Sstevel@tonic-gate
8827c478bd9Sstevel@tonic-gate	/*
8837c478bd9Sstevel@tonic-gate	 * Record the logout information. %g4 contains our DTLB_0
8847c478bd9Sstevel@tonic-gate	 * index + TLB ID and %g7 contains our DTLB_1 index + TLB ID
8857c478bd9Sstevel@tonic-gate	 * both of which will be used for ASI_DTLB_ACCESS and
8867c478bd9Sstevel@tonic-gate	 * ASI_DTLB_TAGREAD. %g1 contains the pointer to our logout
8877c478bd9Sstevel@tonic-gate	 * struct.
8887c478bd9Sstevel@tonic-gate	 */
8897c478bd9Sstevel@tonic-gate	stx	%g3, [%g1 + PN_TLO_INFO]
8907c478bd9Sstevel@tonic-gate	stx	%g2, [%g1 + PN_TLO_ADDR]
8917c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g5
8927c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + PN_TLO_PC]
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate	add	%g1, PN_TLO_DTLB_TTE, %g1	! move up the pointer
8957c478bd9Sstevel@tonic-gate
8967c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_DTLB_ACCESS, %g5	! read the data from DTLB_0
8977c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + CH_TLO_TTE_DATA]	! way 0 and store it away
8987c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_DTLB_TAGREAD, %g5	! read the tag from DTLB_0
8997c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + CH_TLO_TTE_TAG]	! way 0 and store it away
9007c478bd9Sstevel@tonic-gate
9017c478bd9Sstevel@tonic-gate	ldxa	[%g7]ASI_DTLB_ACCESS, %g5	! now repeat for DTLB_1 way 0
9027c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + (CH_TLO_TTE_DATA + (CH_TLO_TTE_SIZE * 2))]
9037c478bd9Sstevel@tonic-gate	ldxa	[%g7]ASI_DTLB_TAGREAD, %g5
9047c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + (CH_TLO_TTE_TAG + (CH_TLO_TTE_SIZE * 2))]
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate	set	PN_TLB_ACC_WAY_BIT, %g6		! same thing again for way 1
9077c478bd9Sstevel@tonic-gate	or	%g4, %g6, %g4			! of each TLB.
9087c478bd9Sstevel@tonic-gate	or	%g7, %g6, %g7
9097c478bd9Sstevel@tonic-gate	add	%g1, CH_TLO_TTE_SIZE, %g1	! move up the pointer
9107c478bd9Sstevel@tonic-gate
9117c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_DTLB_ACCESS, %g5	! read the data from DTLB_0
9127c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + CH_TLO_TTE_DATA]	! way 1 and store it away
9137c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_DTLB_TAGREAD, %g5	! read the tag from DTLB_0
9147c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + CH_TLO_TTE_TAG]	! way 1 and store it away
9157c478bd9Sstevel@tonic-gate
9167c478bd9Sstevel@tonic-gate	ldxa	[%g7]ASI_DTLB_ACCESS, %g5	! now repeat for DTLB_1 way 1
9177c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + (CH_TLO_TTE_DATA + (CH_TLO_TTE_SIZE * 2))]
9187c478bd9Sstevel@tonic-gate	ldxa	[%g7]ASI_DTLB_TAGREAD, %g5
9197c478bd9Sstevel@tonic-gate	stx	%g5, [%g1 + (CH_TLO_TTE_TAG + (CH_TLO_TTE_SIZE * 2))]
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate	andn	%g4, %g6, %g4			! back to way 0
9227c478bd9Sstevel@tonic-gate	andn	%g7, %g6, %g7			! back to way 0
9237c478bd9Sstevel@tonic-gate
9247c478bd9Sstevel@tonic-gatedtlb_parity_trap_2:
9257c478bd9Sstevel@tonic-gate	/*
9267c478bd9Sstevel@tonic-gate	 * at this point:
9277c478bd9Sstevel@tonic-gate	 *    %g2 - contains the VA whose lookup caused the trap
9287c478bd9Sstevel@tonic-gate	 *    %g3 - contains the tlo_info field
9297c478bd9Sstevel@tonic-gate	 *    %g4 - contains the T512_0 access index value for the
9307c478bd9Sstevel@tonic-gate	 *          VA/PgSz in question
9317c478bd9Sstevel@tonic-gate	 *    %g7 - contains the T512_1 access index value for the
9327c478bd9Sstevel@tonic-gate	 *          VA/PgSz in question
9337c478bd9Sstevel@tonic-gate	 *
9347c478bd9Sstevel@tonic-gate	 * Here we will clear the errors from the DTLB.
9357c478bd9Sstevel@tonic-gate	 */
9367c478bd9Sstevel@tonic-gate	set	MMU_TAG_ACCESS, %g5		! We write a TTE tag value of
9377c478bd9Sstevel@tonic-gate	stxa	%g0, [%g5]ASI_DMMU		! 0 as it will be invalid.
9387c478bd9Sstevel@tonic-gate	stxa	%g0, [%g4]ASI_DTLB_ACCESS	! Write the data and tag.
9397c478bd9Sstevel@tonic-gate	stxa	%g0, [%g7]ASI_DTLB_ACCESS	! Now repeat for DTLB_1 way 0
9407c478bd9Sstevel@tonic-gate	membar	#Sync
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate	set	PN_TLB_ACC_WAY_BIT, %g6		! same thing again for way 1
9437c478bd9Sstevel@tonic-gate	or	%g4, %g6, %g4
9447c478bd9Sstevel@tonic-gate	or	%g7, %g6, %g7
9457c478bd9Sstevel@tonic-gate
9467c478bd9Sstevel@tonic-gate	stxa	%g0, [%g4]ASI_DTLB_ACCESS	! Write same data and tag.
9477c478bd9Sstevel@tonic-gate	stxa	%g0, [%g7]ASI_DTLB_ACCESS	! Now repeat for DTLB_1 way 0
9487c478bd9Sstevel@tonic-gate	membar	#Sync
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate	sethi	%hi(FLUSH_ADDR), %g6		! PRM says we need to issue a
9517c478bd9Sstevel@tonic-gate	flush   %g6				! flush after writing MMU regs
9527c478bd9Sstevel@tonic-gate
9537c478bd9Sstevel@tonic-gate	/*
9547c478bd9Sstevel@tonic-gate	 * at this point:
9557c478bd9Sstevel@tonic-gate	 *    %g2 - contains the VA whose lookup caused the trap
9567c478bd9Sstevel@tonic-gate	 *    %g3 - contains the tlo_info field
9577c478bd9Sstevel@tonic-gate	 *
9587c478bd9Sstevel@tonic-gate	 * Call cpu_tlb_parity_error via systrap at PIL 14 unless we're
9597c478bd9Sstevel@tonic-gate	 * already at PIL 15. We do this even for TL>1 traps since
9607c478bd9Sstevel@tonic-gate	 * those will lead to a system panic.
9617c478bd9Sstevel@tonic-gate	 */
9627c478bd9Sstevel@tonic-gate	set	cpu_tlb_parity_error, %g1
9637c478bd9Sstevel@tonic-gate	rdpr	%pil, %g4
9647c478bd9Sstevel@tonic-gate	cmp	%g4, PIL_14
9657c478bd9Sstevel@tonic-gate	movl	%icc, PIL_14, %g4
9667c478bd9Sstevel@tonic-gate	ba	sys_trap
9677c478bd9Sstevel@tonic-gate	  nop
9687c478bd9Sstevel@tonic-gate	SET_SIZE(dtlb_parity_trap)
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate#endif	/* lint */
9717c478bd9Sstevel@tonic-gate
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate#if defined(lint)
9747c478bd9Sstevel@tonic-gate/*
9757c478bd9Sstevel@tonic-gate * Calculates the Panther TLB index based on a virtual address and page size
9767c478bd9Sstevel@tonic-gate *
9777c478bd9Sstevel@tonic-gate * Register usage:
9787c478bd9Sstevel@tonic-gate *	%o0 - virtual address whose index we want
9797c478bd9Sstevel@tonic-gate *	%o1 - Page Size of the TLB in question as encoded in the
9807c478bd9Sstevel@tonic-gate *	      ASI_[D|I]MMU_TAG_ACCESS_EXT register.
9817c478bd9Sstevel@tonic-gate */
9827c478bd9Sstevel@tonic-gateuint64_t
9837c478bd9Sstevel@tonic-gatepn_get_tlb_index(uint64_t va, uint64_t pg_sz)
9847c478bd9Sstevel@tonic-gate{
9857c478bd9Sstevel@tonic-gate	return ((va + pg_sz)-(va + pg_sz));
9867c478bd9Sstevel@tonic-gate}
9877c478bd9Sstevel@tonic-gate#else	/* lint */
9887c478bd9Sstevel@tonic-gate	ENTRY(pn_get_tlb_index)
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate	PN_GET_TLB_INDEX(%o0, %o1)
9917c478bd9Sstevel@tonic-gate
9927c478bd9Sstevel@tonic-gate	retl
9937c478bd9Sstevel@tonic-gate	  nop
9947c478bd9Sstevel@tonic-gate	SET_SIZE(pn_get_tlb_index)
9957c478bd9Sstevel@tonic-gate#endif	/* lint */
9967c478bd9Sstevel@tonic-gate
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate#if defined(lint)
9997c478bd9Sstevel@tonic-gate/*
10007c478bd9Sstevel@tonic-gate * For Panther CPUs we need to flush the IPB after any I$ or D$
10017c478bd9Sstevel@tonic-gate * parity errors are detected.
10027c478bd9Sstevel@tonic-gate */
10037c478bd9Sstevel@tonic-gatevoid
10047c478bd9Sstevel@tonic-gateflush_ipb(void)
10057c478bd9Sstevel@tonic-gate{ return; }
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate#else	/* lint */
10087c478bd9Sstevel@tonic-gate
10097c478bd9Sstevel@tonic-gate	ENTRY(flush_ipb)
10107c478bd9Sstevel@tonic-gate	clr	%o0
10117c478bd9Sstevel@tonic-gate
10127c478bd9Sstevel@tonic-gateflush_ipb_1:
10137c478bd9Sstevel@tonic-gate	stxa	%g0, [%o0]ASI_IPB_TAG
10147c478bd9Sstevel@tonic-gate	membar	#Sync
10157c478bd9Sstevel@tonic-gate	cmp	%o0, PN_IPB_TAG_ADDR_MAX
10167c478bd9Sstevel@tonic-gate	blt	flush_ipb_1
10177c478bd9Sstevel@tonic-gate	  add	%o0, PN_IPB_TAG_ADDR_LINESIZE, 	%o0
10187c478bd9Sstevel@tonic-gate
10197c478bd9Sstevel@tonic-gate	sethi	%hi(FLUSH_ADDR), %o0
10207c478bd9Sstevel@tonic-gate	flush   %o0
10217c478bd9Sstevel@tonic-gate	retl
10227c478bd9Sstevel@tonic-gate	nop
10237c478bd9Sstevel@tonic-gate	SET_SIZE(flush_ipb)
10247c478bd9Sstevel@tonic-gate
10257c478bd9Sstevel@tonic-gate#endif	/* lint */
10267bebe46cSjc25722
10277bebe46cSjc25722
1028