void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target) { #if GICV2_G0_FOR_EL3 int id; /* Target must be a valid MPIDR in the system */ id = plat_core_pos_by_mpidr(target); assert(id >= 0); /* Verify that this is a secure SGI */ assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_EL3); gicv2_raise_sgi(sgi_num, id); #else assert(false); #endif }
/******************************************************************************* * This function is the handler registered for S-EL1 interrupts by the * OPTEED. It validates the interrupt and upon success arranges entry into * the OPTEE at 'optee_fiq_entry()' for handling the interrupt. ******************************************************************************/ static uint64_t opteed_sel1_interrupt_handler(uint32_t id, uint32_t flags, void *handle, void *cookie) { uint32_t linear_id; uint64_t mpidr; optee_context_t *optee_ctx; /* Check the security state when the exception was generated */ assert(get_interrupt_src_ss(flags) == NON_SECURE); #if IMF_READ_INTERRUPT_ID /* Check the security status of the interrupt */ assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_S_EL1); #endif /* Sanity check the pointer to this cpu's context */ mpidr = read_mpidr(); assert(handle == cm_get_context(NON_SECURE)); /* Save the non-secure context before entering the OPTEE */ cm_el1_sysregs_context_save(NON_SECURE); /* Get a reference to this cpu's OPTEE context */ linear_id = platform_get_core_pos(mpidr); optee_ctx = &opteed_sp_context[linear_id]; assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE)); cm_set_elr_el3(SECURE, (uint64_t)&optee_vectors->fiq_entry); cm_el1_sysregs_context_restore(SECURE); cm_set_next_eret_context(SECURE); /* * Tell the OPTEE that it has to handle an FIQ (synchronously). * Also the instruction in normal world where the interrupt was * generated is passed for debugging purposes. It is safe to * retrieve this address from ELR_EL3 as the secure context will * not take effect until el3_exit(). */ SMC_RET1(&optee_ctx->cpu_ctx, read_elr_el3()); }
/******************************************************************************* * This function is the handler registered for S-EL1 interrupts by the TSPD. It * validates the interrupt and upon success arranges entry into the TSP at * 'tsp_fiq_entry()' for handling the interrupt. ******************************************************************************/ static uint64_t tspd_ns_interrupt_handler(uint32_t id, uint32_t flags, void *handle, void *cookie) { /* Check the security state when the exception was generated */ assert(get_interrupt_src_ss(flags) == SECURE); #if IMF_READ_INTERRUPT_ID /* Check the security status of the interrupt */ assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_NS); #endif /* * Disable the routing of NS interrupts from secure world to EL3 while * interrupted on this core. */ disable_intr_rm_local(INTR_TYPE_NS, SECURE); return tspd_handle_sp_preemption(handle); }
/******************************************************************************* * This function is the handler registered for S-EL1 interrupts by the TSPD. It * validates the interrupt and upon success arranges entry into the TSP at * 'tsp_fiq_entry()' for handling the interrupt. ******************************************************************************/ static uint64_t tspd_sel1_interrupt_handler(uint32_t id, uint32_t flags, void *handle, void *cookie) { uint32_t linear_id; tsp_context_t *tsp_ctx; /* Check the security state when the exception was generated */ assert(get_interrupt_src_ss(flags) == NON_SECURE); #if IMF_READ_INTERRUPT_ID /* Check the security status of the interrupt */ assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_S_EL1); #endif /* Sanity check the pointer to this cpu's context */ assert(handle == cm_get_context(NON_SECURE)); /* Save the non-secure context before entering the TSP */ cm_el1_sysregs_context_save(NON_SECURE); /* Get a reference to this cpu's TSP context */ linear_id = plat_my_core_pos(); tsp_ctx = &tspd_sp_context[linear_id]; assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE)); /* * Determine if the TSP was previously preempted. Its last known * context has to be preserved in this case. * The TSP should return control to the TSPD after handling this * FIQ. Preserve essential EL3 context to allow entry into the * TSP at the FIQ entry point using the 'cpu_context' structure. * There is no need to save the secure system register context * since the TSP is supposed to preserve it during S-EL1 interrupt * handling. */ if (get_std_smc_active_flag(tsp_ctx->state)) { tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx, CTX_SPSR_EL3); tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx, CTX_ELR_EL3); #if TSPD_ROUTE_IRQ_TO_EL3 /*Need to save the previously interrupted secure context */ memcpy(&tsp_ctx->sp_ctx, &tsp_ctx->cpu_ctx, TSPD_SP_CTX_SIZE); #endif } cm_el1_sysregs_context_restore(SECURE); cm_set_elr_spsr_el3(SECURE, (uint64_t) &tsp_vectors->fiq_entry, SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS)); cm_set_next_eret_context(SECURE); /* * Tell the TSP that it has to handle an FIQ synchronously. Also the * instruction in normal world where the interrupt was generated is * passed for debugging purposes. It is safe to retrieve this address * from ELR_EL3 as the secure context will not take effect until * el3_exit(). */ SMC_RET2(&tsp_ctx->cpu_ctx, TSP_HANDLE_FIQ_AND_RETURN, read_elr_el3()); }
/******************************************************************************* * This function is the handler registered for S-EL1 interrupts by the FIQD. It * validates the interrupt and upon success arranges entry into the TSP at * 'tsp_fiq_entry()' for handling the interrupt. ******************************************************************************/ static uint64_t fiqd_sel1_interrupt_handler(uint32_t id, uint32_t flags, void *handle, void *cookie) { unsigned int iar; /* Check the security state when the exception was generated */ assert(get_interrupt_src_ss(flags) == NON_SECURE); #if IMF_READ_INTERRUPT_ID /* Check the security status of the interrupt */ assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_S_EL1); #endif /* Sanity check the pointer to this cpu's context */ assert(handle == cm_get_context(NON_SECURE)); /* Save the non-secure context before entering the TSP */ cm_el1_sysregs_context_save(NON_SECURE); iar = get_ack_info(); ack_sgi(iar); if(id == WDT_IRQ_BIT_ID) { /* FIX-ME : change 0xFE to the kernel online CPU mask */ fiq_smp_call_function(0xFE, aee_wdt_dump, 0, 0); aee_wdt_dump(); } if(id == FIQ_SMP_CALL_SGI) { fiq_icc_isr(); } SMC_RET0(handle); #if 0 /* Get a reference to this cpu's TSP context */ linear_id = platform_get_core_pos(mpidr); tsp_ctx = &fiqd_sp_context[linear_id]; assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE)); /* * Determine if the TSP was previously preempted. Its last known * context has to be preserved in this case. * The TSP should return control to the FIQD after handling this * FIQ. Preserve essential EL3 context to allow entry into the * TSP at the FIQ entry point using the 'cpu_context' structure. * There is no need to save the secure system register context * since the TSP is supposed to preserve it during S-EL1 interrupt * handling. */ if (get_std_smc_active_flag(tsp_ctx->state)) { tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx, CTX_SPSR_EL3); tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx, CTX_ELR_EL3); } cm_el1_sysregs_context_restore(SECURE); cm_set_elr_spsr_el3(SECURE, (uint64_t) &tsp_vectors->fiq_entry, SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS)); cm_set_next_eret_context(SECURE); /* * Tell the TSP that it has to handle an FIQ synchronously. Also the * instruction in normal world where the interrupt was generated is * passed for debugging purposes. It is safe to retrieve this address * from ELR_EL3 as the secure context will not take effect until * el3_exit(). */ SMC_RET2(&tsp_ctx->cpu_ctx, TSP_HANDLE_FIQ_AND_RETURN, read_elr_el3()); #endif }