xref: /titanic_50/usr/src/uts/sun4u/io/panther_asm.s (revision 142c9f13e148d687426ed2d4e8bd93717eeaebbc)
1*142c9f13Sbala/*
2*142c9f13Sbala * CDDL HEADER START
3*142c9f13Sbala *
4*142c9f13Sbala * The contents of this file are subject to the terms of the
5*142c9f13Sbala * Common Development and Distribution License (the "License").
6*142c9f13Sbala * You may not use this file except in compliance with the License.
7*142c9f13Sbala *
8*142c9f13Sbala * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*142c9f13Sbala * or http://www.opensolaris.org/os/licensing.
10*142c9f13Sbala * See the License for the specific language governing permissions
11*142c9f13Sbala * and limitations under the License.
12*142c9f13Sbala *
13*142c9f13Sbala * When distributing Covered Code, include this CDDL HEADER in each
14*142c9f13Sbala * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*142c9f13Sbala * If applicable, add the following below this CDDL HEADER, with the
16*142c9f13Sbala * fields enclosed by brackets "[]" replaced with your own identifying
17*142c9f13Sbala * information: Portions Copyright [yyyy] [name of copyright owner]
18*142c9f13Sbala *
19*142c9f13Sbala * CDDL HEADER END
20*142c9f13Sbala */
21*142c9f13Sbala/*
22*142c9f13Sbala * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*142c9f13Sbala * Use is subject to license terms.
24*142c9f13Sbala *
25*142c9f13Sbala * Assembly code support for the Cheetah+ module
26*142c9f13Sbala */
27*142c9f13Sbala
28*142c9f13Sbala#pragma ident	"%Z%%M%	%I%	%E% SMI"
29*142c9f13Sbala
30*142c9f13Sbala#if !defined(lint)
31*142c9f13Sbala#include "assym.h"
32*142c9f13Sbala#endif	/* lint */
33*142c9f13Sbala
34*142c9f13Sbala#include <sys/asm_linkage.h>
35*142c9f13Sbala#include <sys/mmu.h>
36*142c9f13Sbala#include <vm/hat_sfmmu.h>
37*142c9f13Sbala#include <sys/machparam.h>
38*142c9f13Sbala#include <sys/machcpuvar.h>
39*142c9f13Sbala#include <sys/machthread.h>
40*142c9f13Sbala#include <sys/machtrap.h>
41*142c9f13Sbala#include <sys/privregs.h>
42*142c9f13Sbala#include <sys/asm_linkage.h>
43*142c9f13Sbala#include <sys/trap.h>
44*142c9f13Sbala#include <sys/cheetahregs.h>
45*142c9f13Sbala#include <sys/xc_impl.h>
46*142c9f13Sbala#include <sys/intreg.h>
47*142c9f13Sbala#include <sys/async.h>
48*142c9f13Sbala#include <sys/clock.h>
49*142c9f13Sbala#include <sys/cheetahasm.h>
50*142c9f13Sbala#include <sys/cmpregs.h>
51*142c9f13Sbala
52*142c9f13Sbala#ifdef TRAPTRACE
53*142c9f13Sbala#include <sys/traptrace.h>
54*142c9f13Sbala#endif /* TRAPTRACE */
55*142c9f13Sbala
56*142c9f13Sbala
57*142c9f13Sbala#if !defined(lint)
58*142c9f13Sbala
59*142c9f13Sbala	.global retire_l2_start
60*142c9f13Sbala	.global retire_l2_end
61*142c9f13Sbala	.global unretire_l2_start
62*142c9f13Sbala	.global unretire_l2_end
63*142c9f13Sbala	.global retire_l3_start
64*142c9f13Sbala	.global retire_l3_end
65*142c9f13Sbala	.global unretire_l3_start
66*142c9f13Sbala	.global unretire_l3_end
67*142c9f13Sbala
68*142c9f13Sbala/*
69*142c9f13Sbala * Panther version to reflush a line from both the L2 cache and L3
70*142c9f13Sbala * cache by the respective indexes. Flushes all ways of the line from
71*142c9f13Sbala * each cache.
72*142c9f13Sbala *
73*142c9f13Sbala * l2_index	Index into the L2$ of the line to be flushed. This
74*142c9f13Sbala *		register will not be modified by this routine.
75*142c9f13Sbala * l3_index	Index into the L3$ of the line to be flushed. This
76*142c9f13Sbala *		register will not be modified by this routine.
77*142c9f13Sbala * scr2		scratch register.
78*142c9f13Sbala * scr3		scratch register.
79*142c9f13Sbala *
80*142c9f13Sbala */
81*142c9f13Sbala#define	PN_ECACHE_REFLUSH_LINE(l2_index, l3_index, scr2, scr3)		\
82*142c9f13Sbala	set	PN_L2_MAX_SET, scr2;					\
83*142c9f13Sbala	set	PN_L2_SET_SIZE, scr3;					\
84*142c9f13Sbala1:									\
85*142c9f13Sbala	ldxa	[l2_index + scr2]ASI_L2_TAG, %g0;			\
86*142c9f13Sbala	cmp	scr2, %g0;						\
87*142c9f13Sbala	bg,a	1b;							\
88*142c9f13Sbala	  sub	scr2, scr3, scr2;					\
89*142c9f13Sbala	mov	6, scr2;						\
90*142c9f13Sbala6:									\
91*142c9f13Sbala	cmp	scr2, %g0;						\
92*142c9f13Sbala	bg,a	6b;							\
93*142c9f13Sbala	  sub	scr2, 1, scr2;						\
94*142c9f13Sbala	set	PN_L3_MAX_SET, scr2;					\
95*142c9f13Sbala	set	PN_L3_SET_SIZE, scr3;					\
96*142c9f13Sbala2:									\
97*142c9f13Sbala	ldxa	[l3_index + scr2]ASI_EC_DIAG, %g0;			\
98*142c9f13Sbala	cmp	scr2, %g0;						\
99*142c9f13Sbala	bg,a	2b;							\
100*142c9f13Sbala	  sub	scr2, scr3, scr2;
101*142c9f13Sbala
102*142c9f13Sbala/*
103*142c9f13Sbala * Panther version of ecache_flush_line. Flushes the line corresponding
104*142c9f13Sbala * to physaddr from both the L2 cache and the L3 cache.
105*142c9f13Sbala *
106*142c9f13Sbala * physaddr	Input: Physical address to flush.
107*142c9f13Sbala *              Output: Physical address to flush (preserved).
108*142c9f13Sbala * l2_idx_out	Input: scratch register.
109*142c9f13Sbala *              Output: Index into the L2$ of the line to be flushed.
110*142c9f13Sbala * l3_idx_out	Input: scratch register.
111*142c9f13Sbala *              Output: Index into the L3$ of the line to be flushed.
112*142c9f13Sbala * scr3		scratch register.
113*142c9f13Sbala * scr4		scratch register.
114*142c9f13Sbala *
115*142c9f13Sbala */
116*142c9f13Sbala#define	PN_ECACHE_FLUSH_LINE(physaddr, l2_idx_out, l3_idx_out, scr3, scr4)	\
117*142c9f13Sbala	set	PN_L3_SET_SIZE, l2_idx_out;					\
118*142c9f13Sbala	sub	l2_idx_out, 1, l2_idx_out;					\
119*142c9f13Sbala	and	physaddr, l2_idx_out, l3_idx_out;				\
120*142c9f13Sbala	set	PN_L3_IDX_DISP_FLUSH, l2_idx_out;				\
121*142c9f13Sbala	or	l2_idx_out, l3_idx_out, l3_idx_out;				\
122*142c9f13Sbala	set	PN_L2_SET_SIZE, l2_idx_out;					\
123*142c9f13Sbala	sub	l2_idx_out, 1, l2_idx_out;					\
124*142c9f13Sbala	and	physaddr, l2_idx_out, l2_idx_out;				\
125*142c9f13Sbala	set	PN_L2_IDX_DISP_FLUSH, scr3;					\
126*142c9f13Sbala	or	l2_idx_out, scr3, l2_idx_out;					\
127*142c9f13Sbala	PN_ECACHE_REFLUSH_LINE(l2_idx_out, l3_idx_out, scr3, scr4)
128*142c9f13Sbala
129*142c9f13Sbala
130*142c9f13Sbala#endif	/* !lint */
131*142c9f13Sbala
132*142c9f13Sbala#if defined(lint)
133*142c9f13Sbala
134*142c9f13Sbala/*ARGSUSED*/
135*142c9f13Sbalaint
136*142c9f13Sbalaretire_l2(uint64_t tag_addr, uint64_t pattern)
137*142c9f13Sbala{return 0;}
138*142c9f13Sbala
139*142c9f13Sbala#else
140*142c9f13Sbala	.align 4096
141*142c9f13Sbala	ENTRY(retire_l2)
142*142c9f13Sbalaretire_l2_start:
143*142c9f13Sbala
144*142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
145*142c9f13Sbala	rdpr	%pstate, %o2
146*142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
147*142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
148*142c9f13Sbala	/*
149*142c9f13Sbala	 * Save current DCU state.  Turn off IPS
150*142c9f13Sbala	 */
151*142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
152*142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
153*142c9f13Sbala	andn	%g1, %o3, %g4
154*142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
155*142c9f13Sbala	flush	%g0
156*142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
157*142c9f13Sbala	clr	%o5	! assume success
158*142c9f13Sbala8:
159*142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %g2, %g3)
160*142c9f13Sbala1:
161*142c9f13Sbala	! Check if line is invalid; if so, NA it.
162*142c9f13Sbala	ldxa	[%o0]ASI_L2_TAG, %o3
163*142c9f13Sbala	btst	0x7, %o3
164*142c9f13Sbala	bnz	%xcc, 2f
165*142c9f13Sbala	 nop
166*142c9f13Sbala	stxa	%o1, [%o0]ASI_L2_TAG
167*142c9f13Sbala	membar #Sync	! still on same cache line
168*142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
169*142c9f13Sbala	mov	16, %o1
170*142c9f13Sbala1:
171*142c9f13Sbala	brnz,pt	%o1, 1b
172*142c9f13Sbala	 dec	%o1
173*142c9f13Sbala9:
174*142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary
175*142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
176*142c9f13Sbala	/*
177*142c9f13Sbala	 * Restore the DCU
178*142c9f13Sbala	 */
179*142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
180*142c9f13Sbala	flush	%g0
181*142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
182*142c9f13Sbala	retl
183*142c9f13Sbala	 mov	%o5, %o0
184*142c9f13Sbala2:
185*142c9f13Sbala	! It is OK to have STATE as NA (if so, nothing to do!)
186*142c9f13Sbala	and	%o3, 0x7, %o3
187*142c9f13Sbala	cmp	%o3, 0x5
188*142c9f13Sbala	be,a,pt	%xcc, 9b
189*142c9f13Sbala	 mov	1, %o5	! indicate was already NA
190*142c9f13Sbala	! Hmm.	Not INV, not NA.
191*142c9f13Sbala	cmp	%o5, 0
192*142c9f13Sbala	be,a,pt	%xcc, 8b	! Flush the cacheline again
193*142c9f13Sbala	 mov	2, %o5	! indicate retry was done
194*142c9f13Sbala	! We already Flushed cacheline second time. Return -1
195*142c9f13Sbala	clr	%o5
196*142c9f13Sbala	ba	9b
197*142c9f13Sbala	 dec	%o5
198*142c9f13Sbalaretire_l2_end:
199*142c9f13Sbala	SET_SIZE(retire_l2)
200*142c9f13Sbala
201*142c9f13Sbala#endif	/* lint */
202*142c9f13Sbala
203*142c9f13Sbala#if defined(lint)
204*142c9f13Sbala
205*142c9f13Sbala/*
206*142c9f13Sbala */
207*142c9f13Sbala/*ARGSUSED*/
208*142c9f13Sbalaint
209*142c9f13Sbalaunretire_l2(uint64_t tag_addr, uint64_t pattern)
210*142c9f13Sbala{return 0;}
211*142c9f13Sbala
212*142c9f13Sbala#else
213*142c9f13Sbala	ENTRY(unretire_l2)
214*142c9f13Sbalaunretire_l2_start:
215*142c9f13Sbala
216*142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
217*142c9f13Sbala	rdpr	%pstate, %o2
218*142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
219*142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
220*142c9f13Sbala	/*
221*142c9f13Sbala	 * Save current DCU state.  Turn off IPS
222*142c9f13Sbala	 */
223*142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
224*142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
225*142c9f13Sbala	andn	%g1, %o3, %g4
226*142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
227*142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
228*142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
229*142c9f13Sbala
230*142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
231*142c9f13Sbala1:
232*142c9f13Sbala	clr	%o5	! assume success
233*142c9f13Sbala	! Check that line is in NA state; if so, INV it.
234*142c9f13Sbala	ldxa	[%o0]ASI_L2_TAG, %o3
235*142c9f13Sbala	and	%o3, 0x7, %o3
236*142c9f13Sbala	cmp	%o3, 0x5
237*142c9f13Sbala	bne,a,pt %xcc, 9f	! Wasn't NA, so something is wrong
238*142c9f13Sbala	 dec	%o5	! indicate not NA
239*142c9f13Sbala	stxa	%g0, [%o0]ASI_L2_TAG
240*142c9f13Sbala	membar #Sync
241*142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
242*142c9f13Sbala	mov	16, %o1
243*142c9f13Sbala1:
244*142c9f13Sbala	brnz,pt	%o1, 1b
245*142c9f13Sbala	 dec	%o1
246*142c9f13Sbala9:
247*142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions
248*142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
249*142c9f13Sbala	/*
250*142c9f13Sbala	 * Restore the DCU
251*142c9f13Sbala	 */
252*142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
253*142c9f13Sbala	flush	%g0
254*142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
255*142c9f13Sbala	retl
256*142c9f13Sbala	 mov	%o5, %o0
257*142c9f13Sbalaunretire_l2_end:
258*142c9f13Sbala	SET_SIZE(unretire_l2)
259*142c9f13Sbala
260*142c9f13Sbala#endif	/* lint */
261*142c9f13Sbala
262*142c9f13Sbala#if defined(lint)
263*142c9f13Sbala
264*142c9f13Sbala/*ARGSUSED*/
265*142c9f13Sbalaint
266*142c9f13Sbalaretire_l3(uint64_t tag_addr, uint64_t pattern)
267*142c9f13Sbala{return 0;}
268*142c9f13Sbala
269*142c9f13Sbala#else
270*142c9f13Sbala	ENTRY(retire_l3)
271*142c9f13Sbalaretire_l3_start:
272*142c9f13Sbala
273*142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
274*142c9f13Sbala	rdpr	%pstate, %o2
275*142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
276*142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
277*142c9f13Sbala	/*
278*142c9f13Sbala	 * Save current DCU state.  Turn off IPS
279*142c9f13Sbala	 */
280*142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
281*142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
282*142c9f13Sbala	andn	%g1, %o3, %g4
283*142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
284*142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
285*142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
286*142c9f13Sbala
287*142c9f13Sbala	! PN-ECACHE-FLUSH_LINE is 30 instructions
288*142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
289*142c9f13Sbala1:
290*142c9f13Sbala	clr	%o5	! assume success
291*142c9f13Sbala	! Check if line is invalid; if so, NA it.
292*142c9f13Sbala	ldxa	[%o0]ASI_EC_DIAG, %o3
293*142c9f13Sbala	btst	0x7, %o3
294*142c9f13Sbala	bnz	%xcc, 2f
295*142c9f13Sbala	 nop
296*142c9f13Sbala	stxa	%o1, [%o0]ASI_EC_DIAG
297*142c9f13Sbala	membar #Sync	! still on same cache line
298*142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
299*142c9f13Sbala	mov	16, %o1
300*142c9f13Sbala1:
301*142c9f13Sbala	brnz,pt	%o1, 1b
302*142c9f13Sbala	 dec	%o1
303*142c9f13Sbala9:
304*142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary
305*142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
306*142c9f13Sbala	/*
307*142c9f13Sbala	 * Restore the DCU
308*142c9f13Sbala	 */
309*142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
310*142c9f13Sbala	flush	%g0
311*142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
312*142c9f13Sbala	retl
313*142c9f13Sbala	 mov	%o5, %o0
314*142c9f13Sbala2:
315*142c9f13Sbala	! It is OK to have STATE as NA (if so, nothing to do!)
316*142c9f13Sbala	and	%o3, 0x7, %o3
317*142c9f13Sbala	cmp	%o3, 0x5
318*142c9f13Sbala	be,a,pt	%xcc, 9b
319*142c9f13Sbala	 inc	%o5	! indicate was already NA
320*142c9f13Sbala	! Hmm.	Not INV, not NA
321*142c9f13Sbala	ba	9b
322*142c9f13Sbala	 dec	%o5
323*142c9f13Sbalaretire_l3_end:
324*142c9f13Sbala	SET_SIZE(retire_l3)
325*142c9f13Sbala
326*142c9f13Sbala#endif	/* lint */
327*142c9f13Sbala
328*142c9f13Sbala#if defined(lint)
329*142c9f13Sbala
330*142c9f13Sbala/*
331*142c9f13Sbala */
332*142c9f13Sbala/*ARGSUSED*/
333*142c9f13Sbalaint
334*142c9f13Sbalaunretire_l3(uint64_t tag_addr, uint64_t pattern)
335*142c9f13Sbala{return 0;}
336*142c9f13Sbala
337*142c9f13Sbala#else
338*142c9f13Sbala	ENTRY(unretire_l3)
339*142c9f13Sbalaunretire_l3_start:
340*142c9f13Sbala
341*142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
342*142c9f13Sbala	rdpr	%pstate, %o2
343*142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
344*142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
345*142c9f13Sbala	/*
346*142c9f13Sbala	 * Save current DCU state.  Turn off IPS
347*142c9f13Sbala	 */
348*142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
349*142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
350*142c9f13Sbala	andn	%g1, %o3, %g4
351*142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
352*142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
353*142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
354*142c9f13Sbala
355*142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
356*142c9f13Sbala1:
357*142c9f13Sbala	clr	%o5	! assume success
358*142c9f13Sbala	! Check that line is in NA state; if so, INV it.
359*142c9f13Sbala	ldxa	[%o0]ASI_EC_DIAG, %o3
360*142c9f13Sbala	and	%o3, 0x7, %o3
361*142c9f13Sbala	cmp	%o3, 0x5
362*142c9f13Sbala	bne,a,pt %xcc, 9f	! Wasn't NA, so something is wrong
363*142c9f13Sbala	 dec	%o5	! indicate not NA
364*142c9f13Sbala	stxa	%g0, [%o0]ASI_EC_DIAG
365*142c9f13Sbala	membar #Sync
366*142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
367*142c9f13Sbala	mov	16, %o1
368*142c9f13Sbala1:
369*142c9f13Sbala	brnz,pt	%o1, 1b
370*142c9f13Sbala	 dec	%o1
371*142c9f13Sbala9:
372*142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions
373*142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
374*142c9f13Sbala	/*
375*142c9f13Sbala	 * Restore the DCU
376*142c9f13Sbala	 */
377*142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
378*142c9f13Sbala	flush	%g0
379*142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
380*142c9f13Sbala	retl
381*142c9f13Sbala	 mov	%o5, %o0
382*142c9f13Sbalaunretire_l3_end:
383*142c9f13Sbala	SET_SIZE(unretire_l3)
384*142c9f13Sbala
385*142c9f13Sbala#endif	/* lint */
386*142c9f13Sbala
387*142c9f13Sbala#if defined(lint)
388*142c9f13Sbala
389*142c9f13Sbala/*ARGSUSED*/
390*142c9f13Sbalaint
391*142c9f13Sbalaretire_l2_alternate(uint64_t tag_addr, uint64_t pattern)
392*142c9f13Sbala{return 0;}
393*142c9f13Sbala
394*142c9f13Sbala#else
395*142c9f13Sbala	.align 2048
396*142c9f13Sbala
397*142c9f13Sbala	ENTRY(retire_l2_alternate)
398*142c9f13Sbala
399*142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
400*142c9f13Sbala	rdpr	%pstate, %o2
401*142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
402*142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
403*142c9f13Sbala	/*
404*142c9f13Sbala	 * Save current DCU state.  Turn off IPS
405*142c9f13Sbala	 */
406*142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
407*142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
408*142c9f13Sbala	andn	%g1, %o3, %g4
409*142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
410*142c9f13Sbala	flush	%g0
411*142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
412*142c9f13Sbala	clr	%o5	! assume success
413*142c9f13Sbala8:
414*142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %g2, %g3)
415*142c9f13Sbala1:
416*142c9f13Sbala	! Check if line is invalid; if so, NA it.
417*142c9f13Sbala	ldxa	[%o0]ASI_L2_TAG, %o3
418*142c9f13Sbala	btst	0x7, %o3
419*142c9f13Sbala	bnz	%xcc, 2f
420*142c9f13Sbala	 nop
421*142c9f13Sbala	stxa	%o1, [%o0]ASI_L2_TAG
422*142c9f13Sbala	membar #Sync	! still on same cache line
423*142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
424*142c9f13Sbala	mov	16, %o1
425*142c9f13Sbala1:
426*142c9f13Sbala	brnz,pt	%o1, 1b
427*142c9f13Sbala	 dec	%o1
428*142c9f13Sbala9:
429*142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary
430*142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
431*142c9f13Sbala	/*
432*142c9f13Sbala	 * Restore the DCU
433*142c9f13Sbala	 */
434*142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
435*142c9f13Sbala	flush	%g0
436*142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
437*142c9f13Sbala	retl
438*142c9f13Sbala	 mov	%o5, %o0
439*142c9f13Sbala2:
440*142c9f13Sbala	! It is OK to have STATE as NA (if so, nothing to do!)
441*142c9f13Sbala	and	%o3, 0x7, %o3
442*142c9f13Sbala	cmp	%o3, 0x5
443*142c9f13Sbala	be,a,pt	%xcc, 9b
444*142c9f13Sbala	 mov	1, %o5	! indicate was already NA
445*142c9f13Sbala	! Hmm.	Not INV, not NA.
446*142c9f13Sbala	cmp	%o5, 0
447*142c9f13Sbala	be,a,pt	%xcc, 8b	! Flush the cacheline again
448*142c9f13Sbala	 mov	2, %o5	! indicate retry was done
449*142c9f13Sbala	! We already Flushed cacheline second time. Return -1
450*142c9f13Sbala	clr	%o5
451*142c9f13Sbala	ba	9b
452*142c9f13Sbala	 dec	%o5
453*142c9f13Sbala	SET_SIZE(retire_l2_alternate)
454*142c9f13Sbala
455*142c9f13Sbala#endif	/* lint */
456*142c9f13Sbala
457*142c9f13Sbala#if defined(lint)
458*142c9f13Sbala
459*142c9f13Sbala/*
460*142c9f13Sbala */
461*142c9f13Sbala/*ARGSUSED*/
462*142c9f13Sbalaint
463*142c9f13Sbalaunretire_l2_alternate(uint64_t tag_addr, uint64_t pattern)
464*142c9f13Sbala{return 0;}
465*142c9f13Sbala
466*142c9f13Sbala#else
467*142c9f13Sbala	ENTRY(unretire_l2_alternate)
468*142c9f13Sbala
469*142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
470*142c9f13Sbala	rdpr	%pstate, %o2
471*142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
472*142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
473*142c9f13Sbala	/*
474*142c9f13Sbala	 * Save current DCU state.  Turn off IPS
475*142c9f13Sbala	 */
476*142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
477*142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
478*142c9f13Sbala	andn	%g1, %o3, %g4
479*142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
480*142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
481*142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
482*142c9f13Sbala
483*142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
484*142c9f13Sbala1:
485*142c9f13Sbala	clr	%o5	! assume success
486*142c9f13Sbala	! Check that line is in NA state; if so, INV it.
487*142c9f13Sbala	ldxa	[%o0]ASI_L2_TAG, %o3
488*142c9f13Sbala	and	%o3, 0x7, %o3
489*142c9f13Sbala	cmp	%o3, 0x5
490*142c9f13Sbala	bne,a,pt %xcc, 9f	! Wasn't NA, so something is wrong
491*142c9f13Sbala	 dec	%o5	! indicate not NA
492*142c9f13Sbala	stxa	%g0, [%o0]ASI_L2_TAG
493*142c9f13Sbala	membar #Sync
494*142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
495*142c9f13Sbala	mov	16, %o1
496*142c9f13Sbala1:
497*142c9f13Sbala	brnz,pt	%o1, 1b
498*142c9f13Sbala	 dec	%o1
499*142c9f13Sbala9:
500*142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions
501*142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
502*142c9f13Sbala	/*
503*142c9f13Sbala	 * Restore the DCU
504*142c9f13Sbala	 */
505*142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
506*142c9f13Sbala	flush	%g0
507*142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
508*142c9f13Sbala	retl
509*142c9f13Sbala	 mov	%o5, %o0
510*142c9f13Sbala	SET_SIZE(unretire_l2_alternate)
511*142c9f13Sbala
512*142c9f13Sbala#endif	/* lint */
513*142c9f13Sbala
514*142c9f13Sbala#if defined(lint)
515*142c9f13Sbala
516*142c9f13Sbala/*ARGSUSED*/
517*142c9f13Sbalaint
518*142c9f13Sbalaretire_l3_alternate(uint64_t tag_addr, uint64_t pattern)
519*142c9f13Sbala{return 0;}
520*142c9f13Sbala
521*142c9f13Sbala#else
522*142c9f13Sbala	ENTRY(retire_l3_alternate)
523*142c9f13Sbala
524*142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
525*142c9f13Sbala	rdpr	%pstate, %o2
526*142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
527*142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
528*142c9f13Sbala	/*
529*142c9f13Sbala	 * Save current DCU state.  Turn off IPS
530*142c9f13Sbala	 */
531*142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
532*142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
533*142c9f13Sbala	andn	%g1, %o3, %g4
534*142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
535*142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
536*142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
537*142c9f13Sbala
538*142c9f13Sbala	! PN-ECACHE-FLUSH_LINE is 30 instructions
539*142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
540*142c9f13Sbala1:
541*142c9f13Sbala	clr	%o5	! assume success
542*142c9f13Sbala	! Check if line is invalid; if so, NA it.
543*142c9f13Sbala	ldxa	[%o0]ASI_EC_DIAG, %o3
544*142c9f13Sbala	btst	0x7, %o3
545*142c9f13Sbala	bnz	%xcc, 2f
546*142c9f13Sbala	 nop
547*142c9f13Sbala	stxa	%o1, [%o0]ASI_EC_DIAG
548*142c9f13Sbala	membar #Sync	! still on same cache line
549*142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
550*142c9f13Sbala	mov	16, %o1
551*142c9f13Sbala1:
552*142c9f13Sbala	brnz,pt	%o1, 1b
553*142c9f13Sbala	 dec	%o1
554*142c9f13Sbala9:
555*142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary
556*142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
557*142c9f13Sbala	/*
558*142c9f13Sbala	 * Restore the DCU
559*142c9f13Sbala	 */
560*142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
561*142c9f13Sbala	flush	%g0
562*142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
563*142c9f13Sbala	retl
564*142c9f13Sbala	 mov	%o5, %o0
565*142c9f13Sbala2:
566*142c9f13Sbala	! It is OK to have STATE as NA (if so, nothing to do!)
567*142c9f13Sbala	and	%o3, 0x7, %o3
568*142c9f13Sbala	cmp	%o3, 0x5
569*142c9f13Sbala	be,a,pt	%xcc, 9b
570*142c9f13Sbala	 inc	%o5	! indicate was already NA
571*142c9f13Sbala	! Hmm.	Not INV, not NA
572*142c9f13Sbala	ba	9b
573*142c9f13Sbala	 dec	%o5
574*142c9f13Sbala	SET_SIZE(retire_l3_alternate)
575*142c9f13Sbala
576*142c9f13Sbala#endif	/* lint */
577*142c9f13Sbala
578*142c9f13Sbala#if defined(lint)
579*142c9f13Sbala
580*142c9f13Sbala/*
581*142c9f13Sbala */
582*142c9f13Sbala/*ARGSUSED*/
583*142c9f13Sbalaint
584*142c9f13Sbalaunretire_l3_alternate(uint64_t tag_addr, uint64_t pattern)
585*142c9f13Sbala{return 0;}
586*142c9f13Sbala
587*142c9f13Sbala#else
588*142c9f13Sbala	ENTRY(unretire_l3_alternate)
589*142c9f13Sbala
590*142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
591*142c9f13Sbala	rdpr	%pstate, %o2
592*142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
593*142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
594*142c9f13Sbala	/*
595*142c9f13Sbala	 * Save current DCU state.  Turn off IPS
596*142c9f13Sbala	 */
597*142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
598*142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
599*142c9f13Sbala	andn	%g1, %o3, %g4
600*142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
601*142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
602*142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
603*142c9f13Sbala
604*142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
605*142c9f13Sbala1:
606*142c9f13Sbala	clr	%o5	! assume success
607*142c9f13Sbala	! Check that line is in NA state; if so, INV it.
608*142c9f13Sbala	ldxa	[%o0]ASI_EC_DIAG, %o3
609*142c9f13Sbala	and	%o3, 0x7, %o3
610*142c9f13Sbala	cmp	%o3, 0x5
611*142c9f13Sbala	bne,a,pt %xcc, 9f	! Wasn't NA, so something is wrong
612*142c9f13Sbala	 dec	%o5	! indicate not NA
613*142c9f13Sbala	stxa	%g0, [%o0]ASI_EC_DIAG
614*142c9f13Sbala	membar #Sync
615*142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
616*142c9f13Sbala	mov	16, %o1
617*142c9f13Sbala1:
618*142c9f13Sbala	brnz,pt	%o1, 1b
619*142c9f13Sbala	 dec	%o1
620*142c9f13Sbala9:
621*142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions
622*142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
623*142c9f13Sbala	/*
624*142c9f13Sbala	 * Restore the DCU
625*142c9f13Sbala	 */
626*142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
627*142c9f13Sbala	flush	%g0
628*142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
629*142c9f13Sbala	retl
630*142c9f13Sbala	 mov	%o5, %o0
631*142c9f13Sbala	SET_SIZE(unretire_l3_alternate)
632*142c9f13Sbala
633*142c9f13Sbala#endif	/* lint */
634*142c9f13Sbala
635*142c9f13Sbala#if defined(lint)
636*142c9f13Sbala
637*142c9f13Sbala/*ARGSUSED*/
638*142c9f13Sbalavoid
639*142c9f13Sbalaget_ecache_dtags_tl1(uint64_t afar, ch_cpu_logout_t *clop)
640*142c9f13Sbala{ }
641*142c9f13Sbala
642*142c9f13Sbala#else
643*142c9f13Sbala	ENTRY(get_ecache_dtags_tl1)
644*142c9f13Sbala
645*142c9f13Sbala
646*142c9f13Sbala	PARK_SIBLING_CORE(%g3, %g4, %g5)
647*142c9f13Sbala	add	%g2, CH_CLO_DATA + CH_CHD_EC_DATA, %g2
648*142c9f13Sbala	rd	%asi, %g4
649*142c9f13Sbala	wr	%g0, ASI_N, %asi
650*142c9f13Sbala	GET_ECACHE_DTAGS(%g1, %g2, %g5, %g6, %g7)
651*142c9f13Sbala	wr	%g4, %asi
652*142c9f13Sbala	UNPARK_SIBLING_CORE(%g3, %g4, %g5)	! can use %g3 again
653*142c9f13Sbala
654*142c9f13Sbala	retry
655*142c9f13Sbala	SET_SIZE(get_ecache_dtags_tl1)
656*142c9f13Sbala
657*142c9f13Sbala#endif	/* lint */
658*142c9f13Sbala
659*142c9f13Sbala#if defined(lint)
660*142c9f13Sbala/*ARGSUSED*/
661*142c9f13Sbalavoid
662*142c9f13Sbalaget_l2_tag_tl1(uint64_t tag_addr, uint64_t tag_data_ptr)
663*142c9f13Sbala{ }
664*142c9f13Sbala
665*142c9f13Sbala#else
666*142c9f13Sbala	ENTRY(get_l2_tag_tl1)
667*142c9f13Sbala
668*142c9f13Sbala	/*
669*142c9f13Sbala	 * Now read the tag data
670*142c9f13Sbala	 */
671*142c9f13Sbala	ldxa	[%g1]ASI_L2_TAG, %g4		! save tag_data
672*142c9f13Sbala	stx	%g4, [%g2]
673*142c9f13Sbala
674*142c9f13Sbala	retry
675*142c9f13Sbala	SET_SIZE(get_l2_tag_tl1)
676*142c9f13Sbala
677*142c9f13Sbala#endif	/* lint */
678*142c9f13Sbala
679*142c9f13Sbala#if defined(lint)
680*142c9f13Sbala/*ARGSUSED*/
681*142c9f13Sbalavoid
682*142c9f13Sbalaget_l3_tag_tl1(uint64_t tag_addr, uint64_t tag_data_ptr)
683*142c9f13Sbala{ }
684*142c9f13Sbala
685*142c9f13Sbala#else
686*142c9f13Sbala	ENTRY(get_l3_tag_tl1)
687*142c9f13Sbala
688*142c9f13Sbala	/*
689*142c9f13Sbala	 * Now read the tag data
690*142c9f13Sbala	 */
691*142c9f13Sbala	ldxa	[%g1]ASI_EC_DIAG, %g4		! save tag_data
692*142c9f13Sbala	stx	%g4, [%g2]
693*142c9f13Sbala
694*142c9f13Sbala	retry
695*142c9f13Sbala	SET_SIZE(get_l3_tag_tl1)
696*142c9f13Sbala
697*142c9f13Sbala#endif	/* lint */
698*142c9f13Sbala
699