diff --git a/include/bl32/payloads/tlk.h b/include/bl32/payloads/tlk.h new file mode 100644 index 0000000..d9fa794 --- /dev/null +++ b/include/bl32/payloads/tlk.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TLK_H__ +#define __TLK_H__ + +/* + * SMC function IDs that TLK uses to signal various forms of completions + * to the secure payload dispatcher. + */ +#define TLK_ENTRY_DONE (0x32000003 | (1 << 31)) +#define TLK_FID_SHARED_MEMBUF (0x32000005 | (1 << 31)) + +/* + * Total number of function IDs implemented for services offered to NS clients. + */ +#define TLK_NUM_FID 0 + +/* TLK implementation version numbers */ +#define TLK_VERSION_MAJOR 0x0 /* Major version */ +#define TLK_VERSION_MINOR 0x1 /* Minor version */ + +/* + * Standard Trusted OS Function IDs that fall under Trusted OS call range + * according to SMC calling convention + */ +#define TOS_CALL_COUNT 0xbf00ff00 /* Number of calls implemented */ +#define TOS_UID 0xbf00ff01 /* Implementation UID */ +#define TOS_CALL_VERSION 0xbf00ff03 /* Trusted OS Call Version */ + +#endif /* __TLK_H__ */ diff --git a/services/spd/tlkd/tlkd.mk b/services/spd/tlkd/tlkd.mk new file mode 100644 index 0000000..d814d94 --- /dev/null +++ b/services/spd/tlkd/tlkd.mk @@ -0,0 +1,38 @@ +# +# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of ARM nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +SPD_INCLUDES := -Iinclude/bl32/payloads + +SPD_SOURCES := services/spd/tlkd/tlkd_common.c \ + services/spd/tlkd/tlkd_helpers.S \ + services/spd/tlkd/tlkd_main.c \ + services/spd/tlkd/tlkd_pm.c + +NEED_BL32 := yes diff --git a/services/spd/tlkd/tlkd_common.c b/services/spd/tlkd/tlkd_common.c new file mode 100644 index 0000000..5944174 --- /dev/null +++ b/services/spd/tlkd/tlkd_common.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include "tlkd_private.h" + +/******************************************************************************* + * Given a secure payload entrypoint, register width, cpu id & pointer to a + * context data structure, this function will create a secure context ready for + * programming an entry into the secure payload. + ******************************************************************************/ +void tlkd_init_tlk_ep_state(struct entry_point_info *tlk_entry_point, + uint32_t rw, + uint64_t pc, + tlk_context_t *tlk_ctx) +{ + uint32_t ep_attr, spsr; + + /* Passing a NULL context is a critical programming error */ + assert(tlk_ctx); + assert(tlk_entry_point); + assert(pc); + + /* Associate this context with the cpu specified */ + tlk_ctx->mpidr = read_mpidr_el1(); + clr_std_smc_active_flag(tlk_ctx->state); + cm_set_context(&tlk_ctx->cpu_ctx, SECURE); + + if (rw == SP_AARCH64) + spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + else + spsr = SPSR_MODE32(MODE32_svc, + SPSR_T_ARM, + read_sctlr_el3() & SCTLR_EE_BIT, + DISABLE_ALL_EXCEPTIONS); + + /* initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if (read_sctlr_el3() & SCTLR_EE_BIT) + ep_attr |= EP_EE_BIG; + SET_PARAM_HEAD(tlk_entry_point, PARAM_EP, VERSION_1, ep_attr); + + tlk_entry_point->pc = pc; + tlk_entry_point->spsr = spsr; +} + +/******************************************************************************* + * This function takes a TLK context pointer and: + * 1. Applies the S-EL1 system register context from tlk_ctx->cpu_ctx. + * 2. Saves the current C runtime state (callee saved registers) on the stack + * frame and saves a reference to this state. + * 3. Calls el3_exit() so that the EL3 system and general purpose registers + * from the tlk_ctx->cpu_ctx are used to enter the secure payload image. + ******************************************************************************/ +uint64_t tlkd_synchronous_sp_entry(tlk_context_t *tlk_ctx) +{ + uint64_t rc; + + /* Passing a NULL context is a critical programming error */ + assert(tlk_ctx); + assert(tlk_ctx->c_rt_ctx == 0); + + /* Apply the Secure EL1 system register context and switch to it */ + assert(cm_get_context(SECURE) == &tlk_ctx->cpu_ctx); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + rc = tlkd_enter_sp(&tlk_ctx->c_rt_ctx); +#if DEBUG + tlk_ctx->c_rt_ctx = 0; +#endif + + return rc; +} + +/******************************************************************************* + * This function takes a TLK context pointer and: + * 1. Saves the S-EL1 system register context to tlk_ctx->cpu_ctx. + * 2. Restores the current C runtime state (callee saved registers) from the + * stack frame using reference to this state saved in tlkd_enter_sp(). + * 3. It does not need to save any general purpose or EL3 system register state + * as the generic smc entry routine should have saved those. + ******************************************************************************/ +void tlkd_synchronous_sp_exit(tlk_context_t *tlk_ctx, uint64_t ret) +{ + /* Passing a NULL context is a critical programming error */ + assert(tlk_ctx); + + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &tlk_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + assert(tlk_ctx->c_rt_ctx != 0); + tlkd_exit_sp(tlk_ctx->c_rt_ctx, ret); + + /* Should never reach here */ + assert(0); +} diff --git a/services/spd/tlkd/tlkd_helpers.S b/services/spd/tlkd/tlkd_helpers.S new file mode 100644 index 0000000..55a82a3 --- /dev/null +++ b/services/spd/tlkd/tlkd_helpers.S @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "tlkd_private.h" + + .global tlkd_enter_sp + .global tlkd_exit_sp + + /* --------------------------------------------- + * This function is called with SP_EL0 as stack. + * Here we stash our EL3 callee-saved registers + * on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where + * the address of the C runtime context is to be + * saved. + * --------------------------------------------- + */ +func tlkd_enter_sp + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #TLKD_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #TLKD_C_RT_CTX_X19] + stp x21, x22, [sp, #TLKD_C_RT_CTX_X21] + stp x23, x24, [sp, #TLKD_C_RT_CTX_X23] + stp x25, x26, [sp, #TLKD_C_RT_CTX_X25] + stp x27, x28, [sp, #TLKD_C_RT_CTX_X27] + stp x29, x30, [sp, #TLKD_C_RT_CTX_X29] + + /* ---------------------------------------------- + * Everything is setup now. el3_exit() will + * use the secure context to restore to the + * general purpose and EL3 system registers to + * ERET into the secure payload. + * ---------------------------------------------- + */ + b el3_exit + + /* ---------------------------------------------- + * This function is called with 'x0' pointing to + * a C runtime context saved in tlkd_enter_sp(). + * It restores the saved registers and jumps to + * that runtime with 'x0' as the new sp. This + * destroys the C runtime context that had been + * built on the stack below the saved context by + * the caller. Later the second parameter 'x1' + * is passed as return value to the caller + * ---------------------------------------------- + */ +func tlkd_exit_sp + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(TLKD_C_RT_CTX_X19 - TLKD_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(TLKD_C_RT_CTX_X21 - TLKD_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(TLKD_C_RT_CTX_X23 - TLKD_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(TLKD_C_RT_CTX_X25 - TLKD_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(TLKD_C_RT_CTX_X27 - TLKD_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(TLKD_C_RT_CTX_X29 - TLKD_C_RT_CTX_SIZE)] + + /* ------------------------------------------------ + * This should take us back to the instruction + * after the call to the last tlkd_enter_sp(). + * Place the second parameter to x0 so that the + * caller will see it as a return value from the + * original entry call + * ------------------------------------------------ + */ + mov x0, x1 + ret diff --git a/services/spd/tlkd/tlkd_main.c b/services/spd/tlkd/tlkd_main.c new file mode 100644 index 0000000..65466aa --- /dev/null +++ b/services/spd/tlkd/tlkd_main.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/******************************************************************************* + * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a + * plug-in component to the Secure Monitor, registered as a runtime service. The + * SPD is expected to be a functional extension of the Secure Payload (SP) that + * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting + * the Trusted OS/Applications range to the dispatcher. The SPD will either + * handle the request locally or delegate it to the Secure Payload. It is also + * responsible for initialising and maintaining communication with the SP. + ******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tlkd_private.h" + +extern const spd_pm_ops_t tlkd_pm_ops; + +/******************************************************************************* + * Array to keep track of per-cpu Secure Payload state + ******************************************************************************/ +static tlk_context_t tlk_ctx; + +/* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */ +DEFINE_SVC_UUID(tlk_uuid, + 0xbd11e9c9, 0x2bba, 0x52ee, 0xb1, 0x72, + 0x46, 0x1f, 0xba, 0x97, 0x7f, 0x63); + +int32_t tlkd_init(void); + +/* + * The number of arguments/results to save during a SMC call for TLK. + */ +#define TLK_SHDBUF_SIZE 4 + +/******************************************************************************* + * Shared memory buffer for passing SMC args/results to TLK + ******************************************************************************/ +typedef struct tlk_args_results { + uint64_t args[TLK_SHDBUF_SIZE]; +} tlk_args_results_t; + +static tlk_args_results_t *tlk_args_results_buf; + +/* + * Helper function to store args from TLK and pass results back + */ +static inline void store_tlk_args_results(uint64_t x0, uint64_t x1, uint64_t x2, + uint64_t x3) +{ + /* store arguments sent by TLK */ + tlk_args_results_buf->args[0] = x0; + tlk_args_results_buf->args[1] = x1; + tlk_args_results_buf->args[2] = x2; + tlk_args_results_buf->args[3] = x3; + + flush_dcache_range((uint64_t)tlk_args_results_buf, + sizeof(tlk_args_results_t)); +} + +/******************************************************************************* + * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type + * (aarch32/aarch64) if not already known and initialises the context for entry + * into the SP for its initialisation. + ******************************************************************************/ +int32_t tlkd_setup(void) +{ + entry_point_info_t *tlk_ep_info; + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. + */ + tlk_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (!tlk_ep_info) { + WARN("No SP provided. Booting device without SP" + " initialization. SMC`s destined for SP" + " will return SMC_UNK\n"); + return 1; + } + + /* + * If there's no valid entry point for SP, we return a non-zero value + * signalling failure initializing the service. We bail out without + * registering any handlers + */ + if (!tlk_ep_info->pc) + return 1; + + /* + * Inspect the SP image's SPSR and determine it's execution state + * i.e whether AArch32 or AArch64. + */ + tlkd_init_tlk_ep_state(tlk_ep_info, + (tlk_ep_info->spsr >> MODE_RW_SHIFT) & MODE_RW_MASK, + tlk_ep_info->pc, + &tlk_ctx); + + /* + * All TLK SPD initialization done. Now register our init function + * with BL31 for deferred invocation + */ + bl31_register_bl32_init(&tlkd_init); + + return 0; +} + +/******************************************************************************* + * This function passes control to the Secure Payload image (BL32) for the first + * time on the primary cpu after a cold boot. It assumes that a valid secure + * context has already been created by tlkd_setup() which can be directly + * used. This function performs a synchronous entry into the Secure payload. + * The SP passes control back to this routine through a SMC. + ******************************************************************************/ +int32_t tlkd_init(void) +{ + uint64_t mpidr = read_mpidr(); + entry_point_info_t *tlk_entry_point; + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. + */ + tlk_entry_point = bl31_plat_get_next_image_ep_info(SECURE); + assert(tlk_entry_point); + + cm_init_context(mpidr, tlk_entry_point); + + /* + * Arrange for an entry into the test secure payload. + */ + return tlkd_synchronous_sp_entry(&tlk_ctx); +} + +/******************************************************************************* + * This function is responsible for handling all SMCs in the Trusted OS/App + * range from the non-secure state as defined in the SMC Calling Convention + * Document. It is also responsible for communicating with the Secure payload + * to delegate work and return results back to the non-secure state. Lastly it + * will also return any information that the secure payload needs to do the + * work assigned to it. + ******************************************************************************/ +uint64_t tlkd_smc_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) +{ + uint32_t ns; + + /* Passing a NULL context is a critical programming error */ + assert(handle); + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + + switch (smc_fid) { + + /* + * 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) + SMC_RET1(handle, SMC_UNK); + + /* + * SP has been successfully initialized. Register power + * managemnt hooks with PSCI + */ + psci_register_spd_pm_hook(&tlkd_pm_ops); + + /* + * TLK reports completion. The SPD must have initiated + * the original request through a synchronous entry + * into the SP. Jump back to the original C runtime + * context. + */ + tlkd_synchronous_sp_exit(&tlk_ctx, tlk_args_results_buf->args[0]); + + /* + * This is a request from the secure payload to register + * shared memory to pass SMC args/results between EL1, EL3. + */ + case TLK_FID_SHARED_MEMBUF: + if (ns || !x1) + SMC_RET1(handle, SMC_UNK); + + /* + * TODO: Check if the passed memory pointer is valid. Might + * require a call into the platform code. + */ + + tlk_args_results_buf = (tlk_args_results_t *)x1; + SMC_RET0(handle); + + /* + * Return the number of service function IDs implemented to + * provide service to non-secure + */ + case TOS_CALL_COUNT: + SMC_RET1(handle, TLK_NUM_FID); + + /* + * Return TLK's UID to the caller + */ + case TOS_UID: + SMC_UUID_RET(handle, tlk_uuid); + + /* + * Return the version of current implementation + */ + case TOS_CALL_VERSION: + SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR); + + default: + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + tlkd_tos_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + tlkd_setup, + tlkd_smc_handler +); + +/* Define a SPD runtime service descriptor for standard SMC calls */ +DECLARE_RT_SVC( + tlkd_tos_std, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_STD, + NULL, + tlkd_smc_handler +); diff --git a/services/spd/tlkd/tlkd_pm.c b/services/spd/tlkd/tlkd_pm.c new file mode 100644 index 0000000..5f2bae3 --- /dev/null +++ b/services/spd/tlkd/tlkd_pm.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#define MPIDR_CPU0 0x80000000 + +/******************************************************************************* + * Return the type of payload TLKD is dealing with. Report the current + * resident cpu (mpidr format) if it is a UP/UP migratable payload. + ******************************************************************************/ +static int32_t cpu_migrate_info(uint64_t *resident_cpu) +{ + /* the payload runs only on CPU0 */ + *resident_cpu = MPIDR_CPU0; + + /* Uniprocessor, not migrate capable payload */ + return PSCI_TOS_NOT_UP_MIG_CAP; +} + +/******************************************************************************* + * Structure populated by the Dispatcher to be given a chance to perform any + * bookkeeping before PSCI executes a power mgmt. operation. + ******************************************************************************/ +const spd_pm_ops_t tlkd_pm_ops = { + .svc_migrate_info = cpu_migrate_info, +}; diff --git a/services/spd/tlkd/tlkd_private.h b/services/spd/tlkd/tlkd_private.h new file mode 100644 index 0000000..88e720a --- /dev/null +++ b/services/spd/tlkd/tlkd_private.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TLKD_PRIVATE_H__ +#define __TLKD_PRIVATE_H__ + +#include +#include +#include +#include +#include + +/* + * This flag is used by the TLKD to determine if the SP is servicing a standard + * SMC request prior to programming the next entry into the SP e.g. if SP + * execution is preempted by a non-secure interrupt and handed control to the + * normal world. If another request which is distinct from what the SP was + * previously doing arrives, then this flag will be help the TLKD to either + * reject the new request or service it while ensuring that the previous context + * is not corrupted. + */ +#define STD_SMC_ACTIVE_FLAG_SHIFT 2 +#define STD_SMC_ACTIVE_FLAG_MASK 1 +#define get_std_smc_active_flag(state) (((state) >> STD_SMC_ACTIVE_FLAG_SHIFT) \ + & STD_SMC_ACTIVE_FLAG_MASK) +#define set_std_smc_active_flag(state) ((state) |= \ + (1 << STD_SMC_ACTIVE_FLAG_SHIFT)) +#define clr_std_smc_active_flag(state) ((state) &= \ + ~(STD_SMC_ACTIVE_FLAG_MASK \ + << STD_SMC_ACTIVE_FLAG_SHIFT)) + +/******************************************************************************* + * Secure Payload execution state information i.e. aarch32 or aarch64 + ******************************************************************************/ +#define SP_AARCH32 MODE_RW_32 +#define SP_AARCH64 MODE_RW_64 + +/******************************************************************************* + * Number of cpus that the present on this platform. TODO: Rely on a topology + * tree to determine this in the future to avoid assumptions about mpidr + * allocation + ******************************************************************************/ +#define TLKD_CORE_COUNT PLATFORM_CORE_COUNT + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define TLKD_C_RT_CTX_X19 0x0 +#define TLKD_C_RT_CTX_X20 0x8 +#define TLKD_C_RT_CTX_X21 0x10 +#define TLKD_C_RT_CTX_X22 0x18 +#define TLKD_C_RT_CTX_X23 0x20 +#define TLKD_C_RT_CTX_X24 0x28 +#define TLKD_C_RT_CTX_X25 0x30 +#define TLKD_C_RT_CTX_X26 0x38 +#define TLKD_C_RT_CTX_X27 0x40 +#define TLKD_C_RT_CTX_X28 0x48 +#define TLKD_C_RT_CTX_X29 0x50 +#define TLKD_C_RT_CTX_X30 0x58 +#define TLKD_C_RT_CTX_SIZE 0x60 +#define TLKD_C_RT_CTX_ENTRIES (TLKD_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLY__ + +#include +#include + +/* AArch64 callee saved general purpose register context structure. */ +DEFINE_REG_STRUCT(c_rt_regs, TLKD_C_RT_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(TLKD_C_RT_CTX_SIZE == sizeof(c_rt_regs_t), \ + assert_tlkd_c_rt_regs_size_mismatch); + +/******************************************************************************* + * Structure which helps the SPD to maintain the per-cpu state of the SP. + * 'state' - collection of flags to track SP state e.g. on/off + * 'mpidr' - mpidr to associate a context with a cpu + * 'c_rt_ctx' - stack address to restore C runtime context from after + * returning from a synchronous entry into the SP. + * 'cpu_ctx' - space to maintain SP architectural state + * 'saved_tsp_args' - space to store arguments for TSP arithmetic operations + * which will queried using the TSP_GET_ARGS SMC by TSP. + ******************************************************************************/ +typedef struct tlk_context { + uint32_t state; + uint64_t mpidr; + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; +} tlk_context_t; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +uint64_t tlkd_enter_sp(uint64_t *c_rt_ctx); +void __dead2 tlkd_exit_sp(uint64_t c_rt_ctx, uint64_t ret); +uint64_t tlkd_synchronous_sp_entry(tlk_context_t *tlk_ctx); +void __dead2 tlkd_synchronous_sp_exit(tlk_context_t *tlk_ctx, + uint64_t ret); +void tlkd_init_tlk_ep_state(struct entry_point_info *tlk_entry_point, + uint32_t rw, + uint64_t pc, + tlk_context_t *tlk_ctx); + +#endif /*__ASSEMBLY__*/ + +#endif /* __TLKD_PRIVATE_H__ */