From nobody Thu Oct 2 21:28:34 2025 Received: from out30-119.freemail.mail.aliyun.com (out30-119.freemail.mail.aliyun.com [115.124.30.119]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 90F13322A0B for ; Thu, 11 Sep 2025 12:45:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.119 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757594724; cv=none; b=WdPXjBp51+0kmsgaQd5bLk09usomV5Zz/cmBUy7+/uZhaZX0iEUsYkvl7r9/qzIhaKinxcKp39jDVilPv2jIS9wIjoP1Nh1irMa05+VNWdq6bz638pVbJXIKSvLI0EmZBy58qpW0bF9K7f/MJU3jEp1rpztebJ5l2FTDCLY/mrg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757594724; c=relaxed/simple; bh=Y40KNJ4Iscv4xXvptbceaOSSvRBVQbTNlbKyTVagcfA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oC5hmI/AJ5lrakzWaedhvHQYT4qA6K36n4v4B8aiaBiQIDnWdU2xH8oNaZMuqbR/r8sev1cfNFrBQ3+bRG9UmTGsosyM/OIg3fRWGxL4ko/VSluhuvMugH3imPzkiwsgkz1yyQv03E7R387jRGOj7Cux0rhdZ4YHUae3a/pEoKk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=xdV7qw7r; arc=none smtp.client-ip=115.124.30.119 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="xdV7qw7r" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1757594713; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=KlBG/qJSG3l98wLLhwHdyPoQRBJrGWD1/8eAfLJKJ5A=; b=xdV7qw7rEac9kA/Q5FBtNwLHlQDc/lmqWZ+AnuAMPjV1mfnQ6Je/FMDKqYeUmBQMBlghNj8xKZ3Vd8QAWf6Yl5Dt3dNYyOVcgZU9Kch8H+W8fZ48VgXltr4F42H0SPjC93X92SmQabII/Gt8rD1YterbvaqLK89rUNsEV1LcB78= Received: from DESKTOP-S9E58SO.localdomain(mailfrom:cp0613@linux.alibaba.com fp:SMTPD_---0WnmLJjN_1757594711 cluster:ay36) by smtp.aliyun-inc.com; Thu, 11 Sep 2025 20:45:12 +0800 From: cp0613@linux.alibaba.com To: paul.walmsley@sifive.com, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, guoren@kernel.org Cc: linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Chen Pei Subject: [RFC PATCH 3/4] tools: perf: Support perf record with aux buffer for riscv trace Date: Thu, 11 Sep 2025 20:44:47 +0800 Message-ID: <20250911124448.1771-4-cp0613@linux.alibaba.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250911124448.1771-1-cp0613@linux.alibaba.com> References: <20250911124448.1771-1-cp0613@linux.alibaba.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Chen Pei This patch implements AUXTRACE support for RISC-V Trace. The corresponding driver needs to implement the setup_aux and free_aux PMU driver ops. The aux buffer is a type of ring buffer used in trace scenarios, and RISC-V Trace should also reuse this capability. Signed-off-by: Chen Pei --- arch/riscv/events/riscv_trace.c | 61 ++++++++ arch/riscv/events/riscv_trace.h | 8 + tools/perf/arch/riscv/util/Build | 3 + tools/perf/arch/riscv/util/auxtrace.c | 33 ++++ tools/perf/arch/riscv/util/pmu.c | 18 +++ tools/perf/arch/riscv/util/riscv-trace.c | 183 +++++++++++++++++++++++ tools/perf/arch/riscv/util/tsc.c | 15 ++ tools/perf/util/Build | 1 + tools/perf/util/auxtrace.c | 4 + tools/perf/util/auxtrace.h | 1 + tools/perf/util/riscv-trace.c | 162 ++++++++++++++++++++ tools/perf/util/riscv-trace.h | 18 +++ 12 files changed, 507 insertions(+) create mode 100644 tools/perf/arch/riscv/util/auxtrace.c create mode 100644 tools/perf/arch/riscv/util/pmu.c create mode 100644 tools/perf/arch/riscv/util/riscv-trace.c create mode 100644 tools/perf/arch/riscv/util/tsc.c create mode 100644 tools/perf/util/riscv-trace.c create mode 100644 tools/perf/util/riscv-trace.h diff --git a/arch/riscv/events/riscv_trace.c b/arch/riscv/events/riscv_trac= e.c index e408d9a4034a..3ac4a3be5d3e 100644 --- a/arch/riscv/events/riscv_trace.c +++ b/arch/riscv/events/riscv_trace.c @@ -8,6 +8,7 @@ #include #include #include +#include =20 #include "riscv_trace.h" =20 @@ -81,6 +82,9 @@ static void riscv_trace_event_start(struct perf_event *ev= ent, int flags) { pr_info("%s:%d on_cpu=3D%d cpu=3D%d\n", __func__, __LINE__, event->oncpu, event->cpu); + // TODO: Begin aux buffer + // struct xuantie_ntrace_aux_buf *buf; + // buf =3D perf_aux_output_begin(&riscv_trace_pmu.handle, event); // TODO: Enable the trace component } =20 @@ -89,6 +93,61 @@ static void riscv_trace_event_stop(struct perf_event *ev= ent, int flags) pr_info("%s:%d on_cpu=3D%d cpu=3D%d\n", __func__, __LINE__, event->oncpu, event->cpu); // TODO: Disable the trace component + // TODO: End aux buffer + // struct xuantie_ntrace_aux_buf *buf; + // buf =3D perf_get_aux(&riscv_trace_pmu.handle); + // Fill aux buffer + // perf_aux_output_end(&riscv_trace_pmu.handle, size); +} + +static void *riscv_trace_buffer_setup_aux(struct perf_event *event, void *= *pages, + int nr_pages, bool overwrite) +{ + struct riscv_trace_aux_buf *buf; + struct page **pagelist; + int i; + + if (overwrite) { + pr_warn("Overwrite mode is not supported\n"); + return NULL; + } + + buf =3D kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) + return NULL; + + pagelist =3D kcalloc(nr_pages, sizeof(*pagelist), GFP_KERNEL); + if (!pagelist) + goto err; + + for (i =3D 0; i < nr_pages; i++) + pagelist[i] =3D virt_to_page(pages[i]); + + buf->base =3D vmap(pagelist, nr_pages, VM_MAP, PAGE_KERNEL); + if (!buf->base) { + kfree(pagelist); + goto err; + } + + buf->nr_pages =3D nr_pages; + buf->length =3D nr_pages * PAGE_SIZE; + buf->pos =3D 0; + + pr_info("nr_pages=3D%d length=3D%d\n", buf->nr_pages, buf->length); + + kfree(pagelist); + return buf; +err: + kfree(buf); + return NULL; +} + +static void riscv_trace_buffer_free_aux(void *aux) +{ + struct riscv_trace_aux_buf *buf =3D aux; + + vunmap(buf->base); + kfree(buf); } =20 static int __init riscv_trace_init(void) @@ -128,6 +187,8 @@ static int __init riscv_trace_init(void) riscv_trace_pmu.pmu.del =3D riscv_trace_event_del; riscv_trace_pmu.pmu.start =3D riscv_trace_event_start; riscv_trace_pmu.pmu.stop =3D riscv_trace_event_stop; + riscv_trace_pmu.pmu.setup_aux =3D riscv_trace_buffer_setup_aux; + riscv_trace_pmu.pmu.free_aux =3D riscv_trace_buffer_free_aux; =20 return perf_pmu_register(&riscv_trace_pmu.pmu, "riscv_trace", -1); } diff --git a/arch/riscv/events/riscv_trace.h b/arch/riscv/events/riscv_trac= e.h index ef0af0d0b2ee..c28216227006 100644 --- a/arch/riscv/events/riscv_trace.h +++ b/arch/riscv/events/riscv_trace.h @@ -75,6 +75,14 @@ extern struct list_head riscv_trace_controllers; struct riscv_trace_pmu { struct pmu pmu; struct riscv_trace_filter_attr filter_attr; + struct perf_output_handle handle; +}; + +struct riscv_trace_aux_buf { + u32 length; + u32 nr_pages; + void *base; + u32 pos; }; =20 static inline const char *riscv_trace_type2str(enum RISCV_TRACE_COMPONENT_= TYPE diff --git a/tools/perf/arch/riscv/util/Build b/tools/perf/arch/riscv/util/= Build index 58a672246024..d1599b70ef2f 100644 --- a/tools/perf/arch/riscv/util/Build +++ b/tools/perf/arch/riscv/util/Build @@ -1,5 +1,8 @@ perf-util-y +=3D perf_regs.o perf-util-y +=3D header.o +perf-util-y +=3D tsc.o =20 perf-util-$(CONFIG_LIBTRACEEVENT) +=3D kvm-stat.o perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) +=3D unwind-libdw.o + +perf-util-$(CONFIG_AUXTRACE) +=3D pmu.o auxtrace.o riscv-trace.o diff --git a/tools/perf/arch/riscv/util/auxtrace.c b/tools/perf/arch/riscv/= util/auxtrace.c new file mode 100644 index 000000000000..51c8dac5ff61 --- /dev/null +++ b/tools/perf/arch/riscv/util/auxtrace.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +#include "../../../util/auxtrace.h" +#include "../../../util/debug.h" +#include "../../../util/evlist.h" +#include "../../../util/pmu.h" +#include "../../../util/pmus.h" +#include "riscv-trace.h" + +struct auxtrace_record +*auxtrace_record__init(struct evlist *evlist, int *err) +{ + struct perf_pmu *riscv_trace_pmu =3D NULL; + struct evsel *evsel; + bool found_riscv_trace =3D false; + + riscv_trace_pmu =3D perf_pmus__find(RISCV_TRACE_PMU_NAME); + + evlist__for_each_entry(evlist, evsel) { + if (riscv_trace_pmu && evsel->core.attr.type =3D=3D riscv_trace_pmu->typ= e) + found_riscv_trace =3D true; + } + + if (found_riscv_trace) + return riscv_trace_recording_init(err, riscv_trace_pmu); + + return NULL; +} diff --git a/tools/perf/arch/riscv/util/pmu.c b/tools/perf/arch/riscv/util/= pmu.c new file mode 100644 index 000000000000..921b083c4f6b --- /dev/null +++ b/tools/perf/arch/riscv/util/pmu.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +#include "riscv-trace.h" +#include "../../../util/pmu.h" + +void perf_pmu__arch_init(struct perf_pmu *pmu) +{ +#ifdef HAVE_AUXTRACE_SUPPORT + if (!strcmp(pmu->name, RISCV_TRACE_PMU_NAME)) { + pmu->auxtrace =3D true; + pmu->selectable =3D true; + } +#endif +} diff --git a/tools/perf/arch/riscv/util/riscv-trace.c b/tools/perf/arch/ris= cv/util/riscv-trace.c new file mode 100644 index 000000000000..0632f1f43c15 --- /dev/null +++ b/tools/perf/arch/riscv/util/riscv-trace.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include + +#include // page_size +#include "../../../util/auxtrace.h" +#include "../../../util/cpumap.h" +#include "../../../util/debug.h" +#include "../../../util/event.h" +#include "../../../util/evlist.h" +#include "../../../util/evsel.h" +#include "../../../util/pmu.h" +#include "../../../util/record.h" +#include "../../../util/session.h" +#include "../../../util/tsc.h" +#include "../../../util/riscv-trace.h" + +#define KiB(x) ((x) * 1024) +#define MiB(x) ((x) * 1024 * 1024) + +struct riscv_trace_recording { + struct auxtrace_record itr; + struct perf_pmu *riscv_trace_pmu; + struct evlist *evlist; +}; + +static size_t +riscv_trace_info_priv_size(struct auxtrace_record *itr __maybe_unused, + struct evlist *evlist __maybe_unused) +{ + return RISCV_TRACE_AUXTRACE_PRIV_SIZE; +} + +static int riscv_trace_info_fill(struct auxtrace_record *itr, + struct perf_session *session, + struct perf_record_auxtrace_info *auxtrace_info, + size_t priv_size) +{ + struct riscv_trace_recording *pttr =3D + container_of(itr, struct riscv_trace_recording, itr); + struct perf_pmu *riscv_trace_pmu =3D pttr->riscv_trace_pmu; + + if (priv_size !=3D RISCV_TRACE_AUXTRACE_PRIV_SIZE) + return -EINVAL; + + if (!session->evlist->core.nr_mmaps) + return -EINVAL; + + auxtrace_info->type =3D PERF_AUXTRACE_RISCV_TRACE; + auxtrace_info->priv[0] =3D riscv_trace_pmu->type; + + return 0; +} + +static int riscv_trace_set_auxtrace_mmap_page(struct record_opts *opts) +{ + bool privileged =3D perf_event_paranoid_check(-1); + + if (!opts->full_auxtrace) + return 0; + + if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { + if (privileged) { + opts->auxtrace_mmap_pages =3D MiB(16) / page_size; + } else { + opts->auxtrace_mmap_pages =3D KiB(128) / page_size; + if (opts->mmap_pages =3D=3D UINT_MAX) + opts->mmap_pages =3D KiB(256) / page_size; + } + } + + /* Validate auxtrace_mmap_pages */ + if (opts->auxtrace_mmap_pages) { + size_t sz =3D opts->auxtrace_mmap_pages * (size_t)page_size; + size_t min_sz =3D KiB(8); + + if (sz < min_sz || !is_power_of_2(sz)) { + pr_err("Invalid mmap size for riscv trace: must be at least %zuKiB and = a power of 2\n", + min_sz / 1024); + return -EINVAL; + } + } + + return 0; +} + +static int riscv_trace_recording_options(struct auxtrace_record *itr, + struct evlist *evlist, + struct record_opts *opts) +{ + struct riscv_trace_recording *pttr =3D + container_of(itr, struct riscv_trace_recording, itr); + struct perf_pmu *riscv_trace_pmu =3D pttr->riscv_trace_pmu; + struct evsel *evsel, *riscv_trace_evsel =3D NULL; + struct evsel *tracking_evsel; + int err; + + pttr->evlist =3D evlist; + evlist__for_each_entry(evlist, evsel) { + if (evsel->core.attr.type =3D=3D riscv_trace_pmu->type) { + if (riscv_trace_evsel) { + pr_err("There may be only one " RISCV_TRACE_PMU_NAME "x event\n"); + return -EINVAL; + } + evsel->core.attr.freq =3D 0; + evsel->core.attr.sample_period =3D 1; + evsel->needs_auxtrace_mmap =3D true; + riscv_trace_evsel =3D evsel; + opts->full_auxtrace =3D true; + } + } + + err =3D riscv_trace_set_auxtrace_mmap_page(opts); + if (err) + return err; + /* + * To obtain the auxtrace buffer file descriptor, the auxtrace event + * must come first. + */ + evlist__to_front(evlist, riscv_trace_evsel); + evsel__set_sample_bit(riscv_trace_evsel, TIME); + + /* Add dummy event to keep tracking */ + err =3D parse_event(evlist, "dummy:u"); + if (err) + return err; + + tracking_evsel =3D evlist__last(evlist); + evlist__set_tracking_event(evlist, tracking_evsel); + + tracking_evsel->core.attr.freq =3D 0; + tracking_evsel->core.attr.sample_period =3D 1; + evsel__set_sample_bit(tracking_evsel, TIME); + + return 0; +} + +static u64 riscv_trace_reference(struct auxtrace_record *itr __maybe_unuse= d) +{ + return rdtsc(); +} + +static void riscv_trace_recording_free(struct auxtrace_record *itr) +{ + struct riscv_trace_recording *pttr =3D + container_of(itr, struct riscv_trace_recording, itr); + + free(pttr); +} + +struct auxtrace_record *riscv_trace_recording_init(int *err, + struct perf_pmu *riscv_trace_pmu) +{ + struct riscv_trace_recording *pttr; + + if (!riscv_trace_pmu) { + *err =3D -ENODEV; + return NULL; + } + + pttr =3D zalloc(sizeof(*pttr)); + if (!pttr) { + *err =3D -ENOMEM; + return NULL; + } + + pttr->riscv_trace_pmu =3D riscv_trace_pmu; + pttr->itr.recording_options =3D riscv_trace_recording_options; + pttr->itr.info_priv_size =3D riscv_trace_info_priv_size; + pttr->itr.info_fill =3D riscv_trace_info_fill; + pttr->itr.free =3D riscv_trace_recording_free; + pttr->itr.reference =3D riscv_trace_reference; + pttr->itr.read_finish =3D auxtrace_record__read_finish; + pttr->itr.alignment =3D 0; + + *err =3D 0; + return &pttr->itr; +} diff --git a/tools/perf/arch/riscv/util/tsc.c b/tools/perf/arch/riscv/util/= tsc.c new file mode 100644 index 000000000000..cf021e423f79 --- /dev/null +++ b/tools/perf/arch/riscv/util/tsc.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#include "../../../util/tsc.h" + +u64 rdtsc(void) +{ + u64 val; + + // https://lore.kernel.org/all/YxIzgYP3MujXdqwj@aurel32.net/T/ + asm volatile("rdtime %0" : "=3Dr"(val)); + + return val; +} diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 4959e7a990e4..4726a100a156 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -136,6 +136,7 @@ perf-util-$(CONFIG_AUXTRACE) +=3D arm-spe-decoder/ perf-util-$(CONFIG_AUXTRACE) +=3D hisi-ptt.o perf-util-$(CONFIG_AUXTRACE) +=3D hisi-ptt-decoder/ perf-util-$(CONFIG_AUXTRACE) +=3D s390-cpumsf.o +perf-util-$(CONFIG_AUXTRACE) +=3D riscv-trace.o =20 ifdef CONFIG_LIBOPENCSD perf-util-$(CONFIG_AUXTRACE) +=3D cs-etm.o diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index ebd32f1b8f12..b4d8f3c5ebb1 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 "riscv-trace.h" #include "util/mmap.h" =20 #include @@ -1393,6 +1394,9 @@ int perf_event__process_auxtrace_info(struct perf_ses= sion *session, case PERF_AUXTRACE_HISI_PTT: err =3D hisi_ptt_process_auxtrace_info(event, session); break; + case PERF_AUXTRACE_RISCV_TRACE: + err =3D riscv_trace_process_auxtrace_info(event, session); + break; case PERF_AUXTRACE_UNKNOWN: default: return -EINVAL; diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index f001cbb68f8e..5b7ce4a99709 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -50,6 +50,7 @@ enum auxtrace_type { PERF_AUXTRACE_ARM_SPE, PERF_AUXTRACE_S390_CPUMSF, PERF_AUXTRACE_HISI_PTT, + PERF_AUXTRACE_RISCV_TRACE, }; =20 enum itrace_period_type { diff --git a/tools/perf/util/riscv-trace.c b/tools/perf/util/riscv-trace.c new file mode 100644 index 000000000000..c9bc3f6a7857 --- /dev/null +++ b/tools/perf/util/riscv-trace.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "auxtrace.h" +#include "color.h" +#include "debug.h" +#include "evsel.h" +#include "riscv-trace.h" +#include "machine.h" +#include "session.h" +#include "tool.h" +#include + +struct riscv_trace { + struct auxtrace auxtrace; + u32 auxtrace_type; + struct perf_session *session; + struct machine *machine; + u32 pmu_type; +}; + +static void riscv_trace_dump(struct riscv_trace *trace __maybe_unused, + unsigned char *buf, size_t len) +{ + + const char *color =3D PERF_COLOR_BLUE; + + color_fprintf(stdout, color, ". ... %s: buf=3D%p len=3D%zubytes\n", __fun= c__, buf, len); + for (size_t i =3D 0; i < len; i++) + printf("%02x ", buf[i]); +} + +static void riscv_trace_dump_event(struct riscv_trace *trace, unsigned cha= r *buf, + size_t len) +{ + printf(".\n"); + + riscv_trace_dump(trace, buf, len); +} + +static int riscv_trace_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 riscv_trace_process_auxtrace_event(struct perf_session *session, + union perf_event *event, + const struct perf_tool *tool __maybe_unused) +{ + struct riscv_trace *trace =3D container_of(session->auxtrace, struct risc= v_trace, + auxtrace); + int fd =3D perf_data__fd(session->data); + int size =3D event->auxtrace.size; + void *data =3D malloc(size); + off_t data_offset; + int err; + + if (!data) + return -errno; + + if (perf_data__is_pipe(session->data)) { + data_offset =3D 0; + } else { + data_offset =3D lseek(fd, 0, SEEK_CUR); + if (data_offset =3D=3D -1) { + free(data); + return -errno; + } + } + + err =3D readn(fd, data, size); + if (err !=3D (ssize_t)size) { + free(data); + return -errno; + } + + if (dump_trace) + riscv_trace_dump_event(trace, data, size); + + free(data); + return 0; +} + +static int riscv_trace_flush(struct perf_session *session __maybe_unused, + const struct perf_tool *tool __maybe_unused) +{ + return 0; +} + +static void riscv_trace_free_events(struct perf_session *session __maybe_u= nused) +{ +} + +static void riscv_trace_free(struct perf_session *session) +{ + struct riscv_trace *trace =3D container_of(session->auxtrace, struct risc= v_trace, + auxtrace); + + session->auxtrace =3D NULL; + free(trace); +} + +static bool riscv_trace_evsel_is_auxtrace(struct perf_session *session, + struct evsel *evsel) +{ + struct riscv_trace *trace =3D container_of(session->auxtrace, struct risc= v_trace, auxtrace); + + return evsel->core.attr.type =3D=3D trace->pmu_type; +} + +static void riscv_trace_print_info(__u64 type) +{ + if (!dump_trace) + return; + + fprintf(stdout, " PMU Type %" PRId64 "\n", (s64) type); +} + +int riscv_trace_process_auxtrace_info(union perf_event *event, + struct perf_session *session) +{ + struct perf_record_auxtrace_info *auxtrace_info =3D &event->auxtrace_info; + struct riscv_trace *trace; + + if (auxtrace_info->header.size < RISCV_TRACE_AUXTRACE_PRIV_SIZE + + sizeof(struct perf_record_auxtrace_info)) + return -EINVAL; + + trace =3D zalloc(sizeof(*trace)); + if (!trace) + return -ENOMEM; + + trace->session =3D session; + trace->machine =3D &session->machines.host; /* No kvm support */ + trace->auxtrace_type =3D auxtrace_info->type; + trace->pmu_type =3D auxtrace_info->priv[0]; + + trace->auxtrace.process_event =3D riscv_trace_process_event; + trace->auxtrace.process_auxtrace_event =3D riscv_trace_process_auxtrace_e= vent; + trace->auxtrace.flush_events =3D riscv_trace_flush; + trace->auxtrace.free_events =3D riscv_trace_free_events; + trace->auxtrace.free =3D riscv_trace_free; + trace->auxtrace.evsel_is_auxtrace =3D riscv_trace_evsel_is_auxtrace; + session->auxtrace =3D &trace->auxtrace; + + riscv_trace_print_info(auxtrace_info->priv[0]); + + return 0; +} diff --git a/tools/perf/util/riscv-trace.h b/tools/perf/util/riscv-trace.h new file mode 100644 index 000000000000..4901ea323b77 --- /dev/null +++ b/tools/perf/util/riscv-trace.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef INCLUDE__PERF_RISCV_TRACE_H__ +#define INCLUDE__PERF_RISCV_TRACE_H__ + +#define RISCV_TRACE_PMU_NAME "riscv_trace" +#define RISCV_TRACE_AUXTRACE_PRIV_SIZE sizeof(u64) + +union perf_event; +struct perf_session; +struct perf_pmu; + +struct auxtrace_record *riscv_trace_recording_init(int *err, + struct perf_pmu *riscv_ntrace_pmu); + +int riscv_trace_process_auxtrace_info(union perf_event *event, + struct perf_session *session); + +#endif --=20 2.49.0