arm-trusted-firmware/lib/el3_runtime/aarch64/context_debug.c
Jayanth Dodderi Chidanand a0674ab081 refactor(cm): remove el1 context when SPMD_SPM_AT_SEL2=1
* Currently, EL1 context is included in cpu_context_t by default
  for all the build configurations.
  As part of the cpu context structure, we hold a copy of EL1, EL2
  system registers, per world per PE. This context structure is
  enormous and will continue to grow bigger with the addition of
  new features incorporating  new registers.

* Ideally, EL3 should save and restore the system registers at its next
  lower exception level, which is EL2 in majority of the configurations.

* This patch aims at optimising the memory allocation in cases, when
  the members from the context structure are unused. So el1 system
  register context must be omitted when lower EL is always x-EL2.

* "CTX_INCLUDE_EL2_REGS" is the internal build flag which gets set,
  when SPD=spmd and SPMD_SPM_AT_SEL2=1 or ENABLE_RME=1.
  It indicates, the system registers at EL2 are context switched for
  the respective build configuration. Here, there is no need  to save
  and restore EL1 system registers, while x-EL2 is enabled.

Henceforth, this patch addresses this issue, by taking out the EL1
context at all possible places, while EL2 (CTX_INCLUDE_EL2_REGS) is
enabled, there by saving memory.

Change-Id: Ifddc497d3c810e22a15b1c227a731bcc133c2f4a
Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
2024-08-21 16:35:27 +01:00

158 lines
4.5 KiB
C

/*
* Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <string.h>
#include <common/debug.h>
#include <context.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/el3_runtime/cpu_data.h>
/********************************************************************************
* Function that returns the corresponding string constant for a security state
* index.
*******************************************************************************/
static const char *get_context_name_by_idx(unsigned int security_state_idx)
{
assert(security_state_idx < CPU_CONTEXT_NUM);
static const char * const state_names[] = {
"Secure",
"Non Secure"
#if ENABLE_RME
, "Realm"
#endif /* ENABLE_RME */
};
return state_names[security_state_idx];
}
#define PRINT_MEM_USAGE_SEPARATOR() \
do { \
printf("+-----------+-----------" \
"+-----------+-----------+-----------+\n"); \
} while (false)
#define NAME_PLACEHOLDER_LEN 14
#define PRINT_DASH(n) \
for (; n > 0; n--) { \
putchar('-'); \
}
/********************************************************************************
* This function prints the allocated memory for a specific security state.
* Values are grouped by exception level and core. The memory usage for the
* global context and the total memory for the security state are also computed.
*******************************************************************************/
static size_t report_allocated_memory(unsigned int security_state_idx)
{
size_t core_total = 0U;
size_t el3_total = 0U;
#if CTX_INCLUDE_EL2_REGS
size_t el2_total = 0U;
#else
size_t el1_total = 0U;
#endif /* CTX_INCLUDE_EL2_REGS */
size_t other_total = 0U;
size_t total = 0U;
size_t per_world_ctx_size = 0U;
PRINT_MEM_USAGE_SEPARATOR();
printf("| Core | EL3 ");
#if CTX_INCLUDE_EL2_REGS
printf("| EL2 ");
#else
printf("| EL1 ");
#endif /* CTX_INCLUDE_EL2_REGS */
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;
#if CTX_INCLUDE_EL2_REGS
size_t el2_size = 0U;
#else
size_t el1_size = 0U;
#endif /* CTX_INCLUDE_EL2_REGS */
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);
#if CTX_INCLUDE_EL2_REGS
el2_size = sizeof(ctx->el2_sysregs_ctx);
#else
el1_size = sizeof(ctx->el1_sysregs_ctx);
#endif /* CTX_INCLUDE_EL2_REGS */
size_other = core_total - el3_size;
printf("| %9u | %8luB ", i, el3_size);
#if CTX_INCLUDE_EL2_REGS
size_other -= el2_size;
printf("| %8luB ", el2_size);
#else
size_other -= el1_size;
printf("| %8luB ", el1_size);
#endif /* CTX_INCLUDE_EL2_REGS */
printf("| %8luB | %8luB |\n", size_other, core_total);
el3_total += el3_size;
#if CTX_INCLUDE_EL2_REGS
el2_total += el2_size;
#else
el1_total += el1_size;
#endif /* CTX_INCLUDE_EL2_REGS */
other_total += size_other;
total += core_total;
}
PRINT_MEM_USAGE_SEPARATOR();
PRINT_MEM_USAGE_SEPARATOR();
printf("| All | %8luB ", el3_total);
#if CTX_INCLUDE_EL2_REGS
printf("| %8luB ", el2_total);
#else
printf("| %8luB ", el1_total);
#endif /* CTX_INCLUDE_EL2_REGS */
printf("| %8luB | %8luB |\n", other_total, total);
PRINT_MEM_USAGE_SEPARATOR();
printf("\n");
/* Compute memory usage for the global context */
per_world_ctx_size = sizeof(per_world_context[security_state_idx]);
total += per_world_ctx_size;
printf("Per-world context: %luB\n\n", per_world_ctx_size);
printf("TOTAL: %luB\n", total);
return total;
}
/********************************************************************************
* Reports the allocated memory for every security state and then reports the
* total system-wide allocated memory.
*******************************************************************************/
void report_ctx_memory_usage(void)
{
INFO("Context memory allocation:\n");
size_t total = 0U;
for (unsigned int i = 0U; i < CPU_CONTEXT_NUM; i++) {
const char *context_name = get_context_name_by_idx(i);
size_t len = 0U;
printf("Memory usage for %s:\n", context_name);
total += report_allocated_memory(i);
printf("------------------------");
len = NAME_PLACEHOLDER_LEN - printf("End %s", context_name);
PRINT_DASH(len);
printf("-----------------------\n\n");
}
printf("Total context memory allocated: %luB\n\n", total);
}