summaryrefslogtreecommitdiff
path: root/lib/el3_runtime
diff options
context:
space:
mode:
authorJuan Pablo Conde <juanpablo.conde@arm.com>2023-02-22 10:09:52 -0600
committerJuan Pablo Conde <juanpablo.conde@arm.com>2023-04-12 15:26:41 -0500
commitddb615b419074727ac0a1430cf0f88bd018ac8df (patch)
tree762202c1a5d195cbc9c617bae427147b7f01e52a /lib/el3_runtime
parenta1c924df6d31bfa93710f1c7e84b3ba34f06c5cb (diff)
downloadarm-trusted-firmware-ddb615b419074727ac0a1430cf0f88bd018ac8df.tar.gz
feat(hcx): initialize HCRX_EL2 to its default value
The value of register HCRX_EL2 is UNKNOWN out of reset. This can affect the behavior in lower exception levels, such as traps to EL2 due to a wrong configuration of the register upon reset. This patch initializes the register at EL3 and disables all traps related to it. On the other hand, new fields have been introduced for HCRX_EL2, which are now defined in this patch, so they can be used in further development. Signed-off-by: Juan Pablo Conde <juanpablo.conde@arm.com> Change-Id: I0bf1e949aa0d3be9f227358ad088a1ecb96ce222
Diffstat (limited to 'lib/el3_runtime')
-rw-r--r--lib/el3_runtime/aarch64/context_mgmt.c29
1 files changed, 28 insertions, 1 deletions
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;
/*