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