xref: /netbsd/sys/arch/sparc/stand/ofwboot/srt0.s (revision 6550d01e)
1/*	$NetBSD: srt0.s,v 1.6 2007/10/17 19:57:16 garbled Exp $	*/
2
3/*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <machine/psl.h>
35#include <machine/param.h>
36#include <machine/frame.h>
37#include <machine/asm.h>
38#include <machine/ctlreg.h>
39
40
41#ifdef _LP64
42#define	LDPTR		ldx
43#else
44#define	LDPTR		lduw
45#endif
46
47
48	.register %g2,#ignore
49	.register %g3,#ignore
50
51/*
52 * Globals
53 */
54	.globl	_esym
55	.data
56_esym:	.word	0			/* end of symbol table */
57
58/*
59 * Startup entry
60 */
61	.text
62	.globl	_start, _C_LABEL(kernel_text)
63	_C_LABEL(kernel_text) = _start
64_start:
65	nop			! For some reason this is needed to fixup the text section
66
67	/*
68	 * Start by creating a stack for ourselves.
69	 */
70#ifdef _LP64
71	/* 64-bit stack */
72	btst	1, %sp
73	set	CC64FSZ, %g1	! Frame Size (negative)
74	bnz	1f
75	 set	BIAS, %g2	! Bias (negative)
76	andn	%sp, 0x0f, %sp	! 16 byte align, per ELF spec.
77	add	%g1, %g2, %g1	! Frame + Bias
781:
79	sub	%sp, %g1, %g1
80	save	%g1, %g0, %sp
81#else
82	/* 32-bit stack */
83	btst	1, %sp
84	set	CC64FSZ, %g1	! Frame Size (negative)
85	bz	1f
86	 set	BIAS, %g2
87	sub	%g1, %g2, %g1
881:
89	sub	%sp, %g1, %g1	! This is so we properly sign-extend things
90	andn	%g1, 0x7, %g1
91	save	%g1, %g0, %sp
92#endif
93
94	/*
95	 * Set the psr into a known state:
96	 * Set supervisor mode, interrupt level >= 13, traps enabled
97	 */
98	wrpr	%g0, 0, %pil	! So I lied
99	wrpr	%g0, PSTATE_PRIV+PSTATE_IE, %pstate
100
101	clr	%g4		! Point %g4 to start of data segment
102				! only problem is that apparently the
103				! start of the data segment is 0
104
105	/*
106	 * void
107	 * main(void *openfirmware)
108	 */
109	call	_C_LABEL(main)
110	 mov	%i4, %o0
111	call	_C_LABEL(OF_exit)
112	 nop
113
114/*
115 * void syncicache(void* start, int size)
116 *
117 * I$ flush.  Really simple.  Just flush over the whole range.
118 */
119	.align	8
120	.globl	_C_LABEL(syncicache)
121_C_LABEL(syncicache):
122	dec	4, %o1
123	flush	%o0
124	brgz,a,pt	%o1, _C_LABEL(syncicache)
125	 inc	4, %o0
126	retl
127	 nop
128
129/*
130 * openfirmware(cell* param);
131 *
132 * OpenFirmware entry point
133 *
134 * If we're running in 32-bit mode we need to convert to a 64-bit stack
135 * and 64-bit cells.  The cells we'll allocate off the stack for simplicity.
136 */
137	.align 8
138	.globl	_C_LABEL(openfirmware)
139	.proc 1
140	FTYPE(openfirmware)
141_C_LABEL(openfirmware):
142	andcc	%sp, 1, %g0
143	bz,pt	%icc, 1f
144	 sethi	%hi(_C_LABEL(romp)), %o1
145
146	LDPTR	[%o1+%lo(_C_LABEL(romp))], %o4		! v9 stack, just load the addr and callit
147	save	%sp, -CC64FSZ, %sp
148	mov	%i0, %o0				! Copy over our parameter
149	mov	%g1, %l1
150	mov	%g2, %l2
151	mov	%g3, %l3
152	mov	%g4, %l4
153	mov	%g5, %l5
154	mov	%g6, %l6
155	mov	%g7, %l7
156	rdpr	%pstate, %l0
157	jmpl	%i4, %o7
158	 wrpr	%g0, PSTATE_PROM|PSTATE_IE, %pstate
159	wrpr	%l0, %g0, %pstate
160	mov	%l1, %g1
161	mov	%l2, %g2
162	mov	%l3, %g3
163	mov	%l4, %g4
164	mov	%l5, %g5
165	mov	%l6, %g6
166	mov	%l7, %g7
167	ret
168	 restore	%o0, %g0, %o0
169
1701:						! v8 -- need to screw with stack & params
171	save	%sp, -CC64FSZ, %sp			! Get a new 64-bit stack frame
172	add	%sp, -BIAS, %sp
173	sethi	%hi(_C_LABEL(romp)), %o1
174	rdpr	%pstate, %l0
175	LDPTR	[%o1+%lo(_C_LABEL(romp))], %o1		! Do the actual call
176	srl	%sp, 0, %sp
177	mov	%i0, %o0
178	mov	%g1, %l1
179	mov	%g2, %l2
180	mov	%g3, %l3
181	mov	%g4, %l4
182	mov	%g5, %l5
183	mov	%g6, %l6
184	mov	%g7, %l7
185	jmpl	%o1, %o7
186	 wrpr	%g0, PSTATE_PROM|PSTATE_IE, %pstate	! Enable 64-bit addresses for the prom
187	wrpr	%l0, 0, %pstate
188	mov	%l1, %g1
189	mov	%l2, %g2
190	mov	%l3, %g3
191	mov	%l4, %g4
192	mov	%l5, %g5
193	mov	%l6, %g6
194	mov	%l7, %g7
195	ret
196	 restore	%o0, %g0, %o0
197
198/*
199 * vaddr_t
200 * itlb_va_to_pa(vaddr_t)
201 *
202 * Find out if there is a mapping in iTLB for a given virtual address,
203 * return -1 if there is none.
204 */
205	.align	8
206	.globl	_C_LABEL(itlb_va_to_pa)
207_C_LABEL(itlb_va_to_pa):
208	set	_C_LABEL(itlb_slot_max), %o3
209	ld	[%o3], %o3
210	dec	%o3
211	sllx	%o3, 3, %o3
212	clr	%o1
2130:	ldxa	[%o1] ASI_IMMU_TLB_TAG, %o2
214	cmp	%o2, %o0
215	bne,a	%xcc, 1f
216	 nop
217	/* return PA of matching entry */
218	ldxa	[%o1] ASI_IMMU_TLB_DATA, %o0
219	sllx	%o0, 23, %o0
220	srlx	%o0, PGSHIFT+23, %o0
221	sllx	%o0, PGSHIFT, %o0
222	retl
223	 mov	%o0, %o1
2241:	cmp	%o1, %o3
225	blu	%xcc, 0b
226	 add	%o1, 8, %o1
227	clr	%o0
228	retl
229	 not	%o0
230
231/*
232 * vaddr_t
233 * dtlb_va_to_pa(vaddr_t)
234 *
235 * Find out if there is a mapping in dTLB for a given virtual address,
236 * return -1 if there is none.
237 */
238	.align	8
239	.globl	_C_LABEL(dtlb_va_to_pa)
240_C_LABEL(dtlb_va_to_pa):
241	set	_C_LABEL(dtlb_slot_max), %o3
242	ld	[%o3], %o3
243	dec	%o3
244	sllx	%o3, 3, %o3
245	clr	%o1
2460:	ldxa	[%o1] ASI_DMMU_TLB_TAG, %o2
247	cmp	%o2, %o0
248	bne,a	%xcc, 1f
249	 nop
250	/* return PA of matching entry */
251	ldxa	[%o1] ASI_DMMU_TLB_DATA, %o0
252	sllx	%o0, 23, %o0
253	srlx	%o0, PGSHIFT+23, %o0
254	sllx	%o0, PGSHIFT, %o0
255	retl
256	 mov	%o0, %o1
2571:	cmp	%o1, %o3
258	blu	%xcc, 0b
259	 add	%o1, 8, %o1
260	clr	%o0
261	retl
262	 not	%o0
263
264/*
265 * void
266 * itlb_enter(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo)
267 *
268 * Insert new mapping into iTLB. Data tag is passed in two different
269 * registers so that it works even with 32-bit compilers.
270 */
271	.align	8
272	.globl	_C_LABEL(itlb_enter)
273_C_LABEL(itlb_enter):
274	sllx	%o1, 32, %o1
275	or	%o1, %o2, %o1
276	rdpr	%pstate, %o4
277	wrpr	%o4, PSTATE_IE, %pstate
278	mov	TLB_TAG_ACCESS, %o3
279	stxa	%o0, [%o3] ASI_IMMU
280	stxa	%o1, [%g0] ASI_IMMU_DATA_IN
281	membar	#Sync
282	retl
283	 wrpr	%o4, 0, %pstate
284
285
286/*
287 * void
288 * dtlb_replace(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo)
289 *
290 * Replace mapping in dTLB. Data tag is passed in two different
291 * registers so that it works even with 32-bit compilers.
292 */
293	.align	8
294	.globl	_C_LABEL(dtlb_replace)
295_C_LABEL(dtlb_replace):
296	sllx	%o1, 32, %o1
297	or	%o1, %o2, %o1
298	rdpr	%pstate, %o4
299	wrpr	%o4, PSTATE_IE, %pstate
300	/* loop over dtlb entries */
301	clr	%o5
3020:
303	ldxa	[%o5] ASI_DMMU_TLB_TAG, %o2
304	cmp	%o2, %o0
305	bne,a	%xcc, 1f
306	 nop
307	/* found - modify entry */
308	mov	TLB_TAG_ACCESS, %o2
309	stxa	%o0, [%o2] ASI_DMMU
310	stxa	%o1, [%o5] ASI_DMMU_TLB_DATA
311	membar	#Sync
312	retl
313	 wrpr	%o4, 0, %pstate
314
315	/* advance to next tlb entry */
3161:	cmp	%o5, 63<<3
317	blu	%xcc, 0b
318	 add	%o5, 8, %o5
319	retl
320	 nop
321
322/*
323 * void
324 * dtlb_enter(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo)
325 *
326 * Insert new mapping into dTLB. Data tag is passed in two different
327 * registers so that it works even with 32-bit compilers.
328 */
329	.align	8
330	.globl	_C_LABEL(dtlb_enter)
331_C_LABEL(dtlb_enter):
332	sllx	%o1, 32, %o1
333	or	%o1, %o2, %o1
334	rdpr	%pstate, %o4
335	wrpr	%o4, PSTATE_IE, %pstate
336	mov	TLB_TAG_ACCESS, %o3
337	stxa	%o0, [%o3] ASI_DMMU
338	stxa	%o1, [%g0] ASI_DMMU_DATA_IN
339	membar	#Sync
340	retl
341	 wrpr	%o4, 0, %pstate
342
343/*
344 * u_int
345 * get_cpuid(void);
346 *
347 * Return UPA identifier for the CPU we're running on.
348 */
349	.align	8
350	.globl	_C_LABEL(get_cpuid)
351_C_LABEL(get_cpuid):
352	UPA_GET_MID(%o0)
353	retl
354	 nop
355
356#if 0
357	.data
358	.align 8
359bootstack:
360#define STACK_SIZE	0x14000
361	.skip	STACK_SIZE
362ebootstack:			! end (top) of boot stack
363#endif
364