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 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"); 725843bb75SJerome Forissier break; 735843bb75SJerome Forissier 74a05577eaSEtienne Carriere case ALLOC_ID_TA_RAM: 75de19cacbSJens Wiklander phys_mem_stats(stats, p[0].value.b); 76de19cacbSJens Wiklander strlcpy(stats->desc, "Physical TA memory", 77de19cacbSJens Wiklander sizeof(stats->desc)); 785843bb75SJerome Forissier break; 795843bb75SJerome Forissier 80a05577eaSEtienne Carriere case ALLOC_ID_NEXUS_HEAP: 81*6e2e1d60SEtienne Carriere #ifdef CFG_NS_VIRTUALIZATION 825843bb75SJerome Forissier nex_malloc_get_stats(stats); 835843bb75SJerome Forissier strlcpy(stats->desc, "KHeap", sizeof(stats->desc)); 845843bb75SJerome Forissier if (p[0].value.b) 855843bb75SJerome Forissier nex_malloc_reset_stats(); 86*6e2e1d60SEtienne Carriere #else 87*6e2e1d60SEtienne Carriere strlcpy(stats->desc, "KHeap (disabled)", 88*6e2e1d60SEtienne Carriere sizeof(stats->desc)); 895843bb75SJerome Forissier #endif 90*6e2e1d60SEtienne Carriere break; 9176306f73SEtienne Carriere case ALLOC_ID_RPMB: 9276306f73SEtienne Carriere if (rpmb_mem_stats(stats, p[0].value.b)) 9376306f73SEtienne Carriere strlcpy(stats->desc, 9476306f73SEtienne Carriere "RPMB secure storage (no data)", 9576306f73SEtienne Carriere sizeof(stats->desc)); 9676306f73SEtienne Carriere else 9776306f73SEtienne Carriere strlcpy(stats->desc, "RPMB secure storage", 9876306f73SEtienne Carriere sizeof(stats->desc)); 9976306f73SEtienne Carriere break; 1005843bb75SJerome Forissier default: 1015843bb75SJerome Forissier EMSG("Wrong pool id"); 1025843bb75SJerome Forissier break; 1035843bb75SJerome Forissier } 1045843bb75SJerome Forissier 1055843bb75SJerome Forissier stats++; 1065843bb75SJerome Forissier } 1075843bb75SJerome Forissier 1085843bb75SJerome Forissier return TEE_SUCCESS; 1095843bb75SJerome Forissier } 1105843bb75SJerome Forissier 1115843bb75SJerome Forissier static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 1125843bb75SJerome Forissier { 11312f658b9SEtienne Carriere struct tee_pager_stats stats = { }; 1145843bb75SJerome Forissier 1155843bb75SJerome Forissier if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 1165843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT, 1175843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT, 1185843bb75SJerome Forissier TEE_PARAM_TYPE_NONE) != type) { 1195843bb75SJerome Forissier EMSG("expect 3 output values as argument"); 1205843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 1215843bb75SJerome Forissier } 1225843bb75SJerome Forissier 1235843bb75SJerome Forissier tee_pager_get_stats(&stats); 1245843bb75SJerome Forissier p[0].value.a = stats.npages; 1255843bb75SJerome Forissier p[0].value.b = stats.npages_all; 1265843bb75SJerome Forissier p[1].value.a = stats.ro_hits; 1275843bb75SJerome Forissier p[1].value.b = stats.rw_hits; 1285843bb75SJerome Forissier p[2].value.a = stats.hidden_hits; 1295843bb75SJerome Forissier p[2].value.b = stats.zi_released; 1305843bb75SJerome Forissier 1315843bb75SJerome Forissier return TEE_SUCCESS; 1325843bb75SJerome Forissier } 1335843bb75SJerome Forissier 1345843bb75SJerome Forissier static TEE_Result get_memleak_stats(uint32_t type, 135cb94c145SWeizhao Jiang TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) 1365843bb75SJerome Forissier { 1375843bb75SJerome Forissier 1385843bb75SJerome Forissier if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, 1395843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) 1405843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 1415843bb75SJerome Forissier 1425843bb75SJerome Forissier mdbg_check(1); 1435843bb75SJerome Forissier 1445843bb75SJerome Forissier return TEE_SUCCESS; 1455843bb75SJerome Forissier } 1465843bb75SJerome Forissier 147cb94c145SWeizhao Jiang static TEE_Result get_user_ta_stats(uint32_t type, 148cb94c145SWeizhao Jiang TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) 149cb94c145SWeizhao Jiang { 150cb94c145SWeizhao Jiang uint32_t res = TEE_SUCCESS; 151cb94c145SWeizhao Jiang 152cb94c145SWeizhao Jiang if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 153cb94c145SWeizhao Jiang TEE_PARAM_TYPE_NONE, 154cb94c145SWeizhao Jiang TEE_PARAM_TYPE_NONE, 155cb94c145SWeizhao Jiang TEE_PARAM_TYPE_NONE) != type) 156cb94c145SWeizhao Jiang return TEE_ERROR_BAD_PARAMETERS; 157cb94c145SWeizhao Jiang 158cb94c145SWeizhao Jiang #if defined(CFG_TA_STATS) 159cb94c145SWeizhao Jiang res = tee_ta_instance_stats(p[0].memref.buffer, 160cb94c145SWeizhao Jiang &p[0].memref.size); 161cb94c145SWeizhao Jiang if (res != TEE_SUCCESS) 162cb94c145SWeizhao Jiang DMSG("tee_ta_dump_stats return: 0x%"PRIx32, res); 163cb94c145SWeizhao Jiang #else 164cb94c145SWeizhao Jiang res = TEE_ERROR_NOT_SUPPORTED; 165cb94c145SWeizhao Jiang #endif 166cb94c145SWeizhao Jiang return res; 167cb94c145SWeizhao Jiang } 168cb94c145SWeizhao Jiang 169c90dc99bSWeizhao Jiang static TEE_Result get_system_time(uint32_t type, 170c90dc99bSWeizhao Jiang TEE_Param p[TEE_NUM_PARAMS]) 171c90dc99bSWeizhao Jiang { 1724b6a9cdcSClement Faure TEE_Result ret = TEE_ERROR_GENERIC; 173c90dc99bSWeizhao Jiang TEE_Time ree_time = { }; 174c90dc99bSWeizhao Jiang TEE_Time tee_time = { }; 175c90dc99bSWeizhao Jiang 176c90dc99bSWeizhao Jiang if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 177c90dc99bSWeizhao Jiang TEE_PARAM_TYPE_VALUE_OUTPUT, 178c90dc99bSWeizhao Jiang TEE_PARAM_TYPE_NONE, 179c90dc99bSWeizhao Jiang TEE_PARAM_TYPE_NONE) != type) 180c90dc99bSWeizhao Jiang return TEE_ERROR_BAD_PARAMETERS; 181c90dc99bSWeizhao Jiang 1824b6a9cdcSClement Faure ret = tee_time_get_sys_time(&tee_time); 1834b6a9cdcSClement Faure if (ret) 1844b6a9cdcSClement Faure return ret; 1854b6a9cdcSClement Faure 1864b6a9cdcSClement Faure ret = tee_time_get_ree_time(&ree_time); 1874b6a9cdcSClement Faure if (ret) 1884b6a9cdcSClement Faure return ret; 189c90dc99bSWeizhao Jiang 190c90dc99bSWeizhao Jiang p[0].value.a = ree_time.seconds; 191c90dc99bSWeizhao Jiang p[0].value.b = ree_time.millis; 192c90dc99bSWeizhao Jiang p[1].value.a = tee_time.seconds; 193c90dc99bSWeizhao Jiang p[1].value.b = tee_time.millis; 194c90dc99bSWeizhao Jiang 195c90dc99bSWeizhao Jiang return TEE_SUCCESS; 196c90dc99bSWeizhao Jiang } 197c90dc99bSWeizhao Jiang 198a5e75b7eSEtienne Carriere static TEE_Result print_driver_info(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 199a5e75b7eSEtienne Carriere { 200a5e75b7eSEtienne Carriere if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 201a5e75b7eSEtienne Carriere TEE_PARAM_TYPE_NONE, 202a5e75b7eSEtienne Carriere TEE_PARAM_TYPE_NONE, 203a5e75b7eSEtienne Carriere TEE_PARAM_TYPE_NONE) != type) 204a5e75b7eSEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 205a5e75b7eSEtienne Carriere 206a5e75b7eSEtienne Carriere switch (p[0].value.a) { 207a5e75b7eSEtienne Carriere case STATS_DRIVER_TYPE_CLOCK: 208a5e75b7eSEtienne Carriere clk_print_tree(); 209a5e75b7eSEtienne Carriere break; 210a5e75b7eSEtienne Carriere case STATS_DRIVER_TYPE_REGULATOR: 211a5e75b7eSEtienne Carriere regulator_print_tree(); 212a5e75b7eSEtienne Carriere break; 213a5e75b7eSEtienne Carriere default: 214a5e75b7eSEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 215a5e75b7eSEtienne Carriere } 216a5e75b7eSEtienne Carriere 217a5e75b7eSEtienne Carriere return TEE_SUCCESS; 218a5e75b7eSEtienne Carriere } 219a5e75b7eSEtienne Carriere 2205843bb75SJerome Forissier /* 2215843bb75SJerome Forissier * Trusted Application Entry Points 2225843bb75SJerome Forissier */ 2235843bb75SJerome Forissier 2245843bb75SJerome Forissier static TEE_Result invoke_command(void *psess __unused, 2255843bb75SJerome Forissier uint32_t cmd, uint32_t ptypes, 2265843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 2275843bb75SJerome Forissier { 2285843bb75SJerome Forissier switch (cmd) { 2295843bb75SJerome Forissier case STATS_CMD_PAGER_STATS: 2305843bb75SJerome Forissier return get_pager_stats(ptypes, params); 2315843bb75SJerome Forissier case STATS_CMD_ALLOC_STATS: 2325843bb75SJerome Forissier return get_alloc_stats(ptypes, params); 2335843bb75SJerome Forissier case STATS_CMD_MEMLEAK_STATS: 2345843bb75SJerome Forissier return get_memleak_stats(ptypes, params); 235cb94c145SWeizhao Jiang case STATS_CMD_TA_STATS: 236cb94c145SWeizhao Jiang return get_user_ta_stats(ptypes, params); 237c90dc99bSWeizhao Jiang case STATS_CMD_GET_TIME: 238c90dc99bSWeizhao Jiang return get_system_time(ptypes, params); 239a5e75b7eSEtienne Carriere case STATS_CMD_PRINT_DRIVER_INFO: 240a5e75b7eSEtienne Carriere return print_driver_info(ptypes, params); 2415843bb75SJerome Forissier default: 2425843bb75SJerome Forissier break; 2435843bb75SJerome Forissier } 2445843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 2455843bb75SJerome Forissier } 2465843bb75SJerome Forissier 24737a87df8SEtienne Carriere pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta", 2485843bb75SJerome Forissier .flags = PTA_DEFAULT_FLAGS, 2495843bb75SJerome Forissier .invoke_command_entry_point = invoke_command); 250