xref: /optee_os/core/pta/stats.c (revision 37a87df89b44148813ef6b96dd65325241ccd0c4)
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>
11761fc6ecSEtienne Carriere #include <pta_stats.h>
12c90dc99bSWeizhao Jiang #include <stdio.h>
135843bb75SJerome Forissier #include <string.h>
145843bb75SJerome Forissier #include <string_ext.h>
15761fc6ecSEtienne Carriere #include <tee_api_types.h>
16c90dc99bSWeizhao Jiang #include <trace.h>
175843bb75SJerome Forissier 
185843bb75SJerome Forissier static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
195843bb75SJerome Forissier {
2012f658b9SEtienne Carriere 	struct pta_stats_alloc *stats = NULL;
2112f658b9SEtienne Carriere 	uint32_t size_to_retrieve = 0;
2212f658b9SEtienne Carriere 	uint32_t pool_id = 0;
2312f658b9SEtienne Carriere 	uint32_t i = 0;
245843bb75SJerome Forissier 
255843bb75SJerome Forissier 	/*
265843bb75SJerome Forissier 	 * p[0].value.a = pool id (from 0 to n)
275843bb75SJerome Forissier 	 *   - 0 means all the pools to be retrieved
285843bb75SJerome Forissier 	 *   - 1..n means pool id
295843bb75SJerome Forissier 	 * p[0].value.b = 0 if no reset of the stats
302617f49fSEtienne Carriere 	 * p[1].memref.buffer = output buffer to struct pta_stats_alloc
315843bb75SJerome Forissier 	 */
325843bb75SJerome Forissier 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
335843bb75SJerome Forissier 			    TEE_PARAM_TYPE_MEMREF_OUTPUT,
345843bb75SJerome Forissier 			    TEE_PARAM_TYPE_NONE,
355843bb75SJerome Forissier 			    TEE_PARAM_TYPE_NONE) != type) {
365843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
375843bb75SJerome Forissier 	}
385843bb75SJerome Forissier 
395843bb75SJerome Forissier 	pool_id = p[0].value.a;
405843bb75SJerome Forissier 	if (pool_id > STATS_NB_POOLS)
415843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
425843bb75SJerome Forissier 
432617f49fSEtienne Carriere 	size_to_retrieve = sizeof(struct pta_stats_alloc);
44a05577eaSEtienne Carriere 	if (pool_id == ALLOC_ID_ALL)
455843bb75SJerome Forissier 		size_to_retrieve *= STATS_NB_POOLS;
465843bb75SJerome Forissier 
475843bb75SJerome Forissier 	if (p[1].memref.size < size_to_retrieve) {
485843bb75SJerome Forissier 		p[1].memref.size = size_to_retrieve;
495843bb75SJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
505843bb75SJerome Forissier 	}
515843bb75SJerome Forissier 	p[1].memref.size = size_to_retrieve;
525843bb75SJerome Forissier 	stats = p[1].memref.buffer;
535843bb75SJerome Forissier 
54a05577eaSEtienne Carriere 	for (i = ALLOC_ID_HEAP; i <= STATS_NB_POOLS; i++) {
55a05577eaSEtienne Carriere 		if (pool_id != ALLOC_ID_ALL && i != pool_id)
565843bb75SJerome Forissier 			continue;
575843bb75SJerome Forissier 
585843bb75SJerome Forissier 		switch (i) {
59a05577eaSEtienne Carriere 		case ALLOC_ID_HEAP:
605843bb75SJerome Forissier 			malloc_get_stats(stats);
615843bb75SJerome Forissier 			strlcpy(stats->desc, "Heap", sizeof(stats->desc));
625843bb75SJerome Forissier 			if (p[0].value.b)
635843bb75SJerome Forissier 				malloc_reset_stats();
645843bb75SJerome Forissier 			break;
655843bb75SJerome Forissier 
66a05577eaSEtienne Carriere 		case ALLOC_ID_PUBLIC_DDR:
675843bb75SJerome Forissier 			EMSG("public DDR not managed by secure side anymore");
685843bb75SJerome Forissier 			break;
695843bb75SJerome Forissier 
70a05577eaSEtienne Carriere 		case ALLOC_ID_TA_RAM:
715843bb75SJerome Forissier 			tee_mm_get_pool_stats(&tee_mm_sec_ddr, stats,
725843bb75SJerome Forissier 					      !!p[0].value.b);
735843bb75SJerome Forissier 			strlcpy(stats->desc, "Secure DDR", sizeof(stats->desc));
745843bb75SJerome Forissier 			break;
755843bb75SJerome Forissier 
76b76b2296SJerome Forissier #ifdef CFG_NS_VIRTUALIZATION
77a05577eaSEtienne Carriere 		case ALLOC_ID_NEXUS_HEAP:
785843bb75SJerome Forissier 			nex_malloc_get_stats(stats);
795843bb75SJerome Forissier 			strlcpy(stats->desc, "KHeap", sizeof(stats->desc));
805843bb75SJerome Forissier 			if (p[0].value.b)
815843bb75SJerome Forissier 				nex_malloc_reset_stats();
825843bb75SJerome Forissier 			break;
835843bb75SJerome Forissier #endif
845843bb75SJerome Forissier 		default:
855843bb75SJerome Forissier 			EMSG("Wrong pool id");
865843bb75SJerome Forissier 			break;
875843bb75SJerome Forissier 		}
885843bb75SJerome Forissier 
895843bb75SJerome Forissier 		stats++;
905843bb75SJerome Forissier 	}
915843bb75SJerome Forissier 
925843bb75SJerome Forissier 	return TEE_SUCCESS;
935843bb75SJerome Forissier }
945843bb75SJerome Forissier 
955843bb75SJerome Forissier static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
965843bb75SJerome Forissier {
9712f658b9SEtienne Carriere 	struct tee_pager_stats stats = { };
985843bb75SJerome Forissier 
995843bb75SJerome Forissier 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
1005843bb75SJerome Forissier 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
1015843bb75SJerome Forissier 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
1025843bb75SJerome Forissier 			    TEE_PARAM_TYPE_NONE) != type) {
1035843bb75SJerome Forissier 		EMSG("expect 3 output values as argument");
1045843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1055843bb75SJerome Forissier 	}
1065843bb75SJerome Forissier 
1075843bb75SJerome Forissier 	tee_pager_get_stats(&stats);
1085843bb75SJerome Forissier 	p[0].value.a = stats.npages;
1095843bb75SJerome Forissier 	p[0].value.b = stats.npages_all;
1105843bb75SJerome Forissier 	p[1].value.a = stats.ro_hits;
1115843bb75SJerome Forissier 	p[1].value.b = stats.rw_hits;
1125843bb75SJerome Forissier 	p[2].value.a = stats.hidden_hits;
1135843bb75SJerome Forissier 	p[2].value.b = stats.zi_released;
1145843bb75SJerome Forissier 
1155843bb75SJerome Forissier 	return TEE_SUCCESS;
1165843bb75SJerome Forissier }
1175843bb75SJerome Forissier 
1185843bb75SJerome Forissier static TEE_Result get_memleak_stats(uint32_t type,
119cb94c145SWeizhao Jiang 				    TEE_Param p[TEE_NUM_PARAMS] __maybe_unused)
1205843bb75SJerome Forissier {
1215843bb75SJerome Forissier 
1225843bb75SJerome Forissier 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE,
1235843bb75SJerome Forissier 			    TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type)
1245843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1255843bb75SJerome Forissier 
1265843bb75SJerome Forissier 	mdbg_check(1);
1275843bb75SJerome Forissier 
1285843bb75SJerome Forissier 	return TEE_SUCCESS;
1295843bb75SJerome Forissier }
1305843bb75SJerome Forissier 
131cb94c145SWeizhao Jiang static TEE_Result get_user_ta_stats(uint32_t type,
132cb94c145SWeizhao Jiang 				    TEE_Param p[TEE_NUM_PARAMS] __maybe_unused)
133cb94c145SWeizhao Jiang {
134cb94c145SWeizhao Jiang 	uint32_t res = TEE_SUCCESS;
135cb94c145SWeizhao Jiang 
136cb94c145SWeizhao Jiang 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
137cb94c145SWeizhao Jiang 			    TEE_PARAM_TYPE_NONE,
138cb94c145SWeizhao Jiang 			    TEE_PARAM_TYPE_NONE,
139cb94c145SWeizhao Jiang 			    TEE_PARAM_TYPE_NONE) != type)
140cb94c145SWeizhao Jiang 		return TEE_ERROR_BAD_PARAMETERS;
141cb94c145SWeizhao Jiang 
142cb94c145SWeizhao Jiang #if defined(CFG_TA_STATS)
143cb94c145SWeizhao Jiang 	res = tee_ta_instance_stats(p[0].memref.buffer,
144cb94c145SWeizhao Jiang 				    &p[0].memref.size);
145cb94c145SWeizhao Jiang 	if (res != TEE_SUCCESS)
146cb94c145SWeizhao Jiang 		DMSG("tee_ta_dump_stats return: 0x%"PRIx32, res);
147cb94c145SWeizhao Jiang #else
148cb94c145SWeizhao Jiang 	res = TEE_ERROR_NOT_SUPPORTED;
149cb94c145SWeizhao Jiang #endif
150cb94c145SWeizhao Jiang 	return res;
151cb94c145SWeizhao Jiang }
152cb94c145SWeizhao Jiang 
153c90dc99bSWeizhao Jiang static TEE_Result get_system_time(uint32_t type,
154c90dc99bSWeizhao Jiang 				  TEE_Param p[TEE_NUM_PARAMS])
155c90dc99bSWeizhao Jiang {
156c90dc99bSWeizhao Jiang 	TEE_Time ree_time = { };
157c90dc99bSWeizhao Jiang 	TEE_Time tee_time = { };
158c90dc99bSWeizhao Jiang 
159c90dc99bSWeizhao Jiang 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
160c90dc99bSWeizhao Jiang 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
161c90dc99bSWeizhao Jiang 			    TEE_PARAM_TYPE_NONE,
162c90dc99bSWeizhao Jiang 			    TEE_PARAM_TYPE_NONE) != type)
163c90dc99bSWeizhao Jiang 		return TEE_ERROR_BAD_PARAMETERS;
164c90dc99bSWeizhao Jiang 
165c90dc99bSWeizhao Jiang 	tee_time_get_sys_time(&tee_time);
166c90dc99bSWeizhao Jiang 	tee_time_get_ree_time(&ree_time);
167c90dc99bSWeizhao Jiang 
168c90dc99bSWeizhao Jiang 	p[0].value.a = ree_time.seconds;
169c90dc99bSWeizhao Jiang 	p[0].value.b = ree_time.millis;
170c90dc99bSWeizhao Jiang 	p[1].value.a = tee_time.seconds;
171c90dc99bSWeizhao Jiang 	p[1].value.b = tee_time.millis;
172c90dc99bSWeizhao Jiang 
173c90dc99bSWeizhao Jiang 	return TEE_SUCCESS;
174c90dc99bSWeizhao Jiang }
175c90dc99bSWeizhao Jiang 
1765843bb75SJerome Forissier /*
1775843bb75SJerome Forissier  * Trusted Application Entry Points
1785843bb75SJerome Forissier  */
1795843bb75SJerome Forissier 
1805843bb75SJerome Forissier static TEE_Result invoke_command(void *psess __unused,
1815843bb75SJerome Forissier 				 uint32_t cmd, uint32_t ptypes,
1825843bb75SJerome Forissier 				 TEE_Param params[TEE_NUM_PARAMS])
1835843bb75SJerome Forissier {
1845843bb75SJerome Forissier 	switch (cmd) {
1855843bb75SJerome Forissier 	case STATS_CMD_PAGER_STATS:
1865843bb75SJerome Forissier 		return get_pager_stats(ptypes, params);
1875843bb75SJerome Forissier 	case STATS_CMD_ALLOC_STATS:
1885843bb75SJerome Forissier 		return get_alloc_stats(ptypes, params);
1895843bb75SJerome Forissier 	case STATS_CMD_MEMLEAK_STATS:
1905843bb75SJerome Forissier 		return get_memleak_stats(ptypes, params);
191cb94c145SWeizhao Jiang 	case STATS_CMD_TA_STATS:
192cb94c145SWeizhao Jiang 		return get_user_ta_stats(ptypes, params);
193c90dc99bSWeizhao Jiang 	case STATS_CMD_GET_TIME:
194c90dc99bSWeizhao Jiang 		return get_system_time(ptypes, params);
1955843bb75SJerome Forissier 	default:
1965843bb75SJerome Forissier 		break;
1975843bb75SJerome Forissier 	}
1985843bb75SJerome Forissier 	return TEE_ERROR_BAD_PARAMETERS;
1995843bb75SJerome Forissier }
2005843bb75SJerome Forissier 
201*37a87df8SEtienne Carriere pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta",
2025843bb75SJerome Forissier 		   .flags = PTA_DEFAULT_FLAGS,
2035843bb75SJerome Forissier 		   .invoke_command_entry_point = invoke_command);
204