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