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