qemu/qemu_sbsa: enable SPM support

Enable the spm_mm framework for the qemu_sbsa platform.
Memory layout required for spm_mm is created in secure SRAM.

Co-developed-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
Change-Id: I104a623e8bc1e44d035b95f014a13b3f8b33a62a
diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c
index 365cfb7..7f8e4c4 100644
--- a/plat/qemu/common/qemu_common.c
+++ b/plat/qemu/common/qemu_common.c
@@ -1,5 +1,6 @@
+
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -77,7 +78,11 @@
 	MAP_DEVICE2,
 #endif
 	MAP_NS_DRAM0,
+#if SPM_MM
+	QEMU_SP_IMAGE_MMAP,
+#else
 	MAP_BL32_MEM,
+#endif
 	{0}
 };
 #endif
@@ -88,7 +93,11 @@
 #ifdef MAP_DEVICE1
 	MAP_DEVICE1,
 #endif
+#if SPM_MM
+	QEMU_SPM_BUF_EL3_MMAP,
+#else
 	MAP_BL32_MEM,
+#endif
 	{0}
 };
 #endif
diff --git a/plat/qemu/common/qemu_spm.c b/plat/qemu/common/qemu_spm.c
new file mode 100644
index 0000000..e9ab1a5
--- /dev/null
+++ b/plat/qemu/common/qemu_spm.c
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2020, Linaro Limited and Contributors. All rights reserved.
+ */
+
+#include <bl31/ehf.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/spm_mm_partition.h>
+
+#include <platform_def.h>
+
+/* Region equivalent to MAP_DEVICE1 suitable for mapping at EL0 */
+#define MAP_DEVICE1_EL0	MAP_REGION_FLAT(DEVICE1_BASE,			\
+					DEVICE1_SIZE,			\
+					MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+
+const mmap_region_t plat_qemu_secure_partition_mmap[] = {
+	MAP_DEVICE1_EL0, /* for the UART */
+	QEMU_SP_IMAGE_MMAP,
+	QEMU_SPM_BUF_EL0_MMAP,
+	QEMU_SP_IMAGE_NS_BUF_MMAP,
+	QEMU_SP_IMAGE_RW_MMAP,
+	{0}
+};
+
+/*
+ * Boot information passed to a secure partition during initialisation.
+ * Linear indices in MP information will be filled at runtime.
+ */
+static spm_mm_mp_info_t sp_mp_info[] = {
+	[0] = {0x80000000, 0},
+	[1] = {0x80000001, 0},
+	[2] = {0x80000002, 0},
+	[3] = {0x80000003, 0},
+	[4] = {0x80000004, 0},
+	[5] = {0x80000005, 0},
+	[6] = {0x80000006, 0},
+	[7] = {0x80000007, 0}
+};
+
+const spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = {
+	.h.type              = PARAM_SP_IMAGE_BOOT_INFO,
+	.h.version           = VERSION_1,
+	.h.size              = sizeof(spm_mm_boot_info_t),
+	.h.attr              = 0,
+	.sp_mem_base         = PLAT_QEMU_SP_IMAGE_BASE,
+	.sp_mem_limit        = BL32_LIMIT,
+	.sp_image_base       = PLAT_QEMU_SP_IMAGE_BASE,
+	.sp_stack_base       = PLAT_SP_IMAGE_STACK_BASE,
+	.sp_heap_base        = PLAT_QEMU_SP_IMAGE_HEAP_BASE,
+	.sp_ns_comm_buf_base = PLAT_QEMU_SP_IMAGE_NS_BUF_BASE,
+	.sp_shared_buf_base  = PLAT_SPM_BUF_BASE,
+	.sp_image_size       = PLAT_QEMU_SP_IMAGE_SIZE,
+	.sp_pcpu_stack_size  = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
+	.sp_heap_size        = PLAT_QEMU_SP_IMAGE_HEAP_SIZE,
+	.sp_ns_comm_buf_size = PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE,
+	.sp_shared_buf_size  = PLAT_SPM_BUF_SIZE,
+	.num_sp_mem_regions  = PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS,
+	.num_cpus            = PLATFORM_CORE_COUNT,
+	.mp_info             = sp_mp_info
+};
+
+/* Enumeration of priority levels on QEMU platforms. */
+ehf_pri_desc_t qemu_exceptions[] = {
+	EHF_PRI_DESC(QEMU_PRI_BITS, PLAT_SP_PRI)
+};
+
+/* Plug in QEMU exceptions to Exception Handling Framework. */
+EHF_REGISTER_PRIORITIES(qemu_exceptions, ARRAY_SIZE(qemu_exceptions),
+			QEMU_PRI_BITS);
+
+const mmap_region_t *plat_get_secure_partition_mmap(void *cookie)
+{
+	return plat_qemu_secure_partition_mmap;
+}
+
+const spm_mm_boot_info_t *
+plat_get_secure_partition_boot_info(void *cookie)
+{
+	return &plat_qemu_secure_partition_boot_info;
+}
diff --git a/plat/qemu/qemu_sbsa/include/platform_def.h b/plat/qemu/qemu_sbsa/include/platform_def.h
index d0a56cf..7634005 100644
--- a/plat/qemu/qemu_sbsa/include/platform_def.h
+++ b/plat/qemu/qemu_sbsa/include/platform_def.h
@@ -1,10 +1,11 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  *
- * Copyright (c) 2019, Linaro Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited and Contributors.
+ * All rights reserved.
  */
 
-#ifndef __PLATFORM_DEF_H__
-#define __PLATFORM_DEF_H__
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
 
 #include <arch.h>
 #include <plat/common/common_def.h>
@@ -107,9 +108,10 @@
  * 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 BL1_SIZE			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 - 0x12000)
+#define BL1_RW_BASE			(BL1_RW_LIMIT - BL1_SIZE)
 #define BL1_RW_LIMIT			(BL_RAM_BASE + BL_RAM_SIZE)
 
 /*
@@ -118,7 +120,8 @@
  * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
  * size plus a little space for growth.
  */
-#define BL2_BASE			(BL31_BASE - 0x1D000)
+#define BL2_SIZE			0x1D000
+#define BL2_BASE			(BL31_BASE - BL2_SIZE)
 #define BL2_LIMIT			BL31_BASE
 
 /*
@@ -127,8 +130,9 @@
  * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the
  * current BL3-1 debug size plus a little space for growth.
  */
-#define BL31_BASE			(BL31_LIMIT - 0x20000)
-#define BL31_LIMIT			(BL_RAM_BASE + BL_RAM_SIZE)
+#define BL31_SIZE			0x50000
+#define BL31_BASE			(BL31_LIMIT - BL31_SIZE)
+#define BL31_LIMIT			(BL1_RW_BASE)
 #define BL31_PROGBITS_LIMIT		BL1_RW_BASE
 
 
@@ -138,12 +142,11 @@
  * BL3-2 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_DRAM_BASE
-#define BL32_DRAM_LIMIT			(SEC_DRAM_BASE + SEC_DRAM_SIZE)
+#define BL32_SRAM_LIMIT			BL2_BASE
 
 #define BL32_MEM_BASE			BL_RAM_BASE
-#define BL32_MEM_SIZE			BL_RAM_SIZE
+#define BL32_MEM_SIZE			(BL_RAM_SIZE - BL1_SIZE - \
+					BL2_SIZE - BL31_SIZE)
 #define BL32_BASE			BL32_SRAM_BASE
 #define BL32_LIMIT			BL32_SRAM_LIMIT
 
@@ -152,11 +155,21 @@
 
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 42)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 42)
+#if SPM_MM
+#define MAX_MMAP_REGIONS		12
+#define MAX_XLAT_TABLES			11
+#else
 #define MAX_MMAP_REGIONS		11
 #define MAX_XLAT_TABLES			10
+#endif
 #define MAX_IO_DEVICES			3
 #define MAX_IO_HANDLES			4
 
+#if SPM_MM && defined(IMAGE_BL31)
+# define PLAT_SP_IMAGE_MMAP_REGIONS	30
+# define PLAT_SP_IMAGE_MAX_XLAT_TABLES	20
+#endif
+
 /*
  * PL011 related constants
  */
@@ -165,6 +178,10 @@
 #define UART0_CLK_IN_HZ			1
 #define UART1_CLK_IN_HZ			1
 
+/* Secure UART */
+#define UART2_BASE			0x60040000
+#define UART2_CLK_IN_HZ			1
+
 #define PLAT_QEMU_BOOT_UART_BASE	UART0_BASE
 #define PLAT_QEMU_BOOT_UART_CLK_IN_HZ	UART0_CLK_IN_HZ
 
@@ -179,7 +196,7 @@
 #define QEMU_FLASH1_SIZE		0x10000000
 
 #define PLAT_QEMU_FIP_BASE		0x00008000
-#define PLAT_QEMU_FIP_MAX_SIZE		0x00020000
+#define PLAT_QEMU_FIP_MAX_SIZE		0x00400000
 
 /* This is map from GIC_DIST up to last CPU (255) GIC_REDISTR */
 #define DEVICE0_BASE			0x40000000
@@ -240,4 +257,99 @@
  */
 #define SYS_COUNTER_FREQ_IN_TICKS	((1000 * 1000 * 1000) / 16)
 
+#if SPM_MM
+#define PLAT_QEMU_SP_IMAGE_BASE		BL_RAM_BASE
+#define PLAT_QEMU_SP_IMAGE_SIZE		ULL(0x300000)
+
+#ifdef IMAGE_BL2
+/* In BL2 all memory allocated to the SPM Payload image is marked as RW. */
+# define QEMU_SP_IMAGE_MMAP		MAP_REGION_FLAT( \
+						PLAT_QEMU_SP_IMAGE_BASE, \
+						PLAT_QEMU_SP_IMAGE_SIZE, \
+						MT_MEMORY | MT_RW | \
+						MT_SECURE)
+#elif IMAGE_BL31
+/* All SPM Payload memory is marked as code in S-EL0 */
+# define QEMU_SP_IMAGE_MMAP		MAP_REGION2(PLAT_QEMU_SP_IMAGE_BASE, \
+						PLAT_QEMU_SP_IMAGE_BASE, \
+						PLAT_QEMU_SP_IMAGE_SIZE, \
+						MT_CODE | MT_SECURE | \
+						MT_USER,		\
+						PAGE_SIZE)
+#endif
+
+/*
+ * EL3 -> S-EL0 secure shared memory
+ */
+#define PLAT_SPM_BUF_PCPU_SIZE		ULL(0x10000)
+#define PLAT_SPM_BUF_SIZE		(PLATFORM_CORE_COUNT * \
+					PLAT_SPM_BUF_PCPU_SIZE)
+#define PLAT_SPM_BUF_BASE		(BL32_LIMIT - PLAT_SPM_BUF_SIZE)
+
+#define QEMU_SPM_BUF_EL3_MMAP		MAP_REGION_FLAT(PLAT_SPM_BUF_BASE, \
+						PLAT_SPM_BUF_SIZE, \
+						MT_RW_DATA | MT_SECURE)
+
+#define QEMU_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)
+
+/*
+ * Shared memory between Normal world and S-EL0 for
+ * passing data during service requests. It will be marked as RW and NS.
+ */
+#define PLAT_QEMU_SP_IMAGE_NS_BUF_BASE	(PLAT_QEMU_DT_BASE +		\
+						PLAT_QEMU_DT_MAX_SIZE)
+#define PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE	ULL(0x10000)
+#define QEMU_SP_IMAGE_NS_BUF_MMAP	MAP_REGION2( \
+					PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \
+					PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \
+					PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE, \
+					MT_RW_DATA | MT_NS | \
+					MT_USER, \
+					PAGE_SIZE)
+
+#define PLAT_SP_IMAGE_NS_BUF_BASE	PLAT_QEMU_SP_IMAGE_NS_BUF_BASE
+#define PLAT_SP_IMAGE_NS_BUF_SIZE	PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE
+
+#define PLAT_QEMU_SP_IMAGE_HEAP_BASE	(PLAT_QEMU_SP_IMAGE_BASE + \
+					PLAT_QEMU_SP_IMAGE_SIZE)
+#define PLAT_QEMU_SP_IMAGE_HEAP_SIZE	ULL(0x800000)
+
+#define PLAT_SP_IMAGE_STACK_BASE	(PLAT_QEMU_SP_IMAGE_HEAP_BASE + \
+						PLAT_QEMU_SP_IMAGE_HEAP_SIZE)
+#define PLAT_SP_IMAGE_STACK_PCPU_SIZE	ULL(0x10000)
+#define QEMU_SP_IMAGE_STACK_TOTAL_SIZE	(PLATFORM_CORE_COUNT * \
+						PLAT_SP_IMAGE_STACK_PCPU_SIZE)
+
+#define QEMU_SP_IMAGE_RW_MMAP		MAP_REGION2( \
+					PLAT_QEMU_SP_IMAGE_HEAP_BASE, \
+					PLAT_QEMU_SP_IMAGE_HEAP_BASE, \
+					(QEMU_SP_IMAGE_STACK_TOTAL_SIZE + \
+					PLAT_QEMU_SP_IMAGE_HEAP_SIZE), \
+					MT_RW_DATA | MT_SECURE | \
+					MT_USER, \
+					PAGE_SIZE)
+
+/* Total number of memory regions with distinct properties */
+#define PLAT_QEMU_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		"qemu_sp_xlat_table"
+#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME	"qemu_sp_xlat_table"
+
+/* Cookies passed to the Secure Partition at boot. Not used by QEMU platforms.*/
+#define PLAT_SPM_COOKIE_0		ULL(0)
+#define PLAT_SPM_COOKIE_1		ULL(0)
+#endif
+
+#define QEMU_PRI_BITS		2
+#define PLAT_SP_PRI		0x20
+
-#endif /* __PLATFORM_DEF_H__ */
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk
index 09856d6..3aa7cbe 100644
--- a/plat/qemu/qemu_sbsa/platform.mk
+++ b/plat/qemu/qemu_sbsa/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, Linaro Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2020, Linaro Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,6 +8,12 @@
 
 include lib/libfdt/libfdt.mk
 
+ifeq (${SPM_MM},1)
+NEED_BL32		:=	yes
+EL3_EXCEPTION_HANDLING	:=	1
+GICV2_G0_FOR_EL3	:=	1
+endif
+
 # Enable new version of image loading on QEMU platforms
 LOAD_IMAGE_V2		:=	1
 
@@ -80,6 +86,9 @@
 				${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S	\
 				${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c	\
 				${QEMU_GIC_SOURCES}
+ifeq (${SPM_MM},1)
+	BL31_SOURCES		+=	${PLAT_QEMU_COMMON_PATH}/qemu_spm.c
+endif
 
 SEPARATE_CODE_AND_RODATA	:= 1
 ENABLE_STACK_PROTECTOR		:= 0