xref: /titanic_51/usr/src/uts/sun4u/cpu/us3_cheetah_asm.s (revision 750ba2244c23d03e3f43b4967911885b36bbac55)
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
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate/*
23*750ba224Sanbui * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate *
267c478bd9Sstevel@tonic-gate * Assembly code support for the Cheetah module
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate#if !defined(lint)
327c478bd9Sstevel@tonic-gate#include "assym.h"
337c478bd9Sstevel@tonic-gate#endif	/* lint */
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
367c478bd9Sstevel@tonic-gate#include <sys/mmu.h>
377c478bd9Sstevel@tonic-gate#include <vm/hat_sfmmu.h>
387c478bd9Sstevel@tonic-gate#include <sys/machparam.h>
397c478bd9Sstevel@tonic-gate#include <sys/machcpuvar.h>
407c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
417c478bd9Sstevel@tonic-gate#include <sys/machtrap.h>
427c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
437c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
447c478bd9Sstevel@tonic-gate#include <sys/trap.h>
457c478bd9Sstevel@tonic-gate#include <sys/cheetahregs.h>
467c478bd9Sstevel@tonic-gate#include <sys/us3_module.h>
477c478bd9Sstevel@tonic-gate#include <sys/xc_impl.h>
487c478bd9Sstevel@tonic-gate#include <sys/intreg.h>
497c478bd9Sstevel@tonic-gate#include <sys/async.h>
507c478bd9Sstevel@tonic-gate#include <sys/clock.h>
517c478bd9Sstevel@tonic-gate#include <sys/cheetahasm.h>
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
547c478bd9Sstevel@tonic-gate#include <sys/traptrace.h>
557c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate#if !defined(lint)
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate/* BEGIN CSTYLED */
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate/*
627c478bd9Sstevel@tonic-gate * Cheetah version to flush an Ecache line by index (aliased address)
637c478bd9Sstevel@tonic-gate */
647c478bd9Sstevel@tonic-gate#define	ECACHE_REFLUSH_LINE(ecache_size, alias_address, scr2)		\
657c478bd9Sstevel@tonic-gate	ldxa	[alias_address]ASI_MEM, %g0
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate#define	ECACHE_FLUSH_LINE(physaddr, ecache_size, scr1, scr2)		\
687c478bd9Sstevel@tonic-gate	xor	physaddr, ecache_size, scr1;				\
697c478bd9Sstevel@tonic-gate	add	ecache_size, ecache_size, scr2;				\
707c478bd9Sstevel@tonic-gate	sub	scr2, 1, scr2;						\
717c478bd9Sstevel@tonic-gate	and	scr1, scr2, scr1;					\
727c478bd9Sstevel@tonic-gate	ASM_LDX(scr2, ecache_flushaddr);				\
737c478bd9Sstevel@tonic-gate	add	scr1, scr2, scr1;					\
747c478bd9Sstevel@tonic-gate	ECACHE_REFLUSH_LINE(ecache_size, scr1, scr2)
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate/* END CSTYLED */
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate#endif	/* !lint */
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate/*
827c478bd9Sstevel@tonic-gate * Fast ECC error at TL>0 handler
837c478bd9Sstevel@tonic-gate * We get here via trap 70 at TL>0->Software trap 0 at TL>0.  We enter
847c478bd9Sstevel@tonic-gate * this routine with %g1 and %g2 already saved in %tpc, %tnpc and %tstate.
857c478bd9Sstevel@tonic-gate * For a complete description of the Fast ECC at TL>0 handling see the
867c478bd9Sstevel@tonic-gate * comment block "Cheetah/Cheetah+ Fast ECC at TL>0 trap strategy" in
877c478bd9Sstevel@tonic-gate * us3_common_asm.s
887c478bd9Sstevel@tonic-gate */
897c478bd9Sstevel@tonic-gate#if defined(lint)
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gatevoid
927c478bd9Sstevel@tonic-gatefast_ecc_tl1_err(void)
937c478bd9Sstevel@tonic-gate{}
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate#else	/* lint */
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate	.section ".text"
987c478bd9Sstevel@tonic-gate	.align	64
997c478bd9Sstevel@tonic-gate	ENTRY_NP(fast_ecc_tl1_err)
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate	/*
1027c478bd9Sstevel@tonic-gate	 * This macro turns off the D$/I$ if they are on and saves their
1037c478bd9Sstevel@tonic-gate	 * original state in ch_err_tl1_tmp, saves all the %g registers in the
1047c478bd9Sstevel@tonic-gate	 * ch_err_tl1_data structure, updates the ch_err_tl1_flags and saves
1057c478bd9Sstevel@tonic-gate	 * the %tpc in ch_err_tl1_tpc.  At the end of this macro, %g1 will
1067c478bd9Sstevel@tonic-gate	 * point to the ch_err_tl1_data structure and the original D$/I$ state
1077c478bd9Sstevel@tonic-gate	 * will be saved in ch_err_tl1_tmp.  All %g registers except for %g1
1087c478bd9Sstevel@tonic-gate	 * will be available.
1097c478bd9Sstevel@tonic-gate	 */
1107c478bd9Sstevel@tonic-gate	CH_ERR_TL1_FECC_ENTER;
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate	/*
1137c478bd9Sstevel@tonic-gate	 * Get the diagnostic logout data.  %g4 must be initialized to
1147c478bd9Sstevel@tonic-gate	 * current CEEN state, %g5 must point to logout structure in
1157c478bd9Sstevel@tonic-gate	 * ch_err_tl1_data_t.  %g3 will contain the nesting count upon
1167c478bd9Sstevel@tonic-gate	 * return.
1177c478bd9Sstevel@tonic-gate	 */
1187c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g4
1197c478bd9Sstevel@tonic-gate	and	%g4, EN_REG_CEEN, %g4
1207c478bd9Sstevel@tonic-gate	add	%g1, CH_ERR_TL1_LOGOUT, %g5
1217c478bd9Sstevel@tonic-gate	DO_TL1_CPU_LOGOUT(%g3, %g2, %g4, %g5, %g6, %g3, %g4)
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate	/*
1247c478bd9Sstevel@tonic-gate	 * If the logout nesting count is exceeded, we're probably
1257c478bd9Sstevel@tonic-gate	 * not making any progress, try to panic instead.
1267c478bd9Sstevel@tonic-gate	 */
1277c478bd9Sstevel@tonic-gate	cmp	%g3, CLO_NESTING_MAX
1287c478bd9Sstevel@tonic-gate	bge	fecc_tl1_err
1297c478bd9Sstevel@tonic-gate	  nop
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate	/*
1327c478bd9Sstevel@tonic-gate	 * Save the current CEEN and NCEEN state in %g7 and turn them off
1337c478bd9Sstevel@tonic-gate	 * before flushing the Ecache.
1347c478bd9Sstevel@tonic-gate	 */
1357c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %g7
1367c478bd9Sstevel@tonic-gate	andn	%g7, EN_REG_CEEN | EN_REG_NCEEN, %g5
1377c478bd9Sstevel@tonic-gate	stxa	%g5, [%g0]ASI_ESTATE_ERR
1387c478bd9Sstevel@tonic-gate	membar	#Sync
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate	/*
1417c478bd9Sstevel@tonic-gate	 * Flush the Ecache, using the largest possible cache size with the
1427c478bd9Sstevel@tonic-gate	 * smallest possible line size since we can't get the actual sizes
1437c478bd9Sstevel@tonic-gate	 * from the cpu_node due to DTLB misses.
1447c478bd9Sstevel@tonic-gate	 */
1457c478bd9Sstevel@tonic-gate	set	CH_ECACHE_8M_SIZE, %g4
1467c478bd9Sstevel@tonic-gate	set	CH_ECACHE_MIN_LSIZE, %g5
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate	/*
1497c478bd9Sstevel@tonic-gate	 * Use a different flush address to avoid recursion if the error
1507c478bd9Sstevel@tonic-gate	 * exists in ecache_flushaddr.
1517c478bd9Sstevel@tonic-gate	 */
1527c478bd9Sstevel@tonic-gate	ASM_LDX(%g6, ecache_tl1_flushaddr)
1537c478bd9Sstevel@tonic-gate	cmp	%g6, -1		! check if address is valid
1547c478bd9Sstevel@tonic-gate	be	%xcc, fecc_tl1_err
1557c478bd9Sstevel@tonic-gate	  nop
1567c478bd9Sstevel@tonic-gate	CH_ECACHE_FLUSHALL(%g4, %g5, %g6)
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate	/*
1597c478bd9Sstevel@tonic-gate	 * Restore CEEN and NCEEN to the previous state.
1607c478bd9Sstevel@tonic-gate	 */
1617c478bd9Sstevel@tonic-gate	stxa	%g7, [%g0]ASI_ESTATE_ERR
1627c478bd9Sstevel@tonic-gate	membar	#Sync
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate	/*
1657c478bd9Sstevel@tonic-gate	 * If we turned off the D$, then flush it and turn it back on.
1667c478bd9Sstevel@tonic-gate	 */
1677c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_TMP]%asi, %g3
1687c478bd9Sstevel@tonic-gate	andcc	%g3, CH_ERR_TSTATE_DC_ON, %g0
1697c478bd9Sstevel@tonic-gate	bz	%xcc, 3f
1707c478bd9Sstevel@tonic-gate	  nop
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate	/*
1737c478bd9Sstevel@tonic-gate	 * Flush the D$.
1747c478bd9Sstevel@tonic-gate	 */
1757c478bd9Sstevel@tonic-gate	ASM_LD(%g4, dcache_size)
1767c478bd9Sstevel@tonic-gate	ASM_LD(%g5, dcache_linesize)
1777c478bd9Sstevel@tonic-gate	CH_DCACHE_FLUSHALL(%g4, %g5, %g6)
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate	/*
1807c478bd9Sstevel@tonic-gate	 * Turn the D$ back on.
1817c478bd9Sstevel@tonic-gate	 */
1827c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_DCU, %g3
1837c478bd9Sstevel@tonic-gate	or	%g3, DCU_DC, %g3
1847c478bd9Sstevel@tonic-gate	stxa	%g3, [%g0]ASI_DCU
1857c478bd9Sstevel@tonic-gate	membar	#Sync
1867c478bd9Sstevel@tonic-gate3:
1877c478bd9Sstevel@tonic-gate	/*
1887c478bd9Sstevel@tonic-gate	 * If we turned off the I$, then flush it and turn it back on.
1897c478bd9Sstevel@tonic-gate	 */
1907c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_TMP]%asi, %g3
1917c478bd9Sstevel@tonic-gate	andcc	%g3, CH_ERR_TSTATE_IC_ON, %g0
1927c478bd9Sstevel@tonic-gate	bz	%xcc, 4f
1937c478bd9Sstevel@tonic-gate	  nop
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate	/*
1967c478bd9Sstevel@tonic-gate	 * Flush the I$.
1977c478bd9Sstevel@tonic-gate	 */
1987c478bd9Sstevel@tonic-gate	ASM_LD(%g4, icache_size)
1997c478bd9Sstevel@tonic-gate	ASM_LD(%g5, icache_linesize)
2007c478bd9Sstevel@tonic-gate	CH_ICACHE_FLUSHALL(%g4, %g5, %g6, %g3)
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate	/*
2037c478bd9Sstevel@tonic-gate	 * Turn the I$ back on.  Changing DCU_IC requires flush.
2047c478bd9Sstevel@tonic-gate	 */
2057c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_DCU, %g3
2067c478bd9Sstevel@tonic-gate	or	%g3, DCU_IC, %g3
2077c478bd9Sstevel@tonic-gate	stxa	%g3, [%g0]ASI_DCU
2087c478bd9Sstevel@tonic-gate	flush	%g0
2097c478bd9Sstevel@tonic-gate4:
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
2127c478bd9Sstevel@tonic-gate	/*
2137c478bd9Sstevel@tonic-gate	 * Get current trap trace entry physical pointer.
2147c478bd9Sstevel@tonic-gate	 */
2157c478bd9Sstevel@tonic-gate	CPU_INDEX(%g6, %g5)
2167c478bd9Sstevel@tonic-gate	sll	%g6, TRAPTR_SIZE_SHIFT, %g6
2177c478bd9Sstevel@tonic-gate	set	trap_trace_ctl, %g5
2187c478bd9Sstevel@tonic-gate	add	%g6, %g5, %g6
2197c478bd9Sstevel@tonic-gate	ld	[%g6 + TRAPTR_LIMIT], %g5
2207c478bd9Sstevel@tonic-gate	tst	%g5
2217c478bd9Sstevel@tonic-gate	be	%icc, skip_traptrace
2227c478bd9Sstevel@tonic-gate	  nop
2237c478bd9Sstevel@tonic-gate	ldx	[%g6 + TRAPTR_PBASE], %g5
2247c478bd9Sstevel@tonic-gate	ld	[%g6 + TRAPTR_OFFSET], %g4
2257c478bd9Sstevel@tonic-gate	add	%g5, %g4, %g5
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate	/*
2287c478bd9Sstevel@tonic-gate	 * Create trap trace entry.
2297c478bd9Sstevel@tonic-gate	 */
2307c478bd9Sstevel@tonic-gate	rd	%asi, %g7
2317c478bd9Sstevel@tonic-gate	wr	%g0, TRAPTR_ASI, %asi
2327c478bd9Sstevel@tonic-gate	rd	STICK, %g4
2337c478bd9Sstevel@tonic-gate	stxa	%g4, [%g5 + TRAP_ENT_TICK]%asi
2347c478bd9Sstevel@tonic-gate	rdpr	%tl, %g4
2357c478bd9Sstevel@tonic-gate	stha	%g4, [%g5 + TRAP_ENT_TL]%asi
2367c478bd9Sstevel@tonic-gate	rdpr	%tt, %g4
2377c478bd9Sstevel@tonic-gate	stha	%g4, [%g5 + TRAP_ENT_TT]%asi
2387c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g4
2397c478bd9Sstevel@tonic-gate	stna	%g4, [%g5 + TRAP_ENT_TPC]%asi
2407c478bd9Sstevel@tonic-gate	rdpr	%tstate, %g4
2417c478bd9Sstevel@tonic-gate	stxa	%g4, [%g5 + TRAP_ENT_TSTATE]%asi
2427c478bd9Sstevel@tonic-gate	stna	%sp, [%g5 + TRAP_ENT_SP]%asi
2437c478bd9Sstevel@tonic-gate	stna	%g0, [%g5 + TRAP_ENT_TR]%asi
2447c478bd9Sstevel@tonic-gate	wr	%g0, %g7, %asi
2457c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_SDW_AFAR]%asi, %g3
2467c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_SDW_AFSR]%asi, %g4
2477c478bd9Sstevel@tonic-gate	wr	%g0, TRAPTR_ASI, %asi
2487c478bd9Sstevel@tonic-gate	stna	%g3, [%g5 + TRAP_ENT_F1]%asi
2497c478bd9Sstevel@tonic-gate	stna	%g4, [%g5 + TRAP_ENT_F2]%asi
2507c478bd9Sstevel@tonic-gate	wr	%g0, %g7, %asi
2517c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_AFAR]%asi, %g3
2527c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_AFSR]%asi, %g4
2537c478bd9Sstevel@tonic-gate	wr	%g0, TRAPTR_ASI, %asi
2547c478bd9Sstevel@tonic-gate	stna	%g3, [%g5 + TRAP_ENT_F3]%asi
2557c478bd9Sstevel@tonic-gate	stna	%g4, [%g5 + TRAP_ENT_F4]%asi
2567c478bd9Sstevel@tonic-gate	wr	%g0, %g7, %asi
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate	/*
2597c478bd9Sstevel@tonic-gate	 * Advance trap trace pointer.
2607c478bd9Sstevel@tonic-gate	 */
2617c478bd9Sstevel@tonic-gate	ld	[%g6 + TRAPTR_OFFSET], %g5
2627c478bd9Sstevel@tonic-gate	ld	[%g6 + TRAPTR_LIMIT], %g4
2637c478bd9Sstevel@tonic-gate	st	%g5, [%g6 + TRAPTR_LAST_OFFSET]
2647c478bd9Sstevel@tonic-gate	add	%g5, TRAP_ENT_SIZE, %g5
2657c478bd9Sstevel@tonic-gate	sub	%g4, TRAP_ENT_SIZE, %g4
2667c478bd9Sstevel@tonic-gate	cmp	%g5, %g4
2677c478bd9Sstevel@tonic-gate	movge	%icc, 0, %g5
2687c478bd9Sstevel@tonic-gate	st	%g5, [%g6 + TRAPTR_OFFSET]
2697c478bd9Sstevel@tonic-gateskip_traptrace:
2707c478bd9Sstevel@tonic-gate#endif	/* TRAPTRACE */
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate	/*
2737c478bd9Sstevel@tonic-gate	 * If nesting count is not zero, skip all the AFSR/AFAR
2747c478bd9Sstevel@tonic-gate	 * handling and just do the necessary cache-flushing.
2757c478bd9Sstevel@tonic-gate	 */
2767c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_NEST_CNT]%asi, %g2
2777c478bd9Sstevel@tonic-gate	brnz	%g2, 6f
2787c478bd9Sstevel@tonic-gate	  nop
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate	/*
2817c478bd9Sstevel@tonic-gate	 * If a UCU followed by a WDU has occurred go ahead and panic
2827c478bd9Sstevel@tonic-gate	 * since a UE will occur (on the retry) before the UCU and WDU
2837c478bd9Sstevel@tonic-gate	 * messages are enqueued.
2847c478bd9Sstevel@tonic-gate	 */
2857c478bd9Sstevel@tonic-gate	ldxa	[%g1 + CH_ERR_TL1_AFSR]%asi, %g3
2867c478bd9Sstevel@tonic-gate	set	1, %g4
2877c478bd9Sstevel@tonic-gate	sllx	%g4, C_AFSR_UCU_SHIFT, %g4
2887c478bd9Sstevel@tonic-gate	btst	%g4, %g3		! UCU in original AFSR?
2897c478bd9Sstevel@tonic-gate	bz	%xcc, 6f
2907c478bd9Sstevel@tonic-gate	  nop
2917c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %g4	! current AFSR
2927c478bd9Sstevel@tonic-gate	or	%g3, %g4, %g3		! %g3 = original + current AFSR
2937c478bd9Sstevel@tonic-gate	set	1, %g4
2947c478bd9Sstevel@tonic-gate	sllx	%g4, C_AFSR_WDU_SHIFT, %g4
2957c478bd9Sstevel@tonic-gate	btst	%g4, %g3		! WDU in original or current AFSR?
2967c478bd9Sstevel@tonic-gate	bnz	%xcc, fecc_tl1_err
2977c478bd9Sstevel@tonic-gate	  nop
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate6:
3007c478bd9Sstevel@tonic-gate	/*
3017c478bd9Sstevel@tonic-gate	 * We fall into this macro if we've successfully logged the error in
3027c478bd9Sstevel@tonic-gate	 * the ch_err_tl1_data structure and want the PIL15 softint to pick
3037c478bd9Sstevel@tonic-gate	 * it up and log it.  %g1 must point to the ch_err_tl1_data structure.
3047c478bd9Sstevel@tonic-gate	 * Restores the %g registers and issues retry.
3057c478bd9Sstevel@tonic-gate	 */
3067c478bd9Sstevel@tonic-gate	CH_ERR_TL1_EXIT;
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate	/*
3097c478bd9Sstevel@tonic-gate	 * Establish panic exit label.
3107c478bd9Sstevel@tonic-gate	 */
3117c478bd9Sstevel@tonic-gate	CH_ERR_TL1_PANIC_EXIT(fecc_tl1_err);
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate	SET_SIZE(fast_ecc_tl1_err)
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate#endif	/* lint */
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate#if defined(lint)
3197c478bd9Sstevel@tonic-gate/*
3207c478bd9Sstevel@tonic-gate * scrubphys - Pass in the aligned physical memory address
3217c478bd9Sstevel@tonic-gate * that you want to scrub, along with the ecache set size.
3227c478bd9Sstevel@tonic-gate *
3237c478bd9Sstevel@tonic-gate *	1) Displacement flush the E$ line corresponding to %addr.
3247c478bd9Sstevel@tonic-gate *	   The first ldxa guarantees that the %addr is no longer in
3257c478bd9Sstevel@tonic-gate *	   M, O, or E (goes to I or S (if instruction fetch also happens).
3267c478bd9Sstevel@tonic-gate *	2) "Write" the data using a CAS %addr,%g0,%g0.
3277c478bd9Sstevel@tonic-gate *	   The casxa guarantees a transition from I to M or S to M.
3287c478bd9Sstevel@tonic-gate *	3) Displacement flush the E$ line corresponding to %addr.
3297c478bd9Sstevel@tonic-gate *	   The second ldxa pushes the M line out of the ecache, into the
3307c478bd9Sstevel@tonic-gate *	   writeback buffers, on the way to memory.
3317c478bd9Sstevel@tonic-gate *	4) The "membar #Sync" pushes the cache line out of the writeback
3327c478bd9Sstevel@tonic-gate *	   buffers onto the bus, on the way to dram finally.
3337c478bd9Sstevel@tonic-gate *
3347c478bd9Sstevel@tonic-gate * This is a modified version of the algorithm suggested by Gary Lauterbach.
3357c478bd9Sstevel@tonic-gate * In theory the CAS %addr,%g0,%g0 is supposed to mark the addr's cache line
3367c478bd9Sstevel@tonic-gate * as modified, but then we found out that for spitfire, if it misses in the
3377c478bd9Sstevel@tonic-gate * E$ it will probably install as an M, but if it hits in the E$, then it
3387c478bd9Sstevel@tonic-gate * will stay E, if the store doesn't happen. So the first displacement flush
3397c478bd9Sstevel@tonic-gate * should ensure that the CAS will miss in the E$.  Arrgh.
3407c478bd9Sstevel@tonic-gate */
3417c478bd9Sstevel@tonic-gate/* ARGSUSED */
3427c478bd9Sstevel@tonic-gatevoid
3437c478bd9Sstevel@tonic-gatescrubphys(uint64_t paddr, int ecache_set_size)
3447c478bd9Sstevel@tonic-gate{}
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate#else	/* lint */
3477c478bd9Sstevel@tonic-gate	ENTRY(scrubphys)
3487c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o4
3497c478bd9Sstevel@tonic-gate	andn	%o4, PSTATE_IE | PSTATE_AM, %o5
3507c478bd9Sstevel@tonic-gate	wrpr	%o5, %g0, %pstate	! clear IE, AM bits
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate	ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3)
3537c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
3547c478bd9Sstevel@tonic-gate	ECACHE_REFLUSH_LINE(%o1, %o2, %o3)
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate	wrpr	%g0, %o4, %pstate	! restore earlier pstate register value
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate	retl
3597c478bd9Sstevel@tonic-gate	membar	#Sync			! move the data out of the load buffer
3607c478bd9Sstevel@tonic-gate	SET_SIZE(scrubphys)
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate#endif	/* lint */
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate#if defined(lint)
3667c478bd9Sstevel@tonic-gate /*
367*750ba224Sanbui * clearphys - Pass in the physical memory address of the checkblock
368*750ba224Sanbui * that you want to push out, cleared with a recognizable pattern,
369*750ba224Sanbui * from the ecache.
370*750ba224Sanbui *
371*750ba224Sanbui * To ensure that the ecc gets recalculated after the bad data is cleared,
372*750ba224Sanbui * we must write out enough data to fill the w$ line (64 bytes). So we read
373*750ba224Sanbui * in an entire ecache subblock's worth of data, and write it back out.
374*750ba224Sanbui * Then we overwrite the 16 bytes of bad data with the pattern.
3757c478bd9Sstevel@tonic-gate */
3767c478bd9Sstevel@tonic-gate/* ARGSUSED */
3777c478bd9Sstevel@tonic-gatevoid
3787c478bd9Sstevel@tonic-gateclearphys(uint64_t paddr, int ecache_set_size, int ecache_linesize)
3797c478bd9Sstevel@tonic-gate{
3807c478bd9Sstevel@tonic-gate}
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate#else	/* lint */
3837c478bd9Sstevel@tonic-gate	ENTRY(clearphys)
3847c478bd9Sstevel@tonic-gate	/* turn off IE, AM bits */
3857c478bd9Sstevel@tonic-gate	rdpr	%pstate, %o4
3867c478bd9Sstevel@tonic-gate	andn	%o4, PSTATE_IE | PSTATE_AM, %o5
3877c478bd9Sstevel@tonic-gate	wrpr	%o5, %g0, %pstate
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate	/* turn off NCEEN */
3907c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_ESTATE_ERR, %o5
3917c478bd9Sstevel@tonic-gate	andn	%o5, EN_REG_NCEEN, %o3
3927c478bd9Sstevel@tonic-gate	stxa	%o3, [%g0]ASI_ESTATE_ERR
3937c478bd9Sstevel@tonic-gate	membar	#Sync
3947c478bd9Sstevel@tonic-gate
395*750ba224Sanbui	/* align address passed with 64 bytes subblock size */
396*750ba224Sanbui	mov	CH_ECACHE_SUBBLK_SIZE, %o2
397*750ba224Sanbui	andn	%o0, (CH_ECACHE_SUBBLK_SIZE - 1), %g1
398*750ba224Sanbui
399*750ba224Sanbui	/* move the good data into the W$ */
4007c478bd9Sstevel@tonic-gate1:
4017c478bd9Sstevel@tonic-gate	subcc	%o2, 8, %o2
402*750ba224Sanbui	ldxa	[%g1 + %o2]ASI_MEM, %g2
4037c478bd9Sstevel@tonic-gate	bge	1b
404*750ba224Sanbui	  stxa	%g2, [%g1 + %o2]ASI_MEM
405*750ba224Sanbui
406*750ba224Sanbui	/* now overwrite the bad data */
407*750ba224Sanbui	setx	0xbadecc00badecc01, %g1, %g2
408*750ba224Sanbui	stxa	%g2, [%o0]ASI_MEM
409*750ba224Sanbui	mov	8, %g1
410*750ba224Sanbui	stxa	%g2, [%o0 + %g1]ASI_MEM
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate	ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3)
4137c478bd9Sstevel@tonic-gate	casxa	[%o0]ASI_MEM, %g0, %g0
4147c478bd9Sstevel@tonic-gate	ECACHE_REFLUSH_LINE(%o1, %o2, %o3)
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate	/* clear the AFSR */
4177c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_AFSR, %o1
4187c478bd9Sstevel@tonic-gate	stxa	%o1, [%g0]ASI_AFSR
4197c478bd9Sstevel@tonic-gate	membar	#Sync
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate	/* turn NCEEN back on */
4227c478bd9Sstevel@tonic-gate	stxa	%o5, [%g0]ASI_ESTATE_ERR
4237c478bd9Sstevel@tonic-gate	membar	#Sync
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate	/* return and re-enable IE and AM */
4267c478bd9Sstevel@tonic-gate	retl
4277c478bd9Sstevel@tonic-gate	  wrpr	%g0, %o4, %pstate
4287c478bd9Sstevel@tonic-gate	SET_SIZE(clearphys)
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate#endif	/* lint */
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate#if defined(lint)
4347c478bd9Sstevel@tonic-gate/*
4357c478bd9Sstevel@tonic-gate * Cheetah Ecache displacement flush the specified line from the E$
4367c478bd9Sstevel@tonic-gate *
4377c478bd9Sstevel@tonic-gate * Register usage:
4387c478bd9Sstevel@tonic-gate *	%o0 - 64 bit physical address for flushing
4397c478bd9Sstevel@tonic-gate *	%o1 - Ecache set size
4407c478bd9Sstevel@tonic-gate */
4417c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4427c478bd9Sstevel@tonic-gatevoid
4437c478bd9Sstevel@tonic-gateecache_flush_line(uint64_t flushaddr, int ec_set_size)
4447c478bd9Sstevel@tonic-gate{
4457c478bd9Sstevel@tonic-gate}
4467c478bd9Sstevel@tonic-gate#else	/* lint */
4477c478bd9Sstevel@tonic-gate	ENTRY(ecache_flush_line)
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate	ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3)
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate	retl
4527c478bd9Sstevel@tonic-gate	  nop
4537c478bd9Sstevel@tonic-gate	SET_SIZE(ecache_flush_line)
4547c478bd9Sstevel@tonic-gate#endif	/* lint */
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate#if defined(lint)
4587c478bd9Sstevel@tonic-gate/*
4597c478bd9Sstevel@tonic-gate * This routine will not be called in Cheetah systems.
4607c478bd9Sstevel@tonic-gate */
4617c478bd9Sstevel@tonic-gatevoid
4627c478bd9Sstevel@tonic-gateflush_ipb(void)
4637c478bd9Sstevel@tonic-gate{ return; }
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate#else	/* lint */
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate	ENTRY(flush_ipb)
4687c478bd9Sstevel@tonic-gate	retl
4697c478bd9Sstevel@tonic-gate	nop
4707c478bd9Sstevel@tonic-gate	SET_SIZE(flush_ipb)
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate#endif	/* lint */
473