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