* [PATCH 0/6] lib/pmu: cleanups and trace integration
@ 2025-06-16 6:53 Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 1/6] lib/pmu: quiesce rte_pmu_read deprecation warning in chkincs Tomasz Duszynski
` (5 more replies)
0 siblings, 6 replies; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 6:53 UTC (permalink / raw)
To: dev; +Cc: jerinj, thomas, Tomasz Duszynski
This series does some cleanup and refactoring around the rc1 code like: trimming unused headers,
switching to callbacks for per-arch handling, and adding trace support. It also re-enables existing
base test to help catch reported issues on some architectures.
Tomasz Duszynski (6):
lib/pmu: quiesce rte_pmu_read deprecation warning in chkincs
lib/pmu: export only necessary arch headers
lib/pmu: reimplement per-arch ops as callbacks
lib/pmu: use build system defined RTE_LIB_PMU macro
test/pmu: enable fast test
trace: add PMU
MAINTAINERS | 1 +
app/test/test_pmu.c | 4 +-
app/test/test_trace_perf.c | 10 +++
doc/guides/prog_guide/profile_app.rst | 5 ++
doc/guides/prog_guide/trace_lib.rst | 31 ++++++++
doc/guides/rel_notes/release_25_07.rst | 2 +
lib/eal/common/eal_common_trace.c | 5 +-
lib/eal/common/eal_common_trace_pmu.c | 38 ++++++++++
lib/eal/common/eal_common_trace_points.c | 6 ++
lib/eal/common/eal_trace.h | 4 +
lib/eal/common/meson.build | 1 +
lib/eal/include/rte_eal_trace.h | 16 ++++
lib/eal/include/rte_trace_point.h | 7 ++
lib/eal/include/rte_trace_point_register.h | 2 +
lib/eal/meson.build | 3 +
lib/meson.build | 3 +-
lib/pmu/meson.build | 10 +--
lib/pmu/pmu.c | 86 +++++++++++++++++-----
lib/pmu/pmu_arm64.c | 19 +++--
lib/pmu/pmu_private.h | 43 +++++++++--
lib/pmu/rte_pmu.h | 31 +++++++-
21 files changed, 284 insertions(+), 43 deletions(-)
create mode 100644 lib/eal/common/eal_common_trace_pmu.c
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/6] lib/pmu: quiesce rte_pmu_read deprecation warning in chkincs
2025-06-16 6:53 [PATCH 0/6] lib/pmu: cleanups and trace integration Tomasz Duszynski
@ 2025-06-16 6:53 ` Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 2/6] lib/pmu: export only necessary arch headers Tomasz Duszynski
` (4 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 6:53 UTC (permalink / raw)
To: dev, Tomasz Duszynski; +Cc: jerinj, thomas
Add a dummy rte_pmu_read() definition for chkincs when
ALLOW_EXPERIMENTAL_API is not defined to suppress warnings from
use of experimental APIs in tracepoints.
Fixes: 960c43184c4d ("pmu: introduce library for reading PMU events")
Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
lib/pmu/rte_pmu.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/pmu/rte_pmu.h b/lib/pmu/rte_pmu.h
index 57b634ecd8..84a5d522d1 100644
--- a/lib/pmu/rte_pmu.h
+++ b/lib/pmu/rte_pmu.h
@@ -232,6 +232,10 @@ rte_pmu_read(unsigned int index)
return __rte_pmu_read_userpage(group->mmap_pages[index]);
}
+/* quiesce warnings produced by chkincs */
+#ifndef ALLOW_EXPERIMENTAL_API
+#define rte_pmu_read(pc) ({ RTE_SET_USED(pc); 0; })
+#endif
#ifdef __cplusplus
}
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/6] lib/pmu: export only necessary arch headers
2025-06-16 6:53 [PATCH 0/6] lib/pmu: cleanups and trace integration Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 1/6] lib/pmu: quiesce rte_pmu_read deprecation warning in chkincs Tomasz Duszynski
@ 2025-06-16 6:53 ` Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 3/6] lib/pmu: reimplement per-arch ops as callbacks Tomasz Duszynski
` (3 subsequent siblings)
5 siblings, 0 replies; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 6:53 UTC (permalink / raw)
To: dev, Tomasz Duszynski; +Cc: jerinj, thomas
Install only architecture specific headers to avoid header pollution.
Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
lib/pmu/meson.build | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/pmu/meson.build b/lib/pmu/meson.build
index bcb6d10f1a..53013d0ed6 100644
--- a/lib/pmu/meson.build
+++ b/lib/pmu/meson.build
@@ -10,13 +10,13 @@ endif
headers = files('rte_pmu.h')
sources = files('pmu.c')
-indirect_headers += files(
- 'rte_pmu_pmc_arm64.h',
- 'rte_pmu_pmc_x86_64.h',
-)
-
if dpdk_conf.has('RTE_ARCH_ARM64')
+ indirect_headers += files('rte_pmu_pmc_arm64.h')
sources += files('pmu_arm64.c')
endif
+if dpdk_conf.has('RTE_ARCH_X86_64')
+ indirect_headers += files('rte_pmu_pmc_x86_64.h')
+endif
+
deps += ['log']
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 3/6] lib/pmu: reimplement per-arch ops as callbacks
2025-06-16 6:53 [PATCH 0/6] lib/pmu: cleanups and trace integration Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 1/6] lib/pmu: quiesce rte_pmu_read deprecation warning in chkincs Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 2/6] lib/pmu: export only necessary arch headers Tomasz Duszynski
@ 2025-06-16 6:53 ` Tomasz Duszynski
2025-06-16 7:03 ` Thomas Monjalon
2025-06-16 6:53 ` [PATCH 4/6] lib/pmu: use build system defined RTE_LIB_PMU macro Tomasz Duszynski
` (2 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 6:53 UTC (permalink / raw)
To: dev, Tomasz Duszynski, Wathsala Vithanage; +Cc: jerinj, thomas
Replace static per-architecture ops with a callback-based ops
structure. This makes architecture-specific PMU implementations more
modular and easier to extend.
Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
lib/pmu/pmu.c | 17 +----------------
lib/pmu/pmu_arm64.c | 19 +++++++++++++------
lib/pmu/pmu_private.h | 43 +++++++++++++++++++++++++++++++++++++------
3 files changed, 51 insertions(+), 28 deletions(-)
diff --git a/lib/pmu/pmu.c b/lib/pmu/pmu.c
index 46b0b450ac..0709f5e58c 100644
--- a/lib/pmu/pmu.c
+++ b/lib/pmu/pmu.c
@@ -40,22 +40,7 @@ struct rte_pmu_event {
RTE_EXPORT_INTERNAL_SYMBOL(rte_pmu)
struct rte_pmu rte_pmu;
-/* Stubs for arch-specific functions */
-#if !defined(RTE_PMU_SUPPORTED) || defined(RTE_ARCH_X86_64)
-int
-pmu_arch_init(void)
-{
- return 0;
-}
-void
-pmu_arch_fini(void)
-{
-}
-void
-pmu_arch_fixup_config(uint64_t __rte_unused config[3])
-{
-}
-#endif
+const struct pmu_arch_ops *arch_ops;
static int
get_term_format(const char *name, int *num, uint64_t *mask)
diff --git a/lib/pmu/pmu_arm64.c b/lib/pmu/pmu_arm64.c
index a23f1864df..3f4f5fa297 100644
--- a/lib/pmu/pmu_arm64.c
+++ b/lib/pmu/pmu_arm64.c
@@ -62,8 +62,8 @@ write_attr_int(const char *path, int val)
return 0;
}
-int
-pmu_arch_init(void)
+static int
+pmu_arm64_init(void)
{
int ret;
@@ -78,17 +78,24 @@ pmu_arch_init(void)
return write_attr_int(PERF_USER_ACCESS_PATH, 1);
}
-void
-pmu_arch_fini(void)
+static void
+pmu_arm64_fini(void)
{
write_attr_int(PERF_USER_ACCESS_PATH, restore_uaccess);
}
-void
-pmu_arch_fixup_config(uint64_t config[3])
+static void
+pmu_arm64_fixup_config(uint64_t config[3])
{
/* select 64 bit counters */
config[1] |= RTE_BIT64(0);
/* enable userspace access */
config[1] |= RTE_BIT64(1);
}
+
+static const struct pmu_arch_ops arm64_ops = {
+ .init = pmu_arm64_init,
+ .fini = pmu_arm64_fini,
+ .fixup_config = pmu_arm64_fixup_config,
+};
+PMU_SET_ARCH_OPS(arm64_ops)
diff --git a/lib/pmu/pmu_private.h b/lib/pmu/pmu_private.h
index 3db1cb242b..929d0478d5 100644
--- a/lib/pmu/pmu_private.h
+++ b/lib/pmu/pmu_private.h
@@ -5,20 +5,47 @@
#ifndef PMU_PRIVATE_H
#define PMU_PRIVATE_H
+/**
+ * Structure describing architecture specific PMU operations.
+ */
+struct pmu_arch_ops {
+ int (*init)(void);
+ void (*fini)(void);
+ void (*fixup_config)(uint64_t config[3]);
+};
+
+extern const struct pmu_arch_ops *arch_ops;
+
+#define PMU_SET_ARCH_OPS(ops) \
+ RTE_INIT(libpmu_set_arch_ops) \
+ { \
+ arch_ops = &(ops); \
+ }
+
/**
* Architecture-specific PMU init callback.
*
* @return
* 0 in case of success, negative value otherwise.
*/
-int
-pmu_arch_init(void);
+static inline int
+pmu_arch_init(void)
+{
+ if (arch_ops && arch_ops->init)
+ return arch_ops->init();
+
+ return 0;
+}
/**
* Architecture-specific PMU cleanup callback.
*/
-void
-pmu_arch_fini(void);
+static inline void
+pmu_arch_fini(void)
+{
+ if (arch_ops && arch_ops->fini)
+ arch_ops->fini();
+}
/**
* Apply architecture-specific settings to config before passing it to syscall.
@@ -27,7 +54,11 @@ pmu_arch_fini(void);
* Architecture-specific event configuration.
* Consult kernel sources for available options.
*/
-void
-pmu_arch_fixup_config(uint64_t config[3]);
+static inline void
+pmu_arch_fixup_config(uint64_t config[3])
+{
+ if (arch_ops && arch_ops->fixup_config)
+ arch_ops->fixup_config(config);
+}
#endif /* PMU_PRIVATE_H */
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 4/6] lib/pmu: use build system defined RTE_LIB_PMU macro
2025-06-16 6:53 [PATCH 0/6] lib/pmu: cleanups and trace integration Tomasz Duszynski
` (2 preceding siblings ...)
2025-06-16 6:53 ` [PATCH 3/6] lib/pmu: reimplement per-arch ops as callbacks Tomasz Duszynski
@ 2025-06-16 6:53 ` Tomasz Duszynski
2025-06-16 7:08 ` Thomas Monjalon
2025-06-16 6:53 ` [PATCH 5/6] test/pmu: enable fast test Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 6/6] trace: add PMU Tomasz Duszynski
5 siblings, 1 reply; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 6:53 UTC (permalink / raw)
To: dev, Tomasz Duszynski; +Cc: jerinj, thomas
RTE_LIB_PMU is defined by build system automatically if DPDK is build
for Linux. Otherwise it's missing.
That said all cases where conditional compilation is required
can be handled without introducing other macros.
Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
lib/pmu/rte_pmu.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/lib/pmu/rte_pmu.h b/lib/pmu/rte_pmu.h
index 84a5d522d1..e997f62334 100644
--- a/lib/pmu/rte_pmu.h
+++ b/lib/pmu/rte_pmu.h
@@ -33,13 +33,10 @@
#include <rte_compat.h>
#include <rte_lcore.h>
-#define RTE_PMU_SUPPORTED
#if defined(RTE_ARCH_ARM64)
#include "rte_pmu_pmc_arm64.h"
#elif defined(RTE_ARCH_X86_64)
#include "rte_pmu_pmc_x86_64.h"
-#else
-#undef RTE_PMU_SUPPORTED
#endif
#ifdef __cplusplus
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 5/6] test/pmu: enable fast test
2025-06-16 6:53 [PATCH 0/6] lib/pmu: cleanups and trace integration Tomasz Duszynski
` (3 preceding siblings ...)
2025-06-16 6:53 ` [PATCH 4/6] lib/pmu: use build system defined RTE_LIB_PMU macro Tomasz Duszynski
@ 2025-06-16 6:53 ` Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 6/6] trace: add PMU Tomasz Duszynski
5 siblings, 0 replies; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 6:53 UTC (permalink / raw)
To: dev, Tomasz Duszynski; +Cc: jerinj, thomas
DPDK test suite provides much broader architecture coverage than
what can be tested locally so enable the test to help identify
potential issues.
Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
app/test/test_pmu.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/app/test/test_pmu.c b/app/test/test_pmu.c
index 10513bf9c9..4d7ee98393 100644
--- a/app/test/test_pmu.c
+++ b/app/test/test_pmu.c
@@ -52,6 +52,4 @@ test_pmu(void)
return unit_test_suite_runner(&pmu_tests);
}
-/* disabled because of reported failures, waiting for a fix
- * REGISTER_FAST_TEST(pmu_autotest, true, true, test_pmu);
- */
+REGISTER_FAST_TEST(pmu_autotest, true, true, test_pmu);
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 6/6] trace: add PMU
2025-06-16 6:53 [PATCH 0/6] lib/pmu: cleanups and trace integration Tomasz Duszynski
` (4 preceding siblings ...)
2025-06-16 6:53 ` [PATCH 5/6] test/pmu: enable fast test Tomasz Duszynski
@ 2025-06-16 6:53 ` Tomasz Duszynski
2025-06-16 7:13 ` Thomas Monjalon
5 siblings, 1 reply; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 6:53 UTC (permalink / raw)
To: dev, Thomas Monjalon, Jerin Jacob, Sunil Kumar Kori,
Tyler Retzlaff, Tomasz Duszynski
In order to profile app, one needs to store significant amount of samples
somewhere for an analysis later on.
Since trace library supports storing data in a CTF format,
lets take advantage of that and add a dedicated PMU tracepoint.
Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
MAINTAINERS | 1 +
app/test/test_trace_perf.c | 10 ++++
doc/guides/prog_guide/profile_app.rst | 5 ++
doc/guides/prog_guide/trace_lib.rst | 31 ++++++++++
doc/guides/rel_notes/release_25_07.rst | 2 +
lib/eal/common/eal_common_trace.c | 5 +-
lib/eal/common/eal_common_trace_pmu.c | 38 ++++++++++++
lib/eal/common/eal_common_trace_points.c | 6 ++
lib/eal/common/eal_trace.h | 4 ++
lib/eal/common/meson.build | 1 +
lib/eal/include/rte_eal_trace.h | 16 +++++
lib/eal/include/rte_trace_point.h | 7 +++
lib/eal/include/rte_trace_point_register.h | 2 +
lib/eal/meson.build | 3 +
lib/meson.build | 3 +-
lib/pmu/pmu.c | 69 +++++++++++++++++++++-
lib/pmu/rte_pmu.h | 24 ++++++++
17 files changed, 223 insertions(+), 4 deletions(-)
create mode 100644 lib/eal/common/eal_common_trace_pmu.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 7ed7abb038..43c577e0f1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1851,6 +1851,7 @@ F: doc/guides/prog_guide/eventdev/dispatcher_lib.rst
PMU - EXPERIMENTAL
M: Tomasz Duszynski <tduszynski@marvell.com>
F: lib/pmu/
+F: lib/eal/common/eal_common_trace_pmu.c
F: app/test/test_pmu.c
Job statistics
diff --git a/app/test/test_trace_perf.c b/app/test/test_trace_perf.c
index 8257cc02be..28f908ce40 100644
--- a/app/test/test_trace_perf.c
+++ b/app/test/test_trace_perf.c
@@ -114,6 +114,10 @@ worker_fn_##func(void *arg) \
#define GENERIC_DOUBLE rte_eal_trace_generic_double(3.66666)
#define GENERIC_STR rte_eal_trace_generic_str("hello world")
#define VOID_FP app_dpdk_test_fp()
+#ifdef RTE_LIB_PMU
+/* 0 corresponds first event passed via --trace= */
+#define READ_PMU rte_pmu_trace_read(0)
+#endif
WORKER_DEFINE(GENERIC_VOID)
WORKER_DEFINE(GENERIC_U64)
@@ -122,6 +126,9 @@ WORKER_DEFINE(GENERIC_FLOAT)
WORKER_DEFINE(GENERIC_DOUBLE)
WORKER_DEFINE(GENERIC_STR)
WORKER_DEFINE(VOID_FP)
+#ifdef RTE_LIB_PMU
+WORKER_DEFINE(READ_PMU)
+#endif
static void
run_test(const char *str, lcore_function_t f, struct test_data *data, size_t sz)
@@ -174,6 +181,9 @@ test_trace_perf(void)
run_test("double", worker_fn_GENERIC_DOUBLE, data, sz);
run_test("string", worker_fn_GENERIC_STR, data, sz);
run_test("void_fp", worker_fn_VOID_FP, data, sz);
+#ifdef RTE_LIB_PMU
+ run_test("read_pmu", worker_fn_READ_PMU, data, sz);
+#endif
rte_free(data);
return TEST_SUCCESS;
diff --git a/doc/guides/prog_guide/profile_app.rst b/doc/guides/prog_guide/profile_app.rst
index 2f47680d5d..362fd20143 100644
--- a/doc/guides/prog_guide/profile_app.rst
+++ b/doc/guides/prog_guide/profile_app.rst
@@ -42,6 +42,11 @@ Current implementation imposes certain limitations:
* EAL lcores must not share a CPU.
* Each EAL lcore measures the same group of events.
+Alternatively tracing library can be used,
+which offers dedicated tracepoint ``rte_pmu_trace_read()``.
+
+Refer to :doc:`../prog_guide/trace_lib` for more details.
+
Profiling on x86
----------------
diff --git a/doc/guides/prog_guide/trace_lib.rst b/doc/guides/prog_guide/trace_lib.rst
index d9b17abe90..97158cce37 100644
--- a/doc/guides/prog_guide/trace_lib.rst
+++ b/doc/guides/prog_guide/trace_lib.rst
@@ -46,6 +46,7 @@ DPDK tracing library features
trace format and is compatible with ``LTTng``.
For detailed information, refer to
`Common Trace Format <https://diamon.org/ctf/>`_.
+- Support reading PMU events on ARM64 and x86-64 (Intel)
How to add a tracepoint?
------------------------
@@ -139,6 +140,36 @@ the user must use ``RTE_TRACE_POINT_FP`` instead of ``RTE_TRACE_POINT``.
``RTE_TRACE_POINT_FP`` is compiled out by default and it can be enabled using
the ``enable_trace_fp`` option for meson build.
+PMU tracepoint
+--------------
+
+Performance Monitoring Unit (PMU) event values can be read from hardware registers
+using the predefined ``rte_pmu_read`` tracepoint.
+
+Tracing is enabled via ``--trace`` EAL option by passing both expression
+matching PMU tracepoint name i.e ``lib.eal.pmu.read``
+and expression ``e=ev1[,ev2,...]`` matching particular events::
+
+ --trace='.*pmu.read\|e=cpu_cycles,l1d_cache'
+
+Event names are available under ``/sys/bus/event_source/devices/PMU/events`` directory,
+where ``PMU`` is a placeholder for either a ``cpu`` or a directory containing ``cpus``.
+
+In contrary to other tracepoints this does not need any extra variables
+added to source files.
+Instead, caller passes index
+which follows the order of events specified via ``--trace`` parameter.
+In the following example, index ``0`` corresponds to ``cpu_cyclces``,
+while index ``1`` corresponds to ``l1d_cache``.
+
+.. code-block:: c
+
+ rte_pmu_trace_read(0);
+ rte_pmu_trace_read(1);
+
+PMU tracing support must be explicitly enabled
+using the ``enable_trace_fp`` option for Meson build.
+
Event record mode
-----------------
diff --git a/doc/guides/rel_notes/release_25_07.rst b/doc/guides/rel_notes/release_25_07.rst
index f23ddb25a4..05ecb23f1f 100644
--- a/doc/guides/rel_notes/release_25_07.rst
+++ b/doc/guides/rel_notes/release_25_07.rst
@@ -59,6 +59,8 @@ New Features
Added a Performance Monitoring Unit (PMU) library which allows Linux applications
to perform self monitoring activities without depending on external utilities like perf.
+ After integration with :doc:`../prog_guide/trace_lib`, data gathered from hardware counters
+ can be stored in CTF format for further analysis.
* **Added Mucse rnp net driver.**
diff --git a/lib/eal/common/eal_common_trace.c b/lib/eal/common/eal_common_trace.c
index be1f78a68d..45e7f9aa56 100644
--- a/lib/eal/common/eal_common_trace.c
+++ b/lib/eal/common/eal_common_trace.c
@@ -75,8 +75,10 @@ eal_trace_init(void)
goto free_meta;
/* Apply global configurations */
- STAILQ_FOREACH(arg, &trace.args, next)
+ STAILQ_FOREACH(arg, &trace.args, next) {
trace_args_apply(arg->val);
+ trace_pmu_args_apply(arg->val);
+ }
rte_trace_mode_set(trace.mode);
@@ -92,6 +94,7 @@ eal_trace_init(void)
void
eal_trace_fini(void)
{
+ trace_pmu_args_free();
trace_mem_free();
trace_metadata_destroy();
eal_trace_args_free();
diff --git a/lib/eal/common/eal_common_trace_pmu.c b/lib/eal/common/eal_common_trace_pmu.c
new file mode 100644
index 0000000000..3824904481
--- /dev/null
+++ b/lib/eal/common/eal_common_trace_pmu.c
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2025 Marvell International Ltd.
+ */
+
+#include <rte_common.h>
+
+#include "eal_trace.h"
+
+#ifdef RTE_LIB_PMU
+
+#include <rte_pmu.h>
+
+void
+trace_pmu_args_apply(const char *arg)
+{
+ static bool once;
+
+ if (!once) {
+ if (rte_pmu_init())
+ return;
+ once = true;
+ }
+
+ rte_pmu_add_events_by_pattern(arg);
+}
+
+void
+trace_pmu_args_free(void)
+{
+ rte_pmu_fini();
+}
+
+#else /* !RTE_LIB_PMU */
+
+void trace_pmu_args_apply(const char *arg __rte_unused) { return; }
+void trace_pmu_args_free(void) { return; }
+
+#endif /* RTE_LIB_PMU */
diff --git a/lib/eal/common/eal_common_trace_points.c b/lib/eal/common/eal_common_trace_points.c
index 0903f3c639..2b6813404e 100644
--- a/lib/eal/common/eal_common_trace_points.c
+++ b/lib/eal/common/eal_common_trace_points.c
@@ -119,3 +119,9 @@ RTE_TRACE_POINT_REGISTER(rte_eal_trace_intr_enable,
lib.eal.intr.enable)
RTE_TRACE_POINT_REGISTER(rte_eal_trace_intr_disable,
lib.eal.intr.disable)
+
+#ifdef RTE_LIB_PMU
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(__rte_pmu_trace_read, 25.07)
+RTE_TRACE_POINT_REGISTER(rte_pmu_trace_read,
+ lib.pmu.read)
+#endif
diff --git a/lib/eal/common/eal_trace.h b/lib/eal/common/eal_trace.h
index 55262677e0..58fa43472a 100644
--- a/lib/eal/common/eal_trace.h
+++ b/lib/eal/common/eal_trace.h
@@ -104,6 +104,10 @@ int trace_epoch_time_save(void);
void trace_mem_free(void);
void trace_mem_per_thread_free(void);
+/* PMU wrappers */
+void trace_pmu_args_apply(const char *arg);
+void trace_pmu_args_free(void);
+
/* EAL interface */
int eal_trace_init(void);
void eal_trace_fini(void);
diff --git a/lib/eal/common/meson.build b/lib/eal/common/meson.build
index e273745e93..239c111461 100644
--- a/lib/eal/common/meson.build
+++ b/lib/eal/common/meson.build
@@ -28,6 +28,7 @@ sources += files(
'eal_common_tailqs.c',
'eal_common_thread.c',
'eal_common_timer.c',
+ 'eal_common_trace_pmu.c',
'eal_common_trace_points.c',
'eal_common_uuid.c',
'malloc_elem.c',
diff --git a/lib/eal/include/rte_eal_trace.h b/lib/eal/include/rte_eal_trace.h
index 9ad2112801..b7f300c4f0 100644
--- a/lib/eal/include/rte_eal_trace.h
+++ b/lib/eal/include/rte_eal_trace.h
@@ -127,6 +127,22 @@ RTE_TRACE_POINT(
#define RTE_EAL_TRACE_GENERIC_FUNC rte_eal_trace_generic_func(__func__)
+#ifdef RTE_LIB_PMU
+#include <rte_pmu.h>
+RTE_TRACE_POINT_FP(
+ rte_pmu_trace_read,
+ RTE_TRACE_POINT_ARGS(unsigned int index),
+ /* Embedded code should only execute in runtime so cut it out during registration in order
+ * to avoid compilation issues because rte_pmu_tread_read_register(void) does not provide
+ * any context.
+ */
+ RTE_TRACE_POINT_EMBED_CODE(
+ uint64_t val = rte_pmu_read(index);
+ )
+ rte_trace_point_emit_u64(val);
+)
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/eal/include/rte_trace_point.h b/lib/eal/include/rte_trace_point.h
index c0ebf1ce13..df91447d4a 100644
--- a/lib/eal/include/rte_trace_point.h
+++ b/lib/eal/include/rte_trace_point.h
@@ -46,6 +46,13 @@ typedef RTE_ATOMIC(uint64_t) rte_trace_point_t;
*/
#define RTE_TRACE_POINT_ARGS
+/**
+ * Macro to define the tracepoint code in RTE_TRACE_POINT, RTE_TRACE_POINT_FP macros.
+
+ * @see RTE_TRACE_POINT, RTE_TRACE_POINT_FP
+ */
+#define RTE_TRACE_POINT_EMBED_CODE(...) __VA_ARGS__
+
/** @internal Helper macro to support RTE_TRACE_POINT and RTE_TRACE_POINT_FP */
#define __RTE_TRACE_POINT(_mode, _tp, _args, ...) \
extern rte_trace_point_t __##_tp; \
diff --git a/lib/eal/include/rte_trace_point_register.h b/lib/eal/include/rte_trace_point_register.h
index b036121959..81c28cdb5b 100644
--- a/lib/eal/include/rte_trace_point_register.h
+++ b/lib/eal/include/rte_trace_point_register.h
@@ -45,6 +45,8 @@ RTE_DECLARE_PER_LCORE(volatile int, trace_point_sz);
#define RTE_TRACE_POINT_ARGS(...) \
(RTE_TRACE_POINT_ARGS_(RTE_TRACE_POINT_ARGS_COUNT(0, __VA_ARGS__), __VA_ARGS__))
+#define RTE_TRACE_POINT_EMBED_CODE(...)
+
#define __RTE_TRACE_POINT(_mode, _tp, _args, ...) \
extern rte_trace_point_t __##_tp; \
static __rte_always_inline void _tp _args { } \
diff --git a/lib/eal/meson.build b/lib/eal/meson.build
index e1d6c4cf17..c46893aeaa 100644
--- a/lib/eal/meson.build
+++ b/lib/eal/meson.build
@@ -15,6 +15,9 @@ subdir(exec_env)
subdir(arch_subdir)
deps += ['log', 'kvargs']
+if is_linux
+ deps += ['pmu']
+endif
if not is_windows
deps += ['telemetry']
endif
diff --git a/lib/meson.build b/lib/meson.build
index 1934cb4a29..390484d30f 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -13,7 +13,7 @@ libraries = [
'kvargs', # eal depends on kvargs
'argparse',
'telemetry', # basic info querying
- 'pmu',
+ 'pmu', # trace depends on pmu
'eal', # everything depends on eal
'ptr_compress',
'ring',
@@ -86,6 +86,7 @@ always_enable = [
'ring',
'stack',
'telemetry',
+ 'pmu',
]
enable_deprecated_libs = []
diff --git a/lib/pmu/pmu.c b/lib/pmu/pmu.c
index 0709f5e58c..d4ce234491 100644
--- a/lib/pmu/pmu.c
+++ b/lib/pmu/pmu.c
@@ -4,6 +4,7 @@
#include <errno.h>
#include <ctype.h>
+#include <regex.h>
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
@@ -393,13 +394,77 @@ rte_pmu_add_event(const char *name)
return event->index;
}
+static int
+add_events(const char *pattern)
+{
+ char *token, *copy, *tmp;
+ int ret = 0;
+
+ copy = strdup(pattern);
+ if (copy == NULL)
+ return -ENOMEM;
+
+ token = strtok_r(copy, ",", &tmp);
+ while (token) {
+ ret = rte_pmu_add_event(token);
+ if (ret < 0)
+ break;
+
+ token = strtok_r(NULL, ",", &tmp);
+ }
+
+ free(copy);
+
+ return ret >= 0 ? 0 : ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmu_add_events_by_pattern, 25.07)
+int
+rte_pmu_add_events_by_pattern(const char *pattern)
+{
+ regmatch_t rmatch;
+ char buf[BUFSIZ];
+ unsigned int num;
+ regex_t reg;
+ int ret;
+
+ /* events are matched against occurrences of e=ev1[,ev2,..] pattern */
+ ret = regcomp(®, "e=([_[:alnum:]-],?)+", REG_EXTENDED);
+ if (ret) {
+ PMU_LOG(ERR, "Failed to compile event matching regexp");
+ return -EINVAL;
+ }
+
+ for (;;) {
+ if (regexec(®, pattern, 1, &rmatch, 0))
+ break;
+
+ num = rmatch.rm_eo - rmatch.rm_so;
+ if (num > sizeof(buf))
+ num = sizeof(buf);
+
+ /* skip e= pattern prefix */
+ memcpy(buf, pattern + rmatch.rm_so + 2, num - 2);
+ buf[num - 2] = '\0';
+ ret = add_events(buf);
+ if (ret)
+ break;
+
+ pattern += rmatch.rm_eo;
+ }
+
+ regfree(®);
+
+ return ret;
+}
+
RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmu_init, 25.07)
int
rte_pmu_init(void)
{
int ret;
- if (rte_pmu.initialized)
+ if (rte_pmu.initialized && ++rte_pmu.initialized)
return 0;
ret = scan_pmus();
@@ -433,7 +498,7 @@ rte_pmu_fini(void)
struct rte_pmu_event_group *group;
unsigned int i;
- if (!rte_pmu.initialized)
+ if (!rte_pmu.initialized || --rte_pmu.initialized)
return;
RTE_TAILQ_FOREACH_SAFE(event, &rte_pmu.event_list, next, tmp_event) {
diff --git a/lib/pmu/rte_pmu.h b/lib/pmu/rte_pmu.h
index e997f62334..e6df54b304 100644
--- a/lib/pmu/rte_pmu.h
+++ b/lib/pmu/rte_pmu.h
@@ -21,6 +21,10 @@
*
* rte_pmu_init()
* rte_pmu_add_event()
+ * rte_pmu_add_event() [or rte_pmu_add_events_by_pattern()]
+ *
+ * Note that if -Denable_trace_fp=True was passed to Meson,
+ * rte_pmu_init() gets called automatically.
*
* Afterwards all threads can read events by calling rte_pmu_read().
*/
@@ -145,6 +149,8 @@ __rte_pmu_enable_group(struct rte_pmu_event_group *group);
*
* Initialize PMU library.
*
+ * It's safe to call it multiple times.
+ *
* @return
* 0 in case of success, negative value otherwise.
*/
@@ -157,6 +163,9 @@ rte_pmu_init(void);
* @b EXPERIMENTAL: this API may change without prior notice.
*
* Finalize PMU library.
+ *
+ * Number of calls must match number of times rte_pmu_init() was called.
+ * Otherwise memory won't be freed properly.
*/
__rte_experimental
void
@@ -184,6 +193,21 @@ rte_pmu_add_event(const char *name);
#define __rte_pmu_read_userpage(pc) ({ RTE_SET_USED(pc); 0; })
#endif
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Add events matching pattern to the group of enabled events.
+ *
+ * @param pattern
+ * Pattern e=ev1[,ev2,...] matching events
+ * listed under /sys/bus/event_source/devices/pmu/events,
+ * where evX and PMU are placeholders for respectively an event and an event source.
+ */
+__rte_experimental
+int
+rte_pmu_add_events_by_pattern(const char *pattern);
+
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice.
--
2.34.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/6] lib/pmu: reimplement per-arch ops as callbacks
2025-06-16 6:53 ` [PATCH 3/6] lib/pmu: reimplement per-arch ops as callbacks Tomasz Duszynski
@ 2025-06-16 7:03 ` Thomas Monjalon
2025-06-16 9:54 ` Tomasz Duszynski
0 siblings, 1 reply; 15+ messages in thread
From: Thomas Monjalon @ 2025-06-16 7:03 UTC (permalink / raw)
To: Tomasz Duszynski; +Cc: dev, Wathsala Vithanage, jerinj
16/06/2025 08:53, Tomasz Duszynski:
> +static inline int
> +pmu_arch_init(void)
> +{
> + if (arch_ops && arch_ops->init)
> + return arch_ops->init();
These are not boolean values, please compare explicitly with NULL.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 4/6] lib/pmu: use build system defined RTE_LIB_PMU macro
2025-06-16 6:53 ` [PATCH 4/6] lib/pmu: use build system defined RTE_LIB_PMU macro Tomasz Duszynski
@ 2025-06-16 7:08 ` Thomas Monjalon
2025-06-16 10:53 ` Tomasz Duszynski
0 siblings, 1 reply; 15+ messages in thread
From: Thomas Monjalon @ 2025-06-16 7:08 UTC (permalink / raw)
To: Tomasz Duszynski; +Cc: dev, jerinj
16/06/2025 08:53, Tomasz Duszynski:
> RTE_LIB_PMU is defined by build system automatically if DPDK is build
> for Linux. Otherwise it's missing.
>
> That said all cases where conditional compilation is required
> can be handled without introducing other macros.
You don't need to know if it is compiled for an unsupported arch?
What will happen when calling the unit test on RISC-V?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 6/6] trace: add PMU
2025-06-16 6:53 ` [PATCH 6/6] trace: add PMU Tomasz Duszynski
@ 2025-06-16 7:13 ` Thomas Monjalon
2025-06-16 9:49 ` Tomasz Duszynski
0 siblings, 1 reply; 15+ messages in thread
From: Thomas Monjalon @ 2025-06-16 7:13 UTC (permalink / raw)
To: Tomasz Duszynski
Cc: dev, Jerin Jacob, Sunil Kumar Kori, Tyler Retzlaff,
Bruce Richardson, David Marchand
16/06/2025 08:53, Tomasz Duszynski:
> @@ -86,6 +86,7 @@ always_enable = [
> 'ring',
> 'stack',
> 'telemetry',
> + 'pmu',
> ]
This list is alphabetically sorted.
What is the justification for always enabling PMU lib?
Is it a good idea to always enable an experimental library?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 6/6] trace: add PMU
2025-06-16 7:13 ` Thomas Monjalon
@ 2025-06-16 9:49 ` Tomasz Duszynski
2025-06-16 10:32 ` Bruce Richardson
2025-06-16 13:18 ` Morten Brørup
0 siblings, 2 replies; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 9:49 UTC (permalink / raw)
To: thomas
Cc: bruce.richardson, david.marchand, dev, jerinj, roretzla, skori,
tduszynski
>16/06/2025 08:53, Tomasz Duszynski:
>> @@ -86,6 +86,7 @@ always_enable = [
>> 'ring',
>> 'stack',
>> 'telemetry',
>> + 'pmu',
>> ]
>
>This list is alphabetically sorted.
Right, missed that.
>
>What is the justification for always enabling PMU lib?
>Is it a good idea to always enable an experimental library?
Well, since on Linux eal depends on pmu, disabling pmu ends up disabling
eal, which breaks minimal build.
As for the second question - no. I think ideally lib should remain
optional. However, since trace is part of eal, that indirectly forces
pmu to be built.
Alternatively, I guess we could make the library explicitly optional by
extra meson option. But given that there are already options for
controlling libraries that approach is not perfect either.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/6] lib/pmu: reimplement per-arch ops as callbacks
2025-06-16 7:03 ` Thomas Monjalon
@ 2025-06-16 9:54 ` Tomasz Duszynski
0 siblings, 0 replies; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 9:54 UTC (permalink / raw)
To: thomas; +Cc: dev, jerinj, tduszynski, wathsala.vithanage
>16/06/2025 08:53, Tomasz Duszynski:
>> +static inline int
>> +pmu_arch_init(void)
>> +{
>> + if (arch_ops && arch_ops->init)
>> + return arch_ops->init();
>
>These are not boolean values, please compare explicitly with NULL.
Okay.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 6/6] trace: add PMU
2025-06-16 9:49 ` Tomasz Duszynski
@ 2025-06-16 10:32 ` Bruce Richardson
2025-06-16 13:18 ` Morten Brørup
1 sibling, 0 replies; 15+ messages in thread
From: Bruce Richardson @ 2025-06-16 10:32 UTC (permalink / raw)
To: Tomasz Duszynski; +Cc: thomas, david.marchand, dev, jerinj, roretzla, skori
On Mon, Jun 16, 2025 at 11:49:03AM +0200, Tomasz Duszynski wrote:
> >16/06/2025 08:53, Tomasz Duszynski:
> >> @@ -86,6 +86,7 @@ always_enable = [
> >> 'ring',
> >> 'stack',
> >> 'telemetry',
> >> + 'pmu',
> >> ]
> >
> >This list is alphabetically sorted.
>
> Right, missed that.
>
> >
> >What is the justification for always enabling PMU lib?
> >Is it a good idea to always enable an experimental library?
>
> Well, since on Linux eal depends on pmu, disabling pmu ends up disabling
> eal, which breaks minimal build.
>
> As for the second question - no. I think ideally lib should remain
> optional. However, since trace is part of eal, that indirectly forces
> pmu to be built.
>
Or else you need to put ifdefs into the EAL code to only call the pmu
functions when the library is enabled. Given that PMU library is only
enabled for Linux, and yet there are changes in this patch to a number of
common EAL files, that is probably a good option to take. It gives you the
ability to make PMU optional, as well as supporting non-linux OS's.
/Bruce
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 4/6] lib/pmu: use build system defined RTE_LIB_PMU macro
2025-06-16 7:08 ` Thomas Monjalon
@ 2025-06-16 10:53 ` Tomasz Duszynski
0 siblings, 0 replies; 15+ messages in thread
From: Tomasz Duszynski @ 2025-06-16 10:53 UTC (permalink / raw)
To: thomas; +Cc: dev, jerinj, tduszynski
>16/06/2025 08:53, Tomasz Duszynski:
>> RTE_LIB_PMU is defined by build system automatically if DPDK is build
>> for Linux. Otherwise it's missing.
>>
>> That said all cases where conditional compilation is required
>> can be handled without introducing other macros.
>
>You don't need to know if it is compiled for an unsupported arch?
>
No, if arch isn't supported reading whatever counter returns 0. On the other hand
if architecture does not require extra setup (eg., x86-64) all works
automatically because Linux has consistent API for each supported arch.
>What will happen when calling the unit test on RISC-V?
Test will be skipped because event is set to 'NULL' by default. Supported
architectures override it with valid name.
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH 6/6] trace: add PMU
2025-06-16 9:49 ` Tomasz Duszynski
2025-06-16 10:32 ` Bruce Richardson
@ 2025-06-16 13:18 ` Morten Brørup
1 sibling, 0 replies; 15+ messages in thread
From: Morten Brørup @ 2025-06-16 13:18 UTC (permalink / raw)
To: Tomasz Duszynski, thomas
Cc: bruce.richardson, david.marchand, dev, jerinj, roretzla, skori
> From: Tomasz Duszynski [mailto:tduszynski@marvell.com]
> Sent: Monday, 16 June 2025 11.49
>
> >16/06/2025 08:53, Tomasz Duszynski:
> >> @@ -86,6 +86,7 @@ always_enable = [
> >> 'ring',
> >> 'stack',
> >> 'telemetry',
> >> + 'pmu',
> >> ]
> >
> >This list is alphabetically sorted.
>
> Right, missed that.
>
> >
> >What is the justification for always enabling PMU lib?
> >Is it a good idea to always enable an experimental library?
>
> Well, since on Linux eal depends on pmu, disabling pmu ends up disabling
> eal, which breaks minimal build.
>
> As for the second question - no. I think ideally lib should remain
> optional. However, since trace is part of eal, that indirectly forces
> pmu to be built.
Trace is optional, controlled by RTE_TRACE in /config/rte_config.h.
>
> Alternatively, I guess we could make the library explicitly optional by
> extra meson option. But given that there are already options for
> controlling libraries that approach is not perfect either.
PMU should depend on EAL, not the other way around.
Please refer to this fix, where pmu.c is updated to call rte_mem_page_size(), which includes error handling, instead of directly calling sysconf(_SC_PAGE_SIZE) without handling errors from it:
https://patchwork.dpdk.org/project/dpdk/patch/20250612140657.313785-1-mb@smartsharesystems.com/
If there are cross dependency issues due to integration between PMU and Trace, adding the PMU related trace directly in the Trace library is a much better solution than making EAL depend on PMU.
Also, I agree with Thomas that PMU should not be considered a mandatory core library (always_enable).
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2025-06-16 13:18 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-16 6:53 [PATCH 0/6] lib/pmu: cleanups and trace integration Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 1/6] lib/pmu: quiesce rte_pmu_read deprecation warning in chkincs Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 2/6] lib/pmu: export only necessary arch headers Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 3/6] lib/pmu: reimplement per-arch ops as callbacks Tomasz Duszynski
2025-06-16 7:03 ` Thomas Monjalon
2025-06-16 9:54 ` Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 4/6] lib/pmu: use build system defined RTE_LIB_PMU macro Tomasz Duszynski
2025-06-16 7:08 ` Thomas Monjalon
2025-06-16 10:53 ` Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 5/6] test/pmu: enable fast test Tomasz Duszynski
2025-06-16 6:53 ` [PATCH 6/6] trace: add PMU Tomasz Duszynski
2025-06-16 7:13 ` Thomas Monjalon
2025-06-16 9:49 ` Tomasz Duszynski
2025-06-16 10:32 ` Bruce Richardson
2025-06-16 13:18 ` Morten Brørup
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).