From e29efeb1b40a3ac364fc0bf1e15928b400a57e72 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Thu, 9 Nov 2017 11:34:09 +0000 Subject: [PATCH] SPM: FVP: Introduce port of SPM This initial port of the Secure Partitions Manager to FVP supports BL31 in both SRAM and Trusted DRAM. A document with instructions to build the SPM has been added. Change-Id: I4ea83ff0a659be77f2cd72eaf2302cdf8ba98b32 Co-authored-by: Douglas Raillard Co-authored-by: Sandrine Bailleux Co-authored-by: Achin Gupta Co-authored-by: Antonio Nino Diaz Signed-off-by: Antonio Nino Diaz --- docs/spm-user-guide.rst | 59 ++++++++++ include/plat/arm/board/common/board_arm_def.h | 16 ++- include/plat/arm/board/common/v2m_def.h | 5 + include/plat/arm/common/arm_def.h | 19 +++- include/plat/arm/common/arm_spm_def.h | 105 ++++++++++++++++++ plat/arm/board/fvp/fvp_common.c | 70 ++++++++++++ plat/arm/common/arm_common.c | 9 ++ plat/arm/common/arm_tzc400.c | 22 +++- 8 files changed, 297 insertions(+), 8 deletions(-) create mode 100644 docs/spm-user-guide.rst create mode 100644 include/plat/arm/common/arm_spm_def.h diff --git a/docs/spm-user-guide.rst b/docs/spm-user-guide.rst new file mode 100644 index 000000000..a3b64d931 --- /dev/null +++ b/docs/spm-user-guide.rst @@ -0,0 +1,59 @@ +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/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h index 7a4594cc5..97a1af4bf 100644 --- a/include/plat/arm/board/common/board_arm_def.h +++ b/include/plat/arm/board/common/board_arm_def.h @@ -52,7 +52,17 @@ * They are also used for the dynamically mapped regions in the images that * enable dynamic memory mapping. */ -#if defined(IMAGE_BL31) || defined(IMAGE_BL32) +#if defined(IMAGE_BL31) +# if ENABLE_SPM +# define PLAT_ARM_MMAP_ENTRIES 9 +# define MAX_XLAT_TABLES 7 +# define PLAT_SP_IMAGE_MMAP_REGIONS 7 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10 +# else +# define PLAT_ARM_MMAP_ENTRIES 7 +# define MAX_XLAT_TABLES 5 +# endif +#elif defined(IMAGE_BL32) # define PLAT_ARM_MMAP_ENTRIES 7 # define MAX_XLAT_TABLES 5 #else @@ -80,7 +90,11 @@ * 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 #endif /* ARM_BOARD_OPTIMISE_MEM */ diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h index 364b78037..e5f537329 100644 --- a/include/plat/arm/board/common/v2m_def.h +++ b/include/plat/arm/board/common/v2m_def.h @@ -121,6 +121,11 @@ V2M_IOFPGA_SIZE, \ MT_DEVICE | MT_RW | MT_SECURE) +/* Region equivalent to V2M_MAP_IOFPGA suitable for mapping at EL0 */ +#define V2M_MAP_IOFPGA_EL0 MAP_REGION_FLAT( \ + V2M_IOFPGA_BASE, \ + V2M_IOFPGA_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE | MT_USER) #endif /* __V2M_DEF_H__ */ diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index 6cab91fef..9e82e2982 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -378,7 +378,13 @@ * Trusted DRAM (if available) or the DRAM region secured by the TrustZone * controller. */ -#if ARM_BL31_IN_DRAM +#if ENABLE_SPM +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000)) +# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE) +#elif ARM_BL31_IN_DRAM # define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + \ PLAT_ARM_MAX_BL31_SIZE) # define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - \ @@ -409,11 +415,14 @@ # error "Unsupported ARM_TSP_RAM_LOCATION_ID value" #endif -/* BL32 is mandatory in AArch32 */ +/* + * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no + * SPD and no SPM, as they are the only ones that can be used as BL32. + */ #ifndef AARCH32 -#ifdef SPD_none -#undef BL32_BASE -#endif /* SPD_none */ +# if defined(SPD_none) && !ENABLE_SPM +# undef BL32_BASE +# endif #endif /******************************************************************************* diff --git a/include/plat/arm/common/arm_spm_def.h b/include/plat/arm/common/arm_spm_def.h new file mode 100644 index 000000000..83277a6c5 --- /dev/null +++ b/include/plat/arm/common/arm_spm_def.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __ARM_SPM_DEF_H__ +#define __ARM_SPM_DEF_H__ + +#include +#include +#include +#include + +/* + * If BL31 is placed in DRAM, place the Secure Partition in DRAM right after the + * region used by BL31. If BL31 it is placed in SRAM, put the Secure Partition + * at the base of DRAM. + */ +#define ARM_SP_IMAGE_BASE BL32_BASE +#define ARM_SP_IMAGE_LIMIT BL32_LIMIT +/* The maximum size of the S-EL0 payload can be 3MB */ +#define ARM_SP_IMAGE_SIZE ULL(0x300000) + +#ifdef IMAGE_BL2 +/* SPM Payload memory. Mapped as RW in BL2. */ +#define ARM_SP_IMAGE_MMAP MAP_REGION_FLAT( \ + ARM_SP_IMAGE_BASE, \ + ARM_SP_IMAGE_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif +#ifdef IMAGE_BL31 +/* SPM Payload memory. Mapped as code in S-EL1 */ +#define ARM_SP_IMAGE_MMAP MAP_REGION2( \ + ARM_SP_IMAGE_BASE, \ + ARM_SP_IMAGE_BASE, \ + ARM_SP_IMAGE_SIZE, \ + MT_CODE | MT_SECURE | MT_USER, \ + PAGE_SIZE) +#endif + +/* + * Memory shared between EL3 and S-EL0. It is used by EL3 to push data into + * S-EL0, so it is mapped with RW permission from EL3 and with RO permission + * from S-EL0. Placed after SPM Payload memory. + */ +#define PLAT_SPM_BUF_BASE (ARM_SP_IMAGE_BASE + ARM_SP_IMAGE_SIZE) +#define PLAT_SPM_BUF_SIZE ULL(0x100000) + +#define ARM_SPM_BUF_EL3_MMAP MAP_REGION_FLAT( \ + PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_SIZE, \ + MT_RW_DATA | MT_SECURE) +#define ARM_SPM_BUF_EL0_MMAP MAP_REGION2( \ + PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_SIZE, \ + MT_RO_DATA | MT_SECURE | MT_USER,\ + PAGE_SIZE) + +/* + * Memory shared between Normal world and S-EL0 for passing data during service + * requests. Mapped as RW and NS. Placed after the shared memory between EL3 and + * S-EL0. + */ +#define ARM_SP_IMAGE_NS_BUF_BASE (PLAT_SPM_BUF_BASE + PLAT_SPM_BUF_SIZE) +#define ARM_SP_IMAGE_NS_BUF_SIZE ULL(0x10000) +#define ARM_SP_IMAGE_NS_BUF_MMAP MAP_REGION2( \ + ARM_SP_IMAGE_NS_BUF_BASE, \ + ARM_SP_IMAGE_NS_BUF_BASE, \ + ARM_SP_IMAGE_NS_BUF_SIZE, \ + MT_RW_DATA | MT_NS | MT_USER, \ + PAGE_SIZE) + +/* + * RW memory, which uses the remaining Trusted DRAM. Placed after the memory + * shared between Secure and Non-secure worlds. First there is the stack memory + * for all CPUs and then there is the common heap memory. Both are mapped with + * RW permissions. + */ +#define PLAT_SP_IMAGE_STACK_BASE (ARM_SP_IMAGE_NS_BUF_BASE + \ + ARM_SP_IMAGE_NS_BUF_SIZE) +#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x2000) +#define ARM_SP_IMAGE_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * \ + PLAT_SP_IMAGE_STACK_PCPU_SIZE) + +#define ARM_SP_IMAGE_HEAP_BASE (PLAT_SP_IMAGE_STACK_BASE + \ + ARM_SP_IMAGE_STACK_TOTAL_SIZE) +#define ARM_SP_IMAGE_HEAP_SIZE (ARM_SP_IMAGE_LIMIT - ARM_SP_IMAGE_HEAP_BASE) + +#define ARM_SP_IMAGE_RW_MMAP MAP_REGION2( \ + PLAT_SP_IMAGE_STACK_BASE, \ + PLAT_SP_IMAGE_STACK_BASE, \ + (ARM_SP_IMAGE_LIMIT - \ + PLAT_SP_IMAGE_STACK_BASE), \ + MT_RW_DATA | MT_SECURE | MT_USER,\ + PAGE_SIZE) + +/* Total number of memory regions with distinct properties */ +#define ARM_SP_IMAGE_NUM_MEM_REGIONS 6 + +/* 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) + +#endif /* __ARM_SPM_DEF_H__ */ diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index 57cc3d513..6729863d7 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include #include #include +#include #include #include "../fvp_def.h" @@ -89,6 +91,9 @@ const mmap_region_t plat_arm_mmap[] = { /* To access the Root of Trust Public Key registers. */ MAP_DEVICE2, #endif +#if ENABLE_SPM + ARM_SP_IMAGE_MMAP, +#endif #if ARM_BL31_IN_DRAM ARM_MAP_BL31_SEC_DRAM, #endif @@ -114,8 +119,22 @@ const mmap_region_t plat_arm_mmap[] = { MAP_DEVICE0, MAP_DEVICE1, ARM_V2M_MAP_MEM_PROTECT, +#if ENABLE_SPM + ARM_SPM_BUF_EL3_MMAP, +#endif {0} }; + +#if ENABLE_SPM && defined(IMAGE_BL31) +const mmap_region_t plat_arm_secure_partition_mmap[] = { + V2M_MAP_IOFPGA_EL0, /* for the UART */ + ARM_SP_IMAGE_MMAP, + ARM_SP_IMAGE_NS_BUF_MMAP, + ARM_SP_IMAGE_RW_MMAP, + ARM_SPM_BUF_EL0_MMAP, + {0} +}; +#endif #endif #ifdef IMAGE_BL32 const mmap_region_t plat_arm_mmap[] = { @@ -156,6 +175,57 @@ static unsigned int get_interconnect_master(void) } #endif +#if ENABLE_SPM && defined(IMAGE_BL31) +/* + * Boot information passed to a secure partition during initialisation. Linear + * indices in MP information will be filled at runtime. + */ +static secure_partition_mp_info_t sp_mp_info[] = { + [0] = {0x80000000, 0}, + [1] = {0x80000001, 0}, + [2] = {0x80000002, 0}, + [3] = {0x80000003, 0}, + [4] = {0x80000100, 0}, + [5] = {0x80000101, 0}, + [6] = {0x80000102, 0}, + [7] = {0x80000103, 0}, +}; + +const secure_partition_boot_info_t plat_arm_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(secure_partition_boot_info_t), + .h.attr = 0, + .sp_mem_base = ARM_SP_IMAGE_BASE, + .sp_mem_limit = ARM_SP_IMAGE_LIMIT, + .sp_image_base = ARM_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = ARM_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = ARM_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = ARM_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = &sp_mp_info[0], +}; + +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) +{ + return plat_arm_secure_partition_mmap; +} + +const struct secure_partition_boot_info *plat_get_secure_partition_boot_info( + void *cookie) +{ + return &plat_arm_secure_partition_boot_info; +} + +#endif + /******************************************************************************* * A single boot loader stack is expected to work on both the Foundation FVP * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index 420a38651..1905c0b05 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -11,6 +11,7 @@ #include #include #include +#include extern const mmap_region_t plat_arm_mmap[]; @@ -79,6 +80,14 @@ void arm_setup_page_tables(uintptr_t total_base, MT_DEVICE | MT_RW | MT_SECURE); #endif +#if ENABLE_SPM && defined(IMAGE_BL31) + /* The address of the following region is calculated by the linker. */ + mmap_add_region(SP_IMAGE_XLAT_TABLES_START, + SP_IMAGE_XLAT_TABLES_START, + SP_IMAGE_XLAT_TABLES_SIZE, + MT_MEMORY | MT_RW | MT_SECURE); +#endif + /* Now (re-)map the platform-specific memory regions */ mmap_add(plat_arm_get_mmap()); diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c index e19ca673f..23c031734 100644 --- a/plat/arm/common/arm_tzc400.c +++ b/plat/arm/common/arm_tzc400.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include +#include #include #include #include @@ -56,9 +57,26 @@ void arm_tzc400_setup(void) ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS); -#else + +#if ENABLE_SPM + /* + * Region 4 set to cover Non-Secure access to the communication buffer + * shared with the Secure world. + */ + tzc400_configure_region(PLAT_ARM_TZC_FILTERS, + 4, + ARM_SP_IMAGE_NS_BUF_BASE, + (ARM_SP_IMAGE_NS_BUF_BASE + + ARM_SP_IMAGE_NS_BUF_SIZE) - 1, + TZC_REGION_S_NONE, + PLAT_ARM_TZC_NS_DEV_ACCESS); +#endif + +#else /* if defined(EL3_PAYLOAD_BASE) */ + /* Allow secure access only to DRAM for EL3 payloads. */ tzc400_configure_region0(TZC_REGION_S_RDWR, 0); + #endif /* EL3_PAYLOAD_BASE */ /*