xref: /optee_os/core/pta/stats.c (revision 9f34db38245c9b3a4e6e7e63eb78a75e23ab2da3)
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 <trace.h>
19 
20 static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
21 {
22 	struct pta_stats_alloc *stats = NULL;
23 	uint32_t size_to_retrieve = 0;
24 	uint32_t pool_id = 0;
25 	uint32_t i = 0;
26 
27 	/*
28 	 * p[0].value.a = pool id (from 0 to n)
29 	 *   - 0 means all the pools to be retrieved
30 	 *   - 1..n means pool id
31 	 * p[0].value.b = 0 if no reset of the stats
32 	 * p[1].memref.buffer = output buffer to struct pta_stats_alloc
33 	 */
34 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
35 			    TEE_PARAM_TYPE_MEMREF_OUTPUT,
36 			    TEE_PARAM_TYPE_NONE,
37 			    TEE_PARAM_TYPE_NONE) != type) {
38 		return TEE_ERROR_BAD_PARAMETERS;
39 	}
40 
41 	pool_id = p[0].value.a;
42 	if (pool_id > STATS_NB_POOLS)
43 		return TEE_ERROR_BAD_PARAMETERS;
44 
45 	size_to_retrieve = sizeof(struct pta_stats_alloc);
46 	if (pool_id == ALLOC_ID_ALL)
47 		size_to_retrieve *= STATS_NB_POOLS;
48 
49 	if (p[1].memref.size < size_to_retrieve) {
50 		p[1].memref.size = size_to_retrieve;
51 		return TEE_ERROR_SHORT_BUFFER;
52 	}
53 	p[1].memref.size = size_to_retrieve;
54 	stats = p[1].memref.buffer;
55 
56 	for (i = ALLOC_ID_HEAP; i <= STATS_NB_POOLS; i++) {
57 		if (pool_id != ALLOC_ID_ALL && i != pool_id)
58 			continue;
59 
60 		switch (i) {
61 		case ALLOC_ID_HEAP:
62 			malloc_get_stats(stats);
63 			strlcpy(stats->desc, "Heap", sizeof(stats->desc));
64 			if (p[0].value.b)
65 				malloc_reset_stats();
66 			break;
67 
68 		case ALLOC_ID_PUBLIC_DDR:
69 			EMSG("public DDR not managed by secure side anymore");
70 			break;
71 
72 		case ALLOC_ID_TA_RAM:
73 			phys_mem_stats(stats, p[0].value.b);
74 			strlcpy(stats->desc, "Physical TA memory",
75 				sizeof(stats->desc));
76 			break;
77 
78 #ifdef CFG_NS_VIRTUALIZATION
79 		case ALLOC_ID_NEXUS_HEAP:
80 			nex_malloc_get_stats(stats);
81 			strlcpy(stats->desc, "KHeap", sizeof(stats->desc));
82 			if (p[0].value.b)
83 				nex_malloc_reset_stats();
84 			break;
85 #endif
86 		default:
87 			EMSG("Wrong pool id");
88 			break;
89 		}
90 
91 		stats++;
92 	}
93 
94 	return TEE_SUCCESS;
95 }
96 
97 static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
98 {
99 	struct tee_pager_stats stats = { };
100 
101 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
102 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
103 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
104 			    TEE_PARAM_TYPE_NONE) != type) {
105 		EMSG("expect 3 output values as argument");
106 		return TEE_ERROR_BAD_PARAMETERS;
107 	}
108 
109 	tee_pager_get_stats(&stats);
110 	p[0].value.a = stats.npages;
111 	p[0].value.b = stats.npages_all;
112 	p[1].value.a = stats.ro_hits;
113 	p[1].value.b = stats.rw_hits;
114 	p[2].value.a = stats.hidden_hits;
115 	p[2].value.b = stats.zi_released;
116 
117 	return TEE_SUCCESS;
118 }
119 
120 static TEE_Result get_memleak_stats(uint32_t type,
121 				    TEE_Param p[TEE_NUM_PARAMS] __maybe_unused)
122 {
123 
124 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE,
125 			    TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type)
126 		return TEE_ERROR_BAD_PARAMETERS;
127 
128 	mdbg_check(1);
129 
130 	return TEE_SUCCESS;
131 }
132 
133 static TEE_Result get_user_ta_stats(uint32_t type,
134 				    TEE_Param p[TEE_NUM_PARAMS] __maybe_unused)
135 {
136 	uint32_t res = TEE_SUCCESS;
137 
138 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
139 			    TEE_PARAM_TYPE_NONE,
140 			    TEE_PARAM_TYPE_NONE,
141 			    TEE_PARAM_TYPE_NONE) != type)
142 		return TEE_ERROR_BAD_PARAMETERS;
143 
144 #if defined(CFG_TA_STATS)
145 	res = tee_ta_instance_stats(p[0].memref.buffer,
146 				    &p[0].memref.size);
147 	if (res != TEE_SUCCESS)
148 		DMSG("tee_ta_dump_stats return: 0x%"PRIx32, res);
149 #else
150 	res = TEE_ERROR_NOT_SUPPORTED;
151 #endif
152 	return res;
153 }
154 
155 static TEE_Result get_system_time(uint32_t type,
156 				  TEE_Param p[TEE_NUM_PARAMS])
157 {
158 	TEE_Result ret = TEE_ERROR_GENERIC;
159 	TEE_Time ree_time = { };
160 	TEE_Time tee_time = { };
161 
162 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
163 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
164 			    TEE_PARAM_TYPE_NONE,
165 			    TEE_PARAM_TYPE_NONE) != type)
166 		return TEE_ERROR_BAD_PARAMETERS;
167 
168 	ret = tee_time_get_sys_time(&tee_time);
169 	if (ret)
170 		return ret;
171 
172 	ret = tee_time_get_ree_time(&ree_time);
173 	if (ret)
174 		return ret;
175 
176 	p[0].value.a = ree_time.seconds;
177 	p[0].value.b = ree_time.millis;
178 	p[1].value.a = tee_time.seconds;
179 	p[1].value.b = tee_time.millis;
180 
181 	return TEE_SUCCESS;
182 }
183 
184 static TEE_Result print_driver_info(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
185 {
186 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
187 			    TEE_PARAM_TYPE_NONE,
188 			    TEE_PARAM_TYPE_NONE,
189 			    TEE_PARAM_TYPE_NONE) != type)
190 		return TEE_ERROR_BAD_PARAMETERS;
191 
192 	switch (p[0].value.a) {
193 	case STATS_DRIVER_TYPE_CLOCK:
194 		clk_print_tree();
195 		break;
196 	case STATS_DRIVER_TYPE_REGULATOR:
197 		regulator_print_tree();
198 		break;
199 	default:
200 		return TEE_ERROR_BAD_PARAMETERS;
201 	}
202 
203 	return TEE_SUCCESS;
204 }
205 
206 /*
207  * Trusted Application Entry Points
208  */
209 
210 static TEE_Result invoke_command(void *psess __unused,
211 				 uint32_t cmd, uint32_t ptypes,
212 				 TEE_Param params[TEE_NUM_PARAMS])
213 {
214 	switch (cmd) {
215 	case STATS_CMD_PAGER_STATS:
216 		return get_pager_stats(ptypes, params);
217 	case STATS_CMD_ALLOC_STATS:
218 		return get_alloc_stats(ptypes, params);
219 	case STATS_CMD_MEMLEAK_STATS:
220 		return get_memleak_stats(ptypes, params);
221 	case STATS_CMD_TA_STATS:
222 		return get_user_ta_stats(ptypes, params);
223 	case STATS_CMD_GET_TIME:
224 		return get_system_time(ptypes, params);
225 	case STATS_CMD_PRINT_DRIVER_INFO:
226 		return print_driver_info(ptypes, params);
227 	default:
228 		break;
229 	}
230 	return TEE_ERROR_BAD_PARAMETERS;
231 }
232 
233 pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta",
234 		   .flags = PTA_DEFAULT_FLAGS,
235 		   .invoke_command_entry_point = invoke_command);
236