xref: /titanic_50/usr/src/uts/sun4u/serengeti/ml/sbdp_asm.s (revision 03831d35f7499c87d51205817c93e9a8d42c4bae)
1*03831d35Sstevel/*
2*03831d35Sstevel * CDDL HEADER START
3*03831d35Sstevel *
4*03831d35Sstevel * The contents of this file are subject to the terms of the
5*03831d35Sstevel * Common Development and Distribution License (the "License").
6*03831d35Sstevel * You may not use this file except in compliance with the License.
7*03831d35Sstevel *
8*03831d35Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*03831d35Sstevel * or http://www.opensolaris.org/os/licensing.
10*03831d35Sstevel * See the License for the specific language governing permissions
11*03831d35Sstevel * and limitations under the License.
12*03831d35Sstevel *
13*03831d35Sstevel * When distributing Covered Code, include this CDDL HEADER in each
14*03831d35Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*03831d35Sstevel * If applicable, add the following below this CDDL HEADER, with the
16*03831d35Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
17*03831d35Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
18*03831d35Sstevel *
19*03831d35Sstevel * CDDL HEADER END
20*03831d35Sstevel */
21*03831d35Sstevel
22*03831d35Sstevel/*
23*03831d35Sstevel * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*03831d35Sstevel * Use is subject to license terms.
25*03831d35Sstevel */
26*03831d35Sstevel
27*03831d35Sstevel#pragma ident	"%Z%%M%	%I%	%E% SMI"
28*03831d35Sstevel
29*03831d35Sstevel/*
30*03831d35Sstevel * This file is through cpp before being used as
31*03831d35Sstevel * an inline.  It contains support routines used
32*03831d35Sstevel * only by DR for the copy-rename sequence.
33*03831d35Sstevel */
34*03831d35Sstevel
35*03831d35Sstevel#if defined(lint)
36*03831d35Sstevel#include <sys/types.h>
37*03831d35Sstevel#include <sys/sbd_ioctl.h>
38*03831d35Sstevel#include <sys/sbdp_priv.h>
39*03831d35Sstevel#else
40*03831d35Sstevel#include "assym.h"
41*03831d35Sstevel#endif /* lint */
42*03831d35Sstevel
43*03831d35Sstevel#include <sys/asm_linkage.h>
44*03831d35Sstevel#include <sys/param.h>
45*03831d35Sstevel#include <sys/privregs.h>
46*03831d35Sstevel#include <sys/machasi.h>
47*03831d35Sstevel#include <sys/mmu.h>
48*03831d35Sstevel#include <sys/machthread.h>
49*03831d35Sstevel#include <sys/pte.h>
50*03831d35Sstevel#include <sys/stack.h>
51*03831d35Sstevel#include <sys/vis.h>
52*03831d35Sstevel#include <sys/param.h>
53*03831d35Sstevel#include <sys/errno.h>
54*03831d35Sstevel#include <sys/vtrace.h>
55*03831d35Sstevel#include <sys/clock.h>
56*03831d35Sstevel#include <sys/asi.h>
57*03831d35Sstevel#include <sys/fsr.h>
58*03831d35Sstevel#include <sys/cheetahregs.h>
59*03831d35Sstevel#include <sys/cheetahasm.h>
60*03831d35Sstevel
61*03831d35Sstevel#ifndef lint
62*03831d35Sstevel
63*03831d35Sstevel/*
64*03831d35Sstevel * Invalidating the E$ tags is only needed on Cheetah following
65*03831d35Sstevel * the manual displacement flush.  The internal flush ASI used by
66*03831d35Sstevel * Cheetahplus, Jaguar, and Panther will invalidate the cache lines.
67*03831d35Sstevel *
68*03831d35Sstevel * arg1 = ecache_size
69*03831d35Sstevel * arg2 = ecache_linesize
70*03831d35Sstevel */
71*03831d35Sstevel#define ECACHE_FLUSHTAGS(arg1, arg2, tmp1)			\
72*03831d35Sstevel	GET_CPU_IMPL(tmp1)					;\
73*03831d35Sstevel	srlx	arg1, 1, arg1					;\
74*03831d35Sstevel	cmp	tmp1, CHEETAH_IMPL				;\
75*03831d35Sstevel        bne	1f						;\
76*03831d35Sstevel	nop							;\
77*03831d35Sstevel	sub	arg1, arg2, tmp1				;\
78*03831d35Sstevel0:								;\
79*03831d35Sstevel        stxa    %g0, [tmp1]ASI_EC_DIAG				;\
80*03831d35Sstevel        membar  #Sync						;\
81*03831d35Sstevel        cmp     %g0, tmp1					;\
82*03831d35Sstevel        bne,pt  %icc, 0b					;\
83*03831d35Sstevel        sub     tmp1, arg2, tmp1				;\
84*03831d35Sstevel1:
85*03831d35Sstevel
86*03831d35Sstevel
87*03831d35Sstevel#define SWITCH_STACK(estk)                                      \
88*03831d35Sstevel        flushw                                                  ;\
89*03831d35Sstevel        sub     estk, SA(KFPUSIZE+GSR_SIZE), estk              ;\
90*03831d35Sstevel        andn    estk, 0x3f, estk                                ;\
91*03831d35Sstevel        sub     estk, SA(MINFRAME) + STACK_BIAS, %sp            ;\
92*03831d35Sstevel        mov     estk, %fp
93*03831d35Sstevel
94*03831d35Sstevel/*
95*03831d35Sstevel * Returns icache size and linesize in reg1 and reg2, respectively.
96*03831d35Sstevel * Panther has a larger icache compared to Cheetahplus and Jaguar.
97*03831d35Sstevel */
98*03831d35Sstevel#define	GET_ICACHE_PARAMS(reg1, reg2)				\
99*03831d35Sstevel	GET_CPU_IMPL(reg1)					;\
100*03831d35Sstevel	cmp	reg1, PANTHER_IMPL				;\
101*03831d35Sstevel	bne	%xcc, 1f					;\
102*03831d35Sstevel	  nop							;\
103*03831d35Sstevel	set	PN_ICACHE_SIZE, reg1				;\
104*03831d35Sstevel	set	PN_ICACHE_LSIZE, reg2				;\
105*03831d35Sstevel	ba	2f						;\
106*03831d35Sstevel	  nop							;\
107*03831d35Sstevel1:								;\
108*03831d35Sstevel	set	CH_ICACHE_SIZE, reg1				;\
109*03831d35Sstevel	set	CH_ICACHE_LSIZE, reg2				;\
110*03831d35Sstevel2:
111*03831d35Sstevel
112*03831d35Sstevel#endif  /* !lint */
113*03831d35Sstevel
114*03831d35Sstevel#if defined(lint)
115*03831d35Sstevel
116*03831d35Sstevel/*ARGSUSED*/
117*03831d35Sstevelvoid
118*03831d35Sstevelsbdp_shutdown_asm(sbdp_shutdown_t *shutshown)
119*03831d35Sstevel{}
120*03831d35Sstevel
121*03831d35Sstevel#else /* lint */
122*03831d35Sstevel
123*03831d35Sstevel        ENTRY_NP(sbdp_shutdown_asm)
124*03831d35Sstevel        ! %o0 = address of sbdp_shutdown_t structure passed in
125*03831d35Sstevel        !
126*03831d35Sstevel        ! struct sbdp_shutdown {
127*03831d35Sstevel        !       uint64_t        estack;    -> %o0
128*03831d35Sstevel        !       uint64_t        flushaddr; -> %o1
129*03831d35Sstevel        !       uint32_t        size;      -> %o2
130*03831d35Sstevel        !       uint32_t        linesize;  -> %g1
131*03831d35Sstevel        !       uint64_t        physaddr;  -> %o0
132*03831d35Sstevel        ! } sbdp_shutdown_t;
133*03831d35Sstevel        !
134*03831d35Sstevel        membar  #LoadStore
135*03831d35Sstevel        mov     %o0, %o4
136*03831d35Sstevel        ldx     [%o4], %o0
137*03831d35Sstevel        ldx     [%o4 + 8], %o1
138*03831d35Sstevel        ld      [%o4 + 16], %o2
139*03831d35Sstevel        ld      [%o4 + 20], %g1
140*03831d35Sstevel
141*03831d35Sstevel        !
142*03831d35Sstevel        ! Switch stack pointer to bbsram
143*03831d35Sstevel        !
144*03831d35Sstevel        SWITCH_STACK(%o0)
145*03831d35Sstevel
146*03831d35Sstevel        ldx     [%o4 + 24], %o0 !save physaddr in %o0
147*03831d35Sstevel        !
148*03831d35Sstevel        ! Get some globals
149*03831d35Sstevel        !
150*03831d35Sstevel	! ecache_linesize already in %g1
151*03831d35Sstevel
152*03831d35Sstevel        sethi   %hi(dcache_linesize), %g2
153*03831d35Sstevel        ld      [%g2 + %lo(dcache_linesize)], %g2
154*03831d35Sstevel
155*03831d35Sstevel        sethi   %hi(dcache_size), %g3
156*03831d35Sstevel        ld      [%g3 + %lo(dcache_size)], %g3
157*03831d35Sstevel
158*03831d35Sstevel	!
159*03831d35Sstevel	! Save the E$ size
160*03831d35Sstevel	!
161*03831d35Sstevel	mov	%o2, %o5
162*03831d35Sstevel        !
163*03831d35Sstevel        ! Flush E$
164*03831d35Sstevel        !
165*03831d35Sstevel        rdpr    %pstate, %o3
166*03831d35Sstevel        andn    %o3, PSTATE_IE | PSTATE_AM, %o4
167*03831d35Sstevel        wrpr    %g0, %o4, %pstate
168*03831d35Sstevel
169*03831d35Sstevel	! Panther needs to flush L2 before L3 cache.
170*03831d35Sstevel	PN_L2_FLUSHALL(%o4, %g4, %g5)
171*03831d35Sstevel
172*03831d35Sstevel        ECACHE_FLUSHALL(%o2, %g1, %o1, %o4)
173*03831d35Sstevel
174*03831d35Sstevel        wrpr    %g0, %o3, %pstate
175*03831d35Sstevel
176*03831d35Sstevel	!
177*03831d35Sstevel	! Invalidate the E$ tags (Cheetah only).
178*03831d35Sstevel	!
179*03831d35Sstevel	ECACHE_FLUSHTAGS(%o5, %g1, %o3)
180*03831d35Sstevel
181*03831d35Sstevel        !
182*03831d35Sstevel        ! %o2 & %o3 now available
183*03831d35Sstevel        !
184*03831d35Sstevel
185*03831d35Sstevel        membar  #Sync
186*03831d35Sstevel
187*03831d35Sstevel        !
188*03831d35Sstevel        ! Flush D$
189*03831d35Sstevel        !
190*03831d35Sstevel        CH_DCACHE_FLUSHALL(%g3, %g2, %o3)
191*03831d35Sstevel
192*03831d35Sstevel        !
193*03831d35Sstevel        ! Flush I$
194*03831d35Sstevel        !
195*03831d35Sstevel	GET_ICACHE_PARAMS(%g5, %g4)
196*03831d35Sstevel        CH_ICACHE_FLUSHALL(%g5, %g4, %o3, %o4)
197*03831d35Sstevel
198*03831d35Sstevel        membar  #Sync
199*03831d35Sstevel
200*03831d35Sstevel        !
201*03831d35Sstevel        ! Flush all unlocked dtlb's & itlb's
202*03831d35Sstevel        !
203*03831d35Sstevel	sethi	%hi(FLUSH_ADDR), %g3
204*03831d35Sstevel	set	DEMAP_ALL_TYPE, %g1
205*03831d35Sstevel	stxa	%g0, [%g1]ASI_DTLB_DEMAP
206*03831d35Sstevel	stxa	%g0, [%g1]ASI_ITLB_DEMAP
207*03831d35Sstevel	flush	%g3
208*03831d35Sstevel
209*03831d35Sstevel	sir	0
210*03831d35Sstevel        SET_SIZE(sbdp_shutdown_asm)
211*03831d35Sstevel
212*03831d35Sstevel        .global sbdp_shutdown_asm_end
213*03831d35Sstevel
214*03831d35Sstevel        .skip   2048
215*03831d35Sstevel
216*03831d35Sstevelsbdp_shutdown_asm_end:
217*03831d35Sstevel
218*03831d35Sstevel#endif  /* lint */
219*03831d35Sstevel
220*03831d35Sstevel
221*03831d35Sstevel#if defined(lint)
222*03831d35Sstevel
223*03831d35Sstevel#else	/* lint */
224*03831d35Sstevel#include "assym.h"
225*03831d35Sstevel#endif	/* lint */
226*03831d35Sstevel
227*03831d35Sstevel#define	TT_HSM	0x99
228*03831d35Sstevel
229*03831d35Sstevel#if defined(lint)
230*03831d35Sstevel/* ARGSUSED */
231*03831d35Sstevelvoid
232*03831d35Sstevelsgdr_mem_blkcopy(caddr_t src, caddr_t dst, u_int linecount, u_int linesize)
233*03831d35Sstevel{}
234*03831d35Sstevel
235*03831d35Sstevelvoid
236*03831d35Sstevelstdmcdecode(uint64_t physaddr, uint64_t value)
237*03831d35Sstevel{
238*03831d35Sstevel	physaddr = physaddr;
239*03831d35Sstevel	value = value;
240*03831d35Sstevel}
241*03831d35Sstevel
242*03831d35Sstevel#else /* !lint */
243*03831d35Sstevel!
244*03831d35Sstevel! Move a single cache line of data.  Survive UE and CE on the read
245*03831d35Sstevel!
246*03831d35Sstevel! i0 = src va
247*03831d35Sstevel! i1 = dst va
248*03831d35Sstevel! i2 = line count
249*03831d35Sstevel! i3 = line size
250*03831d35Sstevel! i4 = cache of fpu state
251*03831d35Sstevel!
252*03831d35Sstevel	ENTRY(sgdr_mem_blkcopy)
253*03831d35Sstevel
254*03831d35Sstevel	! TODO: can we safely SAVE here
255*03831d35Sstevel	save	%sp, -SA(MINFRAME + 2*64), %sp
256*03831d35Sstevel
257*03831d35Sstevel	! XXX do we need to save the state of the fpu?
258*03831d35Sstevel	rd	%fprs, %i4
259*03831d35Sstevel	btst	(FPRS_DU|FPRS_DL|FPRS_FEF), %i4
260*03831d35Sstevel
261*03831d35Sstevel	! always enable FPU
262*03831d35Sstevel	wr	%g0, FPRS_FEF, %fprs
263*03831d35Sstevel
264*03831d35Sstevel	bz,a	1f
265*03831d35Sstevel	 nop
266*03831d35Sstevel
267*03831d35Sstevel	! save in-use fpregs on stack
268*03831d35Sstevel	membar	#Sync
269*03831d35Sstevel	add	%fp, STACK_BIAS - 81, %o2
270*03831d35Sstevel	and	%o2, -64, %o2
271*03831d35Sstevel	stda	%d0, [%o2]ASI_BLK_P
272*03831d35Sstevel	membar	#Sync
273*03831d35Sstevel
274*03831d35Sstevel1:
275*03831d35Sstevel	brz,pn	%i2, 2f				! while (linecount) {
276*03831d35Sstevel	 nop
277*03831d35Sstevel	ldda	[%i0]ASI_BLK_P, %d0		! *dst = *src;
278*03831d35Sstevel	membar	#Sync
279*03831d35Sstevel	stda	%d0, [%i1]ASI_BLK_COMMIT_P
280*03831d35Sstevel	membar	#Sync
281*03831d35Sstevel
282*03831d35Sstevel	add	%i0, %i3, %i0			! dst++, src++;
283*03831d35Sstevel	add	%i1, %i3, %i1
284*03831d35Sstevel
285*03831d35Sstevel	ba	1b				! linecount-- }
286*03831d35Sstevel	 dec	%i2
287*03831d35Sstevel
288*03831d35Sstevel2:
289*03831d35Sstevel	membar	#Sync
290*03831d35Sstevel
291*03831d35Sstevel	! restore fp to the way we got it
292*03831d35Sstevel	btst	(FPRS_DU|FPRS_DL|FPRS_FEF), %i4
293*03831d35Sstevel	bz,a	3f
294*03831d35Sstevel	 nop
295*03831d35Sstevel
296*03831d35Sstevel	! restore fpregs from stack
297*03831d35Sstevel	add	%fp, STACK_BIAS - 81, %o2
298*03831d35Sstevel	and	%o2, -64, %o2
299*03831d35Sstevel	ldda	[%o2]ASI_BLK_P, %d0
300*03831d35Sstevel	membar	#Sync
301*03831d35Sstevel
302*03831d35Sstevel3:
303*03831d35Sstevel	wr	%g0, %i4, %fprs			! fpu back to the way it was
304*03831d35Sstevel	ret
305*03831d35Sstevel	restore
306*03831d35Sstevel	SET_SIZE(sgdr_mem_blkcopy)
307*03831d35Sstevel
308*03831d35Sstevel        ! Store long word value at mc regs
309*03831d35Sstevel        !
310*03831d35Sstevel        ! void  stdmcdecode(uint64_t physaddr, uint64_t value)
311*03831d35Sstevel        !
312*03831d35Sstevel        ENTRY(stdmcdecode)
313*03831d35Sstevel        /*
314*03831d35Sstevel         * disable interrupts, clear Address Mask to access 64 bit physaddr
315*03831d35Sstevel         */
316*03831d35Sstevel        rdpr    %pstate, %o4
317*03831d35Sstevel        andn    %o4, PSTATE_IE | PSTATE_AM, %o5
318*03831d35Sstevel        wrpr    %o5, 0, %pstate         ! clear IE, AM bits
319*03831d35Sstevel        stxa    %o1, [%o0]ASI_MC_DECODE
320*03831d35Sstevel	membar	#Sync
321*03831d35Sstevel        retl
322*03831d35Sstevel        wrpr    %g0, %o4, %pstate       ! restore earlier pstate register value
323*03831d35Sstevel        SET_SIZE(stdmcdecode)
324*03831d35Sstevel
325*03831d35Sstevel#endif /* lint */
326