SPM: Introduce Secure Partition Manager

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 e.g. ARM Trusted Firmware to be
granted access to system and processor resources. Essentially, it is a
software sandbox that runs under the control of privileged software in
the Secure World and accesses the following system resources:

- Memory and device regions in the system address map.
- PE system registers.
- A range of asynchronous exceptions e.g. interrupts.
- A range of synchronous exceptions e.g. SMC function identifiers.

A Secure Partition enables privileged firmware to implement only the
absolutely essential secure services in EL3 and instantiate the rest in
a partition. Since the partition executes in S-EL0, its implementation
cannot be overly complex.

The component in ARM Trusted Firmware responsible for managing a Secure
Partition is called the Secure Partition Manager (SPM). The SPM is
responsible for the following:

- Validating and allocating resources requested by a Secure Partition.
- Implementing a well defined interface that is used for initialising a
  Secure Partition.
- Implementing a well defined interface that is used by the normal world
  and other secure services for accessing the services exported by a
  Secure Partition.
- Implementing a well defined interface that is used by a Secure
  Partition to fulfil service requests.
- Instantiating the software execution environment required by a Secure
  Partition to fulfil a service request.

Change-Id: I6f7862d6bba8732db5b73f54e789d717a35e802f
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>
diff --git a/include/common/aarch64/asm_macros.S b/include/common/aarch64/asm_macros.S
index 6d6989c..94a9df9 100644
--- a/include/common/aarch64/asm_macros.S
+++ b/include/common/aarch64/asm_macros.S
@@ -51,8 +51,8 @@
 	 * so that it inserts illegal AArch64 instructions. This increases
 	 * security, robustness and potentially facilitates debugging.
 	 */
-	.macro vector_base  label
-	.section .vectors, "ax"
+	.macro vector_base  label, section_name=.vectors
+	.section \section_name, "ax"
 	.align 11, 0
 	\label:
 	.endm
@@ -64,9 +64,9 @@
 	 * so that it inserts illegal AArch64 instructions. This increases
 	 * security, robustness and potentially facilitates debugging.
 	 */
-	.macro vector_entry  label
+	.macro vector_entry  label, section_name=.vectors
 	.cfi_sections .debug_frame
-	.section .vectors, "ax"
+	.section \section_name, "ax"
 	.align 7, 0
 	.type \label, %function
 	.func \label
diff --git a/include/common/param_header.h b/include/common/param_header.h
index 90d59b3..c982fc90a 100644
--- a/include/common/param_header.h
+++ b/include/common/param_header.h
@@ -8,12 +8,13 @@
 #define __PARAM_HEADER_H__
 
 /* Param header types */
-#define PARAM_EP		0x01
-#define PARAM_IMAGE_BINARY	0x02
-#define PARAM_BL31		0x03
-#define PARAM_BL_LOAD_INFO	0x04
-#define PARAM_BL_PARAMS		0x05
-#define PARAM_PSCI_LIB_ARGS	0x06
+#define PARAM_EP			0x01
+#define PARAM_IMAGE_BINARY		0x02
+#define PARAM_BL31			0x03
+#define PARAM_BL_LOAD_INFO		0x04
+#define PARAM_BL_PARAMS			0x05
+#define PARAM_PSCI_LIB_ARGS		0x06
+#define PARAM_SP_IMAGE_BOOT_INFO	0x07
 
 /* Param header version */
 #define VERSION_1	0x01
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 997e3a2..16d12a3 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -126,6 +126,7 @@
 #define ID_AA64PFR0_GIC_MASK	((U(1) << ID_AA64PFR0_GIC_WIDTH) - 1)
 
 /* ID_AA64MMFR0_EL1 definitions */
+#define ID_AA64MMFR0_EL1_PARANGE_SHIFT	U(0)
 #define ID_AA64MMFR0_EL1_PARANGE_MASK	U(0xf)
 
 #define PARANGE_0000	U(32)
@@ -135,6 +136,21 @@
 #define PARANGE_0100	U(44)
 #define PARANGE_0101	U(48)
 
+#define ID_AA64MMFR0_EL1_TGRAN4_SHIFT		U(28)
+#define ID_AA64MMFR0_EL1_TGRAN4_MASK		U(0xf)
+#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED	U(0x0)
+#define ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED	U(0xf)
+
+#define ID_AA64MMFR0_EL1_TGRAN64_SHIFT		U(24)
+#define ID_AA64MMFR0_EL1_TGRAN64_MASK		U(0xf)
+#define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED	U(0x0)
+#define ID_AA64MMFR0_EL1_TGRAN64_NOT_SUPPORTED	U(0xf)
+
+#define ID_AA64MMFR0_EL1_TGRAN16_SHIFT		U(20)
+#define ID_AA64MMFR0_EL1_TGRAN16_MASK		U(0xf)
+#define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED	U(0x1)
+#define ID_AA64MMFR0_EL1_TGRAN16_NOT_SUPPORTED	U(0x0)
+
 /* ID_PFR1_EL1 definitions */
 #define ID_PFR1_VIRTEXT_SHIFT	U(12)
 #define ID_PFR1_VIRTEXT_MASK	U(0xf)
@@ -160,12 +176,25 @@
 #define SCTLR_A_BIT		(U(1) << 1)
 #define SCTLR_C_BIT		(U(1) << 2)
 #define SCTLR_SA_BIT		(U(1) << 3)
+#define SCTLR_SA0_BIT		(U(1) << 4)
 #define SCTLR_CP15BEN_BIT	(U(1) << 5)
+#define SCTLR_ITD_BIT		(U(1) << 7)
+#define SCTLR_SED_BIT		(U(1) << 8)
+#define SCTLR_UMA_BIT		(U(1) << 9)
 #define SCTLR_I_BIT		(U(1) << 12)
+#define SCTLR_V_BIT		(U(1) << 13)
+#define SCTLR_DZE_BIT		(U(1) << 14)
+#define SCTLR_UCT_BIT		(U(1) << 15)
 #define SCTLR_NTWI_BIT		(U(1) << 16)
 #define SCTLR_NTWE_BIT		(U(1) << 18)
 #define SCTLR_WXN_BIT		(U(1) << 19)
+#define SCTLR_UWXN_BIT		(U(1) << 20)
+#define SCTLR_E0E_BIT		(U(1) << 24)
 #define SCTLR_EE_BIT		(U(1) << 25)
+#define SCTLR_UCI_BIT		(U(1) << 26)
+#define SCTLR_TRE_BIT		(U(1) << 28)
+#define SCTLR_AFE_BIT		(U(1) << 29)
+#define SCTLR_TE_BIT		(U(1) << 30)
 #define SCTLR_RESET_VAL		SCTLR_EL3_RES1
 
 /* CPACR_El1 definitions */
@@ -350,6 +379,13 @@
 #define TCR_SH_OUTER_SHAREABLE	(U(0x2) << 12)
 #define TCR_SH_INNER_SHAREABLE	(U(0x3) << 12)
 
+#define TCR_TG0_SHIFT		U(14)
+#define TCR_TG0_MASK		U(3)
+#define TCR_TG0_4K		(ULL(0) << TCR_TG0_SHIFT)
+#define TCR_TG0_64K		(ULL(1) << TCR_TG0_SHIFT)
+#define TCR_TG0_16K		(ULL(2) << TCR_TG0_SHIFT)
+
+#define TCR_EPD0_BIT		(U(1) << 7)
 #define TCR_EPD1_BIT		(U(1) << 23)
 
 #define MODE_SP_SHIFT		U(0x0)
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index e2bfa50..068d7aa 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -23,6 +23,8 @@
 struct image_desc;
 struct bl_load_info;
 struct bl_params;
+struct mmap_region;
+struct secure_partition_boot_info;
 
 /*******************************************************************************
  * plat_get_rotpk_info() flags
@@ -293,6 +295,13 @@
 int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc,
 		unsigned int nv_ctr);
 
+/*******************************************************************************
+ * Secure Partitions functions
+ ******************************************************************************/
+const struct mmap_region *plat_get_secure_partition_mmap(void *cookie);
+const struct secure_partition_boot_info *plat_get_secure_partition_boot_info(
+		void *cookie);
+
 #if LOAD_IMAGE_V2
 /*******************************************************************************
  * Mandatory BL image load functions(may be overridden).
diff --git a/include/services/secure_partition.h b/include/services/secure_partition.h
new file mode 100644
index 0000000..334f761
--- /dev/null
+++ b/include/services/secure_partition.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SECURE_PARTITION_H__
+#define __SECURE_PARTITION_H__
+
+#include <bl_common.h>
+#include <types.h>
+#include <utils_def.h>
+
+/* Linker symbols */
+extern uintptr_t __SP_IMAGE_XLAT_TABLES_START__;
+extern uintptr_t __SP_IMAGE_XLAT_TABLES_END__;
+
+/* Definitions */
+#define SP_IMAGE_XLAT_TABLES_START	\
+	(uintptr_t)(&__SP_IMAGE_XLAT_TABLES_START__)
+#define SP_IMAGE_XLAT_TABLES_END	\
+	(uintptr_t)(&__SP_IMAGE_XLAT_TABLES_END__)
+#define SP_IMAGE_XLAT_TABLES_SIZE	\
+	(SP_IMAGE_XLAT_TABLES_END - SP_IMAGE_XLAT_TABLES_START)
+
+/*
+ * Flags used by the secure_partition_mp_info structure to describe the
+ * characteristics of a cpu. Only a single flag is defined at the moment to
+ * indicate the primary cpu.
+ */
+#define MP_INFO_FLAG_PRIMARY_CPU	U(0x00000001)
+
+/*
+ * This structure is used to provide information required to initialise a S-EL0
+ * partition.
+ */
+typedef struct secure_partition_mp_info {
+	u_register_t		mpidr;
+	unsigned int		linear_id;
+	unsigned int		flags;
+} secure_partition_mp_info_t;
+
+typedef struct secure_partition_boot_info {
+	param_header_t		h;
+	uintptr_t		sp_mem_base;
+	uintptr_t		sp_mem_limit;
+	uintptr_t		sp_image_base;
+	uintptr_t		sp_stack_base;
+	uintptr_t		sp_heap_base;
+	uintptr_t		sp_ns_comm_buf_base;
+	uintptr_t		sp_shared_buf_base;
+	size_t			sp_image_size;
+	size_t			sp_pcpu_stack_size;
+	size_t			sp_heap_size;
+	size_t			sp_ns_comm_buf_size;
+	size_t			sp_shared_buf_size;
+	unsigned int		num_sp_mem_regions;
+	unsigned int		num_cpus;
+	secure_partition_mp_info_t	*mp_info;
+} secure_partition_boot_info_t;
+
+/* Setup function for secure partitions context. */
+
+void secure_partition_setup(void);
+
+#endif /* __SECURE_PARTITION_H__ */
diff --git a/include/services/spm_svc.h b/include/services/spm_svc.h
new file mode 100644
index 0000000..2c8c7cd
--- /dev/null
+++ b/include/services/spm_svc.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SPM_SVC_H__
+#define __SPM_SVC_H__
+
+#include <utils_def.h>
+
+#define SPM_VERSION_MAJOR	U(0)
+#define SPM_VERSION_MINOR	U(1)
+#define SPM_VERSION_FORM(major, minor)	((major << 16) | (minor))
+#define SPM_VERSION_COMPILED	SPM_VERSION_FORM(SPM_VERSION_MAJOR, SPM_VERSION_MINOR)
+
+#define SP_VERSION_MAJOR	U(1)
+#define SP_VERSION_MINOR	U(0)
+#define SP_VERSION_FORM(major, minor)	((major << 16) | (minor))
+#define SP_VERSION_COMPILED	SP_VERSION_FORM(SP_VERSION_MAJOR, SP_VERSION_MINOR)
+
+/* The macros below are used to identify SPM calls from the SMC function ID */
+#define SPM_FID_MASK			U(0xffff)
+#define SPM_FID_MIN_VALUE		U(0x40)
+#define SPM_FID_MAX_VALUE		U(0x7f)
+#define is_spm_fid(_fid)						\
+		((((_fid) & SPM_FID_MASK) >= SPM_FID_MIN_VALUE) &&	\
+		 (((_fid) & SPM_FID_MASK) <= SPM_FID_MAX_VALUE))
+
+/*
+ * SMC IDs defined for accessing services implemented by the Secure Partition
+ * 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)
+
+/*
+ * Macros used by SP_MEM_ATTRIBUTES_SET_AARCH64.
+ */
+
+#define SP_MEM_ATTR_ACCESS_NOACCESS	U(0)
+#define SP_MEM_ATTR_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_MEM_ATTR_EXEC		(U(0) << 2)
+#define SP_MEM_ATTR_NON_EXEC		(U(1) << 2)
+
+/*
+ * SMC IDs defined in [1] for accessing secure partition services from the
+ * Non-secure world. These FIDs occupy the range 0x40 - 0x5f
+ * [1] DEN0060A_ARM_MM_Interface_Specification.pdf
+ */
+#define SP_VERSION_AARCH64		U(0xC4000040)
+#define SP_VERSION_AARCH32		U(0x84000040)
+
+#define SP_COMMUNICATE_AARCH64		U(0xC4000041)
+#define SP_COMMUNICATE_AARCH32		U(0x84000041)
+
+/* SPM error codes. */
+#define SPM_SUCCESS		0
+#define SPM_NOT_SUPPORTED	-1
+#define SPM_INVALID_PARAMETER	-2
+#define SPM_DENIED		-3
+#define SPM_NO_MEMORY		-5
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+int32_t spm_setup(void);
+
+uint64_t spm_smc_handler(uint32_t smc_fid,
+			 uint64_t x1,
+			 uint64_t x2,
+			 uint64_t x3,
+			 uint64_t x4,
+			 void *cookie,
+			 void *handle,
+			 uint64_t flags);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __SPM_SVC_H__ */