diff --git a/include/bl32/payloads/tlk.h b/include/bl32/payloads/tlk.h index d9fa794..b6299a8 100644 --- a/include/bl32/payloads/tlk.h +++ b/include/bl32/payloads/tlk.h @@ -32,9 +32,21 @@ #define __TLK_H__ /* + * Generate function IDs for the Trusted OS/Apps + */ +#define TLK_TOS_STD_FID(fid) ((fid) | 0x72000000 | (0 << 31)) + +/* + * Trusted OS specific function IDs + */ +#define TLK_REGISTER_LOGBUF TLK_TOS_STD_FID(0x1) +#define TLK_REGISTER_REQBUF TLK_TOS_STD_FID(0x2) + +/* * SMC function IDs that TLK uses to signal various forms of completions * to the secure payload dispatcher. */ +#define TLK_REQUEST_DONE (0x32000001 | (1 << 31)) #define TLK_ENTRY_DONE (0x32000003 | (1 << 31)) #define TLK_FID_SHARED_MEMBUF (0x32000005 | (1 << 31)) diff --git a/services/spd/tlkd/tlkd_main.c b/services/spd/tlkd/tlkd_main.c index 65466aa..8d2d437 100644 --- a/services/spd/tlkd/tlkd_main.c +++ b/services/spd/tlkd/tlkd_main.c @@ -186,6 +186,7 @@ void *handle, uint64_t flags) { + cpu_context_t *ns_cpu_context; uint32_t ns; /* Passing a NULL context is a critical programming error */ @@ -197,11 +198,91 @@ switch (smc_fid) { /* + * This is a request from the non-secure context to: + * + * a. register shared memory with the SP for storing it's + * activity logs. + * b. register shared memory with the SP for passing args + * required for maintaining sessions with the Trusted + * Applications. + */ + case TLK_REGISTER_LOGBUF: + case TLK_REGISTER_REQBUF: + if (!ns || !tlk_args_results_buf) + SMC_RET1(handle, SMC_UNK); + + /* + * This is a fresh request from the non-secure client. + * The parameters are in x1 and x2. Figure out which + * registers need to be preserved, save the non-secure + * state and send the request to the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Check if we are already preempted */ + if (get_std_smc_active_flag(tlk_ctx.state)) + SMC_RET1(handle, SMC_UNK); + + cm_el1_sysregs_context_save(NON_SECURE); + + /* + * Verify if there is a valid context to use. + */ + assert(&tlk_ctx.cpu_ctx == cm_get_context(SECURE)); + + /* + * Mark the SP state as active. + */ + set_std_smc_active_flag(tlk_ctx.state); + + /* Save args for use by the SP on return */ + store_tlk_args_results(smc_fid, x1, x2, x3); + + /* + * We are done stashing the non-secure context. Ask the + * secure payload to do the work now. + */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + SMC_RET0(&tlk_ctx.cpu_ctx); + + /* + * This is a request from the SP to mark completion of + * a standard function ID. + */ + case TLK_REQUEST_DONE: + if (ns || !tlk_args_results_buf) + SMC_RET1(handle, SMC_UNK); + + /* + * Mark the SP state as inactive. + */ + clr_std_smc_active_flag(tlk_ctx.state); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * This is a request completion SMC and we must switch to + * the non-secure world to pass the result. + */ + cm_el1_sysregs_context_save(SECURE); + + /* + * We are done stashing the secure context. Switch to the + * non-secure context and return the result. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + SMC_RET1(ns_cpu_context, tlk_args_results_buf->args[0]); + + /* * This function ID is used only by the SP to indicate it has * finished initialising itself after a cold boot */ case TLK_ENTRY_DONE: - if (ns) + if (ns || !tlk_args_results_buf) SMC_RET1(handle, SMC_UNK); /*