15843bb75SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
25843bb75SJerome Forissier /*
35843bb75SJerome Forissier * Copyright (c) 2015, Linaro Limited
45843bb75SJerome Forissier */
55843bb75SJerome Forissier #include <compiler.h>
6a5e75b7eSEtienne Carriere #include <drivers/clk.h>
7a5e75b7eSEtienne Carriere #include <drivers/regulator.h>
85843bb75SJerome Forissier #include <kernel/pseudo_ta.h>
9c90dc99bSWeizhao Jiang #include <kernel/tee_time.h>
10c90dc99bSWeizhao Jiang #include <malloc.h>
11de19cacbSJens Wiklander #include <mm/phys_mem.h>
125843bb75SJerome Forissier #include <mm/tee_mm.h>
13c90dc99bSWeizhao Jiang #include <mm/tee_pager.h>
14761fc6ecSEtienne Carriere #include <pta_stats.h>
155843bb75SJerome Forissier #include <string.h>
165843bb75SJerome Forissier #include <string_ext.h>
17761fc6ecSEtienne Carriere #include <tee_api_types.h>
1876306f73SEtienne Carriere #include <tee/tee_fs.h>
19c90dc99bSWeizhao Jiang #include <trace.h>
205843bb75SJerome Forissier
get_alloc_stats(uint32_t type,TEE_Param p[TEE_NUM_PARAMS])215843bb75SJerome Forissier static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
225843bb75SJerome Forissier {
2312f658b9SEtienne Carriere struct pta_stats_alloc *stats = NULL;
2412f658b9SEtienne Carriere uint32_t size_to_retrieve = 0;
2512f658b9SEtienne Carriere uint32_t pool_id = 0;
2612f658b9SEtienne Carriere uint32_t i = 0;
275843bb75SJerome Forissier
285843bb75SJerome Forissier /*
295843bb75SJerome Forissier * p[0].value.a = pool id (from 0 to n)
305843bb75SJerome Forissier * - 0 means all the pools to be retrieved
315843bb75SJerome Forissier * - 1..n means pool id
325843bb75SJerome Forissier * p[0].value.b = 0 if no reset of the stats
332617f49fSEtienne Carriere * p[1].memref.buffer = output buffer to struct pta_stats_alloc
345843bb75SJerome Forissier */
355843bb75SJerome Forissier if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
365843bb75SJerome Forissier TEE_PARAM_TYPE_MEMREF_OUTPUT,
375843bb75SJerome Forissier TEE_PARAM_TYPE_NONE,
385843bb75SJerome Forissier TEE_PARAM_TYPE_NONE) != type) {
395843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
405843bb75SJerome Forissier }
415843bb75SJerome Forissier
425843bb75SJerome Forissier pool_id = p[0].value.a;
435843bb75SJerome Forissier if (pool_id > STATS_NB_POOLS)
445843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
455843bb75SJerome Forissier
462617f49fSEtienne Carriere size_to_retrieve = sizeof(struct pta_stats_alloc);
47a05577eaSEtienne Carriere if (pool_id == ALLOC_ID_ALL)
485843bb75SJerome Forissier size_to_retrieve *= STATS_NB_POOLS;
495843bb75SJerome Forissier
505843bb75SJerome Forissier if (p[1].memref.size < size_to_retrieve) {
515843bb75SJerome Forissier p[1].memref.size = size_to_retrieve;
525843bb75SJerome Forissier return TEE_ERROR_SHORT_BUFFER;
535843bb75SJerome Forissier }
545843bb75SJerome Forissier p[1].memref.size = size_to_retrieve;
555843bb75SJerome Forissier stats = p[1].memref.buffer;
5676306f73SEtienne Carriere memset(stats, 0, size_to_retrieve);
575843bb75SJerome Forissier
58a05577eaSEtienne Carriere for (i = ALLOC_ID_HEAP; i <= STATS_NB_POOLS; i++) {
59a05577eaSEtienne Carriere if (pool_id != ALLOC_ID_ALL && i != pool_id)
605843bb75SJerome Forissier continue;
615843bb75SJerome Forissier
625843bb75SJerome Forissier switch (i) {
63a05577eaSEtienne Carriere case ALLOC_ID_HEAP:
645843bb75SJerome Forissier malloc_get_stats(stats);
655843bb75SJerome Forissier strlcpy(stats->desc, "Heap", sizeof(stats->desc));
665843bb75SJerome Forissier if (p[0].value.b)
675843bb75SJerome Forissier malloc_reset_stats();
685843bb75SJerome Forissier break;
695843bb75SJerome Forissier
70a05577eaSEtienne Carriere case ALLOC_ID_PUBLIC_DDR:
715843bb75SJerome Forissier EMSG("public DDR not managed by secure side anymore");
72*8261ca4bSEtienne Carriere strlcpy(stats->desc, "Public DDR (deprecated)",
73*8261ca4bSEtienne Carriere sizeof(stats->desc));
745843bb75SJerome Forissier break;
755843bb75SJerome Forissier
76a05577eaSEtienne Carriere case ALLOC_ID_TA_RAM:
77de19cacbSJens Wiklander phys_mem_stats(stats, p[0].value.b);
78de19cacbSJens Wiklander strlcpy(stats->desc, "Physical TA memory",
79de19cacbSJens Wiklander sizeof(stats->desc));
805843bb75SJerome Forissier break;
815843bb75SJerome Forissier
82a05577eaSEtienne Carriere case ALLOC_ID_NEXUS_HEAP:
836e2e1d60SEtienne Carriere #ifdef CFG_NS_VIRTUALIZATION
845843bb75SJerome Forissier nex_malloc_get_stats(stats);
855843bb75SJerome Forissier strlcpy(stats->desc, "KHeap", sizeof(stats->desc));
865843bb75SJerome Forissier if (p[0].value.b)
875843bb75SJerome Forissier nex_malloc_reset_stats();
886e2e1d60SEtienne Carriere #else
896e2e1d60SEtienne Carriere strlcpy(stats->desc, "KHeap (disabled)",
906e2e1d60SEtienne Carriere sizeof(stats->desc));
915843bb75SJerome Forissier #endif
926e2e1d60SEtienne Carriere break;
9376306f73SEtienne Carriere case ALLOC_ID_RPMB:
9476306f73SEtienne Carriere if (rpmb_mem_stats(stats, p[0].value.b))
9576306f73SEtienne Carriere strlcpy(stats->desc,
9676306f73SEtienne Carriere "RPMB secure storage (no data)",
9776306f73SEtienne Carriere sizeof(stats->desc));
9876306f73SEtienne Carriere else
9976306f73SEtienne Carriere strlcpy(stats->desc, "RPMB secure storage",
10076306f73SEtienne Carriere sizeof(stats->desc));
10176306f73SEtienne Carriere break;
1025843bb75SJerome Forissier default:
1035843bb75SJerome Forissier EMSG("Wrong pool id");
1045843bb75SJerome Forissier break;
1055843bb75SJerome Forissier }
1065843bb75SJerome Forissier
1075843bb75SJerome Forissier stats++;
1085843bb75SJerome Forissier }
1095843bb75SJerome Forissier
1105843bb75SJerome Forissier return TEE_SUCCESS;
1115843bb75SJerome Forissier }
1125843bb75SJerome Forissier
get_pager_stats(uint32_t type,TEE_Param p[TEE_NUM_PARAMS])1135843bb75SJerome Forissier static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
1145843bb75SJerome Forissier {
11512f658b9SEtienne Carriere struct tee_pager_stats stats = { };
1165843bb75SJerome Forissier
1175843bb75SJerome Forissier if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
1185843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT,
1195843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT,
1205843bb75SJerome Forissier TEE_PARAM_TYPE_NONE) != type) {
1215843bb75SJerome Forissier EMSG("expect 3 output values as argument");
1225843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
1235843bb75SJerome Forissier }
1245843bb75SJerome Forissier
1255843bb75SJerome Forissier tee_pager_get_stats(&stats);
1265843bb75SJerome Forissier p[0].value.a = stats.npages;
1275843bb75SJerome Forissier p[0].value.b = stats.npages_all;
1285843bb75SJerome Forissier p[1].value.a = stats.ro_hits;
1295843bb75SJerome Forissier p[1].value.b = stats.rw_hits;
1305843bb75SJerome Forissier p[2].value.a = stats.hidden_hits;
1315843bb75SJerome Forissier p[2].value.b = stats.zi_released;
1325843bb75SJerome Forissier
1335843bb75SJerome Forissier return TEE_SUCCESS;
1345843bb75SJerome Forissier }
1355843bb75SJerome Forissier
get_memleak_stats(uint32_t type,TEE_Param p[TEE_NUM_PARAMS]__maybe_unused)1365843bb75SJerome Forissier static TEE_Result get_memleak_stats(uint32_t type,
137cb94c145SWeizhao Jiang TEE_Param p[TEE_NUM_PARAMS] __maybe_unused)
1385843bb75SJerome Forissier {
1395843bb75SJerome Forissier
1405843bb75SJerome Forissier if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE,
1415843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type)
1425843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
1435843bb75SJerome Forissier
1445843bb75SJerome Forissier mdbg_check(1);
1455843bb75SJerome Forissier
1465843bb75SJerome Forissier return TEE_SUCCESS;
1475843bb75SJerome Forissier }
1485843bb75SJerome Forissier
get_user_ta_stats(uint32_t type,TEE_Param p[TEE_NUM_PARAMS]__maybe_unused)149cb94c145SWeizhao Jiang static TEE_Result get_user_ta_stats(uint32_t type,
150cb94c145SWeizhao Jiang TEE_Param p[TEE_NUM_PARAMS] __maybe_unused)
151cb94c145SWeizhao Jiang {
152cb94c145SWeizhao Jiang uint32_t res = TEE_SUCCESS;
153cb94c145SWeizhao Jiang
154cb94c145SWeizhao Jiang if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
155cb94c145SWeizhao Jiang TEE_PARAM_TYPE_NONE,
156cb94c145SWeizhao Jiang TEE_PARAM_TYPE_NONE,
157cb94c145SWeizhao Jiang TEE_PARAM_TYPE_NONE) != type)
158cb94c145SWeizhao Jiang return TEE_ERROR_BAD_PARAMETERS;
159cb94c145SWeizhao Jiang
160cb94c145SWeizhao Jiang #if defined(CFG_TA_STATS)
161cb94c145SWeizhao Jiang res = tee_ta_instance_stats(p[0].memref.buffer,
162cb94c145SWeizhao Jiang &p[0].memref.size);
163cb94c145SWeizhao Jiang if (res != TEE_SUCCESS)
164cb94c145SWeizhao Jiang DMSG("tee_ta_dump_stats return: 0x%"PRIx32, res);
165cb94c145SWeizhao Jiang #else
166cb94c145SWeizhao Jiang res = TEE_ERROR_NOT_SUPPORTED;
167cb94c145SWeizhao Jiang #endif
168cb94c145SWeizhao Jiang return res;
169cb94c145SWeizhao Jiang }
170cb94c145SWeizhao Jiang
get_system_time(uint32_t type,TEE_Param p[TEE_NUM_PARAMS])171c90dc99bSWeizhao Jiang static TEE_Result get_system_time(uint32_t type,
172c90dc99bSWeizhao Jiang TEE_Param p[TEE_NUM_PARAMS])
173c90dc99bSWeizhao Jiang {
1744b6a9cdcSClement Faure TEE_Result ret = TEE_ERROR_GENERIC;
175c90dc99bSWeizhao Jiang TEE_Time ree_time = { };
176c90dc99bSWeizhao Jiang TEE_Time tee_time = { };
177c90dc99bSWeizhao Jiang
178c90dc99bSWeizhao Jiang if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
179c90dc99bSWeizhao Jiang TEE_PARAM_TYPE_VALUE_OUTPUT,
180c90dc99bSWeizhao Jiang TEE_PARAM_TYPE_NONE,
181c90dc99bSWeizhao Jiang TEE_PARAM_TYPE_NONE) != type)
182c90dc99bSWeizhao Jiang return TEE_ERROR_BAD_PARAMETERS;
183c90dc99bSWeizhao Jiang
1844b6a9cdcSClement Faure ret = tee_time_get_sys_time(&tee_time);
1854b6a9cdcSClement Faure if (ret)
1864b6a9cdcSClement Faure return ret;
1874b6a9cdcSClement Faure
1884b6a9cdcSClement Faure ret = tee_time_get_ree_time(&ree_time);
1894b6a9cdcSClement Faure if (ret)
1904b6a9cdcSClement Faure return ret;
191c90dc99bSWeizhao Jiang
192c90dc99bSWeizhao Jiang p[0].value.a = ree_time.seconds;
193c90dc99bSWeizhao Jiang p[0].value.b = ree_time.millis;
194c90dc99bSWeizhao Jiang p[1].value.a = tee_time.seconds;
195c90dc99bSWeizhao Jiang p[1].value.b = tee_time.millis;
196c90dc99bSWeizhao Jiang
197c90dc99bSWeizhao Jiang return TEE_SUCCESS;
198c90dc99bSWeizhao Jiang }
199c90dc99bSWeizhao Jiang
print_driver_info(uint32_t type,TEE_Param p[TEE_NUM_PARAMS])200a5e75b7eSEtienne Carriere static TEE_Result print_driver_info(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
201a5e75b7eSEtienne Carriere {
202a5e75b7eSEtienne Carriere if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
203a5e75b7eSEtienne Carriere TEE_PARAM_TYPE_NONE,
204a5e75b7eSEtienne Carriere TEE_PARAM_TYPE_NONE,
205a5e75b7eSEtienne Carriere TEE_PARAM_TYPE_NONE) != type)
206a5e75b7eSEtienne Carriere return TEE_ERROR_BAD_PARAMETERS;
207a5e75b7eSEtienne Carriere
208a5e75b7eSEtienne Carriere switch (p[0].value.a) {
209a5e75b7eSEtienne Carriere case STATS_DRIVER_TYPE_CLOCK:
210a5e75b7eSEtienne Carriere clk_print_tree();
211a5e75b7eSEtienne Carriere break;
212a5e75b7eSEtienne Carriere case STATS_DRIVER_TYPE_REGULATOR:
213a5e75b7eSEtienne Carriere regulator_print_tree();
214a5e75b7eSEtienne Carriere break;
215a5e75b7eSEtienne Carriere default:
216a5e75b7eSEtienne Carriere return TEE_ERROR_BAD_PARAMETERS;
217a5e75b7eSEtienne Carriere }
218a5e75b7eSEtienne Carriere
219a5e75b7eSEtienne Carriere return TEE_SUCCESS;
220a5e75b7eSEtienne Carriere }
221a5e75b7eSEtienne Carriere
2225843bb75SJerome Forissier /*
2235843bb75SJerome Forissier * Trusted Application Entry Points
2245843bb75SJerome Forissier */
2255843bb75SJerome Forissier
invoke_command(void * psess __unused,uint32_t cmd,uint32_t ptypes,TEE_Param params[TEE_NUM_PARAMS])2265843bb75SJerome Forissier static TEE_Result invoke_command(void *psess __unused,
2275843bb75SJerome Forissier uint32_t cmd, uint32_t ptypes,
2285843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS])
2295843bb75SJerome Forissier {
2305843bb75SJerome Forissier switch (cmd) {
2315843bb75SJerome Forissier case STATS_CMD_PAGER_STATS:
2325843bb75SJerome Forissier return get_pager_stats(ptypes, params);
2335843bb75SJerome Forissier case STATS_CMD_ALLOC_STATS:
2345843bb75SJerome Forissier return get_alloc_stats(ptypes, params);
2355843bb75SJerome Forissier case STATS_CMD_MEMLEAK_STATS:
2365843bb75SJerome Forissier return get_memleak_stats(ptypes, params);
237cb94c145SWeizhao Jiang case STATS_CMD_TA_STATS:
238cb94c145SWeizhao Jiang return get_user_ta_stats(ptypes, params);
239c90dc99bSWeizhao Jiang case STATS_CMD_GET_TIME:
240c90dc99bSWeizhao Jiang return get_system_time(ptypes, params);
241a5e75b7eSEtienne Carriere case STATS_CMD_PRINT_DRIVER_INFO:
242a5e75b7eSEtienne Carriere return print_driver_info(ptypes, params);
2435843bb75SJerome Forissier default:
2445843bb75SJerome Forissier break;
2455843bb75SJerome Forissier }
2465843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS;
2475843bb75SJerome Forissier }
2485843bb75SJerome Forissier
24937a87df8SEtienne Carriere pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta",
2505843bb75SJerome Forissier .flags = PTA_DEFAULT_FLAGS,
2515843bb75SJerome Forissier .invoke_command_entry_point = invoke_command);
252