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