27717d50c3eeca569d033f3f6307a90e4add5c43
[platform/core/security/tef-optee_os.git] / core / arch / arm / kernel / generic_entry_a32.S
1 /*
2  * Copyright (c) 2014, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <platform_config.h>
29
30 #include <asm.S>
31 #include <arm.h>
32 #include <arm32_macros.S>
33 #include <sm/optee_smc.h>
34 #include <sm/teesmc_opteed_macros.h>
35 #include <sm/teesmc_opteed.h>
36 #include <kernel/unwind.h>
37 #include <kernel/asan.h>
38
39 .section .data
40 .balign 4
41
42 #ifdef CFG_BOOT_SYNC_CPU
43 .equ SEM_CPU_READY, 1
44 #endif
45
46 #ifdef CFG_PL310
47 .section .rodata.init
48 panic_boot_file:
49         .asciz __FILE__
50
51 /*
52  * void assert_flat_mapped_range(uint32_t vaddr, uint32_t line)
53  */
54 .section .text.init
55 LOCAL_FUNC __assert_flat_mapped_range , :
56 UNWIND( .fnstart)
57 UNWIND( .cantunwind)
58         push    { r4-r6, lr }
59         mov     r4, r0
60         mov     r5, r1
61         bl      cpu_mmu_enabled
62         cmp     r0, #0
63         beq     1f
64         mov     r0, r4
65         bl      virt_to_phys
66         cmp     r0, r4
67         beq     1f
68         /*
69          * this must be compliant with the panic generic routine:
70          * __do_panic(__FILE__, __LINE__, __func__, str)
71          */
72         ldr     r0, =panic_boot_file
73         mov     r1, r5
74         mov     r2, #0
75         mov     r3, #0
76         bl      __do_panic
77         b       .               /* should NOT return */
78 1:      pop     { r4-r6, pc }
79 UNWIND( .fnend)
80 END_FUNC __assert_flat_mapped_range
81
82         /* panic if mmu is enable and vaddr != paddr (scratch lr) */
83         .macro assert_flat_mapped_range va, line
84                 ldr     r0, =(\va)
85                 ldr     r1, =\line
86                 bl      __assert_flat_mapped_range
87         .endm
88 #endif /* CFG_PL310 */
89
90 .section .text.boot
91 FUNC _start , :
92         b       reset
93         b       .       /* Undef */
94         b       .       /* Syscall */
95         b       .       /* Prefetch abort */
96         b       .       /* Data abort */
97         b       .       /* Reserved */
98         b       .       /* IRQ */
99         b       .       /* FIQ */
100 END_FUNC _start
101
102         .macro cpu_is_ready
103 #ifdef CFG_BOOT_SYNC_CPU
104         bl      get_core_pos
105         lsl     r0, r0, #2
106         ldr     r1,=sem_cpu_sync
107         ldr     r2, =SEM_CPU_READY
108         str     r2, [r1, r0]
109         dsb
110         sev
111 #endif
112         .endm
113
114         .macro wait_primary
115 #ifdef CFG_BOOT_SYNC_CPU
116         ldr     r0, =sem_cpu_sync
117         mov     r2, #SEM_CPU_READY
118         sev
119 1:
120         ldr     r1, [r0]
121         cmp     r1, r2
122         wfene
123         bne     1b
124 #endif
125         .endm
126
127         .macro wait_secondary
128 #ifdef CFG_BOOT_SYNC_CPU
129         ldr     r0, =sem_cpu_sync
130         mov     r3, #CFG_TEE_CORE_NB_CORE
131         mov     r2, #SEM_CPU_READY
132         sev
133 1:
134         subs    r3, r3, #1
135         beq     3f
136         add     r0, r0, #4
137 2:
138         ldr     r1, [r0]
139         cmp     r1, r2
140         wfene
141         bne     2b
142         b       1b
143 3:
144 #endif
145         .endm
146
147         /*
148          * Save boot arguments
149          * entry r0, saved r4: pagestore
150          * entry r1, saved r7: (ARMv7 standard bootarg #1)
151          * entry r2, saved r6: device tree address, (ARMv7 standard bootarg #2)
152          * entry lr, saved r5: non-secure entry address (ARMv7 bootarg #0)
153          */
154         .macro bootargs_entry
155 #if defined(CFG_NS_ENTRY_ADDR)
156         ldr     r5, =CFG_NS_ENTRY_ADDR
157 #else
158         mov     r5, lr
159 #endif
160 #if defined(CFG_PAGEABLE_ADDR)
161         ldr     r4, =CFG_PAGEABLE_ADDR
162 #else
163         mov     r4, r0
164 #endif
165 #if defined(CFG_DT_ADDR)
166         ldr     r6, =CFG_DT_ADDR
167 #else
168         mov     r6, r2
169 #endif
170         mov     r7, r1
171         .endm
172
173 LOCAL_FUNC reset , :
174 UNWIND( .fnstart)
175 UNWIND( .cantunwind)
176
177         bootargs_entry
178
179         /* Enable alignment checks and disable data and instruction cache. */
180         read_sctlr r0
181         orr     r0, r0, #SCTLR_A
182         bic     r0, r0, #SCTLR_C
183         bic     r0, r0, #SCTLR_I
184         write_sctlr r0
185         isb
186
187         /* Early ARM secure MP specific configuration */
188         bl      plat_cpu_reset_early
189
190         ldr     r0, =_start
191         write_vbar r0
192
193 #if defined(CFG_WITH_ARM_TRUSTED_FW)
194         b       reset_primary
195 #else
196         bl      get_core_pos
197         cmp     r0, #0
198         beq     reset_primary
199         b       reset_secondary
200 #endif
201 UNWIND( .fnend)
202 END_FUNC reset
203
204         /*
205          * Setup sp to point to the top of the tmp stack for the current CPU:
206          * sp is assigned stack_tmp + (cpu_id + 1) * stack_tmp_stride -
207          * stack_tmp_offset
208          */
209         .macro set_sp
210                 bl      get_core_pos
211                 cmp     r0, #CFG_TEE_CORE_NB_CORE
212                 /* Unsupported CPU, park it before it breaks something */
213                 bge     unhandled_cpu
214                 add     r0, r0, #1
215                 ldr     r2, =stack_tmp_stride
216                 ldr     r1, [r2]
217                 mul     r2, r0, r1
218                 ldr     r1, =stack_tmp
219                 add     r1, r1, r2
220                 ldr     r2, =stack_tmp_offset
221                 ldr     r2, [r2]
222                 sub     sp, r1, r2
223         .endm
224
225         /*
226          * Cache maintenance during entry: handle outer cache.
227          * End address is exclusive: first byte not to be changed.
228          * Note however arm_clX_inv/cleanbyva operate on full cache lines.
229          *
230          * Use ANSI #define to trap source file line number for PL310 assertion
231          */
232         .macro __inval_cache_vrange vbase, vend, line
233 #ifdef CFG_PL310
234                 assert_flat_mapped_range (\vbase), (\line)
235                 bl      pl310_base
236                 ldr     r1, =(\vbase)
237                 ldr     r2, =(\vend)
238                 bl      arm_cl2_invbypa
239 #endif
240                 ldr     r0, =(\vbase)
241                 ldr     r1, =(\vend)
242                 bl      arm_cl1_d_invbyva
243         .endm
244
245         .macro __flush_cache_vrange vbase, vend, line
246 #ifdef CFG_PL310
247                 assert_flat_mapped_range (\vbase), (\line)
248                 ldr     r0, =(\vbase)
249                 ldr     r1, =(\vend)
250                 bl      arm_cl1_d_cleanbyva
251                 bl      pl310_base
252                 ldr     r1, =(\vbase)
253                 ldr     r2, =(\vend)
254                 bl      arm_cl2_cleaninvbypa
255 #endif
256                 ldr     r0, =(\vbase)
257                 ldr     r1, =(\vend)
258                 bl      arm_cl1_d_cleaninvbyva
259         .endm
260
261 #define inval_cache_vrange(vbase, vend) \
262                 __inval_cache_vrange (vbase), ((vend) - 1), __LINE__
263
264 #define flush_cache_vrange(vbase, vend) \
265                 __flush_cache_vrange (vbase), ((vend) - 1), __LINE__
266
267 #ifdef CFG_BOOT_SYNC_CPU
268 #define flush_cpu_semaphores \
269                 flush_cache_vrange(sem_cpu_sync, \
270                                    (sem_cpu_sync + (CFG_TEE_CORE_NB_CORE << 2)))
271 #else
272 #define flush_cpu_semaphores
273 #endif
274
275 LOCAL_FUNC reset_primary , :
276 UNWIND( .fnstart)
277 UNWIND( .cantunwind)
278
279         /* preserve r4-r7: bootargs */
280
281 #ifdef CFG_WITH_PAGER
282         /*
283          * Move init code into correct location and move hashes to a
284          * temporary safe location until the heap is initialized.
285          *
286          * The binary is built as:
287          * [Pager code, rodata and data] : In correct location
288          * [Init code and rodata] : Should be copied to __text_init_start
289          * [Hashes] : Should be saved before initializing pager
290          *
291          */
292         ldr     r0, =__text_init_start  /* dst */
293         ldr     r1, =__data_end         /* src */
294         ldr     r2, =__tmp_hashes_end   /* dst limit */
295         /* Copy backwards (as memmove) in case we're overlapping */
296         sub     r2, r2, r0              /* len */
297         add     r0, r0, r2
298         add     r1, r1, r2
299         ldr     r2, =__text_init_start
300 copy_init:
301         ldmdb   r1!, {r3, r8-r12, sp}
302         stmdb   r0!, {r3, r8-r12, sp}
303         cmp     r0, r2
304         bgt     copy_init
305 #endif
306
307
308 #ifdef CFG_CORE_SANITIZE_KADDRESS
309         /* First initialize the entire shadow area with no access */
310         ldr     r0, =__asan_shadow_start        /* start */
311         ldr     r1, =__asan_shadow_end  /* limit */
312         mov     r2, #ASAN_DATA_RED_ZONE
313 shadow_no_access:
314         str     r2, [r0], #4
315         cmp     r0, r1
316         bls     shadow_no_access
317
318         /* Mark the entire stack area as OK */
319         ldr     r2, =CFG_ASAN_SHADOW_OFFSET
320         ldr     r0, =__nozi_stack_start /* start */
321         lsr     r0, r0, #ASAN_BLOCK_SHIFT
322         add     r0, r0, r2
323         ldr     r1, =__nozi_stack_end   /* limit */
324         lsr     r1, r1, #ASAN_BLOCK_SHIFT
325         add     r1, r1, r2
326         mov     r2, #0
327 shadow_stack_access_ok:
328         strb    r2, [r0], #1
329         cmp     r0, r1
330         bls     shadow_stack_access_ok
331 #endif
332
333         set_sp
334
335         /* complete ARM secure MP common configuration */
336         bl      plat_cpu_reset_late
337
338         /* Enable Console */
339         bl      console_init
340
341 #ifdef CFG_PL310
342         bl      pl310_base
343         bl      arm_cl2_config
344 #endif
345
346         /*
347          * Invalidate dcache for all memory used during initialization to
348          * avoid nasty surprices when the cache is turned on. We must not
349          * invalidate memory not used by OP-TEE since we may invalidate
350          * entries used by for instance ARM Trusted Firmware.
351          */
352 #ifdef CFG_WITH_PAGER
353         inval_cache_vrange(__text_start, __tmp_hashes_end)
354 #else
355         inval_cache_vrange(__text_start, __end)
356 #endif
357
358 #ifdef CFG_PL310
359         /* Enable PL310 if not yet enabled */
360         bl      pl310_base
361         bl      arm_cl2_enable
362 #endif
363
364         bl      core_init_mmu_map
365         bl      core_init_mmu_regs
366         bl      cpu_mmu_enable
367         bl      cpu_mmu_enable_icache
368         bl      cpu_mmu_enable_dcache
369
370         mov     r0, r4          /* pageable part address */
371         mov     r1, r5          /* ns-entry address */
372         mov     r2, r6          /* DT address */
373         bl      generic_boot_init_primary
374         mov     r4, r0          /* save entry test vector */
375
376         /*
377          * In case we've touched memory that secondary CPUs will use before
378          * they have turned on their D-cache, clean and invalidate the
379          * D-cache before exiting to normal world.
380          */
381 #ifdef CFG_WITH_PAGER
382         flush_cache_vrange(__text_start, __init_end)
383 #else
384         flush_cache_vrange(__text_start, __end)
385 #endif
386
387         /* release secondary boot cores and sync with them */
388         cpu_is_ready
389         flush_cpu_semaphores
390         wait_secondary
391
392 #ifdef CFG_PL310_LOCKED
393         /* lock/invalidate all lines: pl310 behaves as if disable */
394         bl      pl310_base
395         bl      arm_cl2_lockallways
396         bl      pl310_base
397         bl      arm_cl2_cleaninvbyway
398 #endif
399
400         /*
401          * Clear current thread id now to allow the thread to be reused on
402          * next entry. Matches the thread_init_boot_thread() in
403          * generic_boot.c.
404          */
405         bl      thread_clr_boot_thread
406
407 #if defined(CFG_WITH_ARM_TRUSTED_FW)
408         /* Pass the vector address returned from main_init */
409         mov     r1, r4
410 #else
411         /* realy standard bootarg #1 and #2 to non secure entry */
412         mov     r4, #0
413         mov     r3, r6          /* std bootarg #2 for register R2 */
414         mov     r2, r7          /* std bootarg #1 for register R1 */
415         mov     r1, #0
416 #endif /* CFG_WITH_ARM_TRUSTED_FW */
417
418         mov     r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
419         smc     #0
420         b       .       /* SMC should not return */
421 UNWIND( .fnend)
422 END_FUNC reset_primary
423
424
425 LOCAL_FUNC unhandled_cpu , :
426 UNWIND( .fnstart)
427         wfi
428         b       unhandled_cpu
429 UNWIND( .fnend)
430 END_FUNC unhandled_cpu
431
432 #if defined(CFG_WITH_ARM_TRUSTED_FW)
433 FUNC cpu_on_handler , :
434 UNWIND( .fnstart)
435 UNWIND( .cantunwind)
436         mov     r4, r0
437         mov     r5, r1
438         mov     r6, lr
439         read_sctlr r0
440         orr     r0, r0, #SCTLR_A
441         write_sctlr r0
442
443         ldr     r0, =_start
444         write_vbar r0
445
446         mov     r4, lr
447         set_sp
448
449         bl      core_init_mmu_regs
450         bl      cpu_mmu_enable
451         bl      cpu_mmu_enable_icache
452         bl      cpu_mmu_enable_dcache
453
454         mov     r0, r4
455         mov     r1, r5
456         bl      generic_boot_cpu_on_handler
457
458         bx      r6
459 UNWIND( .fnend)
460 END_FUNC cpu_on_handler
461
462 #else /* defined(CFG_WITH_ARM_TRUSTED_FW) */
463
464 LOCAL_FUNC reset_secondary , :
465 UNWIND( .fnstart)
466 UNWIND( .cantunwind)
467
468         wait_primary
469
470         set_sp
471
472         bl      plat_cpu_reset_late
473
474 #if defined (CFG_BOOT_SECONDARY_REQUEST)
475         /* if L1 is not invalidated before, do it here */
476         bl      arm_cl1_d_invbysetway
477 #endif
478
479         bl      core_init_mmu_regs
480         bl      cpu_mmu_enable
481         bl      cpu_mmu_enable_icache
482         bl      cpu_mmu_enable_dcache
483
484         cpu_is_ready
485
486 #if defined (CFG_BOOT_SECONDARY_REQUEST)
487         /* generic_boot_core_hpen return value (r0) is ns entry point */
488         bl      generic_boot_core_hpen
489 #else
490         mov     r0, r5          /* ns-entry address */
491 #endif
492         bl      generic_boot_init_secondary
493
494         mov     r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
495         mov     r1, #0
496         mov     r2, #0
497         mov     r3, #0
498         mov     r4, #0
499         smc     #0
500         b       .       /* SMC should not return */
501 UNWIND( .fnend)
502 END_FUNC reset_secondary
503 #endif /* defined(CFG_WITH_ARM_TRUSTED_FW) */