feat(rme): add GPT Library

This patch introduces the Granule Protection Table (GPT)
library code. This implementation will be updated later to
be more flexible, as the current implementation is very rigid.

Signed-off-by: Zelalem Aweke <zelalem.aweke@arm.com>
Change-Id: I3af824a28c6e9a5d36459c0c51d2d9bebfba1505
diff --git a/include/lib/gpt/gpt.h b/include/lib/gpt/gpt.h
new file mode 100644
index 0000000..89d3017
--- /dev/null
+++ b/include/lib/gpt/gpt.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPT_H
+#define GPT_H
+
+#include <stdint.h>
+
+#include <arch.h>
+
+#include "gpt_defs.h"
+
+#define GPT_DESC_ATTRS(_type, _gpi)		\
+	((((_type) & PAS_REG_DESC_TYPE_MASK)	\
+	  << PAS_REG_DESC_TYPE_SHIFT) |		\
+	(((_gpi) & PAS_REG_GPI_MASK)		\
+	 << PAS_REG_GPI_SHIFT))
+
+/*
+ * Macro to create a GPT entry for this PAS range either as a L0 block
+ * descriptor or L1 table descriptor depending upon the size of the range.
+ */
+#define MAP_GPT_REGION(_pa, _sz, _gpi)					\
+	{								\
+		.base_pa = (_pa),					\
+		.size = (_sz),						\
+		.attrs = GPT_DESC_ATTRS(PAS_REG_DESC_TYPE_ANY, (_gpi)),	\
+	}
+
+/*
+ * Special macro to create a L1 table descriptor at L0 for a 1GB region as
+ * opposed to creating a block mapping by default.
+ */
+#define MAP_GPT_REGION_TBL(_pa, _sz, _gpi)				\
+	{								\
+		.base_pa = (_pa),					\
+		.size = (_sz),						\
+		.attrs = GPT_DESC_ATTRS(PAS_REG_DESC_TYPE_TBL, (_gpi)),	\
+	}
+
+/*
+ * Structure for specifying a Granule range and its properties
+ */
+typedef struct pas_region {
+	unsigned long long	base_pa;	/**< Base address for PAS. */
+	size_t			size;		/**< Size of the PAS. */
+	unsigned int		attrs;		/**< PAS GPI and entry type. */
+} pas_region_t;
+
+/*
+ * Structure to initialise the Granule Protection Tables.
+ */
+typedef struct gpt_init_params {
+	unsigned int pgs;	/**< Address Width of Phisical Granule Size. */
+	unsigned int pps;	/**< Protected Physical Address Size.	     */
+	unsigned int l0gptsz;	/**< Granule size on L0 table entry.	     */
+	pas_region_t *pas_regions; /**< PAS regions to protect.		     */
+	unsigned int pas_count;	/**< Number of PAS regions to initialise.    */
+	uintptr_t l0_mem_base;	/**< L0 Table base address.		     */
+	size_t l0_mem_size;	/**< Size of memory reserved for L0 tables.  */
+	uintptr_t l1_mem_base;	/**< L1 Table base address.		     */
+	size_t l1_mem_size;	/**< Size of memory reserved for L1 tables.  */
+} gpt_init_params_t;
+
+/** @brief Initialise the Granule Protection tables.
+ */
+int gpt_init(gpt_init_params_t *params);
+
+/** @brief Enable the Granule Protection Checks.
+ */
+void gpt_enable(void);
+
+/** @brief Disable the Granule Protection Checks.
+ */
+void gpt_disable(void);
+
+/** @brief Transition a granule between security states.
+ */
+int gpt_transition_pas(uint64_t pa,
+			unsigned int src_sec_state,
+			unsigned int target_pas);
+
+#endif /* GPT_H */
diff --git a/include/lib/gpt/gpt_defs.h b/include/lib/gpt/gpt_defs.h
new file mode 100644
index 0000000..6122a12
--- /dev/null
+++ b/include/lib/gpt/gpt_defs.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPT_DEFS_H
+#define GPT_DEFS_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+
+#include "gpt.h"
+
+/* GPI values */
+#define GPI_NO_ACCESS			U(0x0)
+#define GPI_SECURE			U(0x8)
+#define GPI_NS				U(0x9)
+#define GPI_ROOT			U(0xa)
+#define GPI_REALM			U(0xb)
+#define GPI_ANY				U(0xf)
+#define GPI_VAL_MASK			ULL(0xf)
+
+/* GPT descriptor bit definitions */
+#define GPT_L1_INDEX_MASK		ULL(0xf)
+#define GPT_L1_INDEX_SHIFT		ULL(0x0)
+
+#define GPT_TBL_DESC			ULL(0x3)
+#define GPT_BLK_DESC			ULL(0x1)
+
+#define GPT_TBL_DESC_ADDR_SHIFT		ULL(12)
+#define GPT_TBL_DESC_ADDR_MASK		(((ULL(1) <<			      \
+					 (51 - GPT_TBL_DESC_ADDR_SHIFT)) - 1) \
+					 << GPT_TBL_DESC_ADDR_SHIFT)
+
+#define GPT_BLOCK_DESC_GPI_VAL_SHIFT	ULL(4)
+
+/* Each descriptor is 8 bytes long. */
+#define GPT_DESC_SIZE			ULL(8)
+
+#define PPS_MAX_VAL			PSTCR_EL3_PPS_4PB
+#define PPS_NUM_1GB_ENTRIES		ULL(1024)
+#define PGS_4K_1GB_L1_TABLE_SZ		(U(2) << 17)
+
+/* 2 << LOG2_8K = Bytes in 8K */
+#define LOG2_8K                         U(13)
+
+#define GPT_L1_SIZE			ULL(0x40000)		/* 256K */
+#define SZ_1G				(ULL(0x1) << 30)	/* 1GB */
+
+#define GPT_MIN_PGS_SHIFT		U(12)			/* 4K */
+
+#define L1_GPT_INDEX_MASK		U(0x3fffffff)
+#define GPT_GRAN_DESC_NUM_GPIS		U(4)
+
+#define PAS_REG_GPI_SHIFT		U(0)
+#define PAS_REG_GPI_MASK		U(0xf)
+
+/* .attrs field definitions */
+#define PAS_REG_DESC_TYPE_ANY		U(0)
+#define PAS_REG_DESC_TYPE_BLK		U(1)
+#define PAS_REG_DESC_TYPE_TBL		U(2)
+#define PAS_REG_DESC_TYPE_SHIFT		U(4)
+#define PAS_REG_DESC_TYPE_MASK		U(0x3)
+#define PAS_REG_DESC_TYPE(_attrs)	(((_attrs)			\
+					  >> PAS_REG_DESC_TYPE_SHIFT)	\
+					 & PAS_REG_DESC_TYPE_MASK)
+
+#define PAS_REG_GPI(_attrs)		(((_attrs)			\
+					  >> PAS_REG_GPI_SHIFT)		\
+					 & PAS_REG_GPI_MASK)
+
+#define SZ_1G_MASK			(SZ_1G - U(1))
+#define IS_1GB_ALIGNED(addr)		(((addr) & SZ_1G_MASK) == U(0))
+
+#endif /* GPT_DEFS */