feat(plat/arm): add GPT initialization code for Arm platforms

When RME is enabled, during configuration of the TrustZone controller,
Root regions are initially configured as Secure regions, and Realm
regions as Non-secure regions. Then later these regions are configured
as Root and Realm regions respectively in the GPT. According to the RME
architecture reference manual, Root firmware must ensure that Granule
Protection Check is enabled before enabling any stage of translation.
Therefore initializations are done as follows when RME is enabled :

Initialize/enable the TrustZone controller (plat_arm_security_setup) -->
Initialize/enable GPC (arm_bl2_plat_gpt_setup) -->
enable MMU (enable_mmu_el3)

Signed-off-by: Zelalem Aweke <zelalem.aweke@arm.com>
Change-Id: I91094e8259079437bee02de1f65edb9ad51e43cf
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 758a061..ef37206 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -9,6 +9,7 @@
 
 #include <platform_def.h>
 
+#include <arch_features.h>
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
@@ -17,10 +18,12 @@
 #include <drivers/partition/partition.h>
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/gpt/gpt.h>
 #ifdef SPD_opteed
 #include <lib/optee_utils.h>
 #endif
 #include <lib/utils.h>
+#include <plat/arm/common/arm_pas_def.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
@@ -111,8 +114,10 @@
  */
 void arm_bl2_platform_setup(void)
 {
+#if !ENABLE_RME
 	/* Initialize the secure environment */
 	plat_arm_security_setup();
+#endif
 
 #if defined(PLAT_ARM_MEM_PROT_ADDR)
 	arm_nor_psci_do_static_mem_protect();
@@ -123,10 +128,48 @@
 {
 	arm_bl2_platform_setup();
 }
+
+#if ENABLE_RME
+static void arm_bl2_plat_gpt_setup(void)
+{
+	/*
+	 * The GPT library might modify the gpt regions structure to optimize
+	 * the layout, so the array cannot be constant.
+	 */
+	pas_region_t pas_regions[] = {
+		ARM_PAS_GPI_ANY,
+		ARM_PAS_KERNEL,
+		ARM_PAS_TZC,
+		ARM_PAS_REALM,
+		ARM_PAS_EL3_DRAM,
+		ARM_PAS_GPTS
+	};
+
+	gpt_init_params_t gpt_params = {
+		PLATFORM_PGS,
+		PLATFORM_PPS,
+		PLATFORM_L0GPTSZ,
+		pas_regions,
+		(unsigned int)(sizeof(pas_regions)/sizeof(pas_region_t)),
+		ARM_L0_GPT_ADDR_BASE, ARM_L0_GPT_SIZE,
+		ARM_L1_GPT_ADDR_BASE, ARM_L1_GPT_SIZE
+	};
+
+	/* Initialise the global granule tables */
+	INFO("Enabling Granule Protection Checks\n");
+	if (gpt_init(&gpt_params) < 0) {
+		panic();
+	}
+
+	gpt_enable();
+}
+#endif /* ENABLE_RME */
 
 /*******************************************************************************
- * Perform the very early platform specific architectural setup here. At the
- * moment this is only initializes the mmu in a quick and dirty way.
+ * Perform the very early platform specific architectural setup here.
+ * When RME is enabled the secure environment is initialised before
+ * initialising and enabling Granule Protection.
+ * This function initialises the MMU in a quick and dirty way.
  ******************************************************************************/
 void arm_bl2_plat_arch_setup(void)
 {
@@ -155,10 +198,23 @@
 		{0}
 	};
 
+#if ENABLE_RME
+	/* Initialise the secure environment */
+	plat_arm_security_setup();
+
+	/* Initialise and enable Granule Protection */
+	arm_bl2_plat_gpt_setup();
+#endif
 	setup_page_tables(bl_regions, plat_arm_get_mmap());
 
 #ifdef __aarch64__
+#if ENABLE_RME
+	/* BL2 runs in EL3 when RME enabled. */
+	assert(get_armv9_2_feat_rme_support() != 0U);
+	enable_mmu_el3(0);
+#else
 	enable_mmu_el1(0);
+#endif
 #else
 	enable_mmu_svc_mon(0);
 #endif
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index d2bacd3..d760312 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -13,8 +13,10 @@
 #include <drivers/console.h>
 #include <lib/debugfs.h>
 #include <lib/extensions/ras.h>
+#include <lib/gpt/gpt.h>
 #include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
+#include <plat/arm/common/arm_pas_def.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
@@ -229,6 +231,28 @@
 	 */
 	bl33_image_ep_info.args.arg0 = (u_register_t)ARM_DRAM1_BASE;
 #endif
+
+#if ENABLE_RME
+	/*
+	 * Initialise Granule Protection library and enable GPC
+	 * for the primary processor. The tables were initialised
+	 * in BL2, so there is no need to provide any PAS here.
+	 */
+	gpt_init_params_t gpt_params = {
+		PLATFORM_PGS,
+		PLATFORM_PPS,
+		PLATFORM_L0GPTSZ,
+		NULL,
+		0U,
+		ARM_L0_GPT_ADDR_BASE, ARM_L0_GPT_SIZE,
+		ARM_L1_GPT_ADDR_BASE, ARM_L1_GPT_SIZE
+	};
+
+	/* Initialise the global granule tables. */
+	if (gpt_init(&gpt_params) < 0) {
+		panic();
+	}
+#endif /* ENABLE_RME */
 }
 
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,