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