xref: /illumos-gate/usr/src/uts/sun4u/sys/cheetahasm.h (revision 7c478bd95313f5f23a4c958a745db2134aa0324)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #ifndef	_CHEETAHASM_H
28*7c478bd9Sstevel@tonic-gate #define	_CHEETAHASM_H
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
33*7c478bd9Sstevel@tonic-gate extern "C" {
34*7c478bd9Sstevel@tonic-gate #endif
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #ifdef _ASM
37*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #define	ASM_LD(reg, symbol)						\
40*7c478bd9Sstevel@tonic-gate 	sethi	%hi(symbol), reg;					\
41*7c478bd9Sstevel@tonic-gate 	ld	[reg + %lo(symbol)], reg;				\
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate #define	ASM_LDX(reg, symbol)						\
44*7c478bd9Sstevel@tonic-gate 	sethi	%hi(symbol), reg;					\
45*7c478bd9Sstevel@tonic-gate 	ldx	[reg + %lo(symbol)], reg;				\
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #define	ASM_JMP(reg, symbol)						\
48*7c478bd9Sstevel@tonic-gate 	sethi	%hi(symbol), reg;					\
49*7c478bd9Sstevel@tonic-gate 	jmp	reg + %lo(symbol);					\
50*7c478bd9Sstevel@tonic-gate 	nop
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate /*
53*7c478bd9Sstevel@tonic-gate  * Macro for getting to offset from 'cpu_private' ptr.  The 'cpu_private'
54*7c478bd9Sstevel@tonic-gate  * ptr is in the machcpu structure.
55*7c478bd9Sstevel@tonic-gate  *  off_reg:  Register offset from 'cpu_private' ptr.
56*7c478bd9Sstevel@tonic-gate  *  scr1:    Scratch, ptr is returned in this register.
57*7c478bd9Sstevel@tonic-gate  *  scr2:    Scratch
58*7c478bd9Sstevel@tonic-gate  *  label:   Label to branch to if cpu_private ptr is null/zero.
59*7c478bd9Sstevel@tonic-gate  */
60*7c478bd9Sstevel@tonic-gate #define	GET_CPU_PRIVATE_PTR(off_reg, scr1, scr2, label)			\
61*7c478bd9Sstevel@tonic-gate 	CPU_ADDR(scr1, scr2);						\
62*7c478bd9Sstevel@tonic-gate 	ldn	[scr1 + CPU_PRIVATE], scr1;				\
63*7c478bd9Sstevel@tonic-gate 	cmp	scr1, 0;						\
64*7c478bd9Sstevel@tonic-gate 	be	label;							\
65*7c478bd9Sstevel@tonic-gate 	  nop;								\
66*7c478bd9Sstevel@tonic-gate 	add	scr1, off_reg, scr1
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate  * Macro version of get_dcache_dtag.  We use this macro in the
70*7c478bd9Sstevel@tonic-gate  * CPU logout code. Since the Dcache is virtually indexed, only
71*7c478bd9Sstevel@tonic-gate  * bits [12:5] of the AFAR can be used so we need to search through
72*7c478bd9Sstevel@tonic-gate  * 8 indexes (4 ways + bit 13) in order to find the tag we want.
73*7c478bd9Sstevel@tonic-gate  *   afar:  input AFAR, not modified.
74*7c478bd9Sstevel@tonic-gate  *   datap: input ptr to ch_dc_data_t, at end pts to end of ch_dc_data_t.
75*7c478bd9Sstevel@tonic-gate  *   scr1:  scratch.
76*7c478bd9Sstevel@tonic-gate  *   scr2:  scratch, will hold tag to look for.
77*7c478bd9Sstevel@tonic-gate  *   scr3:  used for Dcache index, loops through 4 ways.
78*7c478bd9Sstevel@tonic-gate  */
79*7c478bd9Sstevel@tonic-gate #define	GET_DCACHE_DTAG(afar, datap, scr1, scr2, scr3)			\
80*7c478bd9Sstevel@tonic-gate 	set	CH_DCACHE_IDX_MASK, scr3;				\
81*7c478bd9Sstevel@tonic-gate 	and	afar, scr3, scr3;					\
82*7c478bd9Sstevel@tonic-gate 	srlx	afar, CH_DCTAG_PA_SHIFT, scr2;				\
83*7c478bd9Sstevel@tonic-gate 	b	1f;							\
84*7c478bd9Sstevel@tonic-gate 	  or	scr2, CH_DCTAG_VALID_BIT, scr2; /* tag we want */	\
85*7c478bd9Sstevel@tonic-gate 	.align	128;							\
86*7c478bd9Sstevel@tonic-gate 1:									\
87*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_DC_TAG, scr1;		/* read tag */		\
88*7c478bd9Sstevel@tonic-gate 	cmp	scr1, scr2;						\
89*7c478bd9Sstevel@tonic-gate 	bne	4f;				/* not found? */	\
90*7c478bd9Sstevel@tonic-gate 	  nop;								\
91*7c478bd9Sstevel@tonic-gate 	stxa	scr3, [datap + CH_DC_IDX]%asi;	/* store index */	\
92*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_DC_TAG]%asi;	/* store tag */		\
93*7c478bd9Sstevel@tonic-gate 	membar	#Sync;			/* Cheetah PRM 10.6.3 */	\
94*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_DC_UTAG, scr1;	/* read utag */		\
95*7c478bd9Sstevel@tonic-gate 	membar	#Sync;			/* Cheetah PRM 10.6.3 */	\
96*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_DC_UTAG]%asi;				\
97*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_DC_SNP_TAG, scr1;	/* read snoop tag */	\
98*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_DC_SNTAG]%asi;			\
99*7c478bd9Sstevel@tonic-gate 	add	datap, CH_DC_DATA, datap;				\
100*7c478bd9Sstevel@tonic-gate 	clr	scr2;							\
101*7c478bd9Sstevel@tonic-gate 2:									\
102*7c478bd9Sstevel@tonic-gate 	membar	#Sync;			/* Cheetah PRM 10.6.1 */	\
103*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3 + scr2]ASI_DC_DATA, scr1;	/* read data */		\
104*7c478bd9Sstevel@tonic-gate 	membar	#Sync;			/* Cheetah PRM 10.6.1 */	\
105*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap]%asi;					\
106*7c478bd9Sstevel@tonic-gate 	add	datap, 8, datap;					\
107*7c478bd9Sstevel@tonic-gate 	cmp	scr2, CH_DC_DATA_REG_SIZE - 8;				\
108*7c478bd9Sstevel@tonic-gate 	blt	2b;							\
109*7c478bd9Sstevel@tonic-gate 	  add	scr2, 8, scr2;						\
110*7c478bd9Sstevel@tonic-gate 									\
111*7c478bd9Sstevel@tonic-gate 	GET_CPU_IMPL(scr2);	/* Parity bits are elsewhere for */	\
112*7c478bd9Sstevel@tonic-gate 	cmp	scr2, PANTHER_IMPL;	/* panther processors. */	\
113*7c478bd9Sstevel@tonic-gate 	bne,a	5f;			/* Done if not panther. */	\
114*7c478bd9Sstevel@tonic-gate 	  add	datap, 8, datap; /* Skip to the end of the struct. */	\
115*7c478bd9Sstevel@tonic-gate 	clr	scr2;							\
116*7c478bd9Sstevel@tonic-gate 	add	datap, 7, datap; /* offset of the last parity byte */	\
117*7c478bd9Sstevel@tonic-gate 	mov	1, scr1;						\
118*7c478bd9Sstevel@tonic-gate 	sll	scr1, PN_DC_DATA_PARITY_BIT_SHIFT, scr1;		\
119*7c478bd9Sstevel@tonic-gate 	or	scr3, scr1, scr3; /* add DC_data_parity bit to index */	\
120*7c478bd9Sstevel@tonic-gate 3:									\
121*7c478bd9Sstevel@tonic-gate 	membar	#Sync;			/* Cheetah PRM 10.6.1 */	\
122*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3 + scr2]ASI_DC_DATA, scr1;	/* read parity bits */	\
123*7c478bd9Sstevel@tonic-gate 	membar	#Sync;			/* Cheetah PRM 10.6.1 */	\
124*7c478bd9Sstevel@tonic-gate 	stba	scr1, [datap]%asi;					\
125*7c478bd9Sstevel@tonic-gate 	dec	datap;							\
126*7c478bd9Sstevel@tonic-gate 	cmp	scr2, CH_DC_DATA_REG_SIZE - 8;				\
127*7c478bd9Sstevel@tonic-gate 	blt	3b;							\
128*7c478bd9Sstevel@tonic-gate 	  add	scr2, 8, scr2;						\
129*7c478bd9Sstevel@tonic-gate 	b	5f;							\
130*7c478bd9Sstevel@tonic-gate 	  add	datap, 5, datap; /* set pointer to end of our struct */	\
131*7c478bd9Sstevel@tonic-gate 4:									\
132*7c478bd9Sstevel@tonic-gate 	set	CH_DCACHE_IDX_INCR, scr1;	/* incr. idx (scr3) */	\
133*7c478bd9Sstevel@tonic-gate 	add	scr3, scr1, scr3;					\
134*7c478bd9Sstevel@tonic-gate 	set	CH_DCACHE_IDX_LIMIT, scr1;	/* done? */		\
135*7c478bd9Sstevel@tonic-gate 	cmp	scr3, scr1;						\
136*7c478bd9Sstevel@tonic-gate 	blt	1b;							\
137*7c478bd9Sstevel@tonic-gate 	  nop;								\
138*7c478bd9Sstevel@tonic-gate 	add	datap, CH_DC_DATA_SIZE, datap;				\
139*7c478bd9Sstevel@tonic-gate 5:
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate /*
142*7c478bd9Sstevel@tonic-gate  * Macro version of get_icache_dtag.  We use this macro in the CPU
143*7c478bd9Sstevel@tonic-gate  * logout code. If the Icache is on, we don't want to capture the data.
144*7c478bd9Sstevel@tonic-gate  *   afar:  input AFAR, not modified.
145*7c478bd9Sstevel@tonic-gate  *   datap: input ptr to ch_ic_data_t, at end pts to end of ch_ic_data_t.
146*7c478bd9Sstevel@tonic-gate  *   scr1:  scratch.
147*7c478bd9Sstevel@tonic-gate  *   scr2:  scratch, will hold tag to look for.
148*7c478bd9Sstevel@tonic-gate  *   scr3:  used for Icache index, loops through 4 ways.
149*7c478bd9Sstevel@tonic-gate  * Note: For Panther, the Icache is virtually indexed and increases in
150*7c478bd9Sstevel@tonic-gate  * size to 64KB (instead of 32KB) with a line size of 64 bytes (instead
151*7c478bd9Sstevel@tonic-gate  * of 32). This means the IC_addr index bits[14:7] for Panther now
152*7c478bd9Sstevel@tonic-gate  * correspond to VA bits[13:6]. But since it is virtually indexed, we
153*7c478bd9Sstevel@tonic-gate  * still mask out only bits[12:5] from the AFAR (we have to manually
154*7c478bd9Sstevel@tonic-gate  * check bit 13). In order to make this code work for all processors,
155*7c478bd9Sstevel@tonic-gate  * we end up checking twice as many indexes (8 instead of 4) as required
156*7c478bd9Sstevel@tonic-gate  * for non-Panther CPUs and saving off twice as much data (16 instructions
157*7c478bd9Sstevel@tonic-gate  * instead of just 8).
158*7c478bd9Sstevel@tonic-gate  */
159*7c478bd9Sstevel@tonic-gate #define	GET_ICACHE_DTAG(afar, datap, scr1, scr2, scr3)			\
160*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_DCU, scr1;					\
161*7c478bd9Sstevel@tonic-gate 	btst	DCU_IC, scr1;		/* is Icache enabled? */	\
162*7c478bd9Sstevel@tonic-gate 	bne,a	6f;			/* yes, don't capture */	\
163*7c478bd9Sstevel@tonic-gate 	  add	datap, CH_IC_DATA_SIZE, datap;	/* anul if no branch */	\
164*7c478bd9Sstevel@tonic-gate 	GET_CPU_IMPL(scr2);	/* Panther only uses VA[13:6] */	\
165*7c478bd9Sstevel@tonic-gate 	cmp	scr2, PANTHER_IMPL;	/* and we also want to mask */	\
166*7c478bd9Sstevel@tonic-gate 	be	1f;			/* out bit 13 since the */	\
167*7c478bd9Sstevel@tonic-gate 	  nop;				/* Panther I$ is VIPT. */	\
168*7c478bd9Sstevel@tonic-gate 	set	CH_ICACHE_IDX_MASK, scr3;				\
169*7c478bd9Sstevel@tonic-gate 	b	2f;							\
170*7c478bd9Sstevel@tonic-gate 	  nop;								\
171*7c478bd9Sstevel@tonic-gate 1:									\
172*7c478bd9Sstevel@tonic-gate 	set	PN_ICACHE_VA_IDX_MASK, scr3;				\
173*7c478bd9Sstevel@tonic-gate 2:									\
174*7c478bd9Sstevel@tonic-gate 	and	afar, scr3, scr3;					\
175*7c478bd9Sstevel@tonic-gate 	sllx	scr3, CH_ICACHE_IDX_SHIFT, scr3;			\
176*7c478bd9Sstevel@tonic-gate 	srlx	afar, CH_ICPATAG_SHIFT, scr2;	/* pa tag we want */	\
177*7c478bd9Sstevel@tonic-gate 	andn	scr2, CH_ICPATAG_LBITS, scr2;	/* mask off lower */	\
178*7c478bd9Sstevel@tonic-gate 	b	3f;							\
179*7c478bd9Sstevel@tonic-gate 	  nop;								\
180*7c478bd9Sstevel@tonic-gate 	.align	128;							\
181*7c478bd9Sstevel@tonic-gate 3:									\
182*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_IC_TAG, scr1;		/* read pa tag */	\
183*7c478bd9Sstevel@tonic-gate 	andn	scr1, CH_ICPATAG_LBITS, scr1;	/* mask off lower */	\
184*7c478bd9Sstevel@tonic-gate 	cmp	scr1, scr2;						\
185*7c478bd9Sstevel@tonic-gate 	bne	5f;				/* not found? */	\
186*7c478bd9Sstevel@tonic-gate 	  nop;								\
187*7c478bd9Sstevel@tonic-gate 	stxa	scr3, [datap + CH_IC_IDX]%asi;	/* store index */	\
188*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_IC_PATAG]%asi; /* store pa tag */	\
189*7c478bd9Sstevel@tonic-gate 	add	scr3, CH_ICTAG_UTAG, scr3;	/* read utag */		\
190*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_IC_TAG, scr1;					\
191*7c478bd9Sstevel@tonic-gate 	add	scr3, (CH_ICTAG_UPPER - CH_ICTAG_UTAG), scr3;		\
192*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_IC_UTAG]%asi;				\
193*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_IC_TAG, scr1;		/* read upper tag */	\
194*7c478bd9Sstevel@tonic-gate 	add	scr3, (CH_ICTAG_LOWER - CH_ICTAG_UPPER), scr3;		\
195*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_IC_UPPER]%asi;			\
196*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_IC_TAG, scr1;		/* read lower tag */	\
197*7c478bd9Sstevel@tonic-gate 	andn	scr3, CH_ICTAG_TMASK, scr3;				\
198*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_IC_LOWER]%asi;			\
199*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_IC_SNP_TAG, scr1;	/* read snoop tag */	\
200*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_IC_SNTAG]%asi;			\
201*7c478bd9Sstevel@tonic-gate 	add	datap, CH_IC_DATA, datap;				\
202*7c478bd9Sstevel@tonic-gate 	clr	scr2;							\
203*7c478bd9Sstevel@tonic-gate 4:									\
204*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3 + scr2]ASI_IC_DATA, scr1;	/* read ins. data */	\
205*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap]%asi;					\
206*7c478bd9Sstevel@tonic-gate 	add	datap, 8, datap;					\
207*7c478bd9Sstevel@tonic-gate 	cmp	scr2, PN_IC_DATA_REG_SIZE - 8;				\
208*7c478bd9Sstevel@tonic-gate 	blt	4b;							\
209*7c478bd9Sstevel@tonic-gate 	  add	scr2, 8, scr2;						\
210*7c478bd9Sstevel@tonic-gate 	b	6f;							\
211*7c478bd9Sstevel@tonic-gate 	  nop;								\
212*7c478bd9Sstevel@tonic-gate 5:									\
213*7c478bd9Sstevel@tonic-gate 	set	CH_ICACHE_IDX_INCR, scr1;	/* incr. idx (scr3) */	\
214*7c478bd9Sstevel@tonic-gate 	add	scr3, scr1, scr3;					\
215*7c478bd9Sstevel@tonic-gate 	set	PN_ICACHE_IDX_LIMIT, scr1;	/* done? */		\
216*7c478bd9Sstevel@tonic-gate 	cmp	scr3, scr1;						\
217*7c478bd9Sstevel@tonic-gate 	blt	3b;							\
218*7c478bd9Sstevel@tonic-gate 	  nop;								\
219*7c478bd9Sstevel@tonic-gate 	add	datap, CH_IC_DATA_SIZE, datap;				\
220*7c478bd9Sstevel@tonic-gate 6:
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate #if defined(JALAPENO) || defined(SERRANO)
223*7c478bd9Sstevel@tonic-gate /*
224*7c478bd9Sstevel@tonic-gate  * Macro version of get_ecache_dtag.  We use this macro in the
225*7c478bd9Sstevel@tonic-gate  * CPU logout code.
226*7c478bd9Sstevel@tonic-gate  *   afar:	input AFAR, not modified
227*7c478bd9Sstevel@tonic-gate  *   datap:	Ptr to ch_ec_data_t, at end pts just past ch_ec_data_t.
228*7c478bd9Sstevel@tonic-gate  *   ec_way:	Constant value (way number)
229*7c478bd9Sstevel@tonic-gate  *   scr1:      Scratch
230*7c478bd9Sstevel@tonic-gate  *   scr2:	Scratch.
231*7c478bd9Sstevel@tonic-gate  *   scr3:	Scratch.
232*7c478bd9Sstevel@tonic-gate  */
233*7c478bd9Sstevel@tonic-gate #define	GET_ECACHE_DTAG(afar, datap, ec_way, scr1, scr2, scr3)		\
234*7c478bd9Sstevel@tonic-gate 	mov	ec_way, scr1;						\
235*7c478bd9Sstevel@tonic-gate 	and	scr1, JP_ECACHE_NWAY - 1, scr1;	/* mask E$ way bits */	\
236*7c478bd9Sstevel@tonic-gate 	sllx	scr1, JP_EC_TAG_DATA_WAY_SHIFT, scr1;			\
237*7c478bd9Sstevel@tonic-gate 	set	((JP_ECACHE_MAX_SIZE / JP_ECACHE_NWAY) - 1), scr2;	\
238*7c478bd9Sstevel@tonic-gate 	and	afar, scr2, scr3;		/* get set offset */	\
239*7c478bd9Sstevel@tonic-gate 	andn	scr3, (JP_ECACHE_MAX_LSIZE - 1), scr3; /* VA<5:0>=0 */	\
240*7c478bd9Sstevel@tonic-gate 	or	scr3, scr1, scr3;		/* or WAY bits */	\
241*7c478bd9Sstevel@tonic-gate 	b	1f;							\
242*7c478bd9Sstevel@tonic-gate 	  stxa	scr3, [datap + CH_EC_IDX]%asi;	/* store E$ index */	\
243*7c478bd9Sstevel@tonic-gate 	.align	64;							\
244*7c478bd9Sstevel@tonic-gate 1:									\
245*7c478bd9Sstevel@tonic-gate 	JP_EC_DIAG_ACCESS_MEMBAR;					\
246*7c478bd9Sstevel@tonic-gate 	ldxa    [scr3]ASI_EC_DIAG, scr1;	/* get E$ tag */	\
247*7c478bd9Sstevel@tonic-gate 	JP_EC_DIAG_ACCESS_MEMBAR;					\
248*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_EC_TAG]%asi;				\
249*7c478bd9Sstevel@tonic-gate 	add	datap, CH_EC_DATA, datap;				\
250*7c478bd9Sstevel@tonic-gate 2:									\
251*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_EC_R, %g0;		/* ld E$ stging regs */	\
252*7c478bd9Sstevel@tonic-gate 	clr	scr1;							\
253*7c478bd9Sstevel@tonic-gate 3:						/* loop thru 5 regs */	\
254*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_EC_DATA, scr2;				\
255*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap]%asi;					\
256*7c478bd9Sstevel@tonic-gate 	add	datap, 8, datap;					\
257*7c478bd9Sstevel@tonic-gate 	cmp	scr1, CH_ECACHE_STGREG_TOTALSIZE - 8;			\
258*7c478bd9Sstevel@tonic-gate 	bne	3b;							\
259*7c478bd9Sstevel@tonic-gate 	   add	scr1, 8, scr1;						\
260*7c478bd9Sstevel@tonic-gate 	btst	CH_ECACHE_STGREG_SIZE, scr3;	/* done? */		\
261*7c478bd9Sstevel@tonic-gate 	beq	2b;							\
262*7c478bd9Sstevel@tonic-gate 	   add	scr3, CH_ECACHE_STGREG_SIZE, scr3
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate #define	GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3)			\
265*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 0, scr1, scr2, scr3);		\
266*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 1, scr1, scr2, scr3);		\
267*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 2, scr1, scr2, scr3);		\
268*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 3, scr1, scr2, scr3);		\
269*7c478bd9Sstevel@tonic-gate 	add	datap, (CHD_EC_DATA_SETS-4)*CH_EC_DATA_SIZE, datap;	\
270*7c478bd9Sstevel@tonic-gate 	add	datap, CH_EC_DATA_SIZE * PN_L2_NWAYS, datap;		\
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate /*
273*7c478bd9Sstevel@tonic-gate  * Jalapeno does not have cores so these macros are null.
274*7c478bd9Sstevel@tonic-gate  */
275*7c478bd9Sstevel@tonic-gate #define	PARK_SIBLING_CORE(dcucr_reg, scr1, scr2)
276*7c478bd9Sstevel@tonic-gate #define	UNPARK_SIBLING_CORE(dcucr_reg, scr1, scr2)
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate #if defined(JALAPENO)
279*7c478bd9Sstevel@tonic-gate /*
280*7c478bd9Sstevel@tonic-gate  * Jalapeno gets primary AFSR and AFAR.  All bits in the AFSR except
281*7c478bd9Sstevel@tonic-gate  * the fatal error bits are cleared.
282*7c478bd9Sstevel@tonic-gate  *	datap:		pointer to cpu logout structure.
283*7c478bd9Sstevel@tonic-gate  *	afar:		returned primary AFAR value.
284*7c478bd9Sstevel@tonic-gate  *	scr1:		scratch
285*7c478bd9Sstevel@tonic-gate  *	scr2:		scratch
286*7c478bd9Sstevel@tonic-gate  */
287*7c478bd9Sstevel@tonic-gate #define	GET_AFSR_AFAR(datap, afar, scr1, scr2)				\
288*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_AFAR, afar;					\
289*7c478bd9Sstevel@tonic-gate 	stxa	afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi;	\
290*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_AFSR, scr2;					\
291*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR)]%asi;	\
292*7c478bd9Sstevel@tonic-gate 	sethi	%hh(C_AFSR_FATAL_ERRS), scr1;				\
293*7c478bd9Sstevel@tonic-gate 	sllx	scr1, 32, scr1;						\
294*7c478bd9Sstevel@tonic-gate 	bclr	scr1, scr2;	/* Clear fatal error bits here, so */	\
295*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [%g0]ASI_AFSR; /* they're left as is in AFSR */	\
296*7c478bd9Sstevel@tonic-gate 	membar	#Sync
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate /*
299*7c478bd9Sstevel@tonic-gate  * Jalapeno has no shadow AFAR, null operation.
300*7c478bd9Sstevel@tonic-gate  */
301*7c478bd9Sstevel@tonic-gate #define	GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3)
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate #elif defined(SERRANO)
304*7c478bd9Sstevel@tonic-gate /*
305*7c478bd9Sstevel@tonic-gate  * Serrano gets primary AFSR and AFAR.  All bits in the AFSR except
306*7c478bd9Sstevel@tonic-gate  * the fatal error bits are cleared.  For Serrano, we also save the
307*7c478bd9Sstevel@tonic-gate  * AFAR2 register.
308*7c478bd9Sstevel@tonic-gate  *	datap:	pointer to cpu logout structure.
309*7c478bd9Sstevel@tonic-gate  *	afar:	returned primary AFAR value.
310*7c478bd9Sstevel@tonic-gate  *	scr1:	scratch
311*7c478bd9Sstevel@tonic-gate  *	scr2:	scratch
312*7c478bd9Sstevel@tonic-gate  */
313*7c478bd9Sstevel@tonic-gate #define GET_AFSR_AFAR(datap, afar, scr1, scr2)				\
314*7c478bd9Sstevel@tonic-gate 	set	ASI_MCU_AFAR2_VA, scr1;					\
315*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_MCU_CTRL, afar;				\
316*7c478bd9Sstevel@tonic-gate 	stxa	afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR2)]%asi;	\
317*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_AFAR, afar;					\
318*7c478bd9Sstevel@tonic-gate 	stxa	afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi;	\
319*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_AFSR, scr2;					\
320*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR)]%asi;	\
321*7c478bd9Sstevel@tonic-gate 	sethi	%hh(C_AFSR_FATAL_ERRS), scr1;				\
322*7c478bd9Sstevel@tonic-gate 	sllx	scr1, 32, scr1;						\
323*7c478bd9Sstevel@tonic-gate 	bclr	scr1, scr2;	/* Clear fatal error bits here, so */	\
324*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [%g0]ASI_AFSR; /* they're left as is in AFSR */ 	\
325*7c478bd9Sstevel@tonic-gate 	membar	#Sync
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate /*
328*7c478bd9Sstevel@tonic-gate  * Serrano needs to capture E$, D$ and I$ lines associated with afar2.
329*7c478bd9Sstevel@tonic-gate  *      afar:   scratch, holds afar2.
330*7c478bd9Sstevel@tonic-gate  *      datap:  pointer to cpu logout structure
331*7c478bd9Sstevel@tonic-gate  *      scr1:   scratch
332*7c478bd9Sstevel@tonic-gate  *      scr2:   scratch
333*7c478bd9Sstevel@tonic-gate  *      scr3:   scratch
334*7c478bd9Sstevel@tonic-gate  */
335*7c478bd9Sstevel@tonic-gate #define	GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3)		\
336*7c478bd9Sstevel@tonic-gate 	ldxa	[datap + (CH_CLO_DATA + CH_CHD_AFAR2)]%asi, afar;	\
337*7c478bd9Sstevel@tonic-gate 	add	datap, CH_CLO_SDW_DATA + CH_CHD_EC_DATA, datap;		\
338*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3);		\
339*7c478bd9Sstevel@tonic-gate 	GET_DCACHE_DTAG(afar, datap, scr1, scr2, scr3);			\
340*7c478bd9Sstevel@tonic-gate 	GET_ICACHE_DTAG(afar, datap, scr1, scr2, scr3);			\
341*7c478bd9Sstevel@tonic-gate 	sub	datap, CH_CPU_LOGOUT_SIZE, datap
342*7c478bd9Sstevel@tonic-gate #endif /* SERRANO */
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate #elif defined(CHEETAH_PLUS)
345*7c478bd9Sstevel@tonic-gate /*
346*7c478bd9Sstevel@tonic-gate  * Macro version of get_ecache_dtag.  We use this macro in the
347*7c478bd9Sstevel@tonic-gate  * CPU logout code.
348*7c478bd9Sstevel@tonic-gate  *   afar:	input AFAR, not modified.
349*7c478bd9Sstevel@tonic-gate  *   datap:	Ptr to ch_ec_data_t, at end pts just past ch_ec_data_t.
350*7c478bd9Sstevel@tonic-gate  *   pn_way:	ecache way for panther (value = 0-3). For non-panther
351*7c478bd9Sstevel@tonic-gate  *		cpus, this macro will be called with pn_way = 0.
352*7c478bd9Sstevel@tonic-gate  *   scr1:	Scratch.
353*7c478bd9Sstevel@tonic-gate  *   scr2:	Scratch.
354*7c478bd9Sstevel@tonic-gate  *   scr3:	Scratch.
355*7c478bd9Sstevel@tonic-gate  */
356*7c478bd9Sstevel@tonic-gate #define	GET_ECACHE_DTAG(afar, datap, pn_way, scr1, scr2, scr3)		\
357*7c478bd9Sstevel@tonic-gate 	mov	afar, scr3;						\
358*7c478bd9Sstevel@tonic-gate 	andn	scr3, (CH_ECACHE_SUBBLK_SIZE - 1), scr3; /* VA<5:0>=0 */\
359*7c478bd9Sstevel@tonic-gate 	set	(CH_ECACHE_8M_SIZE - 1), scr2;				\
360*7c478bd9Sstevel@tonic-gate 	and	scr3, scr2, scr3;		/* VA<63:23>=0 */	\
361*7c478bd9Sstevel@tonic-gate 	mov	pn_way, scr1;	/* panther L3$ is 4-way so we ...    */	\
362*7c478bd9Sstevel@tonic-gate 	sllx	scr1, PN_L3_WAY_SHIFT, scr1;	/* need to mask...   */	\
363*7c478bd9Sstevel@tonic-gate 	or	scr3, scr1, scr3;	/* in the way bits <24:23>.  */	\
364*7c478bd9Sstevel@tonic-gate 	b	1f;							\
365*7c478bd9Sstevel@tonic-gate 	   stxa	scr3, [datap + CH_EC_IDX]%asi;	/* store E$ index */	\
366*7c478bd9Sstevel@tonic-gate 	.align	64;							\
367*7c478bd9Sstevel@tonic-gate 1:									\
368*7c478bd9Sstevel@tonic-gate 	ldxa    [scr3]ASI_EC_DIAG, scr1;	/* get E$ tag */	\
369*7c478bd9Sstevel@tonic-gate 	stxa     scr1, [datap + CH_EC_TAG]%asi;				\
370*7c478bd9Sstevel@tonic-gate 	set	CHP_ECACHE_IDX_TAG_ECC, scr1;				\
371*7c478bd9Sstevel@tonic-gate 	or	scr3, scr1, scr1;					\
372*7c478bd9Sstevel@tonic-gate 	ldxa    [scr1]ASI_EC_DIAG, scr1;	/* get E$ tag ECC */	\
373*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_EC_TAG_ECC]%asi;			\
374*7c478bd9Sstevel@tonic-gate 	add	datap, CH_EC_DATA, datap;				\
375*7c478bd9Sstevel@tonic-gate 2:									\
376*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_EC_R, %g0;		/* ld E$ stging regs */	\
377*7c478bd9Sstevel@tonic-gate 	clr	scr1;							\
378*7c478bd9Sstevel@tonic-gate 3:						/* loop thru 5 regs */	\
379*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_EC_DATA, scr2;				\
380*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap]%asi;					\
381*7c478bd9Sstevel@tonic-gate 	add	datap, 8, datap;					\
382*7c478bd9Sstevel@tonic-gate 	cmp	scr1, CH_ECACHE_STGREG_TOTALSIZE - 8;			\
383*7c478bd9Sstevel@tonic-gate 	bne	3b;							\
384*7c478bd9Sstevel@tonic-gate 	   add	scr1, 8, scr1;						\
385*7c478bd9Sstevel@tonic-gate 	btst	CH_ECACHE_STGREG_SIZE, scr3;	/* done? */		\
386*7c478bd9Sstevel@tonic-gate 	beq	2b;							\
387*7c478bd9Sstevel@tonic-gate 	   add	scr3, CH_ECACHE_STGREG_SIZE, scr3
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate /*
390*7c478bd9Sstevel@tonic-gate  * If this is a panther, we need to make sure the sibling core is
391*7c478bd9Sstevel@tonic-gate  * parked so that we avoid any race conditions during diagnostic
392*7c478bd9Sstevel@tonic-gate  * accesses to the shared L2 and L3 caches.
393*7c478bd9Sstevel@tonic-gate  * dcucr_reg:	This register will be used to keep track of whether
394*7c478bd9Sstevel@tonic-gate  *		or not we need to unpark the core later.
395*7c478bd9Sstevel@tonic-gate  *		It just so happens that we also use this same register
396*7c478bd9Sstevel@tonic-gate  *		to keep track of our saved DCUCR value so we only touch
397*7c478bd9Sstevel@tonic-gate  *		bit 4 of the register (which is a "reserved" bit in the
398*7c478bd9Sstevel@tonic-gate  *		DCUCR) for keeping track of core parking.
399*7c478bd9Sstevel@tonic-gate  * scr1:	Scratch register.
400*7c478bd9Sstevel@tonic-gate  * scr2:	Scratch register.
401*7c478bd9Sstevel@tonic-gate  */
402*7c478bd9Sstevel@tonic-gate #define	PARK_SIBLING_CORE(dcucr_reg, scr1, scr2)			\
403*7c478bd9Sstevel@tonic-gate 	GET_CPU_IMPL(scr1);						\
404*7c478bd9Sstevel@tonic-gate 	cmp	scr1, PANTHER_IMPL;	/* only park for panthers */	\
405*7c478bd9Sstevel@tonic-gate 	bne,a	%xcc, 2f;						\
406*7c478bd9Sstevel@tonic-gate 	  andn	dcucr_reg, PN_PARKED_OTHER_CORE, dcucr_reg;		\
407*7c478bd9Sstevel@tonic-gate 	set	ASI_CORE_RUNNING_STATUS, scr1;	/* check other core */	\
408*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_CMP_SHARED, scr2;	/* is it running?   */	\
409*7c478bd9Sstevel@tonic-gate 	cmp	scr2, PN_BOTH_CORES_RUNNING;				\
410*7c478bd9Sstevel@tonic-gate 	bne,a	%xcc, 2f;	/* if not running, we are done */	\
411*7c478bd9Sstevel@tonic-gate 	  andn	dcucr_reg, PN_PARKED_OTHER_CORE, dcucr_reg;		\
412*7c478bd9Sstevel@tonic-gate 	or	dcucr_reg, PN_PARKED_OTHER_CORE, dcucr_reg;		\
413*7c478bd9Sstevel@tonic-gate 	set	ASI_CORE_ID, scr1;					\
414*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_CMP_PER_CORE, scr2;				\
415*7c478bd9Sstevel@tonic-gate 	and	scr2, COREID_MASK, scr2;				\
416*7c478bd9Sstevel@tonic-gate 	or	%g0, 1, scr1;		/* find out which core... */	\
417*7c478bd9Sstevel@tonic-gate 	sll	scr1, scr2, scr2;	/* ... we need to park... */	\
418*7c478bd9Sstevel@tonic-gate 1:									\
419*7c478bd9Sstevel@tonic-gate 	set	ASI_CORE_RUNNING_RW, scr1;				\
420*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [scr1]ASI_CMP_SHARED;	/* ... and park it. */	\
421*7c478bd9Sstevel@tonic-gate 	membar	#Sync;				/* spin until the... */	\
422*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_CMP_SHARED, scr1;	/* ... the other...  */	\
423*7c478bd9Sstevel@tonic-gate 	cmp	scr1, scr2;	/* ...core is parked according to... */	\
424*7c478bd9Sstevel@tonic-gate 	bne,a	%xcc, 1b;	/* ...the core running status reg.  */	\
425*7c478bd9Sstevel@tonic-gate 	  nop;								\
426*7c478bd9Sstevel@tonic-gate 2:
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate /*
429*7c478bd9Sstevel@tonic-gate  * The core running this code will unpark its sibling core if the
430*7c478bd9Sstevel@tonic-gate  * sibling core had been parked by the current core earlier in this
431*7c478bd9Sstevel@tonic-gate  * trap handler.
432*7c478bd9Sstevel@tonic-gate  * dcucr_reg:	This register is used to keep track of whether or not
433*7c478bd9Sstevel@tonic-gate  *		we need to unpark our sibling core.
434*7c478bd9Sstevel@tonic-gate  *		It just so happens that we also use this same register
435*7c478bd9Sstevel@tonic-gate  *		to keep track of our saved DCUCR value so we only touch
436*7c478bd9Sstevel@tonic-gate  *		bit 4 of the register (which is a "reserved" bit in the
437*7c478bd9Sstevel@tonic-gate  *		DCUCR) for keeping track of core parking.
438*7c478bd9Sstevel@tonic-gate  * scr1:	Scratch register.
439*7c478bd9Sstevel@tonic-gate  * scr2:	Scratch register.
440*7c478bd9Sstevel@tonic-gate  */
441*7c478bd9Sstevel@tonic-gate #define	UNPARK_SIBLING_CORE(dcucr_reg, scr1, scr2)			\
442*7c478bd9Sstevel@tonic-gate 	btst	PN_PARKED_OTHER_CORE, dcucr_reg;			\
443*7c478bd9Sstevel@tonic-gate 	bz,pt	%xcc, 1f;	/* if nothing to unpark, we are done */	\
444*7c478bd9Sstevel@tonic-gate 	  andn	dcucr_reg, PN_PARKED_OTHER_CORE, dcucr_reg;		\
445*7c478bd9Sstevel@tonic-gate 	set	ASI_CORE_RUNNING_RW, scr1;				\
446*7c478bd9Sstevel@tonic-gate 	set	PN_BOTH_CORES_RUNNING, scr2;	/* we want both...   */	\
447*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [scr1]ASI_CMP_SHARED;	/* ...cores running. */	\
448*7c478bd9Sstevel@tonic-gate 	membar	#Sync;							\
449*7c478bd9Sstevel@tonic-gate 1:
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate /*
452*7c478bd9Sstevel@tonic-gate  * Cheetah+ and Jaguar get both primary and secondary AFSR/AFAR.  All bits
453*7c478bd9Sstevel@tonic-gate  * in the primary AFSR are cleared except the fatal error bits.  For Panther,
454*7c478bd9Sstevel@tonic-gate  * we also have to read and clear the AFSR_EXT, again leaving the fatal
455*7c478bd9Sstevel@tonic-gate  * error bits alone.
456*7c478bd9Sstevel@tonic-gate  *	datap:		pointer to cpu logout structure.
457*7c478bd9Sstevel@tonic-gate  *	afar:		returned primary AFAR value.
458*7c478bd9Sstevel@tonic-gate  *	scr1:		scratch
459*7c478bd9Sstevel@tonic-gate  *	scr2:		scratch
460*7c478bd9Sstevel@tonic-gate  */
461*7c478bd9Sstevel@tonic-gate #define	GET_AFSR_AFAR(datap, afar, scr1, scr2)				\
462*7c478bd9Sstevel@tonic-gate 	set	ASI_SHADOW_REG_VA, scr1;				\
463*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_AFAR, scr2;					\
464*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap + (CH_CLO_SDW_DATA + CH_CHD_AFAR)]%asi;	\
465*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_AFSR, scr2;					\
466*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap + (CH_CLO_SDW_DATA + CH_CHD_AFSR)]%asi;	\
467*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_AFAR, afar;					\
468*7c478bd9Sstevel@tonic-gate 	stxa	afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi;	\
469*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_AFSR, scr2;					\
470*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR)]%asi;	\
471*7c478bd9Sstevel@tonic-gate 	sethi	%hh(C_AFSR_FATAL_ERRS), scr1;				\
472*7c478bd9Sstevel@tonic-gate 	sllx	scr1, 32, scr1;						\
473*7c478bd9Sstevel@tonic-gate 	bclr	scr1, scr2;	/* Clear fatal error bits here, so */ 	\
474*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [%g0]ASI_AFSR; /* they're left as is in AFSR */	\
475*7c478bd9Sstevel@tonic-gate 	membar	#Sync;							\
476*7c478bd9Sstevel@tonic-gate 	GET_CPU_IMPL(scr1);						\
477*7c478bd9Sstevel@tonic-gate 	cmp	scr1, PANTHER_IMPL;					\
478*7c478bd9Sstevel@tonic-gate 	bne	%xcc, 1f;						\
479*7c478bd9Sstevel@tonic-gate 	   nop;								\
480*7c478bd9Sstevel@tonic-gate 	set	ASI_SHADOW_AFSR_EXT_VA, scr1;	/* shadow AFSR_EXT */	\
481*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_AFSR, scr2;					\
482*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap + (CH_CLO_SDW_DATA + CH_CHD_AFSR_EXT)]%asi; \
483*7c478bd9Sstevel@tonic-gate 	set	ASI_AFSR_EXT_VA, scr1;		/* primary AFSR_EXT */	\
484*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_AFSR, scr2;					\
485*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR_EXT)]%asi;	\
486*7c478bd9Sstevel@tonic-gate 	set	C_AFSR_EXT_FATAL_ERRS, scr1;				\
487*7c478bd9Sstevel@tonic-gate 	bclr	scr1, scr2;	/* Clear fatal error bits here, */	\
488*7c478bd9Sstevel@tonic-gate 	set	ASI_AFSR_EXT_VA, scr1;	/* so they're left */		\
489*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [scr1]ASI_AFSR;	/* as is in AFSR_EXT */		\
490*7c478bd9Sstevel@tonic-gate 	membar	#Sync;							\
491*7c478bd9Sstevel@tonic-gate 1:
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate /*
494*7c478bd9Sstevel@tonic-gate  * This macro is used in the CPU logout code to capture diagnostic
495*7c478bd9Sstevel@tonic-gate  * information from the L2 cache on panther processors.
496*7c478bd9Sstevel@tonic-gate  *   afar:	input AFAR, not modified.
497*7c478bd9Sstevel@tonic-gate  *   datap:	Ptr to pn_l2_data_t, at end pts just past pn_l2_data_t.
498*7c478bd9Sstevel@tonic-gate  *   scr1:	Scratch.
499*7c478bd9Sstevel@tonic-gate  *   scr2:	Scratch.
500*7c478bd9Sstevel@tonic-gate  *   scr3:	Scratch.
501*7c478bd9Sstevel@tonic-gate  */
502*7c478bd9Sstevel@tonic-gate #define	GET_PN_L2_CACHE_DTAGS(afar, datap, scr1, scr2, scr3)		\
503*7c478bd9Sstevel@tonic-gate 	mov	afar, scr3;						\
504*7c478bd9Sstevel@tonic-gate 	set	PN_L2_INDEX_MASK, scr1;					\
505*7c478bd9Sstevel@tonic-gate 	and	scr3, scr1, scr3;					\
506*7c478bd9Sstevel@tonic-gate 	b	1f;	/* code to read tags and data should be ...  */	\
507*7c478bd9Sstevel@tonic-gate 	   nop;		/* ...on the same cache line if possible.    */	\
508*7c478bd9Sstevel@tonic-gate 	.align	128;	/* update this line if you add lines below. */	\
509*7c478bd9Sstevel@tonic-gate 1:									\
510*7c478bd9Sstevel@tonic-gate 	stxa	scr3, [datap + CH_EC_IDX]%asi;	/* store L2$ index  */	\
511*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_L2_TAG, scr1;		/* read the L2$ tag */	\
512*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_EC_TAG]%asi;				\
513*7c478bd9Sstevel@tonic-gate 	add	datap, CH_EC_DATA, datap;				\
514*7c478bd9Sstevel@tonic-gate 	clr	scr1;							\
515*7c478bd9Sstevel@tonic-gate 2:									\
516*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3 + scr1]ASI_L2_DATA, scr2;	/* loop through     */	\
517*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap]%asi;		/* <511:256> of L2  */	\
518*7c478bd9Sstevel@tonic-gate 	add	datap, 8, datap;		/* data and record  */	\
519*7c478bd9Sstevel@tonic-gate 	cmp	scr1, (PN_L2_LINESIZE / 2) - 8;	/* it in the cpu    */	\
520*7c478bd9Sstevel@tonic-gate 	bne	2b;				/* logout struct.   */	\
521*7c478bd9Sstevel@tonic-gate 	  add	scr1, 8, scr1;						\
522*7c478bd9Sstevel@tonic-gate 	set	PN_L2_DATA_ECC_SEL, scr2;	/* ECC_sel bit.     */	\
523*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3 + scr2]ASI_L2_DATA, scr2;	/* Read and record  */	\
524*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap]%asi;		/* ecc of <511:256> */	\
525*7c478bd9Sstevel@tonic-gate 	add	datap, 8, datap;					\
526*7c478bd9Sstevel@tonic-gate 3:									\
527*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3 + scr1]ASI_L2_DATA, scr2;	/* loop through     */	\
528*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap]%asi;		/* <255:0> of L2    */	\
529*7c478bd9Sstevel@tonic-gate 	add	datap, 8, datap;		/* data and record  */	\
530*7c478bd9Sstevel@tonic-gate 	cmp	scr1, PN_L2_LINESIZE - 8;	/* it in the cpu    */	\
531*7c478bd9Sstevel@tonic-gate 	bne	3b;				/* logout struct.   */	\
532*7c478bd9Sstevel@tonic-gate 	  add	scr1, 8, scr1;						\
533*7c478bd9Sstevel@tonic-gate 	set	PN_L2_DATA_ECC_SEL, scr2;	/* ECC_sel bit.     */	\
534*7c478bd9Sstevel@tonic-gate 	add	scr2, PN_L2_ECC_LO_REG, scr2;				\
535*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3 + scr2]ASI_L2_DATA, scr2;	/* Read and record  */	\
536*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap]%asi;		/* ecc of <255:0>.  */	\
537*7c478bd9Sstevel@tonic-gate 	add	datap, 8, datap;		/* Advance pointer  */	\
538*7c478bd9Sstevel@tonic-gate 	set	PN_L2_SET_SIZE, scr2;					\
539*7c478bd9Sstevel@tonic-gate 	set	PN_L2_MAX_SET, scr1;					\
540*7c478bd9Sstevel@tonic-gate 	cmp	scr1, scr3;	/* more ways to try for this line? */	\
541*7c478bd9Sstevel@tonic-gate 	bg,a	%xcc, 1b;	/* if so, start over with next way */	\
542*7c478bd9Sstevel@tonic-gate 	  add	scr3, scr2, scr3
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate /*
545*7c478bd9Sstevel@tonic-gate  * Cheetah+ assumes E$ is 2-way and grabs both E$ lines associated with afar.
546*7c478bd9Sstevel@tonic-gate  *	afar:	AFAR from access.
547*7c478bd9Sstevel@tonic-gate  *	datap:	pointer to cpu logout structure.
548*7c478bd9Sstevel@tonic-gate  *	scr1:	scratch
549*7c478bd9Sstevel@tonic-gate  *	scr2:	scratch
550*7c478bd9Sstevel@tonic-gate  *	scr3:	scratch
551*7c478bd9Sstevel@tonic-gate  */
552*7c478bd9Sstevel@tonic-gate #define	GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3)			\
553*7c478bd9Sstevel@tonic-gate 	GET_CPU_IMPL(scr1);						\
554*7c478bd9Sstevel@tonic-gate 	cmp	scr1, PANTHER_IMPL;					\
555*7c478bd9Sstevel@tonic-gate 	bne	%xcc, 4f;						\
556*7c478bd9Sstevel@tonic-gate 	  nop;								\
557*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 0, scr1, scr2, scr3);		\
558*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 1, scr1, scr2, scr3);		\
559*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 2, scr1, scr2, scr3);		\
560*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 3, scr1, scr2, scr3);		\
561*7c478bd9Sstevel@tonic-gate 	add	datap, (CHD_EC_DATA_SETS-4)*CH_EC_DATA_SIZE, datap;	\
562*7c478bd9Sstevel@tonic-gate 	GET_PN_L2_CACHE_DTAGS(afar, datap, scr1, scr2, scr3);		\
563*7c478bd9Sstevel@tonic-gate 	b	5f;							\
564*7c478bd9Sstevel@tonic-gate 	  nop;								\
565*7c478bd9Sstevel@tonic-gate 4:									\
566*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 0, scr1, scr2, scr3);		\
567*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_WAY_BIT(scr1, scr2);					\
568*7c478bd9Sstevel@tonic-gate 	xor	afar, scr1, afar;					\
569*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, 0, scr1, scr2, scr3);		\
570*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_WAY_BIT(scr1, scr2);		/* restore AFAR */	\
571*7c478bd9Sstevel@tonic-gate 	xor	afar, scr1, afar;					\
572*7c478bd9Sstevel@tonic-gate 	add	datap, (CHD_EC_DATA_SETS-2)*CH_EC_DATA_SIZE, datap;	\
573*7c478bd9Sstevel@tonic-gate 	add	datap, CH_EC_DATA_SIZE * PN_L2_NWAYS, datap;		\
574*7c478bd9Sstevel@tonic-gate 5:
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate /*
577*7c478bd9Sstevel@tonic-gate  * Cheetah+ needs to capture E$, D$ and I$ lines associated with
578*7c478bd9Sstevel@tonic-gate  * shadow afar.
579*7c478bd9Sstevel@tonic-gate  *	afar:	scratch, holds shadow afar.
580*7c478bd9Sstevel@tonic-gate  *	datap:	pointer to cpu logout structure
581*7c478bd9Sstevel@tonic-gate  *	scr1:	scratch
582*7c478bd9Sstevel@tonic-gate  *	scr2:	scratch
583*7c478bd9Sstevel@tonic-gate  *	scr3:	scratch
584*7c478bd9Sstevel@tonic-gate  */
585*7c478bd9Sstevel@tonic-gate #define	GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3)		\
586*7c478bd9Sstevel@tonic-gate 	ldxa	[datap + (CH_CLO_SDW_DATA + CH_CHD_AFAR)]%asi, afar;	\
587*7c478bd9Sstevel@tonic-gate 	add	datap, CH_CLO_SDW_DATA + CH_CHD_EC_DATA, datap;	\
588*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3);		\
589*7c478bd9Sstevel@tonic-gate 	GET_DCACHE_DTAG(afar, datap, scr1, scr2, scr3);			\
590*7c478bd9Sstevel@tonic-gate 	GET_ICACHE_DTAG(afar, datap, scr1, scr2, scr3);			\
591*7c478bd9Sstevel@tonic-gate 	sub	datap, CH_CPU_LOGOUT_SIZE, datap
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate /*
594*7c478bd9Sstevel@tonic-gate  * Compute the "Way" bit for 2-way Ecache for Cheetah+.
595*7c478bd9Sstevel@tonic-gate  */
596*7c478bd9Sstevel@tonic-gate #define	GET_ECACHE_WAY_BIT(scr1, scr2)					\
597*7c478bd9Sstevel@tonic-gate 	CPU_INDEX(scr1, scr2);						\
598*7c478bd9Sstevel@tonic-gate 	mulx	scr1, CPU_NODE_SIZE, scr1;				\
599*7c478bd9Sstevel@tonic-gate 	add	scr1, ECACHE_SIZE, scr1;				\
600*7c478bd9Sstevel@tonic-gate 	set	cpunodes, scr2;						\
601*7c478bd9Sstevel@tonic-gate 	ld	[scr1 + scr2], scr1;					\
602*7c478bd9Sstevel@tonic-gate 	srlx	scr1, 1, scr1
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate #else /* CHEETAH_PLUS */
605*7c478bd9Sstevel@tonic-gate /*
606*7c478bd9Sstevel@tonic-gate  * Macro version of get_ecache_dtag.  We use this macro in the
607*7c478bd9Sstevel@tonic-gate  * CPU logout code.
608*7c478bd9Sstevel@tonic-gate  *   afar:	input AFAR, not modified.
609*7c478bd9Sstevel@tonic-gate  *   datap:	Ptr to ch_ec_data_t, at end pts just past ch_ec_data_t.
610*7c478bd9Sstevel@tonic-gate  *   scr1:      Scratch.
611*7c478bd9Sstevel@tonic-gate  *   scr2:	Scratch.
612*7c478bd9Sstevel@tonic-gate  *   scr3:	Scratch.
613*7c478bd9Sstevel@tonic-gate  */
614*7c478bd9Sstevel@tonic-gate #define	GET_ECACHE_DTAG(afar, datap, scr1, scr2, scr3)			\
615*7c478bd9Sstevel@tonic-gate 	mov	afar, scr3;						\
616*7c478bd9Sstevel@tonic-gate 	andn	scr3, (CH_ECACHE_SUBBLK_SIZE - 1), scr3; /* VA<5:0>=0 */\
617*7c478bd9Sstevel@tonic-gate 	set	(CH_ECACHE_8M_SIZE - 1), scr2;				\
618*7c478bd9Sstevel@tonic-gate 	and	scr3, scr2, scr3;		/* VA<63:23>=0 */	\
619*7c478bd9Sstevel@tonic-gate 	b	1f;							\
620*7c478bd9Sstevel@tonic-gate 	   stxa	scr3, [datap + CH_EC_IDX]%asi;	/* store E$ index */	\
621*7c478bd9Sstevel@tonic-gate 	.align	64;							\
622*7c478bd9Sstevel@tonic-gate 1:									\
623*7c478bd9Sstevel@tonic-gate 	ldxa    [scr3]ASI_EC_DIAG, scr1;	/* get E$ tag */	\
624*7c478bd9Sstevel@tonic-gate 	stxa	scr1, [datap + CH_EC_TAG]%asi;				\
625*7c478bd9Sstevel@tonic-gate 	add	datap, CH_EC_DATA, datap;				\
626*7c478bd9Sstevel@tonic-gate 2:									\
627*7c478bd9Sstevel@tonic-gate 	ldxa	[scr3]ASI_EC_R, %g0;		/* ld E$ stging regs */	\
628*7c478bd9Sstevel@tonic-gate 	clr	scr1;							\
629*7c478bd9Sstevel@tonic-gate 3:						/* loop thru 5 regs */	\
630*7c478bd9Sstevel@tonic-gate 	ldxa	[scr1]ASI_EC_DATA, scr2;				\
631*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap]%asi;					\
632*7c478bd9Sstevel@tonic-gate 	add	datap, 8, datap;					\
633*7c478bd9Sstevel@tonic-gate 	cmp	scr1, CH_ECACHE_STGREG_TOTALSIZE - 8;			\
634*7c478bd9Sstevel@tonic-gate 	bne	3b;							\
635*7c478bd9Sstevel@tonic-gate 	   add	scr1, 8, scr1;						\
636*7c478bd9Sstevel@tonic-gate 	btst	CH_ECACHE_STGREG_SIZE, scr3;	/* done? */		\
637*7c478bd9Sstevel@tonic-gate 	beq	2b;							\
638*7c478bd9Sstevel@tonic-gate 	   add	scr3, CH_ECACHE_STGREG_SIZE, scr3
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate /*
641*7c478bd9Sstevel@tonic-gate  * Cheetah does not have cores so these macros are null.
642*7c478bd9Sstevel@tonic-gate  */
643*7c478bd9Sstevel@tonic-gate #define	PARK_SIBLING_CORE(dcucr_reg, scr1, scr2)
644*7c478bd9Sstevel@tonic-gate #define	UNPARK_SIBLING_CORE(dcucr_reg, scr1, scr2)
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate /*
647*7c478bd9Sstevel@tonic-gate  * Cheetah gets primary AFSR and AFAR and clears the AFSR, except for the
648*7c478bd9Sstevel@tonic-gate  * fatal error bits.
649*7c478bd9Sstevel@tonic-gate  *	datap:		pointer to cpu logout structure.
650*7c478bd9Sstevel@tonic-gate  *	afar:		returned primary AFAR value.
651*7c478bd9Sstevel@tonic-gate  *	scr1:		scratch
652*7c478bd9Sstevel@tonic-gate  *	scr2:		scratch
653*7c478bd9Sstevel@tonic-gate  */
654*7c478bd9Sstevel@tonic-gate #define	GET_AFSR_AFAR(datap, afar, scr1, scr2)	\
655*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_AFAR, afar;					\
656*7c478bd9Sstevel@tonic-gate 	stxa	afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi;	\
657*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_AFSR, scr2;					\
658*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR)]%asi;	\
659*7c478bd9Sstevel@tonic-gate 	sethi	%hh(C_AFSR_FATAL_ERRS), scr1;				\
660*7c478bd9Sstevel@tonic-gate 	sllx	scr1, 32, scr1;						\
661*7c478bd9Sstevel@tonic-gate 	bclr	scr1, scr2;	/* Clear fatal error bits here, so */	\
662*7c478bd9Sstevel@tonic-gate 	stxa	scr2, [%g0]ASI_AFSR; /* they're left as is in AFSR */	\
663*7c478bd9Sstevel@tonic-gate 	membar	#Sync
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate /*
666*7c478bd9Sstevel@tonic-gate  * Cheetah E$ is direct-mapped, so we grab line data and skip second line.
667*7c478bd9Sstevel@tonic-gate  *	afar:	AFAR from access.
668*7c478bd9Sstevel@tonic-gate  *	datap:	pointer to cpu logout structure.
669*7c478bd9Sstevel@tonic-gate  *	scr1:	scratch
670*7c478bd9Sstevel@tonic-gate  *	scr2:	scratch
671*7c478bd9Sstevel@tonic-gate  *	scr3:	scratch
672*7c478bd9Sstevel@tonic-gate  */
673*7c478bd9Sstevel@tonic-gate #define	GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3)			\
674*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAG(afar, datap, scr1, scr2, scr3);			\
675*7c478bd9Sstevel@tonic-gate 	add	datap, (CHD_EC_DATA_SETS-1)*CH_EC_DATA_SIZE, datap;	\
676*7c478bd9Sstevel@tonic-gate 	add	datap, CH_EC_DATA_SIZE * PN_L2_NWAYS, datap;		\
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate /*
679*7c478bd9Sstevel@tonic-gate  * Cheetah has no shadow AFAR, null operation.
680*7c478bd9Sstevel@tonic-gate  */
681*7c478bd9Sstevel@tonic-gate #define	GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3)
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate #endif	/* CHEETAH_PLUS */
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate /*
686*7c478bd9Sstevel@tonic-gate  * Cheetah/(Cheetah+ Jaguar Panther)/Jalapeno Macro for capturing CPU
687*7c478bd9Sstevel@tonic-gate  * logout data at TL>0. r_val is a register that returns the "failure count"
688*7c478bd9Sstevel@tonic-gate  * to the caller, and may be used as a scratch register until the end of
689*7c478bd9Sstevel@tonic-gate  * the macro.  afar is used to return the primary AFAR value to the caller
690*7c478bd9Sstevel@tonic-gate  * and it too can be used as a scratch register until the end. r_or_s is
691*7c478bd9Sstevel@tonic-gate  * a reg or symbol that has the offset within the "cpu_private" data area
692*7c478bd9Sstevel@tonic-gate  * to deposit the logout data.  t_flags is a register that has the
693*7c478bd9Sstevel@tonic-gate  * trap-type/trap-level/CEEN info. This t_flags register may be used after
694*7c478bd9Sstevel@tonic-gate  * the GET_AFSR_AFAR macro.
695*7c478bd9Sstevel@tonic-gate  *
696*7c478bd9Sstevel@tonic-gate  * The CPU logout operation will fail (r_val > 0) if the logout
697*7c478bd9Sstevel@tonic-gate  * structure in question is already being used. Otherwise, the CPU
698*7c478bd9Sstevel@tonic-gate  * logout operation will succeed (r_val = 0). For failures, r_val
699*7c478bd9Sstevel@tonic-gate  * returns the busy count (# of times we tried using this CPU logout
700*7c478bd9Sstevel@tonic-gate  * structure when it was busy.)
701*7c478bd9Sstevel@tonic-gate  *
702*7c478bd9Sstevel@tonic-gate  *   Register usage:
703*7c478bd9Sstevel@tonic-gate  *	%asi:   Must be set to either ASI_MEM if the address in datap
704*7c478bd9Sstevel@tonic-gate  *		is a physical address or to ASI_N if the address in
705*7c478bd9Sstevel@tonic-gate  *		datap is a virtual address.
706*7c478bd9Sstevel@tonic-gate  *	r_val:	This register is the return value which tells the
707*7c478bd9Sstevel@tonic-gate  *		caller whether or not the LOGOUT operation was successful.
708*7c478bd9Sstevel@tonic-gate  *		For failures, r_val returns the fail count (i.e. number of
709*7c478bd9Sstevel@tonic-gate  *		times we have tried to use this logout structure when it was
710*7c478bd9Sstevel@tonic-gate  *		already being used.
711*7c478bd9Sstevel@tonic-gate  *	afar:	output: contains AFAR on exit
712*7c478bd9Sstevel@tonic-gate  *	t_flags: input trap type info, may be used as scratch after stored
713*7c478bd9Sstevel@tonic-gate  *		to cpu log out structure.
714*7c478bd9Sstevel@tonic-gate  *	datap:	Points to log out data area.
715*7c478bd9Sstevel@tonic-gate  *	scr1:	Scratch
716*7c478bd9Sstevel@tonic-gate  *	scr2:	Scratch (may be r_val)
717*7c478bd9Sstevel@tonic-gate  *	scr3:   Scratch (may be t_flags)
718*7c478bd9Sstevel@tonic-gate  */
719*7c478bd9Sstevel@tonic-gate #define	DO_TL1_CPU_LOGOUT(r_val, afar, t_flags, datap, scr1, scr2, scr3) \
720*7c478bd9Sstevel@tonic-gate 	setx	LOGOUT_INVALID, scr2, scr1;				\
721*7c478bd9Sstevel@tonic-gate 	ldxa	[datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi, scr2;	\
722*7c478bd9Sstevel@tonic-gate 	cmp	scr2, scr1;						\
723*7c478bd9Sstevel@tonic-gate 	bne	8f;							\
724*7c478bd9Sstevel@tonic-gate 	  nop;								\
725*7c478bd9Sstevel@tonic-gate 	stxa	t_flags, [datap + CH_CLO_FLAGS]%asi;			\
726*7c478bd9Sstevel@tonic-gate 	GET_AFSR_AFAR(datap, afar, scr1, scr2);				\
727*7c478bd9Sstevel@tonic-gate 	add	datap, CH_CLO_DATA + CH_CHD_EC_DATA, datap;		\
728*7c478bd9Sstevel@tonic-gate 	GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3);		\
729*7c478bd9Sstevel@tonic-gate 	GET_DCACHE_DTAG(afar, datap, scr1, scr2, scr3);			\
730*7c478bd9Sstevel@tonic-gate 	GET_ICACHE_DTAG(afar, datap, scr1, scr2, scr3);			\
731*7c478bd9Sstevel@tonic-gate 	sub	datap, CH_CLO_DATA + CH_DIAG_DATA_SIZE, datap;		\
732*7c478bd9Sstevel@tonic-gate 	GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3);			\
733*7c478bd9Sstevel@tonic-gate 	ldxa	[datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi, afar;	\
734*7c478bd9Sstevel@tonic-gate 	set	0, r_val;	/* return value for success */		\
735*7c478bd9Sstevel@tonic-gate 	ba	9f;							\
736*7c478bd9Sstevel@tonic-gate 	  nop;								\
737*7c478bd9Sstevel@tonic-gate 8:									\
738*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_AFAR, afar;					\
739*7c478bd9Sstevel@tonic-gate 	ldxa	[datap + CH_CLO_NEST_CNT]%asi, r_val;			\
740*7c478bd9Sstevel@tonic-gate 	inc	r_val;		/* return value for failure */		\
741*7c478bd9Sstevel@tonic-gate 	stxa	r_val, [datap + CH_CLO_NEST_CNT]%asi;			\
742*7c478bd9Sstevel@tonic-gate 	membar	#Sync;							\
743*7c478bd9Sstevel@tonic-gate 9:
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate /*
746*7c478bd9Sstevel@tonic-gate  * Cheetah/(Cheetah+ Jaguar Panther)/Jalapeno Macro for capturing CPU
747*7c478bd9Sstevel@tonic-gate  * logout data.  Uses DO_TL1_CPU_LOGOUT macro defined above, and sets
748*7c478bd9Sstevel@tonic-gate  * up the expected data pointer in the scr1 register and sets the %asi
749*7c478bd9Sstevel@tonic-gate  * register to ASI_N for kernel virtual addresses instead of ASI_MEM as
750*7c478bd9Sstevel@tonic-gate  * is used at TL>0.
751*7c478bd9Sstevel@tonic-gate  *
752*7c478bd9Sstevel@tonic-gate  * The CPU logout operation will fail (r_val > 0) if the logout
753*7c478bd9Sstevel@tonic-gate  * structure in question is already being used. Otherwise, the CPU
754*7c478bd9Sstevel@tonic-gate  * logout operation will succeed (r_val = 0). For failures, r_val
755*7c478bd9Sstevel@tonic-gate  * returns the busy count (# of times we tried using this CPU logout
756*7c478bd9Sstevel@tonic-gate  * structure when it was busy.)
757*7c478bd9Sstevel@tonic-gate  *
758*7c478bd9Sstevel@tonic-gate  *   Register usage:
759*7c478bd9Sstevel@tonic-gate  *	r_val:	This register is the return value which tells the
760*7c478bd9Sstevel@tonic-gate  *		caller whether or not the LOGOUT operation was successful.
761*7c478bd9Sstevel@tonic-gate  *		For failures, r_val returns the fail count (i.e. number of
762*7c478bd9Sstevel@tonic-gate  *		times we have tried to use this logout structure when it was
763*7c478bd9Sstevel@tonic-gate  *		already being used.
764*7c478bd9Sstevel@tonic-gate  *	afar:	returns AFAR, used internally as afar value.
765*7c478bd9Sstevel@tonic-gate  *		output: if the cpu_private struct has not been initialized,
766*7c478bd9Sstevel@tonic-gate  *		        then we return the t_flags value listed below.
767*7c478bd9Sstevel@tonic-gate  *	r_or_s:	input offset, either register or constant (symbol).  It's
768*7c478bd9Sstevel@tonic-gate  *		OK for r_or_s to be a register as long as it's not scr1 or
769*7c478bd9Sstevel@tonic-gate  *		scr3.
770*7c478bd9Sstevel@tonic-gate  *	t_flags: input trap type info, may be used as scratch after stored
771*7c478bd9Sstevel@tonic-gate  *		to cpu log out structure.
772*7c478bd9Sstevel@tonic-gate  *	scr1:	Scratch, points to log out data area.
773*7c478bd9Sstevel@tonic-gate  *	scr2:	Scratch (may be r_or_s)
774*7c478bd9Sstevel@tonic-gate  *	scr3:	Scratch (may be r_val)
775*7c478bd9Sstevel@tonic-gate  *	scr4:   Scratch (may be t_flags)
776*7c478bd9Sstevel@tonic-gate  */
777*7c478bd9Sstevel@tonic-gate #define	DO_CPU_LOGOUT(r_val, afar, r_or_s, t_flags, scr1, scr2, scr3, scr4) \
778*7c478bd9Sstevel@tonic-gate 	GET_CPU_PRIVATE_PTR(r_or_s, scr1, scr3, 7f); /* can't use scr2/4 */ \
779*7c478bd9Sstevel@tonic-gate 	wr	%g0, ASI_N, %asi;					\
780*7c478bd9Sstevel@tonic-gate 	DO_TL1_CPU_LOGOUT(r_val, afar, t_flags, scr1, scr2, scr3, scr4)	\
781*7c478bd9Sstevel@tonic-gate 	ba	6f;							\
782*7c478bd9Sstevel@tonic-gate 	  nop;								\
783*7c478bd9Sstevel@tonic-gate 7:									\
784*7c478bd9Sstevel@tonic-gate 	mov	t_flags, afar;		/* depends on afar = %g2  */	\
785*7c478bd9Sstevel@tonic-gate 	set	0, r_val;		/* success in this case.  */	\
786*7c478bd9Sstevel@tonic-gate 6:
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate /*
789*7c478bd9Sstevel@tonic-gate  * The P$ is flushed as a side effect of writing to the Primary
790*7c478bd9Sstevel@tonic-gate  * or Secondary Context Register. After writing to a context
791*7c478bd9Sstevel@tonic-gate  * register, every line of the P$ in the Valid state is invalidated,
792*7c478bd9Sstevel@tonic-gate  * regardless of which context it belongs to.
793*7c478bd9Sstevel@tonic-gate  * This routine simply touches the Primary context register by
794*7c478bd9Sstevel@tonic-gate  * reading the current value and writing it back. The Primary
795*7c478bd9Sstevel@tonic-gate  * context is not changed.
796*7c478bd9Sstevel@tonic-gate  */
797*7c478bd9Sstevel@tonic-gate #define	PCACHE_FLUSHALL(tmp1, tmp2, tmp3)				\
798*7c478bd9Sstevel@tonic-gate 	sethi	%hi(FLUSH_ADDR), tmp1					;\
799*7c478bd9Sstevel@tonic-gate 	set	MMU_PCONTEXT, tmp2					;\
800*7c478bd9Sstevel@tonic-gate 	ldxa	[tmp2]ASI_DMMU, tmp3					;\
801*7c478bd9Sstevel@tonic-gate 	stxa	tmp3, [tmp2]ASI_DMMU					;\
802*7c478bd9Sstevel@tonic-gate 	flush	tmp1	/* See Cheetah PRM 8.10.2 */
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate /*
805*7c478bd9Sstevel@tonic-gate  * Macro that flushes the entire Dcache.
806*7c478bd9Sstevel@tonic-gate  *
807*7c478bd9Sstevel@tonic-gate  * arg1 = dcache size
808*7c478bd9Sstevel@tonic-gate  * arg2 = dcache linesize
809*7c478bd9Sstevel@tonic-gate  */
810*7c478bd9Sstevel@tonic-gate #define	CH_DCACHE_FLUSHALL(arg1, arg2, tmp1)				\
811*7c478bd9Sstevel@tonic-gate 	sub	arg1, arg2, tmp1;					\
812*7c478bd9Sstevel@tonic-gate 1:									\
813*7c478bd9Sstevel@tonic-gate 	stxa	%g0, [tmp1]ASI_DC_TAG;					\
814*7c478bd9Sstevel@tonic-gate 	membar	#Sync;							\
815*7c478bd9Sstevel@tonic-gate 	cmp	%g0, tmp1;						\
816*7c478bd9Sstevel@tonic-gate 	bne,pt	%icc, 1b;						\
817*7c478bd9Sstevel@tonic-gate 	  sub	tmp1, arg2, tmp1;
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate /*
820*7c478bd9Sstevel@tonic-gate  * Macro that flushes the entire Icache.
821*7c478bd9Sstevel@tonic-gate  *
822*7c478bd9Sstevel@tonic-gate  * Note that we cannot access ASI 0x67 (ASI_IC_TAG) with the Icache on,
823*7c478bd9Sstevel@tonic-gate  * because accesses to ASI 0x67 interfere with Icache coherency.  We
824*7c478bd9Sstevel@tonic-gate  * must make sure the Icache is off, then turn it back on after the entire
825*7c478bd9Sstevel@tonic-gate  * cache has been invalidated.  If the Icache is originally off, we'll just
826*7c478bd9Sstevel@tonic-gate  * clear the tags but not turn the Icache on.
827*7c478bd9Sstevel@tonic-gate  *
828*7c478bd9Sstevel@tonic-gate  * arg1 = icache size
829*7c478bd9Sstevel@tonic-gate  * arg2 = icache linesize
830*7c478bd9Sstevel@tonic-gate  */
831*7c478bd9Sstevel@tonic-gate #define	CH_ICACHE_FLUSHALL(arg1, arg2, tmp1, tmp2)			\
832*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_DCU, tmp2;					\
833*7c478bd9Sstevel@tonic-gate 	andn	tmp2, DCU_IC, tmp1;					\
834*7c478bd9Sstevel@tonic-gate 	stxa	tmp1, [%g0]ASI_DCU;					\
835*7c478bd9Sstevel@tonic-gate 	flush	%g0;	/* flush required after changing the IC bit */	\
836*7c478bd9Sstevel@tonic-gate 	sllx	arg2, 1, arg2;		/* arg2 = linesize * 2 */	\
837*7c478bd9Sstevel@tonic-gate 	sllx	arg1, 1, arg1;		/* arg1 = size * 2 */		\
838*7c478bd9Sstevel@tonic-gate 	sub	arg1, arg2, arg1;					\
839*7c478bd9Sstevel@tonic-gate 	or	arg1, CH_ICTAG_LOWER, arg1;	/* "write" tag */	\
840*7c478bd9Sstevel@tonic-gate 1:									\
841*7c478bd9Sstevel@tonic-gate 	stxa	%g0, [arg1]ASI_IC_TAG;					\
842*7c478bd9Sstevel@tonic-gate 	membar	#Sync;				/* Cheetah PRM 8.9.3 */	\
843*7c478bd9Sstevel@tonic-gate 	cmp	arg1, CH_ICTAG_LOWER;					\
844*7c478bd9Sstevel@tonic-gate 	bne,pt	%icc, 1b;						\
845*7c478bd9Sstevel@tonic-gate 	  sub	arg1, arg2, arg1;					\
846*7c478bd9Sstevel@tonic-gate 	stxa	tmp2, [%g0]ASI_DCU;					\
847*7c478bd9Sstevel@tonic-gate 	flush	%g0;	/* flush required after changing the IC bit */
848*7c478bd9Sstevel@tonic-gate 
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate #if defined(JALAPENO) || defined(SERRANO)
851*7c478bd9Sstevel@tonic-gate 
852*7c478bd9Sstevel@tonic-gate /*
853*7c478bd9Sstevel@tonic-gate  * ASI access to the L2 tag or L2 flush can hang the cpu when interacting
854*7c478bd9Sstevel@tonic-gate  * with combinations of L2 snoops, victims and stores.
855*7c478bd9Sstevel@tonic-gate  *
856*7c478bd9Sstevel@tonic-gate  * A possible workaround is to surround each L2 ASI access with membars
857*7c478bd9Sstevel@tonic-gate  * and make sure that the code is hitting in the Icache.  This requires
858*7c478bd9Sstevel@tonic-gate  * aligning code sequence at E$ boundary and forcing I$ fetch by
859*7c478bd9Sstevel@tonic-gate  * jumping to selected offsets so that we don't take any I$ misses
860*7c478bd9Sstevel@tonic-gate  * during ASI access to the L2 tag or L2 flush.  This also requires
861*7c478bd9Sstevel@tonic-gate  * making sure that we don't take any interrupts or traps (such as
862*7c478bd9Sstevel@tonic-gate  * fast ECC trap, I$/D$ tag parity error) which can result in eviction
863*7c478bd9Sstevel@tonic-gate  * of this code sequence from I$, thus causing a miss.
864*7c478bd9Sstevel@tonic-gate  *
865*7c478bd9Sstevel@tonic-gate  * Because of the complexity/risk, we have decided to do a partial fix
866*7c478bd9Sstevel@tonic-gate  * of adding membar around each ASI access to the L2 tag or L2 flush.
867*7c478bd9Sstevel@tonic-gate  */
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate #define	JP_EC_DIAG_ACCESS_MEMBAR	\
870*7c478bd9Sstevel@tonic-gate 	membar	#Sync
871*7c478bd9Sstevel@tonic-gate 
872*7c478bd9Sstevel@tonic-gate /*
873*7c478bd9Sstevel@tonic-gate  * Jalapeno version of macro that flushes the entire Ecache.
874*7c478bd9Sstevel@tonic-gate  *
875*7c478bd9Sstevel@tonic-gate  * Uses Jalapeno displacement flush feature of ASI_EC_DIAG.
876*7c478bd9Sstevel@tonic-gate  *
877*7c478bd9Sstevel@tonic-gate  * arg1 = ecache size
878*7c478bd9Sstevel@tonic-gate  * arg2 = ecache linesize - not modified; can be an immediate constant.
879*7c478bd9Sstevel@tonic-gate  */
880*7c478bd9Sstevel@tonic-gate #define	ECACHE_FLUSHALL(arg1, arg2, tmp1, tmp2)	\
881*7c478bd9Sstevel@tonic-gate 	CPU_INDEX(tmp1, tmp2);						\
882*7c478bd9Sstevel@tonic-gate 	set	JP_ECACHE_IDX_DISP_FLUSH, tmp2;				\
883*7c478bd9Sstevel@tonic-gate 	sllx	tmp1, JP_ECFLUSH_PORTID_SHIFT, tmp1;			\
884*7c478bd9Sstevel@tonic-gate 	or	tmp1, tmp2, tmp1;					\
885*7c478bd9Sstevel@tonic-gate 	srlx	arg1, JP_EC_TO_SET_SIZE_SHIFT, tmp2;			\
886*7c478bd9Sstevel@tonic-gate 1:									\
887*7c478bd9Sstevel@tonic-gate 	subcc	tmp2, arg2, tmp2;					\
888*7c478bd9Sstevel@tonic-gate 	JP_EC_DIAG_ACCESS_MEMBAR;					\
889*7c478bd9Sstevel@tonic-gate 	ldxa	[tmp1 + tmp2]ASI_EC_DIAG, %g0;				\
890*7c478bd9Sstevel@tonic-gate 	JP_EC_DIAG_ACCESS_MEMBAR;					\
891*7c478bd9Sstevel@tonic-gate 	bg,pt	%xcc, 1b;						\
892*7c478bd9Sstevel@tonic-gate 	  nop;								\
893*7c478bd9Sstevel@tonic-gate 	mov	1, tmp2;						\
894*7c478bd9Sstevel@tonic-gate 	sllx	tmp2, JP_ECFLUSH_EC_WAY_SHIFT, tmp2;			\
895*7c478bd9Sstevel@tonic-gate 	add	tmp1, tmp2, tmp1;					\
896*7c478bd9Sstevel@tonic-gate 	mov	(JP_ECACHE_NWAY-1), tmp2;				\
897*7c478bd9Sstevel@tonic-gate 	sllx	tmp2, JP_ECFLUSH_EC_WAY_SHIFT, tmp2;			\
898*7c478bd9Sstevel@tonic-gate 	andcc	tmp1, tmp2, tmp2;					\
899*7c478bd9Sstevel@tonic-gate 	bnz,pt	%xcc, 1b;						\
900*7c478bd9Sstevel@tonic-gate 	  srlx	arg1, JP_EC_TO_SET_SIZE_SHIFT, tmp2
901*7c478bd9Sstevel@tonic-gate 
902*7c478bd9Sstevel@tonic-gate #else	/* JALAPENO || SERRANO */
903*7c478bd9Sstevel@tonic-gate 
904*7c478bd9Sstevel@tonic-gate /*
905*7c478bd9Sstevel@tonic-gate  * Cheetah version of macro that flushes the entire Ecache.
906*7c478bd9Sstevel@tonic-gate  *
907*7c478bd9Sstevel@tonic-gate  *  Need to displacement flush 2x ecache size from Ecache flush area.
908*7c478bd9Sstevel@tonic-gate  *
909*7c478bd9Sstevel@tonic-gate  * arg1 = ecache size
910*7c478bd9Sstevel@tonic-gate  * arg2 = ecache linesize
911*7c478bd9Sstevel@tonic-gate  * arg3 = ecache flush address - for cheetah only
912*7c478bd9Sstevel@tonic-gate  */
913*7c478bd9Sstevel@tonic-gate #define	CH_ECACHE_FLUSHALL(arg1, arg2, arg3)				\
914*7c478bd9Sstevel@tonic-gate 	sllx	arg1, 1, arg1;						\
915*7c478bd9Sstevel@tonic-gate 1:									\
916*7c478bd9Sstevel@tonic-gate 	subcc	arg1, arg2, arg1;					\
917*7c478bd9Sstevel@tonic-gate 	bg,pt	%xcc, 1b;						\
918*7c478bd9Sstevel@tonic-gate 	  ldxa	[arg1 + arg3]ASI_MEM, %g0;
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate /*
921*7c478bd9Sstevel@tonic-gate  * Cheetah+ version of macro that flushes the entire Ecache.
922*7c478bd9Sstevel@tonic-gate  *
923*7c478bd9Sstevel@tonic-gate  * Uses the displacement flush feature.
924*7c478bd9Sstevel@tonic-gate  *
925*7c478bd9Sstevel@tonic-gate  * arg1 = ecache size
926*7c478bd9Sstevel@tonic-gate  * arg2 = ecache linesize
927*7c478bd9Sstevel@tonic-gate  * impl = CPU implementation as returned from GET_CPU_IMPL()
928*7c478bd9Sstevel@tonic-gate  *        The value in this register is destroyed during execution
929*7c478bd9Sstevel@tonic-gate  *        of the macro.
930*7c478bd9Sstevel@tonic-gate  */
931*7c478bd9Sstevel@tonic-gate #if defined(CHEETAH_PLUS)
932*7c478bd9Sstevel@tonic-gate #define	CHP_ECACHE_FLUSHALL(arg1, arg2, impl)				\
933*7c478bd9Sstevel@tonic-gate 	cmp	impl, PANTHER_IMPL;					\
934*7c478bd9Sstevel@tonic-gate 	bne	%xcc, 1f;						\
935*7c478bd9Sstevel@tonic-gate 	  nop;								\
936*7c478bd9Sstevel@tonic-gate 	set	PN_L3_IDX_DISP_FLUSH, impl;				\
937*7c478bd9Sstevel@tonic-gate 	b	2f;							\
938*7c478bd9Sstevel@tonic-gate 	  nop;								\
939*7c478bd9Sstevel@tonic-gate 1:									\
940*7c478bd9Sstevel@tonic-gate 	set	CHP_ECACHE_IDX_DISP_FLUSH, impl;			\
941*7c478bd9Sstevel@tonic-gate 2:									\
942*7c478bd9Sstevel@tonic-gate 	subcc	arg1, arg2, arg1;					\
943*7c478bd9Sstevel@tonic-gate 	bg,pt	%xcc, 2b;						\
944*7c478bd9Sstevel@tonic-gate 	  ldxa	[arg1 + impl]ASI_EC_DIAG, %g0;
945*7c478bd9Sstevel@tonic-gate #else	/* CHEETAH_PLUS */
946*7c478bd9Sstevel@tonic-gate #define	CHP_ECACHE_FLUSHALL(arg1, arg2, impl)
947*7c478bd9Sstevel@tonic-gate #endif	/* CHEETAH_PLUS */
948*7c478bd9Sstevel@tonic-gate 
949*7c478bd9Sstevel@tonic-gate /*
950*7c478bd9Sstevel@tonic-gate  * Macro that flushes the entire Ecache.
951*7c478bd9Sstevel@tonic-gate  *
952*7c478bd9Sstevel@tonic-gate  * arg1 = ecache size
953*7c478bd9Sstevel@tonic-gate  * arg2 = ecache linesize
954*7c478bd9Sstevel@tonic-gate  * arg3 = ecache flush address - for cheetah only
955*7c478bd9Sstevel@tonic-gate  */
956*7c478bd9Sstevel@tonic-gate #define	ECACHE_FLUSHALL(arg1, arg2, arg3, tmp1)				\
957*7c478bd9Sstevel@tonic-gate 	GET_CPU_IMPL(tmp1);						\
958*7c478bd9Sstevel@tonic-gate 	cmp	tmp1, CHEETAH_IMPL;					\
959*7c478bd9Sstevel@tonic-gate 	bne	%xcc, 2f;						\
960*7c478bd9Sstevel@tonic-gate 	  nop;								\
961*7c478bd9Sstevel@tonic-gate 	CH_ECACHE_FLUSHALL(arg1, arg2, arg3);				\
962*7c478bd9Sstevel@tonic-gate 	ba	3f;							\
963*7c478bd9Sstevel@tonic-gate 	  nop;								\
964*7c478bd9Sstevel@tonic-gate 2:									\
965*7c478bd9Sstevel@tonic-gate 	CHP_ECACHE_FLUSHALL(arg1, arg2, tmp1);				\
966*7c478bd9Sstevel@tonic-gate 3:
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate #endif	/* JALAPENO || SERRANO */
969*7c478bd9Sstevel@tonic-gate 
970*7c478bd9Sstevel@tonic-gate /*
971*7c478bd9Sstevel@tonic-gate  * Macro that flushes the Panther L2 cache.
972*7c478bd9Sstevel@tonic-gate  */
973*7c478bd9Sstevel@tonic-gate #if defined(CHEETAH_PLUS)
974*7c478bd9Sstevel@tonic-gate #define	PN_L2_FLUSHALL(scr1, scr2, scr3)				\
975*7c478bd9Sstevel@tonic-gate 	GET_CPU_IMPL(scr3);						\
976*7c478bd9Sstevel@tonic-gate 	cmp	scr3, PANTHER_IMPL;					\
977*7c478bd9Sstevel@tonic-gate 	bne	%xcc, 2f;						\
978*7c478bd9Sstevel@tonic-gate 	  nop;								\
979*7c478bd9Sstevel@tonic-gate 	set	PN_L2_SIZE, scr1;					\
980*7c478bd9Sstevel@tonic-gate 	set	PN_L2_LINESIZE, scr2;					\
981*7c478bd9Sstevel@tonic-gate 	set	PN_L2_IDX_DISP_FLUSH, scr3;				\
982*7c478bd9Sstevel@tonic-gate 1:									\
983*7c478bd9Sstevel@tonic-gate 	subcc	scr1, scr2, scr1;					\
984*7c478bd9Sstevel@tonic-gate 	bg,pt	%xcc, 1b;						\
985*7c478bd9Sstevel@tonic-gate 	  ldxa	[scr1 + scr3]ASI_L2_TAG, %g0;				\
986*7c478bd9Sstevel@tonic-gate 2:
987*7c478bd9Sstevel@tonic-gate #else	/* CHEETAH_PLUS */
988*7c478bd9Sstevel@tonic-gate #define	PN_L2_FLUSHALL(scr1, scr2, scr3)
989*7c478bd9Sstevel@tonic-gate #endif	/* CHEETAH_PLUS */
990*7c478bd9Sstevel@tonic-gate 
991*7c478bd9Sstevel@tonic-gate /*
992*7c478bd9Sstevel@tonic-gate  * Given a VA and page size (page size as encoded in ASI_MMU_TAG_ACCESS_EXT),
993*7c478bd9Sstevel@tonic-gate  * this macro returns the TLB index for that mapping based on a 512 entry
994*7c478bd9Sstevel@tonic-gate  * (2-way set associative) TLB. Aaside from the 16 entry fully associative
995*7c478bd9Sstevel@tonic-gate  * TLBs, all TLBs in Panther are 512 entry, 2-way set associative.
996*7c478bd9Sstevel@tonic-gate  *
997*7c478bd9Sstevel@tonic-gate  * To find the index, we shift the VA right by 13 + (3 * pg_sz) and then
998*7c478bd9Sstevel@tonic-gate  * mask out all but the lower 8 bits because:
999*7c478bd9Sstevel@tonic-gate  *
1000*7c478bd9Sstevel@tonic-gate  *    ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 0 for   8K
1001*7c478bd9Sstevel@tonic-gate  *    ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 1 for  64K
1002*7c478bd9Sstevel@tonic-gate  *    ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 2 for 512K
1003*7c478bd9Sstevel@tonic-gate  *    ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 3 for   4M
1004*7c478bd9Sstevel@tonic-gate  *    ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 4 for  32M
1005*7c478bd9Sstevel@tonic-gate  *    ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 5 for 256M
1006*7c478bd9Sstevel@tonic-gate  *
1007*7c478bd9Sstevel@tonic-gate  * and
1008*7c478bd9Sstevel@tonic-gate  *
1009*7c478bd9Sstevel@tonic-gate  *    array index for   8K pages = VA[20:13]
1010*7c478bd9Sstevel@tonic-gate  *    array index for  64K pages = VA[23:16]
1011*7c478bd9Sstevel@tonic-gate  *    array index for 512K pages = VA[26:19]
1012*7c478bd9Sstevel@tonic-gate  *    array index for   4M pages = VA[29:22]
1013*7c478bd9Sstevel@tonic-gate  *    array index for  32M pages = VA[32:25]
1014*7c478bd9Sstevel@tonic-gate  *    array index for 256M pages = VA[35:28]
1015*7c478bd9Sstevel@tonic-gate  *
1016*7c478bd9Sstevel@tonic-gate  * Inputs:
1017*7c478bd9Sstevel@tonic-gate  *
1018*7c478bd9Sstevel@tonic-gate  *    va	- Register.
1019*7c478bd9Sstevel@tonic-gate  *		  Input: Virtual address in which we are interested.
1020*7c478bd9Sstevel@tonic-gate  *		  Output: TLB index value.
1021*7c478bd9Sstevel@tonic-gate  *    pg_sz	- Register. Page Size of the TLB in question as encoded
1022*7c478bd9Sstevel@tonic-gate  *		  in the ASI_[D|I]MMU_TAG_ACCESS_EXT register.
1023*7c478bd9Sstevel@tonic-gate  */
1024*7c478bd9Sstevel@tonic-gate #if defined(CHEETAH_PLUS)
1025*7c478bd9Sstevel@tonic-gate #define	PN_GET_TLB_INDEX(va, pg_sz)					\
1026*7c478bd9Sstevel@tonic-gate 	srlx	va, 13, va;	/* first shift the 13 bits and then */	\
1027*7c478bd9Sstevel@tonic-gate 	srlx	va, pg_sz, va;	/* shift by pg_sz three times. */	\
1028*7c478bd9Sstevel@tonic-gate 	srlx	va, pg_sz, va;						\
1029*7c478bd9Sstevel@tonic-gate 	srlx	va, pg_sz, va;						\
1030*7c478bd9Sstevel@tonic-gate 	and	va, 0xff, va;	/* mask out all but the lower 8 bits */
1031*7c478bd9Sstevel@tonic-gate #endif	/* CHEETAH_PLUS */
1032*7c478bd9Sstevel@tonic-gate 
1033*7c478bd9Sstevel@tonic-gate /*
1034*7c478bd9Sstevel@tonic-gate  * The following macros are for error traps at TL>0.
1035*7c478bd9Sstevel@tonic-gate  * The issue with error traps at TL>0 is that there are no safely
1036*7c478bd9Sstevel@tonic-gate  * available global registers.  So we use the trick of generating a
1037*7c478bd9Sstevel@tonic-gate  * software trap, then using the %tpc, %tnpc and %tstate registers to
1038*7c478bd9Sstevel@tonic-gate  * temporarily save the values of %g1 and %g2.
1039*7c478bd9Sstevel@tonic-gate  */
1040*7c478bd9Sstevel@tonic-gate 
1041*7c478bd9Sstevel@tonic-gate /*
1042*7c478bd9Sstevel@tonic-gate  * Macro to generate 8-instruction trap table entry for TL>0 trap handlers.
1043*7c478bd9Sstevel@tonic-gate  * Does the following steps:
1044*7c478bd9Sstevel@tonic-gate  *	1. membar #Sync - required for USIII family errors.
1045*7c478bd9Sstevel@tonic-gate  *	2. Specified software trap.
1046*7c478bd9Sstevel@tonic-gate  * NB: Must be 8 instructions or less to fit in trap table and code must
1047*7c478bd9Sstevel@tonic-gate  *     be relocatable.
1048*7c478bd9Sstevel@tonic-gate  */
1049*7c478bd9Sstevel@tonic-gate #define	CH_ERR_TL1_TRAPENTRY(trapno)		\
1050*7c478bd9Sstevel@tonic-gate 	membar	#Sync;				\
1051*7c478bd9Sstevel@tonic-gate 	ta	trapno;				\
1052*7c478bd9Sstevel@tonic-gate 	nop; nop; nop; nop; nop; nop
1053*7c478bd9Sstevel@tonic-gate 
1054*7c478bd9Sstevel@tonic-gate /*
1055*7c478bd9Sstevel@tonic-gate  * Macro to generate 8-instruction trap table entry for TL>0 software trap.
1056*7c478bd9Sstevel@tonic-gate  * We save the values of %g1 and %g2 in %tpc, %tnpc and %tstate (since
1057*7c478bd9Sstevel@tonic-gate  * the low-order two bits of %tpc/%tnpc are reserved and read as zero,
1058*7c478bd9Sstevel@tonic-gate  * we need to put the low-order two bits of %g1 and %g2 in %tstate).
1059*7c478bd9Sstevel@tonic-gate  * Note that %tstate has a reserved hole from bits 3-7, so we put the
1060*7c478bd9Sstevel@tonic-gate  * low-order two bits of %g1 in bits 0-1 and the low-order two bits of
1061*7c478bd9Sstevel@tonic-gate  * %g2 in bits 10-11 (insuring bits 8-9 are zero for use by the D$/I$
1062*7c478bd9Sstevel@tonic-gate  * state bits).  Note that we must do a jmp instruction, since this
1063*7c478bd9Sstevel@tonic-gate  * is moved into the trap table entry.
1064*7c478bd9Sstevel@tonic-gate  * NB: Must be 8 instructions or less to fit in trap table and code must
1065*7c478bd9Sstevel@tonic-gate  *     be relocatable.
1066*7c478bd9Sstevel@tonic-gate  */
1067*7c478bd9Sstevel@tonic-gate #define	CH_ERR_TL1_SWTRAPENTRY(label)		\
1068*7c478bd9Sstevel@tonic-gate 	wrpr	%g1, %tpc;			\
1069*7c478bd9Sstevel@tonic-gate 	and	%g1, 3, %g1;			\
1070*7c478bd9Sstevel@tonic-gate 	wrpr	%g2, %tnpc;			\
1071*7c478bd9Sstevel@tonic-gate 	sllx	%g2, CH_ERR_G2_TO_TSTATE_SHFT, %g2; \
1072*7c478bd9Sstevel@tonic-gate 	or	%g1, %g2, %g2;			\
1073*7c478bd9Sstevel@tonic-gate 	sethi	%hi(label), %g1;		\
1074*7c478bd9Sstevel@tonic-gate 	jmp	%g1+%lo(label);			\
1075*7c478bd9Sstevel@tonic-gate 	  wrpr	%g2, %tstate
1076*7c478bd9Sstevel@tonic-gate 
1077*7c478bd9Sstevel@tonic-gate /*
1078*7c478bd9Sstevel@tonic-gate  * Macro to get ptr to ch_err_tl1_data.
1079*7c478bd9Sstevel@tonic-gate  * reg1 will either point to a physaddr with ASI_MEM in %asi OR it
1080*7c478bd9Sstevel@tonic-gate  * will point to a kernel nucleus virtual address with ASI_N in %asi.
1081*7c478bd9Sstevel@tonic-gate  * This allows us to:
1082*7c478bd9Sstevel@tonic-gate  *   1. Avoid getting MMU misses.  We may have gotten the original
1083*7c478bd9Sstevel@tonic-gate  *	Fast ECC error in an MMU handler and if we get an MMU trap
1084*7c478bd9Sstevel@tonic-gate  *	in the TL>0 handlers, we'll scribble on the MMU regs.
1085*7c478bd9Sstevel@tonic-gate  *   2. Allows us to use the same code in the TL>0 handlers whether
1086*7c478bd9Sstevel@tonic-gate  *	we're accessing kernel nucleus virtual addresses or physical
1087*7c478bd9Sstevel@tonic-gate  *	addresses.
1088*7c478bd9Sstevel@tonic-gate  * pseudo-code:
1089*7c478bd9Sstevel@tonic-gate  *	reg1 <- ch_err_tl1_paddrs[CPUID];
1090*7c478bd9Sstevel@tonic-gate  *	if (reg1 == NULL) {
1091*7c478bd9Sstevel@tonic-gate  *		reg1 <- &ch_err_tl1_data
1092*7c478bd9Sstevel@tonic-gate  *		%asi <- ASI_N
1093*7c478bd9Sstevel@tonic-gate  *	} else {
1094*7c478bd9Sstevel@tonic-gate  *		reg1 <- reg1 + offset +
1095*7c478bd9Sstevel@tonic-gate  *		    sizeof (ch_err_tl1_data) * (%tl - 3)
1096*7c478bd9Sstevel@tonic-gate  *		%asi <- ASI_MEM
1097*7c478bd9Sstevel@tonic-gate  *	}
1098*7c478bd9Sstevel@tonic-gate  */
1099*7c478bd9Sstevel@tonic-gate #define	GET_CH_ERR_TL1_PTR(reg1, reg2, offset)	\
1100*7c478bd9Sstevel@tonic-gate 	CPU_INDEX(reg1, reg2);			\
1101*7c478bd9Sstevel@tonic-gate 	sllx	reg1, 3, reg1;			\
1102*7c478bd9Sstevel@tonic-gate 	set	ch_err_tl1_paddrs, reg2;	\
1103*7c478bd9Sstevel@tonic-gate 	ldx	[reg1+reg2], reg1;		\
1104*7c478bd9Sstevel@tonic-gate 	brnz	reg1, 1f;			\
1105*7c478bd9Sstevel@tonic-gate 	add	reg1, offset, reg1;		\
1106*7c478bd9Sstevel@tonic-gate 	set	ch_err_tl1_data, reg1;		\
1107*7c478bd9Sstevel@tonic-gate 	ba	2f;				\
1108*7c478bd9Sstevel@tonic-gate 	wr	%g0, ASI_N, %asi;		\
1109*7c478bd9Sstevel@tonic-gate 1:	rdpr	%tl, reg2;			\
1110*7c478bd9Sstevel@tonic-gate 	sub	reg2, 3, reg2;			\
1111*7c478bd9Sstevel@tonic-gate 	mulx	reg2, CH_ERR_TL1_DATA_SIZE, reg2;	\
1112*7c478bd9Sstevel@tonic-gate 	add	reg1, reg2, reg1;		\
1113*7c478bd9Sstevel@tonic-gate 	wr	%g0, ASI_MEM, %asi;		\
1114*7c478bd9Sstevel@tonic-gate 2:
1115*7c478bd9Sstevel@tonic-gate 
1116*7c478bd9Sstevel@tonic-gate /*
1117*7c478bd9Sstevel@tonic-gate  * Macro to generate entry code for TL>0 error handlers.
1118*7c478bd9Sstevel@tonic-gate  * At the end of this macro, %g1 will point to the ch_err_tl1_data
1119*7c478bd9Sstevel@tonic-gate  * structure and %g2 will have the original flags in the ch_err_tl1_data
1120*7c478bd9Sstevel@tonic-gate  * structure and %g5 will have the value of %tstate where the Fast ECC
1121*7c478bd9Sstevel@tonic-gate  * routines will save the state of the D$ in Bit2 CH_ERR_TSTATE_DC_ON.
1122*7c478bd9Sstevel@tonic-gate  * All %g registers except for %g1, %g2 and %g5 will be available after
1123*7c478bd9Sstevel@tonic-gate  * this macro.
1124*7c478bd9Sstevel@tonic-gate  * Does the following steps:
1125*7c478bd9Sstevel@tonic-gate  *   1. Compute physical address of per-cpu/per-tl save area using
1126*7c478bd9Sstevel@tonic-gate  *	only %g1+%g2 (which we've saved in %tpc, %tnpc, %tstate)
1127*7c478bd9Sstevel@tonic-gate  *	leaving address in %g1 and updating the %asi register.
1128*7c478bd9Sstevel@tonic-gate  *	If there is no data area available, we branch to label.
1129*7c478bd9Sstevel@tonic-gate  *   2. Save %g3-%g7 in save area.
1130*7c478bd9Sstevel@tonic-gate  *   3. Save %tpc->%g3, %tnpc->%g4, %tstate->%g5, which contain
1131*7c478bd9Sstevel@tonic-gate  *	original %g1+%g2 values (because we're going to change %tl).
1132*7c478bd9Sstevel@tonic-gate  *   4. set %tl <- %tl - 1.  We do this ASAP to make window of
1133*7c478bd9Sstevel@tonic-gate  *	running at %tl+1 as small as possible.
1134*7c478bd9Sstevel@tonic-gate  *   5. Reconstitute %g1+%g2 from %tpc (%g3), %tnpc (%g4),
1135*7c478bd9Sstevel@tonic-gate  *	%tstate (%g5) and save in save area, carefully preserving %g5
1136*7c478bd9Sstevel@tonic-gate  *	because it has the CH_ERR_TSTATE_DC_ON value.
1137*7c478bd9Sstevel@tonic-gate  *   6. Load existing ch_err_tl1_data flags in %g2
1138*7c478bd9Sstevel@tonic-gate  *   7. Compute the new flags
1139*7c478bd9Sstevel@tonic-gate  *   8. If %g2 is non-zero (the structure was busy), shift the new
1140*7c478bd9Sstevel@tonic-gate  *	flags by CH_ERR_ME_SHIFT and or them with the old flags.
1141*7c478bd9Sstevel@tonic-gate  *   9. Store the updated flags into ch_err_tl1_data flags.
1142*7c478bd9Sstevel@tonic-gate  *   10. If %g2 is non-zero, read the %tpc and store it in
1143*7c478bd9Sstevel@tonic-gate  *	ch_err_tl1_data.
1144*7c478bd9Sstevel@tonic-gate  */
1145*7c478bd9Sstevel@tonic-gate #define	CH_ERR_TL1_ENTER(flags)			\
1146*7c478bd9Sstevel@tonic-gate 	GET_CH_ERR_TL1_PTR(%g1, %g2, CHPR_TL1_ERR_DATA);	\
1147*7c478bd9Sstevel@tonic-gate 	stxa	%g3, [%g1 + CH_ERR_TL1_G3]%asi;	\
1148*7c478bd9Sstevel@tonic-gate 	stxa	%g4, [%g1 + CH_ERR_TL1_G4]%asi;	\
1149*7c478bd9Sstevel@tonic-gate 	stxa	%g5, [%g1 + CH_ERR_TL1_G5]%asi;	\
1150*7c478bd9Sstevel@tonic-gate 	stxa	%g6, [%g1 + CH_ERR_TL1_G6]%asi;	\
1151*7c478bd9Sstevel@tonic-gate 	stxa	%g7, [%g1 + CH_ERR_TL1_G7]%asi;	\
1152*7c478bd9Sstevel@tonic-gate 	rdpr	%tpc, %g3;			\
1153*7c478bd9Sstevel@tonic-gate 	rdpr	%tnpc, %g4;			\
1154*7c478bd9Sstevel@tonic-gate 	rdpr	%tstate, %g5;			\
1155*7c478bd9Sstevel@tonic-gate 	rdpr	%tl, %g6;			\
1156*7c478bd9Sstevel@tonic-gate 	sub	%g6, 1, %g6;			\
1157*7c478bd9Sstevel@tonic-gate 	wrpr	%g6, %tl;			\
1158*7c478bd9Sstevel@tonic-gate 	and	%g5, 3, %g6;			\
1159*7c478bd9Sstevel@tonic-gate 	andn	%g3, 3, %g3;			\
1160*7c478bd9Sstevel@tonic-gate 	or	%g3, %g6, %g3;			\
1161*7c478bd9Sstevel@tonic-gate 	stxa	%g3, [%g1 + CH_ERR_TL1_G1]%asi;	\
1162*7c478bd9Sstevel@tonic-gate 	srlx	%g5, CH_ERR_G2_TO_TSTATE_SHFT, %g6;	\
1163*7c478bd9Sstevel@tonic-gate 	and	%g6, 3, %g6;			\
1164*7c478bd9Sstevel@tonic-gate 	andn	%g4, 3, %g4;			\
1165*7c478bd9Sstevel@tonic-gate 	or	%g6, %g4, %g4;			\
1166*7c478bd9Sstevel@tonic-gate 	stxa	%g4, [%g1 + CH_ERR_TL1_G2]%asi;	\
1167*7c478bd9Sstevel@tonic-gate 	ldxa	[%g1 + CH_ERR_TL1_FLAGS]%asi, %g2;	\
1168*7c478bd9Sstevel@tonic-gate 	set	flags | CH_ERR_TL, %g3;		\
1169*7c478bd9Sstevel@tonic-gate 	brz	%g2, 9f;			\
1170*7c478bd9Sstevel@tonic-gate 	sllx	%g3, CH_ERR_ME_SHIFT, %g4;	\
1171*7c478bd9Sstevel@tonic-gate 	or	%g2, %g4, %g3;			\
1172*7c478bd9Sstevel@tonic-gate 9:	stxa	%g3, [%g1 + CH_ERR_TL1_FLAGS]%asi;	\
1173*7c478bd9Sstevel@tonic-gate 	brnz	%g2, 8f;			\
1174*7c478bd9Sstevel@tonic-gate 	rdpr	%tpc, %g4;			\
1175*7c478bd9Sstevel@tonic-gate 	stxa	%g4, [%g1 + CH_ERR_TL1_TPC]%asi;	\
1176*7c478bd9Sstevel@tonic-gate 8:
1177*7c478bd9Sstevel@tonic-gate 
1178*7c478bd9Sstevel@tonic-gate /*
1179*7c478bd9Sstevel@tonic-gate  * Turns off D$/I$ and saves the state of DCU_DC+DCU_IC in %tstate Bits 8+9
1180*7c478bd9Sstevel@tonic-gate  * (CH_ERR_TSTATE_DC_ON/CH_ERR_TSTATE_IC_ON).  This is invoked on Fast ECC
1181*7c478bd9Sstevel@tonic-gate  * at TL>0 handlers because the D$ may have corrupted data and we need to
1182*7c478bd9Sstevel@tonic-gate  * turn off the I$ to allow for diagnostic accesses.  We then invoke
1183*7c478bd9Sstevel@tonic-gate  * the normal entry macro and after it is done we save the values of
1184*7c478bd9Sstevel@tonic-gate  * the original D$/I$ state, which is in %g5 bits CH_ERR_TSTATE_DC_ON/
1185*7c478bd9Sstevel@tonic-gate  * CH_ERR_TSTATE_IC_ON in ch_err_tl1_tmp.
1186*7c478bd9Sstevel@tonic-gate  */
1187*7c478bd9Sstevel@tonic-gate #define	CH_ERR_TL1_FECC_ENTER			\
1188*7c478bd9Sstevel@tonic-gate 	ldxa	[%g0]ASI_DCU, %g1;		\
1189*7c478bd9Sstevel@tonic-gate 	andn	%g1, DCU_DC + DCU_IC, %g2;	\
1190*7c478bd9Sstevel@tonic-gate 	stxa	%g2, [%g0]ASI_DCU;		\
1191*7c478bd9Sstevel@tonic-gate 	flush	%g0;	/* DCU_IC need flush */	\
1192*7c478bd9Sstevel@tonic-gate 	rdpr	%tstate, %g2;			\
1193*7c478bd9Sstevel@tonic-gate 	and	%g1, DCU_DC + DCU_IC, %g1;	\
1194*7c478bd9Sstevel@tonic-gate 	sllx	%g1, CH_ERR_DCU_TO_TSTATE_SHFT, %g1;	\
1195*7c478bd9Sstevel@tonic-gate 	or	%g1, %g2, %g2;			\
1196*7c478bd9Sstevel@tonic-gate 	wrpr	%g2, %tstate;			\
1197*7c478bd9Sstevel@tonic-gate 	CH_ERR_TL1_ENTER(CH_ERR_FECC);		\
1198*7c478bd9Sstevel@tonic-gate 	and	%g5, CH_ERR_TSTATE_DC_ON + CH_ERR_TSTATE_IC_ON, %g5;	\
1199*7c478bd9Sstevel@tonic-gate 	stxa	%g5, [%g1 + CH_ERR_TL1_TMP]%asi
1200*7c478bd9Sstevel@tonic-gate 
1201*7c478bd9Sstevel@tonic-gate /*
1202*7c478bd9Sstevel@tonic-gate  * Macro to generate exit code for TL>0 error handlers.
1203*7c478bd9Sstevel@tonic-gate  * We fall into this macro if we've successfully logged the error in
1204*7c478bd9Sstevel@tonic-gate  * the ch_err_tl1_data structure and want the PIL15 softint to pick
1205*7c478bd9Sstevel@tonic-gate  * it up and log it.
1206*7c478bd9Sstevel@tonic-gate  * Does the following steps:
1207*7c478bd9Sstevel@tonic-gate  *   1.	Set pending flag for this cpu in ch_err_tl1_pending.
1208*7c478bd9Sstevel@tonic-gate  *   2.	Write %set_softint with (1<<pil) to cause a pil level trap
1209*7c478bd9Sstevel@tonic-gate  *   3.	Restore registers from ch_err_tl1_data, which is pointed to
1210*7c478bd9Sstevel@tonic-gate  *	by %g1, last register to restore is %g1 since it's pointing
1211*7c478bd9Sstevel@tonic-gate  *	to the save area.
1212*7c478bd9Sstevel@tonic-gate  *   4. Execute retry
1213*7c478bd9Sstevel@tonic-gate  */
1214*7c478bd9Sstevel@tonic-gate #define	CH_ERR_TL1_EXIT				\
1215*7c478bd9Sstevel@tonic-gate 	CPU_INDEX(%g2, %g3);			\
1216*7c478bd9Sstevel@tonic-gate 	set	ch_err_tl1_pending, %g3;	\
1217*7c478bd9Sstevel@tonic-gate 	set	-1, %g4;			\
1218*7c478bd9Sstevel@tonic-gate 	stb	%g4, [%g2 + %g3];		\
1219*7c478bd9Sstevel@tonic-gate 	mov	1, %g2;				\
1220*7c478bd9Sstevel@tonic-gate 	sll	%g2, PIL_15, %g2;		\
1221*7c478bd9Sstevel@tonic-gate 	wr	%g2, SET_SOFTINT;		\
1222*7c478bd9Sstevel@tonic-gate 	ldxa	[%g1 + CH_ERR_TL1_G7]%asi, %g7;	\
1223*7c478bd9Sstevel@tonic-gate 	ldxa	[%g1 + CH_ERR_TL1_G6]%asi, %g6;	\
1224*7c478bd9Sstevel@tonic-gate 	ldxa	[%g1 + CH_ERR_TL1_G5]%asi, %g5;	\
1225*7c478bd9Sstevel@tonic-gate 	ldxa	[%g1 + CH_ERR_TL1_G4]%asi, %g4;	\
1226*7c478bd9Sstevel@tonic-gate 	ldxa	[%g1 + CH_ERR_TL1_G3]%asi, %g3;	\
1227*7c478bd9Sstevel@tonic-gate 	ldxa	[%g1 + CH_ERR_TL1_G2]%asi, %g2;	\
1228*7c478bd9Sstevel@tonic-gate 	ldxa	[%g1 + CH_ERR_TL1_G1]%asi, %g1;	\
1229*7c478bd9Sstevel@tonic-gate 	retry
1230*7c478bd9Sstevel@tonic-gate 
1231*7c478bd9Sstevel@tonic-gate /*
1232*7c478bd9Sstevel@tonic-gate  * Generates unrecoverable error label for TL>0 handlers.
1233*7c478bd9Sstevel@tonic-gate  * At label (Unrecoverable error routine)
1234*7c478bd9Sstevel@tonic-gate  *   1. Sets flags in ch_err_tl1_data and leaves in %g2 (first
1235*7c478bd9Sstevel@tonic-gate  *	argument to cpu_tl1_err_panic).
1236*7c478bd9Sstevel@tonic-gate  *   2.	Call cpu_tl1_err_panic via systrap at PIL 15
1237*7c478bd9Sstevel@tonic-gate  */
1238*7c478bd9Sstevel@tonic-gate #define	CH_ERR_TL1_PANIC_EXIT(label)		\
1239*7c478bd9Sstevel@tonic-gate label:	ldxa	[%g1 + CH_ERR_TL1_FLAGS]%asi, %g2;	\
1240*7c478bd9Sstevel@tonic-gate 	or	%g2, CH_ERR_TL | CH_ERR_PANIC, %g2;	\
1241*7c478bd9Sstevel@tonic-gate 	stxa	%g2, [%g1 + CH_ERR_TL1_FLAGS]%asi;	\
1242*7c478bd9Sstevel@tonic-gate 	set	cpu_tl1_err_panic, %g1;		\
1243*7c478bd9Sstevel@tonic-gate 	ba	sys_trap;			\
1244*7c478bd9Sstevel@tonic-gate 	  mov	PIL_15, %g4
1245*7c478bd9Sstevel@tonic-gate 
1246*7c478bd9Sstevel@tonic-gate 
1247*7c478bd9Sstevel@tonic-gate 
1248*7c478bd9Sstevel@tonic-gate /* END CSTYLED */
1249*7c478bd9Sstevel@tonic-gate #endif	/* _ASM */
1250*7c478bd9Sstevel@tonic-gate 
1251*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
1252*7c478bd9Sstevel@tonic-gate }
1253*7c478bd9Sstevel@tonic-gate #endif
1254*7c478bd9Sstevel@tonic-gate 
1255*7c478bd9Sstevel@tonic-gate #endif /* _CHEETAHASM_H */
1256