1 /* 2 * Copyright (c) 2014, STMicroelectronics International N.V. 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 #include <stdint.h> 28 #include <string.h> 29 #include <sm/sm.h> 30 #include <sm/tee_mon.h> 31 #include <sm/teesmc.h> 32 #include <sm/teesmc_optee.h> 33 #include <arm.h> 34 #include <kernel/thread.h> 35 #include <kernel/panic.h> 36 #include <kernel/pm_stubs.h> 37 #include <malloc.h> 38 #include <util.h> 39 #include <trace.h> 40 #include <kernel/misc.h> 41 #include <mm/tee_pager.h> 42 #include <mm/core_mmu.h> 43 #include <mm/tee_mmu.h> 44 #include <mm/tee_mmu_defs.h> 45 #include <tee/entry.h> 46 #include <tee/arch_svc.h> 47 #include <console.h> 48 #include <asc.h> 49 #include <assert.h> 50 #include <platform_config.h> 51 52 /* teecore heap address/size is defined in scatter file */ 53 extern unsigned char teecore_heap_start; 54 extern unsigned char teecore_heap_end; 55 56 57 static void main_fiq(void); 58 static void main_tee_entry(struct thread_smc_args *args); 59 60 static const struct thread_handlers handlers = { 61 .std_smc = main_tee_entry, 62 .fast_smc = main_tee_entry, 63 .fiq = main_fiq, 64 .svc = tee_svc_handler, 65 .abort = tee_pager_abort_handler, 66 .cpu_on = pm_panic, 67 .cpu_off = pm_panic, 68 .cpu_suspend = pm_panic, 69 .cpu_resume = pm_panic, 70 .system_off = pm_panic, 71 .system_reset = pm_panic, 72 }; 73 74 #define PADDR_INVALID 0xffffffff 75 76 /* May be overridden in plat-$(PLATFORM)/main.c */ 77 void main_init_gic(void); 78 __weak void main_init_gic(void) 79 { 80 } 81 82 #if defined(CFG_WITH_ARM_TRUSTED_FW) 83 static void init_sec_mon(uint32_t nsec_entry __unused) 84 { 85 assert(nsec_entry == PADDR_INVALID); 86 /* Do nothing as we don't have a secure monitor */ 87 } 88 #else 89 static void init_sec_mon(uint32_t nsec_entry) 90 { 91 struct sm_nsec_ctx *nsec_ctx; 92 93 assert(nsec_entry != PADDR_INVALID); 94 95 /* Initialize secure monitor */ 96 nsec_ctx = sm_get_nsec_ctx(); 97 nsec_ctx->mon_lr = nsec_entry; 98 nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I; 99 100 } 101 #endif 102 103 #if defined(CFG_WITH_ARM_TRUSTED_FW) 104 static void init_nsacr(void) 105 { 106 } 107 #else 108 static void init_nsacr(void) 109 { 110 /* Normal world can use CP10 and CP11 (SIMD/VFP) */ 111 write_nsacr(read_nsacr() | NSACR_CP10 | NSACR_CP11); 112 } 113 #endif 114 115 #ifdef CFG_WITH_VFP 116 static void init_cpacr(void) 117 { 118 uint32_t cpacr = read_cpacr(); 119 120 /* Enabled usage of CP10 and CP11 (SIMD/VFP) */ 121 cpacr &= ~CPACR_CP(10, CPACR_CP_ACCESS_FULL); 122 cpacr |= CPACR_CP(10, CPACR_CP_ACCESS_PL1_ONLY); 123 cpacr &= ~CPACR_CP(11, CPACR_CP_ACCESS_FULL); 124 cpacr |= CPACR_CP(11, CPACR_CP_ACCESS_PL1_ONLY); 125 write_cpacr(cpacr); 126 } 127 #else 128 static void init_cpacr(void) 129 { 130 /* We're not using VFP/SIMD instructions, leave it disabled */ 131 } 132 #endif 133 134 static void init_primary_helper(uint32_t nsec_entry) 135 { 136 /* 137 * Mask asynchronous exceptions before switch to the thread vector 138 * as the thread handler requires those to be masked while 139 * executing with the temporary stack. The thread subsystem also 140 * asserts that IRQ is blocked when using most if its functions. 141 */ 142 thread_set_exceptions(THREAD_EXCP_ALL); 143 init_cpacr(); 144 145 /* init_runtime(pageable_part); */ 146 147 DMSG("TEE initializing\n"); 148 149 thread_init_primary(&handlers); 150 thread_init_per_cpu(); 151 init_sec_mon(nsec_entry); 152 153 154 main_init_gic(); 155 init_nsacr(); 156 157 { 158 unsigned long a, s; 159 /* core malloc pool init */ 160 #ifdef CFG_TEE_MALLOC_START 161 a = CFG_TEE_MALLOC_START; 162 s = CFG_TEE_MALLOC_SIZE; 163 #else 164 a = (unsigned long)&teecore_heap_start; 165 s = (unsigned long)&teecore_heap_end; 166 a = ((a + 1) & ~0x0FFFF) + 0x10000; /* 64kB aligned */ 167 s = s & ~0x0FFFF; /* 64kB aligned */ 168 s = s - a; 169 #endif 170 malloc_init((void *)a, s); 171 172 teecore_init_ta_ram(); 173 } 174 } 175 176 static void init_secondary_helper(uint32_t nsec_entry) 177 { 178 /* 179 * Mask asynchronous exceptions before switch to the thread vector 180 * as the thread handler requires those to be masked while 181 * executing with the temporary stack. The thread subsystem also 182 * asserts that IRQ is blocked when using most if its functions. 183 */ 184 thread_set_exceptions(THREAD_EXCP_ALL); 185 186 thread_init_per_cpu(); 187 init_sec_mon(nsec_entry); 188 init_cpacr(); 189 init_nsacr(); 190 191 DMSG("Secondary CPU Switching to normal world boot\n"); 192 } 193 194 #if defined(CFG_WITH_ARM_TRUSTED_FW) 195 uint32_t *generic_boot_init_primary(uint32_t pageable_part) 196 { 197 init_primary_helper(pageable_part, PADDR_INVALID); 198 return thread_vector_table; 199 } 200 201 uint32_t generic_boot_cpu_on_handler(uint32_t a0 __unused, uint32_t a1 __unused) 202 { 203 DMSG("cpu %zu: a0 0x%x", get_core_pos(), a0); 204 init_secondary_helper(PADDR_INVALID); 205 return 0; 206 } 207 #else 208 void generic_boot_init_primary(uint32_t nsec_entry); 209 void generic_boot_init_primary(uint32_t nsec_entry) 210 { 211 init_primary_helper(nsec_entry); 212 } 213 214 void generic_boot_init_secondary(uint32_t nsec_entry); 215 void generic_boot_init_secondary(uint32_t nsec_entry) 216 { 217 init_secondary_helper(nsec_entry); 218 } 219 #endif 220 221 static void main_fiq(void) 222 { 223 panic(); 224 } 225 226 static void main_tee_entry(struct thread_smc_args *args) 227 { 228 /* TODO move to main_init() */ 229 if (init_teecore() != TEE_SUCCESS) 230 panic(); 231 232 tee_entry(args); 233 } 234 235 void console_putc(int ch) 236 { 237 __asc_xmit_char((char)ch); 238 } 239 240 void console_flush(void) 241 { 242 __asc_flush(); 243 } 244