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 101 if (is_ctx_pauth_supported()) { 102 PRINT_SINGLE_MEM_USAGE_SEP_BLOCK(); 103 } 104 105 PRINT_MEM_USAGE_SEPARATOR(); 106 107 cpu_context_t *ctx = (cpu_context_t *)cm_get_context_by_index(i, 108 security_state_idx); 109 core_total = sizeof(*ctx); 110 el3_size = sizeof(ctx->el3state_ctx); 111 gp_size = sizeof(ctx->gpregs_ctx); 112 size_other = core_total - (el3_size + gp_size); 113 printf("| %9u | %8luB | %8luB ", i, gp_size, el3_size); 114 115 #if CTX_INCLUDE_EL2_REGS 116 el2_size = sizeof(ctx->el2_sysregs_ctx); 117 size_other -= el2_size; 118 el2_total += el2_size; 119 printf("| %8luB ", el2_size); 120 #else 121 el1_size = sizeof(ctx->el1_sysregs_ctx); 122 size_other -= el1_size; 123 el1_total += el1_size; 124 printf("| %8luB ", el1_size); 125 #endif /* CTX_INCLUDE_EL2_REGS */ 126 127 #if CTX_INCLUDE_PAUTH_REGS 128 if (is_ctx_pauth_supported()) { 129 size_t pauth_size = sizeof(ctx->pauth_ctx); 130 size_other -= pauth_size; 131 pauth_total += pauth_size; 132 printf("| %8luB ", pauth_size); 133 } 134 #endif 135 printf("| %8luB | %8luB |\n", size_other, core_total); 136 137 gp_total += gp_size; 138 el3_total += el3_size; 139 other_total += size_other; 140 total += core_total; 141 } 142 143 if (is_ctx_pauth_supported()) { 144 PRINT_SINGLE_MEM_USAGE_SEP_BLOCK(); 145 } 146 147 PRINT_MEM_USAGE_SEPARATOR(); 148 149 if (is_ctx_pauth_supported()) { 150 PRINT_SINGLE_MEM_USAGE_SEP_BLOCK(); 151 } 152 153 PRINT_MEM_USAGE_SEPARATOR(); 154 155 printf("| All | %8luB | %8luB ", gp_total, el3_total); 156 157 #if CTX_INCLUDE_EL2_REGS 158 printf("| %8luB ", el2_total); 159 #else 160 printf("| %8luB ", el1_total); 161 #endif /* CTX_INCLUDE_EL2_REGS */ 162 163 if (is_ctx_pauth_supported()) { 164 printf("| %8luB ", pauth_total); 165 } 166 167 printf("| %8luB | %8luB |\n", other_total, total); 168 169 if (is_ctx_pauth_supported()) { 170 PRINT_SINGLE_MEM_USAGE_SEP_BLOCK(); 171 } 172 PRINT_MEM_USAGE_SEPARATOR(); 173 printf("\n"); 174 175 /* Compute memory usage for the global context */ 176 per_world_ctx_size = sizeof(per_world_context[security_state_idx]); 177 178 total += per_world_ctx_size; 179 180 printf("Per-world context: %luB\n\n", per_world_ctx_size); 181 182 printf("TOTAL: %luB\n", total); 183 184 return total; 185 } 186 187 /******************************************************************************** 188 * Reports the allocated memory for every security state and then reports the 189 * total system-wide allocated memory. 190 *******************************************************************************/ 191 void report_ctx_memory_usage(void) 192 { 193 INFO("Context memory allocation:\n"); 194 195 size_t total = 0U; 196 197 for (unsigned int i = 0U; i < CPU_CONTEXT_NUM; i++) { 198 const char *context_name = get_context_name_by_idx(i); 199 size_t len = 0U; 200 201 printf("Memory usage for %s:\n", context_name); 202 total += report_allocated_memory(i); 203 printf("------------------------"); 204 len = NAME_PLACEHOLDER_LEN - printf("End %s", context_name); 205 PRINT_DASH(len); 206 printf("-----------------------\n\n"); 207 } 208 209 printf("Total context memory allocated: %luB\n\n", total); 210 } 211