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; 191*6e159e7aSVarun 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 19622038315SVarun Wadekar /* Determine which security state this SMC originated from */ 19722038315SVarun Wadekar ns = is_caller_non_secure(flags); 19822038315SVarun Wadekar 19922038315SVarun Wadekar switch (smc_fid) { 20022038315SVarun Wadekar 20122038315SVarun Wadekar /* 20277199df7SVarun Wadekar * This is a request from the non-secure context to: 20377199df7SVarun Wadekar * 20477199df7SVarun Wadekar * a. register shared memory with the SP for storing it's 20577199df7SVarun Wadekar * activity logs. 20677199df7SVarun Wadekar * b. register shared memory with the SP for passing args 20777199df7SVarun Wadekar * required for maintaining sessions with the Trusted 20877199df7SVarun Wadekar * Applications. 20977199df7SVarun Wadekar */ 21077199df7SVarun Wadekar case TLK_REGISTER_LOGBUF: 21177199df7SVarun Wadekar case TLK_REGISTER_REQBUF: 21277199df7SVarun Wadekar if (!ns || !tlk_args_results_buf) 21377199df7SVarun Wadekar SMC_RET1(handle, SMC_UNK); 21477199df7SVarun Wadekar 21577199df7SVarun Wadekar /* 21677199df7SVarun Wadekar * This is a fresh request from the non-secure client. 21777199df7SVarun Wadekar * The parameters are in x1 and x2. Figure out which 21877199df7SVarun Wadekar * registers need to be preserved, save the non-secure 21977199df7SVarun Wadekar * state and send the request to the secure payload. 22077199df7SVarun Wadekar */ 22177199df7SVarun Wadekar assert(handle == cm_get_context(NON_SECURE)); 22277199df7SVarun Wadekar 22377199df7SVarun Wadekar /* Check if we are already preempted */ 22477199df7SVarun Wadekar if (get_std_smc_active_flag(tlk_ctx.state)) 22577199df7SVarun Wadekar SMC_RET1(handle, SMC_UNK); 22677199df7SVarun Wadekar 22777199df7SVarun Wadekar cm_el1_sysregs_context_save(NON_SECURE); 22877199df7SVarun Wadekar 22977199df7SVarun Wadekar /* 23077199df7SVarun Wadekar * Verify if there is a valid context to use. 23177199df7SVarun Wadekar */ 23277199df7SVarun Wadekar assert(&tlk_ctx.cpu_ctx == cm_get_context(SECURE)); 23377199df7SVarun Wadekar 23477199df7SVarun Wadekar /* 23577199df7SVarun Wadekar * Mark the SP state as active. 23677199df7SVarun Wadekar */ 23777199df7SVarun Wadekar set_std_smc_active_flag(tlk_ctx.state); 23877199df7SVarun Wadekar 23977199df7SVarun Wadekar /* Save args for use by the SP on return */ 24077199df7SVarun Wadekar store_tlk_args_results(smc_fid, x1, x2, x3); 24177199df7SVarun Wadekar 24277199df7SVarun Wadekar /* 24377199df7SVarun Wadekar * We are done stashing the non-secure context. Ask the 24477199df7SVarun Wadekar * secure payload to do the work now. 24577199df7SVarun Wadekar */ 24677199df7SVarun Wadekar cm_el1_sysregs_context_restore(SECURE); 24777199df7SVarun Wadekar cm_set_next_eret_context(SECURE); 24877199df7SVarun Wadekar SMC_RET0(&tlk_ctx.cpu_ctx); 24977199df7SVarun Wadekar 25077199df7SVarun Wadekar /* 251*6e159e7aSVarun Wadekar * Translate NS/EL1-S virtual addresses 252*6e159e7aSVarun Wadekar */ 253*6e159e7aSVarun Wadekar case TLK_VA_TRANSLATE: 254*6e159e7aSVarun Wadekar if (ns || !tlk_args_results_buf) 255*6e159e7aSVarun Wadekar SMC_RET1(handle, SMC_UNK); 256*6e159e7aSVarun Wadekar 257*6e159e7aSVarun Wadekar /* virtual address and type: ns/s */ 258*6e159e7aSVarun Wadekar vaddr = tlk_args_results_buf->args[0]; 259*6e159e7aSVarun Wadekar type = tlk_args_results_buf->args[1]; 260*6e159e7aSVarun Wadekar 261*6e159e7aSVarun Wadekar par = tlkd_va_translate(vaddr, type); 262*6e159e7aSVarun Wadekar 263*6e159e7aSVarun Wadekar /* Save PA for use by the SP on return */ 264*6e159e7aSVarun Wadekar store_tlk_args_results(par, 0, 0, 0); 265*6e159e7aSVarun Wadekar 266*6e159e7aSVarun Wadekar SMC_RET0(handle); 267*6e159e7aSVarun Wadekar 268*6e159e7aSVarun Wadekar /* 26977199df7SVarun Wadekar * This is a request from the SP to mark completion of 27077199df7SVarun Wadekar * a standard function ID. 27177199df7SVarun Wadekar */ 27277199df7SVarun Wadekar case TLK_REQUEST_DONE: 27377199df7SVarun Wadekar if (ns || !tlk_args_results_buf) 27477199df7SVarun Wadekar SMC_RET1(handle, SMC_UNK); 27577199df7SVarun Wadekar 27677199df7SVarun Wadekar /* 27777199df7SVarun Wadekar * Mark the SP state as inactive. 27877199df7SVarun Wadekar */ 27977199df7SVarun Wadekar clr_std_smc_active_flag(tlk_ctx.state); 28077199df7SVarun Wadekar 28177199df7SVarun Wadekar /* Get a reference to the non-secure context */ 28277199df7SVarun Wadekar ns_cpu_context = cm_get_context(NON_SECURE); 28377199df7SVarun Wadekar assert(ns_cpu_context); 28477199df7SVarun Wadekar 28577199df7SVarun Wadekar /* 28677199df7SVarun Wadekar * This is a request completion SMC and we must switch to 28777199df7SVarun Wadekar * the non-secure world to pass the result. 28877199df7SVarun Wadekar */ 28977199df7SVarun Wadekar cm_el1_sysregs_context_save(SECURE); 29077199df7SVarun Wadekar 29177199df7SVarun Wadekar /* 29277199df7SVarun Wadekar * We are done stashing the secure context. Switch to the 29377199df7SVarun Wadekar * non-secure context and return the result. 29477199df7SVarun Wadekar */ 29577199df7SVarun Wadekar cm_el1_sysregs_context_restore(NON_SECURE); 29677199df7SVarun Wadekar cm_set_next_eret_context(NON_SECURE); 29777199df7SVarun Wadekar SMC_RET1(ns_cpu_context, tlk_args_results_buf->args[0]); 29877199df7SVarun Wadekar 29977199df7SVarun Wadekar /* 30022038315SVarun Wadekar * This function ID is used only by the SP to indicate it has 30122038315SVarun Wadekar * finished initialising itself after a cold boot 30222038315SVarun Wadekar */ 30322038315SVarun Wadekar case TLK_ENTRY_DONE: 30477199df7SVarun Wadekar if (ns || !tlk_args_results_buf) 30522038315SVarun Wadekar SMC_RET1(handle, SMC_UNK); 30622038315SVarun Wadekar 30722038315SVarun Wadekar /* 30822038315SVarun Wadekar * SP has been successfully initialized. Register power 30922038315SVarun Wadekar * managemnt hooks with PSCI 31022038315SVarun Wadekar */ 31122038315SVarun Wadekar psci_register_spd_pm_hook(&tlkd_pm_ops); 31222038315SVarun Wadekar 31322038315SVarun Wadekar /* 31422038315SVarun Wadekar * TLK reports completion. The SPD must have initiated 31522038315SVarun Wadekar * the original request through a synchronous entry 31622038315SVarun Wadekar * into the SP. Jump back to the original C runtime 31722038315SVarun Wadekar * context. 31822038315SVarun Wadekar */ 31922038315SVarun Wadekar tlkd_synchronous_sp_exit(&tlk_ctx, tlk_args_results_buf->args[0]); 32022038315SVarun Wadekar 32122038315SVarun Wadekar /* 32222038315SVarun Wadekar * This is a request from the secure payload to register 32322038315SVarun Wadekar * shared memory to pass SMC args/results between EL1, EL3. 32422038315SVarun Wadekar */ 32522038315SVarun Wadekar case TLK_FID_SHARED_MEMBUF: 32622038315SVarun Wadekar if (ns || !x1) 32722038315SVarun Wadekar SMC_RET1(handle, SMC_UNK); 32822038315SVarun Wadekar 32922038315SVarun Wadekar /* 33022038315SVarun Wadekar * TODO: Check if the passed memory pointer is valid. Might 33122038315SVarun Wadekar * require a call into the platform code. 33222038315SVarun Wadekar */ 33322038315SVarun Wadekar 33422038315SVarun Wadekar tlk_args_results_buf = (tlk_args_results_t *)x1; 33522038315SVarun Wadekar SMC_RET0(handle); 33622038315SVarun Wadekar 33722038315SVarun Wadekar /* 33822038315SVarun Wadekar * Return the number of service function IDs implemented to 33922038315SVarun Wadekar * provide service to non-secure 34022038315SVarun Wadekar */ 34122038315SVarun Wadekar case TOS_CALL_COUNT: 34222038315SVarun Wadekar SMC_RET1(handle, TLK_NUM_FID); 34322038315SVarun Wadekar 34422038315SVarun Wadekar /* 34522038315SVarun Wadekar * Return TLK's UID to the caller 34622038315SVarun Wadekar */ 34722038315SVarun Wadekar case TOS_UID: 34822038315SVarun Wadekar SMC_UUID_RET(handle, tlk_uuid); 34922038315SVarun Wadekar 35022038315SVarun Wadekar /* 35122038315SVarun Wadekar * Return the version of current implementation 35222038315SVarun Wadekar */ 35322038315SVarun Wadekar case TOS_CALL_VERSION: 35422038315SVarun Wadekar SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR); 35522038315SVarun Wadekar 35622038315SVarun Wadekar default: 35722038315SVarun Wadekar break; 35822038315SVarun Wadekar } 35922038315SVarun Wadekar 36022038315SVarun Wadekar SMC_RET1(handle, SMC_UNK); 36122038315SVarun Wadekar } 36222038315SVarun Wadekar 36322038315SVarun Wadekar /* Define a SPD runtime service descriptor for fast SMC calls */ 36422038315SVarun Wadekar DECLARE_RT_SVC( 36522038315SVarun Wadekar tlkd_tos_fast, 36622038315SVarun Wadekar 36722038315SVarun Wadekar OEN_TOS_START, 36822038315SVarun Wadekar OEN_TOS_END, 36922038315SVarun Wadekar SMC_TYPE_FAST, 37022038315SVarun Wadekar tlkd_setup, 37122038315SVarun Wadekar tlkd_smc_handler 37222038315SVarun Wadekar ); 37322038315SVarun Wadekar 37422038315SVarun Wadekar /* Define a SPD runtime service descriptor for standard SMC calls */ 37522038315SVarun Wadekar DECLARE_RT_SVC( 37622038315SVarun Wadekar tlkd_tos_std, 37722038315SVarun Wadekar 37822038315SVarun Wadekar OEN_TOS_START, 37922038315SVarun Wadekar OEN_TOS_END, 38022038315SVarun Wadekar SMC_TYPE_STD, 38122038315SVarun Wadekar NULL, 38222038315SVarun Wadekar tlkd_smc_handler 38322038315SVarun Wadekar ); 384