]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/arm/locore.S
MFV on tzdata2008e:
[FreeBSD/FreeBSD.git] / 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 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 #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, VA, PA|attr */
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         /* NOTREACHED */
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 #if defined(FLASHADDR) && defined(LOADERRAMADDR)
215 .L_arm_memcpy:
216         .word   _C_LABEL(_arm_memcpy)
217 #endif
218
219 .Lvirt_done:
220         .word   virt_done
221 .Lmainreturned:
222         .asciz  "main() returned"
223         .align  0
224
225         .bss
226 svcstk:
227         .space  INIT_ARM_STACK_SIZE
228
229         .text
230         .align  0
231
232 .Lcpufuncs:
233         .word   _C_LABEL(cpufuncs)
234
235 ENTRY_NP(cpu_halt)
236         mrs     r2, cpsr
237         bic     r2, r2, #(PSR_MODE)
238         orr     r2, r2, #(PSR_SVC32_MODE)
239         orr     r2, r2, #(I32_bit | F32_bit)
240         msr     cpsr_all, r2
241
242         ldr     r4, .Lcpu_reset_address
243         ldr     r4, [r4]
244
245         ldr     r0, .Lcpufuncs
246         mov     lr, pc
247         ldr     pc, [r0, #CF_IDCACHE_WBINV_ALL]
248
249         /*
250          * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's
251          * necessary.
252          */
253
254         ldr     r1, .Lcpu_reset_needs_v4_MMU_disable
255         ldr     r1, [r1]
256         cmp     r1, #0
257         mov     r2, #0
258
259         /*
260          * MMU & IDC off, 32 bit program & data space
261          * Hurl ourselves into the ROM
262          */
263         mov     r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
264         mcr     15, 0, r0, c1, c0, 0
265         mcrne   15, 0, r2, c8, c7, 0    /* nail I+D TLB on ARMv4 and greater */
266         mov     pc, r4
267
268         /*
269          * _cpu_reset_address contains the address to branch to, to complete
270          * the cpu reset after turning the MMU off
271          * This variable is provided by the hardware specific code
272          */
273 .Lcpu_reset_address:
274         .word   _C_LABEL(cpu_reset_address)
275
276         /*
277          * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the
278          * v4 MMU disable instruction needs executing... it is an illegal instruction
279          * on f.e. ARM6/7 that locks up the computer in an endless illegal
280          * instruction / data-abort / reset loop.
281          */
282 .Lcpu_reset_needs_v4_MMU_disable:
283         .word   _C_LABEL(cpu_reset_needs_v4_MMU_disable)
284
285
286 /*
287  * setjump + longjmp
288  */
289 ENTRY(setjmp)
290         stmia   r0, {r4-r14}
291         mov     r0, #0x00000000
292         RET
293
294 ENTRY(longjmp)
295         ldmia   r0, {r4-r14}
296         mov     r0, #0x00000001
297         RET
298
299         .data
300         .global _C_LABEL(esym)
301 _C_LABEL(esym): .word   _C_LABEL(end)
302
303 ENTRY_NP(abort)
304         b       _C_LABEL(abort)
305
306 ENTRY_NP(sigcode)
307         mov     r0, sp
308         swi     SYS_sigreturn
309
310         /* Well if that failed we better exit quick ! */
311
312         swi     SYS_exit
313         b       . - 8
314
315         .align  0
316         .global _C_LABEL(esigcode)
317                 _C_LABEL(esigcode):
318
319         .data
320         .global szsigcode
321 szsigcode:
322         .long esigcode-sigcode
323 /* End of locore.S */