1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2020 Marvell International Ltd. 3 */ 4 5 #ifndef _RTE_TRACE_POINT_H_ 6 #define _RTE_TRACE_POINT_H_ 7 8 /** 9 * @file 10 * 11 * RTE Tracepoint API 12 * 13 * This file provides the tracepoint API to RTE applications. 14 * 15 * @warning 16 * @b EXPERIMENTAL: this API may change without prior notice 17 */ 18 19 #ifdef __cplusplus 20 extern "C" { 21 #endif 22 23 #include <stdbool.h> 24 #include <stdio.h> 25 26 #include <rte_branch_prediction.h> 27 #include <rte_common.h> 28 #include <rte_compat.h> 29 #include <rte_cycles.h> 30 #include <rte_per_lcore.h> 31 #include <rte_string_fns.h> 32 #include <rte_uuid.h> 33 34 /** The tracepoint object. */ 35 typedef uint64_t rte_trace_point_t; 36 37 /** 38 * Macro to define the tracepoint arguments in RTE_TRACE_POINT macro. 39 40 * @see RTE_TRACE_POINT, RTE_TRACE_POINT_FP 41 */ 42 #define RTE_TRACE_POINT_ARGS 43 44 /** @internal Helper macro to support RTE_TRACE_POINT and RTE_TRACE_POINT_FP */ 45 #define __RTE_TRACE_POINT(_mode, _tp, _args, ...) \ 46 extern rte_trace_point_t __##_tp; \ 47 static __rte_always_inline void \ 48 _tp _args \ 49 { \ 50 __rte_trace_point_emit_header_##_mode(&__##_tp); \ 51 __VA_ARGS__ \ 52 } 53 54 /** 55 * Create a tracepoint. 56 * 57 * A tracepoint is defined by specifying: 58 * - its input arguments: they are the C function style parameters to define 59 * the arguments of tracepoint function. These input arguments are embedded 60 * using the RTE_TRACE_POINT_ARGS macro. 61 * - its output event fields: they are the sources of event fields that form 62 * the payload of any event that the execution of the tracepoint macro emits 63 * for this particular tracepoint. The application uses 64 * rte_trace_point_emit_* macros to emit the output event fields. 65 * 66 * @param tp 67 * Tracepoint object. Before using the tracepoint, an application needs to 68 * define the tracepoint using RTE_TRACE_POINT_REGISTER macro. 69 * @param args 70 * C function style input arguments to define the arguments to tracepoint 71 * function. 72 * @param ... 73 * Define the payload of trace function. The payload will be formed using 74 * rte_trace_point_emit_* macros. Use ";" delimiter between two payloads. 75 * 76 * @see RTE_TRACE_POINT_ARGS, RTE_TRACE_POINT_REGISTER, rte_trace_point_emit_* 77 */ 78 #define RTE_TRACE_POINT(tp, args, ...) \ 79 __RTE_TRACE_POINT(generic, tp, args, __VA_ARGS__) 80 81 /** 82 * Create a tracepoint for fast path. 83 * 84 * Similar to RTE_TRACE_POINT, except that it is removed at compilation time 85 * unless the RTE_ENABLE_TRACE_FP configuration parameter is set. 86 * 87 * @param tp 88 * Tracepoint object. Before using the tracepoint, an application needs to 89 * define the tracepoint using RTE_TRACE_POINT_REGISTER macro. 90 * @param args 91 * C function style input arguments to define the arguments to tracepoint. 92 * function. 93 * @param ... 94 * Define the payload of trace function. The payload will be formed using 95 * rte_trace_point_emit_* macros, Use ";" delimiter between two payloads. 96 * 97 * @see RTE_TRACE_POINT 98 */ 99 #define RTE_TRACE_POINT_FP(tp, args, ...) \ 100 __RTE_TRACE_POINT(fp, tp, args, __VA_ARGS__) 101 102 #ifdef __DOXYGEN__ 103 104 /** 105 * Register a tracepoint. 106 * 107 * @param trace 108 * The tracepoint object created using RTE_TRACE_POINT_REGISTER. 109 * @param name 110 * The name of the tracepoint object. 111 * @return 112 * - 0: Successfully registered the tracepoint. 113 * - <0: Failure to register the tracepoint. 114 */ 115 #define RTE_TRACE_POINT_REGISTER(trace, name) 116 117 /** Tracepoint function payload for uint64_t datatype */ 118 #define rte_trace_point_emit_u64(val) 119 /** Tracepoint function payload for int64_t datatype */ 120 #define rte_trace_point_emit_i64(val) 121 /** Tracepoint function payload for uint32_t datatype */ 122 #define rte_trace_point_emit_u32(val) 123 /** Tracepoint function payload for int32_t datatype */ 124 #define rte_trace_point_emit_i32(val) 125 /** Tracepoint function payload for uint16_t datatype */ 126 #define rte_trace_point_emit_u16(val) 127 /** Tracepoint function payload for int16_t datatype */ 128 #define rte_trace_point_emit_i16(val) 129 /** Tracepoint function payload for uint8_t datatype */ 130 #define rte_trace_point_emit_u8(val) 131 /** Tracepoint function payload for int8_t datatype */ 132 #define rte_trace_point_emit_i8(val) 133 /** Tracepoint function payload for int datatype */ 134 #define rte_trace_point_emit_int(val) 135 /** Tracepoint function payload for long datatype */ 136 #define rte_trace_point_emit_long(val) 137 /** Tracepoint function payload for size_t datatype */ 138 #define rte_trace_point_emit_size_t(val) 139 /** Tracepoint function payload for float datatype */ 140 #define rte_trace_point_emit_float(val) 141 /** Tracepoint function payload for double datatype */ 142 #define rte_trace_point_emit_double(val) 143 /** Tracepoint function payload for pointer datatype */ 144 #define rte_trace_point_emit_ptr(val) 145 /** Tracepoint function payload for string datatype */ 146 #define rte_trace_point_emit_string(val) 147 148 #endif /* __DOXYGEN__ */ 149 150 /** @internal Macro to define maximum emit length of string datatype. */ 151 #define __RTE_TRACE_EMIT_STRING_LEN_MAX 32 152 /** @internal Macro to define event header size. */ 153 #define __RTE_TRACE_EVENT_HEADER_SZ sizeof(uint64_t) 154 155 /** 156 * Enable recording events of the given tracepoint in the trace buffer. 157 * 158 * @param tp 159 * The tracepoint object to enable. 160 * @return 161 * - 0: Success. 162 * - (-ERANGE): Trace object is not registered. 163 */ 164 __rte_experimental 165 int rte_trace_point_enable(rte_trace_point_t *tp); 166 167 /** 168 * Disable recording events of the given tracepoint in the trace buffer. 169 * 170 * @param tp 171 * The tracepoint object to disable. 172 * @return 173 * - 0: Success. 174 * - (-ERANGE): Trace object is not registered. 175 */ 176 __rte_experimental 177 int rte_trace_point_disable(rte_trace_point_t *tp); 178 179 /** 180 * Test if recording events from the given tracepoint is enabled. 181 * 182 * @param tp 183 * The tracepoint object. 184 * @return 185 * true if tracepoint is enabled, false otherwise. 186 */ 187 __rte_experimental 188 bool rte_trace_point_is_enabled(rte_trace_point_t *tp); 189 190 /** 191 * Lookup a tracepoint object from its name. 192 * 193 * @param name 194 * The name of the tracepoint. 195 * @return 196 * The tracepoint object or NULL if not found. 197 */ 198 __rte_experimental 199 rte_trace_point_t *rte_trace_point_lookup(const char *name); 200 201 /** 202 * @internal 203 * 204 * Test if the tracepoint fast path compile-time option is enabled. 205 * 206 * @return 207 * true if tracepoint fast path enabled, false otherwise. 208 */ 209 __rte_experimental 210 static __rte_always_inline bool 211 __rte_trace_point_fp_is_enabled(void) 212 { 213 #ifdef RTE_ENABLE_TRACE_FP 214 return true; 215 #else 216 return false; 217 #endif 218 } 219 220 /** 221 * @internal 222 * 223 * Allocate trace memory buffer per thread. 224 * 225 */ 226 __rte_experimental 227 void __rte_trace_mem_per_thread_alloc(void); 228 229 /** 230 * @internal 231 * 232 * Helper function to emit field. 233 * 234 * @param sz 235 * The tracepoint size. 236 * @param field 237 * The name of the trace event. 238 * @param type 239 * The datatype of the trace event as string. 240 * @return 241 * - 0: Success. 242 * - <0: Failure. 243 */ 244 __rte_experimental 245 void __rte_trace_point_emit_field(size_t sz, const char *field, 246 const char *type); 247 248 /** 249 * @internal 250 * 251 * Helper function to register a dynamic tracepoint. 252 * Use RTE_TRACE_POINT_REGISTER macro for tracepoint registration. 253 * 254 * @param trace 255 * The tracepoint object created using RTE_TRACE_POINT_REGISTER. 256 * @param name 257 * The name of the tracepoint object. 258 * @param register_fn 259 * Trace registration function. 260 * @return 261 * - 0: Successfully registered the tracepoint. 262 * - <0: Failure to register the tracepoint. 263 */ 264 __rte_experimental 265 int __rte_trace_point_register(rte_trace_point_t *trace, const char *name, 266 void (*register_fn)(void)); 267 268 #ifndef __DOXYGEN__ 269 270 #ifndef _RTE_TRACE_POINT_REGISTER_H_ 271 #ifdef ALLOW_EXPERIMENTAL_API 272 273 #define __RTE_TRACE_EVENT_HEADER_ID_SHIFT (48) 274 275 #define __RTE_TRACE_FIELD_SIZE_SHIFT 0 276 #define __RTE_TRACE_FIELD_SIZE_MASK (0xffffULL << __RTE_TRACE_FIELD_SIZE_SHIFT) 277 #define __RTE_TRACE_FIELD_ID_SHIFT (16) 278 #define __RTE_TRACE_FIELD_ID_MASK (0xffffULL << __RTE_TRACE_FIELD_ID_SHIFT) 279 #define __RTE_TRACE_FIELD_ENABLE_MASK (1ULL << 63) 280 #define __RTE_TRACE_FIELD_ENABLE_DISCARD (1ULL << 62) 281 282 struct __rte_trace_stream_header { 283 uint32_t magic; 284 rte_uuid_t uuid; 285 uint32_t lcore_id; 286 char thread_name[__RTE_TRACE_EMIT_STRING_LEN_MAX]; 287 } __rte_packed; 288 289 struct __rte_trace_header { 290 uint32_t offset; 291 uint32_t len; 292 struct __rte_trace_stream_header stream_header; 293 uint8_t mem[]; 294 }; 295 296 RTE_DECLARE_PER_LCORE(void *, trace_mem); 297 298 static __rte_always_inline void * 299 __rte_trace_mem_get(uint64_t in) 300 { 301 struct __rte_trace_header *trace = 302 (struct __rte_trace_header *)(RTE_PER_LCORE(trace_mem)); 303 const uint16_t sz = in & __RTE_TRACE_FIELD_SIZE_MASK; 304 305 /* Trace memory is not initialized for this thread */ 306 if (unlikely(trace == NULL)) { 307 __rte_trace_mem_per_thread_alloc(); 308 trace = (struct __rte_trace_header *)(RTE_PER_LCORE(trace_mem)); 309 if (unlikely(trace == NULL)) 310 return NULL; 311 } 312 /* Check the wrap around case */ 313 uint32_t offset = trace->offset; 314 if (unlikely((offset + sz) >= trace->len)) { 315 /* Disable the trace event if it in DISCARD mode */ 316 if (unlikely(in & __RTE_TRACE_FIELD_ENABLE_DISCARD)) 317 return NULL; 318 319 offset = 0; 320 } 321 /* Align to event header size */ 322 offset = RTE_ALIGN_CEIL(offset, __RTE_TRACE_EVENT_HEADER_SZ); 323 void *mem = RTE_PTR_ADD(&trace->mem[0], offset); 324 offset += sz; 325 trace->offset = offset; 326 327 return mem; 328 } 329 330 static __rte_always_inline void * 331 __rte_trace_point_emit_ev_header(void *mem, uint64_t in) 332 { 333 uint64_t val; 334 335 /* Event header [63:0] = id [63:48] | timestamp [47:0] */ 336 val = rte_get_tsc_cycles() & 337 ~(0xffffULL << __RTE_TRACE_EVENT_HEADER_ID_SHIFT); 338 val |= ((in & __RTE_TRACE_FIELD_ID_MASK) << 339 (__RTE_TRACE_EVENT_HEADER_ID_SHIFT - 340 __RTE_TRACE_FIELD_ID_SHIFT)); 341 342 *(uint64_t *)mem = val; 343 return RTE_PTR_ADD(mem, __RTE_TRACE_EVENT_HEADER_SZ); 344 } 345 346 #define __rte_trace_point_emit_header_generic(t) \ 347 void *mem; \ 348 do { \ 349 const uint64_t val = __atomic_load_n(t, __ATOMIC_ACQUIRE); \ 350 if (likely(!(val & __RTE_TRACE_FIELD_ENABLE_MASK))) \ 351 return; \ 352 mem = __rte_trace_mem_get(val); \ 353 if (unlikely(mem == NULL)) \ 354 return; \ 355 mem = __rte_trace_point_emit_ev_header(mem, val); \ 356 } while (0) 357 358 #define __rte_trace_point_emit_header_fp(t) \ 359 if (!__rte_trace_point_fp_is_enabled()) \ 360 return; \ 361 __rte_trace_point_emit_header_generic(t) 362 363 #define __rte_trace_point_emit(in, type) \ 364 do { \ 365 memcpy(mem, &(in), sizeof(in)); \ 366 mem = RTE_PTR_ADD(mem, sizeof(in)); \ 367 } while (0) 368 369 #define rte_trace_point_emit_string(in) \ 370 do { \ 371 if (unlikely(in == NULL)) \ 372 return; \ 373 rte_strscpy((char *)mem, in, __RTE_TRACE_EMIT_STRING_LEN_MAX); \ 374 mem = RTE_PTR_ADD(mem, __RTE_TRACE_EMIT_STRING_LEN_MAX); \ 375 } while (0) 376 377 #else 378 379 #define __rte_trace_point_emit_header_generic(t) RTE_SET_USED(t) 380 #define __rte_trace_point_emit_header_fp(t) RTE_SET_USED(t) 381 #define __rte_trace_point_emit(in, type) RTE_SET_USED(in) 382 #define rte_trace_point_emit_string(in) RTE_SET_USED(in) 383 384 #endif /* ALLOW_EXPERIMENTAL_API */ 385 #endif /* _RTE_TRACE_POINT_REGISTER_H_ */ 386 387 #define rte_trace_point_emit_u64(in) __rte_trace_point_emit(in, uint64_t) 388 #define rte_trace_point_emit_i64(in) __rte_trace_point_emit(in, int64_t) 389 #define rte_trace_point_emit_u32(in) __rte_trace_point_emit(in, uint32_t) 390 #define rte_trace_point_emit_i32(in) __rte_trace_point_emit(in, int32_t) 391 #define rte_trace_point_emit_u16(in) __rte_trace_point_emit(in, uint16_t) 392 #define rte_trace_point_emit_i16(in) __rte_trace_point_emit(in, int16_t) 393 #define rte_trace_point_emit_u8(in) __rte_trace_point_emit(in, uint8_t) 394 #define rte_trace_point_emit_i8(in) __rte_trace_point_emit(in, int8_t) 395 #define rte_trace_point_emit_int(in) __rte_trace_point_emit(in, int32_t) 396 #define rte_trace_point_emit_long(in) __rte_trace_point_emit(in, long) 397 #define rte_trace_point_emit_size_t(in) __rte_trace_point_emit(in, size_t) 398 #define rte_trace_point_emit_float(in) __rte_trace_point_emit(in, float) 399 #define rte_trace_point_emit_double(in) __rte_trace_point_emit(in, double) 400 #define rte_trace_point_emit_ptr(in) __rte_trace_point_emit(in, uintptr_t) 401 402 #endif /* __DOXYGEN__ */ 403 404 #ifdef __cplusplus 405 } 406 #endif 407 408 #endif /* _RTE_TRACE_POINT_H_ */ 409