arm-trusted-firmware/include/lib/el3_runtime/context_el1.h
Igor Podgainõi 6595f4cb39 fix(cm): fix context management SYSREG128 write macros
This patch fixes a bug which was introduced in commit
3065513 related to improper saving of EL1 context in the
context management library code when using 128-bit
system registers.

Bug explanation:
The function el1_sysregs_context_save still used the normal
macros that read all the system registers related to the EL1
context, which then involved casting them to uint64_t and
eventually writing them to a memory structure. This means that
the context management library was saving EL1-related SYSREG128
registers with the upper 64 bits zeroed out.

Alternative macros had previously been introduced for the EL2
context in the aforementioned commit, but not for EL1.

Some refactoring has also been done as part of this patch:
- Re-added "common" back to write_el2_ctx_common_sysreg128
- Added dummy SYSREG128 macros for cases when some features
  are disabled
- Removed some newlines

Change-Id: I15aa2190794ac099a493e5f430220b1c81e1b558
Signed-off-by: Igor Podgainõi <igor.podgainoi@arm.com>
2024-12-16 18:14:51 +01:00

328 lines
8 KiB
C

/*
* Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef CONTEXT_EL1_H
#define CONTEXT_EL1_H
#include <lib/extensions/sysreg128.h>
#ifndef __ASSEMBLER__
/*******************************************************************************
* EL1 Registers:
* AArch64 EL1 system register context structure for preserving the
* architectural state during world switches.
******************************************************************************/
typedef struct el1_common_regs {
uint64_t spsr_el1;
uint64_t elr_el1;
#if (!ERRATA_SPECULATIVE_AT)
uint64_t sctlr_el1;
uint64_t tcr_el1;
#endif /* ERRATA_SPECULATIVE_AT=0 */
uint64_t cpacr_el1;
uint64_t csselr_el1;
uint64_t sp_el1;
uint64_t esr_el1;
uint64_t mair_el1;
uint64_t amair_el1;
uint64_t actlr_el1;
uint64_t tpidr_el1;
uint64_t tpidr_el0;
uint64_t tpidrro_el0;
uint64_t far_el1;
uint64_t afsr0_el1;
uint64_t afsr1_el1;
uint64_t contextidr_el1;
uint64_t vbar_el1;
uint64_t mdccint_el1;
uint64_t mdscr_el1;
sysreg_t par_el1;
sysreg_t ttbr0_el1;
sysreg_t ttbr1_el1;
} el1_common_regs_t;
typedef struct el1_aarch32_regs {
uint64_t spsr_abt;
uint64_t spsr_und;
uint64_t spsr_irq;
uint64_t spsr_fiq;
uint64_t dacr32_el2;
uint64_t ifsr32_el2;
} el1_aarch32_regs_t;
typedef struct el1_arch_timer_regs {
uint64_t cntp_ctl_el0;
uint64_t cntp_cval_el0;
uint64_t cntv_ctl_el0;
uint64_t cntv_cval_el0;
uint64_t cntkctl_el1;
} el1_arch_timer_regs_t;
typedef struct el1_mte2_regs {
uint64_t tfsre0_el1;
uint64_t tfsr_el1;
uint64_t rgsr_el1;
uint64_t gcr_el1;
} el1_mte2_regs_t;
typedef struct el1_ras_regs {
uint64_t disr_el1;
} el1_ras_regs_t;
typedef struct el1_s1pie_regs {
uint64_t pire0_el1;
uint64_t pir_el1;
} el1_s1pie_regs_t;
typedef struct el1_s1poe_regs {
uint64_t por_el1;
} el1_s1poe_regs_t;
typedef struct el1_s2poe_regs {
uint64_t s2por_el1;
} el1_s2poe_regs_t;
typedef struct el1_tcr2_regs {
uint64_t tcr2_el1;
} el1_tcr2_regs_t;
typedef struct el1_trf_regs {
uint64_t trfcr_el1;
} el1_trf_regs_t;
typedef struct el1_csv2_2_regs {
uint64_t scxtnum_el0;
uint64_t scxtnum_el1;
} el1_csv2_2_regs_t;
typedef struct el1_gcs_regs {
uint64_t gcscr_el1;
uint64_t gcscre0_el1;
uint64_t gcspr_el1;
uint64_t gcspr_el0;
} el1_gcs_regs_t;
typedef struct el1_the_regs {
sysreg_t rcwmask_el1;
sysreg_t rcwsmask_el1;
} el1_the_regs_t;
typedef struct el1_sctlr2_regs {
uint64_t sctlr2_el1;
} el1_sctlr2_regs_t;
typedef struct el1_ls64_regs {
uint64_t accdata_el1;
} el1_ls64_regs_t;
typedef struct el1_sysregs {
el1_common_regs_t common;
#if CTX_INCLUDE_AARCH32_REGS
el1_aarch32_regs_t el1_aarch32;
#endif
#if NS_TIMER_SWITCH
el1_arch_timer_regs_t arch_timer;
#endif
#if ENABLE_FEAT_MTE2
el1_mte2_regs_t mte2;
#endif
#if ENABLE_FEAT_RAS
el1_ras_regs_t ras;
#endif
#if ENABLE_FEAT_S1PIE
el1_s1pie_regs_t s1pie;
#endif
#if ENABLE_FEAT_S1POE
el1_s1poe_regs_t s1poe;
#endif
#if ENABLE_FEAT_S2POE
el1_s2poe_regs_t s2poe;
#endif
#if ENABLE_FEAT_TCR2
el1_tcr2_regs_t tcr2;
#endif
#if ENABLE_TRF_FOR_NS
el1_trf_regs_t trf;
#endif
#if ENABLE_FEAT_CSV2_2
el1_csv2_2_regs_t csv2_2;
#endif
#if ENABLE_FEAT_GCS
el1_gcs_regs_t gcs;
#endif
#if ENABLE_FEAT_THE
el1_the_regs_t the;
#endif
#if ENABLE_FEAT_SCTLR2
el1_sctlr2_regs_t sctlr2;
#endif
#if ENABLE_FEAT_LS64_ACCDATA
el1_ls64_regs_t ls64;
#endif
} el1_sysregs_t;
/*
* Macros to access members related to individual features of the el1_sysregs_t
* structures.
*/
#define read_el1_ctx_common(ctx, reg) (((ctx)->common).reg)
#define write_el1_ctx_common(ctx, reg, val) ((((ctx)->common).reg) \
= (uint64_t) (val))
#define write_el1_ctx_common_sysreg128(ctx, reg, val) ((((ctx)->common).reg) \
= (sysreg_t) (val))
#if NS_TIMER_SWITCH
#define read_el1_ctx_arch_timer(ctx, reg) (((ctx)->arch_timer).reg)
#define write_el1_ctx_arch_timer(ctx, reg, val) ((((ctx)->arch_timer).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_arch_timer(ctx, reg) ULL(0)
#define write_el1_ctx_arch_timer(ctx, reg, val)
#endif /* NS_TIMER_SWITCH */
#if CTX_INCLUDE_AARCH32_REGS
#define read_el1_ctx_aarch32(ctx, reg) (((ctx)->el1_aarch32).reg)
#define write_el1_ctx_aarch32(ctx, reg, val) ((((ctx)->el1_aarch32).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_aarch32(ctx, reg) ULL(0)
#define write_el1_ctx_aarch32(ctx, reg, val)
#endif /* CTX_INCLUDE_AARCH32_REGS */
#if ENABLE_FEAT_MTE2
#define read_el1_ctx_mte2(ctx, reg) (((ctx)->mte2).reg)
#define write_el1_ctx_mte2(ctx, reg, val) ((((ctx)->mte2).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_mte2(ctx, reg) ULL(0)
#define write_el1_ctx_mte2(ctx, reg, val)
#endif /* ENABLE_FEAT_MTE2 */
#if ENABLE_FEAT_RAS
#define read_el1_ctx_ras(ctx, reg) (((ctx)->ras).reg)
#define write_el1_ctx_ras(ctx, reg, val) ((((ctx)->ras).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_ras(ctx, reg) ULL(0)
#define write_el1_ctx_ras(ctx, reg, val)
#endif /* ENABLE_FEAT_RAS */
#if ENABLE_FEAT_S1PIE
#define read_el1_ctx_s1pie(ctx, reg) (((ctx)->s1pie).reg)
#define write_el1_ctx_s1pie(ctx, reg, val) ((((ctx)->s1pie).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_s1pie(ctx, reg) ULL(0)
#define write_el1_ctx_s1pie(ctx, reg, val)
#endif /* ENABLE_FEAT_S1PIE */
#if ENABLE_FEAT_S1POE
#define read_el1_ctx_s1poe(ctx, reg) (((ctx)->s1poe).reg)
#define write_el1_ctx_s1poe(ctx, reg, val) ((((ctx)->s1poe).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_s1poe(ctx, reg) ULL(0)
#define write_el1_ctx_s1poe(ctx, reg, val)
#endif /* ENABLE_FEAT_S1POE */
#if ENABLE_FEAT_S2POE
#define read_el1_ctx_s2poe(ctx, reg) (((ctx)->s2poe).reg)
#define write_el1_ctx_s2poe(ctx, reg, val) ((((ctx)->s2poe).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_s2poe(ctx, reg) ULL(0)
#define write_el1_ctx_s2poe(ctx, reg, val)
#endif /* ENABLE_FEAT_S2POE */
#if ENABLE_FEAT_TCR2
#define read_el1_ctx_tcr2(ctx, reg) (((ctx)->tcr2).reg)
#define write_el1_ctx_tcr2(ctx, reg, val) ((((ctx)->tcr2).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_tcr2(ctx, reg) ULL(0)
#define write_el1_ctx_tcr2(ctx, reg, val)
#endif /* ENABLE_FEAT_TCR2 */
#if ENABLE_TRF_FOR_NS
#define read_el1_ctx_trf(ctx, reg) (((ctx)->trf).reg)
#define write_el1_ctx_trf(ctx, reg, val) ((((ctx)->trf).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_trf(ctx, reg) ULL(0)
#define write_el1_ctx_trf(ctx, reg, val)
#endif /* ENABLE_TRF_FOR_NS */
#if ENABLE_FEAT_CSV2_2
#define read_el1_ctx_csv2_2(ctx, reg) (((ctx)->csv2_2).reg)
#define write_el1_ctx_csv2_2(ctx, reg, val) ((((ctx)->csv2_2).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_csv2_2(ctx, reg) ULL(0)
#define write_el1_ctx_csv2_2(ctx, reg, val)
#endif /* ENABLE_FEAT_CSV2_2 */
#if ENABLE_FEAT_GCS
#define read_el1_ctx_gcs(ctx, reg) (((ctx)->gcs).reg)
#define write_el1_ctx_gcs(ctx, reg, val) ((((ctx)->gcs).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_gcs(ctx, reg) ULL(0)
#define write_el1_ctx_gcs(ctx, reg, val)
#endif /* ENABLE_FEAT_GCS */
#if ENABLE_FEAT_THE
#define read_el1_ctx_the(ctx, reg) (((ctx)->the).reg)
#define write_el1_ctx_the_sysreg128(ctx, reg, val) ((((ctx)->the).reg) \
= (sysreg_t) (val))
#else
#define read_el1_ctx_the(ctx, reg) ULL(0)
#define write_el1_ctx_the_sysreg128(ctx, reg, val)
#endif /* ENABLE_FEAT_THE */
#if ENABLE_FEAT_SCTLR2
#define read_el1_ctx_sctlr2(ctx, reg) (((ctx)->sctlr2).reg)
#define write_el1_ctx_sctlr2(ctx, reg, val) ((((ctx)->sctlr2).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_sctlr2(ctx, reg) ULL(0)
#define write_el1_ctx_sctlr2(ctx, reg, val)
#endif /* ENABLE_FEAT_SCTLR2 */
#if ENABLE_FEAT_LS64_ACCDATA
#define read_el1_ctx_ls64(ctx, reg) (((ctx)->ls64).reg)
#define write_el1_ctx_ls64(ctx, reg, val) ((((ctx)->ls64).reg) \
= (uint64_t) (val))
#else
#define read_el1_ctx_ls64(ctx, reg) ULL(0)
#define write_el1_ctx_ls64(ctx, reg, val)
#endif /* ENABLE_FEAT_LS64_ACCDATA */
/******************************************************************************/
#endif /* __ASSEMBLER__ */
#endif /* CONTEXT_EL1_H */