fix(cm): update gic el2 sysregs save/restore mechanism

This patch does following two changes
- Create a separate routine for saving/restoring GIC el2 system registers
- To access ICC_SRE_EL2 register there was a workaround to set
  SCR_EL3.NS before accessing it. This was required because SCR_EL3.EEL2
  was zero. But with commit f105dd5fa this bit has been set to one early
  on in booting process for a system with FEAT_SEL2 present and S-EL2
  enabled.
  However, we still need the workaround for a system which needs
  save/restore of EL2 registers without secure EL2 being enabled e.g.
  system with Non-secure and Realm world present.

Signed-off-by: Manish Pandey <manish.pandey2@arm.com>
Change-Id: I8d55c3dc6a17c4749748822d4a738912c1e13298
(cherry picked from commit 937d6fdb70cd24602fd2638a5dbd5c46d32559c1)
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 518038b..92db44b 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -794,13 +794,58 @@
 }
 
 #if CTX_INCLUDE_EL2_REGS
+/* ---------------------------------------------------------------------------
+ * The following registers are not added:
+ * ICH_AP0R<n>_EL2
+ * ICH_AP1R<n>_EL2
+ * ICH_LR<n>_EL2
+ *
+ * NOTE: For a system with S-EL2 present but not enabled, accessing
+ * ICC_SRE_EL2 is undefined from EL3. To workaround this change the
+ * SCR_EL3.NS = 1 before accessing this register.
+ * ---------------------------------------------------------------------------
+ */
+static void el2_sysregs_context_save_gic(el2_sysregs_t *ctx)
+{
+#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
+	write_ctx_reg(ctx, CTX_ICC_SRE_EL2, read_icc_sre_el2());
+#else
+	u_register_t scr_el3 = read_scr_el3();
+	write_scr_el3(scr_el3 | SCR_NS_BIT);
+	isb();
+
+	write_ctx_reg(ctx, CTX_ICC_SRE_EL2, read_icc_sre_el2());
+
+	write_scr_el3(scr_el3);
+	isb();
+
+#endif
+	write_ctx_reg(ctx, CTX_ICH_HCR_EL2, read_ich_hcr_el2());
+	write_ctx_reg(ctx, CTX_ICH_VMCR_EL2, read_ich_vmcr_el2());
+}
+
+static void el2_sysregs_context_restore_gic(el2_sysregs_t *ctx)
+{
+#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
+	write_icc_sre_el2(read_ctx_reg(ctx, CTX_ICC_SRE_EL2));
+#else
+	u_register_t scr_el3 = read_scr_el3();
+	write_scr_el3(scr_el3 | SCR_NS_BIT);
+	isb();
+
+	write_icc_sre_el2(read_ctx_reg(ctx, CTX_ICC_SRE_EL2));
+
+	write_scr_el3(scr_el3);
+	isb();
+#endif
+	write_ich_hcr_el2(read_ctx_reg(ctx, CTX_ICH_HCR_EL2));
+	write_ich_vmcr_el2(read_ctx_reg(ctx, CTX_ICH_VMCR_EL2));
+}
+
 /* -----------------------------------------------------
  * The following registers are not added:
  * AMEVCNTVOFF0<n>_EL2
  * AMEVCNTVOFF1<n>_EL2
- * ICH_AP0R<n>_EL2
- * ICH_AP1R<n>_EL2
- * ICH_LR<n>_EL2
  * -----------------------------------------------------
  */
 static void el2_sysregs_context_save_common(el2_sysregs_t *ctx)
@@ -822,9 +867,6 @@
 	write_ctx_reg(ctx, CTX_HCR_EL2, read_hcr_el2());
 	write_ctx_reg(ctx, CTX_HPFAR_EL2, read_hpfar_el2());
 	write_ctx_reg(ctx, CTX_HSTR_EL2, read_hstr_el2());
-	write_ctx_reg(ctx, CTX_ICC_SRE_EL2, read_icc_sre_el2());
-	write_ctx_reg(ctx, CTX_ICH_HCR_EL2, read_ich_hcr_el2());
-	write_ctx_reg(ctx, CTX_ICH_VMCR_EL2, read_ich_vmcr_el2());
 	write_ctx_reg(ctx, CTX_MAIR_EL2, read_mair_el2());
 	write_ctx_reg(ctx, CTX_MDCR_EL2, read_mdcr_el2());
 	write_ctx_reg(ctx, CTX_SCTLR_EL2, read_sctlr_el2());
@@ -859,9 +901,6 @@
 	write_hcr_el2(read_ctx_reg(ctx, CTX_HCR_EL2));
 	write_hpfar_el2(read_ctx_reg(ctx, CTX_HPFAR_EL2));
 	write_hstr_el2(read_ctx_reg(ctx, CTX_HSTR_EL2));
-	write_icc_sre_el2(read_ctx_reg(ctx, CTX_ICC_SRE_EL2));
-	write_ich_hcr_el2(read_ctx_reg(ctx, CTX_ICH_HCR_EL2));
-	write_ich_vmcr_el2(read_ctx_reg(ctx, CTX_ICH_VMCR_EL2));
 	write_mair_el2(read_ctx_reg(ctx, CTX_MAIR_EL2));
 	write_mdcr_el2(read_ctx_reg(ctx, CTX_MDCR_EL2));
 	write_sctlr_el2(read_ctx_reg(ctx, CTX_SCTLR_EL2));
@@ -899,6 +938,8 @@
 		el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
 
 		el2_sysregs_context_save_common(el2_sysregs_ctx);
+		el2_sysregs_context_save_gic(el2_sysregs_ctx);
+
 #if ENABLE_SPE_FOR_LOWER_ELS
 		el2_sysregs_context_save_spe(el2_sysregs_ctx);
 #endif
@@ -957,6 +998,8 @@
 		el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
 
 		el2_sysregs_context_restore_common(el2_sysregs_ctx);
+		el2_sysregs_context_restore_gic(el2_sysregs_ctx);
+
 #if ENABLE_SPE_FOR_LOWER_ELS
 		el2_sysregs_context_restore_spe(el2_sysregs_ctx);
 #endif