xref: /netbsd-src/sys/arch/sparc/stand/ofwboot/srt0.s (revision fdd524d4ccd2bb0c6f67401e938dabf773eb0372)
1/*	$NetBSD: srt0.s,v 1.7 2015/08/23 10:59:15 joerg 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	FTYPE(openfirmware)
140_C_LABEL(openfirmware):
141	andcc	%sp, 1, %g0
142	bz,pt	%icc, 1f
143	 sethi	%hi(_C_LABEL(romp)), %o1
144
145	LDPTR	[%o1+%lo(_C_LABEL(romp))], %o4		! v9 stack, just load the addr and callit
146	save	%sp, -CC64FSZ, %sp
147	mov	%i0, %o0				! Copy over our parameter
148	mov	%g1, %l1
149	mov	%g2, %l2
150	mov	%g3, %l3
151	mov	%g4, %l4
152	mov	%g5, %l5
153	mov	%g6, %l6
154	mov	%g7, %l7
155	rdpr	%pstate, %l0
156	jmpl	%i4, %o7
157	 wrpr	%g0, PSTATE_PROM|PSTATE_IE, %pstate
158	wrpr	%l0, %g0, %pstate
159	mov	%l1, %g1
160	mov	%l2, %g2
161	mov	%l3, %g3
162	mov	%l4, %g4
163	mov	%l5, %g5
164	mov	%l6, %g6
165	mov	%l7, %g7
166	ret
167	 restore	%o0, %g0, %o0
168
1691:						! v8 -- need to screw with stack & params
170	save	%sp, -CC64FSZ, %sp			! Get a new 64-bit stack frame
171	add	%sp, -BIAS, %sp
172	sethi	%hi(_C_LABEL(romp)), %o1
173	rdpr	%pstate, %l0
174	LDPTR	[%o1+%lo(_C_LABEL(romp))], %o1		! Do the actual call
175	srl	%sp, 0, %sp
176	mov	%i0, %o0
177	mov	%g1, %l1
178	mov	%g2, %l2
179	mov	%g3, %l3
180	mov	%g4, %l4
181	mov	%g5, %l5
182	mov	%g6, %l6
183	mov	%g7, %l7
184	jmpl	%o1, %o7
185	 wrpr	%g0, PSTATE_PROM|PSTATE_IE, %pstate	! Enable 64-bit addresses for the prom
186	wrpr	%l0, 0, %pstate
187	mov	%l1, %g1
188	mov	%l2, %g2
189	mov	%l3, %g3
190	mov	%l4, %g4
191	mov	%l5, %g5
192	mov	%l6, %g6
193	mov	%l7, %g7
194	ret
195	 restore	%o0, %g0, %o0
196
197/*
198 * vaddr_t
199 * itlb_va_to_pa(vaddr_t)
200 *
201 * Find out if there is a mapping in iTLB for a given virtual address,
202 * return -1 if there is none.
203 */
204	.align	8
205	.globl	_C_LABEL(itlb_va_to_pa)
206_C_LABEL(itlb_va_to_pa):
207	set	_C_LABEL(itlb_slot_max), %o3
208	ld	[%o3], %o3
209	dec	%o3
210	sllx	%o3, 3, %o3
211	clr	%o1
2120:	ldxa	[%o1] ASI_IMMU_TLB_TAG, %o2
213	cmp	%o2, %o0
214	bne,a	%xcc, 1f
215	 nop
216	/* return PA of matching entry */
217	ldxa	[%o1] ASI_IMMU_TLB_DATA, %o0
218	sllx	%o0, 23, %o0
219	srlx	%o0, PGSHIFT+23, %o0
220	sllx	%o0, PGSHIFT, %o0
221	retl
222	 mov	%o0, %o1
2231:	cmp	%o1, %o3
224	blu	%xcc, 0b
225	 add	%o1, 8, %o1
226	clr	%o0
227	retl
228	 not	%o0
229
230/*
231 * vaddr_t
232 * dtlb_va_to_pa(vaddr_t)
233 *
234 * Find out if there is a mapping in dTLB for a given virtual address,
235 * return -1 if there is none.
236 */
237	.align	8
238	.globl	_C_LABEL(dtlb_va_to_pa)
239_C_LABEL(dtlb_va_to_pa):
240	set	_C_LABEL(dtlb_slot_max), %o3
241	ld	[%o3], %o3
242	dec	%o3
243	sllx	%o3, 3, %o3
244	clr	%o1
2450:	ldxa	[%o1] ASI_DMMU_TLB_TAG, %o2
246	cmp	%o2, %o0
247	bne,a	%xcc, 1f
248	 nop
249	/* return PA of matching entry */
250	ldxa	[%o1] ASI_DMMU_TLB_DATA, %o0
251	sllx	%o0, 23, %o0
252	srlx	%o0, PGSHIFT+23, %o0
253	sllx	%o0, PGSHIFT, %o0
254	retl
255	 mov	%o0, %o1
2561:	cmp	%o1, %o3
257	blu	%xcc, 0b
258	 add	%o1, 8, %o1
259	clr	%o0
260	retl
261	 not	%o0
262
263/*
264 * void
265 * itlb_enter(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo)
266 *
267 * Insert new mapping into iTLB. Data tag is passed in two different
268 * registers so that it works even with 32-bit compilers.
269 */
270	.align	8
271	.globl	_C_LABEL(itlb_enter)
272_C_LABEL(itlb_enter):
273	sllx	%o1, 32, %o1
274	or	%o1, %o2, %o1
275	rdpr	%pstate, %o4
276	wrpr	%o4, PSTATE_IE, %pstate
277	mov	TLB_TAG_ACCESS, %o3
278	stxa	%o0, [%o3] ASI_IMMU
279	stxa	%o1, [%g0] ASI_IMMU_DATA_IN
280	membar	#Sync
281	retl
282	 wrpr	%o4, 0, %pstate
283
284
285/*
286 * void
287 * dtlb_replace(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo)
288 *
289 * Replace mapping in dTLB. Data tag is passed in two different
290 * registers so that it works even with 32-bit compilers.
291 */
292	.align	8
293	.globl	_C_LABEL(dtlb_replace)
294_C_LABEL(dtlb_replace):
295	sllx	%o1, 32, %o1
296	or	%o1, %o2, %o1
297	rdpr	%pstate, %o4
298	wrpr	%o4, PSTATE_IE, %pstate
299	/* loop over dtlb entries */
300	clr	%o5
3010:
302	ldxa	[%o5] ASI_DMMU_TLB_TAG, %o2
303	cmp	%o2, %o0
304	bne,a	%xcc, 1f
305	 nop
306	/* found - modify entry */
307	mov	TLB_TAG_ACCESS, %o2
308	stxa	%o0, [%o2] ASI_DMMU
309	stxa	%o1, [%o5] ASI_DMMU_TLB_DATA
310	membar	#Sync
311	retl
312	 wrpr	%o4, 0, %pstate
313
314	/* advance to next tlb entry */
3151:	cmp	%o5, 63<<3
316	blu	%xcc, 0b
317	 add	%o5, 8, %o5
318	retl
319	 nop
320
321/*
322 * void
323 * dtlb_enter(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo)
324 *
325 * Insert new mapping into dTLB. Data tag is passed in two different
326 * registers so that it works even with 32-bit compilers.
327 */
328	.align	8
329	.globl	_C_LABEL(dtlb_enter)
330_C_LABEL(dtlb_enter):
331	sllx	%o1, 32, %o1
332	or	%o1, %o2, %o1
333	rdpr	%pstate, %o4
334	wrpr	%o4, PSTATE_IE, %pstate
335	mov	TLB_TAG_ACCESS, %o3
336	stxa	%o0, [%o3] ASI_DMMU
337	stxa	%o1, [%g0] ASI_DMMU_DATA_IN
338	membar	#Sync
339	retl
340	 wrpr	%o4, 0, %pstate
341
342/*
343 * u_int
344 * get_cpuid(void);
345 *
346 * Return UPA identifier for the CPU we're running on.
347 */
348	.align	8
349	.globl	_C_LABEL(get_cpuid)
350_C_LABEL(get_cpuid):
351	UPA_GET_MID(%o0)
352	retl
353	 nop
354
355#if 0
356	.data
357	.align 8
358bootstack:
359#define STACK_SIZE	0x14000
360	.skip	STACK_SIZE
361ebootstack:			! end (top) of boot stack
362#endif
363