xref: /optee_os/core/arch/riscv/kernel/boot.c (revision e90887e3f478ad38118e76c3aee2a9c41c12aa31)
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