First version
[3rdparty/ote_partner/tlk.git] / arch / arm / arm / start.S
1 /*
2  * Copyright (c) 2008 Travis Geiselbrecht
3  * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #if ARM_USE_MMU_RELOC
25 #include <config.h>
26 #endif
27
28 #if ARM_WITH_LPAE
29 #include <arch/arm/mmu_ldesc_macros.h>
30 #else
31 #include <arch/arm/mmu_sdesc_macros.h>
32 #endif
33
34 .section ".text.boot"
35 .globl _start
36 _start:
37         b       reset
38         b       arm_undefined
39         b       arm_syscall
40         b       arm_prefetch_abort
41         b       arm_data_abort
42         b       arm_reserved
43         b       arm_irq
44         b       arm_fiq
45
46 reset:
47 #if !defined(WITH_MONITOR_BIN)
48         adr     r3, __jumpback_addr
49         str     r14, [r3]
50
51         /* save boot params passed by the bootloader */
52         adr     r3, __save_boot_regs
53         stmia   r3, {r4-r12}
54         mov     r3, #0
55
56         adr     r3, __save_boot_cpsr
57         mrs     r4, cpsr
58         str r4, [r3]
59 #endif
60
61         adr     r3, __bootarg_addr
62         str     r1, [r3]
63
64 #if ARM_USE_MMU_RELOC
65         /* save load address/size of image */
66         adr     r3, __load_phys_size
67         str     r0, [r3]
68
69         /* Derive the phys_base addr */
70         mov     r1, pc
71         sub     r1, r1, #(.Laddr - _start)
72 .Laddr:
73         adr     r3, __load_phys_base
74         str     r1, [r3]
75
76         /* save phys offset (for v -> p conversions) */
77         adr     r3, __load_phys_offset
78         ldr     r4, =_start
79         sub     r6, r4, r1
80         str     r6, [r3]
81
82         /* ensure phys size doesn't exceed virt size */
83         ldr     r4, =VMEMSIZE
84         cmp     r0, r4
85         bhi     .
86
87         /* copies of phys size / phys base */
88         mov     r4, r0
89         mov     r5, r1
90 #endif
91
92 #if ARM_WITH_CP15
93         mrc     p15, 0, r0, c1, c0, 0
94         /* XXX this is currently for arm926, revist with armv6 cores */
95         /* new thumb behavior, low exception vectors, i/d cache disable, mmu disabled */
96         bic     r0, r0, #(1<<15 | 1<<13 | 1<<12)
97         bic     r0, r0, #(1<<2 | 1<<0)
98         bic     r0, r0, #(1<<29 | 1<<28)
99         /* disable alignment faults */
100         /* user mode app/libs may have unaligned references */
101         bic     r0, r0, #(1<<1)
102         mcr     p15, 0, r0, c1, c0, 0
103 #endif
104
105 #if ARM_USE_MMU_RELOC
106         /*
107          * Create page table(s), on entry:
108          *      r4 = phys size
109          *      r5 = phys base
110          *      r6 = phys offset
111          */
112         ldr     r0, =tt
113         sub     r0, r0, r6              // second level phys
114         mmu_desc_create_null_entry r0, r1
115         mmu_desc_create_ident_mapping r0, r1, r2, r3
116
117 #if defined(WITH_MONITOR_BIN)
118         /*
119          * With a separate monitor binary, phys base with this VMEMBASE isn't
120          * guaranteed to be L2 block aligned (i.e. carveout size is reduced by
121          * the size of the monitor), so needs to be mapped with L3 mappings.
122          *
123          * Because the carveout size is arbitrary, we can't preallocate the
124          * number of L3 page tables needed, so its taken dynamically from the
125          * carveout, reducing what's available for the kernel's heap.
126          */
127         mov     r2, r4                  // carveout in bytes
128         mov32   r0, ((1 << MMU_L3_MAP_SHIFT) - 1)
129         add     r2, r2, r0
130         lsr     r2, r2, #MMU_L3_MAP_SHIFT       // roundup to L3 map size
131         lsl     r2, r2, #MMU_L3_SIZE_SHIFT      // bytes of L3 tables
132
133         /* update _early_heap_allocs for page tables */
134         adr     r0, __early_heap_allocs
135         str     r2, [r0]
136         add     r3, r5, r4              // pt ptr = phys_base + phys_size
137         sub     r3, r3, r2              // pt ptr -= L3 pagetable size
138
139         ldr     r0, =tt
140         mov     r2, r4                  // carveout in bytes
141         sub     r8, r0, r6              // second level phys
142         mov32   r0, VMEMBASE
143         mov     r1, r5
144         mov     r11, #0
145         mmu_desc_map_phys_l3 r0, r1, r2, r3, r8, r9, r10, r11
146 #else
147         /*
148          * Should be L2 block aligned as there was no preceding memory
149          * usage, like in the case of a separate monitor binary.
150          */
151         mmu_desc_phy_align r5, r4, r9
152
153         /* map VMEMBASE -> phys carveout */
154         mov     r2, r4                  // carveout in bytes
155         ldr     r3, =tt
156         sub     r3, r3, r6              // second level phys
157         mov32   r0, VMEMBASE            // virt
158         mov     r1, r5                  // phys
159         mmu_desc_map_phys_l2 r0, r1, r2, r3, r9
160
161         /* map alias -> phys carveout */
162         mov     r2, r4                  // carveout in bytes
163         ldr     r3, =tt
164         sub     r3, r3, r6              // second level phys
165         mov     r0, r5                  // virt
166         mov     r1, r5                  // phys
167         mmu_desc_map_phys_l2 r0, r1, r2, r3, r9
168 #endif
169
170         /* load phys pointers to first/second level tables */
171         ldr     r3, =tt_level1
172         sub     r8, r3, r6              // first level phys
173         ldr     r3, =tt
174         sub     r9, r3, r6              // second level phys
175
176 #if ARM_WITH_LPAE
177         /* setup L1 entries */
178         mov     r0, r9
179         mov     r1, r8
180         mov     r2, #0
181         mmu_desc_map_phys_l1 r0, r1, r2
182 #endif
183         /* invalidate tlb */
184         mcr     p15, 0, r2, c8, c7, 0
185         isb
186
187         /* enable MMU */
188         mov     r0, r8
189         mov     r1, r9
190         mmu_desc_init_mmu r0, r1, r2
191         isb
192
193         ldr     r0, =go_virtual
194         mov     pc, r0
195 go_virtual:
196 #endif
197
198 #if WITH_CPU_EARLY_INIT
199         /* call platform/arch/etc specific init code */
200         bl __cpu_early_init
201 #endif
202
203         /* see if we need to relocate */
204         ldr     r0, __load_phys_base
205         ldr     r1, =_start
206         sub     r1, r1, r6              // compare is in phys addrs
207         cmp     r0, r1
208         beq     .Lstack_setup
209
210         /* we need to relocate ourselves to the proper spot */
211         ldr     r2, =__data_end
212
213 .Lrelocate_loop:
214         ldr     r3, [r0], #4
215         str     r3, [r1], #4
216         cmp     r1, r2
217         bne     .Lrelocate_loop
218
219         /* we're relocated, jump to the right address */
220         ldr     r0, =.Lstack_setup
221         bx      r0
222
223 .ltorg
224
225 .Lstack_setup:
226         /* set up the stack for irq, fiq, abort, undefined, system/user, and lastly supervisor mode */
227         mrs     r0, cpsr
228         bic     r0, r0, #0x1f
229
230         ldr     r2, =abort_stack_top
231         orr     r1, r0, #0x12 // irq
232         msr     cpsr_c, r1
233         ldr     r13, =irq_save_spot     /* save a pointer to a temporary dumping spot used during irq delivery */
234
235         orr     r1, r0, #0x11 // fiq
236         msr     cpsr_c, r1
237         mov     sp, r2
238
239         orr     r1, r0, #0x17 // abort
240         msr     cpsr_c, r1
241         mov     sp, r2
242
243         orr     r1, r0, #0x1b // undefined
244         msr     cpsr_c, r1
245         mov     sp, r2
246
247         orr     r1, r0, #0x1f // system
248         msr     cpsr_c, r1
249         mov     sp, r2
250
251         orr     r1, r0, #0x13 // supervisor
252         msr     cpsr_c, r1
253         mov     sp, r2
254
255         /* copy the initialized data segment out of rom if necessary */
256         ldr     r0, =__data_start_rom
257         ldr     r1, =__data_start
258         ldr     r2, =__data_end
259
260         cmp     r0, r1
261         beq     .L__do_bss
262
263 .L__copy_loop:
264         cmp     r1, r2
265         ldrlt   r3, [r0], #4
266         strlt   r3, [r1], #4
267         blt     .L__copy_loop
268
269 .L__do_bss:
270         /* clear out the bss */
271         ldr     r0, =__bss_start
272         ldr     r1, =_end
273         mov     r2, #0
274 .L__bss_loop:
275         cmp     r0, r1
276         strlt   r2, [r0], #4
277         blt     .L__bss_loop
278
279         bl      kmain
280         b       .
281
282         .type   __save_boot_regs, %object
283 .global __save_boot_regs
284 __save_boot_regs:
285         .long   0, 0, 0, 0, 0, 0, 0, 0, 0
286         .size   __save_boot_regs, . - __save_boot_regs
287
288 .global __save_boot_cpsr
289 __save_boot_cpsr:
290         .int 0
291
292 .ltorg
293
294 #if ARM_USE_MMU_RELOC
295 .align 2
296 /*
297  * Keep location of where the image was loaded, and how much
298  * contiguous memory has been made available.
299  */
300 .global __load_phys_base
301 __load_phys_base:
302         .int 0
303 .global __load_phys_size
304 __load_phys_size:
305         .int 0
306 .global __load_phys_offset
307 __load_phys_offset:
308         .int 0
309 .global __early_heap_allocs
310 __early_heap_allocs:
311         .int 0
312 #endif
313
314 .global __jumpback_addr
315 __jumpback_addr:
316         .int 0
317 .global __bootarg_addr
318 __bootarg_addr:
319         .int 0
320
321 .bss
322 .align 2
323         /* the abort stack is for unrecoverable errors.
324          * also note the initial working stack is set to here.
325          * when the threading system starts up it'll switch to a new
326          * dynamically allocated stack, so we don't need it for very long
327          */
328 abort_stack:
329         .skip 1024
330 .global abort_stack_top
331 abort_stack_top:
332
333 .rodata:
334 .align 2
335
336 /* define the heap end as read-only data containing the end defined in the
337  * linker script. other archs that use dynamic memory length discovery can make
338  * this read-write and update it during init.
339  */
340 .global _heap_end
341 _heap_end:
342         .int _end_of_ram