1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2015, Linaro Limited 4 */ 5 #include <compiler.h> 6 #include <stdio.h> 7 #include <trace.h> 8 #include <kernel/pseudo_ta.h> 9 #include <mm/tee_pager.h> 10 #include <mm/tee_mm.h> 11 #include <string.h> 12 #include <string_ext.h> 13 #include <malloc.h> 14 15 #define TA_NAME "stats.ta" 16 17 #define STATS_UUID \ 18 { 0xd96a5b40, 0xe2c7, 0xb1af, \ 19 { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } 20 21 #define STATS_CMD_PAGER_STATS 0 22 #define STATS_CMD_ALLOC_STATS 1 23 #define STATS_CMD_MEMLEAK_STATS 2 24 25 #define STATS_NB_POOLS 4 26 27 static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 28 { 29 struct malloc_stats *stats; 30 uint32_t size_to_retrieve; 31 uint32_t pool_id; 32 uint32_t i; 33 34 /* 35 * p[0].value.a = pool id (from 0 to n) 36 * - 0 means all the pools to be retrieved 37 * - 1..n means pool id 38 * p[0].value.b = 0 if no reset of the stats 39 * p[1].memref.buffer = output buffer to struct malloc_stats 40 */ 41 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 42 TEE_PARAM_TYPE_MEMREF_OUTPUT, 43 TEE_PARAM_TYPE_NONE, 44 TEE_PARAM_TYPE_NONE) != type) { 45 return TEE_ERROR_BAD_PARAMETERS; 46 } 47 48 pool_id = p[0].value.a; 49 if (pool_id > STATS_NB_POOLS) 50 return TEE_ERROR_BAD_PARAMETERS; 51 52 size_to_retrieve = sizeof(struct malloc_stats); 53 if (!pool_id) 54 size_to_retrieve *= STATS_NB_POOLS; 55 56 if (p[1].memref.size < size_to_retrieve) { 57 p[1].memref.size = size_to_retrieve; 58 return TEE_ERROR_SHORT_BUFFER; 59 } 60 p[1].memref.size = size_to_retrieve; 61 stats = p[1].memref.buffer; 62 63 for (i = 1; i <= STATS_NB_POOLS; i++) { 64 if ((pool_id) && (i != pool_id)) 65 continue; 66 67 switch (i) { 68 case 1: 69 malloc_get_stats(stats); 70 strlcpy(stats->desc, "Heap", sizeof(stats->desc)); 71 if (p[0].value.b) 72 malloc_reset_stats(); 73 break; 74 75 case 2: 76 EMSG("public DDR not managed by secure side anymore"); 77 break; 78 79 case 3: 80 tee_mm_get_pool_stats(&tee_mm_sec_ddr, stats, 81 !!p[0].value.b); 82 strlcpy(stats->desc, "Secure DDR", sizeof(stats->desc)); 83 break; 84 85 #ifdef CFG_VIRTUALIZATION 86 case 4: 87 nex_malloc_get_stats(stats); 88 strlcpy(stats->desc, "KHeap", sizeof(stats->desc)); 89 if (p[0].value.b) 90 nex_malloc_reset_stats(); 91 break; 92 #endif 93 default: 94 EMSG("Wrong pool id"); 95 break; 96 } 97 98 stats++; 99 } 100 101 return TEE_SUCCESS; 102 } 103 104 static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 105 { 106 struct tee_pager_stats stats; 107 108 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 109 TEE_PARAM_TYPE_VALUE_OUTPUT, 110 TEE_PARAM_TYPE_VALUE_OUTPUT, 111 TEE_PARAM_TYPE_NONE) != type) { 112 EMSG("expect 3 output values as argument"); 113 return TEE_ERROR_BAD_PARAMETERS; 114 } 115 116 tee_pager_get_stats(&stats); 117 p[0].value.a = stats.npages; 118 p[0].value.b = stats.npages_all; 119 p[1].value.a = stats.ro_hits; 120 p[1].value.b = stats.rw_hits; 121 p[2].value.a = stats.hidden_hits; 122 p[2].value.b = stats.zi_released; 123 124 return TEE_SUCCESS; 125 } 126 127 static TEE_Result get_memleak_stats(uint32_t type, 128 TEE_Param p[TEE_NUM_PARAMS] __unused) 129 { 130 131 if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, 132 TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) 133 return TEE_ERROR_BAD_PARAMETERS; 134 135 mdbg_check(1); 136 137 return TEE_SUCCESS; 138 } 139 140 /* 141 * Trusted Application Entry Points 142 */ 143 144 static TEE_Result invoke_command(void *psess __unused, 145 uint32_t cmd, uint32_t ptypes, 146 TEE_Param params[TEE_NUM_PARAMS]) 147 { 148 switch (cmd) { 149 case STATS_CMD_PAGER_STATS: 150 return get_pager_stats(ptypes, params); 151 case STATS_CMD_ALLOC_STATS: 152 return get_alloc_stats(ptypes, params); 153 case STATS_CMD_MEMLEAK_STATS: 154 return get_memleak_stats(ptypes, params); 155 default: 156 break; 157 } 158 return TEE_ERROR_BAD_PARAMETERS; 159 } 160 161 pseudo_ta_register(.uuid = STATS_UUID, .name = TA_NAME, 162 .flags = PTA_DEFAULT_FLAGS, 163 .invoke_command_entry_point = invoke_command); 164