feat(fpmr): disable FPMR trap

This patch enables support of FEAT_FPMR by enabling access
to FPMR register. It achieves it by setting the EnFPM bit of
SCR_EL3. This feature is currently enabled for NS world only.

Reference:
https://developer.arm.com/documentation/109697/2024_09/
Feature-descriptions/The-Armv9-5-architecture-extension?lang=en

Change-Id: I580c409b9b22f8ead0737502280fb9093a3d5dd2
Signed-off-by: Arvind Ram Prakash <arvind.ramprakash@arm.com>
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 4ae1306..f963ed1 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -28,6 +28,7 @@
 #include <lib/extensions/brbe.h>
 #include <lib/extensions/debug_v8p9.h>
 #include <lib/extensions/fgt2.h>
+#include <lib/extensions/fpmr.h>
 #include <lib/extensions/mpam.h>
 #include <lib/extensions/pmuv3.h>
 #include <lib/extensions/sme.h>
@@ -291,6 +292,13 @@
 		scr_el3 |= SCR_D128En_BIT;
 	}
 
+	if (is_feat_fpmr_supported()) {
+		/* Set the EnFPM bit in SCR_EL3 to enable access to FPMR
+		 * register.
+		 */
+		scr_el3 |= SCR_EnFPM_BIT;
+	}
+
 	write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
 
 	/* Initialize EL2 context registers */
@@ -714,6 +722,10 @@
 	if (is_feat_mpam_supported()) {
 		mpam_enable_per_world(&per_world_context[CPU_CONTEXT_NS]);
 	}
+
+	if (is_feat_fpmr_supported()) {
+		fpmr_enable_per_world(&per_world_context[CPU_CONTEXT_NS]);
+	}
 }
 #endif /* IMAGE_BL31 */
 
diff --git a/lib/extensions/fpmr/fpmr.c b/lib/extensions/fpmr/fpmr.c
new file mode 100644
index 0000000..8e37e7a
--- /dev/null
+++ b/lib/extensions/fpmr/fpmr.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <lib/extensions/fpmr.h>
+
+void fpmr_enable_per_world(per_world_context_t *per_world_ctx)
+{
+	u_register_t reg;
+
+	/* Disable Floating point Trap in CPTR_EL3. */
+	reg = per_world_ctx->ctx_cptr_el3;
+	reg &= ~TFP_BIT;
+	per_world_ctx->ctx_cptr_el3 = reg;
+}