static void main_init_sec_mon(size_t pos, uint32_t nsec_entry) { struct sm_nsec_ctx *nsec_ctx; assert(nsec_entry != NSEC_ENTRY_INVALID); /* Initialize secure monitor */ sm_init(GET_STACK(stack_sm[pos])); nsec_ctx = sm_get_nsec_ctx(); nsec_ctx->mon_lr = nsec_entry; nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I; sm_set_entry_vector(thread_vector_table); }
/* * Copyright (c) 2014, STMicroelectronics International N.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <stdint.h> #include <string.h> #include <sm/sm.h> #include <sm/sm_defs.h> #include <sm/tee_mon.h> #include <sm/teesmc.h> #include <sm/teesmc_st.h> #include <kernel/arch_debug.h> #include <arm32.h> #include <kernel/thread.h> #include <kernel/panic.h> #include <kernel/util.h> #include <kernel/tee_core_trace.h> #include <kernel/misc.h> #include <mm/tee_pager_unpg.h> #include <mm/core_mmu.h> #include <tee/entry.h> #include <assert.h> #ifdef WITH_STACK_CANARIES #define STACK_CANARY_SIZE (4 * sizeof(uint32_t)) #define START_CANARY_VALUE 0xdededede #define END_CANARY_VALUE 0xabababab #define GET_START_CANARY(name, stack_num) name[stack_num][0] #define GET_END_CANARY(name, stack_num) \ name[stack_num][sizeof(name[stack_num]) / sizeof(uint32_t) - 1] #else #define STACK_CANARY_SIZE 0 #endif #define STACK_ALIGNMENT 8 #define DECLARE_STACK(name, num_stacks, stack_size) \ static uint32_t name[num_stacks][(stack_size + STACK_CANARY_SIZE) / \ sizeof(uint32_t)] \ __attribute__((section(".bss.prebss.stack"), \ aligned(STACK_ALIGNMENT))) #define GET_STACK(stack) \ ((vaddr_t)(stack) + sizeof(stack) - STACK_CANARY_SIZE / 2) DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE, STACK_TMP_SIZE); DECLARE_STACK(stack_abt, CFG_TEE_CORE_NB_CORE, STACK_ABT_SIZE); DECLARE_STACK(stack_sm, CFG_TEE_CORE_NB_CORE, SM_STACK_SIZE); DECLARE_STACK(stack_thread, NUM_THREADS, STACK_THREAD_SIZE); const vaddr_t stack_tmp_top[CFG_TEE_CORE_NB_CORE] = { GET_STACK(stack_tmp[0]), #if CFG_TEE_CORE_NB_CORE > 1 GET_STACK(stack_tmp[1]), #endif #if CFG_TEE_CORE_NB_CORE > 2 GET_STACK(stack_tmp[2]), #endif #if CFG_TEE_CORE_NB_CORE > 3 GET_STACK(stack_tmp[3]), #endif #if CFG_TEE_CORE_NB_CORE > 4 #error "Top of tmp stacks aren't defined for more than 4 CPUS" #endif }; static void main_fiq(void); static void main_tee_entry(struct thread_smc_args *args); static uint32_t main_default_pm_handler(uint32_t a0, uint32_t a1); static void init_canaries(void) { size_t n; #define INIT_CANARY(name) \ for (n = 0; n < ARRAY_SIZE(name); n++) { \ uint32_t *start_canary = &GET_START_CANARY(name, n); \ uint32_t *end_canary = &GET_END_CANARY(name, n); \ \ *start_canary = START_CANARY_VALUE; \ *end_canary = END_CANARY_VALUE; \ } INIT_CANARY(stack_tmp); INIT_CANARY(stack_abt); INIT_CANARY(stack_sm); INIT_CANARY(stack_thread); } void check_canaries(void) { #ifdef WITH_STACK_CANARIES size_t n; #define ASSERT_STACK_CANARIES(name) \ for (n = 0; n < ARRAY_SIZE(name); n++) { \ assert(GET_START_CANARY(name, n) == START_CANARY_VALUE);\ assert(GET_END_CANARY(name, n) == END_CANARY_VALUE); \ } while (0) ASSERT_STACK_CANARIES(stack_tmp); ASSERT_STACK_CANARIES(stack_abt); ASSERT_STACK_CANARIES(stack_sm); ASSERT_STACK_CANARIES(stack_thread); #endif /*WITH_STACK_CANARIES*/ } static const struct thread_handlers handlers = { .std_smc = main_tee_entry, .fast_smc = main_tee_entry, .fiq = main_fiq, .svc = NULL, /* XXX currently using hardcod svc handler */ .abort = tee_pager_abort_handler, .cpu_on = main_default_pm_handler, .cpu_off = main_default_pm_handler, .cpu_suspend = main_default_pm_handler, .cpu_resume = main_default_pm_handler, .system_off = main_default_pm_handler, .system_reset = main_default_pm_handler, }; void main_init(uint32_t nsec_entry); /* called from assembly only */ void main_init(uint32_t nsec_entry) { struct sm_nsec_ctx *nsec_ctx; size_t pos = get_core_pos(); /* * Mask IRQ and FIQ before switch to the thread vector as the * thread handler requires IRQ and FIQ to be masked while executing * with the temporary stack. The thread subsystem also asserts that * IRQ is blocked when using most if its functions. */ write_cpsr(read_cpsr() | CPSR_F | CPSR_I); if (pos == 0) { size_t n; /* Initialize canries around the stacks */ init_canaries(); /* Assign the thread stacks */ for (n = 0; n < NUM_THREADS; n++) { if (!thread_init_stack(n, GET_STACK(stack_thread[n]))) panic(); } } if (!thread_init_stack(THREAD_TMP_STACK, GET_STACK(stack_tmp[pos]))) panic(); if (!thread_init_stack(THREAD_ABT_STACK, GET_STACK(stack_abt[pos]))) panic(); thread_init_handlers(&handlers); /* Initialize secure monitor */ sm_init(GET_STACK(stack_sm[pos])); nsec_ctx = sm_get_nsec_ctx(); nsec_ctx->mon_lr = nsec_entry; nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I; sm_set_entry_vector(thread_vector_table); }