void tbase_init_core(uint64_t mpidr) { uint32_t linear_id = platform_get_core_pos(mpidr); tbase_context *tbase_ctx = &secure_context[linear_id]; tbase_init_secure_context(tbase_ctx); uint32_t boot_core_nro = platform_get_core_pos(tbaseBootCoreMpidr); save_sysregs_core(boot_core_nro, linear_id); }
static void tbase_triggerSgiDump(void) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); uint32_t SGITargets; /* Configure SGI */ gicd_clr_igroupr(get_plat_config()->gicd_base, FIQ_SMP_CALL_SGI); gicd_set_ipriorityr(get_plat_config()->gicd_base, FIQ_SMP_CALL_SGI, GIC_HIGHEST_SEC_PRIORITY); /* Enable SGI */ gicd_set_isenabler(get_plat_config()->gicd_base, FIQ_SMP_CALL_SGI); /* Send SGIs to all cores except the current one (current will directly branch to the dump handler) */ SGITargets = 0xFF; SGITargets &= ~(1 << linear_id); /* Trigger SGI */ irq_raise_softirq(SGITargets, FIQ_SMP_CALL_SGI); /* Current core directly branches to dump handler */ plat_tbase_dump(); }
/******************************************************************************* * This function performs any remaining bookkeeping in the test secure payload * before the system is reset (in response to a psci SYSTEM_RESET request) ******************************************************************************/ tsp_args_t *tsp_system_reset_main(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); /* Update this cpu's statistics */ tsp_stats[linear_id].smc_count++; tsp_stats[linear_id].eret_count++; #if LOG_LEVEL >= LOG_LEVEL_INFO spin_lock(&console_lock); INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", mpidr); INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", mpidr, tsp_stats[linear_id].smc_count, tsp_stats[linear_id].eret_count); spin_unlock(&console_lock); #endif /* Indicate to the SPD that we have completed this request */ return set_smc_args(TSP_SYSTEM_RESET_DONE, 0, 0, 0, 0, 0, 0, 0); }
/******************************************************************************* * This function performs any book keeping in the test secure payload after this * cpu's architectural state has been restored after wakeup from an earlier psci * cpu_suspend request. ******************************************************************************/ tsp_args_t *tsp_cpu_resume_main(uint64_t suspend_level, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); /* Restore the generic timer context */ tsp_generic_timer_restore(); /* Update this cpu's statistics */ tsp_stats[linear_id].smc_count++; tsp_stats[linear_id].eret_count++; tsp_stats[linear_id].cpu_resume_count++; #if LOG_LEVEL >= LOG_LEVEL_INFO spin_lock(&console_lock); INFO("TSP: cpu 0x%lx resumed. suspend level %ld\n", mpidr, suspend_level); INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n", mpidr, tsp_stats[linear_id].smc_count, tsp_stats[linear_id].eret_count, tsp_stats[linear_id].cpu_suspend_count); spin_unlock(&console_lock); #endif /* Indicate to the SPD that we have completed this request */ return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0); }
static tsp_args *set_smc_args(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7) { uint64_t mpidr = read_mpidr(); uint32_t linear_id; tsp_args *pcpu_smc_args; /* * Return to Secure Monitor by raising an SMC. The results of the * service are passed as an arguments to the SMC */ linear_id = platform_get_core_pos(mpidr); pcpu_smc_args = &tsp_smc_args[linear_id]; write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0); write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1); write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2); write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3); write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4); write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5); write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6); write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7); return pcpu_smc_args; }
/******************************************************************************* * TSP main entry point where it gets the opportunity to initialize its secure * state/applications. Once the state is initialized, it must return to the * SPD with a pointer to the 'tsp_vector_table' jump table. ******************************************************************************/ uint64_t tsp_main(void) { NOTICE("TSP: %s\n", version_string); NOTICE("TSP: %s\n", build_message); INFO("TSP: Total memory base : 0x%lx\n", BL32_TOTAL_BASE); INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_LIMIT - BL32_TOTAL_BASE); uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); /* Initialize the platform */ tsp_platform_setup(); /* Initialize secure/applications state here */ tsp_generic_timer_start(); /* Update this cpu's statistics */ tsp_stats[linear_id].smc_count++; tsp_stats[linear_id].eret_count++; tsp_stats[linear_id].cpu_on_count++; #if LOG_LEVEL >= LOG_LEVEL_INFO spin_lock(&console_lock); INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", mpidr, tsp_stats[linear_id].smc_count, tsp_stats[linear_id].eret_count, tsp_stats[linear_id].cpu_on_count); spin_unlock(&console_lock); #endif return (uint64_t) &tsp_vector_table; }
/******************************************************************************* * This cpu is being suspended. S-EL1 state must have been saved in the * resident cpu (mpidr format) if it is a UP/UP migratable TSP. ******************************************************************************/ static void tspd_cpu_suspend_handler(uint64_t power_state) { int32_t rc = 0; uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tsp_context *tsp_ctx = &tspd_sp_context[linear_id]; assert(tsp_entry_info); assert(tsp_ctx->state == TSP_STATE_ON); /* Program the entry point, power_state parameter and enter the TSP */ write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx), CTX_GPREG_X0, power_state); cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_suspend_entry); rc = tspd_synchronous_sp_entry(tsp_ctx); /* * Read the response from the TSP. A non-zero return means that * something went wrong while communicating with the TSP. */ if (rc != 0) panic(); /* Update its context to reflect the state the TSP is in */ tsp_ctx->state = TSP_STATE_SUSPEND; }
/******************************************************************************* * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits * before passing control back to the Secure Monitor. Entry in S-El1 is done * after initialising minimal architectural state that guarantees safe * execution. ******************************************************************************/ static void tspd_cpu_on_finish_handler(uint64_t cookie) { int32_t rc = 0; uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tsp_context *tsp_ctx = &tspd_sp_context[linear_id]; assert(tsp_entry_info); assert(tsp_ctx->state == TSP_STATE_OFF); /* Initialise this cpu's secure context */ tspd_init_secure_context((uint64_t) tsp_entry_info->cpu_on_entry, TSP_AARCH64, mpidr, tsp_ctx); /* Enter the TSP */ rc = tspd_synchronous_sp_entry(tsp_ctx); /* * Read the response from the TSP. A non-zero return means that * something went wrong while communicating with the SP. */ if (rc != 0) panic(); /* Update its context to reflect the state the SP is in */ tsp_ctx->state = TSP_STATE_ON; }
/******************************************************************************* * This cpu is being turned off. Allow the TSPD/TSP to perform any actions * needed ******************************************************************************/ static int32_t tspd_cpu_off_handler(uint64_t cookie) { int32_t rc = 0; uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tsp_context *tsp_ctx = &tspd_sp_context[linear_id]; assert(tsp_entry_info); assert(tsp_ctx->state == TSP_STATE_ON); /* Program the entry point and enter the TSP */ cm_set_el3_elr(SECURE, (uint64_t) tsp_entry_info->cpu_off_entry); rc = tspd_synchronous_sp_entry(tsp_ctx); /* * Read the response from the TSP. A non-zero return means that * something went wrong while communicating with the TSP. */ if (rc != 0) panic(); /* * Reset TSP's context for a fresh start when this cpu is turned on * subsequently. */ tsp_ctx->state = TSP_STATE_OFF; return 0; }
/******************************************************************************* * This function performs any book keeping in the test secure payload after this * cpu's architectural state has been restored after wakeup from an earlier psci * cpu_suspend request. ******************************************************************************/ tsp_args *tsp_cpu_resume_main(uint64_t suspend_level, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); /* Update this cpu's statistics */ tsp_stats[linear_id].smc_count++; tsp_stats[linear_id].eret_count++; tsp_stats[linear_id].cpu_resume_count++; spin_lock(&console_lock); printf("SP: cpu 0x%x resumed. suspend level %d \n\r", mpidr, suspend_level); INFO("cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", mpidr, tsp_stats[linear_id].smc_count, tsp_stats[linear_id].eret_count, tsp_stats[linear_id].cpu_suspend_count); spin_unlock(&console_lock); /* Indicate to the SPD that we have completed this request */ return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0); }
/******************************************************************************* * This function passes control to the OPTEE image (BL32) for the first time * on the primary cpu after a cold boot. It assumes that a valid secure * context has already been created by opteed_setup() which can be directly * used. It also assumes that a valid non-secure context has been * initialised by PSCI so it does not need to save and restore any * non-secure state. This function performs a synchronous entry into * OPTEE. OPTEE passes control back to this routine through a SMC. ******************************************************************************/ static int32_t opteed_init(void) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; entry_point_info_t *optee_entry_point; uint64_t rc; /* * Get information about the OPTEE (BL32) image. Its * absence is a critical failure. */ optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE); assert(optee_entry_point); cm_init_context(mpidr, optee_entry_point); /* * Arrange for an entry into OPTEE. It will be returned via * OPTEE_ENTRY_DONE case */ rc = opteed_synchronous_sp_entry(optee_ctx); assert(rc != 0); return rc; }
/******************************************************************************* * This function performs any remaining book keeping in the test secure payload * after this cpu's architectural state has been setup in response to an earlier * psci cpu_on request. ******************************************************************************/ tsp_args_t *tsp_cpu_on_main(void) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); /* Initialize secure/applications state here */ tsp_generic_timer_start(); /* Update this cpu's statistics */ tsp_stats[linear_id].smc_count++; tsp_stats[linear_id].eret_count++; tsp_stats[linear_id].cpu_on_count++; #if LOG_LEVEL >= LOG_LEVEL_INFO spin_lock(&console_lock); INFO("TSP: cpu 0x%lx turned on\n", mpidr); INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", mpidr, tsp_stats[linear_id].smc_count, tsp_stats[linear_id].eret_count, tsp_stats[linear_id].cpu_on_count); spin_unlock(&console_lock); #endif /* Indicate to the SPD that we have completed turned ourselves on */ return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0); }
/******************************************************************************* * This function sets the pointer to the current 'cpu_context' structure for the * specified security state for the CPU identified by MPIDR ******************************************************************************/ void cm_set_context_by_mpidr(uint64_t mpidr, void *context, uint32_t security_state) { assert(sec_state_is_valid(security_state)); cm_set_context_by_index(platform_get_core_pos(mpidr), context, security_state); }
void save_sysregs_allcore() { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); for (int coreNro = 0; coreNro < TBASE_CORE_COUNT; coreNro++) { save_sysregs_core(linear_id, coreNro); } tbaseBootCoreMpidr = mpidr; }
/******************************************************************************* * The following function provides a compatibility function for SPDs using the * existing cm library routines. This function is expected to be invoked for * initializing the cpu_context for the CPU specified by MPIDR for first use. ******************************************************************************/ void cm_init_context(unsigned long mpidr, const entry_point_info_t *ep) { if ((mpidr & MPIDR_AFFINITY_MASK) == (read_mpidr_el1() & MPIDR_AFFINITY_MASK)) cm_init_my_context(ep); else cm_init_context_by_index(platform_get_core_pos(mpidr), ep); }
void spm_mcdi_finish(unsigned long mpidr) { unsigned long linear_id = platform_get_core_pos(mpidr); spm_lock_get(); spm_mcdi_wfi_sel_leave(mpidr); mmio_write_32(SPM_PCM_SW_INT_CLEAR, (0x1 << linear_id)); spm_lock_release(); }
/******************************************************************************* * The target cpu is being turned on. ******************************************************************************/ static void tbase_cpu_on_handler(uint64_t target_cpu) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tbase_context *tbase_ctx = &secure_context[linear_id]; // TODO tbase_ctx->state = TBASE_STATE_ON; }
void bakery_lock_release(unsigned long mpidr, bakery_lock * bakery) { unsigned int entry = platform_get_core_pos(mpidr); assert_bakery_entry_valid(entry, bakery); assert(bakery->owner == entry); bakery->owner = NO_OWNER; bakery->number[entry] = 0; }
/******************************************************************************* * This cpu is being suspended. S-EL1 state must have been saved in the * resident cpu (mpidr format), if any. ******************************************************************************/ static void tbase_cpu_suspend_handler(uint64_t power_state) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tbase_context *tbase_ctx = &secure_context[linear_id]; assert(tbase_ctx->state == TBASE_STATE_ON); DBG_PRINTF("\r\ntbase_cpu_suspend_handler %d\r\n", linear_id); tbase_ctx->state = TBASE_STATE_SUSPEND; }
/******************************************************************************* * Private FVP function to program the mailbox for a cpu before it is released * from reset. ******************************************************************************/ static void plat_program_mailbox(uint64_t mpidr, uint64_t address) { uint64_t linear_id; mailbox_t *plat_mboxes; linear_id = platform_get_core_pos(mpidr); plat_mboxes = (mailbox_t *)MBOX_BASE; plat_mboxes[linear_id].value = address; flush_dcache_range((unsigned long) &plat_mboxes[linear_id], sizeof(unsigned long)); }
/******************************************************************************* * This function returns a pointer to the most recent 'cpu_context' structure * for the CPU identified by MPIDR that was set as the context for the specified * security state. NULL is returned if no such structure has been specified. ******************************************************************************/ void *cm_get_context_by_mpidr(uint64_t mpidr, uint32_t security_state) { assert(sec_state_is_valid(security_state)); /* * Suppress deprecated declaration warning in compatibility function */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" return cm_get_context_by_index(platform_get_core_pos(mpidr), security_state); #pragma GCC diagnostic pop }
/******************************************************************************* * This cpu is being turned off. ******************************************************************************/ static int32_t tbase_cpu_off_handler(uint64_t cookie) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tbase_context *tbase_ctx = &secure_context[linear_id]; assert(tbase_ctx->state == TBASE_STATE_ON); DBG_PRINTF("\r\ntbase_cpu_off_handler %d\r\n", linear_id); tbase_ctx->state = TBASE_STATE_OFF; return 0; }
/******************************************************************************* * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type * (aarch32/aarch64) if not already known and initialises the context for entry * into the SP for its initialisation. ******************************************************************************/ int32_t fiqd_setup(void) { entry_point_info_t *tsp_ep_info; uint64_t mpidr = read_mpidr(); uint32_t linear_id; linear_id = platform_get_core_pos(mpidr); /* * Get information about the Secure Payload (BL32) image. Its * absence is a critical failure. TODO: Add support to * conditionally include the SPD service */ tsp_ep_info = bl31_plat_get_next_image_ep_info(SECURE); if (!tsp_ep_info) { WARN("No TSP provided by BL2 boot loader, Booting device" " without TSP initialization. SMC`s destined for TSP" " will return SMC_UNK\n"); return 1; } #if 0 /* * If there's no valid entry point for SP, we return a non-zero value * signalling failure initializing the service. We bail out without * registering any handlers */ if (!tsp_ep_info->pc) return 1; #endif /* * We could inspect the SP image and determine it's execution * state i.e whether AArch32 or AArch64. Assuming it's AArch64 * for the time being. */ fiqd_init_tsp_ep_state(tsp_ep_info, TSP_AARCH64, tsp_ep_info->pc, &fiqd_sp_context[linear_id]); #if TSP_INIT_ASYNC bl31_set_next_image_type(SECURE); #else /* * All FIQD initialization done. Now register our init function with * BL31 for deferred invocation */ bl31_register_bl32_init(&fiqd_init); #endif return 0; }
/******************************************************************************* * This cpu has resumed from suspend. ******************************************************************************/ static void tbase_cpu_suspend_finish_handler(uint64_t suspend_level) { // int32_t rc = 0; uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tbase_context *tbase_ctx = &secure_context[linear_id]; assert(tbase_ctx->state == TBASE_STATE_SUSPEND); DBG_PRINTF("\r\ntbase_cpu_suspend_finish_handler %d\r\n", linear_id); // TODO tbase_ctx->state = TBASE_STATE_ON; }
/* * Acquire bakery lock * * Contending CPUs need first obtain a non-zero ticket and then calculate * priority value. A contending CPU iterate over all other CPUs in the platform, * which may be contending for the same lock, in the order of their ordinal * position (CPU0, CPU1 and so on). A non-contending CPU will have its ticket * (and priority) value as 0. The contending CPU compares its priority with that * of others'. The CPU with the highest priority (lowest numerical value) * acquires the lock */ void bakery_lock_get(unsigned long mpidr, bakery_lock_t *bakery) { unsigned int they, me; unsigned int my_ticket, my_prio, their_ticket; me = platform_get_core_pos(mpidr); assert_bakery_entry_valid(me, bakery); /* Prevent recursive acquisition */ assert(bakery->owner != me); /* Get a ticket */ my_ticket = bakery_get_ticket(bakery, me); /* * Now that we got our ticket, compute our priority value, then compare * with that of others, and proceed to acquire the lock */ my_prio = PRIORITY(my_ticket, me); for (they = 0; they < BAKERY_LOCK_MAX_CPUS; they++) { if (me == they) continue; /* Wait for the contender to get their ticket */ while (bakery->entering[they]) wfe(); /* * If the other party is a contender, they'll have non-zero * (valid) ticket value. If they do, compare priorities */ their_ticket = bakery->number[they]; if (their_ticket && (PRIORITY(their_ticket, they) < my_prio)) { /* * They have higher priority (lower value). Wait for * their ticket value to change (either release the lock * to have it dropped to 0; or drop and probably content * again for the same lock to have an even higher value) */ do { wfe(); } while (their_ticket == bakery->number[they]); } } /* Lock acquired */ bakery->owner = me; }
int32_t tsp_irq_received(void) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tsp_stats[linear_id].irq_count++; #if LOG_LEVEL >= LOG_LEVEL_VERBOSE spin_lock(&console_lock); VERBOSE("TSP: cpu 0x%lx received irq\n", mpidr); VERBOSE("TSP: cpu 0x%lx: %d irq requests\n", mpidr, tsp_stats[linear_id].irq_count); spin_unlock(&console_lock); #endif return TSP_PREEMPTED; }
/* Release the lock and signal contenders */ void bakery_lock_release(unsigned long mpidr, bakery_lock_t *bakery) { unsigned int me = platform_get_core_pos(mpidr); assert_bakery_entry_valid(me, bakery); assert(bakery->owner == me); /* * Release lock by resetting ownership and ticket. Then signal other * waiting contenders */ bakery->owner = NO_OWNER; bakery->number[me] = 0; sev(); }
/******************************************************************************* * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type * (aarch32/aarch64) if not already known and initialises the context for entry * into OPTEE for its initialization. ******************************************************************************/ int32_t opteed_setup(void) { entry_point_info_t *optee_ep_info; uint64_t mpidr = read_mpidr(); uint32_t linear_id; linear_id = platform_get_core_pos(mpidr); /* * Get information about the Secure Payload (BL32) image. Its * absence is a critical failure. TODO: Add support to * conditionally include the SPD service */ optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE); if (!optee_ep_info) { WARN("No OPTEE provided by BL2 boot loader, Booting device" " without OPTEE initialization. SMC`s destined for OPTEE" " will return SMC_UNK\n"); return 1; } /* * If there's no valid entry point for SP, we return a non-zero value * signalling failure initializing the service. We bail out without * registering any handlers */ if (!optee_ep_info->pc) return 1; /* * We could inspect the SP image and determine it's execution * state i.e whether AArch32 or AArch64. Assuming it's AArch32 * for the time being. */ opteed_rw = OPTEE_AARCH32; opteed_init_optee_ep_state(optee_ep_info, opteed_rw, optee_ep_info->pc, &opteed_sp_context[linear_id]); /* * All OPTEED initialization done. Now register our init function with * BL31 for deferred invocation */ bl31_register_bl32_init(&opteed_init); return 0; }
/******************************************************************************* * The following function provides a compatibility function for SPDs using the * existing cm library routines. This function is expected to be invoked for * initializing the cpu_context for the CPU specified by MPIDR for first use. ******************************************************************************/ void cm_init_context(uint64_t mpidr, const entry_point_info_t *ep) { if ((mpidr & MPIDR_AFFINITY_MASK) == (read_mpidr_el1() & MPIDR_AFFINITY_MASK)) cm_init_my_context(ep); else { /* * Suppress deprecated declaration warning in compatibility * function */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" cm_init_context_by_index(platform_get_core_pos(mpidr), ep); #pragma GCC diagnostic pop } }
/******************************************************************************* * This cpu has been turned on. ******************************************************************************/ static void tbase_cpu_on_finish_handler(uint64_t cookie) { // int32_t rc = 0; uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tbase_context *tbase_ctx = &secure_context[linear_id]; assert(tbase_ctx->state == TBASE_STATE_OFF); // Core specific initialization; tbase_init_core(mpidr); DBG_PRINTF("\r\ntbase_cpu_on_finish_handler %d\r\n", linear_id); // TODO tbase_ctx->state = TBASE_STATE_ON; }