blob: 01cc179cff1dc73c57151a88fc6efdc64b758280 [file] [log] [blame]
Yatharth Kochar9518d022016-03-11 14:20:19 +00001/*
Jimmy Brissoned202072020-08-04 16:18:52 -05002 * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
Yatharth Kochar9518d022016-03-11 14:20:19 +00003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Yatharth Kochar9518d022016-03-11 14:20:19 +00005 */
6
Antonio Nino Diaze89a4532018-07-18 13:26:25 +01007#ifndef PMF_HELPERS_H
8#define PMF_HELPERS_H
Yatharth Kochar9518d022016-03-11 14:20:19 +00009
Yatharth Kochar9518d022016-03-11 14:20:19 +000010#include <assert.h>
Yatharth Kochar9518d022016-03-11 14:20:19 +000011#include <stddef.h>
Isla Mitchell99305012017-07-11 14:54:08 +010012#include <stdint.h>
Yatharth Kochar9518d022016-03-11 14:20:19 +000013
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000014#include <arch_helpers.h>
15#include <common/bl_common.h>
16#include <plat/common/platform.h>
17
Yatharth Kochar9518d022016-03-11 14:20:19 +000018/*
19 * Prototype for PMF service functions.
20 */
21typedef int (*pmf_svc_init_t)(void);
22typedef 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 */
29typedef 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
Madhukar Pappireddya091d042020-01-06 14:42:30 -060046#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
Yatharth Kochar9518d022016-03-11 14:20:19 +0000148/*
149 * Convenience macro to allocate memory for a PMF service.
Roberto Vargas2ca18d92018-02-12 12:36:17 +0000150 *
151 * The extern declaration is there to satisfy MISRA C-2012 rule 8.4.
Yatharth Kochar9518d022016-03-11 14:20:19 +0000152 */
dp-arma97bd892016-08-15 10:35:54 +0100153#define PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _total_id) \
Roberto Vargas2ca18d92018-02-12 12:36:17 +0000154 extern unsigned long long pmf_ts_mem_ ## _name[_total_id]; \
dp-arma97bd892016-08-15 10:35:54 +0100155 unsigned long long pmf_ts_mem_ ## _name[_total_id] \
dp-arm8810e832016-09-09 11:39:09 +0100156 __aligned(CACHE_WRITEBACK_GRANULE) \
Chris Kay33bfc5e2023-02-14 11:30:04 +0000157 __section(".pmf_timestamp_array") \
dp-arm8810e832016-09-09 11:39:09 +0100158 __used;
Yatharth Kochar9518d022016-03-11 14:20:19 +0000159
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.
Roberto Vargas2ca18d92018-02-12 12:36:17 +0000168 *
169 * The extern declaration is there to satisfy MISRA C-2012 rule 8.4.
Yatharth Kochar9518d022016-03-11 14:20:19 +0000170 */
171#define PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags) \
172 void pmf_capture_timestamp_ ## _name( \
173 unsigned int tid, \
174 unsigned long long ts) \
175 { \
Manish V Badarkhe4d062c02020-03-22 04:23:24 +0000176 CASSERT(_flags != 0, select_proper_config); \
Jimmy Brissoned202072020-08-04 16:18:52 -0500177 PMF_VALIDATE_TID(_name, (uint64_t)tid); \
Yatharth Kochar9518d022016-03-11 14:20:19 +0000178 uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \
Antonio Nino Diaze89a4532018-07-18 13:26:25 +0100179 if (((_flags) & PMF_STORE_ENABLE) != 0) \
Jimmy Brissoned202072020-08-04 16:18:52 -0500180 __pmf_store_timestamp(base_addr, \
181 (uint64_t)tid, ts); \
Antonio Nino Diaze89a4532018-07-18 13:26:25 +0100182 if (((_flags) & PMF_DUMP_ENABLE) != 0) \
Jimmy Brissoned202072020-08-04 16:18:52 -0500183 __pmf_dump_timestamp((uint64_t)tid, ts); \
Yatharth Kochar9518d022016-03-11 14:20:19 +0000184 } \
185 void pmf_capture_timestamp_with_cache_maint_ ## _name( \
186 unsigned int tid, \
187 unsigned long long ts) \
188 { \
Manish V Badarkhe4d062c02020-03-22 04:23:24 +0000189 CASSERT(_flags != 0, select_proper_config); \
Jimmy Brissoned202072020-08-04 16:18:52 -0500190 PMF_VALIDATE_TID(_name, (uint64_t)tid); \
Yatharth Kochar9518d022016-03-11 14:20:19 +0000191 uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \
Antonio Nino Diaze89a4532018-07-18 13:26:25 +0100192 if (((_flags) & PMF_STORE_ENABLE) != 0) \
Jimmy Brissoned202072020-08-04 16:18:52 -0500193 __pmf_store_timestamp_with_cache_maint( \
194 base_addr, (uint64_t)tid, ts); \
Antonio Nino Diaze89a4532018-07-18 13:26:25 +0100195 if (((_flags) & PMF_DUMP_ENABLE) != 0) \
Jimmy Brissoned202072020-08-04 16:18:52 -0500196 __pmf_dump_timestamp((uint64_t)tid, ts); \
Yatharth Kochar9518d022016-03-11 14:20:19 +0000197 }
198
199/*
200 * Convenience macros for retrieving time-stamp.
Roberto Vargas2ca18d92018-02-12 12:36:17 +0000201 *
202 * The extern declaration is there to satisfy MISRA C-2012 rule 8.4.
Yatharth Kochar9518d022016-03-11 14:20:19 +0000203 */
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( \
Yatharth Kochar9518d022016-03-11 14:20:19 +0000213 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 \
Chris Kay33bfc5e2023-02-14 11:30:04 +0000228 __section(".pmf_svc_descs") __used = { \
Yatharth Kochar9518d022016-03-11 14:20:19 +0000229 .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 */
245void __pmf_dump_timestamp(unsigned int tid, unsigned long long ts);
246void __pmf_store_timestamp(uintptr_t base_addr,
247 unsigned int tid,
248 unsigned long long ts);
249void __pmf_store_timestamp_with_cache_maint(uintptr_t base_addr,
250 unsigned int tid,
251 unsigned long long ts);
252unsigned long long __pmf_get_timestamp(uintptr_t base_addr,
253 unsigned int tid,
254 unsigned int cpuid,
255 unsigned int flags);
Antonio Nino Diaze89a4532018-07-18 13:26:25 +0100256#endif /* PMF_HELPERS_H */