xref: /aosp_15_r20/external/arm-trusted-firmware/include/lib/pmf/pmf_helpers.h (revision 54fd6939e177f8ff529b10183254802c76df6d08)
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