Merge "feat(pie/por): support permission indirection and overlay" into integration
diff --git a/Makefile b/Makefile
index 4b60863..98e448f 100644
--- a/Makefile
+++ b/Makefile
@@ -1185,6 +1185,10 @@
         ENABLE_FEAT_RNG_TRAP \
         ENABLE_FEAT_SEL2 \
         ENABLE_FEAT_TCR2 \
+        ENABLE_FEAT_S2PIE \
+        ENABLE_FEAT_S1PIE \
+        ENABLE_FEAT_S2POE \
+        ENABLE_FEAT_S1POE \
         ENABLE_FEAT_VHE \
         ENABLE_MPAM_FOR_LOWER_ELS \
         ENABLE_RME \
@@ -1321,6 +1325,10 @@
         ENABLE_FEAT_CSV2_2 \
         ENABLE_FEAT_PAN \
         ENABLE_FEAT_TCR2 \
+        ENABLE_FEAT_S2PIE \
+        ENABLE_FEAT_S1PIE \
+        ENABLE_FEAT_S2POE \
+        ENABLE_FEAT_S1POE \
         FEATURE_DETECTION \
         TWED_DELAY \
         ENABLE_FEAT_TWED \
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 9394304..1582b9d 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -210,6 +210,14 @@
 	/* v8.9 features */
 	check_feature(ENABLE_FEAT_TCR2, read_feat_tcrx_id_field(),
 		      "TCR2", 1, 1);
+	check_feature(ENABLE_FEAT_S2PIE, read_feat_s2pie_id_field(),
+		      "S2PIE", 1, 1);
+	check_feature(ENABLE_FEAT_S1PIE, read_feat_s1pie_id_field(),
+		      "S1PIE", 1, 1);
+	check_feature(ENABLE_FEAT_S2POE, read_feat_s2poe_id_field(),
+		      "S2POE", 1, 1);
+	check_feature(ENABLE_FEAT_S1POE, read_feat_s1poe_id_field(),
+		      "S1POE", 1, 1);
 
 	/* v9.0 features */
 	check_feature(ENABLE_BRBE_FOR_NS, read_feat_brbe_id_field(),
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index e078e47..03be786 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -354,6 +354,26 @@
    flag can take the values 0 to 2, to align  with the ``FEATURE_DETECTION``
    mechanism. Default value is ``0``.
 
+-  ``ENABLE_FEAT_S2PIE``: Numeric value to enable support for FEAT_S2PIE
+   at EL2 and below, and context switch relevant registers.  This flag
+   can take the values 0 to 2, to align  with the ``FEATURE_DETECTION``
+   mechanism. Default value is ``0``.
+
+-  ``ENABLE_FEAT_S1PIE``: Numeric value to enable support for FEAT_S1PIE
+   at EL2 and below, and context switch relevant registers.  This flag
+   can take the values 0 to 2, to align  with the ``FEATURE_DETECTION``
+   mechanism. Default value is ``0``.
+
+-  ``ENABLE_FEAT_S2POE``: Numeric value to enable support for FEAT_S2POE
+   at EL2 and below, and context switch relevant registers.  This flag
+   can take the values 0 to 2, to align  with the ``FEATURE_DETECTION``
+   mechanism. Default value is ``0``.
+
+-  ``ENABLE_FEAT_S1POE``: Numeric value to enable support for FEAT_S1POE
+   at EL2 and below, and context switch relevant registers.  This flag
+   can take the values 0 to 2, to align  with the ``FEATURE_DETECTION``
+   mechanism. Default value is ``0``.
+
 -  ``ENABLE_LTO``: Boolean option to enable Link Time Optimization (LTO)
    support in GCC for TF-A. This option is currently only supported for
    AArch64. Default is 0.
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index dee7fdc..9b55658 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -355,6 +355,18 @@
 /* ID_AA64MMFR3_EL1 definitions */
 #define ID_AA64MMFR3_EL1			S3_0_C0_C7_3
 
+#define ID_AA64MMFR3_EL1_S2POE_SHIFT		U(20)
+#define ID_AA64MMFR3_EL1_S2POE_MASK		ULL(0xf)
+
+#define ID_AA64MMFR3_EL1_S1POE_SHIFT		U(16)
+#define ID_AA64MMFR3_EL1_S1POE_MASK		ULL(0xf)
+
+#define ID_AA64MMFR3_EL1_S2PIE_SHIFT		U(12)
+#define ID_AA64MMFR3_EL1_S2PIE_MASK		ULL(0xf)
+
+#define ID_AA64MMFR3_EL1_S1PIE_SHIFT		U(8)
+#define ID_AA64MMFR3_EL1_S1PIE_MASK		ULL(0xf)
+
 #define ID_AA64MMFR3_EL1_TCRX_SHIFT		U(0)
 #define ID_AA64MMFR3_EL1_TCRX_MASK		ULL(0xf)
 
@@ -512,6 +524,7 @@
 #define SCR_GPF_BIT		(UL(1) << 48)
 #define SCR_TWEDEL_SHIFT	U(30)
 #define SCR_TWEDEL_MASK		ULL(0xf)
+#define SCR_PIEN_BIT		(UL(1) << 45)
 #define SCR_TCR2EN_BIT		(UL(1) << 43)
 #define SCR_TRNDR_BIT		(UL(1) << 40)
 #define SCR_HXEn_BIT		(UL(1) << 38)
@@ -1321,6 +1334,15 @@
 #define TCR2_EL2		S3_4_C2_C0_3
 
 /*******************************************************************************
+ * Permission indirection and overlay
+ ******************************************************************************/
+
+#define PIRE0_EL2		S3_4_C10_C2_2
+#define PIR_EL2			S3_4_C10_C2_3
+#define POR_EL2			S3_4_C10_C2_4
+#define S2PIR_EL2		S3_4_C10_C2_5
+
+/*******************************************************************************
  * Definitions for DynamicIQ Shared Unit registers
  ******************************************************************************/
 #define CLUSTERPWRDN_EL1	S3_0_c15_c3_6
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 3ea08a6..840b117 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -234,6 +234,88 @@
 	return read_feat_tcrx_id_field() != 0U;
 }
 
+static unsigned int read_feat_s2poe_id_field(void)
+{
+	return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S2POE);
+}
+
+static inline bool is_feat_s2poe_supported(void)
+{
+	if (ENABLE_FEAT_S2POE == FEAT_STATE_DISABLED) {
+		return false;
+	}
+
+	if (ENABLE_FEAT_S2POE == FEAT_STATE_ALWAYS) {
+		return true;
+	}
+
+	return read_feat_s2poe_id_field() != 0U;
+}
+
+static unsigned int read_feat_s1poe_id_field(void)
+{
+	return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S1POE);
+}
+
+static inline bool is_feat_s1poe_supported(void)
+{
+	if (ENABLE_FEAT_S1POE == FEAT_STATE_DISABLED) {
+		return false;
+	}
+
+	if (ENABLE_FEAT_S1POE == FEAT_STATE_ALWAYS) {
+		return true;
+	}
+
+	return read_feat_s1poe_id_field() != 0U;
+}
+
+static inline bool is_feat_sxpoe_supported(void)
+{
+	return is_feat_s1poe_supported() || is_feat_s2poe_supported();
+}
+
+static unsigned int read_feat_s2pie_id_field(void)
+{
+	return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S2PIE);
+}
+
+static inline bool is_feat_s2pie_supported(void)
+{
+	if (ENABLE_FEAT_S2PIE == FEAT_STATE_DISABLED) {
+		return false;
+	}
+
+	if (ENABLE_FEAT_S2PIE == FEAT_STATE_ALWAYS) {
+		return true;
+	}
+
+	return read_feat_s2pie_id_field() != 0U;
+}
+
+static unsigned int read_feat_s1pie_id_field(void)
+{
+	return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S1PIE);
+}
+
+static inline bool is_feat_s1pie_supported(void)
+{
+	if (ENABLE_FEAT_S1PIE == FEAT_STATE_DISABLED) {
+		return false;
+	}
+
+	if (ENABLE_FEAT_S1PIE == FEAT_STATE_ALWAYS) {
+		return true;
+	}
+
+	return read_feat_s1pie_id_field() != 0U;
+}
+
+static inline bool is_feat_sxpie_supported(void)
+{
+	return is_feat_s1pie_supported() || is_feat_s2pie_supported();
+}
+
 /*******************************************************************************
  * Functions to identify the presence of the Activity Monitors Extension
  ******************************************************************************/
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 04b64be..f877f5b 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -605,6 +605,14 @@
 /* FEAT_TCR2 Register */
 DEFINE_RENAME_SYSREG_RW_FUNCS(tcr2_el2, TCR2_EL2)
 
+/* FEAT_SxPIE Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(pire0_el2, PIRE0_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(pir_el2, PIR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(s2pir_el2, S2PIR_EL2)
+
+/* FEAT_SxPOE Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(por_el2, POR_EL2)
+
 /* DynamIQ Shared Unit power management */
 DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1)
 
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index e5e7e74..a8e6d8a 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -230,9 +230,13 @@
 
 // Starting with Armv8.9
 #define CTX_TCR2_EL2            U(0x1d8)
+#define CTX_POR_EL2             U(0x1e0)
+#define CTX_PIRE0_EL2           U(0x1e8)
+#define CTX_PIR_EL2             U(0x1f0)
+#define CTX_S2PIR_EL2		U(0x1f8)
 
 /* Align to the next 16 byte boundary */
-#define CTX_EL2_SYSREGS_END	U(0x1e0)
+#define CTX_EL2_SYSREGS_END	U(0x200)
 
 #endif /* CTX_INCLUDE_EL2_REGS */
 
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 42166eb..94d5ee1 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -355,6 +355,14 @@
 	}
 
 	/*
+	 * SCR_EL3.PIEN: Enable permission indirection and overlay
+	 * registers for AArch64 if present.
+	 */
+	if (is_feat_sxpie_supported() || is_feat_sxpoe_supported()) {
+		scr_el3 |= SCR_PIEN_BIT;
+	}
+
+	/*
 	 * CPTR_EL3 was initialized out of reset, copy that value to the
 	 * context register.
 	 */
@@ -994,6 +1002,16 @@
 		if (is_feat_tcr2_supported()) {
 			write_ctx_reg(el2_sysregs_ctx, CTX_TCR2_EL2, read_tcr2_el2());
 		}
+		if (is_feat_sxpie_supported()) {
+			write_ctx_reg(el2_sysregs_ctx, CTX_PIRE0_EL2, read_pire0_el2());
+			write_ctx_reg(el2_sysregs_ctx, CTX_PIR_EL2, read_pir_el2());
+		}
+		if (is_feat_s2pie_supported()) {
+			write_ctx_reg(el2_sysregs_ctx, CTX_S2PIR_EL2, read_s2pir_el2());
+		}
+		if (is_feat_sxpoe_supported()) {
+			write_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2, read_por_el2());
+		}
 	}
 }
 
@@ -1061,6 +1079,16 @@
 		if (is_feat_tcr2_supported()) {
 			write_tcr2_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TCR2_EL2));
 		}
+		if (is_feat_sxpie_supported()) {
+			write_pire0_el2(read_ctx_reg(el2_sysregs_ctx, CTX_PIRE0_EL2));
+			write_pir_el2(read_ctx_reg(el2_sysregs_ctx, CTX_PIR_EL2));
+		}
+		if (is_feat_s2pie_supported()) {
+			write_s2pir_el2(read_ctx_reg(el2_sysregs_ctx, CTX_S2PIR_EL2));
+		}
+		if (is_feat_sxpoe_supported()) {
+			write_por_el2(read_ctx_reg(el2_sysregs_ctx, CTX_POR_EL2));
+		}
 	}
 }
 #endif /* CTX_INCLUDE_EL2_REGS */
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index af980f5..808a058 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -176,6 +176,18 @@
 # Flag to enable access to TCR2 (FEAT_TCR2)
 ENABLE_FEAT_TCR2		:= 0
 
+# Flag to enable access to Stage 2 Permission Indirection (FEAT_S2PIE)
+ENABLE_FEAT_S2PIE		:= 0
+
+# Flag to enable access to Stage 1 Permission Indirection (FEAT_S1PIE)
+ENABLE_FEAT_S1PIE		:= 0
+
+# Flag to enable access to Stage 2 Permission Overlay (FEAT_S2POE)
+ENABLE_FEAT_S2POE		:= 0
+
+# Flag to enable access to Stage 1 Permission Overlay (FEAT_S1POE)
+ENABLE_FEAT_S1POE		:= 0
+
 # By default BL31 encryption disabled
 ENCRYPT_BL31			:= 0
 
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index ab6e0bf..3fb323b 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -77,6 +77,10 @@
 ENABLE_FEAT_ECV			:= 2
 ENABLE_FEAT_FGT			:= 2
 ENABLE_FEAT_TCR2		:= 2
+ENABLE_FEAT_S2PIE		:= 2
+ENABLE_FEAT_S1PIE		:= 2
+ENABLE_FEAT_S2POE		:= 2
+ENABLE_FEAT_S1POE		:= 2
 endif
 
 # The FVP platform depends on this macro to build with correct GIC driver.