aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile80
-rw-r--r--bl32/tsp/tsp-fvp.mk1
-rw-r--r--bl32/tsp/tsp.mk3
-rw-r--r--plat/fvp/plat_io_storage.c32
-rw-r--r--services/spd/tspd/tspd.mk57
-rw-r--r--services/spd/tspd/tspd_common.c150
-rw-r--r--services/spd/tspd/tspd_helpers.S103
-rw-r--r--services/spd/tspd/tspd_main.c208
-rw-r--r--services/spd/tspd/tspd_private.h134
9 files changed, 759 insertions, 9 deletions
diff --git a/Makefile b/Makefile
index a5a3a78..7b0f78b 100644
--- a/Makefile
+++ b/Makefile
@@ -70,6 +70,8 @@ ARCH ?= aarch64
# By default, build all platforms available
PLAT ?= all
+# By default, build no SPD component
+SPD ?= none
BUILD_BASE := ./build
BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${BUILD_TYPE}
@@ -79,6 +81,7 @@ BUILD_BL31 := ${BUILD_PLAT}/bl31
BUILD_DIRS := ${BUILD_BL1} ${BUILD_BL2} ${BUILD_BL31}
PLATFORMS := $(shell ls -I common plat/)
+SPDS := $(shell ls -I none services/spd)
HELP_PLATFORMS := $(shell echo ${PLATFORMS} | sed 's/ /|/g')
ifeq (${PLAT},)
@@ -111,13 +114,29 @@ ifneq (${PLAT},all)
include bl31/bl31.mk
endif
+# Include SPD Makefile if one has been specified
+ifneq (${SPD},none)
+ # We expect to locate an spd.mk under the specified SPD directory
+ SPD_MAKE := $(shell m="services/spd/${SPD}/${SPD}.mk"; [ -f "$$m" ] && echo "$$m")
+
+ ifeq (${SPD_MAKE},)
+ $(error Error: No services/spd/${SPD}/${SPD}.mk located)
+ endif
+ $(info Including ${SPD_MAKE})
+ include ${SPD_MAKE}
+
+ # If there's BL32 companion for the chosen SPD, and the SPD wants to build the
+ # BL2 from source, we expect that the SPD's Makefile would set NEED_BL32
+ # variable to "yes"
+endif
+
.PHONY: all msg_start ${PLATFORMS} dump clean realclean distclean bl1 bl2 bl31 cscope locate-checkpatch checkcodebase checkpatch fiptool fip locate-bl33
.SUFFIXES:
BL1_OBJS := $(addprefix ${BUILD_BL1}/,${BL1_OBJS} ${BL_COMMON_OBJS} ${PLAT_BL_COMMON_OBJS})
BL2_OBJS := $(addprefix ${BUILD_BL2}/,${BL2_OBJS} ${BL_COMMON_OBJS} ${PLAT_BL_COMMON_OBJS})
-BL31_OBJS := $(addprefix ${BUILD_BL31}/,${BL31_OBJS} ${BL_COMMON_OBJS} ${PLAT_BL_COMMON_OBJS})
+BL31_OBJS := $(addprefix ${BUILD_BL31}/,${BL31_OBJS} ${BL_COMMON_OBJS} ${PLAT_BL_COMMON_OBJS} ${SPD_OBJS})
BL1_MAPFILE := $(addprefix ${BUILD_BL1}/,${BL1_MAPFILE})
BL2_MAPFILE := $(addprefix ${BUILD_BL2}/,${BL2_MAPFILE})
BL31_MAPFILE := $(addprefix ${BUILD_BL31}/,${BL31_MAPFILE})
@@ -125,7 +144,6 @@ BL1_LINKERFILE := $(addprefix ${BUILD_BL1}/,${BL1_LINKERFILE})
BL2_LINKERFILE := $(addprefix ${BUILD_BL2}/,${BL2_LINKERFILE})
BL31_LINKERFILE := $(addprefix ${BUILD_BL31}/,${BL31_LINKERFILE})
-
INCLUDES += -Ilib/include/ \
-Idrivers/io \
-Iinclude/${ARCH}/ \
@@ -135,7 +153,8 @@ INCLUDES += -Ilib/include/ \
-Iinclude/stdlib \
-Iinclude/stdlib/sys \
-Iplat/${PLAT} \
- ${PLAT_INCLUDES}
+ ${PLAT_INCLUDES} \
+ ${SPD_INCLUDES}
ASFLAGS += -nostdinc -ffreestanding -Wa,--fatal-warnings \
-mgeneral-regs-only -D__ASSEMBLY__ ${INCLUDES} \
@@ -185,7 +204,7 @@ BASE_COMMIT ?= origin/master
# Variables for use with Firmware Image Package
FIPTOOLPATH ?= tools/fip_create
-FIPTOOL ?= ${FIPTOOLPATH}/fip_create
+FIPTOOL ?= ${FIPTOOLPATH}/fip_create
fiptool: ${FIPTOOL}
fip: ${BUILD_PLAT}/fip.bin
@@ -214,6 +233,53 @@ endif
endif
+# If BL32 needs to be built, provide necessary build rules and targets
+ifeq (${NEED_BL32},yes)
+BUILD_BL32 := ${BUILD_PLAT}/bl32
+BUILD_DIRS += ${BUILD_BL32}
+
+BL32_OBJS := $(addprefix ${BUILD_BL32}/,${BL32_OBJS})
+BL32_MAPFILE := $(addprefix ${BUILD_BL32}/,${BL32_MAPFILE})
+BL32_LINKERFILE := $(addprefix ${BUILD_BL32}/,${BL32_LINKERFILE})
+BL32_LDFLAGS := -Map=${BL32_MAPFILE} --script ${BL32_LINKERFILE} --entry=${BL32_ENTRY_POINT}
+
+bl32: ${BUILD_BL32} ${BUILD_PLAT}/bl32.bin
+all: bl32
+dump: bl32_dump
+.PHONY: bl32
+
+# Add BL32 image to FIP's input image list
+FIP_DEPS := bl32
+FIP_ARGS := --bl32 ${BUILD_PLAT}/bl32.bin
+
+${BUILD_BL32}/%.o: %.S
+ @echo " AS $<"
+ ${Q}${AS} ${ASFLAGS} -c $< -o $@
+
+${BUILD_BL32}/%.o: %.c
+ @echo " CC $<"
+ ${Q}${CC} ${CFLAGS} -c $< -o $@
+
+${BUILD_BL32}/%.ld: %.ld.S
+ @echo " PP $<"
+ ${Q}${AS} ${ASFLAGS} -P -E $< -o $@
+
+${BUILD_BL32}/bl32.elf: ${BL32_OBJS} ${BL32_LINKERFILE}
+ @echo " LD $@"
+ ${Q}${LD} -o $@ ${LDFLAGS} ${BL32_LDFLAGS} ${BL32_OBJS}
+
+${BUILD_PLAT}/bl32.bin: ${BUILD_BL32}/bl32.elf
+ @echo " BIN $@"
+ ${Q}${OC} -O binary $< $@
+ @echo
+ @echo "Built $@ successfully"
+ @echo
+
+bl32_dump:
+ ${Q}${OD} -d ${BUILD_BL32}/bl32.elf > ${BUILD_BL32}/bl32.dump
+endif
+
+
clean:
@echo " CLEAN"
${Q}rm -rf ${BUILD_PLAT}
@@ -323,13 +389,14 @@ ${BUILD_PLAT}/bl31.bin: ${BUILD_BL31}/bl31.elf
@echo "Built $@ successfully"
@echo
-${BUILD_PLAT}/fip.bin: bl2 bl31 locate-bl33 ${FIPTOOL}
+${BUILD_PLAT}/fip.bin: bl2 bl31 ${FIP_DEPS} locate-bl33 ${FIPTOOL}
@echo " CREATE FIRMWARE IMAGE PACKAGE $@"
@echo
${Q}${FIPTOOL} --dump \
--bl2 ${BUILD_PLAT}/bl2.bin \
--bl31 ${BUILD_PLAT}/bl31.bin \
--bl33 ${BL33} \
+ ${FIP_ARGS} \
$@
@echo
@@ -345,9 +412,8 @@ help:
@echo "PLAT is used to specify which platform you wish to build."
@echo ""
@echo "Supported Targets:"
- @echo " all Build the BL1, BL2 and BL31 binaries"
+ @echo " all Build the BL1, BL31 binaries"
@echo " bl1 Build the BL1 binary"
- @echo " bl2 Build the BL2 binary"
@echo " bl31 Build the BL31 binary"
@echo " checkcodebase Check the coding style of the entire source tree"
@echo " checkpatch Check the coding style on changes in the current"
diff --git a/bl32/tsp/tsp-fvp.mk b/bl32/tsp/tsp-fvp.mk
index c5bbd7f..2bf748e 100644
--- a/bl32/tsp/tsp-fvp.mk
+++ b/bl32/tsp/tsp-fvp.mk
@@ -36,5 +36,4 @@ vpath %.S ${PLAT_BL2_S_VPATH}
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.mk b/bl32/tsp/tsp.mk
index 923af5c..bc23315 100644
--- a/bl32/tsp/tsp.mk
+++ b/bl32/tsp/tsp.mk
@@ -42,7 +42,8 @@ BL32_OBJS += tsp_entrypoint.o \
tsp_main.o \
tsp_request.o \
spinlock.o \
- early_exceptions.o
+ early_exceptions.o \
+ ${BL_COMMON_OBJS}
BL32_ENTRY_POINT := tsp_entrypoint
BL32_MAPFILE := tsp.map
diff --git a/plat/fvp/plat_io_storage.c b/plat/fvp/plat_io_storage.c
index fd2d2b2..768c3c5 100644
--- a/plat/fvp/plat_io_storage.c
+++ b/plat/fvp/plat_io_storage.c
@@ -62,6 +62,7 @@ static io_dev_handle memmap_dev_handle;
static int fvp_bl2_policy(io_dev_handle *dev_handle, void **image_spec);
static int fvp_bl31_policy(io_dev_handle *dev_handle, void **image_spec);
+static int fvp_bl32_policy(io_dev_handle *dev_handle, void **image_spec);
static int fvp_bl33_policy(io_dev_handle *dev_handle, void **image_spec);
static int fvp_fip_policy(io_dev_handle *dev_handle, void **image_spec);
@@ -81,6 +82,11 @@ static io_file_spec bl31_file_spec = {
.mode = FOPEN_MODE_R
};
+static io_file_spec bl32_file_spec = {
+ .path = BL32_IMAGE_NAME,
+ .mode = FOPEN_MODE_R
+};
+
static io_file_spec bl33_file_spec = {
.path = BL33_IMAGE_NAME,
.mode = FOPEN_MODE_R
@@ -89,6 +95,7 @@ static io_file_spec bl33_file_spec = {
static plat_io_policy fvp_policy[] = {
{BL2_IMAGE_NAME, fvp_bl2_policy},
{BL31_IMAGE_NAME, fvp_bl31_policy},
+ {BL32_IMAGE_NAME, fvp_bl32_policy},
{BL33_IMAGE_NAME, fvp_bl33_policy},
{FIP_IMAGE_NAME, fvp_fip_policy},
{NULL, NULL}
@@ -194,6 +201,31 @@ static int fvp_bl31_policy(io_dev_handle *dev_handle, void **image_spec)
}
+/* Try to load BL32 from Firmware Image Package in FLASH first. If there is no
+ * FIP in FLASH or it is broken, try to load the file from semi-hosting.
+ */
+static int fvp_bl32_policy(io_dev_handle *dev_handle, void **image_spec)
+{
+ int result = IO_FAIL;
+ void *local_image_spec = &bl32_file_spec;
+
+ INFO("Loading BL32\n");
+ /* FIP first then fall back to semi-hosting */
+ result = open_fip(local_image_spec);
+ if (result == IO_SUCCESS) {
+ *dev_handle = fip_dev_handle;
+ *(io_file_spec **)image_spec = local_image_spec;
+ } else {
+ result = open_semihosting(local_image_spec);
+ if (result == IO_SUCCESS) {
+ *dev_handle = sh_dev_handle;
+ *(io_file_spec **)image_spec = local_image_spec;
+ }
+ }
+ return result;
+}
+
+
/* Try to load BL33 from Firmware Image Package in FLASH first. If there is no
* FIP in FLASH or it is broken, try to load the file from semi-hosting.
*/
diff --git a/services/spd/tspd/tspd.mk b/services/spd/tspd/tspd.mk
new file mode 100644
index 0000000..60a51a6
--- /dev/null
+++ b/services/spd/tspd/tspd.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.
+#
+
+TSPD_DIR := services/spd/tspd
+SPD_INCLUDES := -Iinclude/spd/tspd \
+ -I${TSPD_DIR}
+
+SPD_OBJS := tspd_common.o \
+ tspd_main.o \
+ tspd_helpers.o
+
+vpath %.c ${TSPD_DIR}
+vpath %.S ${TSPD_DIR}
+
+# This dispatcher is paired with a Test Secure Payload source and we intend to
+# build the Test Secure Payload along with this dispatcher.
+#
+# In cases where an associated Secure Payload lies outside this build
+# system/source tree, the the dispatcher Makefile can either invoke an external
+# build command or assume it pre-built
+
+BL32_ROOT := bl32/tsp
+
+# Include SP's Makefile. The assumption is that the TSP's build system is
+# compatible with that of Trusted Firmware, and it'll add and populate necessary
+# build targets and variables
+include ${BL32_ROOT}/tsp.mk
+
+# Let the top-level Makefile know that we intend to build the SP from source
+NEED_BL32 := yes
diff --git a/services/spd/tspd/tspd_common.c b/services/spd/tspd/tspd_common.c
new file mode 100644
index 0000000..1bfe696
--- /dev/null
+++ b/services/spd/tspd/tspd_common.c
@@ -0,0 +1,150 @@
+/*
+ * 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 <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <arch_helpers.h>
+#include <platform.h>
+#include <bl_common.h>
+#include <runtime_svc.h>
+#include <context_mgmt.h>
+#include <tspd_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.
+ ******************************************************************************/
+int32_t tspd_init_secure_context(uint64_t entrypoint,
+ uint32_t rw,
+ uint64_t mpidr,
+ tsp_context *tsp_ctx)
+{
+ uint32_t scr = read_scr(), sctlr = read_sctlr();
+ el1_sys_regs *el1_state;
+ uint32_t spsr;
+
+ /* Passing a NULL context is a critical programming error */
+ assert(tsp_ctx);
+
+ /*
+ * We support AArch64 TSP for now.
+ * TODO: Add support for AArch32 TSP
+ */
+ assert(rw == TSP_AARCH64);
+
+ /*
+ * This might look redundant if the context was statically
+ * allocated but this function cannot make that assumption.
+ */
+ memset(tsp_ctx, 0, sizeof(*tsp_ctx));
+
+ /* Set the right security state and register width for the SP */
+ scr &= ~SCR_NS_BIT;
+ scr &= ~SCR_RW_BIT;
+ if (rw == TSP_AARCH64)
+ scr |= SCR_RW_BIT;
+
+ /* Get a pointer to the S-EL1 context memory */
+ el1_state = get_sysregs_ctx(&tsp_ctx->cpu_ctx);
+
+ /*
+ * Program the sctlr to allow execution in S-EL1 with caches
+ * and mmu off
+ */
+ sctlr &= SCTLR_EE_BIT;
+ sctlr |= SCTLR_EL1_RES1;
+ write_ctx_reg(el1_state, CTX_SCTLR_EL1, sctlr);
+
+ /* Set this context as ready to be initialised i.e OFF */
+ tsp_ctx->state = TSP_STATE_OFF;
+
+ /* Associate this context with the cpu specified */
+ tsp_ctx->mpidr = mpidr;
+
+ cm_set_context(mpidr, &tsp_ctx->cpu_ctx, SECURE);
+ spsr = make_spsr(MODE_EL1, MODE_SP_ELX, rw);
+ cm_set_el3_eret_context(SECURE, entrypoint, spsr, scr);
+
+ cm_init_exception_stack(mpidr, SECURE);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function takes an SP context pointer and:
+ * 1. Applies the S-EL1 system register context from tsp_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 tsp_ctx->cpu_ctx are used to enter the secure payload image.
+ ******************************************************************************/
+uint64_t tspd_synchronous_sp_entry(tsp_context *tsp_ctx)
+{
+ uint64_t rc;
+
+ assert(tsp_ctx->c_rt_ctx == 0);
+
+ /* Apply the Secure EL1 system register context and switch to it */
+ assert(cm_get_context(read_mpidr(), SECURE) == &tsp_ctx->cpu_ctx);
+ cm_el1_sysregs_context_restore(SECURE);
+ cm_set_next_eret_context(SECURE);
+
+ rc = tspd_enter_sp(&tsp_ctx->c_rt_ctx);
+#if DEBUG
+ tsp_ctx->c_rt_ctx = 0;
+#endif
+
+ return rc;
+}
+
+
+/*******************************************************************************
+ * This function takes an SP context pointer and:
+ * 1. Saves the S-EL1 system register context tp tsp_ctx->cpu_ctx.
+ * 2. Restores the current C runtime state (callee saved registers) from the
+ * stack frame using the reference to this state saved in tspd_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 tspd_synchronous_sp_exit(tsp_context *tsp_ctx, uint64_t ret)
+{
+ /* Save the Secure EL1 system register context */
+ assert(cm_get_context(read_mpidr(), SECURE) == &tsp_ctx->cpu_ctx);
+ cm_el1_sysregs_context_save(SECURE);
+
+ assert(tsp_ctx->c_rt_ctx != 0);
+ tspd_exit_sp(tsp_ctx->c_rt_ctx, ret);
+
+ /* Should never reach here */
+ assert(0);
+}
diff --git a/services/spd/tspd/tspd_helpers.S b/services/spd/tspd/tspd_helpers.S
new file mode 100644
index 0000000..b56b2aa
--- /dev/null
+++ b/services/spd/tspd/tspd_helpers.S
@@ -0,0 +1,103 @@
+/*
+ * 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 <context.h>
+#include <tspd_private.h>
+#include <asm_macros.S>
+#include <cm_macros.S>
+
+ .global tspd_enter_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.
+ * ---------------------------------------------
+ */
+tspd_enter_sp:
+ /* Make space for the registers that we're going to save */
+ mov x3, sp
+ str x3, [x0, #0]
+ sub sp, sp, #TSPD_C_RT_CTX_SIZE
+
+ /* Save callee-saved registers on to the stack */
+ stp x19, x20, [sp, #TSPD_C_RT_CTX_X19]
+ stp x21, x22, [sp, #TSPD_C_RT_CTX_X21]
+ stp x23, x24, [sp, #TSPD_C_RT_CTX_X23]
+ stp x25, x26, [sp, #TSPD_C_RT_CTX_X25]
+ stp x27, x28, [sp, #TSPD_C_RT_CTX_X27]
+ stp x29, x30, [sp, #TSPD_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 'x0' pointing to a C
+ * runtime context saved in tspd_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
+ * ---------------------------------------------
+ */
+ .global tspd_exit_sp
+tspd_exit_sp:
+ /* Restore the previous stack */
+ mov sp, x0
+
+ /* Restore callee-saved registers on to the stack */
+ ldp x19, x20, [x0, #(TSPD_C_RT_CTX_X19 - TSPD_C_RT_CTX_SIZE)]
+ ldp x21, x22, [x0, #(TSPD_C_RT_CTX_X21 - TSPD_C_RT_CTX_SIZE)]
+ ldp x23, x24, [x0, #(TSPD_C_RT_CTX_X23 - TSPD_C_RT_CTX_SIZE)]
+ ldp x25, x26, [x0, #(TSPD_C_RT_CTX_X25 - TSPD_C_RT_CTX_SIZE)]
+ ldp x27, x28, [x0, #(TSPD_C_RT_CTX_X27 - TSPD_C_RT_CTX_SIZE)]
+ ldp x29, x30, [x0, #(TSPD_C_RT_CTX_X29 - TSPD_C_RT_CTX_SIZE)]
+
+ /* ---------------------------------------------
+ * This should take us back to the instruction
+ * after the call to the last tspd_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/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c
new file mode 100644
index 0000000..6896379
--- /dev/null
+++ b/services/spd/tspd/tspd_main.c
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+
+
+/*******************************************************************************
+ * 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 <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <arch_helpers.h>
+#include <console.h>
+#include <platform.h>
+#include <psci_private.h>
+#include <context_mgmt.h>
+#include <runtime_svc.h>
+#include <bl31.h>
+#include <tsp.h>
+#include <psci.h>
+#include <tspd_private.h>
+#include <debug.h>
+
+/*******************************************************************************
+ * Single structure to hold information about the various entry points into the
+ * Secure Payload. It is initialised once on the primary core after a cold boot.
+ ******************************************************************************/
+entry_info *tsp_entry_info;
+
+/*******************************************************************************
+ * Array to keep track of per-cpu Secure Payload state
+ ******************************************************************************/
+tsp_context tspd_sp_context[TSPD_CORE_COUNT];
+
+/*******************************************************************************
+ * 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 tspd_setup(void)
+{
+ el_change_info *image_info;
+ int32_t rc;
+ uint64_t mpidr = read_mpidr();
+ uint32_t linear_id;
+
+ linear_id = platform_get_core_pos(mpidr);
+
+ /*
+ * Get information about the Secure Payload (BL32) image. Its
+ * absence is a critical failure. TODO: Add support to
+ * conditionally include the SPD service
+ */
+ image_info = bl31_get_next_image_info(SECURE);
+ assert(image_info);
+
+ /*
+ * We could inspect the SP image and determine it's execution
+ * state i.e whether AArch32 or AArch64. Assuming it's AArch64
+ * for the time being.
+ */
+ rc = tspd_init_secure_context(image_info->entrypoint,
+ TSP_AARCH64,
+ mpidr,
+ &tspd_sp_context[linear_id]);
+ assert(rc == 0);
+
+ return rc;
+}
+
+/*******************************************************************************
+ * 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 tspd_setup() which can be directly used.
+ * It also assumes that a valid non-secure context has been initialised by PSCI
+ * so it does not need to save and restore any non-secure state. This function
+ * performs a synchronous entry into the Secure payload. The SP passes control
+ * back to this routine through a SMC. It also passes the extents of memory made
+ * available to BL32 by BL31.
+ ******************************************************************************/
+int32_t bl32_init(meminfo *bl32_meminfo)
+{
+ uint64_t mpidr = read_mpidr();
+ uint32_t linear_id = platform_get_core_pos(mpidr);
+ uint64_t rc;
+ tsp_context *tsp_ctx = &tspd_sp_context[linear_id];
+
+ /*
+ * Arrange for passing a pointer to the meminfo structure
+ * describing the memory extents available to the secure
+ * payload.
+ * TODO: We are passing a pointer to BL31 internal memory
+ * whereas this structure should be copied to a communication
+ * buffer between the SP and SPD.
+ */
+ write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
+ CTX_GPREG_X0,
+ (uint64_t) bl32_meminfo);
+
+ /* Arrange for an entry into the secure payload */
+ rc = tspd_synchronous_sp_entry(tsp_ctx);
+ assert(rc != 0);
+ if (rc)
+ tsp_ctx->state = TSP_STATE_ON;
+
+ return rc;
+}
+
+/*******************************************************************************
+ * 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 tspd_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)
+{
+ unsigned long mpidr = read_mpidr();
+ uint32_t linear_id = platform_get_core_pos(mpidr), ns;
+
+ /* 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 TSP_ENTRY_DONE:
+ if (ns)
+ SMC_RET1(handle, SMC_UNK);
+
+ /*
+ * Stash the SP entry points information. This is done
+ * only once on the primary cpu
+ */
+ assert(tsp_entry_info == NULL);
+ tsp_entry_info = (entry_info *) x1;
+
+ /*
+ * SP 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.
+ */
+ tspd_synchronous_sp_exit(&tspd_sp_context[linear_id], x1);
+
+ /* Should never reach here */
+ assert(0);
+
+ default:
+ panic();
+ }
+
+ SMC_RET1(handle, 0);
+}
+
+/* Define a SPD runtime service descriptor */
+DECLARE_RT_SVC(
+ spd,
+
+ OEN_TOS_START,
+ OEN_TOS_END,
+ SMC_TYPE_FAST,
+ tspd_setup,
+ tspd_smc_handler
+);
diff --git a/services/spd/tspd/tspd_private.h b/services/spd/tspd/tspd_private.h
new file mode 100644
index 0000000..2bc35c1
--- /dev/null
+++ b/services/spd/tspd/tspd_private.h
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#ifndef __SPD_PRIVATE_H__
+#define __SPD_PRIVATE_H__
+
+#include <context.h>
+#include <arch.h>
+#include <psci.h>
+#include <tsp.h>
+
+/*******************************************************************************
+ * Secure Payload PM state information e.g. SP is suspended, uninitialised etc
+ ******************************************************************************/
+#define TSP_STATE_OFF 0
+#define TSP_STATE_ON 1
+#define TSP_STATE_SUSPEND 2
+
+/*******************************************************************************
+ * Secure Payload execution state information i.e. aarch32 or aarch64
+ ******************************************************************************/
+#define TSP_AARCH32 MODE_RW_32
+#define TSP_AARCH64 MODE_RW_64
+
+/*******************************************************************************
+ * The SPD should know the type of Secure Payload.
+ ******************************************************************************/
+#define TSP_TYPE_UP PSCI_TOS_NOT_UP_MIG_CAP
+#define TSP_TYPE_UPM PSCI_TOS_UP_MIG_CAP
+#define TSP_TYPE_MP PSCI_TOS_NOT_PRESENT_MP
+
+/*******************************************************************************
+ * Secure Payload migrate type information as known to the SPD. We assume that
+ * the SPD is dealing with an MP Secure Payload.
+ ******************************************************************************/
+#define TSP_MIGRATE_INFO TSP_TYPE_MP
+
+/*******************************************************************************
+ * 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 TSPD_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 TSPD_C_RT_CTX_X19 0x0
+#define TSPD_C_RT_CTX_X20 0x8
+#define TSPD_C_RT_CTX_X21 0x10
+#define TSPD_C_RT_CTX_X22 0x18
+#define TSPD_C_RT_CTX_X23 0x20
+#define TSPD_C_RT_CTX_X24 0x28
+#define TSPD_C_RT_CTX_X25 0x30
+#define TSPD_C_RT_CTX_X26 0x38
+#define TSPD_C_RT_CTX_X27 0x40
+#define TSPD_C_RT_CTX_X28 0x48
+#define TSPD_C_RT_CTX_X29 0x50
+#define TSPD_C_RT_CTX_X30 0x58
+#define TSPD_C_RT_CTX_SIZE 0x60
+#define TSPD_C_RT_CTX_ENTRIES (TSPD_C_RT_CTX_SIZE >> DWORD_SHIFT)
+
+#ifndef __ASSEMBLY__
+
+/* AArch64 callee saved general purpose register context structure. */
+DEFINE_REG_STRUCT(c_rt_regs, TSPD_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(TSPD_C_RT_CTX_SIZE == sizeof(c_rt_regs), \
+ assert_spd_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
+ ******************************************************************************/
+typedef struct {
+ uint32_t state;
+ uint64_t mpidr;
+ uint64_t c_rt_ctx;
+ cpu_context cpu_ctx;
+} tsp_context;
+
+/*******************************************************************************
+ * Function & Data prototypes
+ ******************************************************************************/
+extern uint64_t tspd_enter_sp(uint64_t *c_rt_ctx);
+extern void __dead2 tspd_exit_sp(uint64_t c_rt_ctx, uint64_t ret);
+extern uint64_t tspd_synchronous_sp_entry(tsp_context *tsp_ctx);
+extern void __dead2 tspd_synchronous_sp_exit(tsp_context *tsp_ctx, uint64_t ret);
+extern int32_t tspd_init_secure_context(uint64_t entrypoint,
+ uint32_t rw,
+ uint64_t mpidr,
+ tsp_context *tsp_ctx);
+extern tsp_context tspd_sp_context[TSPD_CORE_COUNT];
+extern entry_info *tsp_entry_info;
+#endif /*__ASSEMBLY__*/
+
+#endif /* __SPD_PRIVATE_H__ */