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