13c47d087SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause
23c47d087SMarouene Boubakri /*
3c120d282SAlvin Chang * Copyright (c) 2023 Andes Technology Corporation
43c47d087SMarouene Boubakri * Copyright 2022-2023 NXP
53c47d087SMarouene Boubakri */
63c47d087SMarouene Boubakri
73c47d087SMarouene Boubakri #include <assert.h>
83c47d087SMarouene Boubakri #include <compiler.h>
93c47d087SMarouene Boubakri #include <config.h>
103c47d087SMarouene Boubakri #include <console.h>
113c47d087SMarouene Boubakri #include <keep.h>
123c47d087SMarouene Boubakri #include <kernel/boot.h>
13c120d282SAlvin Chang #include <kernel/dt.h>
143c47d087SMarouene Boubakri #include <kernel/linker.h>
153c47d087SMarouene Boubakri #include <kernel/misc.h>
163c47d087SMarouene Boubakri #include <kernel/panic.h>
173c47d087SMarouene Boubakri #include <kernel/thread.h>
182e27ec6cSYu-Chien Peter Lin #include <libfdt.h>
193c47d087SMarouene Boubakri #include <mm/core_memprot.h>
203c47d087SMarouene Boubakri #include <mm/core_mmu.h>
21e6a8329aSAlvin Chang #include <mm/page_alloc.h>
223c47d087SMarouene Boubakri #include <mm/tee_mm.h>
233c47d087SMarouene Boubakri #include <mm/tee_pager.h>
243c47d087SMarouene Boubakri #include <platform_config.h>
253c47d087SMarouene Boubakri #include <riscv.h>
26*e90887e3SYu-Chien Peter Lin #include <rng_support.h>
273c47d087SMarouene Boubakri #include <sbi.h>
28b9807372SAlvin Chang #include <stdalign.h>
293c47d087SMarouene Boubakri #include <stdio.h>
303c47d087SMarouene Boubakri #include <trace.h>
313c47d087SMarouene Boubakri #include <util.h>
323c47d087SMarouene Boubakri
333c47d087SMarouene Boubakri #define PADDR_INVALID ULONG_MAX
343c47d087SMarouene Boubakri
353c47d087SMarouene Boubakri paddr_t start_addr;
363c47d087SMarouene Boubakri
373c47d087SMarouene Boubakri uint32_t sem_cpu_sync[CFG_TEE_CORE_NB_CORE];
382e27ec6cSYu-Chien Peter Lin uint32_t hartids[CFG_TEE_CORE_NB_CORE];
393c47d087SMarouene Boubakri
40c120d282SAlvin Chang #if defined(CFG_DT)
mark_tddram_as_reserved(struct dt_descriptor * dt)41c120d282SAlvin Chang static int mark_tddram_as_reserved(struct dt_descriptor *dt)
42c120d282SAlvin Chang {
43c120d282SAlvin Chang return add_res_mem_dt_node(dt, "optee_core", CFG_TDDRAM_START,
44c120d282SAlvin Chang CFG_TDDRAM_SIZE);
45c120d282SAlvin Chang }
46c120d282SAlvin Chang
update_external_dt(void)47c120d282SAlvin Chang static void update_external_dt(void)
48c120d282SAlvin Chang {
49c120d282SAlvin Chang struct dt_descriptor *dt = get_external_dt_desc();
50c120d282SAlvin Chang
51c120d282SAlvin Chang if (!dt || !dt->blob)
52c120d282SAlvin Chang return;
53c120d282SAlvin Chang
54139faa8bSAlvin Chang #ifdef CFG_CORE_RESERVED_SHM
55139faa8bSAlvin Chang if (mark_static_shm_as_reserved(dt))
56139faa8bSAlvin Chang panic("Failed to config non-secure memory");
57139faa8bSAlvin Chang #endif
58139faa8bSAlvin Chang
59c120d282SAlvin Chang if (mark_tddram_as_reserved(dt))
60c120d282SAlvin Chang panic("Failed to config secure memory");
61c120d282SAlvin Chang }
62c120d282SAlvin Chang #else /*CFG_DT*/
update_external_dt(void)63c120d282SAlvin Chang static void update_external_dt(void)
64c120d282SAlvin Chang {
65c120d282SAlvin Chang }
66c120d282SAlvin Chang #endif /*!CFG_DT*/
67c120d282SAlvin Chang
683c47d087SMarouene Boubakri #ifdef CFG_RISCV_S_MODE
start_secondary_cores(void)693c47d087SMarouene Boubakri static void start_secondary_cores(void)
703c47d087SMarouene Boubakri {
712e27ec6cSYu-Chien Peter Lin uint32_t curr_hartid = thread_get_core_local()->hart_id;
722e27ec6cSYu-Chien Peter Lin enum sbi_hsm_hart_state status = 0;
732e27ec6cSYu-Chien Peter Lin uint32_t hartid = 0;
742e27ec6cSYu-Chien Peter Lin int rc = 0;
752e27ec6cSYu-Chien Peter Lin int i = 0;
763c47d087SMarouene Boubakri
772e27ec6cSYu-Chien Peter Lin /* The primary CPU is always indexed by 0 */
782e27ec6cSYu-Chien Peter Lin assert(get_core_pos() == 0);
792e27ec6cSYu-Chien Peter Lin
802e27ec6cSYu-Chien Peter Lin for (i = 0; i < CFG_TEE_CORE_NB_CORE; i++) {
812e27ec6cSYu-Chien Peter Lin hartid = hartids[i];
822e27ec6cSYu-Chien Peter Lin
832e27ec6cSYu-Chien Peter Lin if (hartid == curr_hartid)
842e27ec6cSYu-Chien Peter Lin continue;
852e27ec6cSYu-Chien Peter Lin
862e27ec6cSYu-Chien Peter Lin rc = sbi_hsm_hart_get_status(hartid, &status);
872e27ec6cSYu-Chien Peter Lin /*
882e27ec6cSYu-Chien Peter Lin * Skip if the hartid is not an assigned hart
892e27ec6cSYu-Chien Peter Lin * of the trusted domain, or its HSM state is
902e27ec6cSYu-Chien Peter Lin * not stopped.
912e27ec6cSYu-Chien Peter Lin */
922e27ec6cSYu-Chien Peter Lin if (rc || status != SBI_HSM_STATE_STOPPED)
932e27ec6cSYu-Chien Peter Lin continue;
942e27ec6cSYu-Chien Peter Lin
952e27ec6cSYu-Chien Peter Lin DMSG("Bringing up secondary hart%"PRIu32, hartid);
962e27ec6cSYu-Chien Peter Lin
972e27ec6cSYu-Chien Peter Lin rc = sbi_hsm_hart_start(hartid, start_addr, 0 /* unused */);
982e27ec6cSYu-Chien Peter Lin if (rc) {
992e27ec6cSYu-Chien Peter Lin EMSG("Error starting secondary hart%"PRIu32, hartid);
1002e27ec6cSYu-Chien Peter Lin panic();
1012e27ec6cSYu-Chien Peter Lin }
1022e27ec6cSYu-Chien Peter Lin }
1033c47d087SMarouene Boubakri }
1043c47d087SMarouene Boubakri #endif
1053c47d087SMarouene Boubakri
init_tee_runtime(void)1063c47d087SMarouene Boubakri void init_tee_runtime(void)
1073c47d087SMarouene Boubakri {
1083c47d087SMarouene Boubakri call_preinitcalls();
109fe1244f1SAlvin Chang call_early_initcalls();
110fe1244f1SAlvin Chang call_service_initcalls();
11171ee6d2aSYu-Chien Peter Lin
11271ee6d2aSYu-Chien Peter Lin /* Reinitialize canaries around the stacks with crypto_rng_read(). */
11371ee6d2aSYu-Chien Peter Lin thread_update_canaries();
1143c47d087SMarouene Boubakri }
1153c47d087SMarouene Boubakri
add_padding_to_pool(vaddr_t va,size_t len,void * ptr __unused)116fbdcb35eSAlvin Chang static bool add_padding_to_pool(vaddr_t va, size_t len, void *ptr __unused)
117fbdcb35eSAlvin Chang {
118fbdcb35eSAlvin Chang malloc_add_pool((void *)va, len);
119fbdcb35eSAlvin Chang return true;
120fbdcb35eSAlvin Chang }
121fbdcb35eSAlvin Chang
init_primary(void)1226bfaca07SAlvin Chang static void init_primary(void)
1233c47d087SMarouene Boubakri {
1246ce6769fSAlvin Chang vaddr_t va __maybe_unused = 0;
1256ce6769fSAlvin Chang
1263c47d087SMarouene Boubakri /*
1273c47d087SMarouene Boubakri * Mask asynchronous exceptions before switch to the thread vector
1283c47d087SMarouene Boubakri * as the thread handler requires those to be masked while
1293c47d087SMarouene Boubakri * executing with the temporary stack. The thread subsystem also
1303c47d087SMarouene Boubakri * asserts that the foreign interrupts are blocked when using most of
1313c47d087SMarouene Boubakri * its functions.
1323c47d087SMarouene Boubakri */
1333c47d087SMarouene Boubakri thread_set_exceptions(THREAD_EXCP_ALL);
1343c47d087SMarouene Boubakri
1356ce6769fSAlvin Chang malloc_add_pool(__heap1_start, __heap1_end - __heap1_start);
1366ce6769fSAlvin Chang IMSG_RAW("\n");
137b9807372SAlvin Chang if (IS_ENABLED(CFG_DYN_CONFIG)) {
138b9807372SAlvin Chang size_t sz = sizeof(struct thread_core_local) *
139b9807372SAlvin Chang CFG_TEE_CORE_NB_CORE;
140b9807372SAlvin Chang void *p = boot_mem_alloc(sz, 2 * alignof(void *));
141b9807372SAlvin Chang
142b9807372SAlvin Chang malloc_add_pool(p, sz);
143b9807372SAlvin Chang }
1446ce6769fSAlvin Chang
1456ce6769fSAlvin Chang core_mmu_save_mem_map();
1466ce6769fSAlvin Chang core_mmu_init_phys_mem();
147fbdcb35eSAlvin Chang boot_mem_foreach_padding(add_padding_to_pool, NULL);
1486ce6769fSAlvin Chang va = boot_mem_release_unused();
149e6a8329aSAlvin Chang if (IS_ENABLED(CFG_DYN_CONFIG))
150e6a8329aSAlvin Chang page_alloc_init();
1516ce6769fSAlvin Chang
152b9807372SAlvin Chang /* Initialize canaries around the stacks */
153b9807372SAlvin Chang thread_init_canaries();
1543c47d087SMarouene Boubakri thread_init_per_cpu();
1553c47d087SMarouene Boubakri }
1563c47d087SMarouene Boubakri
1573c47d087SMarouene Boubakri /* May be overridden in plat-$(PLATFORM)/main.c */
plat_primary_init_early(void)1583c47d087SMarouene Boubakri __weak void plat_primary_init_early(void)
1593c47d087SMarouene Boubakri {
1603c47d087SMarouene Boubakri }
1613c47d087SMarouene Boubakri
1623c47d087SMarouene Boubakri /* May be overridden in plat-$(PLATFORM)/main.c */
boot_primary_init_intc(void)163df913c6dSAlvin Chang __weak void boot_primary_init_intc(void)
1643c47d087SMarouene Boubakri {
1653c47d087SMarouene Boubakri }
1663c47d087SMarouene Boubakri
1673c47d087SMarouene Boubakri /* May be overridden in plat-$(PLATFORM)/main.c */
boot_primary_init_core_ids(void)1682e27ec6cSYu-Chien Peter Lin __weak void boot_primary_init_core_ids(void)
1692e27ec6cSYu-Chien Peter Lin {
1702e27ec6cSYu-Chien Peter Lin #ifdef CFG_DT
1712e27ec6cSYu-Chien Peter Lin const void *fdt = get_external_dt();
1722e27ec6cSYu-Chien Peter Lin const fdt32_t *reg = NULL;
1732e27ec6cSYu-Chien Peter Lin int cpu_offset = 0;
1742e27ec6cSYu-Chien Peter Lin int offset = 0;
1752e27ec6cSYu-Chien Peter Lin int len = 0;
1762e27ec6cSYu-Chien Peter Lin int i = 0;
1772e27ec6cSYu-Chien Peter Lin
1782e27ec6cSYu-Chien Peter Lin offset = fdt_path_offset(fdt, "/cpus");
1792e27ec6cSYu-Chien Peter Lin if (offset < 0)
1802e27ec6cSYu-Chien Peter Lin panic("Failed to find /cpus node in the device tree");
1812e27ec6cSYu-Chien Peter Lin
1822e27ec6cSYu-Chien Peter Lin fdt_for_each_subnode(cpu_offset, fdt, offset) {
1832e27ec6cSYu-Chien Peter Lin /*
1842e27ec6cSYu-Chien Peter Lin * Assume all TEE cores are enabled. The "reg"
1852e27ec6cSYu-Chien Peter Lin * property in the CPU node indicates the hart ID.
1862e27ec6cSYu-Chien Peter Lin */
1872e27ec6cSYu-Chien Peter Lin if (fdt_get_status(fdt, cpu_offset) == DT_STATUS_DISABLED)
1882e27ec6cSYu-Chien Peter Lin continue;
1892e27ec6cSYu-Chien Peter Lin
1902e27ec6cSYu-Chien Peter Lin reg = fdt_getprop(fdt, cpu_offset, "reg", &len);
1912e27ec6cSYu-Chien Peter Lin if (!reg) {
1922e27ec6cSYu-Chien Peter Lin EMSG("CPU node does not have 'reg' property");
1932e27ec6cSYu-Chien Peter Lin continue;
1942e27ec6cSYu-Chien Peter Lin }
1952e27ec6cSYu-Chien Peter Lin
1962e27ec6cSYu-Chien Peter Lin assert(i < CFG_TEE_CORE_NB_CORE);
1972e27ec6cSYu-Chien Peter Lin hartids[i++] = fdt32_to_cpu(*reg);
1982e27ec6cSYu-Chien Peter Lin }
1992e27ec6cSYu-Chien Peter Lin
2002e27ec6cSYu-Chien Peter Lin assert(i == CFG_TEE_CORE_NB_CORE);
2012e27ec6cSYu-Chien Peter Lin #endif
2022e27ec6cSYu-Chien Peter Lin }
2032e27ec6cSYu-Chien Peter Lin
2042e27ec6cSYu-Chien Peter Lin /* May be overridden in plat-$(PLATFORM)/main.c */
boot_secondary_init_intc(void)2058aae4669SAlvin Chang __weak void boot_secondary_init_intc(void)
2063c47d087SMarouene Boubakri {
2073c47d087SMarouene Boubakri }
2083c47d087SMarouene Boubakri
boot_init_primary_early(void)2099c5eac75SJens Wiklander void boot_init_primary_early(void)
2103c47d087SMarouene Boubakri {
2116bfaca07SAlvin Chang init_primary();
2123c47d087SMarouene Boubakri }
2133c47d087SMarouene Boubakri
boot_init_primary_late(unsigned long fdt,unsigned long tos_fw_config __unused)214c120d282SAlvin Chang void boot_init_primary_late(unsigned long fdt,
2151f8363e6SAlvin Chang unsigned long tos_fw_config __unused)
2163c47d087SMarouene Boubakri {
217f4ea1751SAlvin Chang init_external_dt(fdt, CFG_DTB_MAX_SIZE);
218f4ea1751SAlvin Chang discover_nsec_memory();
219f4ea1751SAlvin Chang update_external_dt();
220b9807372SAlvin Chang thread_init_threads(CFG_NUM_THREADS);
221f4ea1751SAlvin Chang thread_init_boot_thread();
222b9807372SAlvin Chang thread_init_thread_core_local(CFG_TEE_CORE_NB_CORE);
223f4ea1751SAlvin Chang }
224f4ea1751SAlvin Chang
boot_init_primary_runtime(void)225f4ea1751SAlvin Chang void __weak boot_init_primary_runtime(void)
226f4ea1751SAlvin Chang {
2272e27ec6cSYu-Chien Peter Lin size_t pos = get_core_pos();
2282e27ec6cSYu-Chien Peter Lin
2292e27ec6cSYu-Chien Peter Lin /* The primary CPU is always indexed by 0 */
2302e27ec6cSYu-Chien Peter Lin assert(pos == 0);
2312e27ec6cSYu-Chien Peter Lin
232b9807372SAlvin Chang thread_init_primary();
2333c47d087SMarouene Boubakri IMSG("OP-TEE version: %s", core_v_str);
2349ea709a7SEtienne Carriere if (IS_ENABLED(CFG_INSECURE)) {
2353c47d087SMarouene Boubakri IMSG("WARNING: This OP-TEE configuration might be insecure!");
2363c47d087SMarouene Boubakri IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html");
2373c47d087SMarouene Boubakri }
2382e27ec6cSYu-Chien Peter Lin IMSG("Primary CPU0 (hart%"PRIu32") initializing",
2392e27ec6cSYu-Chien Peter Lin thread_get_hartid_by_hartindex(pos));
240*e90887e3SYu-Chien Peter Lin #ifdef CFG_CORE_ASLR
241*e90887e3SYu-Chien Peter Lin DMSG("Executing at offset %#lx with virtual load address %#"PRIxVA,
242*e90887e3SYu-Chien Peter Lin (unsigned long)boot_mmu_config.map_offset, VCORE_START_VA);
243*e90887e3SYu-Chien Peter Lin #endif
244df913c6dSAlvin Chang boot_primary_init_intc();
2452e27ec6cSYu-Chien Peter Lin boot_primary_init_core_ids();
2463c47d087SMarouene Boubakri init_tee_runtime();
247f4ea1751SAlvin Chang boot_mem_release_tmp_alloc();
2481ede8ef4SAlvin Chang }
2491ede8ef4SAlvin Chang
boot_init_primary_final(void)2501ede8ef4SAlvin Chang void __weak boot_init_primary_final(void)
2511ede8ef4SAlvin Chang {
2522e27ec6cSYu-Chien Peter Lin size_t pos = get_core_pos();
2532e27ec6cSYu-Chien Peter Lin
254fe1244f1SAlvin Chang call_driver_initcalls();
2553c47d087SMarouene Boubakri call_finalcalls();
2562e27ec6cSYu-Chien Peter Lin IMSG("Primary CPU0 (hart%"PRIu32") initialized",
2572e27ec6cSYu-Chien Peter Lin thread_get_hartid_by_hartindex(pos));
2583c47d087SMarouene Boubakri
2593c47d087SMarouene Boubakri #ifdef CFG_RISCV_S_MODE
2603c47d087SMarouene Boubakri start_secondary_cores();
2613c47d087SMarouene Boubakri #endif
2623c47d087SMarouene Boubakri }
2633c47d087SMarouene Boubakri
init_secondary_helper(void)2646bfaca07SAlvin Chang static void init_secondary_helper(void)
2653c47d087SMarouene Boubakri {
2663c47d087SMarouene Boubakri size_t pos = get_core_pos();
2673c47d087SMarouene Boubakri
2682e27ec6cSYu-Chien Peter Lin IMSG("Secondary CPU%zu (hart%"PRIu32") initializing",
2692e27ec6cSYu-Chien Peter Lin pos, thread_get_hartid_by_hartindex(pos));
2703c47d087SMarouene Boubakri
2713c47d087SMarouene Boubakri /*
2723c47d087SMarouene Boubakri * Mask asynchronous exceptions before switch to the thread vector
2733c47d087SMarouene Boubakri * as the thread handler requires those to be masked while
2743c47d087SMarouene Boubakri * executing with the temporary stack. The thread subsystem also
2753c47d087SMarouene Boubakri * asserts that the foreign interrupts are blocked when using most of
2763c47d087SMarouene Boubakri * its functions.
2773c47d087SMarouene Boubakri */
2783c47d087SMarouene Boubakri thread_set_exceptions(THREAD_EXCP_ALL);
2793c47d087SMarouene Boubakri
2803c47d087SMarouene Boubakri thread_init_per_cpu();
2818aae4669SAlvin Chang boot_secondary_init_intc();
2823c47d087SMarouene Boubakri
2832e27ec6cSYu-Chien Peter Lin IMSG("Secondary CPU%zu (hart%"PRIu32") initialized",
2842e27ec6cSYu-Chien Peter Lin pos, thread_get_hartid_by_hartindex(pos));
2853c47d087SMarouene Boubakri }
2863c47d087SMarouene Boubakri
boot_init_secondary(unsigned long nsec_entry __unused)2873c47d087SMarouene Boubakri void boot_init_secondary(unsigned long nsec_entry __unused)
2883c47d087SMarouene Boubakri {
2896bfaca07SAlvin Chang init_secondary_helper();
2903c47d087SMarouene Boubakri }
291*e90887e3SYu-Chien Peter Lin
292*e90887e3SYu-Chien Peter Lin #if defined(CFG_CORE_ASLR)
293*e90887e3SYu-Chien Peter Lin /* May be overridden in plat-$(PLATFORM)/main.c */
plat_get_aslr_seed(void)294*e90887e3SYu-Chien Peter Lin __weak unsigned long plat_get_aslr_seed(void)
295*e90887e3SYu-Chien Peter Lin {
296*e90887e3SYu-Chien Peter Lin return 0;
297*e90887e3SYu-Chien Peter Lin }
298*e90887e3SYu-Chien Peter Lin
get_aslr_seed(void)299*e90887e3SYu-Chien Peter Lin __weak unsigned long get_aslr_seed(void)
300*e90887e3SYu-Chien Peter Lin {
301*e90887e3SYu-Chien Peter Lin TEE_Result res = TEE_SUCCESS;
302*e90887e3SYu-Chien Peter Lin unsigned long seed = 0;
303*e90887e3SYu-Chien Peter Lin
304*e90887e3SYu-Chien Peter Lin if (IS_ENABLED(CFG_RISCV_ZKR_RNG) && riscv_detect_csr_seed()) {
305*e90887e3SYu-Chien Peter Lin res = hw_get_random_bytes(&seed, sizeof(seed));
306*e90887e3SYu-Chien Peter Lin if (res) {
307*e90887e3SYu-Chien Peter Lin DMSG("Zkr: Failed to seed ASLR");
308*e90887e3SYu-Chien Peter Lin goto out;
309*e90887e3SYu-Chien Peter Lin }
310*e90887e3SYu-Chien Peter Lin return seed;
311*e90887e3SYu-Chien Peter Lin }
312*e90887e3SYu-Chien Peter Lin
313*e90887e3SYu-Chien Peter Lin out:
314*e90887e3SYu-Chien Peter Lin /* Try platform implementation */
315*e90887e3SYu-Chien Peter Lin return plat_get_aslr_seed();
316*e90887e3SYu-Chien Peter Lin }
317*e90887e3SYu-Chien Peter Lin #endif /*CFG_CORE_ASLR*/
318