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