summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile26
-rw-r--r--bl1/bl1.ld.S11
-rw-r--r--bl2/bl2.ld.S13
-rw-r--r--bl2u/bl2u.ld.S13
-rw-r--r--bl31/bl31.ld.S19
-rw-r--r--bl31/bl31.mk4
-rw-r--r--bl32/sp_min/sp_min.ld.S13
-rw-r--r--bl32/tsp/tsp.ld.S13
-rw-r--r--common/bl_common.c24
-rw-r--r--common/tf_printf.c43
-rw-r--r--docs/diagrams/secure_sw_stack_sp.pngbin0 -> 34909 bytes
-rw-r--r--docs/diagrams/secure_sw_stack_tos.pngbin0 -> 34202 bytes
-rw-r--r--docs/firmware-design.rst8
-rw-r--r--docs/plat/poplar.rst175
-rw-r--r--docs/plat/rpi3.rst364
-rw-r--r--docs/plat/socionext-uniphier.rst84
-rw-r--r--docs/secure-partition-manager-design.rst825
-rw-r--r--docs/spm-user-guide.rst59
-rw-r--r--docs/user-guide.rst29
-rw-r--r--drivers/io/io_block.c400
-rw-r--r--include/common/aarch64/el3_common_macros.S6
-rw-r--r--include/common/bl_common.h1
-rw-r--r--include/lib/aarch64/arch.h17
-rw-r--r--include/lib/aarch64/arch_helpers.h3
-rw-r--r--include/lib/extensions/sve.h12
-rw-r--r--include/lib/xlat_tables/xlat_tables_v2.h19
-rw-r--r--include/lib/xlat_tables/xlat_tables_v2_helpers.h4
-rw-r--r--include/plat/arm/board/common/board_arm_def.h6
-rw-r--r--include/plat/arm/common/arm_common.ld.S8
-rw-r--r--include/plat/arm/common/arm_def.h11
-rw-r--r--include/plat/arm/common/arm_spm_def.h6
-rw-r--r--include/services/spm_svc.h28
-rw-r--r--lib/cpus/aarch32/cortex_a53.S4
-rw-r--r--lib/cpus/aarch32/cortex_a57.S4
-rw-r--r--lib/cpus/aarch32/cortex_a72.S4
-rw-r--r--lib/el3_runtime/aarch64/context_mgmt.c5
-rw-r--r--lib/extensions/sve/sve.c126
-rw-r--r--maintainers.rst46
-rw-r--r--make_helpers/build_macros.mk46
-rw-r--r--make_helpers/defaults.mk12
-rw-r--r--plat/arm/board/fvp/fvp_pm.c16
-rw-r--r--plat/arm/board/fvp/include/platform_def.h4
-rw-r--r--plat/arm/board/juno/include/platform_def.h3
-rw-r--r--plat/arm/board/juno/platform.mk3
-rw-r--r--plat/arm/common/aarch64/arm_sdei.c19
-rw-r--r--plat/arm/common/arm_common.mk8
-rw-r--r--plat/arm/common/arm_tzc400.c4
-rw-r--r--plat/compat/plat_compat.mk3
-rw-r--r--plat/hisilicon/hikey/platform.mk3
-rw-r--r--plat/hisilicon/hikey960/hikey960_pm.c87
-rw-r--r--plat/hisilicon/hikey960/include/platform_def.h6
-rw-r--r--plat/hisilicon/hikey960/platform.mk3
-rw-r--r--plat/hisilicon/poplar/aarch64/platform_common.c5
-rw-r--r--plat/hisilicon/poplar/bl2_plat_setup.c49
-rw-r--r--plat/hisilicon/poplar/bl31_plat_setup.c32
-rw-r--r--plat/hisilicon/poplar/include/hi3798cv200.h5
-rw-r--r--plat/hisilicon/poplar/include/platform_def.h46
-rw-r--r--plat/hisilicon/poplar/include/poplar_layout.h6
-rw-r--r--plat/hisilicon/poplar/plat_storage.c9
-rw-r--r--plat/hisilicon/poplar/platform.mk13
-rw-r--r--plat/mediatek/mt6795/bl31.ld.S9
-rw-r--r--plat/mediatek/mt6795/platform.mk2
-rw-r--r--plat/mediatek/mt8173/platform.mk3
-rw-r--r--plat/nvidia/tegra/platform.mk3
-rw-r--r--plat/qemu/platform.mk3
-rw-r--r--plat/rockchip/rk3328/platform.mk5
-rw-r--r--plat/rockchip/rk3368/platform.mk5
-rw-r--r--plat/rockchip/rk3399/include/plat.ld.S20
-rw-r--r--plat/rockchip/rk3399/plat_sip_calls.c1
-rw-r--r--plat/rockchip/rk3399/platform.mk3
-rw-r--r--plat/rpi3/aarch64/plat_helpers.S183
-rw-r--r--plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c131
-rw-r--r--plat/rpi3/include/plat_macros.S23
-rw-r--r--plat/rpi3/include/platform_def.h229
-rw-r--r--plat/rpi3/platform.mk113
-rw-r--r--plat/rpi3/rpi3_bl1_setup.c63
-rw-r--r--plat/rpi3/rpi3_bl2_setup.c89
-rw-r--r--plat/rpi3/rpi3_bl31_setup.c168
-rw-r--r--plat/rpi3/rpi3_common.c166
-rw-r--r--plat/rpi3/rpi3_hw.h51
-rw-r--r--plat/rpi3/rpi3_image_load.c35
-rw-r--r--plat/rpi3/rpi3_io_storage.c251
-rw-r--r--plat/rpi3/rpi3_pm.c209
-rw-r--r--plat/rpi3/rpi3_private.h35
-rw-r--r--plat/rpi3/rpi3_topology.c56
-rw-r--r--plat/socionext/uniphier/include/platform_def.h2
-rw-r--r--plat/socionext/uniphier/platform.mk3
-rw-r--r--plat/xilinx/zynqmp/platform.mk3
-rw-r--r--services/std_svc/sdei/sdei_main.c4
-rw-r--r--services/std_svc/spm/secure_partition_setup.c8
-rw-r--r--services/std_svc/spm/spm_main.c119
-rw-r--r--services/std_svc/spm/spm_private.h3
-rw-r--r--tools/fiptool/fiptool.c17
93 files changed, 4241 insertions, 589 deletions
diff --git a/Makefile b/Makefile
index fe757984..1058b396 100644
--- a/Makefile
+++ b/Makefile
@@ -125,6 +125,7 @@ OC := ${CROSS_COMPILE}objcopy
OD := ${CROSS_COMPILE}objdump
NM := ${CROSS_COMPILE}nm
PP := ${CROSS_COMPILE}gcc -E
+DTC ?= dtc
ifeq (${ARM_ARCH_MAJOR},7)
target32-directive = -target arm-none-eabi
@@ -159,10 +160,19 @@ TF_CFLAGS += $(CPPFLAGS) $(TF_CFLAGS_$(ARCH)) \
-ffreestanding -fno-builtin -Wall -std=gnu99 \
-Os -ffunction-sections -fdata-sections
+GCC_V_OUTPUT := $(shell $(CC) -v 2>&1)
+PIE_FOUND := $(findstring --enable-default-pie,${GCC_V_OUTPUT})
+
+ifeq ($(PIE_FOUND),1)
+TF_CFLAGS += -fno-PIE
+endif
+
TF_LDFLAGS += --fatal-warnings -O1
TF_LDFLAGS += --gc-sections
TF_LDFLAGS += $(TF_LDFLAGS_$(ARCH))
+DTC_FLAGS += -I dts -O dtb
+
################################################################################
# Common sources and include directories
################################################################################
@@ -451,6 +461,10 @@ include bl31/bl31.mk
endif
endif
+ifdef FDT_SOURCES
+NEED_FDT := yes
+endif
+
################################################################################
# Build options checks
################################################################################
@@ -468,6 +482,7 @@ $(eval $(call assert_boolean,ENABLE_PMF))
$(eval $(call assert_boolean,ENABLE_PSCI_STAT))
$(eval $(call assert_boolean,ENABLE_RUNTIME_INSTRUMENTATION))
$(eval $(call assert_boolean,ENABLE_SPE_FOR_LOWER_ELS))
+$(eval $(call assert_boolean,ENABLE_SVE_FOR_NS))
$(eval $(call assert_boolean,ERROR_DEPRECATED))
$(eval $(call assert_boolean,GENERATE_COT))
$(eval $(call assert_boolean,GICV2_G0_FOR_EL3))
@@ -508,6 +523,7 @@ $(eval $(call add_define,ENABLE_PMF))
$(eval $(call add_define,ENABLE_PSCI_STAT))
$(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION))
$(eval $(call add_define,ENABLE_SPE_FOR_LOWER_ELS))
+$(eval $(call add_define,ENABLE_SVE_FOR_NS))
$(eval $(call add_define,ERROR_DEPRECATED))
$(eval $(call add_define,GICV2_G0_FOR_EL3))
$(eval $(call add_define,HW_ASSISTED_COHERENCY))
@@ -549,7 +565,7 @@ endif
# Build targets
################################################################################
-.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip fwu_fip certtool
+.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip fwu_fip certtool dtbs
.SUFFIXES:
all: msg_start
@@ -602,6 +618,13 @@ $(if ${BL2U}, ,$(eval $(call MAKE_BL,2u)))
$(eval $(call FWU_FIP_ADD_PAYLOAD,${BL2U_PATH},--ap-fwu-cfg))
endif
+# Expand build macros for the different images
+ifeq (${NEED_FDT},yes)
+$(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES)))
+$(eval $(call MAKE_FDT))
+dtbs: $(DTBS)
+endif
+
locate-checkpatch:
ifndef CHECKPATCH
$(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/scripts/checkpatch.pl")
@@ -729,6 +752,7 @@ help:
@echo " distclean Remove all build artifacts for all platforms"
@echo " certtool Build the Certificate generation tool"
@echo " fiptool Build the Firmware Image Package (FIP) creation tool"
+ @echo " dtbs Build the Flattened device tree (if required for the platform)"
@echo ""
@echo "Note: most build targets require PLAT to be set to a specific platform."
@echo ""
diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S
index 2c453bd2..e4c454b3 100644
--- a/bl1/bl1.ld.S
+++ b/bl1/bl1.ld.S
@@ -5,6 +5,7 @@
*/
#include <platform_def.h>
+#include <xlat_tables_defs.h>
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -18,7 +19,7 @@ MEMORY {
SECTIONS
{
. = BL1_RO_BASE;
- ASSERT(. == ALIGN(4096),
+ ASSERT(. == ALIGN(PAGE_SIZE),
"BL1_RO_BASE address is not aligned on a page boundary.")
#if SEPARATE_CODE_AND_RODATA
@@ -27,7 +28,7 @@ SECTIONS
*bl1_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__TEXT_END__ = .;
} >ROM
@@ -88,7 +89,7 @@ SECTIONS
"cpu_ops not defined for this platform.")
. = BL1_RW_BASE;
- ASSERT(BL1_RW_BASE == ALIGN(4096),
+ ASSERT(BL1_RW_BASE == ALIGN(PAGE_SIZE),
"BL1_RW_BASE address is not aligned on a page boundary.")
/*
@@ -141,7 +142,7 @@ SECTIONS
* 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 (NOLOAD) : ALIGN(PAGE_SIZE) {
__COHERENT_RAM_START__ = .;
*(tzfw_coherent_mem)
__COHERENT_RAM_END_UNALIGNED__ = .;
@@ -150,7 +151,7 @@ SECTIONS
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index f3ab7061..4fe78f9e 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -5,6 +5,7 @@
*/
#include <platform_def.h>
+#include <xlat_tables_defs.h>
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -18,7 +19,7 @@ MEMORY {
SECTIONS
{
. = BL2_BASE;
- ASSERT(. == ALIGN(4096),
+ ASSERT(. == ALIGN(PAGE_SIZE),
"BL2_BASE address is not aligned on a page boundary.")
#if SEPARATE_CODE_AND_RODATA
@@ -27,7 +28,7 @@ SECTIONS
*bl2_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
@@ -41,7 +42,7 @@ SECTIONS
KEEP(*(.img_parser_lib_descs))
__PARSER_LIB_DESCS_END__ = .;
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -64,7 +65,7 @@ SECTIONS
* 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);
+ . = NEXT(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -120,7 +121,7 @@ SECTIONS
* 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 (NOLOAD) : ALIGN(PAGE_SIZE) {
__COHERENT_RAM_START__ = .;
*(tzfw_coherent_mem)
__COHERENT_RAM_END_UNALIGNED__ = .;
@@ -129,7 +130,7 @@ SECTIONS
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S
index efae293d..da587172 100644
--- a/bl2u/bl2u.ld.S
+++ b/bl2u/bl2u.ld.S
@@ -5,6 +5,7 @@
*/
#include <platform_def.h>
+#include <xlat_tables_defs.h>
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -18,7 +19,7 @@ MEMORY {
SECTIONS
{
. = BL2U_BASE;
- ASSERT(. == ALIGN(4096),
+ ASSERT(. == ALIGN(PAGE_SIZE),
"BL2U_BASE address is not aligned on a page boundary.")
#if SEPARATE_CODE_AND_RODATA
@@ -27,14 +28,14 @@ SECTIONS
*bl2u_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
.rodata . : {
__RODATA_START__ = .;
*(.rodata*)
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -51,7 +52,7 @@ SECTIONS
* 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);
+ . = NEXT(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -107,7 +108,7 @@ SECTIONS
* 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 (NOLOAD) : ALIGN(PAGE_SIZE) {
__COHERENT_RAM_START__ = .;
*(tzfw_coherent_mem)
__COHERENT_RAM_END_UNALIGNED__ = .;
@@ -116,7 +117,7 @@ SECTIONS
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 7f442d00..dd046c43 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -5,6 +5,7 @@
*/
#include <platform_def.h>
+#include <xlat_tables_defs.h>
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -22,7 +23,7 @@ MEMORY {
SECTIONS
{
. = BL31_BASE;
- ASSERT(. == ALIGN(4096),
+ ASSERT(. == ALIGN(PAGE_SIZE),
"BL31_BASE address is not aligned on a page boundary.")
#if SEPARATE_CODE_AND_RODATA
@@ -31,7 +32,7 @@ SECTIONS
*bl31_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
@@ -66,7 +67,7 @@ SECTIONS
. = ALIGN(8);
#include <pubsub_events.h>
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -110,7 +111,7 @@ SECTIONS
* executable. No RW data from the next section must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -127,10 +128,10 @@ SECTIONS
* There's no need to include this into the RO section of BL31 because it
* doesn't need to be accessed by BL31.
*/
- spm_shim_exceptions : ALIGN(4096) {
+ spm_shim_exceptions : ALIGN(PAGE_SIZE) {
__SPM_SHIM_EXCEPTIONS_START__ = .;
*(.spm_shim_exceptions)
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__SPM_SHIM_EXCEPTIONS_END__ = .;
} >RAM
#endif
@@ -223,7 +224,7 @@ SECTIONS
__SP_IMAGE_XLAT_TABLES_START__ = .;
*secure_partition*.o(xlat_table)
/* Make sure that the rest of the page is empty. */
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__SP_IMAGE_XLAT_TABLES_END__ = .;
#endif
*(xlat_table)
@@ -236,7 +237,7 @@ SECTIONS
* 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 (NOLOAD) : ALIGN(PAGE_SIZE) {
__COHERENT_RAM_START__ = .;
/*
* Bakery locks are stored in coherent memory
@@ -251,7 +252,7 @@ SECTIONS
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index ebd0e71a..fdcc9313 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -54,6 +54,10 @@ ifeq (${ENABLE_AMU},1)
BL31_SOURCES += lib/extensions/amu/aarch64/amu.c
endif
+ifeq (${ENABLE_SVE_FOR_NS},1)
+BL31_SOURCES += lib/extensions/sve/sve.c
+endif
+
BL31_LINKERFILE := bl31/bl31.ld.S
# Flag used to indicate if Crash reporting via console should be included
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index 93259731..e798a0d3 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -5,6 +5,7 @@
*/
#include <platform_def.h>
+#include <xlat_tables_defs.h>
OUTPUT_FORMAT(elf32-littlearm)
OUTPUT_ARCH(arm)
@@ -18,7 +19,7 @@ MEMORY {
SECTIONS
{
. = BL32_BASE;
- ASSERT(. == ALIGN(4096),
+ ASSERT(. == ALIGN(PAGE_SIZE),
"BL32_BASE address is not aligned on a page boundary.")
#if SEPARATE_CODE_AND_RODATA
@@ -27,7 +28,7 @@ SECTIONS
*entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
@@ -54,7 +55,7 @@ SECTIONS
. = ALIGN(8);
#include <pubsub_events.h>
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -91,7 +92,7 @@ SECTIONS
* read-only, executable. No RW data from the next section must
* creep in. Ensure the rest of the current memory block is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -190,7 +191,7 @@ SECTIONS
* 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 (NOLOAD) : ALIGN(PAGE_SIZE) {
__COHERENT_RAM_START__ = .;
/*
* Bakery locks are stored in coherent memory
@@ -205,7 +206,7 @@ SECTIONS
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index 2b672efe..d256b46c 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -5,6 +5,7 @@
*/
#include <platform_def.h>
+#include <xlat_tables_defs.h>
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -19,7 +20,7 @@ MEMORY {
SECTIONS
{
. = BL32_BASE;
- ASSERT(. == ALIGN(4096),
+ ASSERT(. == ALIGN(PAGE_SIZE),
"BL32_BASE address is not aligned on a page boundary.")
#if SEPARATE_CODE_AND_RODATA
@@ -28,14 +29,14 @@ SECTIONS
*tsp_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
.rodata . : {
__RODATA_START__ = .;
*(.rodata*)
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -51,7 +52,7 @@ SECTIONS
* 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);
+ . = NEXT(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -106,7 +107,7 @@ SECTIONS
* 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 (NOLOAD) : ALIGN(PAGE_SIZE) {
__COHERENT_RAM_START__ = .;
*(tzfw_coherent_mem)
__COHERENT_RAM_END_UNALIGNED__ = .;
@@ -115,7 +116,7 @@ SECTIONS
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/common/bl_common.c b/common/bl_common.c
index e4473ed3..b0d1bfa7 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -200,14 +200,14 @@ size_t image_size(unsigned int image_id)
#if LOAD_IMAGE_V2
/*******************************************************************************
- * Generic function to load an image at a specific address given
+ * Internal function to load an image at a specific address given
* an image ID and extents of free memory.
*
* If the load is successful then the image information is updated.
*
* Returns 0 on success, a negative error code otherwise.
******************************************************************************/
-int load_image(unsigned int image_id, image_info_t *image_data)
+static int load_image(unsigned int image_id, image_info_t *image_data)
{
uintptr_t dev_handle;
uintptr_t image_handle;
@@ -266,17 +266,6 @@ int load_image(unsigned int image_id, image_info_t *image_data)
goto exit;
}
-#if !TRUSTED_BOARD_BOOT
- /*
- * File has been successfully loaded.
- * Flush the image to main memory so that it can be executed later by
- * any CPU, regardless of cache and MMU state.
- * When TBB is enabled the image is flushed later, after image
- * authentication.
- */
- flush_dcache_range(image_base, image_size);
-#endif /* TRUSTED_BOARD_BOOT */
-
INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
(void *) (image_base + image_size));
@@ -329,18 +318,19 @@ static int load_auth_image_internal(unsigned int image_id,
image_data->image_size);
return -EAUTH;
}
+#endif /* TRUSTED_BOARD_BOOT */
/*
- * File has been successfully loaded and authenticated.
* Flush the image to main memory so that it can be executed later by
- * any CPU, regardless of cache and MMU state.
- * Do it only for child images, not for the parents (certificates).
+ * any CPU, regardless of cache and MMU state. If TBB is enabled, then
+ * the file has been successfully loaded and authenticated and flush
+ * only for child images, not for the parents (certificates).
*/
if (!is_parent_image) {
flush_dcache_range(image_data->image_base,
image_data->image_size);
}
-#endif /* TRUSTED_BOARD_BOOT */
+
return 0;
}
diff --git a/common/tf_printf.c b/common/tf_printf.c
index f73842ac..d4039833 100644
--- a/common/tf_printf.c
+++ b/common/tf_printf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -31,7 +31,8 @@ void tf_string_print(const char *str)
putchar(*str++);
}
-static void unsigned_num_print(unsigned long long int unum, unsigned int radix)
+static void unsigned_num_print(unsigned long long int unum, unsigned int radix,
+ char padc, int padn)
{
/* Just need enough space to store 64 bit decimal integer */
unsigned char num_buf[20];
@@ -45,6 +46,12 @@ static void unsigned_num_print(unsigned long long int unum, unsigned int radix)
num_buf[i++] = 'a' + (rem - 0xa);
} while (unum /= radix);
+ if (padn > 0) {
+ while (i < padn--) {
+ putchar(padc);
+ }
+ }
+
while (--i >= 0)
putchar(num_buf[i]);
}
@@ -63,6 +70,9 @@ static void unsigned_num_print(unsigned long long int unum, unsigned int radix)
* %ll - long long int (64-bit on AArch64)
* %z - size_t sized integer formats (64 bit on AArch64)
*
+ * The following padding specifiers are supported by this print
+ * %0NN - Left-pad the number with 0s (NN is a decimal number)
+ *
* The print exits on all other formats specifiers other than valid
* combinations of the above specifiers.
*******************************************************************/
@@ -72,9 +82,12 @@ void tf_vprintf(const char *fmt, va_list args)
long long int num;
unsigned long long int unum;
char *str;
+ char padc = 0; /* Padding character */
+ int padn; /* Number of characters to pad */
while (*fmt) {
l_count = 0;
+ padn = 0;
if (*fmt == '%') {
fmt++;
@@ -87,10 +100,11 @@ loop:
if (num < 0) {
putchar('-');
unum = (unsigned long long int)-num;
+ padn--;
} else
unum = (unsigned long long int)num;
- unsigned_num_print(unum, 10);
+ unsigned_num_print(unum, 10, padc, padn);
break;
case 's':
str = va_arg(args, char *);
@@ -98,14 +112,16 @@ loop:
break;
case 'p':
unum = (uintptr_t)va_arg(args, void *);
- if (unum)
+ if (unum) {
tf_string_print("0x");
+ padn -= 2;
+ }
- unsigned_num_print(unum, 16);
+ unsigned_num_print(unum, 16, padc, padn);
break;
case 'x':
unum = get_unum_va_args(args, l_count);
- unsigned_num_print(unum, 16);
+ unsigned_num_print(unum, 16, padc, padn);
break;
case 'z':
if (sizeof(size_t) == 8)
@@ -119,8 +135,21 @@ loop:
goto loop;
case 'u':
unum = get_unum_va_args(args, l_count);
- unsigned_num_print(unum, 10);
+ unsigned_num_print(unum, 10, padc, padn);
break;
+ case '0':
+ padc = '0';
+ padn = 0;
+ fmt++;
+
+ while (1) {
+ char ch = *fmt;
+ if (ch < '0' || ch > '9') {
+ goto loop;
+ }
+ padn = (padn * 10) + (ch - '0');
+ fmt++;
+ }
default:
/* Exit on any other format specifier */
return;
diff --git a/docs/diagrams/secure_sw_stack_sp.png b/docs/diagrams/secure_sw_stack_sp.png
new file mode 100644
index 00000000..5cb2ca7a
--- /dev/null
+++ b/docs/diagrams/secure_sw_stack_sp.png
Binary files differ
diff --git a/docs/diagrams/secure_sw_stack_tos.png b/docs/diagrams/secure_sw_stack_tos.png
new file mode 100644
index 00000000..1f2d5550
--- /dev/null
+++ b/docs/diagrams/secure_sw_stack_tos.png
Binary files differ
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index 405964d2..3cb004a4 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -1868,9 +1868,11 @@ Firmware Image Package layout
The FIP layout consists of a table of contents (ToC) followed by payload data.
The ToC itself has a header followed by one or more table entries. The ToC is
-terminated by an end marker entry. All ToC entries describe some payload data
-that has been appended to the end of the binary package. With the information
-provided in the ToC entry the corresponding payload data can be retrieved.
+terminated by an end marker entry, and since the size of the ToC is 0 bytes,
+the offset equals the total size of the FIP file. All ToC entries describe some
+payload data that has been appended to the end of the binary package. With the
+information provided in the ToC entry the corresponding payload data can be
+retrieved.
::
diff --git a/docs/plat/poplar.rst b/docs/plat/poplar.rst
index d7f1fe06..01294783 100644
--- a/docs/plat/poplar.rst
+++ b/docs/plat/poplar.rst
@@ -11,6 +11,8 @@ of running any commercial set-top solution based on Linux or Android.
It supports a premium user experience with up to H.265 HEVC decoding of 4K
video at 60 frames per second.
+::
+
SOC Hisilicon Hi3798CV200
CPU Quad-core ARM Cortex-A53 64 bit
DRAM DDR3/3L/4 SDRAM interface, maximum 32-bit data width 2 GB
@@ -28,6 +30,8 @@ At the start of the boot sequence, the bootROM executes the so called l-loader
binary whose main role is to change the processor state to 64bit mode. This
must happen prior invoking the arm trusted firmware:
+::
+
l-loader --> arm_trusted_firmware --> u-boot
How to build
@@ -54,10 +58,16 @@ Build Procedure
- Prepare the AARCH64 toolchain.
- Build u-boot using poplar_defconfig
+
+.. code:: bash
+
make CROSS_COMPILE=aarch64-linux-gnu- poplar_defconfig
make CROSS_COMPILE=aarch64-linux-gnu-
- Build atf providing the previously generated u-boot.bin as the BL33 image
+
+.. code:: bash
+
make CROSS_COMPILE=aarch64-linux-gnu- all fip SPD=none PLAT=poplar
BL33=u-boot.bin
@@ -81,85 +91,86 @@ working firmware to eMMC.
Boot trace
==========
-Bootrom start
-Boot Media: eMMC
-Decrypt auxiliary code ...OK
-
-lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000
-
-Entry boot auxiliary code
-
-Auxiliary code - v1.00
-DDR code - V1.1.2 20160205
-Build: Mar 24 2016 - 17:09:44
-Reg Version: v134
-Reg Time: 2016/03/18 09:44:55
-Reg Name: hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg
-
-Boot auxiliary code success
-Bootrom success
-
-LOADER: Switched to aarch64 mode
-LOADER: Entering ARM TRUSTED FIRMWARE
-LOADER: CPU0 executes at 0x000ce000
-
-INFO: BL1: 0xe1000 - 0xe7000 [size = 24576]
-NOTICE: Booting Trusted Firmware
-NOTICE: BL1: v1.3(debug):v1.3-372-g1ba9c60
-NOTICE: BL1: Built : 17:51:33, Apr 30 2017
-INFO: BL1: RAM 0xe1000 - 0xe7000
-INFO: BL1: Loading BL2
-INFO: Loading image id=1 at address 0xe9000
-INFO: Image id=1 loaded at address 0xe9000, size = 0x5008
-NOTICE: BL1: Booting BL2
-INFO: Entry point address = 0xe9000
-INFO: SPSR = 0x3c5
-NOTICE: BL2: v1.3(debug):v1.3-372-g1ba9c60
-NOTICE: BL2: Built : 17:51:33, Apr 30 2017
-INFO: BL2: Loading BL31
-INFO: Loading image id=3 at address 0x129000
-INFO: Image id=3 loaded at address 0x129000, size = 0x8038
-INFO: BL2: Loading BL33
-INFO: Loading image id=5 at address 0x37000000
-INFO: Image id=5 loaded at address 0x37000000, size = 0x58f17
-NOTICE: BL1: Booting BL31
-INFO: Entry point address = 0x129000
-INFO: SPSR = 0x3cd
-INFO: Boot bl33 from 0x37000000 for 364311 Bytes
-NOTICE: BL31: v1.3(debug):v1.3-372-g1ba9c60
-NOTICE: BL31: Built : 17:51:33, Apr 30 2017
-INFO: BL31: Initializing runtime services
-INFO: BL31: Preparing for EL3 exit to normal world
-INFO: Entry point address = 0x37000000
-INFO: SPSR = 0x3c9
-
-
-U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar
-
-Model: HiSilicon Poplar Development Board
-BOARD: Hisilicon HI3798cv200 Poplar
-DRAM: 1 GiB
-MMC: Hisilicon DWMMC: 0
-In: serial@f8b00000
-Out: serial@f8b00000
-Err: serial@f8b00000
-Net: Net Initialization Skipped
-No ethernet found.
-
-Hit any key to stop autoboot: 0
-starting USB...
-USB0: USB EHCI 1.00
-scanning bus 0 for devices... 1 USB Device(s) found
-USB1: USB EHCI 1.00
-scanning bus 1 for devices... 4 USB Device(s) found
- scanning usb for storage devices... 1 Storage Device(s) found
- scanning usb for ethernet devices... 1 Ethernet Device(s) found
-
-USB device 0:
- Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade
- Type: Removable Hard Disk
- Capacity: 7632.0 MB = 7.4 GB (15630336 x 512)
-... is now current device
-Scanning usb 0:1...
-=>
-
+::
+
+ Bootrom start
+ Boot Media: eMMC
+ Decrypt auxiliary code ...OK
+
+ lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000
+
+ Entry boot auxiliary code
+
+ Auxiliary code - v1.00
+ DDR code - V1.1.2 20160205
+ Build: Mar 24 2016 - 17:09:44
+ Reg Version: v134
+ Reg Time: 2016/03/18 09:44:55
+ Reg Name: hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg
+
+ Boot auxiliary code success
+ Bootrom success
+
+ LOADER: Switched to aarch64 mode
+ LOADER: Entering ARM TRUSTED FIRMWARE
+ LOADER: CPU0 executes at 0x000ce000
+
+ INFO: BL1: 0xe1000 - 0xe7000 [size = 24576]
+ NOTICE: Booting Trusted Firmware
+ NOTICE: BL1: v1.3(debug):v1.3-372-g1ba9c60
+ NOTICE: BL1: Built : 17:51:33, Apr 30 2017
+ INFO: BL1: RAM 0xe1000 - 0xe7000
+ INFO: BL1: Loading BL2
+ INFO: Loading image id=1 at address 0xe9000
+ INFO: Image id=1 loaded at address 0xe9000, size = 0x5008
+ NOTICE: BL1: Booting BL2
+ INFO: Entry point address = 0xe9000
+ INFO: SPSR = 0x3c5
+ NOTICE: BL2: v1.3(debug):v1.3-372-g1ba9c60
+ NOTICE: BL2: Built : 17:51:33, Apr 30 2017
+ INFO: BL2: Loading BL31
+ INFO: Loading image id=3 at address 0x129000
+ INFO: Image id=3 loaded at address 0x129000, size = 0x8038
+ INFO: BL2: Loading BL33
+ INFO: Loading image id=5 at address 0x37000000
+ INFO: Image id=5 loaded at address 0x37000000, size = 0x58f17
+ NOTICE: BL1: Booting BL31
+ INFO: Entry point address = 0x129000
+ INFO: SPSR = 0x3cd
+ INFO: Boot bl33 from 0x37000000 for 364311 Bytes
+ NOTICE: BL31: v1.3(debug):v1.3-372-g1ba9c60
+ NOTICE: BL31: Built : 17:51:33, Apr 30 2017
+ INFO: BL31: Initializing runtime services
+ INFO: BL31: Preparing for EL3 exit to normal world
+ INFO: Entry point address = 0x37000000
+ INFO: SPSR = 0x3c9
+
+
+ U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar
+
+ Model: HiSilicon Poplar Development Board
+ BOARD: Hisilicon HI3798cv200 Poplar
+ DRAM: 1 GiB
+ MMC: Hisilicon DWMMC: 0
+ In: serial@f8b00000
+ Out: serial@f8b00000
+ Err: serial@f8b00000
+ Net: Net Initialization Skipped
+ No ethernet found.
+
+ Hit any key to stop autoboot: 0
+ starting USB...
+ USB0: USB EHCI 1.00
+ scanning bus 0 for devices... 1 USB Device(s) found
+ USB1: USB EHCI 1.00
+ scanning bus 1 for devices... 4 USB Device(s) found
+ scanning usb for storage devices... 1 Storage Device(s) found
+ scanning usb for ethernet devices... 1 Ethernet Device(s) found
+
+ USB device 0:
+ Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade
+ Type: Removable Hard Disk
+ Capacity: 7632.0 MB = 7.4 GB (15630336 x 512)
+ ... is now current device
+ Scanning usb 0:1...
+ =>
diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst
new file mode 100644
index 00000000..219faaff
--- /dev/null
+++ b/docs/plat/rpi3.rst
@@ -0,0 +1,364 @@
+Arm Trusted Firmware for Raspberry Pi 3
+=======================================
+
+.. section-numbering::
+ :suffix: .
+
+.. contents::
+
+The `Raspberry Pi 3`_ is an inexpensive single-board computer that contains four
+Cortex-A53 cores, which makes it possible to have a port of the Arm Trusted
+Firmware.
+
+The following instructions explain how to use this port of the Trusted Firmware
+with the default distribution of `Raspbian`_ because that's the distribution
+officially supported by the Raspberry Pi Foundation. At the moment of writing
+this, the officially supported kernel is a AArch32 kernel. This doesn't mean
+that this port of the Trusted Firmware can't boot a AArch64 kernel. The `Linux
+tree fork`_ maintained by the Foundation can be compiled for AArch64 by
+following the steps in `AArch64 kernel build instructions`_.
+
+**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM,
+which is available from both the Non-secure and Secure worlds. This port
+shouldn't be considered more than a prototype to play with and implement
+elements like PSCI to support the Linux kernel.
+
+Design
+------
+
+The SoC used by the Raspberry Pi 3 is the Broadcom BCM2837. It is a SoC with a
+VideoCore IV that acts as primary processor (and loads everything from the SD
+card) and is located between all Arm cores and the DRAM. Check the `Raspberry Pi
+3 documentation`_ for more information.
+
+This explains why it is possible to change the execution state (AArch64/AArch32)
+depending on a few files on the SD card. We only care about the cases in which
+the cores boot in AArch64 mode.
+
+The rules are simple:
+
+- If a file called ``kernel8.img`` is located on the ``boot`` partition of the
+ SD card, it will load it and execute in EL2 in AArch64. Basically, it executes
+ a `default AArch64 stub`_ at address **0x0** that jumps to the kernel.
+
+- If there is also a file called ``armstub8.bin``, it will load it at address
+ **0x0** (instead of the default stub) and execute it in EL3 in AArch64. All
+ the cores are powered on at the same time and start at address **0x0**.
+
+This means that we can use the default AArch32 kernel provided in the official
+`Raspbian`_ distribution by renaming it to ``kernel8.img``, while the Trusted
+Firmware and anything else we need is in ``armstub8.bin``. This way we can
+forget about the default bootstrap code. When using a AArch64 kernel, it is only
+needed to make sure that the name on the SD card is ``kernel8.img``.
+
+Ideally, we want to load the kernel and have all cores available, which means
+that we need to make the secondary cores work in the way the kernel expects, as
+explained in `Secondary cores`_. In practice, a small bootstrap is needed
+between the Trusted Firmware and the kernel.
+
+To get the most out of a AArch32 kernel, we want to boot it in Hypervisor mode
+in AArch32. This means that BL33 can't be in EL2 in AArch64 mode. The
+architecture specifies that AArch32 Hypervisor mode isn't present when AArch64
+is used for EL2. When using a AArch64 kernel, it should simply start in EL2.
+
+Placement of images
+~~~~~~~~~~~~~~~~~~~
+
+The file ``armstub8.bin`` contains BL1 and the FIP. It is needed to add padding
+between them so that the addresses they are loaded to match the ones specified
+when compiling the Trusted Firmware.
+
+The device tree block is loaded by the VideoCore loader from an appropriate
+file, but we can specify the address it is loaded to in ``config.txt``.
+
+The file ``kernel8.img`` contains a kernel image that is loaded to the address
+specified in ``config.txt``. The `Linux kernel tree`_ has information about how
+a AArch32 Linux kernel image is loaded in ``Documentation/arm/Booting``:
+
+::
+
+ The zImage may also be placed in system RAM and called there. The
+ kernel should be placed in the first 128MiB of RAM. It is recommended
+ that it is loaded above 32MiB in order to avoid the need to relocate
+ prior to decompression, which will make the boot process slightly
+ faster.
+
+There are no similar restrictions for AArch64 kernels, as specified in the file
+``Documentation/arm64/booting.txt``.
+
+This means that we need to avoid the first 128 MiB of RAM when placing the
+Trusted Firmware images (and specially the first 32 MiB, as they are directly
+used to place the uncompressed AArch32 kernel image. This way, both AArch32 and
+AArch64 kernels can be placed at the same address.
+
+In the end, the images look like the following diagram when placed in memory.
+All addresses are Physical Addresses from the point of view of the Arm cores.
+Again, note that this is all just part of the same DRAM that goes from
+**0x00000000** to **0x3F000000**, it just has different names to simulate a real
+secure platform!
+
+::
+
+ 0x00000000 +-----------------+
+ | ROM | BL1
+ 0x00010000 +-----------------+
+ | FIP |
+ 0x00200000 +-----------------+
+ | |
+ | ... |
+ | |
+ 0x01000000 +-----------------+
+ | Kernel |
+ +-----------------+
+ | |
+ | ... |
+ | |
+ 0x02000000 +-----------------+
+ | DTB |
+ +-----------------+
+ | |
+ | ... |
+ | |
+ 0x10000000 +-----------------+
+ | Secure SRAM | BL2, BL31
+ 0x10100000 +-----------------+
+ | Secure DRAM |
+ 0x10300000 +-----------------+
+ | Non-secure DRAM | BL33
+ 0x11000000 +-----------------+
+ | |
+ | ... |
+ | |
+ 0x3F000000 +-----------------+
+ | I/O |
+ 0x40000000 +-----------------+
+
+The area between **0x10000000** and **0x11000000** has to be protected so that
+the kernel doesn't use it. That is done by adding ``memmap=256M$16M`` to the
+command line passed to the kernel. See the `Setup SD card`_ instructions to see
+how to do it.
+
+The last 16 MiB of DRAM can only be accessed by the VideoCore, that has
+different mappings than the Arm cores in which the I/O addresses don't overlap
+the DRAM. The memory reserved to be used by the VideoCore is always placed at
+the end of the DRAM, so this space isn't wasted.
+
+Considering the 128 MiB allocated to the GPU and the 16 MiB allocated for the
+Trusted Firmware, there are 880 MiB available for Linux.
+
+Boot sequence
+~~~~~~~~~~~~~
+
+The boot sequence of the Trusted Firmware is the usual one except when booting
+a AArch32 kernel. In that case, BL33 is booted in AArch32 Hypervisor mode so
+that it can jump to the kernel in the same mode and let it take over that
+privilege level. If BL33 was running in EL2 in AArch64 (as in the default
+bootflow of the Trusted Firmware) it could only jump to the kernel in AArch32 in
+Supervisor mode.
+
+The `Linux kernel tree`_ has instructions on how to jump to the Linux kernel
+in ``Documentation/arm/Booting`` and ``Documentation/arm64/booting.txt``. The
+bootstrap should take care of this.
+
+Secondary cores
+~~~~~~~~~~~~~~~
+
+The kernel used by `Raspbian`_ doesn't have support for PSCI, so it is needed to
+use mailboxes to trap the secondary cores until they are ready to jump to the
+kernel. This mailbox is located at a different address in the AArch32 default
+kernel than in the AArch64 kernel.
+
+Also, this port of the Trusted Firmware has another Trusted Mailbox in Shared BL
+RAM. During cold boot, all secondary cores wait in a loop until they are given
+given an address to jump to in this Mailbox (``bl31_warm_entrypoint``).
+
+Once BL31 has finished and the primary core has jumped to the BL33 payload, it
+has to call ``PSCI_CPU_ON`` to release the secondary CPUs from the wait loop.
+The payload then makes them wait in another waitloop listening from messages
+from the kernel. When the primary CPU jumps into the kernel, it will send an
+address to the mailbox so that the secondary CPUs jump to it and are recognised
+by the kernel.
+
+Build Instructions
+------------------
+
+To boot a AArch64 kernel, only the AArch64 toolchain is required.
+
+To boot a AArch32 kernel, both AArch64 and AArch32 toolchains are required. The
+AArch32 toolchain is needed for the AArch32 bootstrap needed to load a 32-bit
+kernel.
+
+First, clone and compile `Raspberry Pi 3 Arm Trusted Firmware bootstrap`_.
+Choose the one needed for the architecture of your kernel.
+
+Then compile the Arm Trusted Firmware. For a AArch32 kernel, use the following
+command line:
+
+.. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
+ RPI3_BL33_IN_AARCH32=1 \
+ BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin \
+ all fip
+
+For a AArch64 kernel, use this other command line:
+
+.. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
+ BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin \
+ all fip
+
+Then, join BL1 and the FIP with the following instructions (replace ``release``
+by ``debug`` if you set the build option ``DEBUG=1``):
+
+.. code:: shell
+
+ cp build/rpi3/release/bl1.bin bl1.pad.bin
+ truncate --size=65536 bl1.pad.bin
+ cat bl1.pad.bin build/rpi3/release/fip.bin > armstub8.bin
+
+The resulting file, ``armstub8.bin``, contains BL1 and the FIP in the place they
+need to be for the Trusted Firmware to boot correctly. Now, follow the
+instructions in `Setup SD card`_.
+
+The following build options are supported:
+
+- ``PRELOADED_BL33_BASE``: Specially useful because the file ``kernel8.img`` can
+ be loaded anywhere by modifying the file ``config.txt``. It doesn't have to
+ contain a kernel, it could have any arbitrary payload.
+
+- ``RESET_TO_BL31``: Set to 1 by default. If using a 32-bit kernel like
+ `Raspbian`_, the space used by BL1 can overwritten by the kernel when it is
+ being loaded. Even when using a AArch64 kernel the region used by
+ BL1 isn't protected and the kernel could overwrite it. The space used by BL31
+ is reserved by the command line passed to the kernel.
+
+- ``RPI3_BL33_IN_AARCH32``: This port can load a AArch64 or AArch32 BL33 image.
+ By default this option is 0, which means that the Trusted Firmware will jump
+ to BL33 in EL2 in AArch64 mode. If set to 1, it will jump to BL33 in
+ Hypervisor in AArch32 mode.
+
+The following is not currently supported:
+
+- AArch32 for the Trusted Firmware itself.
+
+- ``EL3_PAYLOAD_BASE``: The reason is that you can already load anything to any
+ address by changing the file ``armstub8.bin``, so there's no point in using
+ the Trusted Firmware in this case.
+
+- ``LOAD_IMAGE_V2=0``: Only version 2 is supported.
+
+AArch64 kernel build instructions
+---------------------------------
+
+The following instructions show how to install and run a AArch64 kernel by
+using a SD card with the default `Raspbian`_ install as base. Skip them if you
+want to use the default 32-bit kernel.
+
+Note that this system won't be fully 64-bit because all the tools in the
+filesystem are 32-bit binaries, but it's a quick way to get it working, and it
+allows the user to run 64-bit binaries in addition to 32-bit binaries.
+
+1. Clone the `Linux tree fork`_ maintained by the Raspberry Pi Foundation. To
+ speed things up, do a shallow clone of the desired branch.
+
+.. code:: shell
+
+ git clone --depth=1 -b rpi-4.14.y https://github.com/raspberrypi/linux
+ cd linux
+
+2. Configure and compile the kernel. Adapt the number after ``-j`` so that it is
+ 1.5 times the number of CPUs in your computer. This may take some time to
+ finish.
+
+.. code:: shell
+
+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig
+ make -j 6 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
+
+3. Copy the kernel image and the device tree to the SD card. Replace the path
+ by the corresponding path in your computers to the ``boot`` partition of the
+ SD card.
+
+.. code:: shell
+
+ cp arch/arm64/boot/Image /path/to/boot/kernel8.img
+ cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /path/to/boot/
+
+4. Install the kernel modules. Replace the path by the corresponding path to the
+ filesystem partition of the SD card on your computer.
+
+.. code:: shell
+
+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \
+ INSTALL_MOD_PATH=/path/to/filesystem modules_install
+
+5. Follow the instructions in `Setup SD card`_ except for the step of renaming
+ the existing ``kernel7.img`` (we have already copied a AArch64 kernel).
+
+Setup SD card
+-------------
+
+The instructions assume that you have an SD card with a fresh install of
+`Raspbian`_ (or that, at least, the ``boot`` partition is untouched, or nearly
+untouched). They have been tested with the image available in 2017-09-07.
+
+1. Insert the SD card and open the ``boot`` partition.
+
+2. Rename ``kernel7.img`` to ``kernel8.img``. This tricks the VideoCore
+ bootloader into booting the Arm cores in AArch64 mode, like the Trusted
+ Firmware needs, even though the kernel is not compiled for AArch64.
+
+3. Copy ``armstub8.bin`` here. When ``kernel8.img`` is available, The VideoCore
+ bootloader will look for a file called ``armstub8.bin`` and load it at
+ address **0x0** instead of a predefined one.
+
+4. Open ``cmdline.txt`` and add ``memmap=256M$16M`` to prevent the kernel from
+ using the memory needed by the Trusted Firmware. If you want to enable the
+ serial port "Mini UART", make sure that this file also contains
+ ``console=serial0,115200 console=tty1``.
+
+ Note that the 16 MiB reserved this way won't be available for Linux, the same
+ way as the memory reserved in DRAM for the GPU isn't available.
+
+5. Open ``config.txt`` and add the following lines at the end (``enable_uart=1``
+ is only needed to enable debugging through the Mini UART):
+
+::
+
+ enable_uart=1
+ kernel_address=0x01000000
+ device_tree_address=0x02000000
+
+If you connect a serial cable to the Mini UART and your computer, and connect
+to it (for example, with ``screen /dev/ttyUSB0 115200``) you should see some
+text. In the case of an AArch32 kernel, you should see something like this:
+
+::
+
+ NOTICE: Booting Trusted Firmware
+ NOTICE: BL1: v1.4(release):v1.4-329-g61e94684-dirty
+ NOTICE: BL1: Built : 00:09:25, Nov 6 2017
+ NOTICE: BL1: Booting BL2
+ NOTICE: BL2: v1.4(release):v1.4-329-g61e94684-dirty
+ NOTICE: BL2: Built : 00:09:25, Nov 6 2017
+ NOTICE: BL1: Booting BL31
+ NOTICE: BL31: v1.4(release):v1.4-329-g61e94684-dirty
+ NOTICE: BL31: Built : 00:09:25, Nov 6 2017
+ [ 0.266484] bcm2835-aux-uart 3f215040.serial: could not get clk: -517
+
+ Raspbian GNU/Linux 9 raspberrypi ttyS0
+ raspberrypi login:
+
+Just enter your credentials, everything should work as expected. Note that the
+HDMI output won't show any text during boot.
+
+.. _default Arm stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub7.S
+.. _default AArch64 stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub8.S
+.. _Linux kernel tree: https://github.com/torvalds/linux
+.. _Linux tree fork: https://github.com/raspberrypi/linux
+.. _Raspberry Pi 3: https://www.raspberrypi.org/products/raspberry-pi-3-model-b/
+.. _Raspberry Pi 3 Arm Trusted Firmware bootstrap: https://github.com/AntonioND/rpi3-arm-tf-bootstrap
+.. _Raspberry Pi 3 documentation: https://www.raspberrypi.org/documentation/
+.. _Raspbian: https://www.raspberrypi.org/downloads/raspbian/
diff --git a/docs/plat/socionext-uniphier.rst b/docs/plat/socionext-uniphier.rst
index fb6ebe5e..2c652ac9 100644
--- a/docs/plat/socionext-uniphier.rst
+++ b/docs/plat/socionext-uniphier.rst
@@ -1,11 +1,12 @@
ARM Trusted Firmware for Socionext UniPhier SoCs
================================================
+
Socionext UniPhier ARMv8-A SoCs use ARM Trusted Firmware as the secure world
firmware, supporting BL1, BL2, and BL31.
UniPhier SoC family implements its internal boot ROM, so BL1 is used as pseudo
-ROM (i.e. runs in RAM). The internal boot ROM loads 64KB `1`_ image from a
+ROM (i.e. runs in RAM). The internal boot ROM loads 64KB [1]_ image from a
non-volatile storage to the on-chip SRAM. Unfortunately, BL1 does not fit in
the 64KB limit if `Trusted Board Boot`_ (TBB) is enabled. To solve this problem,
Socionext provides a first stage loader called `UniPhier BL`_. This loader runs
@@ -23,35 +24,33 @@ the UniPhier BL. The concatenation of the UniPhier BL and the compressed BL1
fits in the 64KB limit. The concatenated image is loaded by the boot ROM
(and verified if the chip fuses are blown).
-::
-
- to the lowest common denominator.
Boot Flow
---------
-#. The Boot ROM
+1. The Boot ROM
+
+ This is hard-wired ROM, so never corrupted. It loads the UniPhier BL (with
+ compressed-BL1 appended) into the on-chip SRAM. If the SoC fuses are blown,
+ the image is verified by the SoC's own method.
-This is hard-wired ROM, so never corrupted. It loads the UniPhier BL (with
-compressed-BL1 appended) into the on-chip SRAM. If the SoC fuses are blown,
-the image is verified by the SoC's own method.
+2. UniPhier BL
-#. UniPhier BL
+ This runs in the on-chip SRAM. After the minimum SoC initialization and DRAM
+ setup, it decompresses the appended BL1 image into the DRAM, then jumps to
+ the BL1 entry.
-This runs in the on-chip SRAM. After the minimum SoC initialization and DRAM
-setup, it decompresses the appended BL1 image into the DRAM, then jumps to
-the BL1 entry.
+3. BL1
-#. BL1
+ This runs in the DRAM. It extracts BL2 from FIP (Firmware Image Package).
+ If TBB is enabled, the BL2 is authenticated by the standard mechanism of ARM
+ Trusted Firmware.
-This runs in the DRAM. It extracts BL2 from FIP (Firmware Image Package).
-If TBB is enabled, the BL2 is authenticated by the standard mechanism of ARM
-Trusted Firmware.
+4. BL2, BL31, and more
-#. BL2, BL31, and more
+ They all run in the DRAM, and are authenticated by the standard mechanism if
+ TBB is enabled. See `Firmware Design`_ for details.
-They all run in the DRAM, and are authenticated by the standard mechanism if
-TBB is enabled. See `Firmware Design`_ for details.
Basic Build
-----------
@@ -63,59 +62,52 @@ For a non-secure boot loader (aka BL33), U-Boot is well supported for UniPhier
SoCs. The U-Boot image (``u-boot.bin``) must be built in advance. For the build
procedure of U-Boot, refer to the document in the `U-Boot`_ project.
-To build minimum functionality for UniPhier (without TBB):
-
-::
+To build minimum functionality for UniPhier (without TBB)::
make CROSS_COMPILE=<gcc-prefix> PLAT=uniphier BL33=<path-to-BL33> bl1_gzip fip
Output images:
-- ``bl1.bin.gzip``
-- ``fip.bin``
+- ``bl1.bin.gzip``
+- ``fip.bin``
+
Optional features
-----------------
-- Trusted Board Boot
+- Trusted Board Boot
-`mbed TLS`_ is needed as the cryptographic and image parser modules.
-Refer to the `User Guide`_ for the appropriate version of mbed TLS.
+ `mbed TLS`_ is needed as the cryptographic and image parser modules.
+ Refer to the `User Guide`_ for the appropriate version of mbed TLS.
-To enable TBB, add the following options to the build command:
-
-::
+ To enable TBB, add the following options to the build command::
TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=<path-to-mbedtls>
-- System Control Processor (SCP)
-
-If desired, FIP can include an SCP BL2 image. If BL2 finds an SCP BL2 image
-in FIP, BL2 loads it into DRAM and kicks the SCP. Most of UniPhier boards
-still work without SCP, but SCP provides better power management support.
+- System Control Processor (SCP)
-To include SCP\_BL2, add the following option to the build command:
+ If desired, FIP can include an SCP BL2 image. If BL2 finds an SCP BL2 image
+ in FIP, BL2 loads it into DRAM and kicks the SCP. Most of UniPhier boards
+ still work without SCP, but SCP provides better power management support.
-::
+ To include SCP BL2, add the following option to the build command::
SCP_BL2=<path-to-SCP>
-- BL32 (Secure Payload)
-
-To enable BL32, add the following option to the build command:
+- BL32 (Secure Payload)
-::
+ To enable BL32, add the following options to the build command::
SPD=<spd> BL32=<path-to-BL32>
-If you use TSP for BL32, ``BL32=<path-to-BL32>`` is not required. Just add the
-following:
-
-::
+ If you use TSP for BL32, ``BL32=<path-to-BL32>`` is not required. Just add the
+ following::
SPD=tspd
-.. _1: Some%20SoCs%20can%20load%2080KB,%20but%20the%20software%20implementation%20must%20be%20aligned
+
+.. [1] Some SoCs can load 80KB, but the software implementation must be aligned
+ to the lowest common denominator.
.. _Trusted Board Boot: ../trusted-board-boot.rst
.. _UniPhier BL: https://github.com/uniphier/uniphier-bl
.. _Firmware Design: ../firmware-design.rst
diff --git a/docs/secure-partition-manager-design.rst b/docs/secure-partition-manager-design.rst
new file mode 100644
index 00000000..05d4e8bb
--- /dev/null
+++ b/docs/secure-partition-manager-design.rst
@@ -0,0 +1,825 @@
+*******************************
+Secure Partition Manager Design
+*******************************
+
+.. section-numbering::
+ :suffix: .
+
+.. contents::
+
+Background
+==========
+
+In some market segments that primarily deal with client-side devices like mobile
+phones, tablets, STBs and embedded devices, a Trusted OS instantiates trusted
+applications to provide security services like DRM, secure payment and
+authentication. The Global Platform TEE Client API specification defines the API
+used by Non-secure world applications to access these services. A Trusted OS
+fulfils the requirements of a security service as described above.
+
+Management services are typically implemented at the highest level of privilege
+in the system (i.e. EL3 in Arm Trusted Firmware). The service requirements are
+fulfilled by the execution environment provided by Arm Trusted Firmware.
+
+The following diagram illustrates the corresponding software stack:
+
+|Image 1|
+
+In other market segments that primarily deal with server-side devices (e.g. data
+centres and enterprise servers) the secure software stack typically does not
+include a Global Platform Trusted OS. Security functions are accessed through
+other interfaces (e.g. ACPI TCG TPM interface, UEFI runtime variable service).
+
+Placement of management and security functions with diverse requirements in a
+privileged Exception Level (i.e. EL3 or S-EL1) makes security auditing of
+firmware more difficult and does not allow isolation of unrelated services from
+each other either.
+
+Introduction
+============
+
+A **Secure Partition** is a software execution environment instantiated in
+S-EL0 that can be used to implement simple management and security services.
+Since S-EL0 is an unprivileged Exception Level, a Secure Partition relies on
+privileged firmware (i.e. Arm Trusted Firmware) to be granted access to system
+and processor resources. Essentially, it is a software sandbox in the Secure
+world that runs under the control of privileged software, provides one or more
+services and accesses the following system resources:
+
+- Memory and device regions in the system address map.
+
+- PE system registers.
+
+- A range of synchronous exceptions (e.g. SMC function identifiers).
+
+Note that currently the Arm Trusted Firmware only supports handling one Secure
+Partition.
+
+A Secure Partition enables Arm Trusted Firmware to implement only the essential
+secure services in EL3 and instantiate the rest in a partition in S-EL0.
+Furthermore, multiple Secure Partitions can be used to isolate unrelated
+services from each other.
+
+The following diagram illustrates the place of a Secure Partition in a typical
+ARMv8-A software stack. A single or multiple Secure Partitions provide secure
+services to software components in the Non-secure world and other Secure
+Partitions.
+
+|Image 2|
+
+The Arm Trusted Firmware build system is responsible for including the Secure
+Partition image in the FIP. During boot, BL2 includes support to authenticate
+and load the Secure Partition image. A BL31 component called **Secure Partition
+Manager (SPM)** is responsible for managing the partition. This is semantically
+similar to a hypervisor managing a virtual machine.
+
+The SPM is responsible for the following actions during boot:
+
+- Allocate resources requested by the Secure Partition.
+
+- Perform architectural and system setup required by the Secure Partition to
+ fulfil a service request.
+
+- Implement a standard interface that is used for initialising a Secure
+ Partition.
+
+The SPM is responsible for the following actions during runtime:
+
+- Implement a standard interface that is used by a Secure Partition to fulfil
+ service requests.
+
+- Implement a standard interface that is used by the Non-secure world for
+ accessing the services exported by a Secure Partition. A service can be
+ invoked through a SMC.
+
+Alternatively, a partition can be viewed as a thread of execution running under
+the control of the SPM. Hence common programming concepts described below are
+applicable to a partition.
+
+Description
+===========
+
+The previous section introduced some general aspects of the software
+architecture of a Secure Partition. This section describes the specific choices
+made in the current implementation of this software architecture. Subsequent
+revisions of the implementation will include a richer set of features that
+enable a more flexible architecture.
+
+Building Arm Trusted Firmware with Secure Partition support
+-----------------------------------------------------------
+
+SPM is supported on the Arm FVP exclusively at the moment. The current
+implementation supports inclusion of only a single Secure Partition in which a
+service always runs to completion (e.g. the requested services cannot be
+preempted to give control back to the Normal world).
+
+It is not currently possible for BL31 to integrate SPM support and a Secure
+Payload Dispatcher (SPD) at the same time; they are mutually exclusive. In the
+SPM bootflow, a Secure Partition image executing at S-EL0 replaces the Secure
+Payload image executing at S-EL1 (e.g. a Trusted OS). Both are referred to as
+BL32.
+
+A working prototype of a SP has been implemented by re-purposing the EDK2 code
+and tools, leveraging the concept of the *Standalone Management Mode (MM)* in
+the UEFI specification (see the PI v1.6 Volume 4: Management Mode Core
+Interface). This will be referred to as the *Standalone MM Secure Partition* in
+the rest of this document.
+
+To enable SPM support in the TF, the source code must be compiled with the build
+flag ``ENABLE_SPM=1``. On Arm platforms the build option ``ARM_BL31_IN_DRAM``
+can be used to select the location of BL31, both SRAM and DRAM are supported.
+Also, the location of the binary that contains the BL32 image
+(``BL32=path/to/image.bin``) must be specified.
+
+First, build the Standalone MM Secure Partition. To build it, refer to the
+`instructions in the EDK2 repository`_.
+
+Then build TF with SPM support and include the Standalone MM Secure Partition
+image in the FIP:
+
+::
+
+ BL32=path/to/standalone/mm/sp BL33=path/to/bl33.bin \
+ make PLAT=fvp ENABLE_SPM=1 fip all
+
+Describing Secure Partition resources
+-------------------------------------
+
+Arm Trusted Firmware exports a porting interface that enables a platform to
+specify the system resources required by the Secure Partition. Some instructions
+are given below. However, this interface is under development and it may change
+as new features are implemented.
+
+- A Secure Partition is considered a BL32 image, so the same defines that apply
+ to BL32 images apply to a Secure Partition: ``BL32_BASE`` and ``BL32_LIMIT``.
+
+- The following defines are needed to allocate space for the translation tables
+ used by the Secure Partition: ``PLAT_SP_IMAGE_MMAP_REGIONS`` and
+ ``PLAT_SP_IMAGE_MAX_XLAT_TABLES``.
+
+- The functions ``plat_get_secure_partition_mmap()`` and
+ ``plat_get_secure_partition_boot_info()`` have to be implemented. The file
+ ``plat/arm/board/fvp/fvp_common.c`` can be used as an example. It uses the
+ defines in ``include/plat/arm/common/arm_spm_def.h``.
+
+ - ``plat_get_secure_partition_mmap()`` returns an array of mmap regions that
+ describe the memory regions that the SPM needs to allocate for a Secure
+ Partition.
+
+ - ``plat_get_secure_partition_boot_info()`` returns a
+ ``secure_partition_boot_info_t`` struct that is populated by the platform
+ with information about the memory map of the Secure Partition.
+
+For an example of all the changes in context, you may refer to commit
+``e29efeb1b4``, in which the port for FVP was introduced.
+
+Accessing Secure Partition services
+-----------------------------------
+
+The `SMC Calling Convention`_ (*ARM DEN 0028B*) describes SMCs as a conduit for
+accessing services implemented in the Secure world. The ``MM_COMMUNICATE``
+interface defined in the `Management Mode Interface Specification`_ (*ARM DEN
+0060A*) is used to invoke a Secure Partition service as a Fast Call.
+
+The mechanism used to identify a service within the partition depends on the
+service implementation. It is assumed that the caller of the service will be
+able to discover this mechanism through standard platform discovery mechanisms
+like ACPI and Device Trees. For example, *Volume 4: Platform Initialisation
+Specification v1.6. Management Mode Core Interface* specifies that a GUID is
+used to identify a management mode service. A client populates the GUID in the
+``EFI_MM_COMMUNICATE_HEADER``. The header is populated in the communication
+buffer shared with the Secure Partition.
+
+A Fast Call appears to be atomic from the perspective of the caller and returns
+when the requested operation has completed. A service invoked through the
+``MM_COMMUNICATE`` SMC will run to completion in the partition on a given CPU.
+The SPM is responsible for guaranteeing this behaviour. This means that there
+can only be a single outstanding Fast Call in a partition on a given CPU.
+
+Exchanging data with the Secure Partition
+-----------------------------------------
+
+The exchange of data between the Non-secure world and the partition takes place
+through a shared memory region. The location of data in the shared memory area
+is passed as a parameter to the ``MM_COMMUNICATE`` SMC. The shared memory area
+is statically allocated by the SPM and is expected to be either implicitly known
+to the Non-secure world or discovered through a platform discovery mechanism
+e.g. ACPI table or device tree. It is possible for the Non-secure world to
+exchange data with a partition only if it has been populated in this shared
+memory area. The shared memory area is implemented as per the guidelines
+specified in Section 3.2.3 of the `Management Mode Interface Specification`_
+(*ARM DEN 0060A*).
+
+The format of data structures used to encapsulate data in the shared memory is
+agreed between the Non-secure world and the Secure Partition. For example, in
+the `Management Mode Interface specification`_ (*ARM DEN 0060A*), Section 4
+describes that the communication buffer shared between the Non-secure world and
+the Management Mode (MM) in the Secure world must be of the type
+``EFI_MM_COMMUNICATE_HEADER``. This data structure is defined in *Volume 4:
+Platform Initialisation Specification v1.6. Management Mode Core Interface*.
+Any caller of a MM service will have to use the ``EFI_MM_COMMUNICATE_HEADER``
+data structure.
+
+Runtime model of the Secure Partition
+=====================================
+
+This section describes how the Secure Partition interfaces with the SPM.
+
+Interface with SPM
+------------------
+
+In order to instantiate one or more secure services in the Secure Partition in
+S-EL0, the SPM should define the following types of interfaces:
+
+- Interfaces that enable access to privileged operations from S-EL0. These
+ operations typically require access to system resources that are either shared
+ amongst multiple software components in the Secure world or cannot be directly
+ accessed from an unprivileged Exception Level.
+
+- Interfaces that establish the control path between the SPM and the Secure
+ Partition.
+
+This section describes the APIs currently exported by the SPM that enable a
+Secure Partition to initialise itself and export its services in S-EL0. These
+interfaces are not accessible from the Non-secure world.
+
+Conduit
+^^^^^^^
+
+The `SMC Calling Convention`_ (*ARM DEN 0028B*) specification describes the SMC
+and HVC conduits for accessing firmware services and their availability
+depending on the implemented Exception levels. In S-EL0, the Supervisor Call
+exception (SVC) is the only architectural mechanism available for unprivileged
+software to make a request for an operation implemented in privileged software.
+Hence, the SVC conduit must be used by the Secure Partition to access interfaces
+implemented by the SPM.
+
+A SVC causes an exception to be taken to S-EL1. Arm Trusted Firmware assumes
+ownership of S-EL1 and installs a simple exception vector table in S-EL1 that
+relays a SVC request from a Secure Partition as a SMC request to the SPM in EL3.
+Upon servicing the SMC request, Arm Trusted Firmware returns control directly to
+S-EL0 through an ERET instruction.
+
+Calling conventions
+^^^^^^^^^^^^^^^^^^^
+
+The `SMC Calling Convention`_ (*ARM DEN 0028B*) specification describes the
+32-bit and 64-bit calling conventions for the SMC and HVC conduits. The SVC
+conduit introduces the concept of SVC32 and SVC64 calling conventions. The SVC32
+and SVC64 calling conventions are equivalent to the 32-bit (SMC32) and the
+64-bit (SMC64) calling conventions respectively.
+
+Communication initiated by SPM
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A service request is initiated from the SPM through an exception return
+instruction (ERET) to S-EL0. Later, the Secure Partition issues an SVC
+instruction to signal completion of the request. Some example use cases are
+given below:
+
+- A request to initialise the Secure Partition during system boot.
+
+- A request to handle a runtime service request.
+
+Communication initiated by Secure Partition
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A request is initiated from the Secure Partition by executing a SVC instruction.
+An ERET instruction is used by Arm Trusted Firmware to return to S-EL0 with the
+result of the request.
+
+For instance, a request to perform privileged operations on behalf of a
+partition (e.g. management of memory attributes in the translation tables for
+the Secure EL1&0 translation regime).
+
+Interfaces
+^^^^^^^^^^
+
+The current implementation reserves function IDs for Fast Calls in the Standard
+Secure Service calls range (see `SMC Calling Convention`_ (*ARM DEN 0028B*)
+specification) for each API exported by the SPM. This section defines the
+function prototypes for each function ID. The function IDs specify whether one
+or both of the SVC32 and SVC64 calling conventions can be used to invoke the
+corresponding interface.
+
+Secure Partition Event Management
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Secure Partition provides an Event Management interface that is used by the
+SPM to delegate service requests to the Secure Partition. The interface also
+allows the Secure Partition to:
+
+- Register with the SPM a service that it provides.
+- Indicate completion of a service request delagated by the SPM
+
+Miscellaneous interfaces
+------------------------
+
+``SPM_VERSION_AARCH32``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+- Description
+
+ Returns the version of the interface exported by SPM.
+
+- Parameters
+
+ - **uint32** - Function ID
+
+ - SVC32 Version: **0x84000060**
+
+- Return parameters
+
+ - **int32** - Status
+
+ On success, the format of the value is as follows:
+
+ - Bit [31]: Must be 0
+ - Bits [30:16]: Major Version. Must be 0 for this revision of the SPM
+ interface.
+ - Bits [15:0]: Minor Version. Must be 1 for this revision of the SPM
+ interface.
+
+ On error, the format of the value is as follows:
+
+ - ``NOT_SUPPORTED``: SPM interface is not supported or not available for the
+ client.
+
+- Usage
+
+ This function returns the version of the Secure Partition Manager
+ implementation. The major version is 0 and the minor version is 1. The version
+ number is a 31-bit unsigned integer, with the upper 15 bits denoting the major
+ revision, and the lower 16 bits denoting the minor revision. The following
+ rules apply to the version numbering:
+
+ - Different major revision values indicate possibly incompatible functions.
+
+ - For two revisions, A and B, for which the major revision values are
+ identical, if the minor revision value of revision B is greater than the
+ minor revision value of revision A, then every function in revision A must
+ work in a compatible way with revision B. However, it is possible for
+ revision B to have a higher function count than revision A.
+
+- Implementation responsibilities
+
+ If this function returns a valid version number, all the functions that are
+ described subsequently must be implemented, unless it is explicitly stated
+ that a function is optional.
+
+See `Error Codes`_ for integer values that are associated with each return
+code.
+
+Secure Partition Initialisation
+-------------------------------
+
+The SPM is responsible for initialising the architectural execution context to
+enable initialisation of a service in S-EL0. The responsibilities of the SPM are
+listed below. At the end of initialisation, the partition issues a
+``SP_EVENT_COMPLETE_AARCH64`` call (described later) to signal readiness for
+handling requests for services implemented by the Secure Partition. The
+initialisation event is executed as a Fast Call.
+
+Entry point invocation
+^^^^^^^^^^^^^^^^^^^^^^
+
+The entry point for service requests that should be handled as Fast Calls is
+used as the target of the ERET instruction to start initialisation of the Secure
+Partition.
+
+Architectural Setup
+^^^^^^^^^^^^^^^^^^^
+
+At cold boot, system registers accessible from S-EL0 will be in their reset
+state unless otherwise specified. The SPM will perform the following
+architectural setup to enable execution in S-EL0
+
+MMU setup
+^^^^^^^^^
+
+The platform port of a Secure Partition specifies to the SPM a list of regions
+that it needs access to and their attributes. The SPM validates this resource
+description and initialises the Secure EL1&0 translation regime as follows.
+
+1. Device regions are mapped with nGnRE attributes and Execute Never
+ instruction access permissions.
+
+2. Code memory regions are mapped with RO data and Executable instruction access
+ permissions.
+
+3. Read Only data memory regions are mapped with RO data and Execute Never
+ instruction access permissions.
+
+4. Read Write data memory regions are mapped with RW data and Execute Never
+ instruction access permissions.
+
+5. If the resource description does not explicitly describe the type of memory
+ regions then all memory regions will be marked with Code memory region
+ attributes.
+
+6. The ``UXN`` and ``PXN`` bits are set for regions that are not executable by
+ S-EL0 or S-EL1.
+
+System Register Setup
+^^^^^^^^^^^^^^^^^^^^^
+
+System registers that influence software execution in S-EL0 are setup by the SPM
+as follows:
+
+1. ``SCTLR_EL1``
+
+ - ``UCI=1``
+ - ``EOE=0``
+ - ``WXN=1``
+ - ``nTWE=1``
+ - ``nTWI=1``
+ - ``UCT=1``
+ - ``DZE=1``
+ - ``I=1``
+ - ``UMA=0``
+ - ``SA0=1``
+ - ``C=1``
+ - ``A=1``
+ - ``M=1``
+
+2. ``CPACR_EL1``
+
+ - ``FPEN=b'11``
+
+3. ``PSTATE``
+
+ - ``D,A,I,F=1``
+ - ``CurrentEL=0`` (EL0)
+ - ``SpSel=0`` (Thread mode)
+ - ``NRW=0`` (AArch64)
+
+General Purpose Register Setup
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+SPM will invoke the entry point of a service by executing an ERET instruction.
+This transition into S-EL0 is special since it is not in response to a previous
+request through a SVC instruction. This is the first entry into S-EL0. The
+general purpose register usage at the time of entry will be as specified in the
+"Return State" column of Table 3-1 in Section 3.1 "Register use in AArch64 SMC
+calls" of the `SMC Calling Convention`_ (*ARM DEN 0028B*) specification. In
+addition, certain other restrictions will be applied as described below.
+
+1. ``SP_EL0``
+
+ A non-zero value will indicate that the SPM has initialised the stack pointer
+ for the current CPU.
+
+ The value will be 0 otherwise.
+
+2. ``X4-X30``
+
+ The values of these registers will be 0.
+
+3. ``X0-X3``
+
+ Parameters passed by the SPM.
+
+ - ``X0``: Virtual address of a buffer shared between EL3 and S-EL0. The
+ buffer will be mapped in the Secure EL1&0 translation regime with read-only
+ memory attributes described earlier.
+
+ - ``X1``: Size of the buffer in bytes.
+
+ - ``X2``: Cookie value (*IMPLEMENTATION DEFINED*).
+
+ - ``X3``: Cookie value (*IMPLEMENTATION DEFINED*).
+
+Runtime Event Delegation
+------------------------
+
+The SPM receives requests for Secure Partition services through a synchronous
+invocation (i.e. a SMC from the Non-secure world). These requests are delegated
+to the partition by programming a return from the last
+``SP_EVENT_COMPLETE_AARCH64`` call received from the partition. The last call
+was made to signal either completion of Secure Partition initialisation or
+completion of a partition service request.
+
+``SP_EVENT_COMPLETE_AARCH64``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Description
+
+ Signal completion of the last SP service request.
+
+- Parameters
+
+ - **uint32** - Function ID
+
+ - SVC64 Version: **0xC4000061**
+
+ - **int32** - Event Status Code
+
+ Zero or a positive value indicates that the event was handled successfully.
+ The values depend upon the original event that was delegated to the Secure
+ partition. They are described as follows.
+
+ - ``SUCCESS`` : Used to indicate that the Secure Partition was initialised
+ or a runtime request was handled successfully.
+
+ - Any other value greater than 0 is used to pass a specific Event Status
+ code in response to a runtime event.
+
+ A negative value indicates an error. The values of Event Status code depend
+ on the original event.
+
+- Return parameters
+
+ - **int32** - Event ID/Return Code
+
+ Zero or a positive value specifies the unique ID of the event being
+ delegated to the partition by the SPM.
+
+ In the current implementation, this parameter contains the function ID of
+ the ``MM_COMMUNICATE`` SMC. This value indicates to the partition that an
+ event has been delegated to it in response to an ``MM_COMMUNICATE`` request
+ from the Non-secure world.
+
+ A negative value indicates an error. The format of the value is as follows:
+
+ - ``NOT_SUPPORTED``: Function was called from the Non-secure world.
+
+ See `Error Codes`_ for integer values that are associated with each return
+ code.
+
+ - **uint32** - Event Context Address
+
+ Address of a buffer shared between the SPM and Secure Partition to pass
+ event specific information. The format of the data populated in the buffer
+ is implementation defined.
+
+ The buffer is mapped in the Secure EL1&0 translation regime with read-only
+ memory attributes described earlier.
+
+ For the SVC64 version, this parameter is a 64-bit Virtual Address (VA).
+
+ For the SVC32 version, this parameter is a 32-bit Virtual Address (VA).
+
+ - **uint32** - Event context size
+
+ Size of the memory starting at Event Address.
+
+ - **uint32/uint64** - Event Cookie
+
+ This is an optional parameter. If unused its value is SBZ.
+
+- Usage
+
+ This function signals to the SPM that the handling of the last event delegated
+ to a partition has completed. The partition is ready to handle its next event.
+ A return from this function is in response to the next event that will be
+ delegated to the partition. The return parameters describe the next event.
+
+- Caller responsibilities
+
+ A Secure Partition must only call ``SP_EVENT_COMPLETE_AARCH64`` to signal
+ completion of a request that was delegated to it by the SPM.
+
+- Callee responsibilities
+
+ When the SPM receives this call from a Secure Partition, the corresponding
+ syndrome information can be used to return control through an ERET
+ instruction, to the instruction immediately after the call in the Secure
+ Partition context. This syndrome information comprises of general purpose and
+ system register values when the call was made.
+
+ The SPM must save this syndrome information and use it to delegate the next
+ event to the Secure Partition. The return parameters of this interface must
+ specify the properties of the event and be populated in ``X0-X3/W0-W3``
+ registers.
+
+Secure Partition Memory Management
+----------------------------------
+
+A Secure Partition executes at S-EL0, which is an unprivileged Exception Level.
+The SPM is responsible for enabling access to regions of memory in the system
+address map from a Secure Partition. This is done by mapping these regions in
+the Secure EL1&0 Translation regime with appropriate memory attributes.
+Attributes refer to memory type, permission, cacheability and shareability
+attributes used in the Translation tables. The definitions of these attributes
+and their usage can be found in the `ARMv8 ARM`_ (*ARM DDI 0487*).
+
+All memory required by the Secure Partition is allocated upfront in the SPM,
+even before handing over to the Secure Partition for the first time. The initial
+access permissions of the memory regions are statically provided by the platform
+port and should allow the Secure Partition to run its initialisation code.
+
+However, they might not suit the final needs of the Secure Partition because its
+final memory layout might not be known until the Secure Partition initialises
+itself. As the Secure Partition initialises its runtime environment it might,
+for example, load dynamically some modules. For instance, a Secure Partition
+could implement a loader for a standard executable file format (e.g. an PE-COFF
+loader for loading executable files at runtime). These executable files will be
+a part of the Secure Partition image. The location of various sections in an
+executable file and their permission attributes (e.g. read-write data, read-only
+data and code) will be known only when the file is loaded into memory.
+
+In this case, the Secure Partition needs a way to change the access permissions
+of its memory regions. The SPM provides this feature through the
+``SP_MEMORY_ATTRIBUTES_SET_AARCH64`` SVC interface. This interface is available
+to the Secure Partition during a specific time window: from the first entry into
+the Secure Partition up to the first ``SP_EVENT_COMPLETE`` call that signals the
+Secure Partition has finished its initialisation. Once the initialisation is
+complete, the SPM does not allow changes to the memory attributes.
+
+This section describes the standard SVC interface that is implemented by the SPM
+to determine and change permission attributes of memory regions that belong to a
+Secure Partition.
+
+``SP_MEMORY_ATTRIBUTES_GET_AARCH64``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Description
+
+ Request the permission attributes of a memory region from S-EL0.
+
+- Parameters
+
+ - **uint32** Function ID
+
+ - SVC64 Version: **0xC4000064**
+
+ - **uint64** Base Address
+
+ This parameter is a 64-bit Virtual Address (VA).
+
+ There are no alignment restrictions on the Base Address. The permission
+ attributes of the translation granule it lies in are returned.
+
+- Return parameters
+
+ - **int32** - Memory Attributes/Return Code
+
+ On success the format of the Return Code is as follows:
+
+ - Bits[1:0] : Data access permission
+
+ - b'00 : No access
+ - b'01 : Read-Write access
+ - b'10 : Reserved
+ - b'11 : Read-only access
+
+ - Bit[2]: Instruction access permission
+
+ - b'0 : Executable
+ - b'1 : Non-executable
+
+ - Bit[30:3] : Reserved. SBZ.
+
+ - Bit[31] : Must be 0
+
+ On failure the following error codes are returned:
+
+ - ``INVALID_PARAMETERS``: The Secure Partition is not allowed to access the
+ memory region the Base Address lies in.
+
+ - ``NOT_SUPPORTED`` : The SPM does not support retrieval of attributes of
+ any memory page that is accessible by the Secure Partition, or the
+ function was called from the Non-secure world. Also returned if it is
+ used after ``SP_EVENT_COMPLETE_AARCH64``.
+
+ See `Error Codes`_ for integer values that are associated with each return
+ code.
+
+- Usage
+
+ This function is used to request the permission attributes for S-EL0 on a
+ memory region accessible from a Secure Partition. The size of the memory
+ region is equal to the Translation Granule size used in the Secure EL1&0
+ translation regime. Requests to retrieve other memory region attributes are
+ not currently supported.
+
+- Caller responsibilities
+
+ The caller must obtain the Translation Granule Size of the Secure EL1&0
+ translation regime from the SPM through an implementation defined method.
+
+- Callee responsibilities
+
+ The SPM must not return the memory access controls for a page of memory that
+ is not accessible from a Secure Partition.
+
+``SP_MEMORY_ATTRIBUTES_SET_AARCH64``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Description
+
+ Set the permission attributes of a memory region from S-EL0.
+
+- Parameters
+
+ - **uint32** - Function ID
+
+ - SVC64 Version: **0xC4000065**
+
+ - **uint64** - Base Address
+
+ This parameter is a 64-bit Virtual Address (VA).
+
+ The alignment of the Base Address must be greater than or equal to the size
+ of the Translation Granule Size used in the Secure EL1&0 translation
+ regime.
+
+ - **uint32** - Page count
+
+ Number of pages starting from the Base Address whose memory attributes
+ should be changed. The page size is equal to the Translation Granule Size.
+
+ - **uint32** - Memory Access Controls
+
+ - Bits[1:0] : Data access permission
+
+ - b'00 : No access
+ - b'01 : Read-Write access
+ - b'10 : Reserved
+ - b'11 : Read-only access
+
+ - Bit[2] : Instruction access permission
+
+ - b'0 : Executable
+ - b'1 : Non-executable
+
+ - Bits[31:3] : Reserved. SBZ.
+
+ A combination of attributes that mark the region with RW and Executable
+ permissions is prohibited. A request to mark a device memory region with
+ Executable permissions is prohibited.
+
+- Return parameters
+
+ - **int32** - Return Code
+
+ - ``SUCCESS``: The Memory Access Controls were changed successfully.
+
+ - ``DENIED``: The SPM is servicing a request to change the attributes of a
+ memory region that overlaps with the region specified in this request.
+
+ - ``INVALID_PARAMETER``: An invalid combination of Memory Access Controls
+ has been specified. The Base Address is not correctly aligned. The Secure
+ Partition is not allowed to access part or all of the memory region
+ specified in the call.
+
+ - ``NO_MEMORY``: The SPM does not have memory resources to change the
+ attributes of the memory region in the translation tables.
+
+ - ``NOT_SUPPORTED``: The SPM does not permit change of attributes of any
+ memory region that is accessible by the Secure Partition. Function was
+ called from the Non-secure world. Also returned if it is used after
+ ``SP_EVENT_COMPLETE_AARCH64``.
+
+ See `Error Codes`_ for integer values that are associated with each return
+ code.
+
+- Usage
+
+ This function is used to change the permission attributes for S-EL0 on a
+ memory region accessible from a Secure Partition. The size of the memory
+ region is equal to the Translation Granule size used in the Secure EL1&0
+ translation regime. Requests to change other memory region attributes are not
+ currently supported.
+
+ This function is only available at boot time. This interface is revoked after
+ the Secure Partition sends the first ``SP_EVENT_COMPLETE_AARCH64`` to signal
+ that it is initialised and ready to receive run-time requests.
+
+- Caller responsibilities
+
+ The caller must obtain the Translation Granule Size of the Secure EL1&0
+ translation regime from the SPM through an implementation defined method.
+
+- Callee responsibilities
+
+ The SPM must preserve the original memory access controls of the region of
+ memory in case of an unsuccessful call.  The SPM must preserve the consistency
+ of the S-EL1 translation regime if this function is called on different PEs
+ concurrently and the memory regions specified overlap.
+
+Error Codes
+-----------
+
+.. csv-table::
+ :header: "Name", "Value"
+
+ ``SUCCESS``,0
+ ``NOT_SUPPORTED``,-1
+ ``INVALID_PARAMETER``,-2
+ ``DENIED``,-3
+ ``NO_MEMORY``,-5
+ ``NOT_PRESENT``,-7
+
+--------------
+
+*Copyright (c) 2017, Arm Limited and Contributors. All rights reserved.*
+
+.. _ARMv8 ARM: https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile
+.. _instructions in the EDK2 repository: https://github.com/tianocore/edk2-staging/blob/AArch64StandaloneMm/HowtoBuild.MD
+.. _Management Mode Interface Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0060a/DEN0060A_ARM_MM_Interface_Specification.pdf
+.. _SDEI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
+.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf
+
+.. |Image 1| image:: diagrams/secure_sw_stack_tos.png
+.. |Image 2| image:: diagrams/secure_sw_stack_sp.png
diff --git a/docs/spm-user-guide.rst b/docs/spm-user-guide.rst
deleted file mode 100644
index a3b64d93..00000000
--- a/docs/spm-user-guide.rst
+++ /dev/null
@@ -1,59 +0,0 @@
-ARM Trusted Firmware - SPM User Guide
-=====================================
-
-.. section-numbering::
- :suffix: .
-
-.. contents::
-
-
-This document briefly presents the Secure Partition Management (SPM) support in
-the Arm Trusted Firmware (TF), specifically focusing on how to build Arm TF with
-SPM support.
-
-Overview of the SPM software stack
-----------------------------------
-
-SPM is supported on the Arm FVP exclusively at the moment.
-
-It is not currently possible for BL31 to integrate SPM support and a Secure
-Payload Dispatcher (SPD) at the same time; they are mutually exclusive. In the
-SPM bootflow, a Secure Partition (SP) image executing at Secure-EL0 replaces the
-Secure Payload image executing at Secure-EL1 (e.g. a Trusted OS). Both are
-referred to as BL32.
-
-A working prototype of a SP has been implemented by repurposing the EDK2 code
-and tools, leveraging the concept of the *Standalone Management Mode (MM)* in
-the UEFI specification (see the PI v1.6 Volume 4: Management Mode Core
-Interface). This will be referred to as the *Standalone MM Secure Partition* in
-the rest of this document.
-
-
-Building TF with SPM support
-----------------------------
-
-To enable SPM support in the TF, the source code must be compiled with the build
-flag ``ENABLE_SPM=1``. On Arm platforms the build option ``ARM_BL31_IN_DRAM``
-can be used to select the location of BL31, both SRAM and DRAM are supported.
-
-
-Using the Standalone MM SP
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-First, build the Standalone MM Secure Partition. To build it, refer to the
-`instructions in the EDK2 repository`_.
-
-Then build TF with SPM support and include the Standalone MM Secure Partition
-image in the FIP:
-
-::
-
- BL32=path/to/standalone/mm/sp BL33=path/to/bl33.bin \
- make PLAT=fvp ENABLE_SPM=1 fip all
-
-
---------------
-
-*Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.*
-
-.. _instructions in the EDK2 repository: https://github.com/tianocore/edk2-staging/blob/AArch64StandaloneMm/HowtoBuild.MD
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 138ed8b3..0647e705 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -55,7 +55,7 @@ command:
sudo apt-get install build-essential gcc make git libssl-dev
-ARM TF has been tested with `Linaro Release 17.04`_.
+ARM TF has been tested with `Linaro Release 17.10`_.
Download and install the AArch32 or AArch64 little-endian GCC cross compiler.
The `Linaro Release Notes`_ documents which version of the compiler to use for a
@@ -354,6 +354,17 @@ Common build options
The default is 1 but is automatically disabled when the target architecture
is AArch32.
+- ``ENABLE_SVE_FOR_NS``: Boolean option to enable Scalable Vector Extension
+ (SVE) for the Non-secure world only. SVE is an optional architectural feature
+ for AArch64. Note that when SVE is enabled for the Non-secure world, access
+ to SIMD and floating-point functionality from the Secure world is disabled.
+ This is to avoid corruption of the Non-secure world data in the Z-registers
+ which are aliased by the SIMD and FP registers. The build option is not
+ compatible with the ``CTX_INCLUDE_FPREGS`` build option, and will raise an
+ assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS`` set to
+ 1. The default is 1 but is automatically disabled when the target
+ architecture is AArch32.
+
- ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection
checks in GCC. Allowed values are "all", "strong" and "0" (default).
"strong" is the recommended stack protection level if this feature is
@@ -995,7 +1006,7 @@ images with support for these features:
modules by checking out a recent version of the `mbed TLS Repository`_. It
is important to use a version that is compatible with TF and fixes any
known security vulnerabilities. See `mbed TLS Security Center`_ for more
- information. The latest version of TF is tested with tag ``mbedtls-2.4.2``.
+ information. The latest version of TF is tested with tag ``mbedtls-2.6.0``.
The ``drivers/auth/mbedtls/mbedtls_*.mk`` files contain the list of mbed TLS
source files the modules depend upon.
@@ -1464,10 +1475,10 @@ Running the software on FVP
The latest version of the AArch64 build of ARM Trusted Firmware has been tested
on the following ARM FVPs (64-bit host machine only).
-NOTE: Unless otherwise stated, the model version is Version 11.1 Build 11.1.22.
+NOTE: Unless otherwise stated, the model version is Version 11.2 Build 11.2.33.
- ``Foundation_Platform``
-- ``FVP_Base_AEMv8A-AEMv8A`` (Version 8.7, Build 0.8.8702)
+- ``FVP_Base_AEMv8A-AEMv8A`` (Version 9.0, Build 0.8.9005)
- ``FVP_Base_Cortex-A35x4``
- ``FVP_Base_Cortex-A53x4``
- ``FVP_Base_Cortex-A57x4-A53x4``
@@ -1480,7 +1491,7 @@ NOTE: Unless otherwise stated, the model version is Version 11.1 Build 11.1.22.
The latest version of the AArch32 build of ARM Trusted Firmware has been tested
on the following ARM FVPs (64-bit host machine only).
-- ``FVP_Base_AEMv8A-AEMv8A`` (Version 8.7, Build 0.8.8702)
+- ``FVP_Base_AEMv8A-AEMv8A`` (Version 9.0, Build 0.8.9005)
- ``FVP_Base_Cortex-A32x4``
NOTE: The build numbers quoted above are those reported by launching the FVP
@@ -1857,10 +1868,10 @@ wakeup interrupt from RTC.
.. _Linaro: `Linaro Release Notes`_
.. _Linaro Release: `Linaro Release Notes`_
-.. _Linaro Release Notes: https://community.arm.com/tools/dev-platforms/b/documents/posts/linaro-release-notes-deprecated
-.. _Linaro Release 17.04: https://community.arm.com/tools/dev-platforms/b/documents/posts/linaro-release-notes-deprecated#LinaroRelease17.04
-.. _Linaro instructions: https://community.arm.com/dev-platforms/b/documents/posts/instructions-for-using-the-linaro-software-deliverables
-.. _Instructions for using Linaro's deliverables on Juno: https://community.arm.com/dev-platforms/b/documents/posts/using-linaros-deliverables-on-juno
+.. _Linaro Release Notes: https://community.arm.com/dev-platforms/w/docs/226/old-linaro-release-notes
+.. _Linaro Release 17.10: https://community.arm.com/dev-platforms/w/docs/226/old-linaro-release-notes#1710
+.. _Linaro instructions: https://community.arm.com/dev-platforms/w/docs/304/linaro-software-deliverables
+.. _Instructions for using Linaro's deliverables on Juno: https://community.arm.com/dev-platforms/w/docs/303/juno
.. _ARM Platforms Portal: https://community.arm.com/dev-platforms/
.. _Development Studio 5 (DS-5): http://www.arm.com/products/tools/software-tools/ds-5/index.php
.. _Dia: https://wiki.gnome.org/Apps/Dia/Download
diff --git a/drivers/io/io_block.c b/drivers/io/io_block.c
index 128246fe..8226554d 100644
--- a/drivers/io/io_block.c
+++ b/drivers/io/io_block.c
@@ -167,15 +167,98 @@ static int block_seek(io_entity_t *entity, int mode, ssize_t offset)
return 0;
}
+/*
+ * This function allows the caller to read any number of bytes
+ * from any position. It hides from the caller that the low level
+ * driver only can read aligned blocks of data. For this reason
+ * we need to handle the use case where the first byte to be read is not
+ * aligned to start of the block, the last byte to be read is also not
+ * aligned to the end of a block, and there are zero or more blocks-worth
+ * of data in between.
+ *
+ * In such a case we need to read more bytes than requested (i.e. full
+ * blocks) and strip-out the leading bytes (aka skip) and the trailing
+ * bytes (aka padding). See diagram below
+ *
+ * cur->file_pos ------------
+ * |
+ * cur->base |
+ * | |
+ * v v<---- length ---->
+ * --------------------------------------------------------------
+ * | | block#1 | | block#n |
+ * | block#0 | + | ... | + |
+ * | | <- skip -> + | | + <- padding ->|
+ * ------------------------+----------------------+--------------
+ * ^ ^
+ * | |
+ * v iteration#1 iteration#n v
+ * --------------------------------------------------
+ * | | | |
+ * |<---- request ---->| ... |<----- request ---->|
+ * | | | |
+ * --------------------------------------------------
+ * / / | |
+ * / / | |
+ * / / | |
+ * / / | |
+ * / / | |
+ * / / | |
+ * / / | |
+ * / / | |
+ * / / | |
+ * / / | |
+ * <---- request ------> <------ request ----->
+ * --------------------- -----------------------
+ * | | | | | |
+ * |<-skip->|<-nbytes->| -------->|<-nbytes->|<-padding->|
+ * | | | | | | |
+ * --------------------- | -----------------------
+ * ^ \ \ | | |
+ * | \ \ | | |
+ * | \ \ | | |
+ * buf->offset \ \ buf->offset | |
+ * \ \ | |
+ * \ \ | |
+ * \ \ | |
+ * \ \ | |
+ * \ \ | |
+ * \ \ | |
+ * \ \ | |
+ * --------------------------------
+ * | | | |
+ * buffer-------------->| | ... | |
+ * | | | |
+ * --------------------------------
+ * <-count#1->| |
+ * <---------- count#n -------->
+ * <---------- length ---------->
+ *
+ * Additionally, the IO driver has an underlying buffer that is at least
+ * one block-size and may be big enough to allow.
+ */
static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
size_t *length_read)
{
block_dev_state_t *cur;
io_block_spec_t *buf;
io_block_ops_t *ops;
- size_t aligned_length, skip, count, left, padding, block_size;
int lba;
- int buffer_not_aligned;
+ size_t block_size, left;
+ size_t nbytes; /* number of bytes read in one iteration */
+ size_t request; /* number of requested bytes in one iteration */
+ size_t count; /* number of bytes already read */
+ /*
+ * number of leading bytes from start of the block
+ * to the first byte to be read
+ */
+ size_t skip;
+
+ /*
+ * number of trailing bytes between the last byte
+ * to be read and the end of the block
+ */
+ size_t padding;
assert(entity->info != (uintptr_t)NULL);
cur = (block_dev_state_t *)entity->info;
@@ -186,102 +269,107 @@ static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
(length > 0) &&
(ops->read != 0));
- if ((buffer & (block_size - 1)) != 0) {
+ /*
+ * We don't know the number of bytes that we are going
+ * to read in every iteration, because it will depend
+ * on the low level driver.
+ */
+ count = 0;
+ for (left = length; left > 0; left -= nbytes) {
/*
- * buffer isn't aligned with block size.
- * Block device always relies on DMA operation.
- * It's better to make the buffer as block size aligned.
+ * We must only request operations aligned to the block
+ * size. Therefore if file_pos is not block-aligned,
+ * we have to request the operation to start at the
+ * previous block boundary and skip the leading bytes. And
+ * similarly, the number of bytes requested must be a
+ * block size multiple
*/
- buffer_not_aligned = 1;
- } else {
- buffer_not_aligned = 0;
- }
+ skip = cur->file_pos & (block_size - 1);
- skip = cur->file_pos % block_size;
- aligned_length = ((skip + length) + (block_size - 1)) &
- ~(block_size - 1);
- padding = aligned_length - (skip + length);
- left = aligned_length;
- do {
+ /*
+ * Calculate the block number containing file_pos
+ * - e.g. block 3.
+ */
lba = (cur->file_pos + cur->base) / block_size;
- if (left >= buf->length) {
+
+ if (skip + left > buf->length) {
/*
- * Since left is larger, it's impossible to padding.
- *
- * If buffer isn't aligned, we need to use aligned
- * buffer instead.
+ * The underlying read buffer is too small to
+ * read all the required data - limit to just
+ * fill the buffer, and then read again.
*/
- if (skip || buffer_not_aligned) {
- /*
- * The beginning address (file_pos) isn't
- * aligned with block size, we need to use
- * block buffer to read block. Since block
- * device is always relied on DMA operation.
- */
- count = ops->read(lba, buf->offset,
- buf->length);
- } else {
- count = ops->read(lba, buffer, buf->length);
- }
- assert(count == buf->length);
- cur->file_pos += count - skip;
- if (skip || buffer_not_aligned) {
- /*
- * Since there's not aligned block size caused
- * by skip or not aligned buffer, block buffer
- * is used to store data.
- */
- memcpy((void *)buffer,
- (void *)(buf->offset + skip),
- count - skip);
- }
- left = left - (count - skip);
+ request = buf->length;
} else {
- if (skip || padding || buffer_not_aligned) {
- /*
- * The beginning address (file_pos) isn't
- * aligned with block size, we have to read
- * full block by block buffer instead.
- * The size isn't aligned with block size.
- * Use block buffer to avoid overflow.
- *
- * If buffer isn't aligned, use block buffer
- * to avoid DMA error.
- */
- count = ops->read(lba, buf->offset, left);
- } else
- count = ops->read(lba, buffer, left);
- assert(count == left);
- left = left - (skip + padding);
- cur->file_pos += left;
- if (skip || padding || buffer_not_aligned) {
- /*
- * Since there's not aligned block size or
- * buffer, block buffer is used to store data.
- */
- memcpy((void *)buffer,
- (void *)(buf->offset + skip),
- left);
- }
- /* It's already the last block operation */
- left = 0;
+ /*
+ * The underlying read buffer is big enough to
+ * read all the required data. Calculate the
+ * number of bytes to read to align with the
+ * block size.
+ */
+ request = skip + left;
+ request = (request + (block_size - 1)) & ~(block_size - 1);
}
- skip = cur->file_pos % block_size;
- } while (left > 0);
- *length_read = length;
+ request = ops->read(lba, buf->offset, request);
+
+ if (request <= skip) {
+ /*
+ * We couldn't read enough bytes to jump over
+ * the skip bytes, so we should have to read
+ * again the same block, thus generating
+ * the same error.
+ */
+ return -EIO;
+ }
+
+ /*
+ * Need to remove skip and padding bytes,if any, from
+ * the read data when copying to the user buffer.
+ */
+ nbytes = request - skip;
+ padding = (nbytes > left) ? nbytes - left : 0;
+ nbytes -= padding;
+
+ memcpy((void *)(buffer + count),
+ (void *)(buf->offset + skip),
+ nbytes);
+
+ cur->file_pos += nbytes;
+ count += nbytes;
+ }
+ assert(count == length);
+ *length_read = count;
return 0;
}
+/*
+ * This function allows the caller to write any number of bytes
+ * from any position. It hides from the caller that the low level
+ * driver only can write aligned blocks of data.
+ * See comments for block_read for more details.
+ */
static int block_write(io_entity_t *entity, const uintptr_t buffer,
size_t length, size_t *length_written)
{
block_dev_state_t *cur;
io_block_spec_t *buf;
io_block_ops_t *ops;
- size_t aligned_length, skip, count, left, padding, block_size;
int lba;
- int buffer_not_aligned;
+ size_t block_size, left;
+ size_t nbytes; /* number of bytes read in one iteration */
+ size_t request; /* number of requested bytes in one iteration */
+ size_t count; /* number of bytes already read */
+ /*
+ * number of leading bytes from start of the block
+ * to the first byte to be read
+ */
+ size_t skip;
+
+ /*
+ * number of trailing bytes between the last byte
+ * to be read and the end of the block
+ */
+ size_t padding;
assert(entity->info != (uintptr_t)NULL);
cur = (block_dev_state_t *)entity->info;
@@ -293,75 +381,107 @@ static int block_write(io_entity_t *entity, const uintptr_t buffer,
(ops->read != 0) &&
(ops->write != 0));
- if ((buffer & (block_size - 1)) != 0) {
+ /*
+ * We don't know the number of bytes that we are going
+ * to write in every iteration, because it will depend
+ * on the low level driver.
+ */
+ count = 0;
+ for (left = length; left > 0; left -= nbytes) {
/*
- * buffer isn't aligned with block size.
- * Block device always relies on DMA operation.
- * It's better to make the buffer as block size aligned.
+ * We must only request operations aligned to the block
+ * size. Therefore if file_pos is not block-aligned,
+ * we have to request the operation to start at the
+ * previous block boundary and skip the leading bytes. And
+ * similarly, the number of bytes requested must be a
+ * block size multiple
*/
- buffer_not_aligned = 1;
- } else {
- buffer_not_aligned = 0;
- }
+ skip = cur->file_pos & (block_size - 1);
- skip = cur->file_pos % block_size;
- aligned_length = ((skip + length) + (block_size - 1)) &
- ~(block_size - 1);
- padding = aligned_length - (skip + length);
- left = aligned_length;
- do {
+ /*
+ * Calculate the block number containing file_pos
+ * - e.g. block 3.
+ */
lba = (cur->file_pos + cur->base) / block_size;
- if (left >= buf->length) {
- /* Since left is larger, it's impossible to padding. */
- if (skip || buffer_not_aligned) {
- /*
- * The beginning address (file_pos) isn't
- * aligned with block size or buffer isn't
- * aligned, we need to use block buffer to
- * write block.
- */
- count = ops->read(lba, buf->offset,
- buf->length);
- assert(count == buf->length);
- memcpy((void *)(buf->offset + skip),
- (void *)buffer,
- count - skip);
- count = ops->write(lba, buf->offset,
- buf->length);
- } else
- count = ops->write(lba, buffer, buf->length);
- assert(count == buf->length);
- cur->file_pos += count - skip;
- left = left - (count - skip);
+
+ if (skip + left > buf->length) {
+ /*
+ * The underlying read buffer is too small to
+ * read all the required data - limit to just
+ * fill the buffer, and then read again.
+ */
+ request = buf->length;
} else {
- if (skip || padding || buffer_not_aligned) {
+ /*
+ * The underlying read buffer is big enough to
+ * read all the required data. Calculate the
+ * number of bytes to read to align with the
+ * block size.
+ */
+ request = skip + left;
+ request = (request + (block_size - 1)) & ~(block_size - 1);
+ }
+
+ /*
+ * The number of bytes that we are going to write
+ * from the user buffer will depend of the size
+ * of the current request.
+ */
+ nbytes = request - skip;
+ padding = (nbytes > left) ? nbytes - left : 0;
+ nbytes -= padding;
+
+ /*
+ * If we have skip or padding bytes then we have to preserve
+ * some content and it means that we have to read before
+ * writing
+ */
+ if (skip > 0 || padding > 0) {
+ request = ops->read(lba, buf->offset, request);
+ /*
+ * The read may return size less than
+ * requested. Round down to the nearest block
+ * boundary
+ */
+ request &= ~(block_size-1);
+ if (request <= skip) {
/*
- * The beginning address (file_pos) isn't
- * aligned with block size, we need to avoid
- * poluate data in the beginning. Reading and
- * skipping the beginning is the only way.
- * The size isn't aligned with block size.
- * Use block buffer to avoid overflow.
- *
- * If buffer isn't aligned, use block buffer
- * to avoid DMA error.
+ * We couldn't read enough bytes to jump over
+ * the skip bytes, so we should have to read
+ * again the same block, thus generating
+ * the same error.
*/
- count = ops->read(lba, buf->offset, left);
- assert(count == left);
- memcpy((void *)(buf->offset + skip),
- (void *)buffer,
- left - skip - padding);
- count = ops->write(lba, buf->offset, left);
- } else
- count = ops->write(lba, buffer, left);
- assert(count == left);
- cur->file_pos += left - (skip + padding);
- /* It's already the last block operation */
- left = 0;
+ return -EIO;
+ }
+ nbytes = request - skip;
+ padding = (nbytes > left) ? nbytes - left : 0;
+ nbytes -= padding;
}
- skip = cur->file_pos % block_size;
- } while (left > 0);
- *length_written = length;
+
+ memcpy((void *)(buf->offset + skip),
+ (void *)(buffer + count),
+ nbytes);
+
+ request = ops->write(lba, buf->offset, request);
+ if (request <= skip)
+ return -EIO;
+
+ /*
+ * And the previous write operation may modify the size
+ * of the request, so again, we have to calculate the
+ * number of bytes that we consumed from the user
+ * buffer
+ */
+ nbytes = request - skip;
+ padding = (nbytes > left) ? nbytes - left : 0;
+ nbytes -= padding;
+
+ cur->file_pos += nbytes;
+ count += nbytes;
+ }
+ assert(count == length);
+ *length_written = count;
+
return 0;
}
diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S
index ed35df82..63a0fa77 100644
--- a/include/common/aarch64/el3_common_macros.S
+++ b/include/common/aarch64/el3_common_macros.S
@@ -127,9 +127,9 @@
* CPTR_EL3.TTA: Set to zero so that System register accesses to the
* trace registers do not trap to EL3.
*
- * CPTR_EL3.TFP: Set to zero so that accesses to Advanced SIMD and
- * floating-point functionality do not trap to EL3.
- * ---------------------------------------------------------------------
+ * CPTR_EL3.TFP: Set to zero so that accesses to the V- or Z- registers
+ * by Advanced SIMD, floating-point or SVE instructions (if implemented)
+ * do not trap to EL3.
*/
mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT))
msr cptr_el3, x0
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index 15ffc578..8915ba06 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -205,7 +205,6 @@ int is_mem_free(uintptr_t free_base, size_t free_size,
#if LOAD_IMAGE_V2
-int load_image(unsigned int image_id, image_info_t *image_data);
int load_auth_image(unsigned int image_id, image_info_t *image_data);
#else
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 65e9fc1b..96e2d5fe 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -114,6 +114,9 @@
#define ID_AA64PFR0_AMU_LENGTH U(4)
#define ID_AA64PFR0_AMU_MASK U(0xf)
#define ID_AA64PFR0_ELX_MASK U(0xf)
+#define ID_AA64PFR0_SVE_SHIFT U(32)
+#define ID_AA64PFR0_SVE_MASK U(0xf)
+#define ID_AA64PFR0_SVE_LENGTH U(4)
/* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
#define ID_AA64DFR0_PMS_SHIFT U(32)
@@ -301,6 +304,7 @@
#define TAM_BIT (U(1) << 30)
#define TTA_BIT (U(1) << 20)
#define TFP_BIT (U(1) << 10)
+#define CPTR_EZ_BIT (U(1) << 8)
#define CPTR_EL3_RESET_VAL U(0x0)
/* CPTR_EL2 definitions */
@@ -309,6 +313,7 @@
#define CPTR_EL2_TAM_BIT (U(1) << 30)
#define CPTR_EL2_TTA_BIT (U(1) << 20)
#define CPTR_EL2_TFP_BIT (U(1) << 10)
+#define CPTR_EL2_TZ_BIT (U(1) << 8)
#define CPTR_EL2_RESET_VAL CPTR_EL2_RES1
/* CPSR/SPSR definitions */
@@ -556,6 +561,18 @@
#define PMCR_EL0_D_BIT (U(1) << 3)
/*******************************************************************************
+ * Definitions for system register interface to SVE
+ ******************************************************************************/
+#define ZCR_EL3 S3_6_C1_C2_0
+#define ZCR_EL2 S3_4_C1_C2_0
+
+/* ZCR_EL3 definitions */
+#define ZCR_EL3_LEN_MASK U(0xf)
+
+/* ZCR_EL2 definitions */
+#define ZCR_EL2_LEN_MASK U(0xf)
+
+/*******************************************************************************
* Definitions of MAIR encodings for device and normal memory
******************************************************************************/
/*
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index b6be1675..831dfb06 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -329,6 +329,9 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0)
DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2)
+
#define IS_IN_EL(x) \
(GET_EL(read_CurrentEl()) == MODE_EL##x)
diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h
new file mode 100644
index 00000000..28923e3f
--- /dev/null
+++ b/include/lib/extensions/sve.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SVE_H__
+#define __SVE_H__
+
+void sve_enable(int el2_unused);
+
+#endif /* __SVE_H__ */
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 73a9c533..ba3e3603 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -168,21 +168,28 @@ typedef struct xlat_ctx xlat_ctx_t;
_xlat_tables_count, \
_virt_addr_space_size, \
_phy_addr_space_size, \
- IMAGE_XLAT_DEFAULT_REGIME)
+ IMAGE_XLAT_DEFAULT_REGIME, \
+ "xlat_table")
/*
- * Same as REGISTER_XLAT_CONTEXT plus the additional parameter _xlat_regime to
- * specify the translation regime managed by this xlat_ctx_t instance. The
- * values are the one from xlat_regime_t enumeration.
+ * Same as REGISTER_XLAT_CONTEXT plus the additional parameters:
+ *
+ * _xlat_regime:
+ * Specify the translation regime managed by this xlat_ctx_t instance. The
+ * values are the one from xlat_regime_t enumeration.
+ *
+ * _section_name:
+ * Specify the name of the section where the translation tables have to be
+ * placed by the linker.
*/
#define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \
_virt_addr_space_size, _phy_addr_space_size, \
- _xlat_regime) \
+ _xlat_regime, _section_name) \
_REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \
_xlat_tables_count, \
_virt_addr_space_size, \
_phy_addr_space_size, \
- _xlat_regime)
+ _xlat_regime, _section_name)
/******************************************************************************
* Generic translation table APIs.
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index 96dee1a0..1be99b71 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -123,7 +123,7 @@ struct xlat_ctx {
#define _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, _xlat_tables_count, \
_virt_addr_space_size, _phy_addr_space_size, \
- _xlat_regime) \
+ _xlat_regime, _section_name) \
CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size), \
assert_invalid_virtual_addr_space_size_for_##_ctx_name); \
\
@@ -134,7 +134,7 @@ struct xlat_ctx {
\
static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \
[XLAT_TABLE_ENTRIES] \
- __aligned(XLAT_TABLE_SIZE) __section("xlat_table"); \
+ __aligned(XLAT_TABLE_SIZE) __section(_section_name); \
\
static uint64_t _ctx_name##_base_xlat_table \
[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 68f4a0ec..e0c3c868 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -90,11 +90,7 @@
* PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
* little space for growth.
*/
-#if ENABLE_SPM
-#define PLAT_ARM_MAX_BL31_SIZE 0x28000
-#else
-#define PLAT_ARM_MAX_BL31_SIZE 0x1D000
-#endif
+#define PLAT_ARM_MAX_BL31_SIZE 0x1E000
#ifdef AARCH32
/*
diff --git a/include/plat/arm/common/arm_common.ld.S b/include/plat/arm/common/arm_common.ld.S
index 478b08c2..6edfa099 100644
--- a/include/plat/arm/common/arm_common.ld.S
+++ b/include/plat/arm/common/arm_common.ld.S
@@ -6,6 +6,8 @@
#ifndef __ARM_COMMON_LD_S__
#define __ARM_COMMON_LD_S__
+#include <xlat_tables_defs.h>
+
MEMORY {
EL3_SEC_DRAM (rw): ORIGIN = ARM_EL3_TZC_DRAM1_BASE, LENGTH = ARM_EL3_TZC_DRAM1_SIZE
}
@@ -13,14 +15,14 @@ MEMORY {
SECTIONS
{
. = ARM_EL3_TZC_DRAM1_BASE;
- ASSERT(. == ALIGN(4096),
+ ASSERT(. == ALIGN(PAGE_SIZE),
"ARM_EL3_TZC_DRAM_BASE address is not aligned on a page boundary.")
- el3_tzc_dram (NOLOAD) : ALIGN(4096) {
+ el3_tzc_dram (NOLOAD) : ALIGN(PAGE_SIZE) {
__EL3_SEC_DRAM_START__ = .;
*(arm_el3_tzc_dram)
__EL3_SEC_DRAM_UNALIGNED_END__ = .;
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__EL3_SEC_DRAM_END__ = .;
} >EL3_SEC_DRAM
}
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 78875259..f38c357b 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -491,4 +491,15 @@
#define ARM_SDEI_DS_EVENT_1 2001
#define ARM_SDEI_DS_EVENT_2 2002
+#define ARM_SDEI_PRIVATE_EVENTS \
+ SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI), \
+ SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
+ SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
+ SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
+
+#define ARM_SDEI_SHARED_EVENTS \
+ SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
+ SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
+ SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
+
#endif /* __ARM_DEF_H__ */
diff --git a/include/plat/arm/common/arm_spm_def.h b/include/plat/arm/common/arm_spm_def.h
index 83277a6c..3f5c958d 100644
--- a/include/plat/arm/common/arm_spm_def.h
+++ b/include/plat/arm/common/arm_spm_def.h
@@ -98,6 +98,12 @@
/* Total number of memory regions with distinct properties */
#define ARM_SP_IMAGE_NUM_MEM_REGIONS 6
+/*
+ * Name of the section to put the translation tables used by the S-EL1/S-EL0
+ * context of a Secure Partition.
+ */
+#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "arm_el3_tzc_dram"
+
/* Cookies passed to the Secure Partition at boot. Not used by ARM platforms. */
#define PLAT_SPM_COOKIE_0 ULL(0)
#define PLAT_SPM_COOKIE_1 ULL(0)
diff --git a/include/services/spm_svc.h b/include/services/spm_svc.h
index 2c8c7cd8..738979eb 100644
--- a/include/services/spm_svc.h
+++ b/include/services/spm_svc.h
@@ -32,24 +32,24 @@
* Manager from the Secure Partition(s). These services enable a partition to
* handle delegated events and request privileged operations from the manager.
*/
-#define SPM_VERSION_AARCH32 U(0x84000060)
-#define SP_EVENT_COMPLETE_AARCH64 U(0xC4000061)
-#define SP_MEM_ATTRIBUTES_GET_AARCH64 U(0xC4000064)
-#define SP_MEM_ATTRIBUTES_SET_AARCH64 U(0xC4000065)
+#define SPM_VERSION_AARCH32 U(0x84000060)
+#define SP_EVENT_COMPLETE_AARCH64 U(0xC4000061)
+#define SP_MEMORY_ATTRIBUTES_GET_AARCH64 U(0xC4000064)
+#define SP_MEMORY_ATTRIBUTES_SET_AARCH64 U(0xC4000065)
/*
- * Macros used by SP_MEM_ATTRIBUTES_SET_AARCH64.
+ * Macros used by SP_MEMORY_ATTRIBUTES_SET_AARCH64.
*/
-#define SP_MEM_ATTR_ACCESS_NOACCESS U(0)
-#define SP_MEM_ATTR_ACCESS_RW U(1)
+#define SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS U(0)
+#define SP_MEMORY_ATTRIBUTES_ACCESS_RW U(1)
/* Value U(2) is reserved. */
-#define SP_MEM_ATTR_ACCESS_RO U(3)
-#define SP_MEM_ATTR_ACCESS_MASK U(3)
-#define SP_MEM_ATTR_ACCESS_SHIFT 0
+#define SP_MEMORY_ATTRIBUTES_ACCESS_RO U(3)
+#define SP_MEMORY_ATTRIBUTES_ACCESS_MASK U(3)
+#define SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT 0
-#define SP_MEM_ATTR_EXEC (U(0) << 2)
-#define SP_MEM_ATTR_NON_EXEC (U(1) << 2)
+#define SP_MEMORY_ATTRIBUTES_EXEC (U(0) << 2)
+#define SP_MEMORY_ATTRIBUTES_NON_EXEC (U(1) << 2)
/*
* SMC IDs defined in [1] for accessing secure partition services from the
@@ -59,8 +59,8 @@
#define SP_VERSION_AARCH64 U(0xC4000040)
#define SP_VERSION_AARCH32 U(0x84000040)
-#define SP_COMMUNICATE_AARCH64 U(0xC4000041)
-#define SP_COMMUNICATE_AARCH32 U(0x84000041)
+#define MM_COMMUNICATE_AARCH64 U(0xC4000041)
+#define MM_COMMUNICATE_AARCH32 U(0x84000041)
/* SPM error codes. */
#define SPM_SUCCESS 0
diff --git a/lib/cpus/aarch32/cortex_a53.S b/lib/cpus/aarch32/cortex_a53.S
index 74cedc35..1647e169 100644
--- a/lib/cpus/aarch32/cortex_a53.S
+++ b/lib/cpus/aarch32/cortex_a53.S
@@ -174,7 +174,7 @@ func cortex_a53_core_pwr_dwn
push {r12, lr}
/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
ldcopr r0, SCTLR
tst r0, #SCTLR_C_BIT
ASM_ASSERT(eq)
@@ -204,7 +204,7 @@ func cortex_a53_cluster_pwr_dwn
push {r12, lr}
/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
ldcopr r0, SCTLR
tst r0, #SCTLR_C_BIT
ASM_ASSERT(eq)
diff --git a/lib/cpus/aarch32/cortex_a57.S b/lib/cpus/aarch32/cortex_a57.S
index b5189e77..64a6d674 100644
--- a/lib/cpus/aarch32/cortex_a57.S
+++ b/lib/cpus/aarch32/cortex_a57.S
@@ -406,7 +406,7 @@ func cortex_a57_core_pwr_dwn
push {r12, lr}
/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
ldcopr r0, SCTLR
tst r0, #SCTLR_C_BIT
ASM_ASSERT(eq)
@@ -448,7 +448,7 @@ func cortex_a57_cluster_pwr_dwn
push {r12, lr}
/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
ldcopr r0, SCTLR
tst r0, #SCTLR_C_BIT
ASM_ASSERT(eq)
diff --git a/lib/cpus/aarch32/cortex_a72.S b/lib/cpus/aarch32/cortex_a72.S
index 69cc2ea5..75505206 100644
--- a/lib/cpus/aarch32/cortex_a72.S
+++ b/lib/cpus/aarch32/cortex_a72.S
@@ -120,7 +120,7 @@ func cortex_a72_core_pwr_dwn
push {r12, lr}
/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
ldcopr r0, SCTLR
tst r0, #SCTLR_C_BIT
ASM_ASSERT(eq)
@@ -167,7 +167,7 @@ func cortex_a72_cluster_pwr_dwn
push {r12, lr}
/* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
ldcopr r0, SCTLR
tst r0, #SCTLR_C_BIT
ASM_ASSERT(eq)
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index b892729e..c6c2249a 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -18,6 +18,7 @@
#include <smcc_helpers.h>
#include <spe.h>
#include <string.h>
+#include <sve.h>
#include <utils.h>
@@ -225,6 +226,10 @@ static void enable_extensions_nonsecure(int el2_unused)
#if ENABLE_AMU
amu_enable(el2_unused);
#endif
+
+#if ENABLE_SVE_FOR_NS
+ sve_enable(el2_unused);
+#endif
#endif
}
diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c
new file mode 100644
index 00000000..14e51bd8
--- /dev/null
+++ b/lib/extensions/sve/sve.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <pubsub.h>
+#include <sve.h>
+
+static void *disable_sve_hook(const void *arg)
+{
+ uint64_t features;
+
+ features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
+ if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
+ uint64_t cptr;
+
+ /*
+ * Disable SVE, SIMD and FP access for the Secure world.
+ * As the SIMD/FP registers are part of the SVE Z-registers, any
+ * use of SIMD/FP functionality will corrupt the SVE registers.
+ * Therefore it is necessary to prevent use of SIMD/FP support
+ * in the Secure world as well as SVE functionality.
+ */
+ cptr = read_cptr_el3();
+ cptr = (cptr | TFP_BIT) & ~(CPTR_EZ_BIT);
+ write_cptr_el3(cptr);
+
+ /*
+ * No explicit ISB required here as ERET to switch to Secure
+ * world covers it
+ */
+ }
+ return 0;
+}
+
+static void *enable_sve_hook(const void *arg)
+{
+ uint64_t features;
+
+ features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
+ if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
+ uint64_t cptr;
+
+ /*
+ * Enable SVE, SIMD and FP access for the Non-secure world.
+ */
+ cptr = read_cptr_el3();
+ cptr = (cptr | CPTR_EZ_BIT) & ~(TFP_BIT);
+ write_cptr_el3(cptr);
+
+ /*
+ * No explicit ISB required here as ERET to switch to Non-secure
+ * world covers it
+ */
+ }
+ return 0;
+}
+
+void sve_enable(int el2_unused)
+{
+ uint64_t features;
+
+ features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
+ if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
+ uint64_t cptr;
+#if CTX_INCLUDE_FPREGS
+ /*
+ * CTX_INCLUDE_FPREGS is not supported on SVE enabled systems.
+ */
+ assert(0);
+#endif
+ /*
+ * Update CPTR_EL3 to enable access to SVE functionality for the
+ * Non-secure world.
+ * NOTE - assumed that CPTR_EL3.TFP is set to allow access to
+ * the SIMD, floating-point and SVE support.
+ *
+ * CPTR_EL3.EZ: Set to 1 to enable access to SVE functionality
+ * in the Non-secure world.
+ */
+ cptr = read_cptr_el3();
+ cptr |= CPTR_EZ_BIT;
+ write_cptr_el3(cptr);
+
+ /*
+ * Need explicit ISB here to guarantee that update to ZCR_ELx
+ * and CPTR_EL2.TZ do not result in trap to EL3.
+ */
+ isb();
+
+ /*
+ * Ensure lower ELs have access to full vector length.
+ */
+ write_zcr_el3(ZCR_EL3_LEN_MASK);
+
+ if (el2_unused) {
+ /*
+ * Update CPTR_EL2 to enable access to SVE functionality
+ * for Non-secure world, EL2 and Non-secure EL1 and EL0.
+ * NOTE - assumed that CPTR_EL2.TFP is set to allow
+ * access to the SIMD, floating-point and SVE support.
+ *
+ * CPTR_EL2.TZ: Set to 0 to enable access to SVE support
+ * for EL2 and Non-secure EL1 and EL0.
+ */
+ cptr = read_cptr_el2();
+ cptr &= ~(CPTR_EL2_TZ_BIT);
+ write_cptr_el2(cptr);
+
+ /*
+ * Ensure lower ELs have access to full vector length.
+ */
+ write_zcr_el2(ZCR_EL2_LEN_MASK);
+ }
+ /*
+ * No explicit ISB required here as ERET to switch to
+ * Non-secure world covers it.
+ */
+ }
+}
+
+SUBSCRIBE_TO_EVENT(cm_exited_normal_world, disable_sve_hook);
+SUBSCRIBE_TO_EVENT(cm_entering_normal_world, enable_sve_hook);
diff --git a/maintainers.rst b/maintainers.rst
index 701ea17e..04ab695e 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -21,8 +21,8 @@ Jens Wiklander (jens.wiklander@linaro.org, `jenswi-linaro`_)
Files:
-- docs/spd/optee-dispatcher.md
-- docs/plat/qemu.md
+- docs/plat/qemu.rst
+- docs/spd/optee-dispatcher.rst
- services/spd/opteed/\*
- plat/qemu/\*
@@ -33,8 +33,9 @@ Varun Wadekar (vwadekar@nvidia.com, `vwadekar`_)
Files:
-- docs/spd/tlk-dispatcher.md
-- docs/spd/trusty-dispatcher.md
+- docs/plat/nvidia-tegra.rst
+- docs/spd/tlk-dispatcher.rst
+- docs/spd/trusty-dispatcher.rst
- include/bl32/payloads/tlk.h
- include/lib/cpus/aarch64/denver.h
- lib/cpus/aarch64/denver.S
@@ -49,8 +50,9 @@ Haojian Zhuang (haojian.zhuang@linaro.org, `hzhuang1`_)
Files:
-- docs/plat/hikey.md
-- docs/plat/hikey960.md
+- docs/plat/hikey.rst
+- docs/plat/hikey960.rst
+- docs/plat/poplar.rst
- drivers/emmc/\*
- drivers/partition/\*
- drivers/synopsys/emmc/\*
@@ -71,24 +73,44 @@ Files:
- plat/mediatek/\*
+Raspberry Pi 3 platform sub-maintainer
+--------------------------------------
+
+Antonio Niño Díaz (antonio.ninodiaz@arm.com, `antonio-nino-diaz-arm`_)
+
+Files:
+
+- docs/plat/rpi3.rst
+- plat/rpi3/\*
+
RockChip platform sub-maintainer
--------------------------------
Tony Xie (tony.xie@rock-chips.com, `TonyXie06`_
-or `rkchrome`_)
+or `rockchip-linux`_)
Files:
- plat/rockchip/\*
+UniPhier platform sub-maintainer
+--------------------------------
+
+Masahiro Yamada (yamada.masahiro@socionext.com, `masahir0y`_)
+
+Files:
+
+- docs/plat/socionext-uniphier.rst
+- plat/socionext/\*
+
Xilinx platform sub-maintainer
------------------------------
-Sören Brinkmann (soren.brinkmann@xilinx.com, `sorenb-xlnx`_)
+Siva Durga Prasad Paladugu (siva.durga.paladugu@xilinx.com, `sivadur`_)
Files:
-- docs/plat/xilinx-zynqmp.md
+- docs/plat/xilinx-zynqmp.rst
- plat/xilinx/\*
ARMv7 architecture sub-maintainer
@@ -96,13 +118,15 @@ ARMv7 architecture sub-maintainer
Etienne Carriere (etienne.carriere@linaro.org, `etienne-lms`_)
+.. _antonio-nino-diaz-arm: https://github.com/antonio-nino-diaz-arm
.. _danh-arm: https://github.com/danh-arm
.. _davidcunado-arm: https://github.com/davidcunado-arm
.. _jenswi-linaro: https://github.com/jenswi-linaro
.. _vwadekar: https://github.com/vwadekar
.. _hzhuang1: https://github.com/hzhuang1
+.. _masahir0y: https://github.com/masahir0y
.. _mtk09422: https://github.com/mtk09422
.. _TonyXie06: https://github.com/TonyXie06
-.. _rkchrome: https://github.com/rkchrome
-.. _sorenb-xlnx: https://github.com/sorenb-xlnx
+.. _sivadur: https://github.com/sivadur
+.. _rockchip-linux: https://github.com/rockchip-linux
.. _etienne-lms: https://github.com/etienne-lms
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 7531f6d8..e1bfbbe7 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -336,3 +336,49 @@ $(eval $(call MAKE_TOOL_ARGS,$(1),$(BIN),$(2)))
endef
+define SOURCES_TO_DTBS
+ $(notdir $(patsubst %.dts,%.dtb,$(filter %.dts,$(1))))
+endef
+
+# MAKE_FDT macro defines the targets and options to build each FDT binary
+# Arguments: (none)
+define MAKE_FDT
+ $(eval DTB_BUILD_DIR := ${BUILD_PLAT}/fdts)
+ $(eval DTBS := $(addprefix $(DTB_BUILD_DIR)/,$(call SOURCES_TO_DTBS,$(FDT_SOURCES))))
+ $(eval TEMP_DTB_DIRS := $(sort $(dir ${DTBS})))
+ # The $(dir ) function leaves a trailing / on the directory names
+ # Rip off the / to match directory names with make rule targets.
+ $(eval DTB_DIRS := $(patsubst %/,%,$(TEMP_DTB_DIRS)))
+
+$(eval $(foreach objd,${DTB_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
+
+fdt_dirs: ${DTB_DIRS}
+
+endef
+
+# MAKE_DTB generate the Flattened device tree binary (device tree binary)
+# $(1) = output directory
+# $(2) = input dts
+define MAKE_DTB
+
+$(eval DOBJ := $(1)/$(patsubst %.dts,%.dtb,$(notdir $(2))))
+$(eval DEP := $(patsubst %.dtb,%.d,$(DOBJ)))
+
+$(DOBJ): $(2) | fdt_dirs
+ @echo " DTC $$<"
+ $$(Q)$$(DTC) $$(DTC_FLAGS) -d $(DEP) -o $$@ $$<
+
+-include $(DEP)
+
+endef
+
+# MAKE_DTBS builds flattened device tree sources
+# $(1) = output directory
+# $(2) = list of flattened device tree source files
+define MAKE_DTBS
+ $(eval DOBJS := $(filter %.dts,$(2)))
+ $(eval REMAIN := $(filter-out %.dts,$(2)))
+ $(eval $(foreach obj,$(DOBJS),$(call MAKE_DTB,$(1),$(obj))))
+
+ $(and $(REMAIN),$(error Unexpected s present: $(REMAIN)))
+endef
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 9f7abed1..fa0d17de 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -24,9 +24,6 @@ ARM_ARCH_MINOR := 0
# in EL3. The platform port can change this value if needed.
ARM_GIC_ARCH := 2
-# Flag used to indicate if ASM_ASSERTION should be enabled for the build.
-ASM_ASSERTION := 0
-
# Base commit to perform code check on
BASE_COMMIT := origin/master
@@ -158,3 +155,12 @@ ifeq (${ARCH},aarch32)
endif
ENABLE_AMU := 0
+
+# By default, enable Scalable Vector Extension if implemented for Non-secure
+# lower ELs
+# Note SVE is only supported on AArch64 - therefore do not enable in AArch32
+ifneq (${ARCH},aarch32)
+ ENABLE_SVE_FOR_NS := 1
+else
+ override ENABLE_SVE_FOR_NS := 0
+endif
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 13bd8f23..72845843 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -402,12 +402,20 @@ plat_psci_ops_t plat_arm_psci_pm_ops = {
.validate_ns_entrypoint = arm_validate_psci_entrypoint,
.translate_power_state_by_mpidr = fvp_translate_power_state_by_mpidr,
.get_node_hw_state = fvp_node_hw_state,
+#if !ARM_BL31_IN_DRAM
+ /*
+ * The TrustZone Controller is set up during the warmboot sequence after
+ * resuming the CPU from a SYSTEM_SUSPEND. If BL31 is located in SRAM
+ * this is not a problem but, if it is in TZC-secured DRAM, it tries to
+ * reconfigure the same memory it is running on, causing an exception.
+ */
.get_sys_suspend_power_state = fvp_get_sys_suspend_power_state,
-/*
- * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
- * as that would require mapping in all of NS DRAM into BL31 or BL32.
- */
+#endif
#if !RESET_TO_BL31 && !RESET_TO_SP_MIN
+ /*
+ * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
+ * as that would require mapping in all of NS DRAM into BL31 or BL32.
+ */
.mem_protect_chk = arm_psci_mem_protect_chk,
.read_mem_protect = arm_psci_read_mem_protect,
.write_mem_protect = arm_nor_psci_write_mem_protect,
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 310db7b6..4ac08504 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -8,6 +8,7 @@
#define __PLATFORM_DEF_H__
#include <arm_def.h>
+#include <arm_spm_def.h>
#include <board_arm_def.h>
#include <common_def.h>
#include <tzc400.h>
@@ -145,4 +146,7 @@
#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS
+#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS
+
#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index e475ece5..cac47f72 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -238,4 +238,7 @@
/* CSS SoC NIC-400 Global Programmers View (GPV) */
#define PLAT_SOC_CSS_NIC400_BASE 0x2a000000
+#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS
+#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS
+
#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index bfb7847f..fee4391d 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -99,6 +99,9 @@ ENABLE_PLAT_COMPAT := 0
# Enable memory map related constants optimisation
ARM_BOARD_OPTIMISE_MEM := 1
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
include plat/arm/board/common/board_css.mk
include plat/arm/common/arm_common.mk
include plat/arm/soc/common/soc_css.mk
diff --git a/plat/arm/common/aarch64/arm_sdei.c b/plat/arm/common/aarch64/arm_sdei.c
index 514800c3..687b21d4 100644
--- a/plat/arm/common/aarch64/arm_sdei.c
+++ b/plat/arm/common/aarch64/arm_sdei.c
@@ -11,23 +11,14 @@
#include <sdei.h>
/* Private event mappings */
-static sdei_ev_map_t arm_private_sdei[] = {
- /* Event 0 */
- SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI),
-
- /* Dynamic private events */
- SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
- SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
- SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+static sdei_ev_map_t arm_sdei_private[] = {
+ PLAT_ARM_PRIVATE_SDEI_EVENTS
};
/* Shared event mappings */
-static sdei_ev_map_t arm_shared_sdei[] = {
- /* Dynamic shared events */
- SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
- SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
- SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+static sdei_ev_map_t arm_sdei_shared[] = {
+ PLAT_ARM_SHARED_SDEI_EVENTS
};
/* Export ARM SDEI events */
-REGISTER_SDEI_MAP(arm_private_sdei, arm_shared_sdei);
+REGISTER_SDEI_MAP(arm_sdei_private, arm_sdei_shared);
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 17acae52..fab57f14 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -7,13 +7,9 @@
ifeq (${ARCH}, aarch64)
# On ARM standard platorms, the TSP can execute from Trusted SRAM, Trusted
# DRAM (if available) or the TZC secured area of DRAM.
- # Trusted SRAM is the default.
+ # TZC secured DRAM is the default.
- ifneq (${TRUSTED_BOARD_BOOT},0)
- ARM_TSP_RAM_LOCATION ?= dram
- else
- ARM_TSP_RAM_LOCATION ?= tsram
- endif
+ ARM_TSP_RAM_LOCATION ?= dram
ifeq (${ARM_TSP_RAM_LOCATION}, tsram)
ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
index 23c03173..cf133268 100644
--- a/plat/arm/common/arm_tzc400.c
+++ b/plat/arm/common/arm_tzc400.c
@@ -74,8 +74,8 @@ void arm_tzc400_setup(void)
#else /* if defined(EL3_PAYLOAD_BASE) */
- /* Allow secure access only to DRAM for EL3 payloads. */
- tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
+ /* Allow Secure and Non-secure access to DRAM for EL3 payloads */
+ tzc400_configure_region0(TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS);
#endif /* EL3_PAYLOAD_BASE */
diff --git a/plat/compat/plat_compat.mk b/plat/compat/plat_compat.mk
index af885421..f1867da1 100644
--- a/plat/compat/plat_compat.mk
+++ b/plat/compat/plat_compat.mk
@@ -18,3 +18,6 @@ PLAT_BL_COMMON_SOURCES += plat/compat/aarch64/plat_helpers_compat.S
BL31_SOURCES += plat/common/plat_psci_common.c \
plat/compat/plat_pm_compat.c \
plat/compat/plat_topology_compat.c
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk
index 26218a40..524fa6a4 100644
--- a/plat/hisilicon/hikey/platform.mk
+++ b/plat/hisilicon/hikey/platform.mk
@@ -24,6 +24,7 @@ PLAT_PARTITION_MAX_ENTRIES := 12
PLAT_PL061_MAX_GPIOS := 160
COLD_BOOT_SINGLE_CPU := 1
PROGRAMMABLE_RESET_ADDRESS := 1
+ENABLE_SVE_FOR_NS := 0
# Process flags
$(eval $(call add_define,HIKEY_TSP_RAM_LOCATION_ID))
@@ -119,3 +120,5 @@ endif
ERRATA_A53_836870 := 1
ERRATA_A53_843419 := 1
ERRATA_A53_855873 := 1
+
+FIP_ALIGN := 512
diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c
index 348cdba5..078f0d81 100644
--- a/plat/hisilicon/hikey960/hikey960_pm.c
+++ b/plat/hisilicon/hikey960/hikey960_pm.c
@@ -26,6 +26,38 @@
#define SYSTEM_PWR_STATE(state) \
((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+#define PSTATE_WIDTH 4
+#define PSTATE_MASK ((1 << PSTATE_WIDTH) - 1)
+
+#define MAKE_PWRSTATE(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl2_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH * 2)) | \
+ ((lvl1_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH)) | \
+ ((lvl0_state) << (PSTATE_ID_SHIFT)) | \
+ ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+const unsigned int hikey960_pwr_idle_states[] = {
+ /* State-id - 0x001 */
+ MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
+ PLAT_MAX_STB_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x002 */
+ MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
+ PLAT_MAX_RET_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x003 */
+ MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
+ PLAT_MAX_OFF_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x033 */
+ MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_OFF_STATE,
+ PLAT_MAX_OFF_STATE, MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
+ 0,
+};
+
#define DMAC_GLB_REG_SEC 0x694
#define AXI_CONF_BASE 0x820
@@ -36,16 +68,21 @@ static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state)
unsigned long scr;
unsigned int val = 0;
- assert(cpu_state == PLAT_MAX_RET_STATE);
+ assert(cpu_state == PLAT_MAX_STB_STATE ||
+ cpu_state == PLAT_MAX_RET_STATE);
scr = read_scr_el3();
/* Enable Physical IRQ and FIQ to wake the CPU*/
write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
- set_retention_ticks(val);
+ if (cpu_state == PLAT_MAX_RET_STATE)
+ set_retention_ticks(val);
+
wfi();
- clr_retention_ticks(val);
+
+ if (cpu_state == PLAT_MAX_RET_STATE)
+ clr_retention_ticks(val);
/*
* Restore SCR to the original value, synchronisazion of
@@ -124,38 +161,34 @@ static void __dead2 hikey960_system_reset(void)
int hikey960_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
- int pstate = psci_get_pstate_type(power_state);
- int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ unsigned int state_id;
int i;
assert(req_state);
- if (pwr_lvl > PLAT_MAX_PWR_LVL)
- return PSCI_E_INVALID_PARAMS;
-
- /* Sanity check the requested state */
- if (pstate == PSTATE_TYPE_STANDBY) {
- /*
- * It's possible to enter standby only on power level 0
- * Ignore any other power level.
- */
- if (pwr_lvl != MPIDR_AFFLVL0)
- return PSCI_E_INVALID_PARAMS;
-
- req_state->pwr_domain_state[MPIDR_AFFLVL0] =
- PLAT_MAX_RET_STATE;
- } else {
- for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
- req_state->pwr_domain_state[i] =
- PLAT_MAX_OFF_STATE;
- }
-
/*
- * We expect the 'state id' to be zero.
+ * Currently we are using a linear search for finding the matching
+ * entry in the idle power state array. This can be made a binary
+ * search if the number of entries justify the additional complexity.
*/
- if (psci_get_pstate_id(power_state))
+ for (i = 0; !!hikey960_pwr_idle_states[i]; i++) {
+ if (power_state == hikey960_pwr_idle_states[i])
+ break;
+ }
+
+ /* Return error if entry not found in the idle state array */
+ if (!hikey960_pwr_idle_states[i])
return PSCI_E_INVALID_PARAMS;
+ i = 0;
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id) {
+ req_state->pwr_domain_state[i++] = state_id & PSTATE_MASK;
+ state_id >>= PSTATE_WIDTH;
+ }
+
return PSCI_E_SUCCESS;
}
diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h
index cb760907..2ac7f2a7 100644
--- a/plat/hisilicon/hikey960/include/platform_def.h
+++ b/plat/hisilicon/hikey960/include/platform_def.h
@@ -31,8 +31,10 @@
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
PLATFORM_CLUSTER_COUNT + 1)
-#define PLAT_MAX_RET_STATE 1
-#define PLAT_MAX_OFF_STATE 2
+#define PLAT_MAX_RUN_STATE 0
+#define PLAT_MAX_STB_STATE 1
+#define PLAT_MAX_RET_STATE 2
+#define PLAT_MAX_OFF_STATE 3
#define MAX_IO_DEVICES 3
#define MAX_IO_HANDLES 4
diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk
index da7bb825..cb97deb6 100644
--- a/plat/hisilicon/hikey960/platform.mk
+++ b/plat/hisilicon/hikey960/platform.mk
@@ -20,6 +20,7 @@ endif
CRASH_CONSOLE_BASE := PL011_UART6_BASE
COLD_BOOT_SINGLE_CPU := 1
PROGRAMMABLE_RESET_ADDRESS := 1
+ENABLE_SVE_FOR_NS := 0
# Process flags
$(eval $(call add_define,HIKEY960_TSP_RAM_LOCATION_ID))
@@ -100,3 +101,5 @@ BL31_SOURCES += drivers/arm/cci/cci.c \
ERRATA_A53_836870 := 1
ERRATA_A53_843419 := 1
ERRATA_A53_855873 := 1
+
+FIP_ALIGN := 512
diff --git a/plat/hisilicon/poplar/aarch64/platform_common.c b/plat/hisilicon/poplar/aarch64/platform_common.c
index a7dac4fb..762bd846 100644
--- a/plat/hisilicon/poplar/aarch64/platform_common.c
+++ b/plat/hisilicon/poplar/aarch64/platform_common.c
@@ -25,9 +25,14 @@
DEVICE_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
+#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \
+ TSP_SEC_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
static const mmap_region_t poplar_mmap[] = {
MAP_DDR,
MAP_DEVICE,
+ MAP_TSP_MEM,
{0}
};
diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c
index 1741475b..db507c32 100644
--- a/plat/hisilicon/poplar/bl2_plat_setup.c
+++ b/plat/hisilicon/poplar/bl2_plat_setup.c
@@ -29,8 +29,10 @@
typedef struct bl2_to_bl31_params_mem {
bl31_params_t bl31_params;
image_info_t bl31_image_info;
+ image_info_t bl32_image_info;
image_info_t bl33_image_info;
entry_point_info_t bl33_ep_info;
+ entry_point_info_t bl32_ep_info;
entry_point_info_t bl31_ep_info;
} bl2_to_bl31_params_mem_t;
@@ -61,6 +63,16 @@ bl31_params_t *bl2_plat_get_bl31_params(void)
SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info,
PARAM_IMAGE_BINARY, VERSION_1, 0);
+ /* Fill BL3-2 related information if it exists */
+#ifdef BL32_BASE
+ bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
+ SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
+ VERSION_1, 0);
+ bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
+ SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY,
+ VERSION_1, 0);
+#endif
+
/* Fill BL3-3 related information */
bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
@@ -89,6 +101,41 @@ void bl2_plat_set_bl31_ep_info(image_info_t *image,
DISABLE_ALL_EXCEPTIONS);
}
+/*******************************************************************************
+ * Before calling this function BL32 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL32 and set SPSR and security state.
+ * On Poplar we only set the security state of the entrypoint
+ ******************************************************************************/
+#ifdef BL32_BASE
+void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
+ entry_point_info_t *bl32_ep_info)
+{
+ SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ bl32_ep_info->spsr = 0;
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL32
+ ******************************************************************************/
+void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
+{
+ /*
+ * Populate the extents of memory available for loading BL32.
+ */
+ bl32_meminfo->total_base = BL32_BASE;
+ bl32_meminfo->free_base = BL32_BASE;
+ bl32_meminfo->total_size =
+ (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+ bl32_meminfo->free_size =
+ (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+}
+#endif /* BL32_BASE */
+
static uint32_t hisi_get_spsr_for_bl33_entry(void)
{
unsigned long el_status;
@@ -159,5 +206,5 @@ void bl2_platform_setup(void)
unsigned long plat_get_ns_image_entrypoint(void)
{
- return PLAT_ARM_NS_IMAGE_OFFSET;
+ return PLAT_POPLAR_NS_IMAGE_OFFSET;
}
diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c
index b9a0e18e..e3a5c50f 100644
--- a/plat/hisilicon/poplar/bl31_plat_setup.c
+++ b/plat/hisilicon/poplar/bl31_plat_setup.c
@@ -32,11 +32,31 @@
#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+#define TZPC_SEC_ATTR_CTRL_VALUE (0x9DB98D45)
+
+static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;
+static void hisi_tzpc_sec_init(void)
+{
+ mmio_write_32(HISI_TZPC_SEC_ATTR_CTRL, TZPC_SEC_ATTR_CTRL_VALUE);
+}
+
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
{
- return &bl33_image_ep_info;
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+ /*
+ * None of the images on the ARM development platforms can have 0x0
+ * as the entrypoint
+ */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
}
void bl31_early_platform_setup(bl31_params_t *from_bl2,
@@ -47,6 +67,13 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2,
/* Init console for crash report */
plat_crash_console_init();
+
+ /*
+ * Copy BL32 (if populated by BL2) and BL33 entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ if (from_bl2->bl32_ep_info)
+ bl32_image_ep_info = *from_bl2->bl32_ep_info;
bl33_image_ep_info = *from_bl2->bl33_ep_info;
}
@@ -58,6 +85,9 @@ void bl31_platform_setup(void)
/* Init GIC distributor and CPU interface */
plat_arm_gic_driver_init();
plat_arm_gic_init();
+
+ /* Init security properties of IP blocks */
+ hisi_tzpc_sec_init();
}
void bl31_plat_runtime_setup(void)
diff --git a/plat/hisilicon/poplar/include/hi3798cv200.h b/plat/hisilicon/poplar/include/hi3798cv200.h
index 6318b9c6..540d0aa1 100644
--- a/plat/hisilicon/poplar/include/hi3798cv200.h
+++ b/plat/hisilicon/poplar/include/hi3798cv200.h
@@ -30,7 +30,7 @@
#define TIMER20_BGLOAD (SEC_TIMER2_BASE + 0x018)
/* GPIO */
-#define GPIO_MAX (12)
+#define GPIO_MAX (13)
#define GPIO_BASE(x) (x != 5 ? \
0xf820000 + x * 0x1000 : 0xf8004000)
@@ -97,4 +97,7 @@
/* Watchdog */
#define HISI_WDG0_BASE (0xF8A2C000)
+#define HISI_TZPC_BASE (0xF8A80000)
+#define HISI_TZPC_SEC_ATTR_CTRL (HISI_TZPC_BASE + 0x10)
+
#endif /* __HI3798cv200_H__ */
diff --git a/plat/hisilicon/poplar/include/platform_def.h b/plat/hisilicon/poplar/include/platform_def.h
index b7afe820..3d1ad9b9 100644
--- a/plat/hisilicon/poplar/include/platform_def.h
+++ b/plat/hisilicon/poplar/include/platform_def.h
@@ -48,11 +48,55 @@
#define TEE_SEC_MEM_BASE (0x70000000)
#define TEE_SEC_MEM_SIZE (0x10000000)
+/* Memory location options for TSP */
+#define POPLAR_SRAM_ID 0
+#define POPLAR_DRAM_ID 1
+
+/*
+ * DDR for OP-TEE (28MB from 0x02200000 -0x04000000) is divided in several
+ * regions:
+ * - Secure DDR (default is the top 16MB) used by OP-TEE
+ * - Non-secure DDR (4MB) reserved for OP-TEE's future use
+ * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature
+ * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB)
+ * - Non-secure DDR (2MB) reserved for OP-TEE's future use
+ */
+#define DDR_SEC_SIZE 0x01000000
+#define DDR_SEC_BASE 0x03000000
+
#define BL_MEM_BASE (BL1_RO_BASE)
#define BL_MEM_LIMIT (BL31_LIMIT)
#define BL_MEM_SIZE (BL_MEM_LIMIT - BL_MEM_BASE)
-#define PLAT_ARM_NS_IMAGE_OFFSET 0x37000000
+/*
+ * BL3-2 specific defines.
+ */
+
+/*
+ * The TSP currently executes from TZC secured area of DRAM.
+ */
+#define BL32_DRAM_BASE 0x03000000
+#define BL32_DRAM_LIMIT 0x04000000
+
+#if (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_DRAM_ID)
+#define TSP_SEC_MEM_BASE BL32_DRAM_BASE
+#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE)
+#define BL32_BASE BL32_DRAM_BASE
+#define BL32_LIMIT BL32_DRAM_LIMIT
+#elif (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_SRAM_ID)
+#error "SRAM storage of TSP payload is currently unsupported"
+#else
+#error "Currently unsupported POPLAR_TSP_LOCATION_ID value"
+#endif
+
+/* BL32 is mandatory in AArch32 */
+#ifndef AARCH32
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+#endif
+
+#define PLAT_POPLAR_NS_IMAGE_OFFSET 0x37000000
/* Page table and MMU setup constants */
#define ADDR_SPACE_SIZE (1ull << 32)
diff --git a/plat/hisilicon/poplar/include/poplar_layout.h b/plat/hisilicon/poplar/include/poplar_layout.h
index 192bcb9c..e0b5618e 100644
--- a/plat/hisilicon/poplar/include/poplar_layout.h
+++ b/plat/hisilicon/poplar/include/poplar_layout.h
@@ -74,16 +74,16 @@
* "OFFSET" is an offset to the start of a region relative to the
* base of the "l-loader" TEXT section (also a multiple of page size).
*/
-#define LLOADER_TEXT_BASE 0x00001000 /* page aligned */
+#define LLOADER_TEXT_BASE 0x02001000 /* page aligned */
#define BL1_OFFSET 0x0000D000 /* page multiple */
-#define FIP_BASE 0x00040000
+#define FIP_BASE 0x02040000
#define BL1_RO_SIZE 0x00008000 /* page multiple */
#define BL1_RW_SIZE 0x00008000 /* page multiple */
#define BL1_SIZE (BL1_RO_SIZE + BL1_RW_SIZE)
#define BL2_SIZE 0x0000c000 /* page multiple */
#define BL31_SIZE 0x00014000
-#define FIP_SIZE 0x00068000
+#define FIP_SIZE 0x000c0000 /* absolute max */
/* BL1_OFFSET */ /* (Defined above) */
#define BL1_BASE (LLOADER_TEXT_BASE + BL1_OFFSET)
diff --git a/plat/hisilicon/poplar/plat_storage.c b/plat/hisilicon/poplar/plat_storage.c
index 623a61b7..ab94cba3 100644
--- a/plat/hisilicon/poplar/plat_storage.c
+++ b/plat/hisilicon/poplar/plat_storage.c
@@ -43,6 +43,10 @@ static const io_uuid_spec_t bl31_uuid_spec = {
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
};
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
static const io_uuid_spec_t bl33_uuid_spec = {
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
};
@@ -69,6 +73,11 @@ static const struct plat_io_policy policies[] = {
(uintptr_t)&bl31_uuid_spec,
open_fip
},
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
[BL33_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk
index fc75ff35..818e3115 100644
--- a/plat/hisilicon/poplar/platform.mk
+++ b/plat/hisilicon/poplar/platform.mk
@@ -4,6 +4,17 @@
# SPDX-License-Identifier: BSD-3-Clause
#
+# On Poplar, the TSP can execute from TZC secure area in DRAM.
+POPLAR_TSP_RAM_LOCATION := dram
+ifeq (${POPLAR_TSP_RAM_LOCATION}, dram)
+ POPLAR_TSP_RAM_LOCATION_ID = POPLAR_DRAM_ID
+else ifeq (${HIKEY960_TSP_RAM_LOCATION}, sram)
+ POPLAR_TSP_RAM_LOCATION_ID := POPLAR_SRAM_ID
+else
+ $(error "Currently unsupported POPLAR_TSP_RAM_LOCATION value")
+endif
+$(eval $(call add_define,POPLAR_TSP_RAM_LOCATION_ID))
+
NEED_BL33 := yes
COLD_BOOT_SINGLE_CPU := 1
@@ -13,6 +24,7 @@ ENABLE_PLAT_COMPAT := 0
ERRATA_A53_855873 := 1
ERRATA_A53_835769 := 1
ERRATA_A53_843419 := 1
+ENABLE_SVE_FOR_NS := 0
ARM_GIC_ARCH := 2
$(eval $(call add_define,ARM_GIC_ARCH))
@@ -69,4 +81,3 @@ BL31_SOURCES += \
plat/hisilicon/poplar/bl31_plat_setup.c \
plat/hisilicon/poplar/plat_topology.c \
plat/hisilicon/poplar/plat_pm.c
-
diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S
index 0f60a0c6..eacb1b27 100644
--- a/plat/mediatek/mt6795/bl31.ld.S
+++ b/plat/mediatek/mt6795/bl31.ld.S
@@ -5,6 +5,7 @@
*/
#include <platform_def.h>
+#include <xlat_tables_defs.h>
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
@@ -29,7 +30,7 @@ SECTIONS
*(.vectors)
} >RAM
- ASSERT(. == ALIGN(4096),
+ ASSERT(. == ALIGN(PAGE_SIZE),
"BL31_BASE address is not aligned on a page boundary.")
ro . : {
@@ -58,7 +59,7 @@ SECTIONS
* executable. No RW data from the next section must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__RO_END__ = .;
} >RAM
@@ -144,7 +145,7 @@ SECTIONS
* 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 (NOLOAD) : ALIGN(PAGE_SIZE) {
__COHERENT_RAM_START__ = .;
/*
* Bakery locks are stored in coherent memory
@@ -159,7 +160,7 @@ SECTIONS
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(4096);
+ . = NEXT(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM2
#endif
diff --git a/plat/mediatek/mt6795/platform.mk b/plat/mediatek/mt6795/platform.mk
index 4ebc78e5..82300674 100644
--- a/plat/mediatek/mt6795/platform.mk
+++ b/plat/mediatek/mt6795/platform.mk
@@ -66,3 +66,5 @@ PROGRAMMABLE_RESET_ADDRESS := 1
$(eval $(call add_define,MTK_SIP_KERNEL_BOOT_ENABLE))
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
index cd016451..2eef81bb 100644
--- a/plat/mediatek/mt8173/platform.mk
+++ b/plat/mediatek/mt8173/platform.mk
@@ -70,3 +70,6 @@ ERRATA_A53_855873 := 1
PROGRAMMABLE_RESET_ADDRESS := 1
$(eval $(call add_define,MTK_SIP_SET_AUTHORIZED_SECURE_REG_ENABLE))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index 9a9e79e2..ad60620a 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -29,6 +29,9 @@ SEPARATE_CODE_AND_RODATA := 1
# do not use coherent memory
USE_COHERENT_MEM := 0
+# do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
include plat/nvidia/tegra/common/tegra_common.mk
include ${SOC_DIR}/platform_${TARGET_SOC}.mk
diff --git a/plat/qemu/platform.mk b/plat/qemu/platform.mk
index 2a7415f5..43ab846b 100644
--- a/plat/qemu/platform.mk
+++ b/plat/qemu/platform.mk
@@ -153,3 +153,6 @@ endif
# Process flags
$(eval $(call add_define,BL32_RAM_LOCATION_ID))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk
index 8863fb4f..5de4680e 100644
--- a/plat/rockchip/rk3328/platform.mk
+++ b/plat/rockchip/rk3328/platform.mk
@@ -48,7 +48,10 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \
${RK_PLAT_SOC}/drivers/pmu/pmu.c \
${RK_PLAT_SOC}/drivers/soc/soc.c
-ENABLE_PLAT_COMPAT := 0
+ENABLE_PLAT_COMPAT := 0
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
$(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk
index f6960cf4..d3c6eeff 100644
--- a/plat/rockchip/rk3368/platform.mk
+++ b/plat/rockchip/rk3368/platform.mk
@@ -48,6 +48,9 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \
${RK_PLAT_SOC}/drivers/soc/soc.c \
${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c \
-ENABLE_PLAT_COMPAT := 0
+ENABLE_PLAT_COMPAT := 0
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
diff --git a/plat/rockchip/rk3399/include/plat.ld.S b/plat/rockchip/rk3399/include/plat.ld.S
index c42d9a9a..85f4dc33 100644
--- a/plat/rockchip/rk3399/include/plat.ld.S
+++ b/plat/rockchip/rk3399/include/plat.ld.S
@@ -6,6 +6,8 @@
#ifndef __ROCKCHIP_PLAT_LD_S__
#define __ROCKCHIP_PLAT_LD_S__
+#include <xlat_tables_defs.h>
+
MEMORY {
SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE
PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
@@ -14,7 +16,7 @@ MEMORY {
SECTIONS
{
. = SRAM_BASE;
- ASSERT(. == ALIGN(4096),
+ ASSERT(. == ALIGN(PAGE_SIZE),
"SRAM_BASE address is not aligned on a page boundary.")
/*
@@ -27,40 +29,40 @@ SECTIONS
* | sram data
* ----------------
*/
- .incbin_sram : ALIGN(4096) {
+ .incbin_sram : ALIGN(PAGE_SIZE) {
__sram_incbin_start = .;
*(.sram.incbin)
__sram_incbin_real_end = .;
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__sram_incbin_end = .;
} >SRAM
ASSERT((__sram_incbin_real_end - __sram_incbin_start) <=
SRAM_BIN_LIMIT, ".incbin_sram has exceeded its limit")
- .text_sram : ALIGN(4096) {
+ .text_sram : ALIGN(PAGE_SIZE) {
__bl31_sram_text_start = .;
*(.sram.text)
*(.sram.rodata)
__bl31_sram_text_real_end = .;
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__bl31_sram_text_end = .;
} >SRAM
ASSERT((__bl31_sram_text_real_end - __bl31_sram_text_start) <=
SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit")
- .data_sram : ALIGN(4096) {
+ .data_sram : ALIGN(PAGE_SIZE) {
__bl31_sram_data_start = .;
*(.sram.data)
__bl31_sram_data_real_end = .;
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
__bl31_sram_data_end = .;
} >SRAM
ASSERT((__bl31_sram_data_real_end - __bl31_sram_data_start) <=
SRAM_DATA_LIMIT, ".data_sram has exceeded its limit")
- .stack_sram : ALIGN(4096) {
+ .stack_sram : ALIGN(PAGE_SIZE) {
__bl31_sram_stack_start = .;
- . += 4096;
+ . += PAGE_SIZE;
__bl31_sram_stack_end = .;
} >SRAM
diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c
index 074dc193..2fbda673 100644
--- a/plat/rockchip/rk3399/plat_sip_calls.c
+++ b/plat/rockchip/rk3399/plat_sip_calls.c
@@ -11,6 +11,7 @@
#include <plat_sip_calls.h>
#include <rockchip_sip_svc.h>
#include <runtime_svc.h>
+#include <stdint.h>
#define RK_SIP_DDR_CFG 0x82000008
#define DRAM_INIT 0x00
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index 6cd5b242..33b9723d 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -92,3 +92,6 @@ $(eval $(call MAKE_PREREQ_DIR,${BUILD_M0},${BUILD_PLAT}))
.PHONY: $(RK3399M0FW)
$(RK3399M0FW): | ${BUILD_M0}
$(MAKE) -C ${RK_PLAT_SOC}/drivers/m0 BUILD=$(abspath ${BUILD_PLAT}/m0)
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
diff --git a/plat/rpi3/aarch64/plat_helpers.S b/plat/rpi3/aarch64/plat_helpers.S
new file mode 100644
index 00000000..76a542f5
--- /dev/null
+++ b/plat/rpi3/aarch64/plat_helpers.S
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <platform_def.h>
+
+#include "../rpi3_hw.h"
+
+ .globl plat_crash_console_flush
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl platform_mem_init
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_reset_handler
+ .globl plat_rpi3_calc_core_pos
+ .globl plat_secondary_cold_boot_setup
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ *
+ * This function uses the plat_rpi3_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_rpi3_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
+ *
+ * CorePos = (ClusterId * 4) + CoreId
+ * -----------------------------------------------------
+ */
+func plat_rpi3_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_rpi3_calc_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #RPI3_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* Calculate address of our hold entry */
+ bl plat_my_core_pos
+ lsl x0, x0, #3
+ mov_imm x2, PLAT_RPI3_TM_HOLD_BASE
+ add x0, x0, x2
+
+ /*
+ * This code runs way before requesting the warmboot of this core,
+ * so it is possible to clear the mailbox before getting a request
+ * to boot.
+ */
+ mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
+ str x1,[x0]
+
+ /* Wait until we have a go */
+poll_mailbox:
+ wfe
+ ldr x1, [x0]
+ cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO
+ bne poll_mailbox
+
+ /* Jump to the provided entrypoint */
+ mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT
+ ldr x1, [x0]
+ br x1
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and a warm
+ * boot.
+ *
+ * This functions returns:
+ * - 0 for a cold boot.
+ * - Any other value for a warm boot.
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* TODO: support warm boot */
+ mov x0, #0
+ ret
+endfunc plat_get_my_entrypoint
+
+ /* ---------------------------------------------
+ * void platform_mem_init (void);
+ *
+ * No need to carry out any memory initialization.
+ * ---------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x3
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, PLAT_RPI3_UART_BASE
+ mov_imm x1, PLAT_RPI3_UART_CLK_IN_HZ
+ mov_imm x2, PLAT_RPI3_UART_BAUDRATE
+ b console_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_RPI3_UART_BASE
+ b console_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * int plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x1, PLAT_RPI3_UART_BASE
+ b console_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------
+ * void plat_reset_handler(void);
+ * ---------------------------------------------
+ */
+func plat_reset_handler
+ /* use the 19.2 MHz clock for the architected timer */
+ mov x0, #RPI3_INTC_BASE_ADDRESS
+ mov w1, #0x80000000
+ str wzr, [x0, #RPI3_INTC_CONTROL_OFFSET]
+ str w1, [x0, #RPI3_INTC_PRESCALER_OFFSET]
+
+ /* wire mailbox 3 to the FIQ line */
+ mov w1, RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ
+ str w1, [x0, #RPI3_INTC_MBOX_CONTROL_OFFSET]
+ ret
+endfunc plat_reset_handler
diff --git a/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
new file mode 100644
index 00000000..e3acfe9f
--- /dev/null
+++ b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg1 = RPI3_BL31_PLAT_PARAM_VAL,
+#endif
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+
+# ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE where it is the pager
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE where it is the paged
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+# else
+ .ep_info.pc = PLAT_RPI3_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_RPI3_NS_IMAGE_OFFSET,
+ .image_info.image_max_size = PLAT_RPI3_NS_IMAGE_MAX_SIZE,
+# endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/rpi3/include/plat_macros.S b/plat/rpi3/include/plat_macros.S
new file mode 100644
index 00000000..f5e057ed
--- /dev/null
+++ b/plat/rpi3/include/plat_macros.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+#include <arm_macros.S>
+#include <platform_def.h>
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h
new file mode 100644
index 00000000..5e2f1da5
--- /dev/null
+++ b/plat/rpi3/include/platform_def.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <common_def.h>
+#include <tbbr_img_def.h>
+#include <utils_def.h>
+
+#include "../rpi3_hw.h"
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978)
+
+#define PLATFORM_STACK_SIZE ULL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
+
+#define RPI3_PRIMARY_CPU U(0)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET U(1)
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Partition memory into secure ROM, non-secure DRAM, secure "SRAM", and
+ * secure DRAM. Note that this is all actually DRAM with different names,
+ * there is no Secure RAM in the Raspberry Pi 3.
+ */
+#define SEC_ROM_BASE ULL(0x00000000)
+#define SEC_ROM_SIZE ULL(0x00010000)
+
+/* FIP placed after ROM to append it to BL1 with very little padding. */
+#define PLAT_RPI3_FIP_BASE ULL(0x00010000)
+#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x001F0000)
+
+/* We have 16M of memory reserved at at 256M */
+#define SEC_SRAM_BASE ULL(0x10000000)
+#define SEC_SRAM_SIZE ULL(0x00100000)
+
+#define SEC_DRAM0_BASE ULL(0x10100000)
+#define SEC_DRAM0_SIZE ULL(0x00200000)
+
+#define NS_DRAM0_BASE ULL(0x10300000)
+#define NS_DRAM0_SIZE ULL(0x00D00000)
+/* End of reserved memory */
+
+/*
+ * BL33 entrypoint.
+ */
+#define PLAT_RPI3_NS_IMAGE_OFFSET NS_DRAM0_BASE
+#define PLAT_RPI3_NS_IMAGE_MAX_SIZE NS_DRAM0_SIZE
+
+/*
+ * I/O registers.
+ */
+#define DEVICE0_BASE RPI3_IO_BASE
+#define DEVICE0_SIZE RPI3_IO_SIZE
+
+/*
+ * Arm TF lives in SRAM, partition it here
+ */
+#define SHARED_RAM_BASE SEC_SRAM_BASE
+#define SHARED_RAM_SIZE ULL(0x00001000)
+
+#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE)
+#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE)
+
+/*
+ * Mailbox to control the secondary cores.All secondary cores are held in a wait
+ * loop in cold boot. To release them perform the following steps (plus any
+ * additional barriers that may be needed):
+ *
+ * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT;
+ * *entrypoint = ADDRESS_TO_JUMP_TO;
+ *
+ * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
+ * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO;
+ *
+ * sev();
+ */
+#define PLAT_RPI3_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE
+
+#define PLAT_RPI3_TM_ENTRYPOINT PLAT_RPI3_TRUSTED_MAILBOX_BASE
+#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8)
+
+#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \
+ PLAT_RPI3_TM_ENTRYPOINT_SIZE)
+#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8)
+#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \
+ PLAT_RPI3_TM_HOLD_SIZE)
+
+#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0)
+#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1)
+
+/*
+ * BL1 specific defines.
+ *
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
+ * addresses.
+ *
+ * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using
+ * the current BL1 RW debug size plus a little space for growth.
+ */
+#define PLAT_MAX_BL1_RW_SIZE ULL(0x12000)
+
+#define BL1_RO_BASE SEC_ROM_BASE
+#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE)
+#define BL1_RW_BASE (BL1_RW_LIMIT - PLAT_MAX_BL1_RW_SIZE)
+#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
+
+/*
+ * BL2 specific defines.
+ *
+ * Put BL2 just below BL31. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define PLAT_MAX_BL2_SIZE ULL(0x2C000)
+
+#define BL2_BASE (BL2_LIMIT - PLAT_MAX_BL2_SIZE)
+#define BL2_LIMIT BL31_BASE
+
+/*
+ * BL31 specific defines.
+ *
+ * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define PLAT_MAX_BL31_SIZE ULL(0x20000)
+
+#define BL31_BASE (BL31_LIMIT - PLAT_MAX_BL31_SIZE)
+#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
+#define BL31_PROGBITS_LIMIT BL1_RW_BASE
+
+/*
+ * BL32 specific defines.
+ *
+ * BL32 can execute from Secure SRAM or Secure DRAM.
+ */
+#define BL32_SRAM_BASE BL_RAM_BASE
+#define BL32_SRAM_LIMIT BL31_BASE
+#define BL32_DRAM_BASE SEC_DRAM0_BASE
+#define BL32_DRAM_LIMIT (SEC_DRAM0_BASE + SEC_DRAM0_SIZE)
+
+#define SEC_SRAM_ID 0
+#define SEC_DRAM_ID 1
+
+#if RPI3_BL32_RAM_LOCATION_ID == SEC_SRAM_ID
+# define BL32_MEM_BASE BL_RAM_BASE
+# define BL32_MEM_SIZE BL_RAM_SIZE
+# define BL32_BASE BL32_SRAM_BASE
+# define BL32_LIMIT BL32_SRAM_LIMIT
+#elif RPI3_BL32_RAM_LOCATION_ID == SEC_DRAM_ID
+# define BL32_MEM_BASE SEC_DRAM0_BASE
+# define BL32_MEM_SIZE SEC_DRAM0_SIZE
+# define BL32_BASE BL32_DRAM_BASE
+# define BL32_LIMIT BL32_DRAM_LIMIT
+#else
+# error "Unsupported RPI3_BL32_RAM_LOCATION_ID value"
+#endif
+#define BL32_SIZE (BL32_LIMIT - BL32_BASE)
+
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+
+/*
+ * Other memory-related defines.
+ */
+#define ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS U(8)
+#define MAX_XLAT_TABLES U(4)
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+/*
+ * Serial-related constants.
+ */
+#define PLAT_RPI3_UART_BASE RPI3_MINI_UART_BASE
+#define PLAT_RPI3_UART_CLK_IN_HZ RPI3_MINI_UART_CLK_IN_HZ
+#define PLAT_RPI3_UART_BAUDRATE ULL(115200)
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS ULL(19200000)
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk
new file mode 100644
index 00000000..821f8015
--- /dev/null
+++ b/plat/rpi3/platform.mk
@@ -0,0 +1,113 @@
+#
+# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := -Iinclude/common/tbbr \
+ -Iinclude/plat/arm/common/ \
+ -Iinclude/plat/arm/common/aarch64/ \
+ -Iplat/rpi3/include
+
+PLAT_BL_COMMON_SOURCES := drivers/console/aarch64/console.S \
+ drivers/ti/uart/aarch64/16550_console.S \
+ plat/rpi3/rpi3_common.c
+
+BL1_SOURCES += drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/aarch64/platform_mp_stack.S \
+ plat/rpi3/aarch64/plat_helpers.S \
+ plat/rpi3/rpi3_bl1_setup.c \
+ plat/rpi3/rpi3_io_storage.c
+
+BL2_SOURCES += common/desc_image_load.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ plat/common/aarch64/platform_mp_stack.S \
+ plat/rpi3/aarch64/plat_helpers.S \
+ plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c \
+ plat/rpi3/rpi3_bl2_setup.c \
+ plat/rpi3/rpi3_image_load.c \
+ plat/rpi3/rpi3_io_storage.c
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ plat/common/aarch64/plat_psci_common.c \
+ plat/rpi3/aarch64/plat_helpers.S \
+ plat/rpi3/rpi3_bl31_setup.c \
+ plat/rpi3/rpi3_pm.c \
+ plat/rpi3/rpi3_topology.c
+
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else
+ TF_CFLAGS_aarch64 += -mtune=cortex-a53
+endif
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_826319 := 1
+ERRATA_A53_835769 := 1
+ERRATA_A53_836870 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+# Disable the PSCI platform compatibility layer by default
+ENABLE_PLAT_COMPAT := 0
+
+# Enable reset to BL31 by default
+RESET_TO_BL31 := 1
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+# Enable new version of image loading
+LOAD_IMAGE_V2 := 1
+
+# Platform build flags
+# --------------------
+
+# BL33 images are in AArch64 by default
+RPI3_BL33_IN_AARCH32 := 0
+
+# BL32 location
+RPI3_BL32_RAM_LOCATION := tdram
+ifeq (${RPI3_BL32_RAM_LOCATION}, tsram)
+ RPI3_BL32_RAM_LOCATION_ID = SEC_SRAM_ID
+else ifeq (${RPI3_BL32_RAM_LOCATION}, tdram)
+ RPI3_BL32_RAM_LOCATION_ID = SEC_DRAM_ID
+else
+ $(error "Unsupported RPI3_BL32_RAM_LOCATION value")
+endif
+
+# Process platform flags
+# ----------------------
+
+$(eval $(call add_define,RPI3_BL32_RAM_LOCATION_ID))
+$(eval $(call add_define,RPI3_BL33_IN_AARCH32))
+
+# Verify build config
+# -------------------
+
+ifneq (${LOAD_IMAGE_V2}, 1)
+ $(error Error: rpi3 needs LOAD_IMAGE_V2=1)
+endif
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on rpi3)
+endif
diff --git a/plat/rpi3/rpi3_bl1_setup.c b/plat/rpi3/rpi3_bl1_setup.c
new file mode 100644
index 00000000..11c0f4af
--- /dev/null
+++ b/plat/rpi3/rpi3_bl1_setup.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <bl_common.h>
+#include <console.h>
+#include <platform_def.h>
+#include <xlat_mmu_helpers.h>
+#include <xlat_tables_defs.h>
+
+#include "../../bl1/bl1_private.h"
+#include "rpi3_private.h"
+
+/* Data structure which holds the extents of the trusted SRAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+ /* Initialize the console to provide early debug support */
+ console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
+ PLAT_RPI3_UART_BAUDRATE);
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = BL_RAM_BASE;
+ bl1_tzram_layout.total_size = BL_RAM_SIZE;
+}
+
+/******************************************************************************
+ * Perform the very early platform specific architecture setup. This only
+ * does basic initialization. Later architectural setup (bl1_arch_setup())
+ * does not do anything platform specific.
+ *****************************************************************************/
+void bl1_plat_arch_setup(void)
+{
+ rpi3_setup_page_tables(bl1_tzram_layout.total_base,
+ bl1_tzram_layout.total_size,
+ BL_CODE_BASE, BL1_CODE_END,
+ BL1_RO_DATA_BASE, BL1_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+ );
+
+ enable_mmu_el3(0);
+}
+
+void bl1_platform_setup(void)
+{
+ /* Initialise the IO layer and register platform IO devices */
+ plat_rpi3_io_setup();
+}
diff --git a/plat/rpi3/rpi3_bl2_setup.c b/plat/rpi3/rpi3_bl2_setup.c
new file mode 100644
index 00000000..1fd822e9
--- /dev/null
+++ b/plat/rpi3/rpi3_bl2_setup.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <desc_image_load.h>
+#include <platform_def.h>
+#include <xlat_mmu_helpers.h>
+#include <xlat_tables_defs.h>
+
+#include "rpi3_private.h"
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/*******************************************************************************
+ * BL1 has passed the extents of the trusted SRAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted SRAM.
+ * Copy it to a safe location before its reclaimed by later BL2 functionality.
+ ******************************************************************************/
+void bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+ /* Initialize the console to provide early debug support */
+ console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
+ PLAT_RPI3_UART_BAUDRATE);
+
+ /* Setup the BL2 memory layout */
+ bl2_tzram_layout = *mem_layout;
+
+ plat_rpi3_io_setup();
+}
+
+void bl2_platform_setup(void)
+{
+ /*
+ * This is where a TrustZone address space controller and other
+ * security related peripherals, would be configured.
+ */
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here.
+ ******************************************************************************/
+void bl2_plat_arch_setup(void)
+{
+ rpi3_setup_page_tables(bl2_tzram_layout.total_base,
+ bl2_tzram_layout.total_size,
+ BL_CODE_BASE, BL_CODE_END,
+ BL_RO_DATA_BASE, BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+ );
+
+ enable_mmu_el1(0);
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+ assert(bl_mem_params != NULL);
+
+ switch (image_id) {
+ case BL32_IMAGE_ID:
+ bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl32_entry();
+ break;
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
+ break;
+
+ }
+
+ return err;
+}
diff --git a/plat/rpi3/rpi3_bl31_setup.c b/plat/rpi3/rpi3_bl31_setup.c
new file mode 100644
index 00000000..39133564
--- /dev/null
+++ b/plat/rpi3/rpi3_bl31_setup.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <xlat_mmu_helpers.h>
+#include <xlat_tables_defs.h>
+
+#include "rpi3_private.h"
+
+#define BL31_END (uintptr_t)(&__BL31_END__)
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type) != 0);
+
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images can have 0x0 as the entrypoint. */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+void bl31_early_platform_setup(void *from_bl2,
+ void *plat_params_from_bl2)
+{
+ /* Initialize the console to provide early debug support */
+ console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
+ PLAT_RPI3_UART_BAUDRATE);
+
+#if RESET_TO_BL31
+
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(from_bl2 == NULL);
+ assert(plat_params_from_bl2 == NULL);
+
+#ifdef BL32_BASE
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = rpi3_get_spsr_for_bl32_entry();
+#endif /* BL32_BASE */
+
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+
+ bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#else /* RESET_TO_BL31 */
+
+ /*
+ * In debug builds, we pass a special value in 'plat_params_from_bl2'
+ * to verify platform parameters from BL2 to BL31.
+ * In release builds, it's not used.
+ */
+ assert(((uintptr_t)plat_params_from_bl2) == RPI3_BL31_PLAT_PARAM_VAL);
+
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID) {
+ bl32_image_ep_info = *bl_params->ep_info;
+ }
+
+ if (bl_params->image_id == BL33_IMAGE_ID) {
+ bl33_image_ep_info = *bl_params->ep_info;
+ }
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_image_ep_info.pc == 0) {
+ panic();
+ }
+
+#endif /* RESET_TO_BL31 */
+}
+
+void bl31_plat_arch_setup(void)
+{
+ rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE,
+ BL_CODE_BASE, BL_CODE_END,
+ BL_RO_DATA_BASE, BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+ );
+
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+#if RESET_TO_BL31
+ /*
+ * Do initial security configuration to allow DRAM/device access
+ * (if earlier BL has not already done so).
+ */
+#endif /* RESET_TO_BL31 */
+
+ return;
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ /* Initialize the runtime console */
+ console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
+ PLAT_RPI3_UART_BAUDRATE);
+}
diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c
new file mode 100644
index 00000000..97dce091
--- /dev/null
+++ b/plat/rpi3/rpi3_common.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <interrupt_mgmt.h>
+#include <platform_def.h>
+#include <xlat_tables_v2.h>
+
+#include "rpi3_hw.h"
+#include "rpi3_private.h"
+
+#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \
+ SHARED_RAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_FIP MAP_REGION_FLAT(PLAT_RPI3_FIP_BASE, \
+ PLAT_RPI3_FIP_MAX_SIZE, \
+ MT_MEMORY | MT_RO | MT_NS)
+
+#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for various BL stages to map using the MMU.
+ */
+#ifdef IMAGE_BL1
+static const mmap_region_t plat_rpi3_mmap[] = {
+ MAP_SHARED_RAM,
+ MAP_DEVICE0,
+ MAP_FIP,
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL2
+static const mmap_region_t plat_rpi3_mmap[] = {
+ MAP_SHARED_RAM,
+ MAP_DEVICE0,
+ MAP_FIP,
+ MAP_NS_DRAM0,
+#ifdef BL32_BASE
+ MAP_BL32_MEM,
+#endif
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL31
+static const mmap_region_t plat_rpi3_mmap[] = {
+ MAP_SHARED_RAM,
+ MAP_DEVICE0,
+#ifdef BL32_BASE
+ MAP_BL32_MEM,
+#endif
+ {0}
+};
+#endif
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
+ uintptr_t code_start, uintptr_t code_limit,
+ uintptr_t rodata_start, uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+ , uintptr_t coh_start, uintptr_t coh_limit
+#endif
+ )
+{
+ /*
+ * Map the Trusted SRAM with appropriate memory attributes.
+ * Subsequent mappings will adjust the attributes for specific regions.
+ */
+ VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n",
+ (void *) total_base, (void *) (total_base + total_size));
+ mmap_add_region(total_base, total_base,
+ total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+
+ /* Re-map the code section */
+ VERBOSE("Code region: %p - %p\n",
+ (void *) code_start, (void *) code_limit);
+ mmap_add_region(code_start, code_start,
+ code_limit - code_start,
+ MT_CODE | MT_SECURE);
+
+ /* Re-map the read-only data section */
+ VERBOSE("Read-only data region: %p - %p\n",
+ (void *) rodata_start, (void *) rodata_limit);
+ mmap_add_region(rodata_start, rodata_start,
+ rodata_limit - rodata_start,
+ MT_RO_DATA | MT_SECURE);
+
+#if USE_COHERENT_MEM
+ /* Re-map the coherent memory region */
+ VERBOSE("Coherent region: %p - %p\n",
+ (void *) coh_start, (void *) coh_limit);
+ mmap_add_region(coh_start, coh_start,
+ coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+
+ mmap_add(plat_rpi3_mmap);
+
+ init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Return entrypoint of BL33.
+ ******************************************************************************/
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ return PLAT_RPI3_NS_IMAGE_OFFSET;
+#endif
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t rpi3_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+uint32_t rpi3_get_spsr_for_bl33_entry(void)
+{
+#if RPI3_BL33_IN_AARCH32
+ INFO("BL33 will boot in Non-secure AArch32 Hypervisor mode\n");
+ return SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS);
+#else
+ return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+#endif
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+ return INTR_TYPE_INVAL;
+}
diff --git a/plat/rpi3/rpi3_hw.h b/plat/rpi3/rpi3_hw.h
new file mode 100644
index 00000000..70272e00
--- /dev/null
+++ b/plat/rpi3/rpi3_hw.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __RPI3_HW__
+#define __RPI3_HW__
+
+#include <utils_def.h>
+
+/*
+ * Peripherals
+ */
+
+#define RPI3_IO_BASE ULL(0x3F000000)
+#define RPI3_IO_SIZE ULL(0x01000000)
+
+/*
+ * Serial port (called 'Mini UART' in the BCM docucmentation).
+ */
+#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040)
+#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET)
+#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000)
+
+/*
+ * Power management, reset controller, watchdog.
+ */
+#define RPI3_IO_PM_OFFSET ULL(0x00100000)
+#define RPI3_PM_BASE (RPI3_IO_BASE + RPI3_IO_PM_OFFSET)
+/* Registers on top of RPI3_PM_BASE. */
+#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
+#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
+/* Watchdog constants */
+#define RPI3_PM_PASSWORD ULL(0x5A000000)
+#define RPI3_PM_RSTC_WRCFG_MASK ULL(0x00000030)
+#define RPI3_PM_RSTC_WRCFG_FULL_RESET ULL(0x00000020)
+
+/*
+ * Local interrupt controller
+ */
+#define RPI3_INTC_BASE_ADDRESS ULL(0x40000000)
+/* Registers on top of RPI3_INTC_BASE_ADDRESS */
+#define RPI3_INTC_CONTROL_OFFSET ULL(0x00000000)
+#define RPI3_INTC_PRESCALER_OFFSET ULL(0x00000008)
+#define RPI3_INTC_MBOX_CONTROL_OFFSET ULL(0x00000050)
+#define RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ ULL(0x00000080)
+#define RPI3_INTC_PENDING_FIQ_OFFSET ULL(0x00000070)
+#define RPI3_INTC_PENDING_FIQ_MBOX3 ULL(0x00000080)
+
+#endif /* __RPI3_HW__ */
diff --git a/plat/rpi3/rpi3_image_load.c b/plat/rpi3/rpi3_image_load.c
new file mode 100644
index 00000000..fad9e4f3
--- /dev/null
+++ b/plat/rpi3/rpi3_image_load.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <desc_image_load.h>
+#include <platform.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/rpi3/rpi3_io_storage.c b/plat/rpi3/rpi3_io_storage.c
new file mode 100644
index 00000000..7ac45ef6
--- /dev/null
+++ b/plat/rpi3/rpi3_io_storage.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <firmware_image_package.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <platform_def.h>
+#include <string.h>
+
+/* Semihosting filenames */
+#define BL2_IMAGE_NAME "bl2.bin"
+#define BL31_IMAGE_NAME "bl31.bin"
+#define BL32_IMAGE_NAME "bl32.bin"
+#define BL33_IMAGE_NAME "bl33.bin"
+
+#if TRUSTED_BOARD_BOOT
+#define BL2_CERT_NAME "bl2.crt"
+#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
+#define BL31_KEY_CERT_NAME "bl31_key.crt"
+#define BL32_KEY_CERT_NAME "bl32_key.crt"
+#define BL33_KEY_CERT_NAME "bl33_key.crt"
+#define BL31_CERT_NAME "bl31.crt"
+#define BL32_CERT_NAME "bl32.crt"
+#define BL33_CERT_NAME "bl33.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+ .offset = PLAT_RPI3_FIP_BASE,
+ .length = PLAT_RPI3_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t bl2_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT,
+};
+
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t bl31_key_cert_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT,
+};
+
+static const io_uuid_spec_t bl32_key_cert_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_KEY_CERT,
+};
+
+static const io_uuid_spec_t bl33_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT,
+};
+
+static const io_uuid_spec_t bl31_cert_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT,
+};
+
+static const io_uuid_spec_t bl32_cert_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_CERT,
+};
+
+static const io_uuid_spec_t bl33_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+/* By default, load images from the FIP */
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &memmap_dev_handle,
+ (uintptr_t)&fip_block_spec,
+ open_memmap
+ },
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ open_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+#if TRUSTED_BOARD_BOOT
+ [BL2_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&trusted_key_cert_uuid_spec,
+ open_fip
+ },
+ [BL31_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_key_cert_uuid_spec,
+ open_fip
+ },
+ [BL32_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_key_cert_uuid_spec,
+ open_fip
+ },
+ [BL33_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_key_cert_uuid_spec,
+ open_fip
+ },
+ [BL31_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_cert_uuid_spec,
+ open_fip
+ },
+ [BL32_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_cert_uuid_spec,
+ open_fip
+ },
+ [BL33_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_cert_uuid_spec,
+ open_fip
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+static int open_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+static int open_memmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(memmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Memmap\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+void plat_rpi3_io_setup(void)
+{
+ int io_result;
+
+ io_result = register_io_dev_fip(&fip_dev_con);
+ assert(io_result == 0);
+
+ io_result = register_io_dev_memmap(&memmap_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+ assert(io_result == 0);
+
+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+ &memmap_dev_handle);
+ assert(io_result == 0);
+
+ /* Ignore improbable errors in release builds */
+ (void)io_result;
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ }
+
+ return result;
+}
diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c
new file mode 100644
index 00000000..1d067fb1
--- /dev/null
+++ b/plat/rpi3/rpi3_pm.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <console.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <platform.h>
+#include <psci.h>
+
+#include "rpi3_hw.h"
+
+/*
+ * The secure entry point to be used on warm reset.
+ */
+static uintptr_t secure_entrypoint;
+
+/* Make composite power state parameter till power level 0 */
+#if PSCI_EXTENDED_STATE_ID
+
+#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+
+#else
+
+#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+
+#endif /* PSCI_EXTENDED_STATE_ID */
+
+#define rpi3_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \
+ rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
+
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+static const unsigned int rpi3_pm_idle_states[] = {
+ /* State-id - 0x01 */
+ rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET,
+ MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x02 */
+ rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF,
+ MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x22 */
+ rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF,
+ MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
+ 0,
+};
+
+/*******************************************************************************
+ * Platform handler called to check the validity of the power state
+ * parameter. The power state parameter has to be a composite power state.
+ ******************************************************************************/
+static int rpi3_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int state_id;
+ int i;
+
+ assert(req_state != 0);
+
+ /*
+ * Currently we are using a linear search for finding the matching
+ * entry in the idle power state array. This can be made a binary
+ * search if the number of entries justify the additional complexity.
+ */
+ for (i = 0; rpi3_pm_idle_states[i] != 0; i++) {
+ if (power_state == rpi3_pm_idle_states[i]) {
+ break;
+ }
+ }
+
+ /* Return error if entry not found in the idle state array */
+ if (!rpi3_pm_idle_states[i]) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ i = 0;
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id) {
+ req_state->pwr_domain_state[i++] = state_id &
+ PLAT_LOCAL_PSTATE_MASK;
+ state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+static void rpi3_cpu_standby(plat_local_state_t cpu_state)
+{
+ assert(cpu_state == PLAT_LOCAL_STATE_RET);
+
+ /*
+ * Enter standby state.
+ * dsb is good practice before using wfi to enter low power states
+ */
+ dsb();
+ wfi();
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int rpi3_pwr_domain_on(u_register_t mpidr)
+{
+ int rc = PSCI_E_SUCCESS;
+ unsigned int pos = plat_core_pos_by_mpidr(mpidr);
+ uint64_t *hold_base = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
+
+ assert(pos < PLATFORM_CORE_COUNT);
+
+ hold_base[pos] = PLAT_RPI3_TM_HOLD_STATE_GO;
+
+ /* Make sure that the write has completed */
+ dsb();
+ isb();
+
+ sev();
+
+ return rc;
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+}
+
+/*******************************************************************************
+ * Platform handler to reboot the system
+ ******************************************************************************/
+#define RESET_TIMEOUT 10
+
+static void __dead2 rpi3_system_reset(void)
+{
+ /* Setup watchdog for reset */
+
+ static const uintptr_t base = RPI3_PM_BASE;
+ uint32_t rstc;
+
+ INFO("rpi3: PSCI System Reset: invoking watchdog reset\n");
+
+ console_flush();
+
+ rstc = mmio_read_32(base + RPI3_PM_RSTC_OFFSET);
+ rstc &= ~RPI3_PM_RSTC_WRCFG_MASK;
+ rstc |= RPI3_PM_RSTC_WRCFG_FULL_RESET;
+
+ dmbst();
+
+ /*
+ * Watchdog timer = Timer clock / 16
+ * Password (31:16) | Value (11:0)
+ */
+ mmio_write_32(base + RPI3_PM_WDOG_OFFSET,
+ RPI3_PM_PASSWORD | RESET_TIMEOUT);
+ mmio_write_32(base + RPI3_PM_RSTC_OFFSET,
+ RPI3_PM_PASSWORD | rstc);
+
+ for (;;) {
+ wfi();
+ }
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t plat_rpi3_psci_pm_ops = {
+ .cpu_standby = rpi3_cpu_standby,
+ .pwr_domain_on = rpi3_pwr_domain_on,
+ .pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
+ .system_reset = rpi3_system_reset,
+ .validate_power_state = rpi3_validate_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ uintptr_t *mailbox = (void *)PLAT_RPI3_TRUSTED_MAILBOX_BASE;
+
+ *mailbox = sec_entrypoint;
+ secure_entrypoint = (uintptr_t)sec_entrypoint;
+ *psci_ops = &plat_rpi3_psci_pm_ops;
+
+ return 0;
+}
diff --git a/plat/rpi3/rpi3_private.h b/plat/rpi3/rpi3_private.h
new file mode 100644
index 00000000..01c4055f
--- /dev/null
+++ b/plat/rpi3/rpi3_private.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __RPI3_PRIVATE_H__
+#define __RPI3_PRIVATE_H__
+
+#include <sys/types.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+/* Utility functions */
+void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
+ uintptr_t code_start, uintptr_t code_limit,
+ uintptr_t rodata_start, uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+ , uintptr_t coh_start, uintptr_t coh_limit
+#endif
+ );
+
+/* Optional functions required in the Raspberry Pi 3 port */
+unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
+
+/* BL2 utility functions */
+uint32_t rpi3_get_spsr_for_bl32_entry(void);
+uint32_t rpi3_get_spsr_for_bl33_entry(void);
+
+/* IO storage utility functions */
+void plat_rpi3_io_setup(void);
+
+#endif /*__RPI3_PRIVATE_H__ */
diff --git a/plat/rpi3/rpi3_topology.c b/plat/rpi3/rpi3_topology.c
new file mode 100644
index 00000000..0e03ec32
--- /dev/null
+++ b/plat/rpi3/rpi3_topology.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform_def.h>
+#include <sys/types.h>
+
+#include "rpi3_private.h"
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the ARM default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
+ return -1;
+ }
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ return -1;
+ }
+
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ return -1;
+ }
+
+ return plat_rpi3_calc_core_pos(mpidr);
+}
diff --git a/plat/socionext/uniphier/include/platform_def.h b/plat/socionext/uniphier/include/platform_def.h
index b5dc16aa..cc046eb4 100644
--- a/plat/socionext/uniphier/include/platform_def.h
+++ b/plat/socionext/uniphier/include/platform_def.h
@@ -47,7 +47,7 @@
#define BL32_LIMIT (UNIPHIER_SEC_DRAM_LIMIT)
#define UNIPHIER_BLOCK_BUF_SIZE 0x00400000
-#define UNIPHIER_BLOCK_BUF_BASE ((BL2_LIMIT) - \
+#define UNIPHIER_BLOCK_BUF_BASE ((BL2_BASE) - \
(UNIPHIER_BLOCK_BUF_SIZE))
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index c91abb6b..41d04448 100644
--- a/plat/socionext/uniphier/platform.mk
+++ b/plat/socionext/uniphier/platform.mk
@@ -10,6 +10,7 @@ override ERROR_DEPRECATED := 1
override LOAD_IMAGE_V2 := 1
override USE_COHERENT_MEM := 1
override USE_TBBR_DEFS := 1
+override ENABLE_SVE_FOR_NS := 0
# Cortex-A53 revision r0p4-51rel0
# needed for LD20, unneeded for LD11, PXs3 (no ACE)
@@ -115,5 +116,5 @@ endif
.PHONY: bl1_gzip
bl1_gzip: $(BUILD_PLAT)/bl1.bin.gzip
%.gzip: %
- @echo " GZIP $@"
+ @echo " GZIP $@"
$(Q)(cat $< | gzip -n -f -9 > $@) || (rm -f $@ || false)
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index ca87cc8f..cb3b4421 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -11,6 +11,9 @@ A53_DISABLE_NON_TEMPORAL_HINT := 0
SEPARATE_CODE_AND_RODATA := 1
override RESET_TO_BL31 := 1
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
ifdef ZYNQMP_ATF_MEM_BASE
$(eval $(call add_define,ZYNQMP_ATF_MEM_BASE))
diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c
index 2f08c8ba..1969307f 100644
--- a/services/std_svc/sdei/sdei_main.c
+++ b/services/std_svc/sdei/sdei_main.c
@@ -795,7 +795,7 @@ static int sdei_private_reset(void)
*/
ret = sdei_event_unregister(map->ev_num);
if ((ret == SDEI_EPEND) && (final_ret == 0))
- final_ret = ret;
+ final_ret = SDEI_EDENY;
}
return final_ret;
@@ -817,7 +817,7 @@ static int sdei_shared_reset(void)
*/
ret = sdei_event_unregister(map->ev_num);
if ((ret == SDEI_EPEND) && (final_ret == 0))
- final_ret = ret;
+ final_ret = SDEI_EDENY;
}
if (final_ret != 0)
diff --git a/services/std_svc/spm/secure_partition_setup.c b/services/std_svc/spm/secure_partition_setup.c
index 6f4b0571..c1f0edf6 100644
--- a/services/std_svc/spm/secure_partition_setup.c
+++ b/services/std_svc/spm/secure_partition_setup.c
@@ -6,7 +6,6 @@
#include <arch.h>
#include <arch_helpers.h>
-#include <arm_spm_def.h>
#include <assert.h>
#include <common_def.h>
#include <context.h>
@@ -22,12 +21,17 @@
#include "spm_private.h"
#include "spm_shim_private.h"
+/* Place translation tables by default along with the ones used by BL31. */
+#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME
+#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "xlat_table"
+#endif
+
/* Allocate and initialise the translation context for the secure partition. */
REGISTER_XLAT_CONTEXT2(secure_partition,
PLAT_SP_IMAGE_MMAP_REGIONS,
PLAT_SP_IMAGE_MAX_XLAT_TABLES,
PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
- EL1_EL0_REGIME);
+ EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME);
/* Export a handle on the secure partition translation context */
xlat_ctx_t *secure_partition_xlat_ctx_handle = &secure_partition_xlat_ctx;
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index de657a2f..979b9a8f 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.c
@@ -29,7 +29,6 @@ static spinlock_t mem_attr_smc_lock;
* Secure Partition context information.
******************************************************************************/
static secure_partition_context_t sp_ctx;
-unsigned int sp_init_in_progress;
/*******************************************************************************
* Replace the S-EL1 re-entry information with S-EL0 re-entry
@@ -48,7 +47,7 @@ void spm_setup_next_eret_into_sel0(cpu_context_t *secure_context)
* 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 sp_ctx->cpu_ctx are used to enter the secure payload image.
+ * from the sp_ctx->cpu_ctx are used to enter the secure partition image.
******************************************************************************/
static uint64_t spm_synchronous_sp_entry(secure_partition_context_t *sp_ctx_ptr)
{
@@ -75,7 +74,7 @@ static uint64_t spm_synchronous_sp_entry(secure_partition_context_t *sp_ctx_ptr)
/*******************************************************************************
* This function takes a Secure partition context pointer and:
- * 1. Saves the S-EL1 system register context tp sp_ctx->cpu_ctx.
+ * 1. Saves the S-EL1 system register context to sp_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
* spm_secure_partition_enter().
@@ -101,7 +100,7 @@ static void __dead2 spm_synchronous_sp_exit(
* This function passes control to the Secure Partition 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 spm_setup() which can be directly
- * used. This function performs a synchronous entry into the Secure payload.
+ * used. This function performs a synchronous entry into the Secure partition.
* The SP passes control back to this routine through a SMC.
******************************************************************************/
int32_t spm_init(void)
@@ -126,21 +125,28 @@ int32_t spm_init(void)
secure_partition_setup();
/*
- * Arrange for an entry into the secure payload.
+ * Make all CPUs use the same secure context.
*/
- sp_init_in_progress = 1;
+ for (unsigned int i = 0; i < PLATFORM_CORE_COUNT; i++) {
+ cm_set_context_by_index(i, &sp_ctx.cpu_ctx, SECURE);
+ }
+
+ /*
+ * Arrange for an entry into the secure partition.
+ */
+ sp_ctx.sp_init_in_progress = 1;
rc = spm_synchronous_sp_entry(&sp_ctx);
assert(rc == 0);
- sp_init_in_progress = 0;
- VERBOSE("SP_MEM_ATTRIBUTES_SET_AARCH64 availability has been revoked\n");
+ sp_ctx.sp_init_in_progress = 0;
+ VERBOSE("SP_MEMORY_ATTRIBUTES_SET_AARCH64 availability has been revoked\n");
return rc;
}
/*******************************************************************************
- * Given a secure payload entrypoint info pointer, entry point PC & pointer to
+ * Given a secure partition entrypoint info pointer, entry point PC & pointer to
* a context data structure, this function will initialize the SPM context and
- * entry point info for the secure payload
+ * entry point info for the secure partition.
******************************************************************************/
void spm_init_sp_ep_state(struct entry_point_info *sp_ep_info,
uint64_t pc,
@@ -161,7 +167,7 @@ void spm_init_sp_ep_state(struct entry_point_info *sp_ep_info,
SET_PARAM_HEAD(sp_ep_info, PARAM_EP, VERSION_1, ep_attr);
sp_ep_info->pc = pc;
- /* The SPM payload runs in S-EL0 */
+ /* The secure partition runs in S-EL0. */
sp_ep_info->spsr = SPSR_64(MODE_EL0,
MODE_SP_EL0,
DISABLE_ALL_EXCEPTIONS);
@@ -228,21 +234,21 @@ static mmap_attr_t smc_attr_to_mmap_attr(unsigned int attributes)
{
mmap_attr_t tf_attr = 0;
- unsigned int access = (attributes & SP_MEM_ATTR_ACCESS_MASK)
- >> SP_MEM_ATTR_ACCESS_SHIFT;
+ unsigned int access = (attributes & SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
+ >> SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
- if (access == SP_MEM_ATTR_ACCESS_RW) {
+ if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RW) {
tf_attr |= MT_RW | MT_USER;
- } else if (access == SP_MEM_ATTR_ACCESS_RO) {
+ } else if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RO) {
tf_attr |= MT_RO | MT_USER;
} else {
/* Other values are reserved. */
- assert(access == SP_MEM_ATTR_ACCESS_NOACCESS);
+ assert(access == SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS);
/* The only requirement is that there's no access from EL0 */
tf_attr |= MT_RO | MT_PRIVILEGED;
}
- if ((attributes & SP_MEM_ATTR_NON_EXEC) == 0) {
+ if ((attributes & SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) {
tf_attr |= MT_EXECUTE;
} else {
tf_attr |= MT_EXECUTE_NEVER;
@@ -263,20 +269,21 @@ static int smc_mmap_to_smc_attr(mmap_attr_t attr)
if ((attr & MT_USER) == 0) {
/* No access from EL0. */
- data_access = SP_MEM_ATTR_ACCESS_NOACCESS;
+ data_access = SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS;
} else {
if ((attr & MT_RW) != 0) {
assert(MT_TYPE(attr) != MT_DEVICE);
- data_access = SP_MEM_ATTR_ACCESS_RW;
+ data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RW;
} else {
- data_access = SP_MEM_ATTR_ACCESS_RO;
+ data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RO;
}
}
- smc_attr |= (data_access & SP_MEM_ATTR_ACCESS_MASK) << SP_MEM_ATTR_ACCESS_SHIFT;
+ smc_attr |= (data_access & SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
+ << SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
if (attr & MT_EXECUTE_NEVER) {
- smc_attr |= SP_MEM_ATTR_NON_EXEC;
+ smc_attr |= SP_MEMORY_ATTRIBUTES_NON_EXEC;
}
return smc_attr;
@@ -349,7 +356,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
switch (smc_fid) {
- case SPM_VERSION_AARCH32:
+ case SPM_VERSION_AARCH32:
SMC_RET1(handle, SPM_VERSION_COMPILED);
case SP_EVENT_COMPLETE_AARCH64:
@@ -357,7 +364,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
cm_el1_sysregs_context_save(SECURE);
spm_setup_next_eret_into_sel0(handle);
- if (sp_init_in_progress) {
+ if (sp_ctx.sp_init_in_progress) {
/*
* SPM reports completion. The SPM must have
* initiated the original request through a
@@ -369,6 +376,9 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
assert(0);
}
+ /* Release the Secure Partition context */
+ spin_unlock(&sp_ctx.lock);
+
/*
* This is the result from the Secure partition of an
* earlier request. Copy the result into the non-secure
@@ -387,20 +397,20 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
/* Return to normal world */
SMC_RET1(ns_cpu_context, x1);
- case SP_MEM_ATTRIBUTES_GET_AARCH64:
- INFO("Received SP_MEM_ATTRIBUTES_GET_AARCH64 SMC\n");
+ case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
+ INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
- if (!sp_init_in_progress) {
- WARN("SP_MEM_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
+ if (!sp_ctx.sp_init_in_progress) {
+ WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
SMC_RET1(handle, SPM_NOT_SUPPORTED);
}
SMC_RET1(handle, spm_memory_attributes_get_smc_handler(x1));
- case SP_MEM_ATTRIBUTES_SET_AARCH64:
- INFO("Received SP_MEM_ATTRIBUTES_SET_AARCH64 SMC\n");
+ case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
+ INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
- if (!sp_init_in_progress) {
- WARN("SP_MEM_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
+ if (!sp_ctx.sp_init_in_progress) {
+ WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
SMC_RET1(handle, SPM_NOT_SUPPORTED);
}
SMC_RET1(handle, spm_memory_attributes_set_smc_handler(x1, x2, x3));
@@ -413,16 +423,38 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
switch (smc_fid) {
- case SP_VERSION_AARCH64:
- case SP_VERSION_AARCH32:
+ case SP_VERSION_AARCH64:
+ case SP_VERSION_AARCH32:
SMC_RET1(handle, SP_VERSION_COMPILED);
- case SP_COMMUNICATE_AARCH32:
- case SP_COMMUNICATE_AARCH64:
+ case MM_COMMUNICATE_AARCH32:
+ case MM_COMMUNICATE_AARCH64:
+ {
+ uint64_t mm_cookie = x1;
+ uint64_t comm_buffer_address = x2;
+ uint64_t comm_size_address = x3;
+
+ /* Cookie. Reserved for future use. It must be zero. */
+ if (mm_cookie != 0) {
+ ERROR("MM_COMMUNICATE: cookie is not zero\n");
+ SMC_RET1(handle, SPM_INVALID_PARAMETER);
+ }
+
+ if (comm_buffer_address == 0) {
+ ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
+ SMC_RET1(handle, SPM_INVALID_PARAMETER);
+ }
+
+ if (comm_size_address != 0) {
+ VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
+ }
/* Save the Normal world context */
cm_el1_sysregs_context_save(NON_SECURE);
+ /* Lock the Secure Partition context. */
+ spin_lock(&sp_ctx.lock);
+
/*
* Restore the secure world context and prepare for
* entry in S-EL0
@@ -431,17 +463,12 @@ uint64_t spm_smc_handler(uint32_t smc_fid,
cm_el1_sysregs_context_restore(SECURE);
cm_set_next_eret_context(SECURE);
- /* Cookie. Reserved for future use. It must be zero. */
- assert(x1 == 0);
-
- if (x3 != 0) {
- VERBOSE("SP_COMMUNICATE_AARCH32/64: X3 is not 0 as recommended.\n");
- }
-
- SMC_RET4(&sp_ctx.cpu_ctx, smc_fid, x1, x2, x3);
+ SMC_RET4(&sp_ctx.cpu_ctx, smc_fid, comm_buffer_address,
+ comm_size_address, plat_my_core_pos());
+ }
- case SP_MEM_ATTRIBUTES_GET_AARCH64:
- case SP_MEM_ATTRIBUTES_SET_AARCH64:
+ case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
+ case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
/* SMC interfaces reserved for secure callers. */
SMC_RET1(handle, SPM_NOT_SUPPORTED);
diff --git a/services/std_svc/spm/spm_private.h b/services/std_svc/spm/spm_private.h
index 16993e8c..1d16b458 100644
--- a/services/std_svc/spm/spm_private.h
+++ b/services/std_svc/spm/spm_private.h
@@ -32,6 +32,7 @@
#ifndef __ASSEMBLY__
+#include <spinlock.h>
#include <stdint.h>
#include <xlat_tables_v2.h>
@@ -43,6 +44,8 @@ struct entry_point_info;
typedef struct secure_partition_context {
uint64_t c_rt_ctx;
cpu_context_t cpu_ctx;
+ unsigned int sp_init_in_progress;
+ spinlock_t lock;
} secure_partition_context_t;
uint64_t spm_secure_partition_enter(uint64_t *c_rt_ctx);
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index 1dcb7e8e..33c451e4 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -492,7 +492,7 @@ static int pack_images(const char *filename, uint64_t toc_flags, unsigned long a
fip_toc_header_t *toc_header;
fip_toc_entry_t *toc_entry;
char *buf;
- uint64_t entry_offset, buf_size, payload_size = 0;
+ uint64_t entry_offset, buf_size, payload_size = 0, pad_size;
size_t nr_images = 0;
for (desc = image_desc_head; desc != NULL; desc = desc->next)
@@ -526,9 +526,13 @@ static int pack_images(const char *filename, uint64_t toc_flags, unsigned long a
entry_offset += image->toc_e.size;
}
- /* Append a null uuid entry to mark the end of ToC entries. */
+ /*
+ * Append a null uuid entry to mark the end of ToC entries.
+ * NOTE the offset address for the last toc_entry must match the fip
+ * size.
+ */
memset(toc_entry, 0, sizeof(*toc_entry));
- toc_entry->offset_address = entry_offset;
+ toc_entry->offset_address = (entry_offset + align - 1) & ~(align - 1);
/* Generate the FIP file. */
fp = fopen(filename, "wb");
@@ -555,6 +559,13 @@ static int pack_images(const char *filename, uint64_t toc_flags, unsigned long a
xfwrite(image->buffer, image->toc_e.size, fp, filename);
}
+ if (fseek(fp, entry_offset, SEEK_SET))
+ log_errx("Failed to set file position");
+
+ pad_size = toc_entry->offset_address - entry_offset;
+ while (pad_size--)
+ fputc(0x0, fp);
+
fclose(fp);
return 0;
}