diff --git a/MAINTAINERS b/MAINTAINERS index 52bbff6233..56217c9daf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -199,6 +199,7 @@ M: Jerin Jacob M: Sunil Kumar Kori F: lib/librte_eal/include/rte_trace*.h F: lib/librte_eal/common/eal_common_trace*.c +F: lib/librte_eal/common/eal_trace.h Memory Allocation M: Anatoly Burakov diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c index 33a6e563a1..966bcf0e33 100644 --- a/lib/librte_eal/common/eal_common_trace.c +++ b/lib/librte_eal/common/eal_common_trace.c @@ -2,6 +2,107 @@ * Copyright(C) 2020 Marvell International Ltd. */ -#include -#include +#include +#include +#include +#include +#include +#include +#include + +#include "eal_trace.h" + +RTE_DEFINE_PER_LCORE(volatile int, trace_point_sz); +static RTE_DEFINE_PER_LCORE(char, ctf_field[TRACE_CTF_FIELD_SIZE]); +static RTE_DEFINE_PER_LCORE(int, ctf_count); + +static struct trace_point_head tp_list = STAILQ_HEAD_INITIALIZER(tp_list); +static struct trace trace; + +int +__rte_trace_point_register(rte_trace_point_t *handle, const char *name, + void (*register_fn)(void)) +{ + char *field = RTE_PER_LCORE(ctf_field); + struct trace_point *tp; + uint16_t sz; + + /* Sanity checks of arguments */ + if (name == NULL || register_fn == NULL || handle == NULL) { + trace_err("invalid arguments"); + rte_errno = EINVAL; + goto fail; + } + + /* Check the size of the trace point object */ + RTE_PER_LCORE(trace_point_sz) = 0; + RTE_PER_LCORE(ctf_count) = 0; + register_fn(); + if (RTE_PER_LCORE(trace_point_sz) == 0) { + trace_err("missing rte_trace_emit_header() in register fn"); + rte_errno = EBADF; + goto fail; + } + + /* Is size overflowed */ + if (RTE_PER_LCORE(trace_point_sz) > UINT16_MAX) { + trace_err("trace point size overflowed"); + rte_errno = ENOSPC; + goto fail; + } + + /* Are we running out of space to store trace points? */ + if (trace.nb_trace_points > UINT16_MAX) { + trace_err("trace point exceeds the max count"); + rte_errno = ENOSPC; + goto fail; + } + + /* Get the size of the trace point */ + sz = RTE_PER_LCORE(trace_point_sz); + tp = calloc(1, sizeof(struct trace_point)); + if (tp == NULL) { + trace_err("fail to allocate trace point memory"); + rte_errno = ENOMEM; + goto fail; + } + + /* Initialize the trace point */ + if (rte_strscpy(tp->name, name, TRACE_POINT_NAME_SIZE) < 0) { + trace_err("name is too long"); + rte_errno = E2BIG; + goto free; + } + + /* Copy the field data for future use */ + if (rte_strscpy(tp->ctf_field, field, TRACE_CTF_FIELD_SIZE) < 0) { + trace_err("CTF field size is too long"); + rte_errno = E2BIG; + goto free; + } + + /* Clear field memory for the next event */ + memset(field, 0, TRACE_CTF_FIELD_SIZE); + + /* Form the trace handle */ + *handle = sz; + *handle |= trace.nb_trace_points << __RTE_TRACE_FIELD_ID_SHIFT; + + trace.nb_trace_points++; + tp->handle = handle; + + /* Add the trace point at tail */ + STAILQ_INSERT_TAIL(&tp_list, tp, next); + __atomic_thread_fence(__ATOMIC_RELEASE); + + /* All Good !!! */ + return 0; +free: + free(tp); +fail: + if (trace.register_errno == 0) + trace.register_errno = rte_errno; + + return -rte_errno; +} diff --git a/lib/librte_eal/common/eal_trace.h b/lib/librte_eal/common/eal_trace.h new file mode 100644 index 0000000000..a294834e03 --- /dev/null +++ b/lib/librte_eal/common/eal_trace.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2020 Marvell International Ltd. + */ + +#ifndef __EAL_TRACE_H +#define __EAL_TRACE_H + +#include +#include + +#define trace_err(fmt, args...) \ + RTE_LOG(ERR, EAL, "%s():%u " fmt "\n", __func__, __LINE__, ## args) + +#define trace_crit(fmt, args...) \ + RTE_LOG(CRIT, EAL, "%s():%u " fmt "\n", __func__, __LINE__, ## args) + +#define TRACE_CTF_FIELD_SIZE 384 +#define TRACE_POINT_NAME_SIZE 64 + +struct trace_point { + STAILQ_ENTRY(trace_point) next; + rte_trace_point_t *handle; + char name[TRACE_POINT_NAME_SIZE]; + char ctf_field[TRACE_CTF_FIELD_SIZE]; +}; + +struct trace { + int register_errno; + uint32_t nb_trace_points; +}; + +/* Trace point list functions */ +STAILQ_HEAD(trace_point_head, trace_point); + +#endif /* __EAL_TRACE_H */ diff --git a/lib/librte_eal/include/meson.build b/lib/librte_eal/include/meson.build index 126455d1cf..ce360615f1 100644 --- a/lib/librte_eal/include/meson.build +++ b/lib/librte_eal/include/meson.build @@ -42,6 +42,8 @@ headers += files( 'rte_time.h', 'rte_trace.h', 'rte_trace_point.h', + 'rte_trace_point_provider.h', + 'rte_trace_point_register.h', 'rte_uuid.h', 'rte_version.h', 'rte_vfio.h', diff --git a/lib/librte_eal/include/rte_trace_point.h b/lib/librte_eal/include/rte_trace_point.h index 3c2f8805e8..89f384db30 100644 --- a/lib/librte_eal/include/rte_trace_point.h +++ b/lib/librte_eal/include/rte_trace_point.h @@ -227,6 +227,32 @@ __rte_trace_point_fp_is_enabled(void) #endif } +/** + * @internal + * + * Helper function to register a dynamic tracepoint. + * Use RTE_TRACE_POINT_REGISTER macro for tracepoint registration. + * + * @param trace + * The tracepoint object created using RTE_TRACE_POINT_DEFINE. + * @param name + * The name of the tracepoint object. + * @param register_fn + * Trace registration function. + * @return + * - 0: Successfully registered the tracepoint. + * - <0: Failure to register the tracepoint. + */ +__rte_experimental +int __rte_trace_point_register(rte_trace_point_t *trace, const char *name, + void (*register_fn)(void)); + +#ifdef RTE_TRACE_POINT_REGISTER_SELECT +#include +#else +#include +#endif + #ifdef __cplusplus } #endif diff --git a/lib/librte_eal/include/rte_trace_point_provider.h b/lib/librte_eal/include/rte_trace_point_provider.h new file mode 100644 index 0000000000..45a113c0d1 --- /dev/null +++ b/lib/librte_eal/include/rte_trace_point_provider.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2020 Marvell International Ltd. + */ + +#ifndef _RTE_TRACE_POINT_H_ +#error do not include this file directly, use instead +#endif + +#ifndef _RTE_TRACE_POINT_PROVIDER_H_ +#define _RTE_TRACE_POINT_PROVIDER_H_ + +#define __RTE_TRACE_EVENT_HEADER_ID_SHIFT (48) + +#define __RTE_TRACE_FIELD_SIZE_SHIFT 0 +#define __RTE_TRACE_FIELD_SIZE_MASK (0xffffULL << __RTE_TRACE_FIELD_SIZE_SHIFT) +#define __RTE_TRACE_FIELD_ID_SHIFT (16) +#define __RTE_TRACE_FIELD_ID_MASK (0xffffULL << __RTE_TRACE_FIELD_ID_SHIFT) +#define __RTE_TRACE_FIELD_ENABLE_MASK (1ULL << 63) +#define __RTE_TRACE_FIELD_ENABLE_DISCARD (1ULL << 62) + +#endif /* _RTE_TRACE_POINT_PROVIDER_H_ */ diff --git a/lib/librte_eal/include/rte_trace_point_register.h b/lib/librte_eal/include/rte_trace_point_register.h new file mode 100644 index 0000000000..6c5872a3e6 --- /dev/null +++ b/lib/librte_eal/include/rte_trace_point_register.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2020 Marvell International Ltd. + */ + +#ifndef _RTE_TRACE_POINT_H_ +#error do not include this file directly, use instead +#endif + +#ifndef _RTE_TRACE_POINT_REGISTER_H_ +#define _RTE_TRACE_POINT_REGISTER_H_ + +#include + +RTE_DECLARE_PER_LCORE(volatile int, trace_point_sz); + +#define RTE_TRACE_POINT_REGISTER(trace, name) \ + __rte_trace_point_register(&__##trace, RTE_STR(name), \ + (void (*)(void)) trace) + +#endif /* _RTE_TRACE_POINT_REGISTER_H_ */ diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map index 71098581f9..02a5951269 100644 --- a/lib/librte_eal/rte_eal_version.map +++ b/lib/librte_eal/rte_eal_version.map @@ -337,6 +337,8 @@ EXPERIMENTAL { rte_thread_is_intr; # added in 20.05 + __rte_trace_point_register; + per_lcore_trace_point_sz; rte_log_can_log; rte_thread_getname; };