fix(amu): fault handling on EL2 context switch

The HAFGRTR_EL2 register is UNDEFINED unless the CPU supports both
FEAT_FGT and FEAT_AMUv1. FEAT_FGT is mandatory for v8.6-A and upwards,
but FEAT_AMUv1 is optional (from v8.4-A upwards), and as such any
8.6-A cores today without support for FEAT_AMUv1 will trigger an
undefined instruction exception on accessing this register.

Currently ARM_ARCH_AT_LEAST macro has been used to associate with an
architecture extension allowing to access HAFGRTR_EL2 register. This
condition should be replaced with macros specific to individual
features. This patch adds a new set of macros "ENABLE_FEAT_FGT,
ENABLE_FEAT_AMUv1, ENABLE_FEAT_ECV" under build options to provide
controlled access to the HAFGRTR_EL2 register.

Further to ensure that the the build options passed comply
with the given hardware implementation, a feature detection mechanism,
checking whether build options match with the architecture is required
at bootime. This will be implemented and pushed later in a separate
patch.

Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
Change-Id: Ie390f4babe233b8b09455290277edbddecd33ead
diff --git a/Makefile b/Makefile
index 73007b4..32eb501 100644
--- a/Makefile
+++ b/Makefile
@@ -267,6 +267,16 @@
 ENABLE_FEAT_SB		= 	1
 endif
 
+# Determine and enable FEAT_FGT to access HDFGRTR_EL2 register for v8.6 and higher versions.
+ifeq "8.6" "$(word 1, $(sort 8.6 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
+ENABLE_FEAT_FGT		=	1
+endif
+
+# Determine and enable FEAT_ECV to access CNTPOFF_EL2 register for v8.6 and higher versions.
+ifeq "8.6" "$(word 1, $(sort 8.6 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
+ENABLE_FEAT_ECV		=	1
+endif
+
 ifneq ($(findstring armclang,$(notdir $(CC))),)
 TF_CFLAGS_aarch32	=	-target arm-arm-none-eabi $(march32-directive)
 TF_CFLAGS_aarch64	=	-target aarch64-arm-none-eabi $(march64-directive)
@@ -1041,6 +1051,9 @@
         ENABLE_FEAT_HCX \
         ENABLE_MPMM \
         ENABLE_MPMM_FCONF \
+        ENABLE_FEAT_FGT \
+        ENABLE_FEAT_AMUv1 \
+        ENABLE_FEAT_ECV \
 )))
 
 $(eval $(call assert_numerics,\
@@ -1153,6 +1166,9 @@
         ENABLE_FEAT_HCX \
         ENABLE_MPMM \
         ENABLE_MPMM_FCONF \
+        ENABLE_FEAT_FGT \
+        ENABLE_FEAT_AMUv1 \
+        ENABLE_FEAT_ECV \
 )))
 
 ifeq (${SANITIZE_UB},trap)
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 698e208..512d196 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -207,8 +207,8 @@
 #define CTX_MPAMVPMV_EL2	U(0x158)
 
 // Starting with Armv8.6
-#define CTX_HAFGRTR_EL2		U(0x160)
-#define CTX_HDFGRTR_EL2		U(0x168)
+#define CTX_HDFGRTR_EL2		U(0x160)
+#define CTX_HAFGRTR_EL2		U(0x168)
 #define CTX_HDFGWTR_EL2		U(0x170)
 #define CTX_HFGITR_EL2		U(0x178)
 #define CTX_HFGRTR_EL2		U(0x180)
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index e270ad0..c9035e8 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -145,11 +145,14 @@
 	stp	x11, x12, [x0, #CTX_MPAMVPM7_EL2]
 #endif
 
-#if ARM_ARCH_AT_LEAST(8, 6)
-	mrs	x13, HAFGRTR_EL2
-	mrs	x14, HDFGRTR_EL2
-	stp	x13, x14, [x0, #CTX_HAFGRTR_EL2]
-
+#if ENABLE_FEAT_FGT
+	mrs	x13, HDFGRTR_EL2
+#if ENABLE_FEAT_AMUv1
+   	mrs	x14, HAFGRTR_EL2
+   	stp	x13, x14, [x0, #CTX_HDFGRTR_EL2]
+#else
+   	str	x13, [x0, #CTX_HDFGRTR_EL2]
+#endif
 	mrs	x15, HDFGWTR_EL2
 	mrs	x16, HFGITR_EL2
 	stp	x15, x16, [x0, #CTX_HDFGWTR_EL2]
@@ -157,7 +160,9 @@
 	mrs	x9, HFGRTR_EL2
 	mrs	x10, HFGWTR_EL2
 	stp	x9, x10, [x0, #CTX_HFGRTR_EL2]
+#endif
 
+#if ENABLE_FEAT_ECV
 	mrs	x11, CNTPOFF_EL2
 	str	x11, [x0, #CTX_CNTPOFF_EL2]
 #endif
@@ -319,10 +324,14 @@
 	msr	MPAMVPMV_EL2, x12
 #endif
 
-#if ARM_ARCH_AT_LEAST(8, 6)
-	ldp	x13, x14, [x0, #CTX_HAFGRTR_EL2]
-	msr	HAFGRTR_EL2, x13
-	msr	HDFGRTR_EL2, x14
+#if ENABLE_FEAT_FGT
+#if ENABLE_FEAT_AMUv1
+	ldp	x13, x14, [x0, #CTX_HDFGRTR_EL2]
+	msr	HAFGRTR_EL2, x14
+#else
+	ldr	x13, [x0, #CTX_HDFGRTR_EL2]
+#endif
+	msr	HDFGRTR_EL2, x13
 
 	ldp	x15, x16, [x0, #CTX_HDFGWTR_EL2]
 	msr	HDFGWTR_EL2, x15
@@ -331,7 +340,9 @@
 	ldp	x9, x10, [x0, #CTX_HFGRTR_EL2]
 	msr	HFGRTR_EL2, x9
 	msr	HFGWTR_EL2, x10
+#endif
 
+#if ENABLE_FEAT_ECV
 	ldr	x11, [x0, #CTX_CNTPOFF_EL2]
 	msr	CNTPOFF_EL2, x11
 #endif
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index e88148f..595ba7b 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -136,6 +136,9 @@
 # Flag to enable access to the HCRX_EL2 register by setting SCR_EL3.HXEn.
 ENABLE_FEAT_HCX			:= 0
 
+# Flag to enable access to the HAFGRTR_EL2 register
+ENABLE_FEAT_AMUv1		:= 0
+
 # By default BL31 encryption disabled
 ENCRYPT_BL31			:= 0