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 break; 73 74 case ALLOC_ID_TA_RAM: 75 phys_mem_stats(stats, p[0].value.b); 76 strlcpy(stats->desc, "Physical TA memory", 77 sizeof(stats->desc)); 78 break; 79 80 case ALLOC_ID_NEXUS_HEAP: 81 #ifdef CFG_NS_VIRTUALIZATION 82 nex_malloc_get_stats(stats); 83 strlcpy(stats->desc, "KHeap", sizeof(stats->desc)); 84 if (p[0].value.b) 85 nex_malloc_reset_stats(); 86 #else 87 strlcpy(stats->desc, "KHeap (disabled)", 88 sizeof(stats->desc)); 89 #endif 90 break; 91 case ALLOC_ID_RPMB: 92 if (rpmb_mem_stats(stats, p[0].value.b)) 93 strlcpy(stats->desc, 94 "RPMB secure storage (no data)", 95 sizeof(stats->desc)); 96 else 97 strlcpy(stats->desc, "RPMB secure storage", 98 sizeof(stats->desc)); 99 break; 100 default: 101 EMSG("Wrong pool id"); 102 break; 103 } 104 105 stats++; 106 } 107 108 return TEE_SUCCESS; 109 } 110 111 static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 112 { 113 struct tee_pager_stats stats = { }; 114 115 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 116 TEE_PARAM_TYPE_VALUE_OUTPUT, 117 TEE_PARAM_TYPE_VALUE_OUTPUT, 118 TEE_PARAM_TYPE_NONE) != type) { 119 EMSG("expect 3 output values as argument"); 120 return TEE_ERROR_BAD_PARAMETERS; 121 } 122 123 tee_pager_get_stats(&stats); 124 p[0].value.a = stats.npages; 125 p[0].value.b = stats.npages_all; 126 p[1].value.a = stats.ro_hits; 127 p[1].value.b = stats.rw_hits; 128 p[2].value.a = stats.hidden_hits; 129 p[2].value.b = stats.zi_released; 130 131 return TEE_SUCCESS; 132 } 133 134 static TEE_Result get_memleak_stats(uint32_t type, 135 TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) 136 { 137 138 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, 139 TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) 140 return TEE_ERROR_BAD_PARAMETERS; 141 142 mdbg_check(1); 143 144 return TEE_SUCCESS; 145 } 146 147 static TEE_Result get_user_ta_stats(uint32_t type, 148 TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) 149 { 150 uint32_t res = TEE_SUCCESS; 151 152 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 153 TEE_PARAM_TYPE_NONE, 154 TEE_PARAM_TYPE_NONE, 155 TEE_PARAM_TYPE_NONE) != type) 156 return TEE_ERROR_BAD_PARAMETERS; 157 158 #if defined(CFG_TA_STATS) 159 res = tee_ta_instance_stats(p[0].memref.buffer, 160 &p[0].memref.size); 161 if (res != TEE_SUCCESS) 162 DMSG("tee_ta_dump_stats return: 0x%"PRIx32, res); 163 #else 164 res = TEE_ERROR_NOT_SUPPORTED; 165 #endif 166 return res; 167 } 168 169 static TEE_Result get_system_time(uint32_t type, 170 TEE_Param p[TEE_NUM_PARAMS]) 171 { 172 TEE_Result ret = TEE_ERROR_GENERIC; 173 TEE_Time ree_time = { }; 174 TEE_Time tee_time = { }; 175 176 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 177 TEE_PARAM_TYPE_VALUE_OUTPUT, 178 TEE_PARAM_TYPE_NONE, 179 TEE_PARAM_TYPE_NONE) != type) 180 return TEE_ERROR_BAD_PARAMETERS; 181 182 ret = tee_time_get_sys_time(&tee_time); 183 if (ret) 184 return ret; 185 186 ret = tee_time_get_ree_time(&ree_time); 187 if (ret) 188 return ret; 189 190 p[0].value.a = ree_time.seconds; 191 p[0].value.b = ree_time.millis; 192 p[1].value.a = tee_time.seconds; 193 p[1].value.b = tee_time.millis; 194 195 return TEE_SUCCESS; 196 } 197 198 static TEE_Result print_driver_info(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 199 { 200 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 201 TEE_PARAM_TYPE_NONE, 202 TEE_PARAM_TYPE_NONE, 203 TEE_PARAM_TYPE_NONE) != type) 204 return TEE_ERROR_BAD_PARAMETERS; 205 206 switch (p[0].value.a) { 207 case STATS_DRIVER_TYPE_CLOCK: 208 clk_print_tree(); 209 break; 210 case STATS_DRIVER_TYPE_REGULATOR: 211 regulator_print_tree(); 212 break; 213 default: 214 return TEE_ERROR_BAD_PARAMETERS; 215 } 216 217 return TEE_SUCCESS; 218 } 219 220 /* 221 * Trusted Application Entry Points 222 */ 223 224 static TEE_Result invoke_command(void *psess __unused, 225 uint32_t cmd, uint32_t ptypes, 226 TEE_Param params[TEE_NUM_PARAMS]) 227 { 228 switch (cmd) { 229 case STATS_CMD_PAGER_STATS: 230 return get_pager_stats(ptypes, params); 231 case STATS_CMD_ALLOC_STATS: 232 return get_alloc_stats(ptypes, params); 233 case STATS_CMD_MEMLEAK_STATS: 234 return get_memleak_stats(ptypes, params); 235 case STATS_CMD_TA_STATS: 236 return get_user_ta_stats(ptypes, params); 237 case STATS_CMD_GET_TIME: 238 return get_system_time(ptypes, params); 239 case STATS_CMD_PRINT_DRIVER_INFO: 240 return print_driver_info(ptypes, params); 241 default: 242 break; 243 } 244 return TEE_ERROR_BAD_PARAMETERS; 245 } 246 247 pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta", 248 .flags = PTA_DEFAULT_FLAGS, 249 .invoke_command_entry_point = invoke_command); 250