]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
feat(hcx): initialize HCRX_EL2 to its default value
authorJuan Pablo Conde <juanpablo.conde@arm.com>
Wed, 22 Feb 2023 16:09:52 +0000 (10:09 -0600)
committerJuan Pablo Conde <juanpablo.conde@arm.com>
Wed, 12 Apr 2023 20:26:41 +0000 (15:26 -0500)
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

include/arch/aarch64/arch.h
lib/el3_runtime/aarch64/context_mgmt.c

index dee7fdcff2b0df6ef0ba5e7a3a36bddc3449a3ca..596d02075213e14106eb586dc88667344af7cf6d 100644 (file)
  * 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
index 42166eb999c8fcd79cf837c31c475b6a8389ab5c..ce78439282473a68d133d2f041d05b3b1cc62632 100644 (file)
@@ -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;
 
                        /*