xref: /optee_os/core/pta/stats.c (revision af3fb62410645ac9636d27c3d1db72c0c9fca913)
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