1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * This file is through cpp before being used as
31 * an inline.  It contains support routines used
32 * only by DR for the copy-rename sequence.
33 */
34
35#if defined(lint)
36#include <sys/types.h>
37#else
38#include "assym.h"
39#endif /* lint */
40
41#include <sys/asm_linkage.h>
42#include <sys/param.h>
43#include <sys/privregs.h>
44#include <sys/machasi.h>
45#include <sys/spitregs.h>
46#include <sys/mmu.h>
47#include <sys/machthread.h>
48#include <sys/pte.h>
49#include <sys/stack.h>
50#include <sys/vis.h>
51
52#ifndef	lint
53
54/*
55 * arg1 = icache_size
56 * arg2 = icache_linesize
57 */
58#define	ICACHE_FLUSHALL(lbl, arg1, arg2, tmp1)			\
59	ldxa	[%g0]ASI_LSU, tmp1				;\
60	btst	LSU_IC, tmp1					;\
61	bz,pn	%icc, lbl/**/1					;\
62	sub	arg1, arg2, tmp1				;\
63lbl/**/0:							;\
64	stxa	%g0, [tmp1]ASI_IC_TAG				;\
65	membar	#Sync						;\
66	cmp	%g0, tmp1					;\
67	bne,pt	%icc, lbl/**/0					;\
68	sub	tmp1, arg2, tmp1				;\
69lbl/**/1:
70
71/*
72 * arg1 = dcache_size
73 * arg2 = dcache_linesize
74 */
75#define	DCACHE_FLUSHALL(lbl, arg1, arg2, tmp1)			\
76	ldxa	[%g0]ASI_LSU, tmp1				;\
77	btst	LSU_DC, tmp1					;\
78	bz,pn	%icc, lbl/**/1					;\
79	sub	arg1, arg2, tmp1				;\
80lbl/**/0:							;\
81	stxa	%g0, [tmp1]ASI_DC_TAG				;\
82	membar	#Sync						;\
83	cmp	%g0, tmp1					;\
84	bne,pt	%icc, lbl/**/0					;\
85	sub	tmp1, arg2, tmp1				;\
86lbl/**/1:
87
88/*
89 * arg1 = ecache flush physaddr
90 * arg2 = size
91 * arg3 = ecache_linesize
92 */
93#define	ECACHE_FLUSHALL(lbl, arg1, arg2, arg3, tmp1, tmp2)	\
94	rdpr	%pstate, tmp1					;\
95	andn	tmp1, PSTATE_IE | PSTATE_AM, tmp2		;\
96	wrpr	%g0, tmp2, %pstate				;\
97	b	lbl/**/1					;\
98lbl/**/0:							;\
99	sub	arg2, arg3, arg2				;\
100lbl/**/1:							;\
101	brgez,a	arg2, lbl/**/0					;\
102	ldxa	[arg1 + arg2]ASI_MEM, %g0			;\
103	wrpr	%g0, tmp1, %pstate
104
105#ifdef SF_ERRATA_32
106#define	SF_WORKAROUND(tmp1, tmp2)				\
107	sethi	%hi(FLUSH_ADDR), tmp2				;\
108	set	MMU_PCONTEXT, tmp1				;\
109	stxa	%g0, [tmp1]ASI_DMMU				;\
110	flush	tmp2						;
111#else
112#define	SF_WORKAROUND(tmp1, tmp2)
113#endif /* SF_ERRATA_32 */
114
115/*
116 * arg1 = vaddr
117 * arg2 = ctxnum
118 *	- disable interrupts and clear address mask
119 *	  to access 64 bit physaddr
120 *	- Blow out the TLB.
121 *	  . If it's kernel context, then use primary context.
122 *	  . Otherwise, use secondary.
123 */
124#define VTAG_FLUSHPAGE(lbl, arg1, arg2, tmp1, tmp2, tmp3, tmp4)	\
125	rdpr	%pstate, tmp1					;\
126	andn	tmp1, PSTATE_IE | PSTATE_AM, tmp2		;\
127	wrpr	tmp2, 0, %pstate				;\
128	brnz,pt	arg2, lbl/**/1					;\
129	sethi	%hi(FLUSH_ADDR), tmp2				;\
130	stxa	%g0, [arg1]ASI_DTLB_DEMAP			;\
131	stxa	%g0, [arg1]ASI_ITLB_DEMAP			;\
132	b	lbl/**/5					;\
133	  flush	tmp2						;\
134lbl/**/1:							;\
135	set	MMU_SCONTEXT, tmp3				;\
136	ldxa	[tmp3]ASI_DMMU, tmp4				;\
137	or	DEMAP_SECOND | DEMAP_PAGE_TYPE, arg1, arg1	;\
138	cmp	tmp4, arg2					;\
139	be,a,pt	%icc, lbl/**/4					;\
140	  nop							;\
141	stxa	arg2, [tmp3]ASI_DMMU				;\
142lbl/**/4:							;\
143	stxa	%g0, [arg1]ASI_DTLB_DEMAP			;\
144	stxa	%g0, [arg1]ASI_ITLB_DEMAP			;\
145	flush	tmp2						;\
146	be,a,pt	%icc, lbl/**/5					;\
147	  nop							;\
148	stxa	tmp4, [tmp3]ASI_DMMU				;\
149	flush	tmp2						;\
150lbl/**/5:							;\
151	wrpr	%g0, tmp1, %pstate
152
153/*
154 * arg1 = dtlb entry
155 *	- Before first compare:
156 *		tmp4 = tte
157 *		tmp5 = vaddr
158 *		tmp6 = cntxnum
159 */
160#define	DTLB_FLUSH_UNLOCKED(lbl, arg1, tmp1, tmp2, tmp3, \
161				tmp4, tmp5, tmp6) \
162lbl/**/0:							;\
163	sllx	arg1, 3, tmp3					;\
164	SF_WORKAROUND(tmp1, tmp2)				;\
165	ldxa	[tmp3]ASI_DTLB_ACCESS, tmp4			;\
166	srlx	tmp4, 6, tmp4					;\
167	andcc	tmp4, 1, %g0					;\
168	bnz,pn	%xcc, lbl/**/1					;\
169	srlx	tmp4, 57, tmp4					;\
170	andcc	tmp4, 1, %g0					;\
171	beq,pn	%xcc, lbl/**/1					;\
172	  nop							;\
173	set	TAGREAD_CTX_MASK, tmp1				;\
174	ldxa	[tmp3]ASI_DTLB_TAGREAD, tmp2			;\
175	and	tmp2, tmp1, tmp6				;\
176	andn	tmp2, tmp1, tmp5				;\
177	VTAG_FLUSHPAGE(VD, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4)	;\
178lbl/**/1:							;\
179	brgz,pt	arg1, lbl/**/0					;\
180	sub	arg1, 1, arg1
181
182/*
183 * arg1 = itlb entry
184 *	- Before first compare:
185 *		tmp4 = tte
186 *		tmp5 = vaddr
187 *		tmp6 = cntxnum
188 */
189#define	ITLB_FLUSH_UNLOCKED(lbl, arg1, tmp1, tmp2, tmp3, \
190				tmp4, tmp5, tmp6) \
191lbl/**/0:							;\
192	sllx	arg1, 3, tmp3					;\
193	SF_WORKAROUND(tmp1, tmp2)				;\
194	ldxa	[tmp3]ASI_ITLB_ACCESS, tmp4			;\
195	srlx	tmp4, 6, tmp4					;\
196	andcc	tmp4, 1, %g0					;\
197	bnz,pn	%xcc, lbl/**/1					;\
198	srlx	tmp4, 57, tmp4					;\
199	andcc	tmp4, 1, %g0					;\
200	beq,pn	%xcc, lbl/**/1					;\
201	  nop							;\
202	set	TAGREAD_CTX_MASK, tmp1				;\
203	ldxa	[tmp3]ASI_ITLB_TAGREAD, tmp2			;\
204	and	tmp2, tmp1, tmp6				;\
205	andn	tmp2, tmp1, tmp5				;\
206	VTAG_FLUSHPAGE(VI, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4)	;\
207lbl/**/1:							;\
208	brgz,pt	arg1, lbl/**/0					;\
209	sub	arg1, 1, arg1
210
211#define	CLEARTL(lvl)			\
212	wrpr	%g0, lvl, %tl		;\
213	wrpr	%g0, %g0, %tpc		;\
214	wrpr	%g0, %g0, %tnpc		;\
215	wrpr	%g0, %g0, %tt
216
217#define	SWITCH_STACK(estk)					\
218	flushw							;\
219	sub	estk, SA(KFPUSIZE+GSR_SIZE), estk		;\
220	andn	estk, 0x3f, estk				;\
221	sub	estk, SA(MINFRAME) + STACK_BIAS, %sp		;\
222	mov	estk, %fp
223
224#endif	/* !lint */
225
226#if defined(lint)
227
228/*ARGSUSED*/
229void
230drmach_shutdown_asm(uint64_t mbox_addr)
231{}
232
233#else /* lint */
234
235	ENTRY_NP(drmach_shutdown_asm)
236	mov	%o0, %o5
237
238	ldxa	[%o5]ASI_MEM, %o0	! get 8-byte estack in o0
239	add	%o5, 8, %o5
240	ldxa	[%o5]ASI_MEM, %o1	! get 8-byte flushaddr in o1
241	add	%o5, 8, %o5
242	lda	[%o5]ASI_MEM, %o2	! get 4-byte size in o2
243	srl	%o2, 0, %o2
244	add	%o5, 4, %o5
245	lda	[%o5]ASI_MEM, %o3	! get 4-byte linesize in o3
246	srl	%o3, 0, %o3
247	add	%o5, 4, %o5
248	ldxa	[%o5]ASI_MEM, %o4	! get 8-byte physaddr in o4
249
250
251	! %o0 = base (va mapping this code in bbsram)
252	! %o1 = flushaddr for ecache
253	! %o2 = size to use for ecache flush
254	! %o3 = ecache linesize
255	! %o4 = phys addr of byte to clear when finished
256	!
257	! output: Stores a zero at [%o4]ASI_MEM
258
259	membar	#LoadStore
260
261	!
262	! Switch stack pointer to bbsram
263	!
264	SWITCH_STACK(%o0)
265
266	!
267	! Get some globals
268	!
269	mov	%o3, %g1		! ecache_linesize
270	mov	%o4, %o0		! physaddr byte to clear
271
272	sethi	%hi(dcache_linesize), %g2
273	ld	[%g2 + %lo(dcache_linesize)], %g2
274
275	sethi	%hi(dcache_size), %g3
276	ld	[%g3 + %lo(dcache_size)], %g3
277
278	sethi	%hi(icache_linesize), %g4
279	ld	[%g4 + %lo(icache_linesize)], %g4
280
281	sethi	%hi(icache_size), %g5
282	ld	[%g5 + %lo(icache_size)], %g5
283
284	sethi	%hi(dtlb_entries), %o5
285	ld	[%o5 + %lo(dtlb_entries)], %o5
286	sllx	%o5, 32, %o5
287	srlx	%o5, 32, %o5
288
289	sethi	%hi(itlb_entries), %o3
290	ld	[%o3 + %lo(itlb_entries)], %o3
291	!
292	! cram Xtlb_entries into a single register (%o5)
293	! %o5 upper 32 = itlb_entries
294	!     lower 32 = dtlb_entries
295	!
296	sllx	%o3, 32, %o3
297	or	%o5, %o3, %o5
298
299	!
300	! Flush E$
301	!
302	ECACHE_FLUSHALL(EC, %o1, %o2, %g1, %o3, %o4)
303	!
304	! %o1 & %o2 now available
305	!
306
307	membar	#Sync
308
309	!
310	! Flush D$
311	!
312	DCACHE_FLUSHALL(DC, %g3, %g2, %o3)
313
314	!
315	! Flush I$
316	!
317	ICACHE_FLUSHALL(IC, %g5, %g4, %o3)
318
319	membar	#Sync
320
321	!
322	! Flush dtlb's
323	!
324	srlx	%o5, 32, %g5		! %g5 = itlb_entries
325	sllx	%o5, 32, %o5
326	srlx	%o5, 32, %g1
327	sub	%g1, 1, %g1		! %g1 = dtlb_entries - 1
328
329	DTLB_FLUSH_UNLOCKED(D, %g1, %g3, %g4, %o2, %o3, %o4, %o5)
330
331	!
332	! Flush itlb's
333	!
334	sub	%g5, 1, %g1		! %g1 = itlb_entries - 1
335
336	ITLB_FLUSH_UNLOCKED(I, %g1, %g3, %g4, %o2, %o3, %o4, %o5)
337
338	membar	#Sync
339
340	!
341	! Clear byte to signal finished.
342	!
343	stba	%g0, [%o0]ASI_MEM
344	membar	#Sync
345
346	!
347	! read ensures that last write completed (has left queue in the PC chip)
348	!
349	lduba	[%o0]ASI_MEM, %g0
3505:
351	ba	5b
352	nop
353	SET_SIZE(drmach_shutdown_asm)
354
355	.global	drmach_shutdown_asm_end
356
357	.skip	2048
358
359drmach_shutdown_asm_end:
360
361#endif /* lint */
362