From nobody Tue Oct 7 10:38:20 2025 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 77D342E5423 for ; Thu, 10 Jul 2025 23:57:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752191880; cv=none; b=VCiiTajAMFsNuZ8FzVQ6yZJ+hHQgrMz6YewxsJ2mC8LzHsbzRpXHWz0c0t52l9VBAmayEmtNR+Xk2AOJyUGbfbPuN7XSiOS+14meE6Zz2fSy6DNYFeZAjjS+tCxFKBhsZ0Lka0Zdtl8rA7S1nHRiYWKQW8o1gkjw2hCL8l8iIO0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752191880; c=relaxed/simple; bh=wU3wz0df7C5ZQeeQLCPpt5hn2poNUqfyMGtKBgXp6Co=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=NgUeUAiw+t8mB88z7MS0efHHTVCIFb2MEjrX/jIyQwEfYC/+H/RgVYT0O435+rYVD8BedWGSltM4JvMKA0VUq3brqLhZTsD2TKH/nXfPLqX0FHANe+oge7SmjcMLpLLG3B0gUIa1HvzA1tDkaguqrgeSJWlCgtEnReaiTirDjrs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=CyJY7SXH; arc=none smtp.client-ip=209.85.210.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="CyJY7SXH" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-74d15d8dcd1so1003887b3a.2 for ; Thu, 10 Jul 2025 16:57:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752191878; x=1752796678; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=wHY0GCNF2IapelErUdXSA7miepGcy18/bQ3SNGrcpTA=; b=CyJY7SXH+3CiZGFfSkOdLVioLotatTl9fcOWtG2kHkkyYfvUQVVVAujPN3kjdL0wOr IU9LXjO/hFsguQgDvLOlePZAKAEzzaFEN2xcYlEehmnrCeFSgm/gFvkuWeHvPeK/0/IG qTNtcRkelbtTe2TQcZqbCSl5fGlOgur8AASPhtMr+wIrTGaAG0MqPs1dEd6MlM4rNmC0 diMpALA5EWRrrYyTXERgKzHIlJh7wDluf1E/WwTghVcPRMTTZchmYOJ5S/j4ZKnsVPV8 EPgTe13q6SF6MtI0cjE7IYomZwo1QdaE10OU1njkUcVudrHKJg7xM0Sfp4YoHNxaQY8C GNWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752191878; x=1752796678; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=wHY0GCNF2IapelErUdXSA7miepGcy18/bQ3SNGrcpTA=; b=Sg+sBBtq81bUsZ7NeA8yLP5ZI4YhcOt/jJ/yIMk6ge/Nx72+wMzdIVB5BLyGKpmki7 +FVmIF+NGgTo44FmoB3ts5PFkxivuw4mbbc1xl/IbrLmWEIh8yF2Cq1YKqUUpn1zsquv KoZibfFYO670uctyjuYKA0ixSgyZ+fiJncYkwizaQzPzC9ECk8JjVqlY+wyw1fEPRF7j 6wyTfawmKHaBTsESG554zoZ0jxdcUjdJ8URbZC9im7ZWDQTCCVGASofEFtuIOoxQ9Nq0 oTDaKe/aMJMRBiOOK3zdccZS76tXc6iAa/VkTDT/MSINR1Ob2G13YcBz7mRzBcxNb8Po yaCQ== X-Forwarded-Encrypted: i=1; AJvYcCXIYOwaA8qte4+v57Ttd/eCijF8gNvfYTuoWf5kUsKb8Jkmn9Is5zNr6BsfF3PUvmG4z/x8gRR3kzV1jdQ=@vger.kernel.org X-Gm-Message-State: AOJu0Ywdfe+9yRfSM0gLXGncM4Ah6UsJcmjHTCp2UcW2XqQxXJS6v6Un MgdM8JlndQtac7KhfonGpaZEkgNMbuf8nwGt2wIOQbJnHpwwozpVMwrqzlYFJd7vJ59blNatQcD EsTkktPt+cQ== X-Google-Smtp-Source: AGHT+IGaD95oNcduHMucrFF7/1alshsLJdEW6sf76XpwxHlWV7GNUif1shqMOFMfHqKasdfsGp6sV7EHzBdM X-Received: from pgcc2.prod.google.com ([2002:a63:1c02:0:b0:b2f:1e09:528b]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:62c1:b0:1f5:7eee:bb10 with SMTP id adf61e73a8af0-23135d64191mr1402049637.8.1752191877623; Thu, 10 Jul 2025 16:57:57 -0700 (PDT) Date: Thu, 10 Jul 2025 16:57:24 -0700 In-Reply-To: <20250710235735.1089240-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250710235735.1089240-1-irogers@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250710235735.1089240-4-irogers@google.com> Subject: [PATCH v6 03/14] perf tp_pmu: Factor existing tracepoint logic to new file From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Kan Liang , James Clark , Xu Yang , "Masami Hiramatsu (Google)" , Collin Funk , Howard Chu , Weilin Wang , Andi Kleen , "Dr. David Alan Gilbert" , Thomas Richter , Tiezhu Yang , Gautam Menghani , Thomas Falcon , Chun-Tse Shao , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Start the creation of a tracepoint PMU abstraction. Tracepoint events don't follow the regular sysfs perf conventions. Eventually the new PMU abstraction will bridge the gap so tracepoint events look more like regular perf ones. Signed-off-by: Ian Rogers --- tools/perf/util/Build | 1 + tools/perf/util/evsel.c | 21 +---- tools/perf/util/parse-events.c | 147 ++++++++++++++------------------- tools/perf/util/tp_pmu.c | 95 +++++++++++++++++++++ tools/perf/util/tp_pmu.h | 12 +++ 5 files changed, 170 insertions(+), 106 deletions(-) create mode 100644 tools/perf/util/tp_pmu.c create mode 100644 tools/perf/util/tp_pmu.h diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 12bc01c843b2..4959e7a990e4 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -88,6 +88,7 @@ perf-util-y +=3D pmu-bison.o perf-util-y +=3D drm_pmu.o perf-util-y +=3D hwmon_pmu.o perf-util-y +=3D tool_pmu.o +perf-util-y +=3D tp_pmu.o perf-util-y +=3D svghelper.o perf-util-y +=3D trace-event-info.o perf-util-y +=3D trace-event-scripting.o diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 3896a04d90af..5a1d19b4e5cd 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -59,6 +59,7 @@ #include "drm_pmu.h" #include "hwmon_pmu.h" #include "tool_pmu.h" +#include "tp_pmu.h" #include "rlimit.h" #include "../perf-sys.h" #include "util/parse-branch-options.h" @@ -571,24 +572,6 @@ struct evsel *evsel__clone(struct evsel *dest, struct = evsel *orig) return NULL; } =20 -static int trace_event__id(const char *sys, const char *name) -{ - char *tp_dir =3D get_events_file(sys); - char path[PATH_MAX]; - int id, err; - - if (!tp_dir) - return -1; - - scnprintf(path, PATH_MAX, "%s/%s/id", tp_dir, name); - put_events_file(tp_dir); - err =3D filename__read_int(path, &id); - if (err) - return err; - - return id; -} - /* * Returns pointer with encoded error via interface. */ @@ -622,7 +605,7 @@ struct evsel *evsel__newtp_idx(const char *sys, const c= har *name, int idx, bool event_attr_init(&attr); =20 if (format) { - id =3D trace_event__id(sys, name); + id =3D tp_pmu__id(sys, name); if (id < 0) { err =3D id; goto out_free; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 1ae481c9802b..f19541ca5268 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -17,13 +17,12 @@ #include "string2.h" #include "strbuf.h" #include "debug.h" -#include -#include #include #include #include #include "pmu.h" #include "pmus.h" +#include "tp_pmu.h" #include "asm/bug.h" #include "ui/ui.h" #include "util/parse-branch-options.h" @@ -33,6 +32,7 @@ #include "util/stat.h" #include "util/util.h" #include "tracepoint.h" +#include =20 #define MAX_NAME_LEN 100 =20 @@ -558,105 +558,82 @@ static int add_tracepoint(struct parse_events_state = *parse_state, return 0; } =20 -static int add_tracepoint_multi_event(struct parse_events_state *parse_sta= te, - struct list_head *list, - const char *sys_name, const char *evt_name, - struct parse_events_error *err, - struct parse_events_terms *head_config, YYLTYPE *loc) -{ - char *evt_path; - struct io_dirent64 *evt_ent; - struct io_dir evt_dir; - int ret =3D 0, found =3D 0; - - evt_path =3D get_events_file(sys_name); - if (!evt_path) { - tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); - return -1; - } - io_dir__init(&evt_dir, open(evt_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY)= ); - if (evt_dir.dirfd < 0) { - put_events_file(evt_path); - tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); - return -1; - } +struct add_tracepoint_multi_args { + struct parse_events_state *parse_state; + struct list_head *list; + const char *sys_glob; + const char *evt_glob; + struct parse_events_error *err; + struct parse_events_terms *head_config; + YYLTYPE *loc; + int found; +}; =20 - while (!ret && (evt_ent =3D io_dir__readdir(&evt_dir))) { - if (!strcmp(evt_ent->d_name, ".") - || !strcmp(evt_ent->d_name, "..") - || !strcmp(evt_ent->d_name, "enable") - || !strcmp(evt_ent->d_name, "filter")) - continue; +static int add_tracepoint_multi_event_cb(void *state, const char *sys_name= , const char *evt_name) +{ + struct add_tracepoint_multi_args *args =3D state; + int ret; =20 - if (!strglobmatch(evt_ent->d_name, evt_name)) - continue; + if (!strglobmatch(evt_name, args->evt_glob)) + return 0; =20 - found++; + args->found++; + ret =3D add_tracepoint(args->parse_state, args->list, sys_name, evt_name, + args->err, args->head_config, args->loc); =20 - ret =3D add_tracepoint(parse_state, list, sys_name, evt_ent->d_name, - err, head_config, loc); - } + return ret; +} =20 - if (!found) { - tracepoint_error(err, ENOENT, sys_name, evt_name, loc->first_column); - ret =3D -1; +static int add_tracepoint_multi_event(struct add_tracepoint_multi_args *ar= gs, const char *sys_name) +{ + if (strpbrk(args->evt_glob, "*?") =3D=3D NULL) { + /* Not a glob. */ + args->found++; + return add_tracepoint(args->parse_state, args->list, sys_name, args->evt= _glob, + args->err, args->head_config, args->loc); } =20 - put_events_file(evt_path); - close(evt_dir.dirfd); - return ret; + return tp_pmu__for_each_tp_event(sys_name, args, add_tracepoint_multi_eve= nt_cb); } =20 -static int add_tracepoint_event(struct parse_events_state *parse_state, - struct list_head *list, - const char *sys_name, const char *evt_name, - struct parse_events_error *err, - struct parse_events_terms *head_config, YYLTYPE *loc) +static int add_tracepoint_multi_sys_cb(void *state, const char *sys_name) { - return strpbrk(evt_name, "*?") ? - add_tracepoint_multi_event(parse_state, list, sys_name, evt_name, - err, head_config, loc) : - add_tracepoint(parse_state, list, sys_name, evt_name, - err, head_config, loc); + struct add_tracepoint_multi_args *args =3D state; + + if (!strglobmatch(sys_name, args->sys_glob)) + return 0; + + return add_tracepoint_multi_event(args, sys_name); } =20 static int add_tracepoint_multi_sys(struct parse_events_state *parse_state, struct list_head *list, - const char *sys_name, const char *evt_name, + const char *sys_glob, const char *evt_glob, struct parse_events_error *err, struct parse_events_terms *head_config, YYLTYPE *loc) { - struct io_dirent64 *events_ent; - struct io_dir events_dir; - int ret =3D 0; - char *events_dir_path =3D get_tracing_file("events"); + struct add_tracepoint_multi_args args =3D { + .parse_state =3D parse_state, + .list =3D list, + .sys_glob =3D sys_glob, + .evt_glob =3D evt_glob, + .err =3D err, + .head_config =3D head_config, + .loc =3D loc, + .found =3D 0, + }; + int ret; =20 - if (!events_dir_path) { - tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); - return -1; + if (strpbrk(sys_glob, "*?") =3D=3D NULL) { + /* Not a glob. */ + ret =3D add_tracepoint_multi_event(&args, sys_glob); + } else { + ret =3D tp_pmu__for_each_tp_sys(&args, add_tracepoint_multi_sys_cb); } - io_dir__init(&events_dir, open(events_dir_path, O_CLOEXEC | O_DIRECTORY |= O_RDONLY)); - put_events_file(events_dir_path); - if (events_dir.dirfd < 0) { - tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); - return -1; + if (args.found =3D=3D 0) { + tracepoint_error(err, ENOENT, sys_glob, evt_glob, loc->first_column); + return -ENOENT; } - - while (!ret && (events_ent =3D io_dir__readdir(&events_dir))) { - if (!strcmp(events_ent->d_name, ".") - || !strcmp(events_ent->d_name, "..") - || !strcmp(events_ent->d_name, "enable") - || !strcmp(events_ent->d_name, "header_event") - || !strcmp(events_ent->d_name, "header_page")) - continue; - - if (!strglobmatch(events_ent->d_name, sys_name)) - continue; - - ret =3D add_tracepoint_event(parse_state, list, events_ent->d_name, - evt_name, err, head_config, loc); - } - close(events_dir.dirfd); return ret; } =20 @@ -1348,12 +1325,8 @@ int parse_events_add_tracepoint(struct parse_events_= state *parse_state, return -EINVAL; } =20 - if (strpbrk(sys, "*?")) - return add_tracepoint_multi_sys(parse_state, list, sys, event, - err, head_config, loc); - else - return add_tracepoint_event(parse_state, list, sys, event, - err, head_config, loc); + return add_tracepoint_multi_sys(parse_state, list, sys, event, + err, head_config, loc); } =20 static int __parse_events_add_numeric(struct parse_events_state *parse_sta= te, diff --git a/tools/perf/util/tp_pmu.c b/tools/perf/util/tp_pmu.c new file mode 100644 index 000000000000..fd83164f8763 --- /dev/null +++ b/tools/perf/util/tp_pmu.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +#include "tp_pmu.h" +#include +#include +#include +#include +#include +#include + +int tp_pmu__id(const char *sys, const char *name) +{ + char *tp_dir =3D get_events_file(sys); + char path[PATH_MAX]; + int id, err; + + if (!tp_dir) + return -1; + + scnprintf(path, PATH_MAX, "%s/%s/id", tp_dir, name); + put_events_file(tp_dir); + err =3D filename__read_int(path, &id); + if (err) + return err; + + return id; +} + + +int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callb= ack cb) +{ + char *evt_path; + struct io_dirent64 *evt_ent; + struct io_dir evt_dir; + int ret =3D 0; + + evt_path =3D get_events_file(sys); + if (!evt_path) + return -errno; + + io_dir__init(&evt_dir, open(evt_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY)= ); + if (evt_dir.dirfd < 0) { + ret =3D -errno; + put_events_file(evt_path); + return ret; + } + put_events_file(evt_path); + + while (!ret && (evt_ent =3D io_dir__readdir(&evt_dir))) { + if (!strcmp(evt_ent->d_name, ".") + || !strcmp(evt_ent->d_name, "..") + || !strcmp(evt_ent->d_name, "enable") + || !strcmp(evt_ent->d_name, "filter")) + continue; + + ret =3D cb(state, sys, evt_ent->d_name); + if (ret) + break; + } + close(evt_dir.dirfd); + return ret; +} + +int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb) +{ + struct io_dirent64 *events_ent; + struct io_dir events_dir; + int ret =3D 0; + char *events_dir_path =3D get_tracing_file("events"); + + if (!events_dir_path) + return -errno; + + io_dir__init(&events_dir, open(events_dir_path, O_CLOEXEC | O_DIRECTORY |= O_RDONLY)); + if (events_dir.dirfd < 0) { + ret =3D -errno; + put_events_file(events_dir_path); + return ret; + } + put_events_file(events_dir_path); + + while (!ret && (events_ent =3D io_dir__readdir(&events_dir))) { + if (!strcmp(events_ent->d_name, ".") + || !strcmp(events_ent->d_name, "..") + || !strcmp(events_ent->d_name, "enable") + || !strcmp(events_ent->d_name, "header_event") + || !strcmp(events_ent->d_name, "header_page")) + continue; + + ret =3D cb(state, events_ent->d_name); + if (ret) + break; + } + close(events_dir.dirfd); + return ret; +} diff --git a/tools/perf/util/tp_pmu.h b/tools/perf/util/tp_pmu.h new file mode 100644 index 000000000000..49537303bd73 --- /dev/null +++ b/tools/perf/util/tp_pmu.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +#ifndef __TP_PMU_H +#define __TP_PMU_H + +typedef int (*tp_sys_callback)(void *state, const char *sys_name); +typedef int (*tp_event_callback)(void *state, const char *sys_name, const = char *evt_name); + +int tp_pmu__id(const char *sys, const char *name); +int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callb= ack cb); +int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb); + +#endif /* __TP_PMU_H */ --=20 2.50.0.727.gbf7dc18ff4-goog