1*54fd6939SJiyong Park /* 2*54fd6939SJiyong Park * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. 3*54fd6939SJiyong Park * 4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause 5*54fd6939SJiyong Park */ 6*54fd6939SJiyong Park 7*54fd6939SJiyong Park #ifndef PMF_HELPERS_H 8*54fd6939SJiyong Park #define PMF_HELPERS_H 9*54fd6939SJiyong Park 10*54fd6939SJiyong Park #include <assert.h> 11*54fd6939SJiyong Park #include <stddef.h> 12*54fd6939SJiyong Park #include <stdint.h> 13*54fd6939SJiyong Park 14*54fd6939SJiyong Park #include <arch_helpers.h> 15*54fd6939SJiyong Park #include <common/bl_common.h> 16*54fd6939SJiyong Park #include <plat/common/platform.h> 17*54fd6939SJiyong Park 18*54fd6939SJiyong Park /* 19*54fd6939SJiyong Park * Prototype for PMF service functions. 20*54fd6939SJiyong Park */ 21*54fd6939SJiyong Park typedef int (*pmf_svc_init_t)(void); 22*54fd6939SJiyong Park typedef unsigned long long (*pmf_svc_get_ts_t)(unsigned int tid, 23*54fd6939SJiyong Park u_register_t mpidr, 24*54fd6939SJiyong Park unsigned int flags); 25*54fd6939SJiyong Park 26*54fd6939SJiyong Park /* 27*54fd6939SJiyong Park * This is the definition of PMF service desc. 28*54fd6939SJiyong Park */ 29*54fd6939SJiyong Park typedef struct pmf_svc_desc { 30*54fd6939SJiyong Park /* Structure version information */ 31*54fd6939SJiyong Park param_header_t h; 32*54fd6939SJiyong Park 33*54fd6939SJiyong Park /* Name of the PMF service */ 34*54fd6939SJiyong Park const char *name; 35*54fd6939SJiyong Park 36*54fd6939SJiyong Park /* PMF service config: Implementer id, Service id and total id*/ 37*54fd6939SJiyong Park unsigned int svc_config; 38*54fd6939SJiyong Park 39*54fd6939SJiyong Park /* PMF service initialization handler */ 40*54fd6939SJiyong Park pmf_svc_init_t init; 41*54fd6939SJiyong Park 42*54fd6939SJiyong Park /* PMF service time-stamp retrieval handler */ 43*54fd6939SJiyong Park pmf_svc_get_ts_t get_ts; 44*54fd6939SJiyong Park } pmf_svc_desc_t; 45*54fd6939SJiyong Park 46*54fd6939SJiyong Park #if ENABLE_PMF 47*54fd6939SJiyong Park /* 48*54fd6939SJiyong Park * Convenience macros for capturing time-stamp. 49*54fd6939SJiyong Park */ 50*54fd6939SJiyong Park #define PMF_DECLARE_CAPTURE_TIMESTAMP(_name) \ 51*54fd6939SJiyong Park void pmf_capture_timestamp_with_cache_maint_ ## _name( \ 52*54fd6939SJiyong Park unsigned int tid, \ 53*54fd6939SJiyong Park unsigned long long ts); \ 54*54fd6939SJiyong Park void pmf_capture_timestamp_ ## _name( \ 55*54fd6939SJiyong Park unsigned int tid, \ 56*54fd6939SJiyong Park unsigned long long ts); 57*54fd6939SJiyong Park 58*54fd6939SJiyong Park #define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags) \ 59*54fd6939SJiyong Park do { \ 60*54fd6939SJiyong Park unsigned long long ts = read_cntpct_el0(); \ 61*54fd6939SJiyong Park if (((_flags) & PMF_CACHE_MAINT) != 0U) \ 62*54fd6939SJiyong Park pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), ts);\ 63*54fd6939SJiyong Park else \ 64*54fd6939SJiyong Park pmf_capture_timestamp_ ## _name((_tid), ts); \ 65*54fd6939SJiyong Park } while (0) 66*54fd6939SJiyong Park 67*54fd6939SJiyong Park #define PMF_CAPTURE_AND_GET_TIMESTAMP(_name, _tid, _flags, _tsval) \ 68*54fd6939SJiyong Park do { \ 69*54fd6939SJiyong Park (_tsval) = read_cntpct_el0(); \ 70*54fd6939SJiyong Park CASSERT(sizeof(_tsval) == sizeof(unsigned long long), invalid_tsval_size);\ 71*54fd6939SJiyong Park if (((_flags) & PMF_CACHE_MAINT) != 0U) \ 72*54fd6939SJiyong Park pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_tsval));\ 73*54fd6939SJiyong Park else \ 74*54fd6939SJiyong Park pmf_capture_timestamp_ ## _name((_tid), (_tsval));\ 75*54fd6939SJiyong Park } while (0) 76*54fd6939SJiyong Park 77*54fd6939SJiyong Park #define PMF_WRITE_TIMESTAMP(_name, _tid, _flags, _wrval) \ 78*54fd6939SJiyong Park do { \ 79*54fd6939SJiyong Park CASSERT(sizeof(_wrval) == sizeof(unsigned long long), invalid_wrval_size);\ 80*54fd6939SJiyong Park if (((_flags) & PMF_CACHE_MAINT) != 0U) \ 81*54fd6939SJiyong Park pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_wrval));\ 82*54fd6939SJiyong Park else \ 83*54fd6939SJiyong Park pmf_capture_timestamp_ ## _name((_tid), (_wrval));\ 84*54fd6939SJiyong Park } while (0) 85*54fd6939SJiyong Park 86*54fd6939SJiyong Park /* 87*54fd6939SJiyong Park * Convenience macros for retrieving time-stamp. 88*54fd6939SJiyong Park */ 89*54fd6939SJiyong Park #define PMF_DECLARE_GET_TIMESTAMP(_name) \ 90*54fd6939SJiyong Park unsigned long long pmf_get_timestamp_by_index_ ## _name(\ 91*54fd6939SJiyong Park unsigned int tid, \ 92*54fd6939SJiyong Park unsigned int cpuid, \ 93*54fd6939SJiyong Park unsigned int flags); \ 94*54fd6939SJiyong Park unsigned long long pmf_get_timestamp_by_mpidr_ ## _name(\ 95*54fd6939SJiyong Park unsigned int tid, \ 96*54fd6939SJiyong Park u_register_t mpidr, \ 97*54fd6939SJiyong Park unsigned int flags); 98*54fd6939SJiyong Park 99*54fd6939SJiyong Park #define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval)\ 100*54fd6939SJiyong Park _tsval = pmf_get_timestamp_by_mpidr_ ## _name(_tid, _mpidr, _flags) 101*54fd6939SJiyong Park 102*54fd6939SJiyong Park #define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval)\ 103*54fd6939SJiyong Park _tsval = pmf_get_timestamp_by_index_ ## _name(_tid, _cpuid, _flags) 104*54fd6939SJiyong Park 105*54fd6939SJiyong Park /* Convenience macros to register a PMF service.*/ 106*54fd6939SJiyong Park /* 107*54fd6939SJiyong Park * This macro is used to register a PMF Service. It allocates PMF memory 108*54fd6939SJiyong Park * and defines default service-specific PMF functions. 109*54fd6939SJiyong Park */ 110*54fd6939SJiyong Park #define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) \ 111*54fd6939SJiyong Park PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _totalid) \ 112*54fd6939SJiyong Park PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags) \ 113*54fd6939SJiyong Park PMF_DEFINE_GET_TIMESTAMP(_name) 114*54fd6939SJiyong Park 115*54fd6939SJiyong Park /* 116*54fd6939SJiyong Park * This macro is used to register a PMF service, including an 117*54fd6939SJiyong Park * SMC interface to that service. 118*54fd6939SJiyong Park */ 119*54fd6939SJiyong Park #define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags)\ 120*54fd6939SJiyong Park PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) \ 121*54fd6939SJiyong Park PMF_DEFINE_SERVICE_DESC(_name, PMF_ARM_TIF_IMPL_ID, \ 122*54fd6939SJiyong Park _svcid, _totalid, NULL, \ 123*54fd6939SJiyong Park pmf_get_timestamp_by_mpidr_ ## _name) 124*54fd6939SJiyong Park 125*54fd6939SJiyong Park /* 126*54fd6939SJiyong Park * This macro is used to register a PMF service that has an SMC interface 127*54fd6939SJiyong Park * but provides its own service-specific PMF functions. 128*54fd6939SJiyong Park */ 129*54fd6939SJiyong Park #define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid, \ 130*54fd6939SJiyong Park _init, _getts) \ 131*54fd6939SJiyong Park PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid, \ 132*54fd6939SJiyong Park _init, _getts) 133*54fd6939SJiyong Park 134*54fd6939SJiyong Park #else 135*54fd6939SJiyong Park 136*54fd6939SJiyong Park #define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) 137*54fd6939SJiyong Park #define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags) 138*54fd6939SJiyong Park #define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid, \ 139*54fd6939SJiyong Park _init, _getts) 140*54fd6939SJiyong Park #define PMF_DECLARE_CAPTURE_TIMESTAMP(_name) 141*54fd6939SJiyong Park #define PMF_DECLARE_GET_TIMESTAMP(_name) 142*54fd6939SJiyong Park #define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags) 143*54fd6939SJiyong Park #define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval) 144*54fd6939SJiyong Park #define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval) 145*54fd6939SJiyong Park 146*54fd6939SJiyong Park #endif /* ENABLE_PMF */ 147*54fd6939SJiyong Park 148*54fd6939SJiyong Park /* 149*54fd6939SJiyong Park * Convenience macro to allocate memory for a PMF service. 150*54fd6939SJiyong Park * 151*54fd6939SJiyong Park * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. 152*54fd6939SJiyong Park */ 153*54fd6939SJiyong Park #define PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _total_id) \ 154*54fd6939SJiyong Park extern unsigned long long pmf_ts_mem_ ## _name[_total_id]; \ 155*54fd6939SJiyong Park unsigned long long pmf_ts_mem_ ## _name[_total_id] \ 156*54fd6939SJiyong Park __aligned(CACHE_WRITEBACK_GRANULE) \ 157*54fd6939SJiyong Park __section("pmf_timestamp_array") \ 158*54fd6939SJiyong Park __used; 159*54fd6939SJiyong Park 160*54fd6939SJiyong Park /* 161*54fd6939SJiyong Park * Convenience macro to validate tid index for the given TS array. 162*54fd6939SJiyong Park */ 163*54fd6939SJiyong Park #define PMF_VALIDATE_TID(_name, _tid) \ 164*54fd6939SJiyong Park assert((_tid & PMF_TID_MASK) < (ARRAY_SIZE(pmf_ts_mem_ ## _name))) 165*54fd6939SJiyong Park 166*54fd6939SJiyong Park /* 167*54fd6939SJiyong Park * Convenience macros for capturing time-stamp. 168*54fd6939SJiyong Park * 169*54fd6939SJiyong Park * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. 170*54fd6939SJiyong Park */ 171*54fd6939SJiyong Park #define PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags) \ 172*54fd6939SJiyong Park void pmf_capture_timestamp_ ## _name( \ 173*54fd6939SJiyong Park unsigned int tid, \ 174*54fd6939SJiyong Park unsigned long long ts) \ 175*54fd6939SJiyong Park { \ 176*54fd6939SJiyong Park CASSERT(_flags != 0, select_proper_config); \ 177*54fd6939SJiyong Park PMF_VALIDATE_TID(_name, (uint64_t)tid); \ 178*54fd6939SJiyong Park uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ 179*54fd6939SJiyong Park if (((_flags) & PMF_STORE_ENABLE) != 0) \ 180*54fd6939SJiyong Park __pmf_store_timestamp(base_addr, \ 181*54fd6939SJiyong Park (uint64_t)tid, ts); \ 182*54fd6939SJiyong Park if (((_flags) & PMF_DUMP_ENABLE) != 0) \ 183*54fd6939SJiyong Park __pmf_dump_timestamp((uint64_t)tid, ts); \ 184*54fd6939SJiyong Park } \ 185*54fd6939SJiyong Park void pmf_capture_timestamp_with_cache_maint_ ## _name( \ 186*54fd6939SJiyong Park unsigned int tid, \ 187*54fd6939SJiyong Park unsigned long long ts) \ 188*54fd6939SJiyong Park { \ 189*54fd6939SJiyong Park CASSERT(_flags != 0, select_proper_config); \ 190*54fd6939SJiyong Park PMF_VALIDATE_TID(_name, (uint64_t)tid); \ 191*54fd6939SJiyong Park uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ 192*54fd6939SJiyong Park if (((_flags) & PMF_STORE_ENABLE) != 0) \ 193*54fd6939SJiyong Park __pmf_store_timestamp_with_cache_maint( \ 194*54fd6939SJiyong Park base_addr, (uint64_t)tid, ts); \ 195*54fd6939SJiyong Park if (((_flags) & PMF_DUMP_ENABLE) != 0) \ 196*54fd6939SJiyong Park __pmf_dump_timestamp((uint64_t)tid, ts); \ 197*54fd6939SJiyong Park } 198*54fd6939SJiyong Park 199*54fd6939SJiyong Park /* 200*54fd6939SJiyong Park * Convenience macros for retrieving time-stamp. 201*54fd6939SJiyong Park * 202*54fd6939SJiyong Park * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. 203*54fd6939SJiyong Park */ 204*54fd6939SJiyong Park #define PMF_DEFINE_GET_TIMESTAMP(_name) \ 205*54fd6939SJiyong Park unsigned long long pmf_get_timestamp_by_index_ ## _name( \ 206*54fd6939SJiyong Park unsigned int tid, unsigned int cpuid, unsigned int flags)\ 207*54fd6939SJiyong Park { \ 208*54fd6939SJiyong Park PMF_VALIDATE_TID(_name, tid); \ 209*54fd6939SJiyong Park uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ 210*54fd6939SJiyong Park return __pmf_get_timestamp(base_addr, tid, cpuid, flags);\ 211*54fd6939SJiyong Park } \ 212*54fd6939SJiyong Park unsigned long long pmf_get_timestamp_by_mpidr_ ## _name( \ 213*54fd6939SJiyong Park unsigned int tid, u_register_t mpidr, unsigned int flags)\ 214*54fd6939SJiyong Park { \ 215*54fd6939SJiyong Park PMF_VALIDATE_TID(_name, tid); \ 216*54fd6939SJiyong Park uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ 217*54fd6939SJiyong Park return __pmf_get_timestamp(base_addr, tid, \ 218*54fd6939SJiyong Park plat_core_pos_by_mpidr(mpidr), flags); \ 219*54fd6939SJiyong Park } 220*54fd6939SJiyong Park 221*54fd6939SJiyong Park /* 222*54fd6939SJiyong Park * Convenience macro to register a PMF service. 223*54fd6939SJiyong Park * This is needed for services that require SMC handling. 224*54fd6939SJiyong Park */ 225*54fd6939SJiyong Park #define PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid, \ 226*54fd6939SJiyong Park _init, _getts_by_mpidr) \ 227*54fd6939SJiyong Park static const pmf_svc_desc_t __pmf_desc_ ## _name \ 228*54fd6939SJiyong Park __section("pmf_svc_descs") __used = { \ 229*54fd6939SJiyong Park .h.type = PARAM_EP, \ 230*54fd6939SJiyong Park .h.version = VERSION_1, \ 231*54fd6939SJiyong Park .h.size = sizeof(pmf_svc_desc_t), \ 232*54fd6939SJiyong Park .h.attr = 0, \ 233*54fd6939SJiyong Park .name = #_name, \ 234*54fd6939SJiyong Park .svc_config = ((((_implid) << PMF_IMPL_ID_SHIFT) & \ 235*54fd6939SJiyong Park PMF_IMPL_ID_MASK) | \ 236*54fd6939SJiyong Park (((_svcid) << PMF_SVC_ID_SHIFT) & \ 237*54fd6939SJiyong Park PMF_SVC_ID_MASK) | \ 238*54fd6939SJiyong Park (((_totalid) << PMF_TID_SHIFT) & \ 239*54fd6939SJiyong Park PMF_TID_MASK)), \ 240*54fd6939SJiyong Park .init = _init, \ 241*54fd6939SJiyong Park .get_ts = _getts_by_mpidr \ 242*54fd6939SJiyong Park }; 243*54fd6939SJiyong Park 244*54fd6939SJiyong Park /* PMF internal functions */ 245*54fd6939SJiyong Park void __pmf_dump_timestamp(unsigned int tid, unsigned long long ts); 246*54fd6939SJiyong Park void __pmf_store_timestamp(uintptr_t base_addr, 247*54fd6939SJiyong Park unsigned int tid, 248*54fd6939SJiyong Park unsigned long long ts); 249*54fd6939SJiyong Park void __pmf_store_timestamp_with_cache_maint(uintptr_t base_addr, 250*54fd6939SJiyong Park unsigned int tid, 251*54fd6939SJiyong Park unsigned long long ts); 252*54fd6939SJiyong Park unsigned long long __pmf_get_timestamp(uintptr_t base_addr, 253*54fd6939SJiyong Park unsigned int tid, 254*54fd6939SJiyong Park unsigned int cpuid, 255*54fd6939SJiyong Park unsigned int flags); 256*54fd6939SJiyong Park #endif /* PMF_HELPERS_H */ 257