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 { 189*77199df7SVarun Wadekar cpu_context_t *ns_cpu_context; 19022038315SVarun Wadekar uint32_t ns; 19122038315SVarun Wadekar 19222038315SVarun Wadekar /* Passing a NULL context is a critical programming error */ 19322038315SVarun Wadekar assert(handle); 19422038315SVarun Wadekar 19522038315SVarun Wadekar /* Determine which security state this SMC originated from */ 19622038315SVarun Wadekar ns = is_caller_non_secure(flags); 19722038315SVarun Wadekar 19822038315SVarun Wadekar switch (smc_fid) { 19922038315SVarun Wadekar 20022038315SVarun Wadekar /* 201*77199df7SVarun Wadekar * This is a request from the non-secure context to: 202*77199df7SVarun Wadekar * 203*77199df7SVarun Wadekar * a. register shared memory with the SP for storing it's 204*77199df7SVarun Wadekar * activity logs. 205*77199df7SVarun Wadekar * b. register shared memory with the SP for passing args 206*77199df7SVarun Wadekar * required for maintaining sessions with the Trusted 207*77199df7SVarun Wadekar * Applications. 208*77199df7SVarun Wadekar */ 209*77199df7SVarun Wadekar case TLK_REGISTER_LOGBUF: 210*77199df7SVarun Wadekar case TLK_REGISTER_REQBUF: 211*77199df7SVarun Wadekar if (!ns || !tlk_args_results_buf) 212*77199df7SVarun Wadekar SMC_RET1(handle, SMC_UNK); 213*77199df7SVarun Wadekar 214*77199df7SVarun Wadekar /* 215*77199df7SVarun Wadekar * This is a fresh request from the non-secure client. 216*77199df7SVarun Wadekar * The parameters are in x1 and x2. Figure out which 217*77199df7SVarun Wadekar * registers need to be preserved, save the non-secure 218*77199df7SVarun Wadekar * state and send the request to the secure payload. 219*77199df7SVarun Wadekar */ 220*77199df7SVarun Wadekar assert(handle == cm_get_context(NON_SECURE)); 221*77199df7SVarun Wadekar 222*77199df7SVarun Wadekar /* Check if we are already preempted */ 223*77199df7SVarun Wadekar if (get_std_smc_active_flag(tlk_ctx.state)) 224*77199df7SVarun Wadekar SMC_RET1(handle, SMC_UNK); 225*77199df7SVarun Wadekar 226*77199df7SVarun Wadekar cm_el1_sysregs_context_save(NON_SECURE); 227*77199df7SVarun Wadekar 228*77199df7SVarun Wadekar /* 229*77199df7SVarun Wadekar * Verify if there is a valid context to use. 230*77199df7SVarun Wadekar */ 231*77199df7SVarun Wadekar assert(&tlk_ctx.cpu_ctx == cm_get_context(SECURE)); 232*77199df7SVarun Wadekar 233*77199df7SVarun Wadekar /* 234*77199df7SVarun Wadekar * Mark the SP state as active. 235*77199df7SVarun Wadekar */ 236*77199df7SVarun Wadekar set_std_smc_active_flag(tlk_ctx.state); 237*77199df7SVarun Wadekar 238*77199df7SVarun Wadekar /* Save args for use by the SP on return */ 239*77199df7SVarun Wadekar store_tlk_args_results(smc_fid, x1, x2, x3); 240*77199df7SVarun Wadekar 241*77199df7SVarun Wadekar /* 242*77199df7SVarun Wadekar * We are done stashing the non-secure context. Ask the 243*77199df7SVarun Wadekar * secure payload to do the work now. 244*77199df7SVarun Wadekar */ 245*77199df7SVarun Wadekar cm_el1_sysregs_context_restore(SECURE); 246*77199df7SVarun Wadekar cm_set_next_eret_context(SECURE); 247*77199df7SVarun Wadekar SMC_RET0(&tlk_ctx.cpu_ctx); 248*77199df7SVarun Wadekar 249*77199df7SVarun Wadekar /* 250*77199df7SVarun Wadekar * This is a request from the SP to mark completion of 251*77199df7SVarun Wadekar * a standard function ID. 252*77199df7SVarun Wadekar */ 253*77199df7SVarun Wadekar case TLK_REQUEST_DONE: 254*77199df7SVarun Wadekar if (ns || !tlk_args_results_buf) 255*77199df7SVarun Wadekar SMC_RET1(handle, SMC_UNK); 256*77199df7SVarun Wadekar 257*77199df7SVarun Wadekar /* 258*77199df7SVarun Wadekar * Mark the SP state as inactive. 259*77199df7SVarun Wadekar */ 260*77199df7SVarun Wadekar clr_std_smc_active_flag(tlk_ctx.state); 261*77199df7SVarun Wadekar 262*77199df7SVarun Wadekar /* Get a reference to the non-secure context */ 263*77199df7SVarun Wadekar ns_cpu_context = cm_get_context(NON_SECURE); 264*77199df7SVarun Wadekar assert(ns_cpu_context); 265*77199df7SVarun Wadekar 266*77199df7SVarun Wadekar /* 267*77199df7SVarun Wadekar * This is a request completion SMC and we must switch to 268*77199df7SVarun Wadekar * the non-secure world to pass the result. 269*77199df7SVarun Wadekar */ 270*77199df7SVarun Wadekar cm_el1_sysregs_context_save(SECURE); 271*77199df7SVarun Wadekar 272*77199df7SVarun Wadekar /* 273*77199df7SVarun Wadekar * We are done stashing the secure context. Switch to the 274*77199df7SVarun Wadekar * non-secure context and return the result. 275*77199df7SVarun Wadekar */ 276*77199df7SVarun Wadekar cm_el1_sysregs_context_restore(NON_SECURE); 277*77199df7SVarun Wadekar cm_set_next_eret_context(NON_SECURE); 278*77199df7SVarun Wadekar SMC_RET1(ns_cpu_context, tlk_args_results_buf->args[0]); 279*77199df7SVarun Wadekar 280*77199df7SVarun Wadekar /* 28122038315SVarun Wadekar * This function ID is used only by the SP to indicate it has 28222038315SVarun Wadekar * finished initialising itself after a cold boot 28322038315SVarun Wadekar */ 28422038315SVarun Wadekar case TLK_ENTRY_DONE: 285*77199df7SVarun Wadekar if (ns || !tlk_args_results_buf) 28622038315SVarun Wadekar SMC_RET1(handle, SMC_UNK); 28722038315SVarun Wadekar 28822038315SVarun Wadekar /* 28922038315SVarun Wadekar * SP has been successfully initialized. Register power 29022038315SVarun Wadekar * managemnt hooks with PSCI 29122038315SVarun Wadekar */ 29222038315SVarun Wadekar psci_register_spd_pm_hook(&tlkd_pm_ops); 29322038315SVarun Wadekar 29422038315SVarun Wadekar /* 29522038315SVarun Wadekar * TLK reports completion. The SPD must have initiated 29622038315SVarun Wadekar * the original request through a synchronous entry 29722038315SVarun Wadekar * into the SP. Jump back to the original C runtime 29822038315SVarun Wadekar * context. 29922038315SVarun Wadekar */ 30022038315SVarun Wadekar tlkd_synchronous_sp_exit(&tlk_ctx, tlk_args_results_buf->args[0]); 30122038315SVarun Wadekar 30222038315SVarun Wadekar /* 30322038315SVarun Wadekar * This is a request from the secure payload to register 30422038315SVarun Wadekar * shared memory to pass SMC args/results between EL1, EL3. 30522038315SVarun Wadekar */ 30622038315SVarun Wadekar case TLK_FID_SHARED_MEMBUF: 30722038315SVarun Wadekar if (ns || !x1) 30822038315SVarun Wadekar SMC_RET1(handle, SMC_UNK); 30922038315SVarun Wadekar 31022038315SVarun Wadekar /* 31122038315SVarun Wadekar * TODO: Check if the passed memory pointer is valid. Might 31222038315SVarun Wadekar * require a call into the platform code. 31322038315SVarun Wadekar */ 31422038315SVarun Wadekar 31522038315SVarun Wadekar tlk_args_results_buf = (tlk_args_results_t *)x1; 31622038315SVarun Wadekar SMC_RET0(handle); 31722038315SVarun Wadekar 31822038315SVarun Wadekar /* 31922038315SVarun Wadekar * Return the number of service function IDs implemented to 32022038315SVarun Wadekar * provide service to non-secure 32122038315SVarun Wadekar */ 32222038315SVarun Wadekar case TOS_CALL_COUNT: 32322038315SVarun Wadekar SMC_RET1(handle, TLK_NUM_FID); 32422038315SVarun Wadekar 32522038315SVarun Wadekar /* 32622038315SVarun Wadekar * Return TLK's UID to the caller 32722038315SVarun Wadekar */ 32822038315SVarun Wadekar case TOS_UID: 32922038315SVarun Wadekar SMC_UUID_RET(handle, tlk_uuid); 33022038315SVarun Wadekar 33122038315SVarun Wadekar /* 33222038315SVarun Wadekar * Return the version of current implementation 33322038315SVarun Wadekar */ 33422038315SVarun Wadekar case TOS_CALL_VERSION: 33522038315SVarun Wadekar SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR); 33622038315SVarun Wadekar 33722038315SVarun Wadekar default: 33822038315SVarun Wadekar break; 33922038315SVarun Wadekar } 34022038315SVarun Wadekar 34122038315SVarun Wadekar SMC_RET1(handle, SMC_UNK); 34222038315SVarun Wadekar } 34322038315SVarun Wadekar 34422038315SVarun Wadekar /* Define a SPD runtime service descriptor for fast SMC calls */ 34522038315SVarun Wadekar DECLARE_RT_SVC( 34622038315SVarun Wadekar tlkd_tos_fast, 34722038315SVarun Wadekar 34822038315SVarun Wadekar OEN_TOS_START, 34922038315SVarun Wadekar OEN_TOS_END, 35022038315SVarun Wadekar SMC_TYPE_FAST, 35122038315SVarun Wadekar tlkd_setup, 35222038315SVarun Wadekar tlkd_smc_handler 35322038315SVarun Wadekar ); 35422038315SVarun Wadekar 35522038315SVarun Wadekar /* Define a SPD runtime service descriptor for standard SMC calls */ 35622038315SVarun Wadekar DECLARE_RT_SVC( 35722038315SVarun Wadekar tlkd_tos_std, 35822038315SVarun Wadekar 35922038315SVarun Wadekar OEN_TOS_START, 36022038315SVarun Wadekar OEN_TOS_END, 36122038315SVarun Wadekar SMC_TYPE_STD, 36222038315SVarun Wadekar NULL, 36322038315SVarun Wadekar tlkd_smc_handler 36422038315SVarun Wadekar ); 365