xref: /illumos-gate/usr/src/uts/sun4u/io/panther_asm.S (revision 55fea89d)
1142c9f13Sbala/*
2142c9f13Sbala * CDDL HEADER START
3142c9f13Sbala *
4142c9f13Sbala * The contents of this file are subject to the terms of the
5142c9f13Sbala * Common Development and Distribution License (the "License").
6142c9f13Sbala * You may not use this file except in compliance with the License.
7142c9f13Sbala *
8142c9f13Sbala * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9142c9f13Sbala * or http://www.opensolaris.org/os/licensing.
10142c9f13Sbala * See the License for the specific language governing permissions
11142c9f13Sbala * and limitations under the License.
12142c9f13Sbala *
13142c9f13Sbala * When distributing Covered Code, include this CDDL HEADER in each
14142c9f13Sbala * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15142c9f13Sbala * If applicable, add the following below this CDDL HEADER, with the
16142c9f13Sbala * fields enclosed by brackets "[]" replaced with your own identifying
17142c9f13Sbala * information: Portions Copyright [yyyy] [name of copyright owner]
18142c9f13Sbala *
19142c9f13Sbala * CDDL HEADER END
20142c9f13Sbala */
21142c9f13Sbala/*
22142c9f13Sbala * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23142c9f13Sbala * Use is subject to license terms.
24142c9f13Sbala *
25142c9f13Sbala * Assembly code support for the Cheetah+ module
26142c9f13Sbala */
27142c9f13Sbala
28142c9f13Sbala#include "assym.h"
29142c9f13Sbala
30142c9f13Sbala#include <sys/asm_linkage.h>
31142c9f13Sbala#include <sys/mmu.h>
32142c9f13Sbala#include <vm/hat_sfmmu.h>
33142c9f13Sbala#include <sys/machparam.h>
34142c9f13Sbala#include <sys/machcpuvar.h>
35142c9f13Sbala#include <sys/machthread.h>
36142c9f13Sbala#include <sys/machtrap.h>
37142c9f13Sbala#include <sys/privregs.h>
38142c9f13Sbala#include <sys/asm_linkage.h>
39142c9f13Sbala#include <sys/trap.h>
40142c9f13Sbala#include <sys/cheetahregs.h>
41142c9f13Sbala#include <sys/xc_impl.h>
42142c9f13Sbala#include <sys/intreg.h>
43142c9f13Sbala#include <sys/async.h>
44142c9f13Sbala#include <sys/clock.h>
45142c9f13Sbala#include <sys/cheetahasm.h>
46142c9f13Sbala#include <sys/cmpregs.h>
47142c9f13Sbala
48142c9f13Sbala#ifdef TRAPTRACE
49142c9f13Sbala#include <sys/traptrace.h>
50142c9f13Sbala#endif /* TRAPTRACE */
51142c9f13Sbala
52142c9f13Sbala
53142c9f13Sbala	.global retire_l2_start
54142c9f13Sbala	.global retire_l2_end
55142c9f13Sbala	.global unretire_l2_start
56142c9f13Sbala	.global unretire_l2_end
57142c9f13Sbala	.global retire_l3_start
58142c9f13Sbala	.global retire_l3_end
59142c9f13Sbala	.global unretire_l3_start
60142c9f13Sbala	.global unretire_l3_end
61142c9f13Sbala
62142c9f13Sbala/*
63142c9f13Sbala * Panther version to reflush a line from both the L2 cache and L3
64142c9f13Sbala * cache by the respective indexes. Flushes all ways of the line from
65142c9f13Sbala * each cache.
66142c9f13Sbala *
67142c9f13Sbala * l2_index	Index into the L2$ of the line to be flushed. This
68142c9f13Sbala *		register will not be modified by this routine.
69142c9f13Sbala * l3_index	Index into the L3$ of the line to be flushed. This
70142c9f13Sbala *		register will not be modified by this routine.
71142c9f13Sbala * scr2		scratch register.
72142c9f13Sbala * scr3		scratch register.
73142c9f13Sbala *
74142c9f13Sbala */
75142c9f13Sbala#define	PN_ECACHE_REFLUSH_LINE(l2_index, l3_index, scr2, scr3)		\
76142c9f13Sbala	set	PN_L2_MAX_SET, scr2;					\
77142c9f13Sbala	set	PN_L2_SET_SIZE, scr3;					\
78142c9f13Sbala1:									\
79142c9f13Sbala	ldxa	[l2_index + scr2]ASI_L2_TAG, %g0;			\
80142c9f13Sbala	cmp	scr2, %g0;						\
81142c9f13Sbala	bg,a	1b;							\
82142c9f13Sbala	  sub	scr2, scr3, scr2;					\
83142c9f13Sbala	mov	6, scr2;						\
84142c9f13Sbala6:									\
85142c9f13Sbala	cmp	scr2, %g0;						\
86142c9f13Sbala	bg,a	6b;							\
87142c9f13Sbala	  sub	scr2, 1, scr2;						\
88142c9f13Sbala	set	PN_L3_MAX_SET, scr2;					\
89142c9f13Sbala	set	PN_L3_SET_SIZE, scr3;					\
90142c9f13Sbala2:									\
91142c9f13Sbala	ldxa	[l3_index + scr2]ASI_EC_DIAG, %g0;			\
92142c9f13Sbala	cmp	scr2, %g0;						\
93142c9f13Sbala	bg,a	2b;							\
94142c9f13Sbala	  sub	scr2, scr3, scr2;
95142c9f13Sbala
96142c9f13Sbala/*
97142c9f13Sbala * Panther version of ecache_flush_line. Flushes the line corresponding
98142c9f13Sbala * to physaddr from both the L2 cache and the L3 cache.
99142c9f13Sbala *
100142c9f13Sbala * physaddr	Input: Physical address to flush.
101142c9f13Sbala *              Output: Physical address to flush (preserved).
102142c9f13Sbala * l2_idx_out	Input: scratch register.
103142c9f13Sbala *              Output: Index into the L2$ of the line to be flushed.
104142c9f13Sbala * l3_idx_out	Input: scratch register.
105142c9f13Sbala *              Output: Index into the L3$ of the line to be flushed.
106142c9f13Sbala * scr3		scratch register.
107142c9f13Sbala * scr4		scratch register.
108142c9f13Sbala *
109142c9f13Sbala */
110142c9f13Sbala#define	PN_ECACHE_FLUSH_LINE(physaddr, l2_idx_out, l3_idx_out, scr3, scr4)	\
111142c9f13Sbala	set	PN_L3_SET_SIZE, l2_idx_out;					\
112142c9f13Sbala	sub	l2_idx_out, 1, l2_idx_out;					\
113142c9f13Sbala	and	physaddr, l2_idx_out, l3_idx_out;				\
114142c9f13Sbala	set	PN_L3_IDX_DISP_FLUSH, l2_idx_out;				\
115142c9f13Sbala	or	l2_idx_out, l3_idx_out, l3_idx_out;				\
116142c9f13Sbala	set	PN_L2_SET_SIZE, l2_idx_out;					\
117142c9f13Sbala	sub	l2_idx_out, 1, l2_idx_out;					\
118142c9f13Sbala	and	physaddr, l2_idx_out, l2_idx_out;				\
119142c9f13Sbala	set	PN_L2_IDX_DISP_FLUSH, scr3;					\
120142c9f13Sbala	or	l2_idx_out, scr3, l2_idx_out;					\
121142c9f13Sbala	PN_ECACHE_REFLUSH_LINE(l2_idx_out, l3_idx_out, scr3, scr4)
122142c9f13Sbala
123142c9f13Sbala
124142c9f13Sbala	.align 4096
125142c9f13Sbala	ENTRY(retire_l2)
126142c9f13Sbalaretire_l2_start:
127142c9f13Sbala
128142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
129142c9f13Sbala	rdpr	%pstate, %o2
130142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
131142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
132142c9f13Sbala	/*
133142c9f13Sbala	 * Save current DCU state.  Turn off IPS
134142c9f13Sbala	 */
135142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
136142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
137142c9f13Sbala	andn	%g1, %o3, %g4
138142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
139142c9f13Sbala	flush	%g0
140142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
141142c9f13Sbala	clr	%o5	! assume success
142142c9f13Sbala8:
143142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %g2, %g3)
144142c9f13Sbala1:
145142c9f13Sbala	! Check if line is invalid; if so, NA it.
146142c9f13Sbala	ldxa	[%o0]ASI_L2_TAG, %o3
147142c9f13Sbala	btst	0x7, %o3
148142c9f13Sbala	bnz	%xcc, 2f
149142c9f13Sbala	 nop
150142c9f13Sbala	stxa	%o1, [%o0]ASI_L2_TAG
151*55fea89dSDan Cross	membar #Sync	! still on same cache line
152142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
153142c9f13Sbala	mov	16, %o1
154142c9f13Sbala1:
155142c9f13Sbala	brnz,pt	%o1, 1b
156142c9f13Sbala	 dec	%o1
157142c9f13Sbala9:
158142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary
159142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
160142c9f13Sbala	/*
161142c9f13Sbala	 * Restore the DCU
162142c9f13Sbala	 */
163142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
164142c9f13Sbala	flush	%g0
165142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
166142c9f13Sbala	retl
167142c9f13Sbala	 mov	%o5, %o0
168142c9f13Sbala2:
169142c9f13Sbala	! It is OK to have STATE as NA (if so, nothing to do!)
170142c9f13Sbala	and	%o3, 0x7, %o3
171142c9f13Sbala	cmp	%o3, 0x5
172142c9f13Sbala	be,a,pt	%xcc, 9b
173142c9f13Sbala	 mov	1, %o5	! indicate was already NA
174142c9f13Sbala	! Hmm.	Not INV, not NA.
175142c9f13Sbala	cmp	%o5, 0
176142c9f13Sbala	be,a,pt	%xcc, 8b	! Flush the cacheline again
177142c9f13Sbala	 mov	2, %o5	! indicate retry was done
178142c9f13Sbala	! We already Flushed cacheline second time. Return -1
179142c9f13Sbala	clr	%o5
180142c9f13Sbala	ba	9b
181142c9f13Sbala	 dec	%o5
182142c9f13Sbalaretire_l2_end:
183142c9f13Sbala	SET_SIZE(retire_l2)
184142c9f13Sbala
185142c9f13Sbala	ENTRY(unretire_l2)
186142c9f13Sbalaunretire_l2_start:
187142c9f13Sbala
188142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
189142c9f13Sbala	rdpr	%pstate, %o2
190142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
191142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
192142c9f13Sbala	/*
193142c9f13Sbala	 * Save current DCU state.  Turn off IPS
194142c9f13Sbala	 */
195142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
196142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
197142c9f13Sbala	andn	%g1, %o3, %g4
198142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
199142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
200142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
201142c9f13Sbala
202142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
203142c9f13Sbala1:
204142c9f13Sbala	clr	%o5	! assume success
205142c9f13Sbala	! Check that line is in NA state; if so, INV it.
206142c9f13Sbala	ldxa	[%o0]ASI_L2_TAG, %o3
207142c9f13Sbala	and	%o3, 0x7, %o3
208142c9f13Sbala	cmp	%o3, 0x5
209142c9f13Sbala	bne,a,pt %xcc, 9f	! Wasn't NA, so something is wrong
210142c9f13Sbala	 dec	%o5	! indicate not NA
211142c9f13Sbala	stxa	%g0, [%o0]ASI_L2_TAG
212142c9f13Sbala	membar #Sync
213142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
214142c9f13Sbala	mov	16, %o1
215142c9f13Sbala1:
216142c9f13Sbala	brnz,pt	%o1, 1b
217142c9f13Sbala	 dec	%o1
218142c9f13Sbala9:
219142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions
220142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
221142c9f13Sbala	/*
222142c9f13Sbala	 * Restore the DCU
223142c9f13Sbala	 */
224142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
225142c9f13Sbala	flush	%g0
226142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
227142c9f13Sbala	retl
228142c9f13Sbala	 mov	%o5, %o0
229142c9f13Sbalaunretire_l2_end:
230142c9f13Sbala	SET_SIZE(unretire_l2)
231142c9f13Sbala
232142c9f13Sbala	ENTRY(retire_l3)
233142c9f13Sbalaretire_l3_start:
234142c9f13Sbala
235142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
236142c9f13Sbala	rdpr	%pstate, %o2
237142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
238142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
239142c9f13Sbala	/*
240142c9f13Sbala	 * Save current DCU state.  Turn off IPS
241142c9f13Sbala	 */
242142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
243142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
244142c9f13Sbala	andn	%g1, %o3, %g4
245142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
246142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
247142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
248142c9f13Sbala
249142c9f13Sbala	! PN-ECACHE-FLUSH_LINE is 30 instructions
250142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
251142c9f13Sbala1:
252142c9f13Sbala	clr	%o5	! assume success
253142c9f13Sbala	! Check if line is invalid; if so, NA it.
254142c9f13Sbala	ldxa	[%o0]ASI_EC_DIAG, %o3
255142c9f13Sbala	btst	0x7, %o3
256142c9f13Sbala	bnz	%xcc, 2f
257142c9f13Sbala	 nop
258142c9f13Sbala	stxa	%o1, [%o0]ASI_EC_DIAG
259*55fea89dSDan Cross	membar #Sync	! still on same cache line
260142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
261142c9f13Sbala	mov	16, %o1
262142c9f13Sbala1:
263142c9f13Sbala	brnz,pt	%o1, 1b
264142c9f13Sbala	 dec	%o1
265142c9f13Sbala9:
266142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary
267142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
268142c9f13Sbala	/*
269142c9f13Sbala	 * Restore the DCU
270142c9f13Sbala	 */
271142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
272142c9f13Sbala	flush	%g0
273142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
274142c9f13Sbala	retl
275142c9f13Sbala	 mov	%o5, %o0
276142c9f13Sbala2:
277142c9f13Sbala	! It is OK to have STATE as NA (if so, nothing to do!)
278142c9f13Sbala	and	%o3, 0x7, %o3
279142c9f13Sbala	cmp	%o3, 0x5
280142c9f13Sbala	be,a,pt	%xcc, 9b
281142c9f13Sbala	 inc	%o5	! indicate was already NA
282142c9f13Sbala	! Hmm.	Not INV, not NA
283142c9f13Sbala	ba	9b
284142c9f13Sbala	 dec	%o5
285142c9f13Sbalaretire_l3_end:
286142c9f13Sbala	SET_SIZE(retire_l3)
287142c9f13Sbala
288142c9f13Sbala	ENTRY(unretire_l3)
289142c9f13Sbalaunretire_l3_start:
290142c9f13Sbala
291142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
292142c9f13Sbala	rdpr	%pstate, %o2
293142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
294142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
295142c9f13Sbala	/*
296142c9f13Sbala	 * Save current DCU state.  Turn off IPS
297142c9f13Sbala	 */
298142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
299142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
300142c9f13Sbala	andn	%g1, %o3, %g4
301142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
302142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
303142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
304142c9f13Sbala
305142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
306142c9f13Sbala1:
307142c9f13Sbala	clr	%o5	! assume success
308142c9f13Sbala	! Check that line is in NA state; if so, INV it.
309142c9f13Sbala	ldxa	[%o0]ASI_EC_DIAG, %o3
310142c9f13Sbala	and	%o3, 0x7, %o3
311142c9f13Sbala	cmp	%o3, 0x5
312142c9f13Sbala	bne,a,pt %xcc, 9f	! Wasn't NA, so something is wrong
313142c9f13Sbala	 dec	%o5	! indicate not NA
314142c9f13Sbala	stxa	%g0, [%o0]ASI_EC_DIAG
315142c9f13Sbala	membar #Sync
316142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
317142c9f13Sbala	mov	16, %o1
318142c9f13Sbala1:
319142c9f13Sbala	brnz,pt	%o1, 1b
320142c9f13Sbala	 dec	%o1
321142c9f13Sbala9:
322142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions
323142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
324142c9f13Sbala	/*
325142c9f13Sbala	 * Restore the DCU
326142c9f13Sbala	 */
327142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
328142c9f13Sbala	flush	%g0
329142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
330142c9f13Sbala	retl
331142c9f13Sbala	 mov	%o5, %o0
332142c9f13Sbalaunretire_l3_end:
333142c9f13Sbala	SET_SIZE(unretire_l3)
334142c9f13Sbala
335142c9f13Sbala	.align 2048
336142c9f13Sbala
337142c9f13Sbala	ENTRY(retire_l2_alternate)
338142c9f13Sbala
339142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
340142c9f13Sbala	rdpr	%pstate, %o2
341142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
342142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
343142c9f13Sbala	/*
344142c9f13Sbala	 * Save current DCU state.  Turn off IPS
345142c9f13Sbala	 */
346142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
347142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
348142c9f13Sbala	andn	%g1, %o3, %g4
349142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
350142c9f13Sbala	flush	%g0
351142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
352142c9f13Sbala	clr	%o5	! assume success
353142c9f13Sbala8:
354142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %g2, %g3)
355142c9f13Sbala1:
356142c9f13Sbala	! Check if line is invalid; if so, NA it.
357142c9f13Sbala	ldxa	[%o0]ASI_L2_TAG, %o3
358142c9f13Sbala	btst	0x7, %o3
359142c9f13Sbala	bnz	%xcc, 2f
360142c9f13Sbala	 nop
361142c9f13Sbala	stxa	%o1, [%o0]ASI_L2_TAG
362*55fea89dSDan Cross	membar #Sync	! still on same cache line
363142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
364142c9f13Sbala	mov	16, %o1
365142c9f13Sbala1:
366142c9f13Sbala	brnz,pt	%o1, 1b
367142c9f13Sbala	 dec	%o1
368142c9f13Sbala9:
369142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary
370142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
371142c9f13Sbala	/*
372142c9f13Sbala	 * Restore the DCU
373142c9f13Sbala	 */
374142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
375142c9f13Sbala	flush	%g0
376142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
377142c9f13Sbala	retl
378142c9f13Sbala	 mov	%o5, %o0
379142c9f13Sbala2:
380142c9f13Sbala	! It is OK to have STATE as NA (if so, nothing to do!)
381142c9f13Sbala	and	%o3, 0x7, %o3
382142c9f13Sbala	cmp	%o3, 0x5
383142c9f13Sbala	be,a,pt	%xcc, 9b
384142c9f13Sbala	 mov	1, %o5	! indicate was already NA
385142c9f13Sbala	! Hmm.	Not INV, not NA.
386142c9f13Sbala	cmp	%o5, 0
387142c9f13Sbala	be,a,pt	%xcc, 8b	! Flush the cacheline again
388142c9f13Sbala	 mov	2, %o5	! indicate retry was done
389142c9f13Sbala	! We already Flushed cacheline second time. Return -1
390142c9f13Sbala	clr	%o5
391142c9f13Sbala	ba	9b
392142c9f13Sbala	 dec	%o5
393142c9f13Sbala	SET_SIZE(retire_l2_alternate)
394142c9f13Sbala
395142c9f13Sbala	ENTRY(unretire_l2_alternate)
396142c9f13Sbala
397142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
398142c9f13Sbala	rdpr	%pstate, %o2
399142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
400142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
401142c9f13Sbala	/*
402142c9f13Sbala	 * Save current DCU state.  Turn off IPS
403142c9f13Sbala	 */
404142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
405142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
406142c9f13Sbala	andn	%g1, %o3, %g4
407142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
408142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
409142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
410142c9f13Sbala
411142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
412142c9f13Sbala1:
413142c9f13Sbala	clr	%o5	! assume success
414142c9f13Sbala	! Check that line is in NA state; if so, INV it.
415142c9f13Sbala	ldxa	[%o0]ASI_L2_TAG, %o3
416142c9f13Sbala	and	%o3, 0x7, %o3
417142c9f13Sbala	cmp	%o3, 0x5
418142c9f13Sbala	bne,a,pt %xcc, 9f	! Wasn't NA, so something is wrong
419142c9f13Sbala	 dec	%o5	! indicate not NA
420142c9f13Sbala	stxa	%g0, [%o0]ASI_L2_TAG
421142c9f13Sbala	membar #Sync
422142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
423142c9f13Sbala	mov	16, %o1
424142c9f13Sbala1:
425142c9f13Sbala	brnz,pt	%o1, 1b
426142c9f13Sbala	 dec	%o1
427142c9f13Sbala9:
428142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions
429142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
430142c9f13Sbala	/*
431142c9f13Sbala	 * Restore the DCU
432142c9f13Sbala	 */
433142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
434142c9f13Sbala	flush	%g0
435142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
436142c9f13Sbala	retl
437142c9f13Sbala	 mov	%o5, %o0
438142c9f13Sbala	SET_SIZE(unretire_l2_alternate)
439142c9f13Sbala
440142c9f13Sbala	ENTRY(retire_l3_alternate)
441142c9f13Sbala
442142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
443142c9f13Sbala	rdpr	%pstate, %o2
444142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
445142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
446142c9f13Sbala	/*
447142c9f13Sbala	 * Save current DCU state.  Turn off IPS
448142c9f13Sbala	 */
449142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
450142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
451142c9f13Sbala	andn	%g1, %o3, %g4
452142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
453142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
454142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
455142c9f13Sbala
456142c9f13Sbala	! PN-ECACHE-FLUSH_LINE is 30 instructions
457142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
458142c9f13Sbala1:
459142c9f13Sbala	clr	%o5	! assume success
460142c9f13Sbala	! Check if line is invalid; if so, NA it.
461142c9f13Sbala	ldxa	[%o0]ASI_EC_DIAG, %o3
462142c9f13Sbala	btst	0x7, %o3
463142c9f13Sbala	bnz	%xcc, 2f
464142c9f13Sbala	 nop
465142c9f13Sbala	stxa	%o1, [%o0]ASI_EC_DIAG
466*55fea89dSDan Cross	membar #Sync	! still on same cache line
467142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
468142c9f13Sbala	mov	16, %o1
469142c9f13Sbala1:
470142c9f13Sbala	brnz,pt	%o1, 1b
471142c9f13Sbala	 dec	%o1
472142c9f13Sbala9:
473142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary
474142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
475142c9f13Sbala	/*
476142c9f13Sbala	 * Restore the DCU
477142c9f13Sbala	 */
478142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
479142c9f13Sbala	flush	%g0
480142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
481142c9f13Sbala	retl
482142c9f13Sbala	 mov	%o5, %o0
483142c9f13Sbala2:
484142c9f13Sbala	! It is OK to have STATE as NA (if so, nothing to do!)
485142c9f13Sbala	and	%o3, 0x7, %o3
486142c9f13Sbala	cmp	%o3, 0x5
487142c9f13Sbala	be,a,pt	%xcc, 9b
488142c9f13Sbala	 inc	%o5	! indicate was already NA
489142c9f13Sbala	! Hmm.	Not INV, not NA
490142c9f13Sbala	ba	9b
491142c9f13Sbala	 dec	%o5
492142c9f13Sbala	SET_SIZE(retire_l3_alternate)
493142c9f13Sbala
494142c9f13Sbala	ENTRY(unretire_l3_alternate)
495142c9f13Sbala
496142c9f13Sbala	! since we disable interrupts, we don't need to do kpreempt_disable()
497142c9f13Sbala	rdpr	%pstate, %o2
498142c9f13Sbala	andn	%o2, PSTATE_IE, %g1
499142c9f13Sbala	wrpr	%g0, %g1, %pstate		! disable interrupts
500142c9f13Sbala	/*
501142c9f13Sbala	 * Save current DCU state.  Turn off IPS
502142c9f13Sbala	 */
503142c9f13Sbala	setx	DCU_IPS_MASK, %g2, %o3
504142c9f13Sbala	ldxa	[%g0]ASI_DCU, %g1	! save DCU in %g1
505142c9f13Sbala	andn	%g1, %o3, %g4
506142c9f13Sbala	stxa	%g4, [%g0]ASI_DCU
507142c9f13Sbala	flush	%g0	/* flush required after changing the IC bit */
508142c9f13Sbala	PARK_SIBLING_CORE(%g1, %o3, %o4)	! %g1 has DCU value
509142c9f13Sbala
510142c9f13Sbala	PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2)
511142c9f13Sbala1:
512142c9f13Sbala	clr	%o5	! assume success
513142c9f13Sbala	! Check that line is in NA state; if so, INV it.
514142c9f13Sbala	ldxa	[%o0]ASI_EC_DIAG, %o3
515142c9f13Sbala	and	%o3, 0x7, %o3
516142c9f13Sbala	cmp	%o3, 0x5
517142c9f13Sbala	bne,a,pt %xcc, 9f	! Wasn't NA, so something is wrong
518142c9f13Sbala	 dec	%o5	! indicate not NA
519142c9f13Sbala	stxa	%g0, [%o0]ASI_EC_DIAG
520142c9f13Sbala	membar #Sync
521142c9f13Sbala	! now delay 15 cycles so we don't have hazard when we return
522142c9f13Sbala	mov	16, %o1
523142c9f13Sbala1:
524142c9f13Sbala	brnz,pt	%o1, 1b
525142c9f13Sbala	 dec	%o1
526142c9f13Sbala9:
527142c9f13Sbala	! UNPARK-SIBLING_CORE is 7 instructions
528142c9f13Sbala	UNPARK_SIBLING_CORE(%g1, %o3, %o4)	! 7 instructions
529142c9f13Sbala	/*
530142c9f13Sbala	 * Restore the DCU
531142c9f13Sbala	 */
532142c9f13Sbala	stxa	%g1, [%g0]ASI_DCU
533142c9f13Sbala	flush	%g0
534142c9f13Sbala	wrpr	%g0, %o2, %pstate		!restore pstate
535142c9f13Sbala	retl
536142c9f13Sbala	 mov	%o5, %o0
537142c9f13Sbala	SET_SIZE(unretire_l3_alternate)
538142c9f13Sbala
539142c9f13Sbala	ENTRY(get_ecache_dtags_tl1)
540142c9f13Sbala
541142c9f13Sbala
542*55fea89dSDan Cross	PARK_SIBLING_CORE(%g3, %g4, %g5)
543142c9f13Sbala	add	%g2, CH_CLO_DATA + CH_CHD_EC_DATA, %g2
544142c9f13Sbala	rd	%asi, %g4
545142c9f13Sbala	wr	%g0, ASI_N, %asi
546142c9f13Sbala	GET_ECACHE_DTAGS(%g1, %g2, %g5, %g6, %g7)
547142c9f13Sbala	wr	%g4, %asi
548142c9f13Sbala	UNPARK_SIBLING_CORE(%g3, %g4, %g5)	! can use %g3 again
549142c9f13Sbala
550142c9f13Sbala	retry
551142c9f13Sbala	SET_SIZE(get_ecache_dtags_tl1)
552142c9f13Sbala
553142c9f13Sbala	ENTRY(get_l2_tag_tl1)
554142c9f13Sbala
555142c9f13Sbala	/*
556142c9f13Sbala	 * Now read the tag data
557142c9f13Sbala	 */
558142c9f13Sbala	ldxa	[%g1]ASI_L2_TAG, %g4		! save tag_data
559142c9f13Sbala	stx	%g4, [%g2]
560142c9f13Sbala
561142c9f13Sbala	retry
562142c9f13Sbala	SET_SIZE(get_l2_tag_tl1)
563142c9f13Sbala
564142c9f13Sbala	ENTRY(get_l3_tag_tl1)
565142c9f13Sbala
566142c9f13Sbala	/*
567142c9f13Sbala	 * Now read the tag data
568142c9f13Sbala	 */
569142c9f13Sbala	ldxa	[%g1]ASI_EC_DIAG, %g4		! save tag_data
570142c9f13Sbala	stx	%g4, [%g2]
571142c9f13Sbala
572142c9f13Sbala	retry
573142c9f13Sbala	SET_SIZE(get_l3_tag_tl1)
574142c9f13Sbala
575