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> 7*c90dc99bSWeizhao Jiang #include <kernel/tee_time.h> 8*c90dc99bSWeizhao Jiang #include <malloc.h> 95843bb75SJerome Forissier #include <mm/tee_mm.h> 10*c90dc99bSWeizhao Jiang #include <mm/tee_pager.h> 11*c90dc99bSWeizhao Jiang #include <stdio.h> 125843bb75SJerome Forissier #include <string.h> 135843bb75SJerome Forissier #include <string_ext.h> 14*c90dc99bSWeizhao 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 42*c90dc99bSWeizhao Jiang /* 43*c90dc99bSWeizhao Jiang * STATS_CMD_GET_TIME - Get both REE time and TEE time 44*c90dc99bSWeizhao Jiang * 45*c90dc99bSWeizhao Jiang * [out] value[0].a REE time as seen by OP-TEE in seconds 46*c90dc99bSWeizhao Jiang * [out] value[0].b REE time as seen by OP-TEE, milliseconds part 47*c90dc99bSWeizhao Jiang * [out] value[1].a TEE system time in seconds 48*c90dc99bSWeizhao Jiang * [out] value[1].b TEE system time, milliseconds part 49*c90dc99bSWeizhao Jiang */ 50*c90dc99bSWeizhao Jiang #define STATS_CMD_GET_TIME 4 51*c90dc99bSWeizhao 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 { 565843bb75SJerome Forissier struct malloc_stats *stats; 575843bb75SJerome Forissier uint32_t size_to_retrieve; 585843bb75SJerome Forissier uint32_t pool_id; 595843bb75SJerome Forissier uint32_t i; 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 665843bb75SJerome Forissier * p[1].memref.buffer = output buffer to struct malloc_stats 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 795843bb75SJerome Forissier size_to_retrieve = sizeof(struct malloc_stats); 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 { 1335843bb75SJerome Forissier 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 189*c90dc99bSWeizhao Jiang static TEE_Result get_system_time(uint32_t type, 190*c90dc99bSWeizhao Jiang TEE_Param p[TEE_NUM_PARAMS]) 191*c90dc99bSWeizhao Jiang { 192*c90dc99bSWeizhao Jiang TEE_Time ree_time = { }; 193*c90dc99bSWeizhao Jiang TEE_Time tee_time = { }; 194*c90dc99bSWeizhao Jiang 195*c90dc99bSWeizhao Jiang if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 196*c90dc99bSWeizhao Jiang TEE_PARAM_TYPE_VALUE_OUTPUT, 197*c90dc99bSWeizhao Jiang TEE_PARAM_TYPE_NONE, 198*c90dc99bSWeizhao Jiang TEE_PARAM_TYPE_NONE) != type) 199*c90dc99bSWeizhao Jiang return TEE_ERROR_BAD_PARAMETERS; 200*c90dc99bSWeizhao Jiang 201*c90dc99bSWeizhao Jiang tee_time_get_sys_time(&tee_time); 202*c90dc99bSWeizhao Jiang tee_time_get_ree_time(&ree_time); 203*c90dc99bSWeizhao Jiang 204*c90dc99bSWeizhao Jiang p[0].value.a = ree_time.seconds; 205*c90dc99bSWeizhao Jiang p[0].value.b = ree_time.millis; 206*c90dc99bSWeizhao Jiang p[1].value.a = tee_time.seconds; 207*c90dc99bSWeizhao Jiang p[1].value.b = tee_time.millis; 208*c90dc99bSWeizhao Jiang 209*c90dc99bSWeizhao Jiang return TEE_SUCCESS; 210*c90dc99bSWeizhao Jiang } 211*c90dc99bSWeizhao 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); 229*c90dc99bSWeizhao Jiang case STATS_CMD_GET_TIME: 230*c90dc99bSWeizhao 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