FreeBSD/Linux Kernel Cross Reference
sys/arm/arm/locore.S
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: src/sys/arm/arm/locore.S,v 1.21 2008/10/14 10:11:14 raj Exp $");
41
42 /* What size should this really be ? It is only used by initarm() */
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
66 ENTRY_NP(btext)
67
68 ASENTRY_NP(_start)
69
70 /*
71 * Move metadata ptr to r12 (ip)
72 */
73
74 mov ip, r0
75
76 #if defined (FLASHADDR) && defined(LOADERRAMADDR)
77 /* Check if we're running from flash. */
78 ldr r7, =FLASHADDR
79 /*
80 * If we're running with MMU disabled, test against the
81 * physical address instead.
82 */
83 mrc p15, 0, r2, c1, c0, 0
84 ands r2, r2, #CPU_CONTROL_MMU_ENABLE
85 ldreq r8, =PHYSADDR
86 ldrne r8, =LOADERRAMADDR
87 cmp r7, r8
88 bls flash_lower
89 cmp r7, pc
90 bhi from_ram
91 b do_copy
92
93 flash_lower:
94 cmp r8, pc
95 bls from_ram
96 do_copy:
97 ldr r9, =KERNBASE
98 adr r1, _start
99 ldr r0, Lreal_start
100 ldr r2, Lend
101 sub r2, r2, r0
102 sub r0, r0, r9
103 add r0, r0, r8
104 mov r4, r0
105 bl memcpy
106 ldr r0, Lram_offset
107 add pc, r4, r0
108 Lram_offset: .word from_ram-_C_LABEL(_start)
109 from_ram:
110 nop
111 #endif
112 adr r7, Lunmapped
113 bic r7, r7, #0xff000000
114 orr r7, r7, #PHYSADDR
115
116
117 disable_mmu:
118 /* Disable MMU for a while */
119 mrc p15, 0, r2, c1, c0, 0
120 bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
121 CPU_CONTROL_WBUF_ENABLE)
122 bic r2, r2, #(CPU_CONTROL_IC_ENABLE)
123 bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
124 mcr p15, 0, r2, c1, c0, 0
125
126 nop
127 nop
128 nop
129 mov pc, r7
130 Lunmapped:
131 #ifdef STARTUP_PAGETABLE_ADDR
132 /* build page table from scratch */
133 ldr r0, Lstartup_pagetable
134 adr r4, mmu_init_table
135 b 3f
136
137 2:
138 str r3, [r0, r2]
139 add r2, r2, #4
140 add r3, r3, #(L1_S_SIZE)
141 adds r1, r1, #-1
142 bhi 2b
143 3:
144 ldmia r4!, {r1,r2,r3} /* # of sections, VA, PA|attr */
145 cmp r1, #0
146 adrne r5, 2b
147 bicne r5, r5, #0xff000000
148 orrne r5, r5, #PHYSADDR
149 movne pc, r5
150
151 mcr p15, 0, r0, c2, c0, 0 /* Set TTB */
152 mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */
153
154 /* Set the Domain Access register. Very important! */
155 mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
156 mcr p15, 0, r0, c3, c0, 0
157 /* Enable MMU */
158 mrc p15, 0, r0, c1, c0, 0
159 orr r0, r0, #CPU_CONTROL_MMU_ENABLE
160 mcr p15, 0, r0, c1, c0, 0
161 nop
162 nop
163 nop
164 CPWAIT(r0)
165
166 #endif
167 mmu_done:
168 nop
169 adr r1, .Lstart
170 ldmia r1, {r1, r2, sp} /* Set initial stack and */
171 sub r2, r2, r1 /* get zero init data */
172 mov r3, #0
173 .L1:
174 str r3, [r1], #0x0004 /* get zero init data */
175 subs r2, r2, #4
176 bgt .L1
177 ldr pc, .Lvirt_done
178
179 virt_done:
180 mov r0, ip /* Load argument: metadata ptr */
181
182 mov fp, #0 /* trace back starts here */
183 bl _C_LABEL(initarm) /* Off we go */
184
185 /* init arm will return the new stack pointer. */
186 mov sp, r0
187
188 bl _C_LABEL(mi_startup) /* call mi_startup()! */
189
190 adr r0, .Lmainreturned
191 b _C_LABEL(panic)
192 /* NOTREACHED */
193 #ifdef STARTUP_PAGETABLE_ADDR
194 #define MMU_INIT(va,pa,n_sec,attr) \
195 .word n_sec ; \
196 .word 4*((va)>>L1_S_SHIFT) ; \
197 .word (pa)|(attr) ;
198
199 Lvirtaddr:
200 .word KERNVIRTADDR
201 Lphysaddr:
202 .word KERNPHYSADDR
203 Lreal_start:
204 .word _start
205 Lend:
206 .word _edata
207 Lstartup_pagetable:
208 .word STARTUP_PAGETABLE_ADDR
209 mmu_init_table:
210 /* fill all table VA==PA */
211 /* map SDRAM VA==PA, WT cacheable */
212 MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
213 /* map VA 0xc0000000..0xc3ffffff to PA */
214 MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
215
216 .word 0 /* end of table */
217 #endif
218 .Lstart:
219 .word _edata
220 .word _end
221 .word svcstk + INIT_ARM_STACK_SIZE
222
223 #if defined(FLASHADDR) && defined(LOADERRAMADDR)
224 .L_arm_memcpy:
225 .word _C_LABEL(_arm_memcpy)
226 #endif
227
228 .Lvirt_done:
229 .word virt_done
230 .Lmainreturned:
231 .asciz "main() returned"
232 .align 0
233
234 .bss
235 svcstk:
236 .space INIT_ARM_STACK_SIZE
237
238 .text
239 .align 0
240
241 .Lcpufuncs:
242 .word _C_LABEL(cpufuncs)
243
244 ENTRY_NP(cpu_halt)
245 mrs r2, cpsr
246 bic r2, r2, #(PSR_MODE)
247 orr r2, r2, #(PSR_SVC32_MODE)
248 orr r2, r2, #(I32_bit | F32_bit)
249 msr cpsr_all, r2
250
251 ldr r4, .Lcpu_reset_address
252 ldr r4, [r4]
253
254 ldr r0, .Lcpufuncs
255 mov lr, pc
256 ldr pc, [r0, #CF_IDCACHE_WBINV_ALL]
257 mov lr, pc
258 ldr pc, [r0, #CF_L2CACHE_WBINV_ALL]
259
260 /*
261 * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's
262 * necessary.
263 */
264
265 ldr r1, .Lcpu_reset_needs_v4_MMU_disable
266 ldr r1, [r1]
267 cmp r1, #0
268 mov r2, #0
269
270 /*
271 * MMU & IDC off, 32 bit program & data space
272 * Hurl ourselves into the ROM
273 */
274 mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
275 mcr 15, 0, r0, c1, c0, 0
276 mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */
277 mov pc, r4
278
279 /*
280 * _cpu_reset_address contains the address to branch to, to complete
281 * the cpu reset after turning the MMU off
282 * This variable is provided by the hardware specific code
283 */
284 .Lcpu_reset_address:
285 .word _C_LABEL(cpu_reset_address)
286
287 /*
288 * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the
289 * v4 MMU disable instruction needs executing... it is an illegal instruction
290 * on f.e. ARM6/7 that locks up the computer in an endless illegal
291 * instruction / data-abort / reset loop.
292 */
293 .Lcpu_reset_needs_v4_MMU_disable:
294 .word _C_LABEL(cpu_reset_needs_v4_MMU_disable)
295
296
297 /*
298 * setjump + longjmp
299 */
300 ENTRY(setjmp)
301 stmia r0, {r4-r14}
302 mov r0, #0x00000000
303 RET
304
305 ENTRY(longjmp)
306 ldmia r0, {r4-r14}
307 mov r0, #0x00000001
308 RET
309
310 .data
311 .global _C_LABEL(esym)
312 _C_LABEL(esym): .word _C_LABEL(end)
313
314 ENTRY_NP(abort)
315 b _C_LABEL(abort)
316
317 ENTRY_NP(sigcode)
318 mov r0, sp
319 swi SYS_sigreturn
320
321 /* Well if that failed we better exit quick ! */
322
323 swi SYS_exit
324 b . - 8
325
326 .align 0
327 .global _C_LABEL(esigcode)
328 _C_LABEL(esigcode):
329
330 .data
331 .global szsigcode
332 szsigcode:
333 .long esigcode-sigcode
334 /* End of locore.S */
Cache object: fa4f917b1fb897e4277ee2e920707fa0
|