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