feat(cpufeat): add support for FEAT_FGWTE3

Enable write traps for key EL3 system registers as per FEAT_FGWTE3,
ensuring their values remain unchanged after boot.

Excluded Registers:
MDCR_EL3 and MPAM3_EL3: Not trapped as they are part of the EL3 context.
SCTLR_EL3: Not trapped since it is overwritten during
powerdown sequence(Included when HW_ASSISTED_COHERENCY=1)

TPIDR_EL3: Excluded due to its use in crash reporting(It is included
when CRASH_REPORTING=0)

Reference:
https://developer.arm.com/documentation/ddi0601/2025-06/AArch64-Registers/FGWTE3-EL3--Fine-Grained-Write-Traps-EL3

Change-Id: Idcb32aaac7d65a0b0e5c90571af00e01a4e9edb1
Signed-off-by: Arvind Ram Prakash <arvind.ramprakash@arm.com>
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 5506cb1..ee18309 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -443,6 +443,13 @@
 #define ID_AA64MMFR3_EL1_TCRX_SHIFT		U(0)
 #define ID_AA64MMFR3_EL1_TCRX_MASK		ULL(0xf)
 
+/* ID_AA64MMFR4_EL1 definitions */
+#define ID_AA64MMFR4_EL1			S3_0_C0_C7_4
+
+#define ID_AA64MMFR4_EL1_FGWTE3_SHIFT		U(16)
+#define ID_AA64MMFR4_EL1_FGWTE3_MASK		ULL(0xf)
+#define FGWTE3_IMPLEMENTED			ULL(0x1)
+
 /* ID_AA64PFR1_EL1 definitions */
 
 #define ID_AA64PFR1_EL1_BT_SHIFT	U(0)
@@ -1622,4 +1629,68 @@
 #define MECIDR_EL2_MECIDWidthm1_MASK	U(0xf)
 #define MECIDR_EL2_MECIDWidthm1_SHIFT	U(0)
 
+/******************************************************************************
+ * FEAT_FGWTE3 - Fine Grained Write Trap
+ ******************************************************************************/
+#define FGWTE3_EL3					S3_6_C1_C1_5
+
+/* FGWTE3_EL3 Defintions */
+#define FGWTE3_EL3_VBAR_EL3_BIT				(U(1) << 21)
+#define FGWTE3_EL3_TTBR0_EL3_BIT			(U(1) << 20)
+#define FGWTE3_EL3_TPIDR_EL3_BIT			(U(1) << 19)
+#define FGWTE3_EL3_TCR_EL3_BIT				(U(1) << 18)
+#define FGWTE3_EL3_SPMROOTCR_EL3_BIT			(U(1) << 17)
+#define FGWTE3_EL3_SCTLR2_EL3_BIT			(U(1) << 16)
+#define FGWTE3_EL3_SCTLR_EL3_BIT			(U(1) << 15)
+#define FGWTE3_EL3_PIR_EL3_BIT				(U(1) << 14)
+#define FGWTE3_EL3_MECID_RL_A_EL3_BIT			(U(1) << 12)
+#define FGWTE3_EL3_MAIR2_EL3_BIT			(U(1) << 10)
+#define FGWTE3_EL3_MAIR_EL3_BIT				(U(1) << 9)
+#define FGWTE3_EL3_GPTBR_EL3_BIT			(U(1) << 8)
+#define FGWTE3_EL3_GPCCR_EL3_BIT			(U(1) << 7)
+#define FGWTE3_EL3_GCSPR_EL3_BIT			(U(1) << 6)
+#define FGWTE3_EL3_GCSCR_EL3_BIT			(U(1) << 5)
+#define FGWTE3_EL3_AMAIR2_EL3_BIT			(U(1) << 4)
+#define FGWTE3_EL3_AMAIR_EL3_BIT			(U(1) << 3)
+#define FGWTE3_EL3_AFSR1_EL3_BIT			(U(1) << 2)
+#define FGWTE3_EL3_AFSR0_EL3_BIT			(U(1) << 1)
+#define FGWTE3_EL3_ACTLR_EL3_BIT			(U(1) << 0)
+
+#define FGWTE3_EL3_EARLY_INIT_VAL			(	\
+		FGWTE3_EL3_VBAR_EL3_BIT 		| 	\
+		FGWTE3_EL3_TTBR0_EL3_BIT 		|	\
+		FGWTE3_EL3_SPMROOTCR_EL3_BIT		|	\
+		FGWTE3_EL3_SCTLR2_EL3_BIT		|	\
+		FGWTE3_EL3_PIR_EL3_BIT			|	\
+		FGWTE3_EL3_MECID_RL_A_EL3_BIT		|	\
+		FGWTE3_EL3_MAIR2_EL3_BIT		|	\
+		FGWTE3_EL3_MAIR_EL3_BIT			|	\
+		FGWTE3_EL3_GPTBR_EL3_BIT		|	\
+		FGWTE3_EL3_GPCCR_EL3_BIT		|	\
+		FGWTE3_EL3_GCSPR_EL3_BIT		|	\
+		FGWTE3_EL3_GCSCR_EL3_BIT		|	\
+		FGWTE3_EL3_AMAIR2_EL3_BIT		|	\
+		FGWTE3_EL3_AMAIR_EL3_BIT		|	\
+		FGWTE3_EL3_AFSR1_EL3_BIT		|	\
+		FGWTE3_EL3_AFSR0_EL3_BIT)
+
+#if HW_ASSISTED_COHERENCY
+#define FGWTE3_EL3_LATE_INIT_SCTLR_EL3_BIT   FGWTE3_EL3_SCTLR_EL3_BIT |
+#else
+#define FGWTE3_EL3_LATE_INIT_SCTLR_EL3_BIT
+#endif
+
+#if !(CRASH_REPORTING)
+#define FGWTE3_EL3_LATE_INIT_TPIDR_EL3_BIT	FGWTE3_EL3_TPIDR_EL3_BIT |
+#else
+#define FGWTE3_EL3_LATE_INIT_TPIDR_EL3_BIT
+#endif
+
+#define FGWTE3_EL3_LATE_INIT_VAL			(	\
+		FGWTE3_EL3_EARLY_INIT_VAL		|	\
+		FGWTE3_EL3_LATE_INIT_SCTLR_EL3_BIT		\
+		FGWTE3_EL3_LATE_INIT_TPIDR_EL3_BIT		\
+		FGWTE3_EL3_TCR_EL3_BIT			|	\
+		FGWTE3_EL3_ACTLR_EL3_BIT)
+
 #endif /* ARCH_H */
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 77355cd..ddb5e23 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -148,6 +148,8 @@
  * +----------------------------+
  * |	FEAT_PAUTH_LR		|
  * +----------------------------+
+ * |    FEAT_FGWTE3             |
+ * +----------------------------+
  */
 
 __attribute__((always_inline))
@@ -271,6 +273,11 @@
 CREATE_FEATURE_FUNCS(feat_fgt2, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_FGT_SHIFT,
 		     ID_AA64MMFR0_EL1_FGT_MASK, FGT2_IMPLEMENTED, ENABLE_FEAT_FGT2)
 
+/* FEAT_FGWTE3: Fine-grained write traps EL3 */
+CREATE_FEATURE_FUNCS(feat_fgwte3, id_aa64mmfr4_el1, ID_AA64MMFR4_EL1_FGWTE3_SHIFT,
+		     ID_AA64MMFR4_EL1_FGWTE3_MASK, FGWTE3_IMPLEMENTED,
+		     ENABLE_FEAT_FGWTE3)
+
 /* FEAT_ECV: Enhanced Counter Virtualization */
 CREATE_FEATURE_FUNCS(feat_ecv, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_ECV_SHIFT,
 		     ID_AA64MMFR0_EL1_ECV_MASK, 1U, ENABLE_FEAT_ECV)
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index a59c531..b0ad93b 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -770,6 +770,11 @@
 /* FEAT_MEC Registers */
 DEFINE_RENAME_SYSREG_READ_FUNC(mecidr_el2, MECIDR_EL2)
 
+DEFINE_RENAME_IDREG_READ_FUNC(id_aa64mmfr4_el1, ID_AA64MMFR4_EL1)
+
+/* FEAT_FGWTE3 Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(fgwte3_el3, FGWTE3_EL3)
+
 #define IS_IN_EL(x) \
 	(GET_EL(read_CurrentEl()) == MODE_EL##x)