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