Merge changes from topic "jc/refact_el1_ctx" into integration

* changes:
  feat(cm): enhance the cpu_context memory report
  refactor(cm): remove el1 context when SPMD_SPM_AT_SEL2=1
This commit is contained in:
Madhukar Pappireddy 2024-08-21 21:55:56 +02:00 committed by TrustedFirmware Code Review
commit 021cdbfbd4
7 changed files with 166 additions and 75 deletions

View file

@ -7,8 +7,16 @@
#ifndef CONTEXT_H
#define CONTEXT_H
#include <lib/el3_runtime/context_el1.h>
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
#include <lib/el3_runtime/context_el2.h>
#else
/**
* El1 context is required either when:
* IMAGE_BL1 || ((!CTX_INCLUDE_EL2_REGS) && IMAGE_BL31)
*/
#include <lib/el3_runtime/context_el1.h>
#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
#include <lib/el3_runtime/cpu_data.h>
#include <lib/el3_runtime/simd_ctx.h>
#include <lib/utils_def.h>
@ -250,10 +258,16 @@ typedef struct cpu_context {
pauth_t pauth_ctx;
#endif
el1_sysregs_t el1_sysregs_ctx;
#if CTX_INCLUDE_EL2_REGS
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
el2_sysregs_t el2_sysregs_ctx;
#else
/* El1 context should be included only either for IMAGE_BL1,
* or for IMAGE_BL31 when CTX_INCLUDE_EL2_REGS=0:
* When SPMD_SPM_AT_SEL2=1, SPMC at S-EL2 takes care of saving
* and restoring EL1 registers. In this case, BL31 at EL3 can
* exclude save and restore of EL1 context registers.
*/
el1_sysregs_t el1_sysregs_ctx;
#endif
} cpu_context_t;
@ -272,10 +286,13 @@ extern per_world_context_t per_world_context[CPU_DATA_CONTEXT_NUM];
/* Macros to access members of the 'cpu_context_t' structure */
#define get_el3state_ctx(h) (&((cpu_context_t *) h)->el3state_ctx)
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
#define get_el2_sysregs_ctx(h) (&((cpu_context_t *) h)->el2_sysregs_ctx)
#else
#define get_el1_sysregs_ctx(h) (&((cpu_context_t *) h)->el1_sysregs_ctx)
#if CTX_INCLUDE_EL2_REGS
# define get_el2_sysregs_ctx(h) (&((cpu_context_t *) h)->el2_sysregs_ctx)
#endif
#define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx)
#define get_cve_2018_3639_ctx(h) (&((cpu_context_t *) h)->cve_2018_3639_ctx)
@ -356,6 +373,27 @@ void fpregs_context_save(simd_regs_t *regs);
void fpregs_context_restore(simd_regs_t *regs);
#endif
/*******************************************************************************
* The next four inline functions are required for IMAGE_BL1, as well as for
* IMAGE_BL31 for the below combinations.
* ============================================================================
* | ERRATA_SPECULATIVE_AT| CTX_INCLUDE_EL2_REGS | Combination |
* ============================================================================
* | 0 | 0 | Valid (EL1 ctx) |
* |______________________|______________________|____________________________|
* | | | Invalid (No Errata/EL1 Ctx)|
* | 0 | 1 | Hence commented out. |
* |______________________|______________________|____________________________|
* | | | |
* | 1 | 0 | Valid (Errata ctx) |
* |______________________|______________________|____________________________|
* | | | |
* | 1 | 1 | Valid (Errata ctx) |
* |______________________|______________________|____________________________|
* ============================================================================
******************************************************************************/
#if (IMAGE_BL1 || ((ERRATA_SPECULATIVE_AT) || (!CTX_INCLUDE_EL2_REGS)))
static inline void write_ctx_sctlr_el1_reg_errata(cpu_context_t *ctx, u_register_t val)
{
#if (ERRATA_SPECULATIVE_AT)
@ -396,6 +434,8 @@ static inline u_register_t read_ctx_tcr_el1_reg_errata(cpu_context_t *ctx)
#endif /* ERRATA_SPECULATIVE_AT */
}
#endif /* (IMAGE_BL1 || ((ERRATA_SPECULATIVE_AT) || (!CTX_INCLUDE_EL2_REGS))) */
#endif /* __ASSEMBLER__ */
#endif /* CONTEXT_H */

View file

@ -13,7 +13,6 @@
* AArch64 EL2 system register context structure for preserving the
* architectural state during world switches.
******************************************************************************/
#if CTX_INCLUDE_EL2_REGS
typedef struct el2_common_regs {
uint64_t actlr_el2;
uint64_t afsr0_el2;
@ -359,7 +358,6 @@ typedef struct el2_sysregs {
#define write_el2_ctx_mpam(ctx, reg, val)
#endif /* CTX_INCLUDE_MPAM_REGS */
#endif /* CTX_INCLUDE_EL2_REGS */
/******************************************************************************/
#endif /* __ASSEMBLER__ */

View file

@ -47,13 +47,14 @@ void cm_el3_arch_init_per_world(per_world_context_t *per_world_ctx);
void cm_handle_asymmetric_features(void);
#endif
#if CTX_INCLUDE_EL2_REGS
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
void cm_el2_sysregs_context_save(uint32_t security_state);
void cm_el2_sysregs_context_restore(uint32_t security_state);
#endif
#else
void cm_el1_sysregs_context_save(uint32_t security_state);
void cm_el1_sysregs_context_restore(uint32_t security_state);
#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
void cm_set_elr_el3(uint32_t security_state, uintptr_t entrypoint);
void cm_set_elr_spsr_el3(uint32_t security_state,
uintptr_t entrypoint, uint32_t spsr);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -28,19 +28,11 @@ static const char *get_context_name_by_idx(unsigned int security_state_idx)
return state_names[security_state_idx];
}
#if CTX_INCLUDE_EL2_REGS
#define PRINT_MEM_USAGE_SEPARATOR() \
do { \
printf("+-----------+-----------+-----------" \
"+-----------+-----------+-----------+\n"); \
} while (false)
#else
#define PRINT_MEM_USAGE_SEPARATOR() \
do { \
printf("+-----------+-----------" \
"+-----------+-----------+-----------+\n"); \
} while (false)
#endif /* CTX_INCLUDE_EL2_REGS */
#define NAME_PLACEHOLDER_LEN 14
@ -49,6 +41,11 @@ static const char *get_context_name_by_idx(unsigned int security_state_idx)
putchar('-'); \
}
#define PRINT_SINGLE_MEM_USAGE_SEP_BLOCK() \
do { \
printf("+-----------"); \
} while (false)
/********************************************************************************
* This function prints the allocated memory for a specific security state.
* Values are grouped by exception level and core. The memory usage for the
@ -57,64 +54,119 @@ static const char *get_context_name_by_idx(unsigned int security_state_idx)
static size_t report_allocated_memory(unsigned int security_state_idx)
{
size_t core_total = 0U;
size_t gp_total = 0U;
size_t el3_total = 0U;
#if CTX_INCLUDE_EL2_REGS
size_t el2_total = 0U;
#endif /* CTX_INCLUDE_EL2_REGS */
size_t el1_total = 0U;
size_t other_total = 0U;
size_t total = 0U;
size_t per_world_ctx_size = 0U;
#if CTX_INCLUDE_EL2_REGS
size_t el2_total = 0U;
#else
size_t el1_total = 0U;
#endif /* CTX_INCLUDE_EL2_REGS */
#if CTX_INCLUDE_PAUTH_REGS
size_t pauth_total = 0U;
PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
#endif
PRINT_MEM_USAGE_SEPARATOR();
printf("| Core | EL3 ");
printf("| Core | GP | EL3 ");
#if CTX_INCLUDE_EL2_REGS
printf("| EL2 ");
#else
printf("| EL1 ");
#endif /* CTX_INCLUDE_EL2_REGS */
printf("| EL1 | Other | Total |\n");
#if CTX_INCLUDE_PAUTH_REGS
printf("| PAUTH ");
#endif
printf("| Other | Total |\n");
/* Compute memory usage for each core's context */
for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) {
size_t size_other = 0U;
size_t el3_size = 0U;
size_t gp_size = 0U;
#if CTX_INCLUDE_EL2_REGS
size_t el2_size = 0U;
#endif /* CTX_INCLUDE_EL2_REGS */
#else
size_t el1_size = 0U;
#endif /* CTX_INCLUDE_EL2_REGS */
#if CTX_INCLUDE_PAUTH_REGS
size_t pauth_size = 0U;
PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
#endif
PRINT_MEM_USAGE_SEPARATOR();
cpu_context_t *ctx = (cpu_context_t *)cm_get_context_by_index(i,
security_state_idx);
core_total = sizeof(*ctx);
el3_size = sizeof(ctx->el3state_ctx);
gp_size = sizeof(ctx->gpregs_ctx);
size_other = core_total - (el3_size + gp_size);
printf("| %9u | %8luB | %8luB ", i, gp_size, el3_size);
#if CTX_INCLUDE_EL2_REGS
el2_size = sizeof(ctx->el2_sysregs_ctx);
#endif /* CTX_INCLUDE_EL2_REGS */
el1_size = sizeof(ctx->el1_sysregs_ctx);
size_other = core_total - el3_size - el1_size;
printf("| %9u | %8luB ", i, el3_size);
#if CTX_INCLUDE_EL2_REGS
size_other -= el2_size;
printf("| %8luB ", el2_size);
#endif /* CTX_INCLUDE_EL2_REGS */
printf("| %8luB | %8luB | %8luB |\n", el1_size, size_other, core_total);
el3_total += el3_size;
#if CTX_INCLUDE_EL2_REGS
el2_total += el2_size;
#endif /* CTX_INCLUDE_EL2_REGS */
printf("| %8luB ", el2_size);
#else
el1_size = sizeof(ctx->el1_sysregs_ctx);
size_other -= el1_size;
el1_total += el1_size;
printf("| %8luB ", el1_size);
#endif /* CTX_INCLUDE_EL2_REGS */
#if CTX_INCLUDE_PAUTH_REGS
pauth_size = sizeof(ctx->pauth_ctx);
size_other -= pauth_size;
pauth_total += pauth_size;
printf("| %8luB ", pauth_size);
#endif
printf("| %8luB | %8luB |\n", size_other, core_total);
gp_total += gp_size;
el3_total += el3_size;
other_total += size_other;
total += core_total;
}
#if CTX_INCLUDE_PAUTH_REGS
PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
#endif
PRINT_MEM_USAGE_SEPARATOR();
#if CTX_INCLUDE_PAUTH_REGS
PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
#endif
PRINT_MEM_USAGE_SEPARATOR();
printf("| All | %8luB ", el3_total);
printf("| All | %8luB | %8luB ", gp_total, el3_total);
#if CTX_INCLUDE_EL2_REGS
printf("| %8luB ", el2_total);
#else
printf("| %8luB ", el1_total);
#endif /* CTX_INCLUDE_EL2_REGS */
printf("| %8luB | %8luB | %8luB |\n", el1_total, other_total, total);
#if CTX_INCLUDE_PAUTH_REGS
printf("| %8luB ", pauth_total);
#endif
printf("| %8luB | %8luB |\n", other_total, total);
#if CTX_INCLUDE_PAUTH_REGS
PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
#endif
PRINT_MEM_USAGE_SEPARATOR();
printf("\n");
@ -146,18 +198,10 @@ void report_ctx_memory_usage(void)
printf("Memory usage for %s:\n", context_name);
total += report_allocated_memory(i);
printf("------------------------"
#if CTX_INCLUDE_EL2_REGS
"------"
#endif /* CTX_INCLUDE_EL2_REGS */
);
printf("------------------------");
len = NAME_PLACEHOLDER_LEN - printf("End %s", context_name);
PRINT_DASH(len);
printf(
#if CTX_INCLUDE_EL2_REGS
"------"
#endif /* CTX_INCLUDE_EL2_REGS */
"-----------------------\n\n");
printf("-----------------------\n\n");
}
printf("Total context memory allocated: %luB\n\n", total);

View file

@ -51,6 +51,7 @@ static void manage_extensions_nonsecure(cpu_context_t *ctx);
static void manage_extensions_secure(cpu_context_t *ctx);
static void manage_extensions_secure_per_world(void);
#if ((IMAGE_BL1) || (IMAGE_BL31 && (!CTX_INCLUDE_EL2_REGS)))
static void setup_el1_context(cpu_context_t *ctx, const struct entry_point_info *ep)
{
u_register_t sctlr_elx, actlr_elx;
@ -108,6 +109,7 @@ static void setup_el1_context(cpu_context_t *ctx, const struct entry_point_info
actlr_elx = read_actlr_el1();
write_el1_ctx_common(get_el1_sysregs_ctx(ctx), actlr_el1, actlr_elx);
}
#endif /* (IMAGE_BL1) || (IMAGE_BL31 && (!CTX_INCLUDE_EL2_REGS)) */
/******************************************************************************
* This function performs initializations that are specific to SECURE state
@ -140,7 +142,7 @@ static void setup_secure_context(cpu_context_t *ctx, const struct entry_point_in
* Initialize EL1 context registers unless SPMC is running
* at S-EL2.
*/
#if !SPMD_SPM_AT_SEL2
#if (!SPMD_SPM_AT_SEL2)
setup_el1_context(ctx, ep);
#endif
@ -156,7 +158,6 @@ static void setup_secure_context(cpu_context_t *ctx, const struct entry_point_in
if (!has_secure_perworld_init) {
manage_extensions_secure_per_world();
}
}
#if ENABLE_RME
@ -260,11 +261,8 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info *
#endif
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
/* Initialize EL1 context registers */
setup_el1_context(ctx, ep);
/* Initialize EL2 context registers */
#if CTX_INCLUDE_EL2_REGS
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
/*
* Initialize SCTLR_EL2 context register with reset value.
@ -297,8 +295,10 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info *
write_el2_ctx_fgt(get_el2_sysregs_ctx(ctx), hfgwtr_el2,
HFGWTR_EL2_INIT_VAL);
}
#endif /* CTX_INCLUDE_EL2_REGS */
#else
/* Initialize EL1 context registers */
setup_el1_context(ctx, ep);
#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
manage_extensions_nonsecure(ctx);
}
@ -329,7 +329,7 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
* to boot correctly. However, there are very few registers where this
* is not true and some values need to be recreated.
*/
#if CTX_INCLUDE_EL2_REGS
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
el2_sysregs_t *el2_ctx = get_el2_sysregs_ctx(ctx);
/*
@ -345,7 +345,7 @@ static void setup_context_common(cpu_context_t *ctx, const entry_point_info_t *e
* and it may contain access control bits (e.g. CLUSTERPMUEN bit).
*/
write_el2_ctx_common(el2_ctx, actlr_el2, read_actlr_el2());
#endif /* CTX_INCLUDE_EL2_REGS */
#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
/* Start with a clean SCR_EL3 copy as all relevant values are set */
scr_el3 = SCR_RESET_VAL;
@ -1087,11 +1087,14 @@ void cm_prepare_el3_exit(uint32_t security_state)
}
}
}
#if (!CTX_INCLUDE_EL2_REGS)
/* Restore EL1 system registers, only when CTX_INCLUDE_EL2_REGS=0 */
cm_el1_sysregs_context_restore(security_state);
#endif
cm_set_next_eret_context(security_state);
}
#if CTX_INCLUDE_EL2_REGS
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
static void el2_sysregs_context_save_fgt(el2_sysregs_t *ctx)
{
@ -1519,7 +1522,7 @@ void cm_el2_sysregs_context_restore(uint32_t security_state)
write_gcspr_el2(read_el2_ctx_gcs(el2_sysregs_ctx, gcspr_el2));
}
}
#endif /* CTX_INCLUDE_EL2_REGS */
#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
#if IMAGE_BL31
/*********************************************************************************
@ -1580,7 +1583,7 @@ void cm_prepare_el3_exit_ns(void)
cm_handle_asymmetric_features();
#endif
#if CTX_INCLUDE_EL2_REGS
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
#if ENABLE_ASSERTIONS
cpu_context_t *ctx = cm_get_context(NON_SECURE);
assert(ctx != NULL);
@ -1591,15 +1594,19 @@ void cm_prepare_el3_exit_ns(void)
(el_implemented(2U) != EL_IMPL_NONE));
#endif /* ENABLE_ASSERTIONS */
/* Restore EL2 and EL1 sysreg contexts */
/* Restore EL2 sysreg contexts */
cm_el2_sysregs_context_restore(NON_SECURE);
cm_el1_sysregs_context_restore(NON_SECURE);
cm_set_next_eret_context(NON_SECURE);
#else
cm_prepare_el3_exit(NON_SECURE);
#endif /* CTX_INCLUDE_EL2_REGS */
#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
}
#if ((IMAGE_BL1) || (IMAGE_BL31 && (!CTX_INCLUDE_EL2_REGS)))
/*******************************************************************************
* The next set of six functions are used by runtime services to save and restore
* EL1 context on the 'cpu_context' structure for the specified security state.
******************************************************************************/
static void el1_sysregs_context_save(el1_sysregs_t *ctx)
{
write_el1_ctx_common(ctx, spsr_el1, read_spsr_el1());
@ -1791,9 +1798,8 @@ static void el1_sysregs_context_restore(el1_sysregs_t *ctx)
}
/*******************************************************************************
* The next four functions are used by runtime services to save and restore
* EL1 context on the 'cpu_context' structure for the specified security
* state.
* The next couple of functions are used by runtime services to save and restore
* EL1 context on the 'cpu_context' structure for the specified security state.
******************************************************************************/
void cm_el1_sysregs_context_save(uint32_t security_state)
{
@ -1829,6 +1835,8 @@ void cm_el1_sysregs_context_restore(uint32_t security_state)
#endif
}
#endif /* ((IMAGE_BL1) || (IMAGE_BL31 && (!CTX_INCLUDE_EL2_REGS))) */
/*******************************************************************************
* This function populates ELR_EL3 member of 'cpu_context' pertaining to the
* given security state with the given entrypoint

View file

@ -23,13 +23,13 @@ static u_register_t init_mdcr_el2_hpmn(u_register_t mdcr_el2)
void pmuv3_enable(cpu_context_t *ctx)
{
#if CTX_INCLUDE_EL2_REGS
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
u_register_t mdcr_el2_val;
mdcr_el2_val = read_el2_ctx_common(get_el2_sysregs_ctx(ctx), mdcr_el2);
mdcr_el2_val = init_mdcr_el2_hpmn(mdcr_el2_val);
write_el2_ctx_common(get_el2_sysregs_ctx(ctx), mdcr_el2, mdcr_el2_val);
#endif /* CTX_INCLUDE_EL2_REGS */
#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
}
static u_register_t mtpmu_disable_el3(u_register_t mdcr_el3)

View file

@ -92,7 +92,7 @@ static void populate_cpu_err_data(cpu_err_info *cpu_info,
cpu_info->ErrCtxEl1Reg[16] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
ttbr1_el1);
#if CTX_INCLUDE_EL2_REGS
#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
cpu_info->ErrCtxEl2Reg[0] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
elr_el2);
cpu_info->ErrCtxEl2Reg[1] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
@ -125,7 +125,7 @@ static void populate_cpu_err_data(cpu_err_info *cpu_info,
vttbr_el2);
cpu_info->ErrCtxEl2Reg[15] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
esr_el2);
#endif /* CTX_INCLUDE_EL2_REGS */
#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
cpu_info->ErrCtxEl3Reg[0] = read_ctx_reg(get_el3state_ctx(ctx),
CTX_ELR_EL3);