1*5843bb75SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2*5843bb75SJerome Forissier /* 3*5843bb75SJerome Forissier * Copyright (c) 2015, Linaro Limited 4*5843bb75SJerome Forissier */ 5*5843bb75SJerome Forissier #include <compiler.h> 6*5843bb75SJerome Forissier #include <stdio.h> 7*5843bb75SJerome Forissier #include <trace.h> 8*5843bb75SJerome Forissier #include <kernel/pseudo_ta.h> 9*5843bb75SJerome Forissier #include <mm/tee_pager.h> 10*5843bb75SJerome Forissier #include <mm/tee_mm.h> 11*5843bb75SJerome Forissier #include <string.h> 12*5843bb75SJerome Forissier #include <string_ext.h> 13*5843bb75SJerome Forissier #include <malloc.h> 14*5843bb75SJerome Forissier 15*5843bb75SJerome Forissier #define TA_NAME "stats.ta" 16*5843bb75SJerome Forissier 17*5843bb75SJerome Forissier #define STATS_UUID \ 18*5843bb75SJerome Forissier { 0xd96a5b40, 0xe2c7, 0xb1af, \ 19*5843bb75SJerome Forissier { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } 20*5843bb75SJerome Forissier 21*5843bb75SJerome Forissier #define STATS_CMD_PAGER_STATS 0 22*5843bb75SJerome Forissier #define STATS_CMD_ALLOC_STATS 1 23*5843bb75SJerome Forissier #define STATS_CMD_MEMLEAK_STATS 2 24*5843bb75SJerome Forissier 25*5843bb75SJerome Forissier #define STATS_NB_POOLS 4 26*5843bb75SJerome Forissier 27*5843bb75SJerome Forissier static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 28*5843bb75SJerome Forissier { 29*5843bb75SJerome Forissier struct malloc_stats *stats; 30*5843bb75SJerome Forissier uint32_t size_to_retrieve; 31*5843bb75SJerome Forissier uint32_t pool_id; 32*5843bb75SJerome Forissier uint32_t i; 33*5843bb75SJerome Forissier 34*5843bb75SJerome Forissier /* 35*5843bb75SJerome Forissier * p[0].value.a = pool id (from 0 to n) 36*5843bb75SJerome Forissier * - 0 means all the pools to be retrieved 37*5843bb75SJerome Forissier * - 1..n means pool id 38*5843bb75SJerome Forissier * p[0].value.b = 0 if no reset of the stats 39*5843bb75SJerome Forissier * p[1].memref.buffer = output buffer to struct malloc_stats 40*5843bb75SJerome Forissier */ 41*5843bb75SJerome Forissier if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 42*5843bb75SJerome Forissier TEE_PARAM_TYPE_MEMREF_OUTPUT, 43*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 44*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE) != type) { 45*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 46*5843bb75SJerome Forissier } 47*5843bb75SJerome Forissier 48*5843bb75SJerome Forissier pool_id = p[0].value.a; 49*5843bb75SJerome Forissier if (pool_id > STATS_NB_POOLS) 50*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 51*5843bb75SJerome Forissier 52*5843bb75SJerome Forissier size_to_retrieve = sizeof(struct malloc_stats); 53*5843bb75SJerome Forissier if (!pool_id) 54*5843bb75SJerome Forissier size_to_retrieve *= STATS_NB_POOLS; 55*5843bb75SJerome Forissier 56*5843bb75SJerome Forissier if (p[1].memref.size < size_to_retrieve) { 57*5843bb75SJerome Forissier p[1].memref.size = size_to_retrieve; 58*5843bb75SJerome Forissier return TEE_ERROR_SHORT_BUFFER; 59*5843bb75SJerome Forissier } 60*5843bb75SJerome Forissier p[1].memref.size = size_to_retrieve; 61*5843bb75SJerome Forissier stats = p[1].memref.buffer; 62*5843bb75SJerome Forissier 63*5843bb75SJerome Forissier for (i = 1; i <= STATS_NB_POOLS; i++) { 64*5843bb75SJerome Forissier if ((pool_id) && (i != pool_id)) 65*5843bb75SJerome Forissier continue; 66*5843bb75SJerome Forissier 67*5843bb75SJerome Forissier switch (i) { 68*5843bb75SJerome Forissier case 1: 69*5843bb75SJerome Forissier malloc_get_stats(stats); 70*5843bb75SJerome Forissier strlcpy(stats->desc, "Heap", sizeof(stats->desc)); 71*5843bb75SJerome Forissier if (p[0].value.b) 72*5843bb75SJerome Forissier malloc_reset_stats(); 73*5843bb75SJerome Forissier break; 74*5843bb75SJerome Forissier 75*5843bb75SJerome Forissier case 2: 76*5843bb75SJerome Forissier EMSG("public DDR not managed by secure side anymore"); 77*5843bb75SJerome Forissier break; 78*5843bb75SJerome Forissier 79*5843bb75SJerome Forissier case 3: 80*5843bb75SJerome Forissier tee_mm_get_pool_stats(&tee_mm_sec_ddr, stats, 81*5843bb75SJerome Forissier !!p[0].value.b); 82*5843bb75SJerome Forissier strlcpy(stats->desc, "Secure DDR", sizeof(stats->desc)); 83*5843bb75SJerome Forissier break; 84*5843bb75SJerome Forissier 85*5843bb75SJerome Forissier #ifdef CFG_VIRTUALIZATION 86*5843bb75SJerome Forissier case 4: 87*5843bb75SJerome Forissier nex_malloc_get_stats(stats); 88*5843bb75SJerome Forissier strlcpy(stats->desc, "KHeap", sizeof(stats->desc)); 89*5843bb75SJerome Forissier if (p[0].value.b) 90*5843bb75SJerome Forissier nex_malloc_reset_stats(); 91*5843bb75SJerome Forissier break; 92*5843bb75SJerome Forissier #endif 93*5843bb75SJerome Forissier default: 94*5843bb75SJerome Forissier EMSG("Wrong pool id"); 95*5843bb75SJerome Forissier break; 96*5843bb75SJerome Forissier } 97*5843bb75SJerome Forissier 98*5843bb75SJerome Forissier stats++; 99*5843bb75SJerome Forissier } 100*5843bb75SJerome Forissier 101*5843bb75SJerome Forissier return TEE_SUCCESS; 102*5843bb75SJerome Forissier } 103*5843bb75SJerome Forissier 104*5843bb75SJerome Forissier static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 105*5843bb75SJerome Forissier { 106*5843bb75SJerome Forissier struct tee_pager_stats stats; 107*5843bb75SJerome Forissier 108*5843bb75SJerome Forissier if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 109*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT, 110*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT, 111*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE) != type) { 112*5843bb75SJerome Forissier EMSG("expect 3 output values as argument"); 113*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 114*5843bb75SJerome Forissier } 115*5843bb75SJerome Forissier 116*5843bb75SJerome Forissier tee_pager_get_stats(&stats); 117*5843bb75SJerome Forissier p[0].value.a = stats.npages; 118*5843bb75SJerome Forissier p[0].value.b = stats.npages_all; 119*5843bb75SJerome Forissier p[1].value.a = stats.ro_hits; 120*5843bb75SJerome Forissier p[1].value.b = stats.rw_hits; 121*5843bb75SJerome Forissier p[2].value.a = stats.hidden_hits; 122*5843bb75SJerome Forissier p[2].value.b = stats.zi_released; 123*5843bb75SJerome Forissier 124*5843bb75SJerome Forissier return TEE_SUCCESS; 125*5843bb75SJerome Forissier } 126*5843bb75SJerome Forissier 127*5843bb75SJerome Forissier static TEE_Result get_memleak_stats(uint32_t type, 128*5843bb75SJerome Forissier TEE_Param p[TEE_NUM_PARAMS] __unused) 129*5843bb75SJerome Forissier { 130*5843bb75SJerome Forissier 131*5843bb75SJerome Forissier if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, 132*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) 133*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 134*5843bb75SJerome Forissier 135*5843bb75SJerome Forissier mdbg_check(1); 136*5843bb75SJerome Forissier 137*5843bb75SJerome Forissier return TEE_SUCCESS; 138*5843bb75SJerome Forissier } 139*5843bb75SJerome Forissier 140*5843bb75SJerome Forissier /* 141*5843bb75SJerome Forissier * Trusted Application Entry Points 142*5843bb75SJerome Forissier */ 143*5843bb75SJerome Forissier 144*5843bb75SJerome Forissier static TEE_Result invoke_command(void *psess __unused, 145*5843bb75SJerome Forissier uint32_t cmd, uint32_t ptypes, 146*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 147*5843bb75SJerome Forissier { 148*5843bb75SJerome Forissier switch (cmd) { 149*5843bb75SJerome Forissier case STATS_CMD_PAGER_STATS: 150*5843bb75SJerome Forissier return get_pager_stats(ptypes, params); 151*5843bb75SJerome Forissier case STATS_CMD_ALLOC_STATS: 152*5843bb75SJerome Forissier return get_alloc_stats(ptypes, params); 153*5843bb75SJerome Forissier case STATS_CMD_MEMLEAK_STATS: 154*5843bb75SJerome Forissier return get_memleak_stats(ptypes, params); 155*5843bb75SJerome Forissier default: 156*5843bb75SJerome Forissier break; 157*5843bb75SJerome Forissier } 158*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 159*5843bb75SJerome Forissier } 160*5843bb75SJerome Forissier 161*5843bb75SJerome Forissier pseudo_ta_register(.uuid = STATS_UUID, .name = TA_NAME, 162*5843bb75SJerome Forissier .flags = PTA_DEFAULT_FLAGS, 163*5843bb75SJerome Forissier .invoke_command_entry_point = invoke_command); 164