[PATCH v2 11/12] perf tools: Initial support for RISC-V trace decoder

Anup Patel posted 12 patches 3 months, 1 week ago
[PATCH v2 11/12] perf tools: Initial support for RISC-V trace decoder
Posted by Anup Patel 3 months, 1 week ago
From: Mayuresh Chitale <mchitale@ventanamicro.com>

Add bare bones support for RISC-V trace decoder so that the data received
from the hardware by the RISC-V trace perf driver can be written to the
perf record output file.

Co-developed-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
---
 tools/perf/util/Build             |  1 +
 tools/perf/util/auxtrace.c        |  3 +
 tools/perf/util/rvtrace-decoder.c | 91 +++++++++++++++++++++++++++++++
 tools/perf/util/rvtrace.h         |  2 +
 4 files changed, 97 insertions(+)
 create mode 100644 tools/perf/util/rvtrace-decoder.c

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 4be313cd115a..f736cea51fd8 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -145,6 +145,7 @@ perf-util-$(CONFIG_AUXTRACE) += cs-etm.o
 perf-util-$(CONFIG_AUXTRACE) += cs-etm-decoder/
 endif
 perf-util-$(CONFIG_AUXTRACE) += cs-etm-base.o
+perf-util-$(CONFIG_AUXTRACE) += rvtrace-decoder.o
 
 perf-util-y += parse-branch-options.o
 perf-util-y += dump-insn.o
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c905563e0d8a..299991d5d305 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -54,6 +54,7 @@
 #include "arm-spe.h"
 #include "hisi-ptt.h"
 #include "s390-cpumsf.h"
+#include "rvtrace.h"
 #include "util/mmap.h"
 #include "powerpc-vpadtl.h"
 
@@ -1395,6 +1396,8 @@ int perf_event__process_auxtrace_info(struct perf_session *session,
 		err = powerpc_vpadtl_process_auxtrace_info(event, session);
 		break;
 	case PERF_AUXTRACE_RISCV_TRACE:
+		err = rvtrace__process_auxtrace_info(event, session);
+		break;
 	case PERF_AUXTRACE_UNKNOWN:
 	default:
 		return -EINVAL;
diff --git a/tools/perf/util/rvtrace-decoder.c b/tools/perf/util/rvtrace-decoder.c
new file mode 100644
index 000000000000..58db5ca62c1a
--- /dev/null
+++ b/tools/perf/util/rvtrace-decoder.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RISC-V trace Decoder
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include "evlist.h"
+#include <internal/lib.h>
+#include "rvtrace.h"
+
+struct rvtrace_decoder {
+	struct auxtrace auxtrace;
+	u32 auxtrace_type;
+	struct perf_session *session;
+	struct machine *machine;
+	u32 pmu_type;
+};
+
+static int rvtrace_process_event(struct perf_session *session __maybe_unused,
+				 union perf_event *event __maybe_unused,
+				 struct perf_sample *sample __maybe_unused,
+				 const struct perf_tool *tool __maybe_unused)
+{
+	return 0;
+}
+
+static int rvtrace_process_auxtrace_event(struct perf_session *session __maybe_unused,
+					  union perf_event *event __maybe_unused,
+					  const struct perf_tool *tool __maybe_unused)
+{
+	return 0;
+}
+
+static int rvtrace_flush(struct perf_session *session __maybe_unused,
+			 const struct perf_tool *tool __maybe_unused)
+{
+	return 0;
+}
+
+static void rvtrace_free_events(struct perf_session *session __maybe_unused)
+{
+}
+
+static void rvtrace_free(struct perf_session *session)
+{
+	struct rvtrace_decoder *ptr = container_of(session->auxtrace, struct rvtrace_decoder,
+					    auxtrace);
+
+	session->auxtrace = NULL;
+	free(ptr);
+}
+
+static bool rvtrace_evsel_is_auxtrace(struct perf_session *session,
+				      struct evsel *evsel)
+{
+	struct rvtrace_decoder *ptr = container_of(session->auxtrace,
+						   struct rvtrace_decoder, auxtrace);
+
+	return evsel->core.attr.type == ptr->pmu_type;
+}
+
+int rvtrace__process_auxtrace_info(union perf_event *event,
+				   struct perf_session *session)
+{
+	struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
+	struct rvtrace_decoder *ptr;
+
+	if (auxtrace_info->header.size < RVTRACE_AUXTRACE_PRIV_SIZE +
+	    sizeof(struct perf_record_auxtrace_info))
+		return -EINVAL;
+
+	ptr = zalloc(sizeof(*ptr));
+	if (!ptr)
+		return -ENOMEM;
+
+	ptr->session = session;
+	ptr->machine = &session->machines.host;
+	ptr->auxtrace_type = auxtrace_info->type;
+	ptr->pmu_type = auxtrace_info->priv[0];
+
+	ptr->auxtrace.process_event = rvtrace_process_event;
+	ptr->auxtrace.process_auxtrace_event = rvtrace_process_auxtrace_event;
+	ptr->auxtrace.flush_events = rvtrace_flush;
+	ptr->auxtrace.free_events = rvtrace_free_events;
+	ptr->auxtrace.free = rvtrace_free;
+	ptr->auxtrace.evsel_is_auxtrace = rvtrace_evsel_is_auxtrace;
+	session->auxtrace = &ptr->auxtrace;
+
+	return 0;
+}
diff --git a/tools/perf/util/rvtrace.h b/tools/perf/util/rvtrace.h
index 93c041db8660..fdf2e5866c85 100644
--- a/tools/perf/util/rvtrace.h
+++ b/tools/perf/util/rvtrace.h
@@ -15,4 +15,6 @@
 
 #define RVTRACE_AUXTRACE_PRIV_SIZE	sizeof(u64)
 
+int rvtrace__process_auxtrace_info(union perf_event *event, struct perf_session *session);
+struct auxtrace_record *rvtrace_record_init(int *err);
 #endif
-- 
2.43.0
Re: [PATCH v2 11/12] perf tools: Initial support for RISC-V trace decoder
Posted by Eric Lin 1 day, 4 hours ago
Hi Anup,

On Sat, Nov 1, 2025 at 11:45 PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> From: Mayuresh Chitale <mchitale@ventanamicro.com>
>
> Add bare bones support for RISC-V trace decoder so that the data received
> from the hardware by the RISC-V trace perf driver can be written to the
> perf record output file.
>
> Co-developed-by: Anup Patel <apatel@ventanamicro.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
> ---
>  tools/perf/util/Build             |  1 +
>  tools/perf/util/auxtrace.c        |  3 +
>  tools/perf/util/rvtrace-decoder.c | 91 +++++++++++++++++++++++++++++++
>  tools/perf/util/rvtrace.h         |  2 +
>  4 files changed, 97 insertions(+)
>  create mode 100644 tools/perf/util/rvtrace-decoder.c
>
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index 4be313cd115a..f736cea51fd8 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -145,6 +145,7 @@ perf-util-$(CONFIG_AUXTRACE) += cs-etm.o
>  perf-util-$(CONFIG_AUXTRACE) += cs-etm-decoder/
>  endif
>  perf-util-$(CONFIG_AUXTRACE) += cs-etm-base.o
> +perf-util-$(CONFIG_AUXTRACE) += rvtrace-decoder.o
>
>  perf-util-y += parse-branch-options.o
>  perf-util-y += dump-insn.o
> diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
> index c905563e0d8a..299991d5d305 100644
> --- a/tools/perf/util/auxtrace.c
> +++ b/tools/perf/util/auxtrace.c
> @@ -54,6 +54,7 @@
>  #include "arm-spe.h"
>  #include "hisi-ptt.h"
>  #include "s390-cpumsf.h"
> +#include "rvtrace.h"
>  #include "util/mmap.h"
>  #include "powerpc-vpadtl.h"
>
> @@ -1395,6 +1396,8 @@ int perf_event__process_auxtrace_info(struct perf_session *session,
>                 err = powerpc_vpadtl_process_auxtrace_info(event, session);
>                 break;
>         case PERF_AUXTRACE_RISCV_TRACE:
> +               err = rvtrace__process_auxtrace_info(event, session);
> +               break;
>         case PERF_AUXTRACE_UNKNOWN:
>         default:
>                 return -EINVAL;
> diff --git a/tools/perf/util/rvtrace-decoder.c b/tools/perf/util/rvtrace-decoder.c
> new file mode 100644
> index 000000000000..58db5ca62c1a
> --- /dev/null
> +++ b/tools/perf/util/rvtrace-decoder.c
> @@ -0,0 +1,91 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * RISC-V trace Decoder
> + */
> +
> +#include <errno.h>
> +#include <inttypes.h>
> +#include "evlist.h"
> +#include <internal/lib.h>
> +#include "rvtrace.h"
> +
> +struct rvtrace_decoder {
> +       struct auxtrace auxtrace;
> +       u32 auxtrace_type;
> +       struct perf_session *session;
> +       struct machine *machine;
> +       u32 pmu_type;
> +};
> +
> +static int rvtrace_process_event(struct perf_session *session __maybe_unused,
> +                                union perf_event *event __maybe_unused,
> +                                struct perf_sample *sample __maybe_unused,
> +                                const struct perf_tool *tool __maybe_unused)
> +{
> +       return 0;
> +}
> +
> +static int rvtrace_process_auxtrace_event(struct perf_session *session __maybe_unused,
> +                                         union perf_event *event __maybe_unused,
> +                                         const struct perf_tool *tool __maybe_unused)
> +{
> +       return 0;
> +}
> +
> +static int rvtrace_flush(struct perf_session *session __maybe_unused,
> +                        const struct perf_tool *tool __maybe_unused)
> +{
> +       return 0;
> +}
> +
> +static void rvtrace_free_events(struct perf_session *session __maybe_unused)
> +{
> +}
> +
> +static void rvtrace_free(struct perf_session *session)
> +{
> +       struct rvtrace_decoder *ptr = container_of(session->auxtrace, struct rvtrace_decoder,
> +                                           auxtrace);
> +
> +       session->auxtrace = NULL;
> +       free(ptr);
> +}
> +
> +static bool rvtrace_evsel_is_auxtrace(struct perf_session *session,
> +                                     struct evsel *evsel)
> +{
> +       struct rvtrace_decoder *ptr = container_of(session->auxtrace,
> +                                                  struct rvtrace_decoder, auxtrace);
> +
> +       return evsel->core.attr.type == ptr->pmu_type;
> +}
> +
> +int rvtrace__process_auxtrace_info(union perf_event *event,
> +                                  struct perf_session *session)
> +{
> +       struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
> +       struct rvtrace_decoder *ptr;
> +
> +       if (auxtrace_info->header.size < RVTRACE_AUXTRACE_PRIV_SIZE +
> +           sizeof(struct perf_record_auxtrace_info))
> +               return -EINVAL;
> +
> +       ptr = zalloc(sizeof(*ptr));
> +       if (!ptr)
> +               return -ENOMEM;
> +
> +       ptr->session = session;
> +       ptr->machine = &session->machines.host;
> +       ptr->auxtrace_type = auxtrace_info->type;
> +       ptr->pmu_type = auxtrace_info->priv[0];
> +
> +       ptr->auxtrace.process_event = rvtrace_process_event;
> +       ptr->auxtrace.process_auxtrace_event = rvtrace_process_auxtrace_event;
> +       ptr->auxtrace.flush_events = rvtrace_flush;
> +       ptr->auxtrace.free_events = rvtrace_free_events;
> +       ptr->auxtrace.free = rvtrace_free;
> +       ptr->auxtrace.evsel_is_auxtrace = rvtrace_evsel_is_auxtrace;
> +       session->auxtrace = &ptr->auxtrace;
> +
> +       return 0;
> +}
> diff --git a/tools/perf/util/rvtrace.h b/tools/perf/util/rvtrace.h
> index 93c041db8660..fdf2e5866c85 100644
> --- a/tools/perf/util/rvtrace.h
> +++ b/tools/perf/util/rvtrace.h
> @@ -15,4 +15,6 @@
>
>  #define RVTRACE_AUXTRACE_PRIV_SIZE     sizeof(u64)
>
> +int rvtrace__process_auxtrace_info(union perf_event *event, struct perf_session *session);
> +struct auxtrace_record *rvtrace_record_init(int *err);

It looks like the implementation of `rvtrace_recording_init` in the
auxtrace.c file is static (private), and the arguments don't match
this declaration.
Should we remove "static" from auxtrace.c and update this prototype
to: "struct auxtrace_record *rvtrace_recording_init(int *err, struct
perf_pmu *rvtrace_pmu);"?

Or should we simply remove this declaration from the header? Thanks.

Regards,
Eric Lin,

>  #endif
> --
> 2.43.0
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv