summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/arch/aarch64/arch.h8
-rw-r--r--lib/el3_runtime/aarch64/context_mgmt.c29
2 files changed, 36 insertions, 1 deletions
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index dee7fdcff..596d02075 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -1309,11 +1309,19 @@
* FEAT_HCX - Extended Hypervisor Configuration Register
******************************************************************************/
#define HCRX_EL2 S3_4_C1_C2_2
+#define HCRX_EL2_MSCEn_BIT (UL(1) << 11)
+#define HCRX_EL2_MCE2_BIT (UL(1) << 10)
+#define HCRX_EL2_CMOW_BIT (UL(1) << 9)
+#define HCRX_EL2_VFNMI_BIT (UL(1) << 8)
+#define HCRX_EL2_VINMI_BIT (UL(1) << 7)
+#define HCRX_EL2_TALLINT_BIT (UL(1) << 6)
+#define HCRX_EL2_SMPME_BIT (UL(1) << 5)
#define HCRX_EL2_FGTnXS_BIT (UL(1) << 4)
#define HCRX_EL2_FnXS_BIT (UL(1) << 3)
#define HCRX_EL2_EnASR_BIT (UL(1) << 2)
#define HCRX_EL2_EnALS_BIT (UL(1) << 1)
#define HCRX_EL2_EnAS0_BIT (UL(1) << 0)
+#define HCRX_EL2_INIT_VAL ULL(0x0)
/*******************************************************************************
* FEAT_TCR2 - Extended Translation Control Register
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 42166eb99..ce7843928 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -274,6 +274,19 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info *
u_register_t mdcr_el2 = ((read_pmcr_el0() >> PMCR_EL0_N_SHIFT) &
PMCR_EL0_N_MASK);
write_ctx_reg(get_el2_sysregs_ctx(ctx), CTX_MDCR_EL2, mdcr_el2);
+
+ if (is_feat_hcx_supported()) {
+ /*
+ * Initialize register HCRX_EL2 with its init value.
+ * As the value of HCRX_EL2 is UNKNOWN on reset, there is a
+ * chance that this can lead to unexpected behavior in lower
+ * ELs that have not been updated since the introduction of
+ * this feature if not properly initialized, especially when
+ * it comes to those bits that enable/disable traps.
+ */
+ write_ctx_reg(get_el2_sysregs_ctx(ctx), CTX_HCRX_EL2,
+ HCRX_EL2_INIT_VAL);
+ }
#endif /* CTX_INCLUDE_EL2_REGS */
}
@@ -604,8 +617,22 @@ void cm_prepare_el3_exit(uint32_t security_state)
assert(ctx != NULL);
if (security_state == NON_SECURE) {
+ uint64_t el2_implemented = el_implemented(2);
+
scr_el3 = read_ctx_reg(get_el3state_ctx(ctx),
CTX_SCR_EL3);
+
+ if (((scr_el3 & SCR_HCE_BIT) != 0U)
+ || (el2_implemented != EL_IMPL_NONE)) {
+ /*
+ * If context is not being used for EL2, initialize
+ * HCRX_EL2 with its init value here.
+ */
+ if (is_feat_hcx_supported()) {
+ write_hcrx_el2(HCRX_EL2_INIT_VAL);
+ }
+ }
+
if ((scr_el3 & SCR_HCE_BIT) != 0U) {
/* Use SCTLR_EL1.EE value to initialise sctlr_el2 */
sctlr_elx = read_ctx_reg(get_el1_sysregs_ctx(ctx),
@@ -621,7 +648,7 @@ void cm_prepare_el3_exit(uint32_t security_state)
sctlr_elx |= SCTLR_IESB_BIT;
#endif
write_sctlr_el2(sctlr_elx);
- } else if (el_implemented(2) != EL_IMPL_NONE) {
+ } else if (el2_implemented != EL_IMPL_NONE) {
el2_unused = true;
/*