122038315SVarun Wadekar /* 222038315SVarun Wadekar * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 322038315SVarun Wadekar * 422038315SVarun Wadekar * Redistribution and use in source and binary forms, with or without 522038315SVarun Wadekar * modification, are permitted provided that the following conditions are met: 622038315SVarun Wadekar * 722038315SVarun Wadekar * Redistributions of source code must retain the above copyright notice, this 822038315SVarun Wadekar * list of conditions and the following disclaimer. 922038315SVarun Wadekar * 1022038315SVarun Wadekar * Redistributions in binary form must reproduce the above copyright notice, 1122038315SVarun Wadekar * this list of conditions and the following disclaimer in the documentation 1222038315SVarun Wadekar * and/or other materials provided with the distribution. 1322038315SVarun Wadekar * 1422038315SVarun Wadekar * Neither the name of ARM nor the names of its contributors may be used 1522038315SVarun Wadekar * to endorse or promote products derived from this software without specific 1622038315SVarun Wadekar * prior written permission. 1722038315SVarun Wadekar * 1822038315SVarun Wadekar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1922038315SVarun Wadekar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2022038315SVarun Wadekar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2122038315SVarun Wadekar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2222038315SVarun Wadekar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2322038315SVarun Wadekar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2422038315SVarun Wadekar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2522038315SVarun Wadekar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2622038315SVarun Wadekar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2722038315SVarun Wadekar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2822038315SVarun Wadekar * POSSIBILITY OF SUCH DAMAGE. 2922038315SVarun Wadekar */ 3022038315SVarun Wadekar 3122038315SVarun Wadekar /******************************************************************************* 3222038315SVarun Wadekar * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a 3322038315SVarun Wadekar * plug-in component to the Secure Monitor, registered as a runtime service. The 3422038315SVarun Wadekar * SPD is expected to be a functional extension of the Secure Payload (SP) that 3522038315SVarun Wadekar * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting 3622038315SVarun Wadekar * the Trusted OS/Applications range to the dispatcher. The SPD will either 3722038315SVarun Wadekar * handle the request locally or delegate it to the Secure Payload. It is also 3822038315SVarun Wadekar * responsible for initialising and maintaining communication with the SP. 3922038315SVarun Wadekar ******************************************************************************/ 4022038315SVarun Wadekar #include <arch_helpers.h> 4122038315SVarun Wadekar #include <assert.h> 4222038315SVarun Wadekar #include <bl_common.h> 4322038315SVarun Wadekar #include <bl31.h> 4422038315SVarun Wadekar #include <context_mgmt.h> 4522038315SVarun Wadekar #include <debug.h> 4622038315SVarun Wadekar #include <errno.h> 4722038315SVarun Wadekar #include <platform.h> 4822038315SVarun Wadekar #include <runtime_svc.h> 4922038315SVarun Wadekar #include <stddef.h> 5022038315SVarun Wadekar #include <tlk.h> 5122038315SVarun Wadekar #include <uuid.h> 5222038315SVarun Wadekar #include "tlkd_private.h" 5322038315SVarun Wadekar 5422038315SVarun Wadekar extern const spd_pm_ops_t tlkd_pm_ops; 5522038315SVarun Wadekar 5622038315SVarun Wadekar /******************************************************************************* 5722038315SVarun Wadekar * Array to keep track of per-cpu Secure Payload state 5822038315SVarun Wadekar ******************************************************************************/ 5922038315SVarun Wadekar static tlk_context_t tlk_ctx; 6022038315SVarun Wadekar 6122038315SVarun Wadekar /* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */ 6222038315SVarun Wadekar DEFINE_SVC_UUID(tlk_uuid, 6322038315SVarun Wadekar 0xbd11e9c9, 0x2bba, 0x52ee, 0xb1, 0x72, 6422038315SVarun Wadekar 0x46, 0x1f, 0xba, 0x97, 0x7f, 0x63); 6522038315SVarun Wadekar 6622038315SVarun Wadekar int32_t tlkd_init(void); 6722038315SVarun Wadekar 6822038315SVarun Wadekar /* 6922038315SVarun Wadekar * The number of arguments/results to save during a SMC call for TLK. 7022038315SVarun Wadekar */ 7122038315SVarun Wadekar #define TLK_SHDBUF_SIZE 4 7222038315SVarun Wadekar 7322038315SVarun Wadekar /******************************************************************************* 7422038315SVarun Wadekar * Shared memory buffer for passing SMC args/results to TLK 7522038315SVarun Wadekar ******************************************************************************/ 7622038315SVarun Wadekar typedef struct tlk_args_results { 7722038315SVarun Wadekar uint64_t args[TLK_SHDBUF_SIZE]; 7822038315SVarun Wadekar } tlk_args_results_t; 7922038315SVarun Wadekar 8022038315SVarun Wadekar static tlk_args_results_t *tlk_args_results_buf; 8122038315SVarun Wadekar 8222038315SVarun Wadekar /* 8322038315SVarun Wadekar * Helper function to store args from TLK and pass results back 8422038315SVarun Wadekar */ 8522038315SVarun Wadekar static inline void store_tlk_args_results(uint64_t x0, uint64_t x1, uint64_t x2, 8622038315SVarun Wadekar uint64_t x3) 8722038315SVarun Wadekar { 8822038315SVarun Wadekar /* store arguments sent by TLK */ 8922038315SVarun Wadekar tlk_args_results_buf->args[0] = x0; 9022038315SVarun Wadekar tlk_args_results_buf->args[1] = x1; 9122038315SVarun Wadekar tlk_args_results_buf->args[2] = x2; 9222038315SVarun Wadekar tlk_args_results_buf->args[3] = x3; 9322038315SVarun Wadekar 9422038315SVarun Wadekar flush_dcache_range((uint64_t)tlk_args_results_buf, 9522038315SVarun Wadekar sizeof(tlk_args_results_t)); 9622038315SVarun Wadekar } 9722038315SVarun Wadekar 9822038315SVarun Wadekar /******************************************************************************* 9922038315SVarun Wadekar * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type 10022038315SVarun Wadekar * (aarch32/aarch64) if not already known and initialises the context for entry 10122038315SVarun Wadekar * into the SP for its initialisation. 10222038315SVarun Wadekar ******************************************************************************/ 10322038315SVarun Wadekar int32_t tlkd_setup(void) 10422038315SVarun Wadekar { 10522038315SVarun Wadekar entry_point_info_t *tlk_ep_info; 10622038315SVarun Wadekar 10722038315SVarun Wadekar /* 10822038315SVarun Wadekar * Get information about the Secure Payload (BL32) image. Its 10922038315SVarun Wadekar * absence is a critical failure. 11022038315SVarun Wadekar */ 11122038315SVarun Wadekar tlk_ep_info = bl31_plat_get_next_image_ep_info(SECURE); 11222038315SVarun Wadekar if (!tlk_ep_info) { 11322038315SVarun Wadekar WARN("No SP provided. Booting device without SP" 11422038315SVarun Wadekar " initialization. SMC`s destined for SP" 11522038315SVarun Wadekar " will return SMC_UNK\n"); 11622038315SVarun Wadekar return 1; 11722038315SVarun Wadekar } 11822038315SVarun Wadekar 11922038315SVarun Wadekar /* 12022038315SVarun Wadekar * If there's no valid entry point for SP, we return a non-zero value 12122038315SVarun Wadekar * signalling failure initializing the service. We bail out without 12222038315SVarun Wadekar * registering any handlers 12322038315SVarun Wadekar */ 12422038315SVarun Wadekar if (!tlk_ep_info->pc) 12522038315SVarun Wadekar return 1; 12622038315SVarun Wadekar 12722038315SVarun Wadekar /* 12822038315SVarun Wadekar * Inspect the SP image's SPSR and determine it's execution state 12922038315SVarun Wadekar * i.e whether AArch32 or AArch64. 13022038315SVarun Wadekar */ 13122038315SVarun Wadekar tlkd_init_tlk_ep_state(tlk_ep_info, 13222038315SVarun Wadekar (tlk_ep_info->spsr >> MODE_RW_SHIFT) & MODE_RW_MASK, 13322038315SVarun Wadekar tlk_ep_info->pc, 13422038315SVarun Wadekar &tlk_ctx); 13522038315SVarun Wadekar 13622038315SVarun Wadekar /* 13722038315SVarun Wadekar * All TLK SPD initialization done. Now register our init function 13822038315SVarun Wadekar * with BL31 for deferred invocation 13922038315SVarun Wadekar */ 14022038315SVarun Wadekar bl31_register_bl32_init(&tlkd_init); 14122038315SVarun Wadekar 14222038315SVarun Wadekar return 0; 14322038315SVarun Wadekar } 14422038315SVarun Wadekar 14522038315SVarun Wadekar /******************************************************************************* 14622038315SVarun Wadekar * This function passes control to the Secure Payload image (BL32) for the first 14722038315SVarun Wadekar * time on the primary cpu after a cold boot. It assumes that a valid secure 14822038315SVarun Wadekar * context has already been created by tlkd_setup() which can be directly 14922038315SVarun Wadekar * used. This function performs a synchronous entry into the Secure payload. 15022038315SVarun Wadekar * The SP passes control back to this routine through a SMC. 15122038315SVarun Wadekar ******************************************************************************/ 15222038315SVarun Wadekar int32_t tlkd_init(void) 15322038315SVarun Wadekar { 15422038315SVarun Wadekar uint64_t mpidr = read_mpidr(); 15522038315SVarun Wadekar entry_point_info_t *tlk_entry_point; 15622038315SVarun Wadekar 15722038315SVarun Wadekar /* 15822038315SVarun Wadekar * Get information about the Secure Payload (BL32) image. Its 15922038315SVarun Wadekar * absence is a critical failure. 16022038315SVarun Wadekar */ 16122038315SVarun Wadekar tlk_entry_point = bl31_plat_get_next_image_ep_info(SECURE); 16222038315SVarun Wadekar assert(tlk_entry_point); 16322038315SVarun Wadekar 16422038315SVarun Wadekar cm_init_context(mpidr, tlk_entry_point); 16522038315SVarun Wadekar 16622038315SVarun Wadekar /* 16722038315SVarun Wadekar * Arrange for an entry into the test secure payload. 16822038315SVarun Wadekar */ 16922038315SVarun Wadekar return tlkd_synchronous_sp_entry(&tlk_ctx); 17022038315SVarun Wadekar } 17122038315SVarun Wadekar 17222038315SVarun Wadekar /******************************************************************************* 17322038315SVarun Wadekar * This function is responsible for handling all SMCs in the Trusted OS/App 17422038315SVarun Wadekar * range from the non-secure state as defined in the SMC Calling Convention 17522038315SVarun Wadekar * Document. It is also responsible for communicating with the Secure payload 17622038315SVarun Wadekar * to delegate work and return results back to the non-secure state. Lastly it 17722038315SVarun Wadekar * will also return any information that the secure payload needs to do the 17822038315SVarun Wadekar * work assigned to it. 17922038315SVarun Wadekar ******************************************************************************/ 18022038315SVarun Wadekar uint64_t tlkd_smc_handler(uint32_t smc_fid, 18122038315SVarun Wadekar uint64_t x1, 18222038315SVarun Wadekar uint64_t x2, 18322038315SVarun Wadekar uint64_t x3, 18422038315SVarun Wadekar uint64_t x4, 18522038315SVarun Wadekar void *cookie, 18622038315SVarun Wadekar void *handle, 18722038315SVarun Wadekar uint64_t flags) 18822038315SVarun Wadekar { 18977199df7SVarun Wadekar cpu_context_t *ns_cpu_context; 19022038315SVarun Wadekar uint32_t ns; 1916e159e7aSVarun Wadekar uint64_t vaddr, type, par; 19222038315SVarun Wadekar 19322038315SVarun Wadekar /* Passing a NULL context is a critical programming error */ 19422038315SVarun Wadekar assert(handle); 19522038315SVarun Wadekar 196*6693962cSVarun Wadekar /* These SMCs are only supported by CPU0 */ 197*6693962cSVarun Wadekar if ((read_mpidr() & MPIDR_CPU_MASK) != 0) 198*6693962cSVarun Wadekar SMC_RET1(handle, SMC_UNK); 199*6693962cSVarun Wadekar 20022038315SVarun Wadekar /* Determine which security state this SMC originated from */ 20122038315SVarun Wadekar ns = is_caller_non_secure(flags); 20222038315SVarun Wadekar 20322038315SVarun Wadekar switch (smc_fid) { 20422038315SVarun Wadekar 20522038315SVarun Wadekar /* 206f9d25054SVarun Wadekar * This function ID is used by SP to indicate that it was 207f9d25054SVarun Wadekar * preempted by a non-secure world IRQ. 208f9d25054SVarun Wadekar */ 209f9d25054SVarun Wadekar case TLK_PREEMPTED: 210f9d25054SVarun Wadekar 211f9d25054SVarun Wadekar if (ns) 212f9d25054SVarun Wadekar SMC_RET1(handle, SMC_UNK); 213f9d25054SVarun Wadekar 214f9d25054SVarun Wadekar assert(handle == cm_get_context(SECURE)); 215f9d25054SVarun Wadekar cm_el1_sysregs_context_save(SECURE); 216f9d25054SVarun Wadekar 217f9d25054SVarun Wadekar /* Get a reference to the non-secure context */ 218f9d25054SVarun Wadekar ns_cpu_context = cm_get_context(NON_SECURE); 219f9d25054SVarun Wadekar assert(ns_cpu_context); 220f9d25054SVarun Wadekar 221f9d25054SVarun Wadekar /* 222f9d25054SVarun Wadekar * Restore non-secure state. There is no need to save the 223f9d25054SVarun Wadekar * secure system register context since the SP was supposed 224f9d25054SVarun Wadekar * to preserve it during S-EL1 interrupt handling. 225f9d25054SVarun Wadekar */ 226f9d25054SVarun Wadekar cm_el1_sysregs_context_restore(NON_SECURE); 227f9d25054SVarun Wadekar cm_set_next_eret_context(NON_SECURE); 228f9d25054SVarun Wadekar 229f9d25054SVarun Wadekar SMC_RET1(ns_cpu_context, tlk_args_results_buf->args[0]); 230f9d25054SVarun Wadekar 231f9d25054SVarun Wadekar /* 232f9d25054SVarun Wadekar * Request from non secure world to resume the preempted 233f9d25054SVarun Wadekar * Standard SMC call. 234f9d25054SVarun Wadekar */ 235f9d25054SVarun Wadekar case TLK_RESUME_FID: 236f9d25054SVarun Wadekar 237f9d25054SVarun Wadekar /* RESUME should be invoked only by normal world */ 238f9d25054SVarun Wadekar if (!ns) 239f9d25054SVarun Wadekar SMC_RET1(handle, SMC_UNK); 240f9d25054SVarun Wadekar 241f9d25054SVarun Wadekar /* 242f9d25054SVarun Wadekar * This is a resume request from the non-secure client. 243f9d25054SVarun Wadekar * save the non-secure state and send the request to 244f9d25054SVarun Wadekar * the secure payload. 245f9d25054SVarun Wadekar */ 246f9d25054SVarun Wadekar assert(handle == cm_get_context(NON_SECURE)); 247f9d25054SVarun Wadekar 248f9d25054SVarun Wadekar /* Check if we are already preempted before resume */ 249f9d25054SVarun Wadekar if (!get_std_smc_active_flag(tlk_ctx.state)) 250f9d25054SVarun Wadekar SMC_RET1(handle, SMC_UNK); 251f9d25054SVarun Wadekar 252f9d25054SVarun Wadekar cm_el1_sysregs_context_save(NON_SECURE); 253f9d25054SVarun Wadekar 254f9d25054SVarun Wadekar /* 255f9d25054SVarun Wadekar * We are done stashing the non-secure context. Ask the 256f9d25054SVarun Wadekar * secure payload to do the work now. 257f9d25054SVarun Wadekar */ 258f9d25054SVarun Wadekar 259f9d25054SVarun Wadekar /* We just need to return to the preempted point in 260f9d25054SVarun Wadekar * SP and the execution will resume as normal. 261f9d25054SVarun Wadekar */ 262f9d25054SVarun Wadekar cm_el1_sysregs_context_restore(SECURE); 263f9d25054SVarun Wadekar cm_set_next_eret_context(SECURE); 264f9d25054SVarun Wadekar SMC_RET0(handle); 265f9d25054SVarun Wadekar 266f9d25054SVarun Wadekar /* 26777199df7SVarun Wadekar * This is a request from the non-secure context to: 26877199df7SVarun Wadekar * 26977199df7SVarun Wadekar * a. register shared memory with the SP for storing it's 27077199df7SVarun Wadekar * activity logs. 27177199df7SVarun Wadekar * b. register shared memory with the SP for passing args 27277199df7SVarun Wadekar * required for maintaining sessions with the Trusted 27377199df7SVarun Wadekar * Applications. 274*6693962cSVarun Wadekar * c. open/close sessions 275*6693962cSVarun Wadekar * d. issue commands to the Trusted Apps 27677199df7SVarun Wadekar */ 27777199df7SVarun Wadekar case TLK_REGISTER_LOGBUF: 27877199df7SVarun Wadekar case TLK_REGISTER_REQBUF: 279*6693962cSVarun Wadekar case TLK_OPEN_TA_SESSION: 280*6693962cSVarun Wadekar case TLK_CLOSE_TA_SESSION: 281*6693962cSVarun Wadekar case TLK_TA_LAUNCH_OP: 282*6693962cSVarun Wadekar case TLK_TA_SEND_EVENT: 283*6693962cSVarun Wadekar 28477199df7SVarun Wadekar if (!ns || !tlk_args_results_buf) 28577199df7SVarun Wadekar SMC_RET1(handle, SMC_UNK); 28677199df7SVarun Wadekar 28777199df7SVarun Wadekar /* 28877199df7SVarun Wadekar * This is a fresh request from the non-secure client. 28977199df7SVarun Wadekar * The parameters are in x1 and x2. Figure out which 29077199df7SVarun Wadekar * registers need to be preserved, save the non-secure 29177199df7SVarun Wadekar * state and send the request to the secure payload. 29277199df7SVarun Wadekar */ 29377199df7SVarun Wadekar assert(handle == cm_get_context(NON_SECURE)); 29477199df7SVarun Wadekar 29577199df7SVarun Wadekar /* Check if we are already preempted */ 29677199df7SVarun Wadekar if (get_std_smc_active_flag(tlk_ctx.state)) 29777199df7SVarun Wadekar SMC_RET1(handle, SMC_UNK); 29877199df7SVarun Wadekar 29977199df7SVarun Wadekar cm_el1_sysregs_context_save(NON_SECURE); 30077199df7SVarun Wadekar 30177199df7SVarun Wadekar /* 30277199df7SVarun Wadekar * Verify if there is a valid context to use. 30377199df7SVarun Wadekar */ 30477199df7SVarun Wadekar assert(&tlk_ctx.cpu_ctx == cm_get_context(SECURE)); 30577199df7SVarun Wadekar 30677199df7SVarun Wadekar /* 30777199df7SVarun Wadekar * Mark the SP state as active. 30877199df7SVarun Wadekar */ 30977199df7SVarun Wadekar set_std_smc_active_flag(tlk_ctx.state); 31077199df7SVarun Wadekar 31177199df7SVarun Wadekar /* Save args for use by the SP on return */ 31277199df7SVarun Wadekar store_tlk_args_results(smc_fid, x1, x2, x3); 31377199df7SVarun Wadekar 31477199df7SVarun Wadekar /* 31577199df7SVarun Wadekar * We are done stashing the non-secure context. Ask the 31677199df7SVarun Wadekar * secure payload to do the work now. 31777199df7SVarun Wadekar */ 31877199df7SVarun Wadekar cm_el1_sysregs_context_restore(SECURE); 31977199df7SVarun Wadekar cm_set_next_eret_context(SECURE); 32077199df7SVarun Wadekar SMC_RET0(&tlk_ctx.cpu_ctx); 32177199df7SVarun Wadekar 32277199df7SVarun Wadekar /* 3236e159e7aSVarun Wadekar * Translate NS/EL1-S virtual addresses 3246e159e7aSVarun Wadekar */ 3256e159e7aSVarun Wadekar case TLK_VA_TRANSLATE: 3266e159e7aSVarun Wadekar if (ns || !tlk_args_results_buf) 3276e159e7aSVarun Wadekar SMC_RET1(handle, SMC_UNK); 3286e159e7aSVarun Wadekar 3296e159e7aSVarun Wadekar /* virtual address and type: ns/s */ 3306e159e7aSVarun Wadekar vaddr = tlk_args_results_buf->args[0]; 3316e159e7aSVarun Wadekar type = tlk_args_results_buf->args[1]; 3326e159e7aSVarun Wadekar 3336e159e7aSVarun Wadekar par = tlkd_va_translate(vaddr, type); 3346e159e7aSVarun Wadekar 3356e159e7aSVarun Wadekar /* Save PA for use by the SP on return */ 3366e159e7aSVarun Wadekar store_tlk_args_results(par, 0, 0, 0); 3376e159e7aSVarun Wadekar 3386e159e7aSVarun Wadekar SMC_RET0(handle); 3396e159e7aSVarun Wadekar 3406e159e7aSVarun Wadekar /* 34177199df7SVarun Wadekar * This is a request from the SP to mark completion of 34277199df7SVarun Wadekar * a standard function ID. 34377199df7SVarun Wadekar */ 34477199df7SVarun Wadekar case TLK_REQUEST_DONE: 34577199df7SVarun Wadekar if (ns || !tlk_args_results_buf) 34677199df7SVarun Wadekar SMC_RET1(handle, SMC_UNK); 34777199df7SVarun Wadekar 34877199df7SVarun Wadekar /* 34977199df7SVarun Wadekar * Mark the SP state as inactive. 35077199df7SVarun Wadekar */ 35177199df7SVarun Wadekar clr_std_smc_active_flag(tlk_ctx.state); 35277199df7SVarun Wadekar 35377199df7SVarun Wadekar /* Get a reference to the non-secure context */ 35477199df7SVarun Wadekar ns_cpu_context = cm_get_context(NON_SECURE); 35577199df7SVarun Wadekar assert(ns_cpu_context); 35677199df7SVarun Wadekar 35777199df7SVarun Wadekar /* 35877199df7SVarun Wadekar * This is a request completion SMC and we must switch to 35977199df7SVarun Wadekar * the non-secure world to pass the result. 36077199df7SVarun Wadekar */ 36177199df7SVarun Wadekar cm_el1_sysregs_context_save(SECURE); 36277199df7SVarun Wadekar 36377199df7SVarun Wadekar /* 36477199df7SVarun Wadekar * We are done stashing the secure context. Switch to the 36577199df7SVarun Wadekar * non-secure context and return the result. 36677199df7SVarun Wadekar */ 36777199df7SVarun Wadekar cm_el1_sysregs_context_restore(NON_SECURE); 36877199df7SVarun Wadekar cm_set_next_eret_context(NON_SECURE); 36977199df7SVarun Wadekar SMC_RET1(ns_cpu_context, tlk_args_results_buf->args[0]); 37077199df7SVarun Wadekar 37177199df7SVarun Wadekar /* 37222038315SVarun Wadekar * This function ID is used only by the SP to indicate it has 37322038315SVarun Wadekar * finished initialising itself after a cold boot 37422038315SVarun Wadekar */ 37522038315SVarun Wadekar case TLK_ENTRY_DONE: 37677199df7SVarun Wadekar if (ns || !tlk_args_results_buf) 37722038315SVarun Wadekar SMC_RET1(handle, SMC_UNK); 37822038315SVarun Wadekar 37922038315SVarun Wadekar /* 38022038315SVarun Wadekar * SP has been successfully initialized. Register power 38122038315SVarun Wadekar * managemnt hooks with PSCI 38222038315SVarun Wadekar */ 38322038315SVarun Wadekar psci_register_spd_pm_hook(&tlkd_pm_ops); 38422038315SVarun Wadekar 38522038315SVarun Wadekar /* 38622038315SVarun Wadekar * TLK reports completion. The SPD must have initiated 38722038315SVarun Wadekar * the original request through a synchronous entry 38822038315SVarun Wadekar * into the SP. Jump back to the original C runtime 38922038315SVarun Wadekar * context. 39022038315SVarun Wadekar */ 39122038315SVarun Wadekar tlkd_synchronous_sp_exit(&tlk_ctx, tlk_args_results_buf->args[0]); 39222038315SVarun Wadekar 39322038315SVarun Wadekar /* 39422038315SVarun Wadekar * This is a request from the secure payload to register 39522038315SVarun Wadekar * shared memory to pass SMC args/results between EL1, EL3. 39622038315SVarun Wadekar */ 39722038315SVarun Wadekar case TLK_FID_SHARED_MEMBUF: 39822038315SVarun Wadekar if (ns || !x1) 39922038315SVarun Wadekar SMC_RET1(handle, SMC_UNK); 40022038315SVarun Wadekar 40122038315SVarun Wadekar /* 40222038315SVarun Wadekar * TODO: Check if the passed memory pointer is valid. Might 40322038315SVarun Wadekar * require a call into the platform code. 40422038315SVarun Wadekar */ 40522038315SVarun Wadekar 40622038315SVarun Wadekar tlk_args_results_buf = (tlk_args_results_t *)x1; 40722038315SVarun Wadekar SMC_RET0(handle); 40822038315SVarun Wadekar 40922038315SVarun Wadekar /* 41022038315SVarun Wadekar * Return the number of service function IDs implemented to 41122038315SVarun Wadekar * provide service to non-secure 41222038315SVarun Wadekar */ 41322038315SVarun Wadekar case TOS_CALL_COUNT: 41422038315SVarun Wadekar SMC_RET1(handle, TLK_NUM_FID); 41522038315SVarun Wadekar 41622038315SVarun Wadekar /* 41722038315SVarun Wadekar * Return TLK's UID to the caller 41822038315SVarun Wadekar */ 41922038315SVarun Wadekar case TOS_UID: 42022038315SVarun Wadekar SMC_UUID_RET(handle, tlk_uuid); 42122038315SVarun Wadekar 42222038315SVarun Wadekar /* 42322038315SVarun Wadekar * Return the version of current implementation 42422038315SVarun Wadekar */ 42522038315SVarun Wadekar case TOS_CALL_VERSION: 42622038315SVarun Wadekar SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR); 42722038315SVarun Wadekar 42822038315SVarun Wadekar default: 42922038315SVarun Wadekar break; 43022038315SVarun Wadekar } 43122038315SVarun Wadekar 43222038315SVarun Wadekar SMC_RET1(handle, SMC_UNK); 43322038315SVarun Wadekar } 43422038315SVarun Wadekar 43522038315SVarun Wadekar /* Define a SPD runtime service descriptor for fast SMC calls */ 43622038315SVarun Wadekar DECLARE_RT_SVC( 43722038315SVarun Wadekar tlkd_tos_fast, 43822038315SVarun Wadekar 43922038315SVarun Wadekar OEN_TOS_START, 44022038315SVarun Wadekar OEN_TOS_END, 44122038315SVarun Wadekar SMC_TYPE_FAST, 44222038315SVarun Wadekar tlkd_setup, 44322038315SVarun Wadekar tlkd_smc_handler 44422038315SVarun Wadekar ); 44522038315SVarun Wadekar 44622038315SVarun Wadekar /* Define a SPD runtime service descriptor for standard SMC calls */ 44722038315SVarun Wadekar DECLARE_RT_SVC( 44822038315SVarun Wadekar tlkd_tos_std, 44922038315SVarun Wadekar 45022038315SVarun Wadekar OEN_TOS_START, 45122038315SVarun Wadekar OEN_TOS_END, 45222038315SVarun Wadekar SMC_TYPE_STD, 45322038315SVarun Wadekar NULL, 45422038315SVarun Wadekar tlkd_smc_handler 45522038315SVarun Wadekar ); 456*6693962cSVarun Wadekar 457*6693962cSVarun Wadekar /* Define a SPD runtime service descriptor for fast SMC calls */ 458*6693962cSVarun Wadekar DECLARE_RT_SVC( 459*6693962cSVarun Wadekar tlkd_tap_fast, 460*6693962cSVarun Wadekar 461*6693962cSVarun Wadekar OEN_TAP_START, 462*6693962cSVarun Wadekar OEN_TAP_END, 463*6693962cSVarun Wadekar SMC_TYPE_FAST, 464*6693962cSVarun Wadekar NULL, 465*6693962cSVarun Wadekar tlkd_smc_handler 466*6693962cSVarun Wadekar ); 467*6693962cSVarun Wadekar 468*6693962cSVarun Wadekar /* Define a SPD runtime service descriptor for standard SMC calls */ 469*6693962cSVarun Wadekar DECLARE_RT_SVC( 470*6693962cSVarun Wadekar tlkd_tap_std, 471*6693962cSVarun Wadekar 472*6693962cSVarun Wadekar OEN_TAP_START, 473*6693962cSVarun Wadekar OEN_TAP_END, 474*6693962cSVarun Wadekar SMC_TYPE_STD, 475*6693962cSVarun Wadekar NULL, 476*6693962cSVarun Wadekar tlkd_smc_handler 477*6693962cSVarun Wadekar ); 478