refactor(cm): reset the cptr_el3 before perworld context setup

Currently, the registers which are maintained per-world, does not
take into account the reset value while configuring the context for
the respective world.
This leads to an issue, wherein the register retains the same value
across world switch, which is an error.

This patch addresses this problem, by configuring the register
(cptr_el3) precisely according to the world, the cpu is in
execution via resetting it before initializing the world specific context.

Change-Id: I592d82af373155fca67eed109c199341c305f0b9
Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 47d91de..235b2cf 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -341,9 +341,9 @@
 /*******************************************************************************
  * Registers initialised in a per-world context.
  ******************************************************************************/
-#define CTX_CPTR_EL3		U(0x0)
-#define CTX_ZCR_EL3		U(0x8)
-#define CTX_GLOBAL_EL3STATE_END	U(0x10)
+#define CTX_CPTR_EL3			U(0x0)
+#define CTX_ZCR_EL3			U(0x8)
+#define CTX_PERWORLD_EL3STATE_END	U(0x10)
 
 #ifndef __ASSEMBLER__
 
diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h
index b2bdaf5..f631125 100644
--- a/include/lib/el3_runtime/context_mgmt.h
+++ b/include/lib/el3_runtime/context_mgmt.h
@@ -40,7 +40,9 @@
 #if IMAGE_BL31
 void cm_manage_extensions_el3(void);
 void manage_extensions_nonsecure_per_world(void);
+void cm_el3_arch_init_per_world(per_world_context_t *per_world_ctx);
 #endif
+
 #if CTX_INCLUDE_EL2_REGS
 void cm_el2_sysregs_context_save(uint32_t security_state);
 void cm_el2_sysregs_context_restore(uint32_t security_state);
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 631094f..18bdca8 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -581,7 +581,7 @@
 .macro get_per_world_context _reg:req
 	ldr 	x10, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
 	get_security_state x9, x10
-	mov_imm	x10, (CTX_GLOBAL_EL3STATE_END - CTX_CPTR_EL3)
+	mov_imm	x10, (CTX_PERWORLD_EL3STATE_END - CTX_CPTR_EL3)
 	mul	x9, x9, x10
 	adrp	x10, per_world_context
 	add	x10, x10, :lo12:per_world_context
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index fdd1388..a0212c6 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -600,6 +600,28 @@
 }
 #endif /* IMAGE_BL31 */
 
+/******************************************************************************
+ * Function to initialise the registers with the RESET values in the context
+ * memory, which are maintained per world.
+ ******************************************************************************/
+#if IMAGE_BL31
+void cm_el3_arch_init_per_world(per_world_context_t *per_world_ctx)
+{
+	/*
+	 * Initialise CPTR_EL3, setting all fields rather than relying on hw.
+	 *
+	 * CPTR_EL3.TFP: Set to zero so that accesses to the V- or Z- registers
+	 *  by Advanced SIMD, floating-point or SVE instructions (if
+	 *  implemented) do not trap to EL3.
+	 *
+	 * CPTR_EL3.TCPAC: Set to zero so that accesses to CPACR_EL1,
+	 *  CPTR_EL2,CPACR, or HCPTR do not trap to EL3.
+	 */
+	uint64_t cptr_el3 = CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TFP_BIT);
+	per_world_ctx->ctx_cptr_el3 = cptr_el3;
+}
+#endif /* IMAGE_BL31 */
+
 /*******************************************************************************
  * Initialise per_world_context for Non-Secure world.
  * This function enables the architecture extensions, which have same value
@@ -608,6 +630,8 @@
 #if IMAGE_BL31
 void manage_extensions_nonsecure_per_world(void)
 {
+	cm_el3_arch_init_per_world(&per_world_context[CPU_CONTEXT_NS]);
+
 	if (is_feat_sme_supported()) {
 		sme_enable_per_world(&per_world_context[CPU_CONTEXT_NS]);
 	}
@@ -631,10 +655,11 @@
  * This function enables the architecture extensions, which have same value
  * across the cores for the secure world.
  ******************************************************************************/
-
 static void manage_extensions_secure_per_world(void)
 {
 #if IMAGE_BL31
+	cm_el3_arch_init_per_world(&per_world_context[CPU_CONTEXT_SECURE]);
+
 	if (is_feat_sme_supported()) {
 
 		if (ENABLE_SME_FOR_SWD) {
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 8b78b13..4ea074f 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -134,6 +134,8 @@
 
 static void manage_extensions_realm_per_world(void)
 {
+	cm_el3_arch_init_per_world(&per_world_context[CPU_CONTEXT_REALM]);
+
 	if (is_feat_sve_supported()) {
 	/*
 	 * Enable SVE and FPU in realm context when it is enabled for NS.