xref: /arm-trusted-firmware/include/lib/pmf/pmf_helpers.h (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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