mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 09:34:18 +00:00
fix(cpus): workaround for accessing ICH_VMCR_EL2
When ICH_VMCR_EL2.VBPR1 is written in Secure state (SCR_EL3.NS==0) and then subsequently read in Non-secure state (SCR_EL3.NS==1), a wrong value might be returned. The same issue exists in the opposite way. Adding workaround in EL3 software that performs context save/restore on a change of Security state to use a value of SCR_EL3.NS when accessing ICH_VMCR_EL2 that reflects the Security state that owns the data being saved or restored. For example, EL3 software should set SCR_EL3.NS to 1 when saving or restoring the value ICH_VMCR_EL2 for Non-secure(or Realm) state. EL3 software should clear SCR_EL3.NS to 0 when saving or restoring the value ICH_VMCR_EL2 for Secure state. SDEN documentation: https://developer.arm.com/documentation/SDEN-1775101/latest/ Change-Id: I9f0403601c6346276e925f02eab55908b009d957 Signed-off-by: Govindraj Raja <govindraj.raja@arm.com>
This commit is contained in:
parent
58d98ba82d
commit
7455cd1721
3 changed files with 52 additions and 9 deletions
|
@ -70,6 +70,7 @@ unsigned int check_if_affected_core(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int check_wa_cve_2024_7881(void);
|
int check_wa_cve_2024_7881(void);
|
||||||
|
bool errata_ich_vmcr_el2_applies(void);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
|
* Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -8,9 +8,9 @@
|
||||||
|
|
||||||
#include <arch.h>
|
#include <arch.h>
|
||||||
#include <arch_helpers.h>
|
#include <arch_helpers.h>
|
||||||
|
#include <cortex_a75.h>
|
||||||
#include <cortex_a520.h>
|
#include <cortex_a520.h>
|
||||||
#include <cortex_x4.h>
|
#include <cortex_x4.h>
|
||||||
#include <cortex_a75.h>
|
|
||||||
#include <lib/cpus/cpu_ops.h>
|
#include <lib/cpus/cpu_ops.h>
|
||||||
#include <lib/cpus/errata.h>
|
#include <lib/cpus/errata.h>
|
||||||
|
|
||||||
|
@ -40,3 +40,13 @@ bool errata_a75_764081_applies(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif /* ERRATA_A75_764081 */
|
#endif /* ERRATA_A75_764081 */
|
||||||
|
|
||||||
|
bool errata_ich_vmcr_el2_applies(void)
|
||||||
|
{
|
||||||
|
switch (EXTRACT_PARTNUM(read_midr())) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
|
* Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
|
||||||
* Copyright (c) 2022, NVIDIA Corporation. All rights reserved.
|
* Copyright (c) 2022, NVIDIA Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
@ -1291,12 +1291,13 @@ static void el2_sysregs_context_restore_mpam(el2_sysregs_t *ctx)
|
||||||
* SCR_EL3.NS = 1 before accessing this register.
|
* SCR_EL3.NS = 1 before accessing this register.
|
||||||
* ---------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
static void el2_sysregs_context_save_gic(el2_sysregs_t *ctx)
|
static void el2_sysregs_context_save_gic(el2_sysregs_t *ctx, uint32_t security_state)
|
||||||
{
|
{
|
||||||
|
u_register_t scr_el3 = read_scr_el3();
|
||||||
|
|
||||||
#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
|
#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
|
||||||
write_el2_ctx_common(ctx, icc_sre_el2, read_icc_sre_el2());
|
write_el2_ctx_common(ctx, icc_sre_el2, read_icc_sre_el2());
|
||||||
#else
|
#else
|
||||||
u_register_t scr_el3 = read_scr_el3();
|
|
||||||
write_scr_el3(scr_el3 | SCR_NS_BIT);
|
write_scr_el3(scr_el3 | SCR_NS_BIT);
|
||||||
isb();
|
isb();
|
||||||
|
|
||||||
|
@ -1306,15 +1307,31 @@ static void el2_sysregs_context_save_gic(el2_sysregs_t *ctx)
|
||||||
isb();
|
isb();
|
||||||
#endif
|
#endif
|
||||||
write_el2_ctx_common(ctx, ich_hcr_el2, read_ich_hcr_el2());
|
write_el2_ctx_common(ctx, ich_hcr_el2, read_ich_hcr_el2());
|
||||||
|
|
||||||
|
if (errata_ich_vmcr_el2_applies()) {
|
||||||
|
if (security_state == SECURE) {
|
||||||
|
write_scr_el3(scr_el3 & ~SCR_NS_BIT);
|
||||||
|
} else {
|
||||||
|
write_scr_el3(scr_el3 | SCR_NS_BIT);
|
||||||
|
}
|
||||||
|
isb();
|
||||||
|
}
|
||||||
|
|
||||||
write_el2_ctx_common(ctx, ich_vmcr_el2, read_ich_vmcr_el2());
|
write_el2_ctx_common(ctx, ich_vmcr_el2, read_ich_vmcr_el2());
|
||||||
|
|
||||||
|
if (errata_ich_vmcr_el2_applies()) {
|
||||||
|
write_scr_el3(scr_el3);
|
||||||
|
isb();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void el2_sysregs_context_restore_gic(el2_sysregs_t *ctx)
|
static void el2_sysregs_context_restore_gic(el2_sysregs_t *ctx, uint32_t security_state)
|
||||||
{
|
{
|
||||||
|
u_register_t scr_el3 = read_scr_el3();
|
||||||
|
|
||||||
#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
|
#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
|
||||||
write_icc_sre_el2(read_el2_ctx_common(ctx, icc_sre_el2));
|
write_icc_sre_el2(read_el2_ctx_common(ctx, icc_sre_el2));
|
||||||
#else
|
#else
|
||||||
u_register_t scr_el3 = read_scr_el3();
|
|
||||||
write_scr_el3(scr_el3 | SCR_NS_BIT);
|
write_scr_el3(scr_el3 | SCR_NS_BIT);
|
||||||
isb();
|
isb();
|
||||||
|
|
||||||
|
@ -1324,7 +1341,22 @@ static void el2_sysregs_context_restore_gic(el2_sysregs_t *ctx)
|
||||||
isb();
|
isb();
|
||||||
#endif
|
#endif
|
||||||
write_ich_hcr_el2(read_el2_ctx_common(ctx, ich_hcr_el2));
|
write_ich_hcr_el2(read_el2_ctx_common(ctx, ich_hcr_el2));
|
||||||
|
|
||||||
|
if (errata_ich_vmcr_el2_applies()) {
|
||||||
|
if (security_state == SECURE) {
|
||||||
|
write_scr_el3(scr_el3 & ~SCR_NS_BIT);
|
||||||
|
} else {
|
||||||
|
write_scr_el3(scr_el3 | SCR_NS_BIT);
|
||||||
|
}
|
||||||
|
isb();
|
||||||
|
}
|
||||||
|
|
||||||
write_ich_vmcr_el2(read_el2_ctx_common(ctx, ich_vmcr_el2));
|
write_ich_vmcr_el2(read_el2_ctx_common(ctx, ich_vmcr_el2));
|
||||||
|
|
||||||
|
if (errata_ich_vmcr_el2_applies()) {
|
||||||
|
write_scr_el3(scr_el3);
|
||||||
|
isb();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------
|
/* -----------------------------------------------------
|
||||||
|
@ -1416,7 +1448,7 @@ void cm_el2_sysregs_context_save(uint32_t security_state)
|
||||||
el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
|
el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
|
||||||
|
|
||||||
el2_sysregs_context_save_common(el2_sysregs_ctx);
|
el2_sysregs_context_save_common(el2_sysregs_ctx);
|
||||||
el2_sysregs_context_save_gic(el2_sysregs_ctx);
|
el2_sysregs_context_save_gic(el2_sysregs_ctx, security_state);
|
||||||
|
|
||||||
if (is_feat_mte2_supported()) {
|
if (is_feat_mte2_supported()) {
|
||||||
write_el2_ctx_mte2(el2_sysregs_ctx, tfsr_el2, read_tfsr_el2());
|
write_el2_ctx_mte2(el2_sysregs_ctx, tfsr_el2, read_tfsr_el2());
|
||||||
|
@ -1507,7 +1539,7 @@ void cm_el2_sysregs_context_restore(uint32_t security_state)
|
||||||
el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
|
el2_sysregs_ctx = get_el2_sysregs_ctx(ctx);
|
||||||
|
|
||||||
el2_sysregs_context_restore_common(el2_sysregs_ctx);
|
el2_sysregs_context_restore_common(el2_sysregs_ctx);
|
||||||
el2_sysregs_context_restore_gic(el2_sysregs_ctx);
|
el2_sysregs_context_restore_gic(el2_sysregs_ctx, security_state);
|
||||||
|
|
||||||
if (is_feat_mte2_supported()) {
|
if (is_feat_mte2_supported()) {
|
||||||
write_tfsr_el2(read_el2_ctx_mte2(el2_sysregs_ctx, tfsr_el2));
|
write_tfsr_el2(read_el2_ctx_mte2(el2_sysregs_ctx, tfsr_el2));
|
||||||
|
|
Loading…
Add table
Reference in a new issue