static void tbase_status(uint64_t x1,uint64_t x2) { DBG_PRINTF( "tbase_fastcall_handler TBASE_SMC_FASTCALL_STATUS %x %x\n\r", x1, x2 ); switch(maskSWdRegister(x1)) { case TBASE_SMC_FASTCALL_STATUS_EXECUTION: tbaseExecutionStatus = maskSWdRegister(x2); TBASE_EXECUTION_STATUS(tbaseExecutionStatus); break; } }
static void output(uint64_t x1,uint64_t x2) { switch(maskSWdRegister(x1)) { case TBASE_SMC_FASTCALL_OUTPUT_PUTC: TBASE_OUTPUT_PUTC(x2&0xFF); break; } }
void configure_tbase(uint64_t x1, uint64_t x2) { uint32_t w1 = maskSWdRegister(x1); DBG_PRINTF( "tbase_fastcall_handler TBASE_SMC_FASTCALL_CONFIG_OK\n\r"); if (TBASE_SMC_FASTCALL_CONFIG_VECTOR==w1) { tbaseEntryBase = maskSWdRegister(x2); tbaseInitStatus = TBASE_INIT_CONFIG_OK; DBG_PRINTF("tbase config ok %llx %x\n\r", tbaseEntryBase, tbaseInitStatus); // Register an FIQ handler when executing in the non-secure state. uint32_t flags = 0; set_interrupt_rm_flag(flags, NON_SECURE); uint32_t rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, tbase_fiq_handler, flags); if (rc!=0) { DBG_PRINTF( "tbase_fastcall_setup FIQ register failed.\n\r"); } } else { // Just to keep compatibility for a minute tbaseEntryBase = w1; tbaseInitStatus = TBASE_INIT_CONFIG_OK; } }
// ************************************************************************************ // fastcall handler static uint64_t tbase_fastcall_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, void *cookie, void *handle, uint64_t flags) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); tbase_context *tbase_ctx = &secure_context[linear_id]; int caller_security_state = flags&1; if (caller_security_state==SECURE) { switch(maskSWdRegister(smc_fid)) { case TBASE_SMC_FASTCALL_RETURN: { // Return values from fastcall already in cpu_context! // TODO: Could we skip saving sysregs? DBG_PRINTF( "tbase_fastcall_handler TBASE_SMC_FASTCALL_RETURN\n\r"); tbase_synchronous_sp_exit(tbase_ctx, 0, 1); } case TBASE_SMC_FASTCALL_CONFIG_OK: { DBG_PRINTF( "tbase_fastcall_handler TBASE_SMC_FASTCALL_CONFIG_OK\n\r"); configure_tbase(x1,x2); SMC_RET1(handle,smc_fid); break; } case TBASE_SMC_FASTCALL_OUTPUT: { output(x1,x2); SMC_RET1(handle,smc_fid); break; } case TBASE_SMC_FASTCALL_STATUS: { DBG_PRINTF( "tbase_fastcall_handler TBASE_SMC_FASTCALL_STATUS\n\r"); tbase_status(x1,x2); SMC_RET1(handle,smc_fid); break; } case TBASE_SMC_FASTCALL_INPUT: { DBG_PRINTF( "tbase_fastcall_handler TBASE_SMC_FASTCALL_INPUT\n\r"); smc_fid = plat_tbase_input(x1,&x2,&(tbase_ctx->tbase_input_fastcall)); SMC_RET3(handle,smc_fid,page_align(registerFileEnd[REGISTER_FILE_NWD] - registerFileStart[REGISTER_FILE_NWD], UP)+(uint64_t)&(tbase_ctx->tbase_input_fastcall)- registerFileStart[REGISTER_FILE_MONITOR],x2); break; } case TBASE_SMC_FASTCALL_DUMP: { DBG_PRINTF( "tbase_fastcall_handler TBASE_SMC_FASTCALL_DUMP\n\r"); tbase_triggerSgiDump(); SMC_RET1(handle,smc_fid); break; } default: { // What now? DBG_PRINTF( "tbase_fastcall_handler SMC_UNK %x\n\r", smc_fid ); SMC_RET1(handle, SMC_UNK); break; } } } else { if (smc_fid == TBASE_SMC_AEE_DUMP) // N-world can request AEE Dump function { mt_atf_trigger_WDT_FIQ(); // Once we return to the N-world's caller, // FIQ will be trigged and bring us on EL3 (ATF) on core #0 because HW wiring. // Then FIQ will be handled the same way as for HW WDT FIQ. //Do we need to save-recover n-context before being able to use it for return? cm_el1_sysregs_context_restore(NON_SECURE); cm_set_next_eret_context(NON_SECURE); return 0; } if ((tbaseExecutionStatus&TBASE_STATUS_FASTCALL_OK_BIT)==0) { // TBASE must be initialized to be usable // TODO: What is correct error code? DBG_PRINTF( "tbase_fastcall_handler tbase not ready for fastcall\n\r" ); SMC_RET1(handle, SMC_UNK); return 0; } if(tbase_ctx->state == TBASE_STATE_OFF) { DBG_PRINTF( "tbase_fastcall_handler tbase not ready for fastcall\n\r" ); SMC_RET1(handle, SMC_UNK); return 0; } DBG_PRINTF( "tbase_fastcall_handler NWd %x\n\r", smc_fid ); // So far all fastcalls go to tbase // Save NWd context gp_regs_t *ns_gpregs = get_gpregs_ctx((cpu_context_t *)handle); write_ctx_reg(ns_gpregs, CTX_GPREG_X0, smc_fid ); // These are not saved yet write_ctx_reg(ns_gpregs, CTX_GPREG_X1, x1 ); write_ctx_reg(ns_gpregs, CTX_GPREG_X2, x2 ); write_ctx_reg(ns_gpregs, CTX_GPREG_X3, x3 ); cm_el1_sysregs_context_save(NON_SECURE); // Load SWd context tbase_setup_entry_nwd((cpu_context_t *)handle,ENTRY_OFFSET_FASTCALL); #if DEBUG print_fastcall_params("entry", NON_SECURE); #endif tbase_synchronous_sp_entry(tbase_ctx); cm_el1_sysregs_context_restore(NON_SECURE); cm_set_next_eret_context(NON_SECURE); return 0; // Does not seem to matter what we return } }