locore-v4.S revision 153550
1/*	$NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $	*/
2
3/*-
4 * Copyright (C) 1994-1997 Mark Brinicombe
5 * Copyright (C) 1994 Brini
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 Brini.
19 * 4. The name of Brini 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 BRINI ``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 BRINI 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
35#include "assym.s"
36#include <sys/syscall.h>
37#include <machine/asm.h>
38#include <machine/armreg.h>
39#include <machine/pte.h>
40__FBSDID("$FreeBSD: head/sys/arm/arm/locore.S 153550 2005-12-20 01:29:17Z cognet $");
41
42/* What size should this really be ? It is only used by init_arm() */
43#define INIT_ARM_STACK_SIZE	2048
44
45/*
46 * This is for kvm_mkdb, and should be the address of the beginning
47 * of the kernel text segment (not necessarily the same as kernbase).
48 */
49
50
51#define	CPWAIT_BRANCH							 \
52	sub	pc, pc, #4
53
54#define	CPWAIT(tmp)							 \
55	mrc	p15, 0, tmp, c2, c0, 0	/* arbitrary read of CP15 */	;\
56	mov	tmp, tmp		/* wait for it to complete */	;\
57	CPWAIT_BRANCH			/* branch to next insn */
58
59	.text
60	.align	0
61.globl kernbase
62.set kernbase,KERNBASE
63.globl physaddr
64.set physaddr,PHYSADDR
65
66ENTRY_NP(btext)
67
68ASENTRY_NP(_start)
69
70
71	/* Check if we are running on RAM, if not move ourself to RAM */
72#if 0
73	cmp	pc, #PHYSADDR
74	bhi	start_inram /* XXX: This is wrong */
75#endif
76	b	start_inram /*
77			     * XXX: this is even more wrong, but RedBoot
78			     * use 0x00000000-0x100000000 as virtual
79			     * addresses for the RAM.
80			     */
81
82	/* move me to RAM
83	 * XXX: we can use memcpy if it is PIC
84	 */
85	ldr r1, Lcopy_size
86	adr r0, _C_LABEL(_start)
87	add r1, r1, #3
88	mov r1, r1, LSR #2
89	mov r2, #PHYSADDR
90	add r2, r2, #0x00200000
91	mov r4, r2
92
935:	ldr r3,[r0],#4
94	str r3,[r2],#4
95	subs r1,r1,#1
96	bhi 5b
97
98	/* Jump to RAM */
99	ldr r0, Lstart_off
100	add pc, r4, r0
101
102Lcopy_size:	.word _edata-_C_LABEL(_start)
103Lstart_off:	.word start_inram-_C_LABEL(_start)
104start_inram:
105	adr	r7, Lunmapped
106
107	/* Disable MMU for a while */
108	mrc     p15, 0, r2, c1, c0, 0
109	bic	r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
110	    CPU_CONTROL_WBUF_ENABLE)
111	bic	r2, r2, #(CPU_CONTROL_IC_ENABLE)
112	bic	r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
113	mcr     p15, 0, r2, c1, c0, 0
114
115	nop
116	nop
117	nop
118	mov	pc, r7
119Lunmapped:
120
121#ifdef STARTUP_PAGETABLE_ADDR
122	/* build page table from scratch */
123	ldr	r0, Lstartup_pagetable
124	adr	r4, mmu_init_table
125	bic	r4, r4, #0xff000000
126	orr	r4, r4, #PHYSADDR
127	b	3f
128
1292:
130	str	r3, [r0, r2]
131	add	r2, r2, #4
132	add	r3, r3, #(L1_S_SIZE)
133	adds	r1, r1, #-1
134	bhi	2b
1353:
136	ldmia	r4!, {r1,r2,r3}   /* # of sections, PA|attr, VA */
137	cmp	r1, #0
138	adrne	r5, 2b
139	bicne	r5, r5, #0xff000000
140	orrne	r5, r5, #PHYSADDR
141	movne	pc, r5
142
143	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
144	mcr	p15, 0, r0, c8, c7, 0	/* Flush TLB */
145
146	/* Set the Domain Access register.  Very important! */
147	mov     r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
148	mcr	p15, 0, r0, c3, c0, 0
149	/* Enable MMU */
150	mrc	p15, 0, r0, c1, c0, 0
151	orr	r0, r0, #CPU_CONTROL_MMU_ENABLE
152	mcr	p15, 0, r0, c1, c0, 0
153	nop
154	nop
155	nop
156	CPWAIT(r0)
157
158#endif
159mmu_done:
160	nop
161	adr	r1, .Lstart
162	ldmia	r1, {r1, r2, sp}	/* Set initial stack and */
163	sub	r2, r2, r1		/* get zero init data */
164	mov	r3, #0
165.L1:
166	str	r3, [r1], #0x0004	/* get zero init data */
167	subs	r2, r2, #4
168	bgt	.L1
169	ldr	pc, .Lvirt_done
170
171virt_done:
172	mov	fp, #0		/* trace back starts here */
173	bl	_C_LABEL(initarm)	/* Off we go */
174
175	/* init arm will return the new stack pointer. */
176	mov	sp, r0
177
178	bl	_C_LABEL(mi_startup)		/* call mi_startup()! */
179
180	adr	r0, .Lmainreturned
181	b	_C_LABEL(panic)
182	/* NOTEACHED */
183#ifdef STARTUP_PAGETABLE_ADDR
184#define MMU_INIT(va,pa,n_sec,attr) \
185	.word	n_sec					    ; \
186	.word	4*((va)>>L1_S_SHIFT)			    ; \
187	.word	(pa)|(attr)				    ;
188
189Lvirtaddr:
190	.word	KERNVIRTADDR
191Lphysaddr:
192	.word	KERNPHYSADDR
193Lstartup_pagetable:
194	.word	STARTUP_PAGETABLE_ADDR
195mmu_init_table:
196	/* fill all table VA==PA */
197	/* map SDRAM VA==PA, WT cacheable */
198	MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
199	/* map VA 0xc0000000..0xc3ffffff to PA */
200	MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
201
202	.word 0	/* end of table */
203#endif
204.Lstart:
205	.word	_edata
206	.word	_end
207	.word	svcstk + INIT_ARM_STACK_SIZE
208
209.Lvirt_done:
210	.word	virt_done
211.Lmainreturned:
212	.asciz	"main() returned"
213	.align	0
214
215	.bss
216svcstk:
217	.space	INIT_ARM_STACK_SIZE
218
219	.text
220	.align	0
221
222#ifndef OFW
223	/* OFW based systems will used OF_boot() */
224
225.Lcpufuncs:
226	.word	_C_LABEL(cpufuncs)
227
228ENTRY_NP(cpu_halt)
229	mrs     r2, cpsr
230	bic	r2, r2, #(PSR_MODE)
231	orr     r2, r2, #(PSR_SVC32_MODE)
232	orr	r2, r2, #(I32_bit | F32_bit)
233	msr     cpsr_all, r2
234
235	ldr	r4, .Lcpu_reset_address
236	ldr	r4, [r4]
237
238	ldr	r0, .Lcpufuncs
239	mov	lr, pc
240	ldr	pc, [r0, #CF_IDCACHE_WBINV_ALL]
241
242	/*
243	 * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's
244	 * necessary.
245	 */
246
247	ldr	r1, .Lcpu_reset_needs_v4_MMU_disable
248	ldr	r1, [r1]
249	cmp	r1, #0
250	mov	r2, #0
251
252	/*
253 	 * MMU & IDC off, 32 bit program & data space
254	 * Hurl ourselves into the ROM
255	 */
256	mov	r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
257	mcr     15, 0, r0, c1, c0, 0
258	mcrne   15, 0, r2, c8, c7, 0 	/* nail I+D TLB on ARMv4 and greater */
259	mov     pc, r4
260
261	/*
262	 * _cpu_reset_address contains the address to branch to, to complete
263	 * the cpu reset after turning the MMU off
264	 * This variable is provided by the hardware specific code
265	 */
266.Lcpu_reset_address:
267	.word	_C_LABEL(cpu_reset_address)
268
269	/*
270	 * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the
271	 * v4 MMU disable instruction needs executing... it is an illegal instruction
272	 * on f.e. ARM6/7 that locks up the computer in an endless illegal
273	 * instruction / data-abort / reset loop.
274	 */
275.Lcpu_reset_needs_v4_MMU_disable:
276	.word	_C_LABEL(cpu_reset_needs_v4_MMU_disable)
277
278#endif	/* OFW */
279
280#ifdef IPKDB
281/*
282 * Execute(inst, psr, args, sp)
283 *
284 * Execute INSTruction with PSR and ARGS[0] - ARGS[3] making
285 * available stack at SP for next undefined instruction trap.
286 *
287 * Move the instruction onto the stack and jump to it.
288 */
289ENTRY_NP(Execute)
290	mov	ip, sp
291	stmfd	sp!, {r2, r4-r7, fp, ip, lr, pc}
292	sub	fp, ip, #4
293	mov	ip, r3
294	ldr	r7, .Lreturn
295	stmfd	sp!, {r0, r7}
296	adr	r7, #.LExec
297	mov	r5, r1
298	mrs	r4, cpsr
299	ldmia	r2, {r0-r3}
300	mov	r6, sp
301	mov	sp, ip
302	msr	cpsr_all, r5
303	mov	pc, r6
304.LExec:
305	mrs	r5, cpsr
306/* XXX Cannot switch thus easily back from user mode */
307	msr	cpsr_all, r4
308	add	sp, r6, #8
309	ldmfd	sp!, {r6}
310	stmia	r6, {r0-r3}
311	mov	r0, r5
312	ldmdb	fp, {r4-r7, fp, sp, pc}
313.Lreturn:
314	mov	pc, r7
315#endif
316
317/*
318 * setjump + longjmp
319 */
320ENTRY(setjmp)
321	stmia	r0, {r4-r14}
322	mov	r0, #0x00000000
323	RET
324
325ENTRY(longjmp)
326	ldmia	r0, {r4-r14}
327	mov	r0, #0x00000001
328	RET
329
330	.data
331	.global _C_LABEL(esym)
332_C_LABEL(esym):	.word	_C_LABEL(end)
333
334ENTRY_NP(abort)
335	b	_C_LABEL(abort)
336
337ENTRY_NP(sigcode)
338	mov	r0, sp
339	swi	SYS_sigreturn
340
341	/* Well if that failed we better exit quick ! */
342
343	swi	SYS_exit
344	b	. - 8
345
346	.align	0
347	.global _C_LABEL(esigcode)
348		_C_LABEL(esigcode):
349
350	.data
351	.global szsigcode
352szsigcode:
353	.long esigcode-sigcode
354/* End of locore.S */
355