diff options
Diffstat (limited to 'bl32')
-rw-r--r-- | bl32/tsp/aarch64/tsp_entrypoint.S | 269 | ||||
-rw-r--r-- | bl32/tsp/aarch64/tsp_request.S | 64 | ||||
-rw-r--r-- | bl32/tsp/tsp-fvp.mk | 40 | ||||
-rw-r--r-- | bl32/tsp/tsp.ld.S | 121 | ||||
-rw-r--r-- | bl32/tsp/tsp.mk | 57 | ||||
-rw-r--r-- | bl32/tsp/tsp_main.c | 355 |
6 files changed, 906 insertions, 0 deletions
diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S new file mode 100644 index 000000000..fd02fd892 --- /dev/null +++ b/bl32/tsp/aarch64/tsp_entrypoint.S @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2013-2014, 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 <bl_common.h> +#include <arch.h> +#include <tsp.h> + + + .globl tsp_entrypoint + .globl tsp_cpu_on_entry + .globl tsp_cpu_off_entry + .globl tsp_cpu_suspend_entry + .globl tsp_cpu_resume_entry + .globl tsp_fast_smc_entry + + /* --------------------------------------------- + * Populate the params in x0-x7 from the pointer + * to the smc args structure in x0. + * --------------------------------------------- + */ + .macro restore_args_call_smc + ldp x6, x7, [x0, #TSP_ARG6] + ldp x4, x5, [x0, #TSP_ARG4] + ldp x2, x3, [x0, #TSP_ARG2] + ldp x0, x1, [x0, #TSP_ARG0] + smc #0 + .endm + + .section .text, "ax"; .align 3 + + +tsp_entrypoint: ; .type tsp_entrypoint, %function + /*--------------------------------------------- + * Store the extents of the tzram available to + * BL32 for future use. + * TODO: We are assuming that x9-x10 will not be + * corrupted by any function before platform + * setup. + * --------------------------------------------- + */ + mov x9, x0 + mov x10, x1 + + /* --------------------------------------------- + * The entrypoint is expected to be executed + * only by the primary cpu (at least for now). + * So, make sure no secondary has lost its way. + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + bl platform_is_primary_cpu + cbz x0, tsp_entrypoint_panic + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + adr x0, early_exceptions + msr vbar_el1, x0 + + /* --------------------------------------------- + * Enable the instruction cache. + * --------------------------------------------- + */ + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_I_BIT + msr sctlr_el1, x0 + isb + + /* --------------------------------------------- + * Zero out NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section. + * --------------------------------------------- + */ + ldr x0, =__BSS_START__ + ldr x1, =__BSS_SIZE__ + bl zeromem16 + + ldr x0, =__COHERENT_RAM_START__ + ldr x1, =__COHERENT_RAM_UNALIGNED_SIZE__ + bl zeromem16 + + /* -------------------------------------------- + * Give ourselves a small coherent stack to + * ease the pain of initializing the MMU + * -------------------------------------------- + */ + mrs x0, mpidr_el1 + bl platform_set_coherent_stack + + /* --------------------------------------------- + * Perform early platform setup & platform + * specific early arch. setup e.g. mmu setup + * --------------------------------------------- + */ + mov x0, x9 + mov x1, x10 + bl bl32_early_platform_setup + bl bl32_plat_arch_setup + + /* --------------------------------------------- + * Give ourselves a stack allocated in Normal + * -IS-WBWA memory + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + bl platform_set_stack + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl tsp_main + + /* --------------------------------------------- + * Tell TSPD that we are done initialising + * --------------------------------------------- + */ + mov x1, x0 + mov x0, #TSP_ENTRY_DONE + smc #0 + +tsp_entrypoint_panic: + b tsp_entrypoint_panic + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu is to be turned off through a CPU_OFF + * psci call to ask the TSP to perform any + * bookeeping necessary. In the current + * implementation, the TSPD expects the TSP to + * re-initialise its state so nothing is done + * here except for acknowledging the request. + * --------------------------------------------- + */ +tsp_cpu_off_entry: ; .type tsp_cpu_off_entry, %function + bl tsp_cpu_off_main + restore_args_call_smc + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu is turned on using a CPU_ON psci call to + * ask the TSP to initialise itself i.e. setup + * the mmu, stacks etc. Minimal architectural + * state will be initialised by the TSPD when + * this function is entered i.e. Caches and MMU + * will be turned off, the execution state + * will be aarch64 and exceptions masked. + * --------------------------------------------- + */ +tsp_cpu_on_entry: ; .type tsp_cpu_on_entry, %function + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + adr x0, early_exceptions + msr vbar_el1, x0 + + /* --------------------------------------------- + * Enable the instruction cache. + * --------------------------------------------- + */ + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_I_BIT + msr sctlr_el1, x0 + isb + + /* -------------------------------------------- + * Give ourselves a small coherent stack to + * ease the pain of initializing the MMU + * -------------------------------------------- + */ + mrs x0, mpidr_el1 + bl platform_set_coherent_stack + + /* --------------------------------------------- + * Initialise the MMU + * --------------------------------------------- + */ + bl enable_mmu + + /* --------------------------------------------- + * Give ourselves a stack allocated in Normal + * -IS-WBWA memory + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + bl platform_set_stack + + /* --------------------------------------------- + * Enter C runtime to perform any remaining + * book keeping + * --------------------------------------------- + */ + bl tsp_cpu_on_main + restore_args_call_smc + + /* Should never reach here */ +tsp_cpu_on_entry_panic: + b tsp_cpu_on_entry_panic + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu is to be suspended through a CPU_SUSPEND + * psci call to ask the TSP to perform any + * bookeeping necessary. In the current + * implementation, the TSPD saves and restores + * the EL1 state. + * --------------------------------------------- + */ +tsp_cpu_suspend_entry: ; .type tsp_cpu_suspend_entry, %function + bl tsp_cpu_suspend_main + restore_args_call_smc + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu resumes execution after an earlier + * CPU_SUSPEND psci call to ask the TSP to + * restore its saved context. In the current + * implementation, the TSPD saves and restores + * EL1 state so nothing is done here apart from + * acknowledging the request. + * --------------------------------------------- + */ +tsp_cpu_resume_entry: ; .type tsp_cpu_resume_entry, %function + bl tsp_cpu_resume_main + restore_args_call_smc +tsp_cpu_resume_panic: + b tsp_cpu_resume_panic + + /*--------------------------------------------- + * This entrypoint is used by the TSPD to ask + * the TSP to service a fast smc request. + * --------------------------------------------- + */ +tsp_fast_smc_entry: ; .type tsp_fast_smc_entry, %function + bl tsp_fast_smc_handler + restore_args_call_smc +tsp_fast_smc_entry_panic: + b tsp_fast_smc_entry_panic + diff --git a/bl32/tsp/aarch64/tsp_request.S b/bl32/tsp/aarch64/tsp_request.S new file mode 100644 index 000000000..763e8fce1 --- /dev/null +++ b/bl32/tsp/aarch64/tsp_request.S @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013-2014, 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 <tsp.h> + + .globl tsp_get_magic + + .section .text, "ax"; .align 3 + + +/* + * This function raises an SMC to retrieve arguments from secure + * monitor/dispatcher, saves the returned arguments the array received in x0, + * and then returns to the caller + */ +tsp_get_magic: + /* Save address to stack */ + stp x0, xzr, [sp, #-16]! + + /* Load arguments */ + ldr w0, _tsp_fid_get_magic + + /* Raise SMC */ + smc #0 + + /* Restore address from stack */ + ldp x4, xzr, [sp], #16 + + /* Store returned arguments to the array */ + stp x0, x1, [x4, #0] + stp x2, x3, [x4, #16] + + ret + + .align 2 +_tsp_fid_get_magic: + .word TSP_GET_ARGS diff --git a/bl32/tsp/tsp-fvp.mk b/bl32/tsp/tsp-fvp.mk new file mode 100644 index 000000000..c5bbd7fc6 --- /dev/null +++ b/bl32/tsp/tsp-fvp.mk @@ -0,0 +1,40 @@ +# +# Copyright (c) 2013-2014, 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. +# + + +vpath %.c ${PLAT_BL2_C_VPATH} +vpath %.S ${PLAT_BL2_S_VPATH} + +# TSP source files specific to FVP platform +BL32_OBJS += bl32_plat_setup.o \ + bl32_setup_xlat.o \ + plat_common.o \ + ${BL_COMMON_OBJS} \ + ${PLAT_BL_COMMON_OBJS} diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S new file mode 100644 index 000000000..30d9a93bc --- /dev/null +++ b/bl32/tsp/tsp.ld.S @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2013-2014, 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 <platform.h> + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) + +MEMORY { + RAM (rwx): ORIGIN = TZDRAM_BASE, LENGTH = TZDRAM_SIZE +} + + +SECTIONS +{ + . = BL32_BASE; + ASSERT(. == ALIGN(4096), + "BL32_BASE address is not aligned on a page boundary.") + + ro . : { + __RO_START__ = .; + *tsp_entrypoint.o(.text) + *(.text) + *(.rodata*) + *(.vectors) + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = NEXT(4096); + __RO_END__ = .; + } >RAM + + .data . : { + __DATA_START__ = .; + *(.data) + __DATA_END__ = .; + } >RAM + + stacks (NOLOAD) : { + __STACKS_START__ = .; + *(tzfw_normal_stacks) + __STACKS_END__ = .; + } >RAM + + /* + * The .bss section gets initialised to 0 at runtime. + * Its base address must be 16-byte aligned. + */ + .bss : ALIGN(16) { + __BSS_START__ = .; + *(SORT_BY_ALIGNMENT(.bss)) + *(COMMON) + __BSS_END__ = .; + } >RAM + + /* + * The xlat_table section is for full, aligned page tables (4K). + * Removing them from .bss avoids forcing 4K alignment on + * the .bss section and eliminates the unecessary zero init + */ + xlat_table (NOLOAD) : { + *(xlat_table) + } >RAM + + /* + * The base address of the coherent memory section must be page-aligned (4K) + * to guarantee that the coherent data are stored on their own pages and + * are not mixed with normal data. This is required to set up the correct + * memory attributes for the coherent data page tables. + */ + coherent_ram (NOLOAD) : ALIGN(4096) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked + * as device memory. No other unexpected data must creep in. + * Ensure the rest of the current memory page is unused. + */ + . = NEXT(4096); + __COHERENT_RAM_END__ = .; + } >RAM + + __BL2_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; + + ASSERT(. <= TZDRAM_BASE + (1 << 21), "BL32 image does not fit in the first 2MB of Trusted DRAM.") +} diff --git a/bl32/tsp/tsp.mk b/bl32/tsp/tsp.mk new file mode 100644 index 000000000..923af5ca8 --- /dev/null +++ b/bl32/tsp/tsp.mk @@ -0,0 +1,57 @@ +# +# Copyright (c) 2013-2014, 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. +# + +vpath %.c common \ + lib \ + plat/${PLAT} \ + plat/${PLAT}/${ARCH} \ + arch/${ARCH} + +vpath %.S lib/arch/${ARCH} \ + include \ + lib/sync/locks/exclusive + +BL32_OBJS += tsp_entrypoint.o \ + tsp_main.o \ + tsp_request.o \ + spinlock.o \ + early_exceptions.o + +BL32_ENTRY_POINT := tsp_entrypoint +BL32_MAPFILE := tsp.map +BL32_LINKERFILE := tsp.ld + +vpath %.ld.S ${BL32_ROOT} +vpath %.c ${BL32_ROOT} +vpath %.c ${BL32_ROOT}/${ARCH} +vpath %.S ${BL32_ROOT}/${ARCH} + +# Include an optional platform-specific TSP Makefile +-include bl32/tsp/tsp-${PLAT}.mk diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c new file mode 100644 index 000000000..258bee49e --- /dev/null +++ b/bl32/tsp/tsp_main.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2013-2014, 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 <bl32.h> +#include <tsp.h> +#include <arch_helpers.h> +#include <stdio.h> +#include <platform.h> +#include <debug.h> +#include <spinlock.h> + +/******************************************************************************* + * Lock to control access to the console + ******************************************************************************/ +spinlock_t console_lock; + +/******************************************************************************* + * Per cpu data structure to populate parameters for an SMC in C code and use + * a pointer to this structure in assembler code to populate x0-x7 + ******************************************************************************/ +static tsp_args tsp_smc_args[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Per cpu data structure to keep track of TSP activity + ******************************************************************************/ +static work_statistics tsp_stats[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Single reference to the various entry points exported by the test secure + * payload. A single copy should suffice for all cpus as they are not expected + * to change. + ******************************************************************************/ +static const entry_info tsp_entry_info = { + tsp_fast_smc_entry, + tsp_cpu_on_entry, + tsp_cpu_off_entry, + tsp_cpu_resume_entry, + tsp_cpu_suspend_entry, +}; + +static tsp_args *set_smc_args(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint64_t mpidr = read_mpidr(); + uint32_t linear_id; + tsp_args *pcpu_smc_args; + + /* + * Return to Secure Monitor by raising an SMC. The results of the + * service are passed as an arguments to the SMC + */ + linear_id = platform_get_core_pos(mpidr); + pcpu_smc_args = &tsp_smc_args[linear_id]; + write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0); + write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1); + write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2); + write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3); + write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4); + write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5); + write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6); + write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7); + + return pcpu_smc_args; +} + +/******************************************************************************* + * TSP main entry point where it gets the opportunity to initialize its secure + * state/applications. Once the state is initialized, it must return to the + * SPD with a pointer to the 'tsp_entry_info' structure. + ******************************************************************************/ +uint64_t tsp_main(void) +{ + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + +#if DEBUG + meminfo *mem_layout = bl32_plat_sec_mem_layout(); +#endif + + /* Initialize the platform */ + bl32_platform_setup(); + + /* Initialize secure/applications state here */ + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_on_count++; + + spin_lock(&console_lock); +#if defined (__GNUC__) + printf("TSP Built : %s, %s\n\r", __TIME__, __DATE__); +#endif + INFO("Total memory base : 0x%x\n", mem_layout->total_base); + INFO("Total memory size : 0x%x bytes\n", mem_layout->total_size); + INFO("Free memory base : 0x%x\n", mem_layout->free_base); + INFO("Free memory size : 0x%x bytes\n", mem_layout->free_size); + INFO("cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr, + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_on_count); + spin_unlock(&console_lock); + + /* + * TODO: There is a massive assumption that the SPD and SP can see each + * other's memory without issues so it is safe to pass pointers to + * internal memory. Replace this with a shared communication buffer. + */ + return (uint64_t) &tsp_entry_info; +} + +/******************************************************************************* + * This function performs any remaining book keeping in the test secure payload + * after this cpu's architectural state has been setup in response to an earlier + * psci cpu_on request. + ******************************************************************************/ +tsp_args *tsp_cpu_on_main(void) +{ + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_on_count++; + + spin_lock(&console_lock); + printf("SP: cpu 0x%x turned on\n\r", mpidr); + INFO("cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr, + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_on_count); + spin_unlock(&console_lock); + + /* Indicate to the SPD that we have completed turned ourselves on */ + return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any remaining book keeping in the test secure payload + * before this cpu is turned off in response to a psci cpu_off request. + ******************************************************************************/ +tsp_args *tsp_cpu_off_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_off_count++; + + spin_lock(&console_lock); + printf("SP: cpu 0x%x off request\n\r", mpidr); + INFO("cpu 0x%x: %d smcs, %d erets %d cpu off requests\n", mpidr, + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_off_count); + spin_unlock(&console_lock); + + + /* + * Indicate to the SPD that we have completed + * this initialisation request. + */ + return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any book keeping in the test secure payload before + * this cpu's architectural state is saved in response to an earlier psci + * cpu_suspend request. + ******************************************************************************/ +tsp_args *tsp_cpu_suspend_main(uint64_t power_state, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_suspend_count++; + + spin_lock(&console_lock); + printf("SP: cpu 0x%x suspend request. power state: 0x%x\n\r", + mpidr, power_state); + INFO("cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", mpidr, + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_suspend_count); + spin_unlock(&console_lock); + + /* + * Indicate to the SPD that we have completed + * this initialisation request. + */ + return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any book keeping in the test secure payload after this + * cpu's architectural state has been restored after wakeup from an earlier psci + * cpu_suspend request. + ******************************************************************************/ +tsp_args *tsp_cpu_resume_main(uint64_t suspend_level, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_resume_count++; + + spin_lock(&console_lock); + printf("SP: cpu 0x%x resumed. suspend level %d \n\r", + mpidr, suspend_level); + INFO("cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", mpidr, + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_suspend_count); + spin_unlock(&console_lock); + + /* + * Indicate to the SPD that we have completed + * this initialisation request. + */ + return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * TSP fast smc handler. The secure monitor jumps to this function by + * doing the ERET after populating X0-X7 registers. The arguments are received + * in the function arguments in order. Once the service is rendered, this + * function returns to Secure Monitor by raising SMC + ******************************************************************************/ +tsp_args *tsp_fast_smc_handler(uint64_t func, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint64_t results[4]; + uint64_t service_args[4]; + + INFO("Received fast smc 0x%x on cpu 0x%x\n", func, read_mpidr()); + + /* Render sercure services and obtain results here */ + + results[0] = arg1; + results[1] = arg2; + results[2] = arg3; + results[3] = arg4; + + /* + * Request a service back from dispatcher/secure monitor. This call + * return and thereafter resume exectuion + */ + tsp_get_magic(service_args); + + /* Determine the function to perform based on the function ID */ + switch (func) { + case TSP_FID_ADD: + results[0] += service_args[0]; + results[1] += service_args[1]; + results[2] += service_args[2]; + results[3] += service_args[3]; + break; + case TSP_FID_SUB: + results[0] -= service_args[0]; + results[1] -= service_args[1]; + results[2] -= service_args[2]; + results[3] -= service_args[3]; + break; + case TSP_FID_MUL: + results[0] *= service_args[0]; + results[1] *= service_args[1]; + results[2] *= service_args[2]; + results[3] *= service_args[3]; + break; + case TSP_FID_DIV: + results[0] /= service_args[0] ? service_args[0] : 1; + results[1] /= service_args[1] ? service_args[1] : 1; + results[2] /= service_args[2] ? service_args[2] : 1; + results[3] /= service_args[3] ? service_args[3] : 1; + break; + default: + break; + } + + return set_smc_args(TSP_WORK_DONE, + results[0], + results[1], + results[2], + results[3], + 0, 0, 0); +} + |