1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2015, Linaro Limited 4 */ 5 #include <compiler.h> 6 #include <drivers/clk.h> 7 #include <drivers/regulator.h> 8 #include <kernel/pseudo_ta.h> 9 #include <kernel/tee_time.h> 10 #include <malloc.h> 11 #include <mm/phys_mem.h> 12 #include <mm/tee_mm.h> 13 #include <mm/tee_pager.h> 14 #include <pta_stats.h> 15 #include <string.h> 16 #include <string_ext.h> 17 #include <tee_api_types.h> 18 #include <tee/tee_fs.h> 19 #include <trace.h> 20 21 static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 22 { 23 struct pta_stats_alloc *stats = NULL; 24 uint32_t size_to_retrieve = 0; 25 uint32_t pool_id = 0; 26 uint32_t i = 0; 27 28 /* 29 * p[0].value.a = pool id (from 0 to n) 30 * - 0 means all the pools to be retrieved 31 * - 1..n means pool id 32 * p[0].value.b = 0 if no reset of the stats 33 * p[1].memref.buffer = output buffer to struct pta_stats_alloc 34 */ 35 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 36 TEE_PARAM_TYPE_MEMREF_OUTPUT, 37 TEE_PARAM_TYPE_NONE, 38 TEE_PARAM_TYPE_NONE) != type) { 39 return TEE_ERROR_BAD_PARAMETERS; 40 } 41 42 pool_id = p[0].value.a; 43 if (pool_id > STATS_NB_POOLS) 44 return TEE_ERROR_BAD_PARAMETERS; 45 46 size_to_retrieve = sizeof(struct pta_stats_alloc); 47 if (pool_id == ALLOC_ID_ALL) 48 size_to_retrieve *= STATS_NB_POOLS; 49 50 if (p[1].memref.size < size_to_retrieve) { 51 p[1].memref.size = size_to_retrieve; 52 return TEE_ERROR_SHORT_BUFFER; 53 } 54 p[1].memref.size = size_to_retrieve; 55 stats = p[1].memref.buffer; 56 memset(stats, 0, size_to_retrieve); 57 58 for (i = ALLOC_ID_HEAP; i <= STATS_NB_POOLS; i++) { 59 if (pool_id != ALLOC_ID_ALL && i != pool_id) 60 continue; 61 62 switch (i) { 63 case ALLOC_ID_HEAP: 64 malloc_get_stats(stats); 65 strlcpy(stats->desc, "Heap", sizeof(stats->desc)); 66 if (p[0].value.b) 67 malloc_reset_stats(); 68 break; 69 70 case ALLOC_ID_PUBLIC_DDR: 71 EMSG("public DDR not managed by secure side anymore"); 72 strlcpy(stats->desc, "Public DDR (deprecated)", 73 sizeof(stats->desc)); 74 break; 75 76 case ALLOC_ID_TA_RAM: 77 phys_mem_stats(stats, p[0].value.b); 78 strlcpy(stats->desc, "Physical TA memory", 79 sizeof(stats->desc)); 80 break; 81 82 case ALLOC_ID_NEXUS_HEAP: 83 #ifdef CFG_NS_VIRTUALIZATION 84 nex_malloc_get_stats(stats); 85 strlcpy(stats->desc, "KHeap", sizeof(stats->desc)); 86 if (p[0].value.b) 87 nex_malloc_reset_stats(); 88 #else 89 strlcpy(stats->desc, "KHeap (disabled)", 90 sizeof(stats->desc)); 91 #endif 92 break; 93 case ALLOC_ID_RPMB: 94 if (rpmb_mem_stats(stats, p[0].value.b)) 95 strlcpy(stats->desc, 96 "RPMB secure storage (no data)", 97 sizeof(stats->desc)); 98 else 99 strlcpy(stats->desc, "RPMB secure storage", 100 sizeof(stats->desc)); 101 break; 102 default: 103 EMSG("Wrong pool id"); 104 break; 105 } 106 107 stats++; 108 } 109 110 return TEE_SUCCESS; 111 } 112 113 static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 114 { 115 struct tee_pager_stats stats = { }; 116 117 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 118 TEE_PARAM_TYPE_VALUE_OUTPUT, 119 TEE_PARAM_TYPE_VALUE_OUTPUT, 120 TEE_PARAM_TYPE_NONE) != type) { 121 EMSG("expect 3 output values as argument"); 122 return TEE_ERROR_BAD_PARAMETERS; 123 } 124 125 tee_pager_get_stats(&stats); 126 p[0].value.a = stats.npages; 127 p[0].value.b = stats.npages_all; 128 p[1].value.a = stats.ro_hits; 129 p[1].value.b = stats.rw_hits; 130 p[2].value.a = stats.hidden_hits; 131 p[2].value.b = stats.zi_released; 132 133 return TEE_SUCCESS; 134 } 135 136 static TEE_Result get_memleak_stats(uint32_t type, 137 TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) 138 { 139 140 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, 141 TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) 142 return TEE_ERROR_BAD_PARAMETERS; 143 144 mdbg_check(1); 145 146 return TEE_SUCCESS; 147 } 148 149 static TEE_Result get_user_ta_stats(uint32_t type, 150 TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) 151 { 152 uint32_t res = TEE_SUCCESS; 153 154 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 155 TEE_PARAM_TYPE_NONE, 156 TEE_PARAM_TYPE_NONE, 157 TEE_PARAM_TYPE_NONE) != type) 158 return TEE_ERROR_BAD_PARAMETERS; 159 160 #if defined(CFG_TA_STATS) 161 res = tee_ta_instance_stats(p[0].memref.buffer, 162 &p[0].memref.size); 163 if (res != TEE_SUCCESS) 164 DMSG("tee_ta_dump_stats return: 0x%"PRIx32, res); 165 #else 166 res = TEE_ERROR_NOT_SUPPORTED; 167 #endif 168 return res; 169 } 170 171 static TEE_Result get_system_time(uint32_t type, 172 TEE_Param p[TEE_NUM_PARAMS]) 173 { 174 TEE_Result ret = TEE_ERROR_GENERIC; 175 TEE_Time ree_time = { }; 176 TEE_Time tee_time = { }; 177 178 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 179 TEE_PARAM_TYPE_VALUE_OUTPUT, 180 TEE_PARAM_TYPE_NONE, 181 TEE_PARAM_TYPE_NONE) != type) 182 return TEE_ERROR_BAD_PARAMETERS; 183 184 ret = tee_time_get_sys_time(&tee_time); 185 if (ret) 186 return ret; 187 188 ret = tee_time_get_ree_time(&ree_time); 189 if (ret) 190 return ret; 191 192 p[0].value.a = ree_time.seconds; 193 p[0].value.b = ree_time.millis; 194 p[1].value.a = tee_time.seconds; 195 p[1].value.b = tee_time.millis; 196 197 return TEE_SUCCESS; 198 } 199 200 static TEE_Result print_driver_info(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 201 { 202 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 203 TEE_PARAM_TYPE_NONE, 204 TEE_PARAM_TYPE_NONE, 205 TEE_PARAM_TYPE_NONE) != type) 206 return TEE_ERROR_BAD_PARAMETERS; 207 208 switch (p[0].value.a) { 209 case STATS_DRIVER_TYPE_CLOCK: 210 clk_print_tree(); 211 break; 212 case STATS_DRIVER_TYPE_REGULATOR: 213 regulator_print_tree(); 214 break; 215 default: 216 return TEE_ERROR_BAD_PARAMETERS; 217 } 218 219 return TEE_SUCCESS; 220 } 221 222 /* 223 * Trusted Application Entry Points 224 */ 225 226 static TEE_Result invoke_command(void *psess __unused, 227 uint32_t cmd, uint32_t ptypes, 228 TEE_Param params[TEE_NUM_PARAMS]) 229 { 230 switch (cmd) { 231 case STATS_CMD_PAGER_STATS: 232 return get_pager_stats(ptypes, params); 233 case STATS_CMD_ALLOC_STATS: 234 return get_alloc_stats(ptypes, params); 235 case STATS_CMD_MEMLEAK_STATS: 236 return get_memleak_stats(ptypes, params); 237 case STATS_CMD_TA_STATS: 238 return get_user_ta_stats(ptypes, params); 239 case STATS_CMD_GET_TIME: 240 return get_system_time(ptypes, params); 241 case STATS_CMD_PRINT_DRIVER_INFO: 242 return print_driver_info(ptypes, params); 243 default: 244 break; 245 } 246 return TEE_ERROR_BAD_PARAMETERS; 247 } 248 249 pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta", 250 .flags = PTA_DEFAULT_FLAGS, 251 .invoke_command_entry_point = invoke_command); 252