feat(mops): enable FEAT_MOPS in EL3 when INIT_UNUSED_NS_EL2=1

FEAT_MOPS, mandatory from Arm v8.8, is typically managed in EL2.
However, in configurations where NS_EL2 is not enabled,
EL3 must set the HCRX_EL2.MSCEn bit to 1 to enable the feature.

This patch ensures FEAT_MOPS is enabled by setting HCRX_EL2.MSCEn to 1.

Change-Id: Ic4960e0cc14a44279156b79ded50de475b3b21c5
Signed-off-by: Arvind Ram Prakash <arvind.ramprakash@arm.com>
diff --git a/Makefile b/Makefile
index a286a4a..de1d71e 100644
--- a/Makefile
+++ b/Makefile
@@ -958,6 +958,10 @@
 	ifeq (${ARCH_FEATURE_AVAILABILITY},1)
                 $(error "ARCH_FEATURE_AVAILABILITY cannot be used with ARCH=aarch32")
 	endif
+	# FEAT_MOPS is only supported on AArch64
+	ifneq (${ENABLE_FEAT_MOPS},0)
+		$(error "ENABLE_FEAT_MOPS cannot be used with ARCH=aarch32")
+	endif
 endif #(ARCH=aarch32)
 
 ifneq (${ENABLE_FEAT_FPMR},0)
@@ -1284,6 +1288,7 @@
 	ENABLE_FEAT_FPMR \
 	ENABLE_FEAT_HCX \
 	ENABLE_FEAT_LS64_ACCDATA \
+	ENABLE_FEAT_MOPS \
 	ENABLE_FEAT_MTE2 \
 	ENABLE_FEAT_PAN \
 	ENABLE_FEAT_RNG \
@@ -1462,6 +1467,7 @@
 	ENABLE_FEAT_SCTLR2 \
 	ENABLE_FEAT_D128 \
 	ENABLE_FEAT_GCS \
+	ENABLE_FEAT_MOPS \
 	ENABLE_FEAT_MTE2 \
 	FEATURE_DETECTION \
 	TWED_DELAY \
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 0f6be9f..821ccb8 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -286,6 +286,12 @@
 			     ID_AA64PFR2_EL1_FPMR_MASK);
 }
 
+static unsigned int read_feat_mops_id_field(void)
+{
+	return ISOLATE_FIELD(read_id_aa64isar2_el1(), ID_AA64ISAR2_EL1_MOPS_SHIFT,
+			     ID_AA64ISAR2_EL1_MOPS_MASK);
+}
+
 /***********************************************************************************
  * TF-A supports many Arm architectural features starting from arch version
  * (8.0 till 8.7+). These features are mostly enabled through build flags. This
@@ -343,6 +349,8 @@
 	check_feature(ENABLE_FEAT_DIT, read_feat_dit_id_field(), "DIT", 1, 1);
 	check_feature(ENABLE_FEAT_AMU, read_feat_amu_id_field(),
 		      "AMUv1", 1, 2);
+	check_feature(ENABLE_FEAT_MOPS, read_feat_mops_id_field(),
+		      "MOPS", 1, 1);
 	check_feature(ENABLE_FEAT_MPAM, read_feat_mpam_version(),
 		      "MPAM", 1, 17);
 	check_feature(CTX_INCLUDE_NEVE_REGS, read_feat_nv_id_field(),
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index a8184e6..58321e7 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -378,6 +378,16 @@
    flag can take the values 0 to 2, to align  with the ``ENABLE_FEAT``
    mechanism. Default value is ``0``.
 
+- ``ENABLE_FEAT_MOPS``: Numeric value to enable FEAT_MOPS (Standardization
+   of memory operations) when INIT_UNUSED_NS_EL2=1.
+   This feature is mandatory from v8.8 and enabling of FEAT_MOPS does not
+   require any settings from EL3 as the controls are present in EL2 registers
+   (HCRX_EL2.{MSCEn,MCE2} and SCTLR_EL2.MSCEn) and in most configurations
+   we expect EL2 to be present. But in case of INIT_UNUSED_NS_EL2=1 ,
+   EL3 should configure the EL2 registers. This flag
+   can take values 0 to 2, to align with the ``ENABLE_FEAT`` mechanism.
+   Default value is ``0``.
+
 -  ``ENABLE_FEAT_MTE2``: Numeric value to enable Memory Tagging Extension2
    if the platform wants to use this feature and MTE2 is enabled at ELX.
    This flag can take values 0 to 2, to align with the ``ENABLE_FEAT``
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index fefee4a..4d26153 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -317,6 +317,10 @@
 
 /* ID_AA64ISAR2_EL1 definitions */
 #define ID_AA64ISAR2_EL1		S3_0_C0_C6_2
+#define ID_AA64ISAR2_EL1_MOPS_SHIFT	U(16)
+#define ID_AA64ISAR2_EL1_MOPS_MASK	ULL(0xf)
+
+#define MOPS_IMPLEMENTED		ULL(0x1)
 
 /* ID_AA64PFR2_EL1 definitions */
 #define ID_AA64PFR2_EL1			S3_0_C0_C4_2
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 99c2cdf..1d0a2e0 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -144,6 +144,8 @@
  * +----------------------------+
  * |	FEAT_FPMR		|
  * +----------------------------+
+ * |	FEAT_MOPS		|
+ * +----------------------------+
  */
 
 __attribute__((always_inline))
@@ -290,7 +292,10 @@
 CREATE_FEATURE_FUNCS(feat_fpmr, id_aa64pfr2_el1, ID_AA64PFR2_EL1_FPMR_SHIFT,
 		     ID_AA64PFR2_EL1_FPMR_MASK, FPMR_IMPLEMENTED,
 		     ENABLE_FEAT_FPMR)
-
+/* FEAT_MOPS */
+CREATE_FEATURE_FUNCS(feat_mops, id_aa64isar2_el1, ID_AA64ISAR2_EL1_MOPS_SHIFT,
+		     ID_AA64ISAR2_EL1_MOPS_MASK, MOPS_IMPLEMENTED,
+		     ENABLE_FEAT_MOPS)
 
 __attribute__((always_inline))
 static inline bool is_feat_sxpie_supported(void)
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index f220d8a..9b97685 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -883,6 +883,10 @@
 		sme_init_el2_unused();
 	}
 
+	if (is_feat_mops_supported()) {
+		write_hcrx_el2(read_hcrx_el2() | HCRX_EL2_MSCEn_BIT);
+	}
+
 #if ENABLE_PAUTH
 	enable_pauth_el2();
 #endif /* ENABLE_PAUTH */
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index a1db0b8..3c9e136 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -83,6 +83,7 @@
 
 # Enable the features which are mandatory from ARCH version 8.8 and upwards.
 ifeq "8.8" "$(word 1, $(sort 8.8 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
+armv8-8-a-feats		:= ENABLE_FEAT_MOPS
 # 8.7 Compliant
 armv8-8-a-feats         += ${armv8-7-a-feats}
 FEAT_LIST               := ${armv8-8-a-feats}
@@ -213,6 +214,14 @@
 ENABLE_FEAT_HCX			?=	0
 
 #----
+# 8.8
+#----
+
+# Flag to enable FEAT_MOPS (Standardization of Memory operations)
+# when INIT_UNUSED_NS_EL2 = 1
+ENABLE_FEAT_MOPS		?=	0
+
+#----
 # 8.9
 #----
 
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 08fbfee..241003a 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -58,6 +58,7 @@
       ENABLE_TRBE_FOR_NS	:= 2
       ENABLE_FEAT_D128		:= 2
       ENABLE_FEAT_FPMR		:= 2
+      ENABLE_FEAT_MOPS		:= 2
 endif
 
 ENABLE_SYS_REG_TRACE_FOR_NS	:= 2