SPM: FVP: Introduce port of SPM
authorAntonio Nino Diaz <antonio.ninodiaz@arm.com>
Thu, 9 Nov 2017 11:34:09 +0000 (11:34 +0000)
committerAntonio Nino Diaz <antonio.ninodiaz@arm.com>
Thu, 9 Nov 2017 11:34:09 +0000 (11:34 +0000)
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>
docs/spm-user-guide.rst [new file with mode: 0644]
include/plat/arm/board/common/board_arm_def.h
include/plat/arm/board/common/v2m_def.h
include/plat/arm/common/arm_def.h
include/plat/arm/common/arm_spm_def.h [new file with mode: 0644]
plat/arm/board/fvp/fvp_common.c
plat/arm/common/arm_common.c
plat/arm/common/arm_tzc400.c

diff --git a/docs/spm-user-guide.rst b/docs/spm-user-guide.rst
new file mode 100644 (file)
index 0000000..a3b64d9
--- /dev/null
@@ -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
index 7a4594cc5ad97fae37041499b7cb37419dd20b19..97a1af4bff6623e5626d12dbc6aa7603a1d7a9df 100644 (file)
  * 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
  * 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 */
 
index 364b780375f8982d085cae222c5f7aea149b7175..e5f53732921df8694d72ce1e6b743c7a2b5f5134 100644 (file)
                                                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__ */
index 6cab91fef643f29622adc108f38c4c617ef1d01c..9e82e2982116ec1a3ce2b6290a00698678b77844 100644 (file)
  * 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 -        \
 # 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 (file)
index 0000000..83277a6
--- /dev/null
@@ -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__ */
index 57cc3d513064bfadddaa41b57c24e7d6f6148342..6729863d7b8e564db7748143a020654528b73b2b 100644 (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,9 +119,23 @@ 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[] = {
 #ifdef AARCH32
@@ -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
index 420a3865137adbd199a4b5e93186fd2363d98b8b..1905c0b05efc88ea18b4d31d1ee1bb17ed104cc9 100644 (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());
 
index e19ca673fa64c177128c3146a1469f0b325761e7..23c031734542f7653345f383a5ed85e9d8c45452 100644 (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 */
 
        /*