1 /* 2 * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <string.h> 8 9 #include <arch_features.h> 10 #include <common/debug.h> 11 #include <context.h> 12 #include <lib/el3_runtime/context_mgmt.h> 13 #include <lib/el3_runtime/cpu_data.h> 14 15 /******************************************************************************** 16 * Function that returns the corresponding string constant for a security state 17 * index. 18 *******************************************************************************/ 19 static const char *get_context_name_by_idx(unsigned int security_state_idx) 20 { 21 assert(security_state_idx < CPU_CONTEXT_NUM); 22 static const char * const state_names[] = { 23 "Secure", 24 "Non Secure" 25 #if ENABLE_RME 26 , "Realm" 27 #endif /* ENABLE_RME */ 28 }; 29 return state_names[security_state_idx]; 30 } 31 32 #define PRINT_MEM_USAGE_SEPARATOR() \ 33 do { \ 34 printf("+-----------+-----------+-----------" \ 35 "+-----------+-----------+-----------+\n"); \ 36 } while (false) 37 38 #define NAME_PLACEHOLDER_LEN 14 39 40 #define PRINT_DASH(n) \ 41 for (; n > 0; n--) { \ 42 putchar('-'); \ 43 } 44 45 #define PRINT_SINGLE_MEM_USAGE_SEP_BLOCK() \ 46 do { \ 47 printf("+-----------"); \ 48 } while (false) 49 50 /******************************************************************************** 51 * This function prints the allocated memory for a specific security state. 52 * Values are grouped by exception level and core. The memory usage for the 53 * global context and the total memory for the security state are also computed. 54 *******************************************************************************/ 55 static size_t report_allocated_memory(unsigned int security_state_idx) 56 { 57 size_t core_total = 0U; 58 size_t gp_total = 0U; 59 size_t el3_total = 0U; 60 size_t other_total = 0U; 61 size_t total = 0U; 62 size_t per_world_ctx_size = 0U; 63 64 #if CTX_INCLUDE_EL2_REGS 65 size_t el2_total = 0U; 66 #else 67 size_t el1_total = 0U; 68 #endif /* CTX_INCLUDE_EL2_REGS */ 69 size_t pauth_total = 0U; 70 71 if (is_ctx_pauth_supported()) { 72 PRINT_SINGLE_MEM_USAGE_SEP_BLOCK(); 73 } 74 75 PRINT_MEM_USAGE_SEPARATOR(); 76 77 printf("| Core | GP | EL3 "); 78 #if CTX_INCLUDE_EL2_REGS 79 printf("| EL2 "); 80 #else 81 printf("| EL1 "); 82 #endif /* CTX_INCLUDE_EL2_REGS */ 83 84 if (is_ctx_pauth_supported()) { 85 printf("| PAUTH "); 86 } 87 88 printf("| Other | Total |\n"); 89 90 /* Compute memory usage for each core's context */ 91 for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) { 92 size_t size_other = 0U; 93 size_t el3_size = 0U; 94 size_t gp_size = 0U; 95 #if CTX_INCLUDE_EL2_REGS 96 size_t el2_size = 0U; 97 #else 98 size_t el1_size = 0U; 99 #endif /* CTX_INCLUDE_EL2_REGS */ 100 size_t pauth_size = 0U; 101 102 if (is_ctx_pauth_supported()) { 103 PRINT_SINGLE_MEM_USAGE_SEP_BLOCK(); 104 } 105 106 PRINT_MEM_USAGE_SEPARATOR(); 107 108 cpu_context_t *ctx = (cpu_context_t *)cm_get_context_by_index(i, 109 security_state_idx); 110 core_total = sizeof(*ctx); 111 el3_size = sizeof(ctx->el3state_ctx); 112 gp_size = sizeof(ctx->gpregs_ctx); 113 size_other = core_total - (el3_size + gp_size); 114 printf("| %9u | %8luB | %8luB ", i, gp_size, el3_size); 115 116 #if CTX_INCLUDE_EL2_REGS 117 el2_size = sizeof(ctx->el2_sysregs_ctx); 118 size_other -= el2_size; 119 el2_total += el2_size; 120 printf("| %8luB ", el2_size); 121 #else 122 el1_size = sizeof(ctx->el1_sysregs_ctx); 123 size_other -= el1_size; 124 el1_total += el1_size; 125 printf("| %8luB ", el1_size); 126 #endif /* CTX_INCLUDE_EL2_REGS */ 127 128 if (is_ctx_pauth_supported()) { 129 pauth_size = sizeof(ctx->pauth_ctx); 130 size_other -= pauth_size; 131 pauth_total += pauth_size; 132 printf("| %8luB ", pauth_size); 133 } 134 printf("| %8luB | %8luB |\n", size_other, core_total); 135 136 gp_total += gp_size; 137 el3_total += el3_size; 138 other_total += size_other; 139 total += core_total; 140 } 141 142 if (is_ctx_pauth_supported()) { 143 PRINT_SINGLE_MEM_USAGE_SEP_BLOCK(); 144 } 145 146 PRINT_MEM_USAGE_SEPARATOR(); 147 148 if (is_ctx_pauth_supported()) { 149 PRINT_SINGLE_MEM_USAGE_SEP_BLOCK(); 150 } 151 152 PRINT_MEM_USAGE_SEPARATOR(); 153 154 printf("| All | %8luB | %8luB ", gp_total, el3_total); 155 156 #if CTX_INCLUDE_EL2_REGS 157 printf("| %8luB ", el2_total); 158 #else 159 printf("| %8luB ", el1_total); 160 #endif /* CTX_INCLUDE_EL2_REGS */ 161 162 if (is_ctx_pauth_supported()) { 163 printf("| %8luB ", pauth_total); 164 } 165 166 printf("| %8luB | %8luB |\n", other_total, total); 167 168 if (is_ctx_pauth_supported()) { 169 PRINT_SINGLE_MEM_USAGE_SEP_BLOCK(); 170 } 171 PRINT_MEM_USAGE_SEPARATOR(); 172 printf("\n"); 173 174 /* Compute memory usage for the global context */ 175 per_world_ctx_size = sizeof(per_world_context[security_state_idx]); 176 177 total += per_world_ctx_size; 178 179 printf("Per-world context: %luB\n\n", per_world_ctx_size); 180 181 printf("TOTAL: %luB\n", total); 182 183 return total; 184 } 185 186 /******************************************************************************** 187 * Reports the allocated memory for every security state and then reports the 188 * total system-wide allocated memory. 189 *******************************************************************************/ 190 void report_ctx_memory_usage(void) 191 { 192 INFO("Context memory allocation:\n"); 193 194 size_t total = 0U; 195 196 for (unsigned int i = 0U; i < CPU_CONTEXT_NUM; i++) { 197 const char *context_name = get_context_name_by_idx(i); 198 size_t len = 0U; 199 200 printf("Memory usage for %s:\n", context_name); 201 total += report_allocated_memory(i); 202 printf("------------------------"); 203 len = NAME_PLACEHOLDER_LEN - printf("End %s", context_name); 204 PRINT_DASH(len); 205 printf("-----------------------\n\n"); 206 } 207 208 printf("Total context memory allocated: %luB\n\n", total); 209 } 210