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 <douglas.raillard@arm.com>
Co-authored-by: Sandrine Bailleux <sandrine.bailleux@arm.com>
Co-authored-by: Achin Gupta <achin.gupta@arm.com>
Co-authored-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
This commit is contained in:
Antonio Nino Diaz 2017-11-09 11:34:09 +00:00
parent 2fccb22804
commit e29efeb1b4
8 changed files with 297 additions and 8 deletions

59
docs/spm-user-guide.rst Normal file
View File

@ -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

View File

@ -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 */

View File

@ -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__ */

View File

@ -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
/*******************************************************************************

View File

@ -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 <arm_def.h>
#include <platform_def.h>
#include <utils_def.h>
#include <xlat_tables_defs.h>
/*
* 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__ */

View File

@ -6,6 +6,7 @@
#include <arm_config.h>
#include <arm_def.h>
#include <arm_spm_def.h>
#include <assert.h>
#include <cci.h>
#include <ccn.h>
@ -13,6 +14,7 @@
#include <gicv2.h>
#include <mmio.h>
#include <plat_arm.h>
#include <secure_partition.h>
#include <v2m_def.h>
#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

View File

@ -11,6 +11,7 @@
#include <mmio.h>
#include <plat_arm.h>
#include <platform_def.h>
#include <secure_partition.h>
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());

View File

@ -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 <arm_def.h>
#include <arm_spm_def.h>
#include <debug.h>
#include <platform_def.h>
#include <tzc400.h>
@ -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 */
/*