pmf_helpers.h 8.2 KB

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