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