xref: /optee_os/core/pta/stats.c (revision 12f658b9e912d3f5934a07291e48ab2895712cd0)
15843bb75SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
25843bb75SJerome Forissier /*
35843bb75SJerome Forissier  * Copyright (c) 2015, Linaro Limited
45843bb75SJerome Forissier  */
55843bb75SJerome Forissier #include <compiler.h>
65843bb75SJerome Forissier #include <kernel/pseudo_ta.h>
7c90dc99bSWeizhao Jiang #include <kernel/tee_time.h>
8c90dc99bSWeizhao Jiang #include <malloc.h>
95843bb75SJerome Forissier #include <mm/tee_mm.h>
10c90dc99bSWeizhao Jiang #include <mm/tee_pager.h>
11c90dc99bSWeizhao Jiang #include <stdio.h>
125843bb75SJerome Forissier #include <string.h>
135843bb75SJerome Forissier #include <string_ext.h>
14c90dc99bSWeizhao Jiang #include <trace.h>
155843bb75SJerome Forissier 
165843bb75SJerome Forissier #define TA_NAME		"stats.ta"
175843bb75SJerome Forissier 
185843bb75SJerome Forissier #define STATS_UUID \
195843bb75SJerome Forissier 		{ 0xd96a5b40, 0xe2c7, 0xb1af, \
205843bb75SJerome Forissier 			{ 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } }
215843bb75SJerome Forissier 
225843bb75SJerome Forissier #define STATS_CMD_PAGER_STATS		0
235843bb75SJerome Forissier #define STATS_CMD_ALLOC_STATS		1
245843bb75SJerome Forissier #define STATS_CMD_MEMLEAK_STATS		2
25cb94c145SWeizhao Jiang /*
26cb94c145SWeizhao Jiang  * UTEE_ENTRY_FUNC_DUMP_MEMSTATS
27cb94c145SWeizhao Jiang  * [out]    memref[0]        Array of context information of loaded TAs
28cb94c145SWeizhao Jiang  *
29cb94c145SWeizhao Jiang  * Each cell of the TA information array contains:
30cb94c145SWeizhao Jiang  * TEE_UUID    TA UUID
31cb94c145SWeizhao Jiang  * uint32_t    Non zero if TA panicked, 0 otherwise
32cb94c145SWeizhao Jiang  * uint32_t    Number of sessions opened by the TA
33cb94c145SWeizhao Jiang  * uint32_t    Byte size currently allocated in TA heap
34cb94c145SWeizhao Jiang  * uint32_t    Max bytes allocated since last stats reset
35cb94c145SWeizhao Jiang  * uint32_t    TA heap pool byte size
36cb94c145SWeizhao Jiang  * uint32_t    Number of failed allocation requests
37cb94c145SWeizhao Jiang  * uint32_t    Biggest byte size which allocation failed
38cb94c145SWeizhao Jiang  * uint32_t    Biggest byte size which allocation succeeded
39cb94c145SWeizhao Jiang  */
40cb94c145SWeizhao Jiang #define STATS_CMD_TA_STATS		3
415843bb75SJerome Forissier 
42c90dc99bSWeizhao Jiang /*
43c90dc99bSWeizhao Jiang  * STATS_CMD_GET_TIME - Get both REE time and TEE time
44c90dc99bSWeizhao Jiang  *
45c90dc99bSWeizhao Jiang  * [out]    value[0].a        REE time as seen by OP-TEE in seconds
46c90dc99bSWeizhao Jiang  * [out]    value[0].b        REE time as seen by OP-TEE, milliseconds part
47c90dc99bSWeizhao Jiang  * [out]    value[1].a        TEE system time in seconds
48c90dc99bSWeizhao Jiang  * [out]    value[1].b        TEE system time, milliseconds part
49c90dc99bSWeizhao Jiang  */
50c90dc99bSWeizhao Jiang #define STATS_CMD_GET_TIME		4
51c90dc99bSWeizhao Jiang 
525843bb75SJerome Forissier #define STATS_NB_POOLS			4
535843bb75SJerome Forissier 
545843bb75SJerome Forissier static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
555843bb75SJerome Forissier {
56*12f658b9SEtienne Carriere 	struct pta_stats_alloc *stats = NULL;
57*12f658b9SEtienne Carriere 	uint32_t size_to_retrieve = 0;
58*12f658b9SEtienne Carriere 	uint32_t pool_id = 0;
59*12f658b9SEtienne Carriere 	uint32_t i = 0;
605843bb75SJerome Forissier 
615843bb75SJerome Forissier 	/*
625843bb75SJerome Forissier 	 * p[0].value.a = pool id (from 0 to n)
635843bb75SJerome Forissier 	 *   - 0 means all the pools to be retrieved
645843bb75SJerome Forissier 	 *   - 1..n means pool id
655843bb75SJerome Forissier 	 * p[0].value.b = 0 if no reset of the stats
662617f49fSEtienne Carriere 	 * p[1].memref.buffer = output buffer to struct pta_stats_alloc
675843bb75SJerome Forissier 	 */
685843bb75SJerome Forissier 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
695843bb75SJerome Forissier 			    TEE_PARAM_TYPE_MEMREF_OUTPUT,
705843bb75SJerome Forissier 			    TEE_PARAM_TYPE_NONE,
715843bb75SJerome Forissier 			    TEE_PARAM_TYPE_NONE) != type) {
725843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
735843bb75SJerome Forissier 	}
745843bb75SJerome Forissier 
755843bb75SJerome Forissier 	pool_id = p[0].value.a;
765843bb75SJerome Forissier 	if (pool_id > STATS_NB_POOLS)
775843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
785843bb75SJerome Forissier 
792617f49fSEtienne Carriere 	size_to_retrieve = sizeof(struct pta_stats_alloc);
805843bb75SJerome Forissier 	if (!pool_id)
815843bb75SJerome Forissier 		size_to_retrieve *= STATS_NB_POOLS;
825843bb75SJerome Forissier 
835843bb75SJerome Forissier 	if (p[1].memref.size < size_to_retrieve) {
845843bb75SJerome Forissier 		p[1].memref.size = size_to_retrieve;
855843bb75SJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
865843bb75SJerome Forissier 	}
875843bb75SJerome Forissier 	p[1].memref.size = size_to_retrieve;
885843bb75SJerome Forissier 	stats = p[1].memref.buffer;
895843bb75SJerome Forissier 
905843bb75SJerome Forissier 	for (i = 1; i <= STATS_NB_POOLS; i++) {
915843bb75SJerome Forissier 		if ((pool_id) && (i != pool_id))
925843bb75SJerome Forissier 			continue;
935843bb75SJerome Forissier 
945843bb75SJerome Forissier 		switch (i) {
955843bb75SJerome Forissier 		case 1:
965843bb75SJerome Forissier 			malloc_get_stats(stats);
975843bb75SJerome Forissier 			strlcpy(stats->desc, "Heap", sizeof(stats->desc));
985843bb75SJerome Forissier 			if (p[0].value.b)
995843bb75SJerome Forissier 				malloc_reset_stats();
1005843bb75SJerome Forissier 			break;
1015843bb75SJerome Forissier 
1025843bb75SJerome Forissier 		case 2:
1035843bb75SJerome Forissier 			EMSG("public DDR not managed by secure side anymore");
1045843bb75SJerome Forissier 			break;
1055843bb75SJerome Forissier 
1065843bb75SJerome Forissier 		case 3:
1075843bb75SJerome Forissier 			tee_mm_get_pool_stats(&tee_mm_sec_ddr, stats,
1085843bb75SJerome Forissier 					      !!p[0].value.b);
1095843bb75SJerome Forissier 			strlcpy(stats->desc, "Secure DDR", sizeof(stats->desc));
1105843bb75SJerome Forissier 			break;
1115843bb75SJerome Forissier 
112b76b2296SJerome Forissier #ifdef CFG_NS_VIRTUALIZATION
1135843bb75SJerome Forissier 		case 4:
1145843bb75SJerome Forissier 			nex_malloc_get_stats(stats);
1155843bb75SJerome Forissier 			strlcpy(stats->desc, "KHeap", sizeof(stats->desc));
1165843bb75SJerome Forissier 			if (p[0].value.b)
1175843bb75SJerome Forissier 				nex_malloc_reset_stats();
1185843bb75SJerome Forissier 			break;
1195843bb75SJerome Forissier #endif
1205843bb75SJerome Forissier 		default:
1215843bb75SJerome Forissier 			EMSG("Wrong pool id");
1225843bb75SJerome Forissier 			break;
1235843bb75SJerome Forissier 		}
1245843bb75SJerome Forissier 
1255843bb75SJerome Forissier 		stats++;
1265843bb75SJerome Forissier 	}
1275843bb75SJerome Forissier 
1285843bb75SJerome Forissier 	return TEE_SUCCESS;
1295843bb75SJerome Forissier }
1305843bb75SJerome Forissier 
1315843bb75SJerome Forissier static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
1325843bb75SJerome Forissier {
133*12f658b9SEtienne Carriere 	struct tee_pager_stats stats = { };
1345843bb75SJerome Forissier 
1355843bb75SJerome Forissier 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
1365843bb75SJerome Forissier 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
1375843bb75SJerome Forissier 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
1385843bb75SJerome Forissier 			    TEE_PARAM_TYPE_NONE) != type) {
1395843bb75SJerome Forissier 		EMSG("expect 3 output values as argument");
1405843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1415843bb75SJerome Forissier 	}
1425843bb75SJerome Forissier 
1435843bb75SJerome Forissier 	tee_pager_get_stats(&stats);
1445843bb75SJerome Forissier 	p[0].value.a = stats.npages;
1455843bb75SJerome Forissier 	p[0].value.b = stats.npages_all;
1465843bb75SJerome Forissier 	p[1].value.a = stats.ro_hits;
1475843bb75SJerome Forissier 	p[1].value.b = stats.rw_hits;
1485843bb75SJerome Forissier 	p[2].value.a = stats.hidden_hits;
1495843bb75SJerome Forissier 	p[2].value.b = stats.zi_released;
1505843bb75SJerome Forissier 
1515843bb75SJerome Forissier 	return TEE_SUCCESS;
1525843bb75SJerome Forissier }
1535843bb75SJerome Forissier 
1545843bb75SJerome Forissier static TEE_Result get_memleak_stats(uint32_t type,
155cb94c145SWeizhao Jiang 				    TEE_Param p[TEE_NUM_PARAMS] __maybe_unused)
1565843bb75SJerome Forissier {
1575843bb75SJerome Forissier 
1585843bb75SJerome Forissier 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE,
1595843bb75SJerome Forissier 			    TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type)
1605843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1615843bb75SJerome Forissier 
1625843bb75SJerome Forissier 	mdbg_check(1);
1635843bb75SJerome Forissier 
1645843bb75SJerome Forissier 	return TEE_SUCCESS;
1655843bb75SJerome Forissier }
1665843bb75SJerome Forissier 
167cb94c145SWeizhao Jiang static TEE_Result get_user_ta_stats(uint32_t type,
168cb94c145SWeizhao Jiang 				    TEE_Param p[TEE_NUM_PARAMS] __maybe_unused)
169cb94c145SWeizhao Jiang {
170cb94c145SWeizhao Jiang 	uint32_t res = TEE_SUCCESS;
171cb94c145SWeizhao Jiang 
172cb94c145SWeizhao Jiang 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
173cb94c145SWeizhao Jiang 			    TEE_PARAM_TYPE_NONE,
174cb94c145SWeizhao Jiang 			    TEE_PARAM_TYPE_NONE,
175cb94c145SWeizhao Jiang 			    TEE_PARAM_TYPE_NONE) != type)
176cb94c145SWeizhao Jiang 		return TEE_ERROR_BAD_PARAMETERS;
177cb94c145SWeizhao Jiang 
178cb94c145SWeizhao Jiang #if defined(CFG_TA_STATS)
179cb94c145SWeizhao Jiang 	res = tee_ta_instance_stats(p[0].memref.buffer,
180cb94c145SWeizhao Jiang 				    &p[0].memref.size);
181cb94c145SWeizhao Jiang 	if (res != TEE_SUCCESS)
182cb94c145SWeizhao Jiang 		DMSG("tee_ta_dump_stats return: 0x%"PRIx32, res);
183cb94c145SWeizhao Jiang #else
184cb94c145SWeizhao Jiang 	res = TEE_ERROR_NOT_SUPPORTED;
185cb94c145SWeizhao Jiang #endif
186cb94c145SWeizhao Jiang 	return res;
187cb94c145SWeizhao Jiang }
188cb94c145SWeizhao Jiang 
189c90dc99bSWeizhao Jiang static TEE_Result get_system_time(uint32_t type,
190c90dc99bSWeizhao Jiang 				  TEE_Param p[TEE_NUM_PARAMS])
191c90dc99bSWeizhao Jiang {
192c90dc99bSWeizhao Jiang 	TEE_Time ree_time = { };
193c90dc99bSWeizhao Jiang 	TEE_Time tee_time = { };
194c90dc99bSWeizhao Jiang 
195c90dc99bSWeizhao Jiang 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
196c90dc99bSWeizhao Jiang 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
197c90dc99bSWeizhao Jiang 			    TEE_PARAM_TYPE_NONE,
198c90dc99bSWeizhao Jiang 			    TEE_PARAM_TYPE_NONE) != type)
199c90dc99bSWeizhao Jiang 		return TEE_ERROR_BAD_PARAMETERS;
200c90dc99bSWeizhao Jiang 
201c90dc99bSWeizhao Jiang 	tee_time_get_sys_time(&tee_time);
202c90dc99bSWeizhao Jiang 	tee_time_get_ree_time(&ree_time);
203c90dc99bSWeizhao Jiang 
204c90dc99bSWeizhao Jiang 	p[0].value.a = ree_time.seconds;
205c90dc99bSWeizhao Jiang 	p[0].value.b = ree_time.millis;
206c90dc99bSWeizhao Jiang 	p[1].value.a = tee_time.seconds;
207c90dc99bSWeizhao Jiang 	p[1].value.b = tee_time.millis;
208c90dc99bSWeizhao Jiang 
209c90dc99bSWeizhao Jiang 	return TEE_SUCCESS;
210c90dc99bSWeizhao Jiang }
211c90dc99bSWeizhao Jiang 
2125843bb75SJerome Forissier /*
2135843bb75SJerome Forissier  * Trusted Application Entry Points
2145843bb75SJerome Forissier  */
2155843bb75SJerome Forissier 
2165843bb75SJerome Forissier static TEE_Result invoke_command(void *psess __unused,
2175843bb75SJerome Forissier 				 uint32_t cmd, uint32_t ptypes,
2185843bb75SJerome Forissier 				 TEE_Param params[TEE_NUM_PARAMS])
2195843bb75SJerome Forissier {
2205843bb75SJerome Forissier 	switch (cmd) {
2215843bb75SJerome Forissier 	case STATS_CMD_PAGER_STATS:
2225843bb75SJerome Forissier 		return get_pager_stats(ptypes, params);
2235843bb75SJerome Forissier 	case STATS_CMD_ALLOC_STATS:
2245843bb75SJerome Forissier 		return get_alloc_stats(ptypes, params);
2255843bb75SJerome Forissier 	case STATS_CMD_MEMLEAK_STATS:
2265843bb75SJerome Forissier 		return get_memleak_stats(ptypes, params);
227cb94c145SWeizhao Jiang 	case STATS_CMD_TA_STATS:
228cb94c145SWeizhao Jiang 		return get_user_ta_stats(ptypes, params);
229c90dc99bSWeizhao Jiang 	case STATS_CMD_GET_TIME:
230c90dc99bSWeizhao Jiang 		return get_system_time(ptypes, params);
2315843bb75SJerome Forissier 	default:
2325843bb75SJerome Forissier 		break;
2335843bb75SJerome Forissier 	}
2345843bb75SJerome Forissier 	return TEE_ERROR_BAD_PARAMETERS;
2355843bb75SJerome Forissier }
2365843bb75SJerome Forissier 
2375843bb75SJerome Forissier pseudo_ta_register(.uuid = STATS_UUID, .name = TA_NAME,
2385843bb75SJerome Forissier 		   .flags = PTA_DEFAULT_FLAGS,
2395843bb75SJerome Forissier 		   .invoke_command_entry_point = invoke_command);
240