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