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