diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index 9b55658ff..89f4b40bd 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -1322,11 +1322,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 94d5ee1d2..c411b73ab 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 */ } @@ -612,8 +625,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), @@ -629,7 +656,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; /*