⚠️ The code is based on: https://gitlab.com/riseproject/riscv-optee/optee_os/-/tree/dev-optee-mpxy
Commit ID:
75df9ba41a404aec897399ead0ff0aebcbff48ca
_start()- Run a lottery to decide the primary hart.
- Use
amoadd.wto decide which core is the primary hart.
- Use
- For primary hart:
- For secondary hart:
- Run a lottery to decide the primary hart.
reset_primary()Zero .bss section.
set_tp()- Set
$tptothread_core_local[hartid]. - Save current hart ID to
thread_core_local[hartid].hart_id.
- Set
thread_init_thread_core_local()- Set
thread_core_local.curr_threadtoTHREAD_ID_INVALIDfor all cores (CFG_TEE_CORE_NB_CORE). - Set
thread_core_local.flagtoTHREAD_CLF_TMPto indicate that it’s using the temporary stack for all cores (CFG_TEE_CORE_NB_CORE). - Set first core’s
thread_core_local[0].tmp_stack_va_endtostack_tmp[0].
- Set
plat_primary_init_early()- Do nothing right now.
console_init()- In Andes’ demo, semihosting is used to print out the console.
set_satp()- Set
$satptocore_mmu_config.satp[hartid]. core_mmu_config.satp[]is configured incore_init_mmu_map().
- Set
thread_clr_boot_thread()- Set current thread (
l->curr_thread)’s state toTHREAD_STATE_FREE. - Set
l->curr_threadtoTHREAD_ID_INVALID.
- Set current thread (
- Before calling:
$a0is set toTEEABI_OPTEED_RETURN_ENTRY_DONE.$a1is set tothread_vector_table.$a3~$a5are set to 0.
- This will eventually set
entry_vector_tablein OpenSBI.
- Before calling:
reset_secondary()- Wait for primary hart:
- Set
sem_cpu_sync[hartid]to1to indicate that current hart is ready. boot_init_secondary()
boot_init_primary_early()init_primary()thread_init_core_local_stacks()- Set
thread_core_local.tmp_stack_va_endto the per-corestack_tmpfor all cores (CFG_TEE_CORE_NB_CORE).- Temporary stack (
stack_tmp) is used in the non-thread context, e.g.interrupt_from_kernel()interrupt_from_user()thread_std_abi_entry()thread_rpc_xstatus()
- Temporary stack (
- Set
thread_core_local.abt_stack_va_endto the per-corestack_abtfor all cores (CFG_TEE_CORE_NB_CORE).- Abort stack (
stack_abt) is used in the non-thread context for exception (except for ecall), e.g.exception_from_kernel()exception_from_user()
- Abort stack (
- Set
Call
thread_set_exceptions()withTHREAD_EXCP_ALLto mask both native and foreign interrupts.init_runtime()- Add heap section to the malloc pool.
thread_init_boot_thread()thread_init_threads()init_thread_stacks()- Call
thread_init_stack()to setthread_ctx.stack_va_endto the per-thread stack (#ifndef CFG_WITH_PAGER:stack_thread;#else: dynamically allocated stack) for all threads (CFG_NUM_THREADS).- P.S.
$spwill be set tothreads[0].stack_va_endafterboot_init_primary_early()is returned, before jumping toboot_init_primary_late().
- P.S.
- Call
pgt_init()
- Set
l->curr_threadto Thread 0. - Set Thread 0’s state to
Active.
thread_init_primary()thread_init_canaries()init_user_kcode()- Do nothing in RISC-V.
thread_init_per_cpu()- Set
mtvec/stvectothread_trap_vect(). - Set
mscratch/sscratchto0to indicate that the following traps are from kernel.
- Set
init_sec_mon()- Do nothing as RISC-V doesn’t have a secure monitor.
- Secure monitor is OpenSBI.
- Do nothing as RISC-V doesn’t have a secure monitor.
boot_init_primary_late()init_external_dt()- Initialize the external DTB located at the given address:
- Add MMU mapping of the external DTB.
- Initialize device tree overlay.
- Initialize the external DTB located at the given address:
discover_nsec_memory()- Call
get_nsec_memory()to find all non-secure memories from DT.- Lookup for the DT nodes with
device_type = “memory”.
- Lookup for the DT nodes with
- Call
core_mmu_set_discovered_nsec_ddr()to set:discovered_nsec_ddr_startto the first non-secure memory.- Non-secure memories are sorted by the physical address in ascending order.
discovered_nsec_ddr_nelemsto the number of the non-secure memories.
- Call
update_external_dt()- Call
add_optee_dt_node()to add/firmware/opteeDT node.compatible = "linaro,optee-tz";
- Call
mark_tddram_as_reserved()to add/reserved-memory/optee_coreDT node.- Reserve the secure memory regions in DRAM used by OP-TEE (
CFG_TDDRAM_START~(CFG_TDDRAM_START + CFG_TDDRAM_SIZE - 1)) to prevent Linux from using it.- If
CFG_WITH_PAGERis set andCFG_TDSRAM_STARTis defined, TEE core secure RAM (TEE_RAM) is allocated in SRAM, instead of DRAM. We don’t need to reserve the memory region for it.- However, we still need to reserve other secure memory regions in DRAM (TA_RAM) used by OP-TEE.
- If
- Reserve the secure memory regions in DRAM used by OP-TEE (
- Call
#ifdef CFG_RISCV_S_MODEmpxy_opteed_channel_init()- Check if MPXY extension is supported by OpenSBI.
- Extract MPXY channel ID from DT:
compatible = “riscv,sbi-mpxy-opteed";riscv,sbi-mpxy-channel-id← Defines MPXY channel ID.- Save MPXY channel ID to
mpxy_opteed_ctx.channel_id.
- Save MPXY channel ID to
opensbi-domain-instance← Defines the OpenSBI domain used by OP-TEE (not used by OP-TEE).1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17chosen { opensbi-domains { trusted-domain { compatible = "opensbi,domain,instance"; regions = <0x04 0x3f>; possible-harts = <0x03 0x01>; next-addr = <0x00 0xf1000000>; next-mode = <0x01>; phandle = <0x02>; }; }; sbi-mpxy-opteed { opensbi-domain-instance = <0x02>; riscv,sbi-mpxy-channel-id = <0x02>; compatible = "riscv,sbi-mpxy-opteed"; };
sbi_mpxy_setup_shmem()- Allocates 4KB MPXY shared memory (4KB aligned).
- Call
sbi_mpxy_set_shmemSBI call to set up the allocated MPXY shared memory for the current core. This will invoke OpenSBI’ssbi_mpxy_set_shmem()to save the shared memory address and size into current harttdomain’smpxy_state.
boot_primary_init_intc()plic_init()- Initialize interrupt controller, e.g. PLIC.
init_tee_runtime()core_mmu_init_ta_ram()- Initialize the memory region for static TAs.
MEM_AREA_TA_RAM: Secure RAM where teecore loads/exec TA instances.
- Initialize the memory region for static TAs.
call_preinitcalls()- Call the preinitcalls defined in
.scattered_array_preinitcallsection. - e.g.
mobj_mapped_shm_init()- … etc
- Call the preinitcalls defined in
call_initcalls()- Call the initcalls defined in
.scattered_array_initcallsection. - e.g.
probe_dt_drivers_early()check_ta_store()early_ta_init()verify_pseudo_tas_conformance()tee_cryp_init()- … etc
- Call the initcalls defined in
call_finalcalls()- Call the finalcalls defined in
scattered_array_call_finalcallsection. - e.g.
release_external_dt()- … etc
- Call the finalcalls defined in
#ifdef CFG_RISCV_S_MODEstart_secondary_cores()- Call
sbi_hsm_hart_start()to start the secondary cores.- Start address =
start_addr=_start
- Start address =
- Call
boot_init_secondary()init_secondary_helper()boot_secondary_init_intc()plic_hart_init()- Do nothing.
How to sync boot core and secondary cores during boot up (
#ifdef CFG_BOOT_SYNC_CPU):1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18// core/arch/riscv/kernel/entry.S #ifdef CFG_BOOT_SYNC_CPU .equ SEM_CPU_READY, 1 #endif ..... #ifdef CFG_BOOT_SYNC_CPU LOCAL_DATA sem_cpu_sync_start , : .word sem_cpu_sync END_DATA sem_cpu_sync_start LOCAL_DATA sem_cpu_sync_end , : // Shifted by 4 bytes (uint32_t). .word sem_cpu_sync + (CFG_TEE_CORE_NB_CORE << 2) END_DATA sem_cpu_sync_end #endif1 2 3 4 5 6 7 8 9 10 11 12 13 14 15// core/arch/riscv/kernel/entry.S // Set sem_cpu_sync[hartid] to SEM_CPU_READY (1). .macro cpu_is_ready #ifdef CFG_BOOT_SYNC_CPU // hartid is stored in $xscratch. csrr t0, CSR_XSCRATCH la t1, sem_cpu_sync slli t0, t0, 2 add t1, t1, t0 li t2, SEM_CPU_READY sw t2, 0(t1) fence #endif .endm1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17// core/arch/riscv/kernel/entry.S #ifdef CFG_BOOT_SYNC_CPU // Looks like it doesn't do anything useful in RISC-V... ?! // // In ARM, flush_cpu_semaphores() is defined to: // flush_cache_vrange(sem_cpu_sync_start, sem_cpu_sync_end), // which flushes sem_cpu_sync[0] ~ sem_cpu_sync[CFG_TEE_CORE_NB_CORE - 1] // in boot core caches so that secondary cores can read the updated semaphore // for the boot core. #define flush_cpu_semaphores \ la t0, sem_cpu_sync_start la t1, sem_cpu_sync_end fence #else #define flush_cpu_semaphores #endif1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21// core/arch/riscv/kernel/entry.S // Wait until sem_cpu_sync[1] ~ sem_cpu_sync[CFG_TEE_CORE_NB_CORE - 1] // are all SEM_CPU_READY (1). .macro wait_secondary #ifdef CFG_BOOT_SYNC_CPU la t0, sem_cpu_sync li t1, CFG_TEE_CORE_NB_CORE li t2, SEM_CPU_READY 1: addi t1, t1, -1 beqz t1, 3f addi t0, t0, 4 2: fence lw t1, 0(t0) bne t1, t2, 2b j 1b 3: #endif .endm