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
get_alloc_stats(uint32_t type,TEE_Param p[TEE_NUM_PARAMS])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
get_pager_stats(uint32_t type,TEE_Param p[TEE_NUM_PARAMS])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
get_memleak_stats(uint32_t type,TEE_Param p[TEE_NUM_PARAMS]__unused)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
invoke_command(void * psess __unused,uint32_t cmd,uint32_t ptypes,TEE_Param params[TEE_NUM_PARAMS])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