From patchwork Wed May 18 22:47:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 12854203 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 97939C433F5 for ; Wed, 18 May 2022 22:47:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230243AbiERWrk (ORCPT ); Wed, 18 May 2022 18:47:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35492 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230268AbiERWre (ORCPT ); Wed, 18 May 2022 18:47:34 -0400 Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 094C616D4A5; Wed, 18 May 2022 15:47:29 -0700 (PDT) Received: by mail-pj1-x1033.google.com with SMTP id nk9-20020a17090b194900b001df2fcdc165so7060470pjb.0; Wed, 18 May 2022 15:47:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5k+UAQBgaQSFvof05RgSIz5e6L+wrYZgJDsxYwQlz4Q=; b=hVxIHikvxUPAAmOD/wRvVA384X/YFMiIJbmleOFQvgg+XaXFD+Gc7ZBYbp9TsRSxtD mICvQ4a/8++UAcjAXI6j0qRZdX+Sty4ojBibKQtrqtj1lEQInKAMtgEcdrb07DPdmyFL c/pSl464X0I1gVYmLgYSVlHHUqbKhkTnd3ykN0WE6zG0rGattoiZP2h86CElaAZ6pY3n zrsNjJvN4Ju7YlguLgqe+nBMIiOQ+YDuYfCPnnnTXjob8C/qYOapoEZav8z68nbhQkK9 EfvS1zGAAVJxAFYO7mPLEY/qtaSFadVVsxufAA/BZK/B+4tjG0pHxBJHhWppPgcgpNZ0 lfdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=5k+UAQBgaQSFvof05RgSIz5e6L+wrYZgJDsxYwQlz4Q=; b=W5T5mfGJtE063d+Pn9pZz7eMi2x24OKOU19Phu9yulc5ZMKUmGY1EIE5GzkuHxoq/V efSchN2bDsxeoeb8YT3xJAq+Qwh3r02Fz8GeTTueLibHr/lQjJpZWil/vX22diCCRtXU a45+9uwskj+GBO4ar7mrAlJygGo2KieO+eKuRzEkKrlmfFNlU8pBmHA5NhzrpKJ9Qxdf YfSqpWX0NwaVfRLPACyh9GVcwaD7tahj8F+jtjor2Bc7cgDzEnpYTaw0ukLyUU8s0kmX YZ6sLgXHamZ3OMNyhSUuHghdIEXw7Pd/YnST4tSZZs9lV1HTRTPHkyLxXKbsGSR+E9SD J98w== X-Gm-Message-State: AOAM533VJdg/dLPTXA4BykwFgelJcnmxt2/6doIxdlmv7n6o3tQ4Yfma /yId/hGoOR8mim/A5cSzb+k= X-Google-Smtp-Source: ABdhPJzbYzjCT1gW3ilXdnX3/GctK0XISfQyTjracq66aaKXBPShW0zidNoWF2zkjNY+/uV2XEolKw== X-Received: by 2002:a17:90b:17c1:b0:1dc:a6e6:ef26 with SMTP id me1-20020a17090b17c100b001dca6e6ef26mr2406476pjb.22.1652914048988; Wed, 18 May 2022 15:47:28 -0700 (PDT) Received: from balhae.corp.google.com ([2620:15c:2c1:200:a718:cbfe:31cb:3a04]) by smtp.gmail.com with ESMTPSA id d23-20020a170902aa9700b0015e8d4eb2besm2214100plr.264.2022.05.18.15.47.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 May 2022 15:47:28 -0700 (PDT) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa Cc: Ingo Molnar , Peter Zijlstra , LKML , Andi Kleen , Ian Rogers , Song Liu , Hao Luo , Milian Wolff , bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Blake Jones Subject: [PATCH 1/6] perf report: Do not extend sample type of bpf-output event Date: Wed, 18 May 2022 15:47:20 -0700 Message-Id: <20220518224725.742882-2-namhyung@kernel.org> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog In-Reply-To: <20220518224725.742882-1-namhyung@kernel.org> References: <20220518224725.742882-1-namhyung@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Currently evsel__new_idx() sets more sample_type bits when it finds a BPF-output event. But it should honor what's recorded in the perf data file rather than blindly sets the bits. Otherwise it could lead to a parse error when it recorded with a modified sample_type. Signed-off-by: Namhyung Kim --- tools/perf/util/evsel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1cf967d689aa..d3c8ebdc6d43 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -296,8 +296,8 @@ struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx) return NULL; evsel__init(evsel, attr, idx); - if (evsel__is_bpf_output(evsel)) { - evsel->core.attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | + if (evsel__is_bpf_output(evsel) && !attr->sample_type) { + evsel->core.attr.sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD), evsel->core.attr.sample_period = 1; } From patchwork Wed May 18 22:47:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 12854206 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7E0EFC433F5 for ; Wed, 18 May 2022 22:47:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230287AbiERWrn (ORCPT ); Wed, 18 May 2022 18:47:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36434 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230238AbiERWrg (ORCPT ); Wed, 18 May 2022 18:47:36 -0400 Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81E4C179C3D; Wed, 18 May 2022 15:47:31 -0700 (PDT) Received: by mail-pj1-x102a.google.com with SMTP id pq9-20020a17090b3d8900b001df622bf81dso3472728pjb.3; Wed, 18 May 2022 15:47:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=IVBOxfzQt/PIEE4vMniJHKiPU+TnxC7q6f218dueTkE=; b=mKE7ggYCATdvEklKmOjZLDBN0EX+PFd8N7wqo6DZsP8ydfBOZvPmc8zgNYh9la9sgL 9YZRLS2+WXU2AgEgtwQMEdLbzFI/QPtudyj36EEq1UlnnM5wDNJSpItCHgqWcjGaB1lT tBkHREXIMdHNaUQkjRisIxdT4KU4ryH0TWKdC7ox99+xNStG0wKSakFBv98FpeQWy6Zz c+ADvv+K7tcO2/saNgaDBTPaqYAkV1YdQ8n8eKzWKkEOzxsNg/591stA2Jtzvx2VD3AT fJE7vfCqwdyhl/HPN4587uZOzwqao7sf4iqqj9Tu1DtDYSSuBYP9xVNOTeUFuzqbyC9Z EEbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=IVBOxfzQt/PIEE4vMniJHKiPU+TnxC7q6f218dueTkE=; b=765eXD9UDyVsTlv2x4l48rcNGbRrBLAdmGC5yIUIsJ8LlXKC5LSt1kRRdufKMeMq9q mml0R6hR8e23oZ1Axw4OIfbVsnBQY9MytfByWOaMgoML48RAZ27qsvHGrnRSq+U98ZZI MkWp4zFNEaOOJGxzgwMpmQIe7SY5q3AA83NDzsR7hs2Q9Df/ZuZdY954a5uqAtMYDKDL md/1I+kXT9EsGXPz+i7fV2i+nkrnBr3EcZP4B7pBylI6ASN9ESuY3J7eVj+sUFDZWk20 Cs1Z+clllETpiBFvTGXgqiaYWOnMQSJ+s7zPBotOW5U23jx/me61ktLCesmB/Vealqg/ lAFA== X-Gm-Message-State: AOAM532kLW3iyTlYbhEljPBZZdKpi929k8v/CveLY3GddqUYa1HNAzUU f+EqJDpHY8/5YdBwve5cGKk= X-Google-Smtp-Source: ABdhPJyXlvYhSRlr9OBApZK2Y5Gjs9mDJ83qz7VD1h/6RYMvsvcG8z76Kgk/OfjTxGGJF10qix5Lyw== X-Received: by 2002:a17:902:d512:b0:15e:93de:762a with SMTP id b18-20020a170902d51200b0015e93de762amr1641329plg.132.1652914050193; Wed, 18 May 2022 15:47:30 -0700 (PDT) Received: from balhae.corp.google.com ([2620:15c:2c1:200:a718:cbfe:31cb:3a04]) by smtp.gmail.com with ESMTPSA id d23-20020a170902aa9700b0015e8d4eb2besm2214100plr.264.2022.05.18.15.47.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 May 2022 15:47:29 -0700 (PDT) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa Cc: Ingo Molnar , Peter Zijlstra , LKML , Andi Kleen , Ian Rogers , Song Liu , Hao Luo , Milian Wolff , bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Blake Jones Subject: [PATCH 2/6] perf record: Enable off-cpu analysis with BPF Date: Wed, 18 May 2022 15:47:21 -0700 Message-Id: <20220518224725.742882-3-namhyung@kernel.org> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog In-Reply-To: <20220518224725.742882-1-namhyung@kernel.org> References: <20220518224725.742882-1-namhyung@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Add --off-cpu option to enable the off-cpu profiling with BPF. It'd use a bpf_output event and rename it to "offcpu-time". Samples will be synthesized at the end of the record session using data from a BPF map which contains the aggregated off-cpu time at context switches. So it needs root privilege to get the off-cpu profiling. Each sample will have a separate user stacktrace so it will skip kernel threads. The sample ip will be set from the stacktrace and other sample data will be updated accordingly. Currently it only handles some basic sample types. The sample timestamp is set to a dummy value just not to bother with other events during the sorting. So it has a very big initial value and increase it on processing each samples. Good thing is that it can be used together with regular profiling like cpu cycles. If you don't want to that, you can use a dummy event to enable off-cpu profiling only. Example output: $ sudo perf record --off-cpu perf bench sched messaging -l 1000 $ sudo perf report --stdio --call-graph=no # Total Lost Samples: 0 # # Samples: 41K of event 'cycles' # Event count (approx.): 42137343851 ... # Samples: 1K of event 'offcpu-time' # Event count (approx.): 587990831640 # # Children Self Command Shared Object Symbol # ........ ........ ............... .................. ......................... # 81.66% 0.00% sched-messaging libc-2.33.so [.] __libc_start_main 81.66% 0.00% sched-messaging perf [.] cmd_bench 81.66% 0.00% sched-messaging perf [.] main 81.66% 0.00% sched-messaging perf [.] run_builtin 81.43% 0.00% sched-messaging perf [.] bench_sched_messaging 40.86% 40.86% sched-messaging libpthread-2.33.so [.] __read 37.66% 37.66% sched-messaging libpthread-2.33.so [.] __write 2.91% 2.91% sched-messaging libc-2.33.so [.] __poll ... As you can see it spent most of off-cpu time in read and write in bench_sched_messaging(). The --call-graph=no was added just to make the output concise here. It uses perf hooks facility to control BPF program during the record session rather than adding new BPF/off-cpu specific calls. Signed-off-by: Namhyung Kim Acked-by: Ian Rogers Reported-by: Ian Rogers Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-record.txt | 10 ++ tools/perf/Makefile.perf | 1 + tools/perf/builtin-record.c | 25 +++ tools/perf/util/Build | 1 + tools/perf/util/bpf_off_cpu.c | 204 +++++++++++++++++++++++ tools/perf/util/bpf_skel/off_cpu.bpf.c | 139 +++++++++++++++ tools/perf/util/off_cpu.h | 24 +++ 7 files changed, 404 insertions(+) create mode 100644 tools/perf/util/bpf_off_cpu.c create mode 100644 tools/perf/util/bpf_skel/off_cpu.bpf.c create mode 100644 tools/perf/util/off_cpu.h diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 465be4e62a17..b4e9ef7edfef 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -758,6 +758,16 @@ include::intel-hybrid.txt[] If the URLs is not specified, the value of DEBUGINFOD_URLS system environment variable is used. +--off-cpu:: + Enable off-cpu profiling with BPF. The BPF program will collect + task scheduling information with (user) stacktrace and save them + as sample data of a software event named "offcpu-time". The + sample period will have the time the task slept in nanoseconds. + + Note that BPF can collect stack traces using frame pointer ("fp") + only, as of now. So the applications built without the frame + pointer might see bogus addresses. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-list[1], linkperf:perf-intel-pt[1] diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 6e5aded855cc..8f738e11356d 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -1038,6 +1038,7 @@ SKEL_TMP_OUT := $(abspath $(SKEL_OUT)/.tmp) SKELETONS := $(SKEL_OUT)/bpf_prog_profiler.skel.h SKELETONS += $(SKEL_OUT)/bperf_leader.skel.h $(SKEL_OUT)/bperf_follower.skel.h SKELETONS += $(SKEL_OUT)/bperf_cgroup.skel.h $(SKEL_OUT)/func_latency.skel.h +SKELETONS += $(SKEL_OUT)/off_cpu.skel.h $(SKEL_TMP_OUT) $(LIBBPF_OUTPUT): $(Q)$(MKDIR) -p $@ diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a5cf6a99d67f..91f88501412e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -49,6 +49,7 @@ #include "util/clockid.h" #include "util/pmu-hybrid.h" #include "util/evlist-hybrid.h" +#include "util/off_cpu.h" #include "asm/bug.h" #include "perf.h" #include "cputopo.h" @@ -162,6 +163,7 @@ struct record { bool buildid_mmap; bool timestamp_filename; bool timestamp_boundary; + bool off_cpu; struct switch_output switch_output; unsigned long long samples; unsigned long output_max_size; /* = 0: unlimited */ @@ -903,6 +905,11 @@ static int record__config_text_poke(struct evlist *evlist) return 0; } +static int record__config_off_cpu(struct record *rec) +{ + return off_cpu_prepare(rec->evlist); +} + static bool record__kcore_readable(struct machine *machine) { char kcore[PATH_MAX]; @@ -2600,6 +2607,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) } else status = err; + if (rec->off_cpu) + rec->bytes_written += off_cpu_write(rec->session); + record__synthesize(rec, true); /* this will be recalculated during process_buildids() */ rec->samples = 0; @@ -3324,6 +3334,7 @@ static struct option __record_options[] = { OPT_CALLBACK_OPTARG(0, "threads", &record.opts, NULL, "spec", "write collected trace data into several data files using parallel threads", record__parse_threads), + OPT_BOOLEAN(0, "off-cpu", &record.off_cpu, "Enable off-cpu analysis"), OPT_END() }; @@ -3743,6 +3754,12 @@ int cmd_record(int argc, const char **argv) set_nobuild('\0', "vmlinux", true); # undef set_nobuild # undef REASON +#endif + +#ifndef HAVE_BPF_SKEL +# define set_nobuild(s, l, m, c) set_option_nobuild(record_options, s, l, m, c) + set_nobuild('\0', "off-cpu", "no BUILD_BPF_SKEL=1", true); +# undef set_nobuild #endif rec->opts.affinity = PERF_AFFINITY_SYS; @@ -3981,6 +3998,14 @@ int cmd_record(int argc, const char **argv) } } + if (rec->off_cpu) { + err = record__config_off_cpu(rec); + if (err) { + pr_err("record__config_off_cpu failed, error %d\n", err); + goto out; + } + } + if (record_opts__config(&rec->opts)) { err = -EINVAL; goto out; diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 9a7209a99e16..a51267d88ca9 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -147,6 +147,7 @@ perf-$(CONFIG_LIBBPF) += bpf_map.o perf-$(CONFIG_PERF_BPF_SKEL) += bpf_counter.o perf-$(CONFIG_PERF_BPF_SKEL) += bpf_counter_cgroup.o perf-$(CONFIG_PERF_BPF_SKEL) += bpf_ftrace.o +perf-$(CONFIG_PERF_BPF_SKEL) += bpf_off_cpu.o perf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o perf-$(CONFIG_LIBELF) += symbol-elf.o perf-$(CONFIG_LIBELF) += probe-file.o diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c new file mode 100644 index 000000000000..9ed7aca3f4ac --- /dev/null +++ b/tools/perf/util/bpf_off_cpu.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "util/bpf_counter.h" +#include "util/debug.h" +#include "util/evsel.h" +#include "util/evlist.h" +#include "util/off_cpu.h" +#include "util/perf-hooks.h" +#include "util/session.h" +#include + +#include "bpf_skel/off_cpu.skel.h" + +#define MAX_STACKS 32 +/* we don't need actual timestamp, just want to put the samples at last */ +#define OFF_CPU_TIMESTAMP (~0ull << 32) + +static struct off_cpu_bpf *skel; + +struct off_cpu_key { + u32 pid; + u32 tgid; + u32 stack_id; + u32 state; +}; + +union off_cpu_data { + struct perf_event_header hdr; + u64 array[1024 / sizeof(u64)]; +}; + +static int off_cpu_config(struct evlist *evlist) +{ + struct evsel *evsel; + struct perf_event_attr attr = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_BPF_OUTPUT, + .size = sizeof(attr), /* to capture ABI version */ + }; + char *evname = strdup(OFFCPU_EVENT); + + if (evname == NULL) + return -ENOMEM; + + evsel = evsel__new(&attr); + if (!evsel) { + free(evname); + return -ENOMEM; + } + + evsel->core.attr.freq = 1; + evsel->core.attr.sample_period = 1; + /* off-cpu analysis depends on stack trace */ + evsel->core.attr.sample_type = PERF_SAMPLE_CALLCHAIN; + + evlist__add(evlist, evsel); + + free(evsel->name); + evsel->name = evname; + + return 0; +} + +static void off_cpu_start(void *arg __maybe_unused) +{ + skel->bss->enabled = 1; +} + +static void off_cpu_finish(void *arg __maybe_unused) +{ + skel->bss->enabled = 0; + off_cpu_bpf__destroy(skel); +} + +int off_cpu_prepare(struct evlist *evlist) +{ + int err; + + if (off_cpu_config(evlist) < 0) { + pr_err("Failed to config off-cpu BPF event\n"); + return -1; + } + + set_max_rlimit(); + + skel = off_cpu_bpf__open_and_load(); + if (!skel) { + pr_err("Failed to open off-cpu BPF skeleton\n"); + return -1; + } + + err = off_cpu_bpf__attach(skel); + if (err) { + pr_err("Failed to attach off-cpu BPF skeleton\n"); + goto out; + } + + if (perf_hooks__set_hook("record_start", off_cpu_start, NULL) || + perf_hooks__set_hook("record_end", off_cpu_finish, NULL)) { + pr_err("Failed to attach off-cpu skeleton\n"); + goto out; + } + + return 0; + +out: + off_cpu_bpf__destroy(skel); + return -1; +} + +int off_cpu_write(struct perf_session *session) +{ + int bytes = 0, size; + int fd, stack; + u64 sample_type, val, sid = 0; + struct evsel *evsel; + struct perf_data_file *file = &session->data->file; + struct off_cpu_key prev, key; + union off_cpu_data data = { + .hdr = { + .type = PERF_RECORD_SAMPLE, + .misc = PERF_RECORD_MISC_USER, + }, + }; + u64 tstamp = OFF_CPU_TIMESTAMP; + + skel->bss->enabled = 0; + + evsel = evlist__find_evsel_by_str(session->evlist, OFFCPU_EVENT); + if (evsel == NULL) { + pr_err("%s evsel not found\n", OFFCPU_EVENT); + return 0; + } + + sample_type = evsel->core.attr.sample_type; + + if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER)) { + if (evsel->core.id) + sid = evsel->core.id[0]; + } + + fd = bpf_map__fd(skel->maps.off_cpu); + stack = bpf_map__fd(skel->maps.stacks); + memset(&prev, 0, sizeof(prev)); + + while (!bpf_map_get_next_key(fd, &prev, &key)) { + int n = 1; /* start from perf_event_header */ + int ip_pos = -1; + + bpf_map_lookup_elem(fd, &key, &val); + + if (sample_type & PERF_SAMPLE_IDENTIFIER) + data.array[n++] = sid; + if (sample_type & PERF_SAMPLE_IP) { + ip_pos = n; + data.array[n++] = 0; /* will be updated */ + } + if (sample_type & PERF_SAMPLE_TID) + data.array[n++] = (u64)key.pid << 32 | key.tgid; + if (sample_type & PERF_SAMPLE_TIME) + data.array[n++] = tstamp; + if (sample_type & PERF_SAMPLE_ID) + data.array[n++] = sid; + if (sample_type & PERF_SAMPLE_CPU) + data.array[n++] = 0; + if (sample_type & PERF_SAMPLE_PERIOD) + data.array[n++] = val; + if (sample_type & PERF_SAMPLE_CALLCHAIN) { + int len = 0; + + /* data.array[n] is callchain->nr (updated later) */ + data.array[n + 1] = PERF_CONTEXT_USER; + data.array[n + 2] = 0; + + bpf_map_lookup_elem(stack, &key.stack_id, &data.array[n + 2]); + while (data.array[n + 2 + len]) + len++; + + /* update length of callchain */ + data.array[n] = len + 1; + + /* update sample ip with the first callchain entry */ + if (ip_pos >= 0) + data.array[ip_pos] = data.array[n + 2]; + + /* calculate sample callchain data array length */ + n += len + 2; + } + /* TODO: handle more sample types */ + + size = n * sizeof(u64); + data.hdr.size = size; + bytes += size; + + if (perf_data_file__write(file, &data, size) < 0) { + pr_err("failed to write perf data, error: %m\n"); + return bytes; + } + + prev = key; + /* increase dummy timestamp to sort later samples */ + tstamp++; + } + return bytes; +} diff --git a/tools/perf/util/bpf_skel/off_cpu.bpf.c b/tools/perf/util/bpf_skel/off_cpu.bpf.c new file mode 100644 index 000000000000..5173ed882fdf --- /dev/null +++ b/tools/perf/util/bpf_skel/off_cpu.bpf.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +// Copyright (c) 2022 Google +#include "vmlinux.h" +#include +#include +#include + +/* task->flags for off-cpu analysis */ +#define PF_KTHREAD 0x00200000 /* I am a kernel thread */ + +/* task->state for off-cpu analysis */ +#define TASK_INTERRUPTIBLE 0x0001 +#define TASK_UNINTERRUPTIBLE 0x0002 + +#define MAX_STACKS 32 +#define MAX_ENTRIES 102400 + +struct tstamp_data { + __u32 stack_id; + __u32 state; + __u64 timestamp; +}; + +struct offcpu_key { + __u32 pid; + __u32 tgid; + __u32 stack_id; + __u32 state; +}; + +struct { + __uint(type, BPF_MAP_TYPE_STACK_TRACE); + __uint(key_size, sizeof(__u32)); + __uint(value_size, MAX_STACKS * sizeof(__u64)); + __uint(max_entries, MAX_ENTRIES); +} stacks SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_TASK_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, struct tstamp_data); +} tstamp SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(struct offcpu_key)); + __uint(value_size, sizeof(__u64)); + __uint(max_entries, MAX_ENTRIES); +} off_cpu SEC(".maps"); + +/* old kernel task_struct definition */ +struct task_struct___old { + long state; +} __attribute__((preserve_access_index)); + +int enabled = 0; + +/* + * Old kernel used to call it task_struct->state and now it's '__state'. + * Use BPF CO-RE "ignored suffix rule" to deal with it like below: + * + * https://nakryiko.com/posts/bpf-core-reference-guide/#handling-incompatible-field-and-type-changes + */ +static inline int get_task_state(struct task_struct *t) +{ + if (bpf_core_field_exists(t->__state)) + return BPF_CORE_READ(t, __state); + + /* recast pointer to capture task_struct___old type for compiler */ + struct task_struct___old *t_old = (void *)t; + + /* now use old "state" name of the field */ + return BPF_CORE_READ(t_old, state); +} + +SEC("tp_btf/sched_switch") +int on_switch(u64 *ctx) +{ + __u64 ts; + int state; + __u32 stack_id; + struct task_struct *prev, *next; + struct tstamp_data *pelem; + + if (!enabled) + return 0; + + prev = (struct task_struct *)ctx[1]; + next = (struct task_struct *)ctx[2]; + state = get_task_state(prev); + + ts = bpf_ktime_get_ns(); + + if (prev->flags & PF_KTHREAD) + goto next; + if (state != TASK_INTERRUPTIBLE && + state != TASK_UNINTERRUPTIBLE) + goto next; + + stack_id = bpf_get_stackid(ctx, &stacks, + BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK); + + pelem = bpf_task_storage_get(&tstamp, prev, NULL, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!pelem) + goto next; + + pelem->timestamp = ts; + pelem->state = state; + pelem->stack_id = stack_id; + +next: + pelem = bpf_task_storage_get(&tstamp, next, NULL, 0); + + if (pelem && pelem->timestamp) { + struct offcpu_key key = { + .pid = next->pid, + .tgid = next->tgid, + .stack_id = pelem->stack_id, + .state = pelem->state, + }; + __u64 delta = ts - pelem->timestamp; + __u64 *total; + + total = bpf_map_lookup_elem(&off_cpu, &key); + if (total) + *total += delta; + else + bpf_map_update_elem(&off_cpu, &key, &delta, BPF_ANY); + + /* prevent to reuse the timestamp later */ + pelem->timestamp = 0; + } + + return 0; +} + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; diff --git a/tools/perf/util/off_cpu.h b/tools/perf/util/off_cpu.h new file mode 100644 index 000000000000..375d03c424ea --- /dev/null +++ b/tools/perf/util/off_cpu.h @@ -0,0 +1,24 @@ +#ifndef PERF_UTIL_OFF_CPU_H +#define PERF_UTIL_OFF_CPU_H + +struct evlist; +struct perf_session; + +#define OFFCPU_EVENT "offcpu-time" + +#ifdef HAVE_BPF_SKEL +int off_cpu_prepare(struct evlist *evlist); +int off_cpu_write(struct perf_session *session); +#else +static inline int off_cpu_prepare(struct evlist *evlist __maybe_unused) +{ + return -1; +} + +static inline int off_cpu_write(struct perf_session *session __maybe_unused) +{ + return -1; +} +#endif + +#endif /* PERF_UTIL_OFF_CPU_H */ From patchwork Wed May 18 22:47:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 12854205 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9EF19C433EF for ; Wed, 18 May 2022 22:47:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229718AbiERWrm (ORCPT ); Wed, 18 May 2022 18:47:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36474 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230242AbiERWrg (ORCPT ); Wed, 18 May 2022 18:47:36 -0400 Received: from mail-pg1-x536.google.com (mail-pg1-x536.google.com [IPv6:2607:f8b0:4864:20::536]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 36801F68A7; Wed, 18 May 2022 15:47:32 -0700 (PDT) Received: by mail-pg1-x536.google.com with SMTP id h186so3428394pgc.3; Wed, 18 May 2022 15:47:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6/vKyzls7syv00DbTMSXJKHt/yE06QGrFeT+BAiim5I=; b=B+PqxvLVuo7JR62fdK74JSKwXF0yOd8vPTRoOe7kLQPrv2EAkm8iGEv7UkD9s2Lsaq kT3hV15fEuBypK8aZnQfFF8ZLBGGHSKAbpYfymFEC50tLgzx6ORuOZUOE1KFeEaXhz6D Xu1UU2K3R38oPWFQIb4M4ffJLWX2dKuZ4tF6BHtUtdcIIkCFlYVTJdlk4lht/NN/OFno 3J/HxwGmk7hukbcxOIYuzOxvJ8//6bHzhaIypYZrRntxd9osRqYc+XMIDYNiJiwU3f/Y BybVYK0MAZPLf1LExTjp0bybT9vWImwmc+EIfK4kcE4e3ZFppgoZ0hn/FEfBnGFvt4Qb /v6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=6/vKyzls7syv00DbTMSXJKHt/yE06QGrFeT+BAiim5I=; b=aY5ZJULj4aRrgKSI+HO5mdznOTeKcEDoztmjwRf8HCHdT3x8aCr42MtieMeEo/5BIF 3lu+Go+gz9svxmUdN/xOOifM8Wip0jETThAiwn3njuKGjYjlJxmjU5UNC6kHWvsQyMak Sk2fCvyA4Tt+kOJhmiIFUDFoQk7cBB9CXEW/7w+vMTTwG+7mwmOGzNkiqXxhPJnYwWsH 0dwyyWHq3HGxhXlf6oHrPLjDB6YtWs6pfG26Q6gT8vNXBCjn9mO/WfsQWW+v54OjHzov MN49eym89IUCJrGtOyCjJfo4QEYvYmxmk57Tm7joQw+bMTZupu8aWWJ2dTBAQk+uCBY5 fRrQ== X-Gm-Message-State: AOAM53069WcZ7er3mowboEVfXDzzPdGAm227nEMLCascJCxfL5C1gX53 gPNuoJueHK7kr09tAIqDq7U= X-Google-Smtp-Source: ABdhPJxv8Q2CtbizcugUZbgc+ae3NHGmBDrEGzA2CQleVUsGJPaMd94wAq20h9xVRFiR6JP4Sopidg== X-Received: by 2002:a63:5f4a:0:b0:3f5:d34e:dd44 with SMTP id t71-20020a635f4a000000b003f5d34edd44mr1346184pgb.567.1652914051587; Wed, 18 May 2022 15:47:31 -0700 (PDT) Received: from balhae.corp.google.com ([2620:15c:2c1:200:a718:cbfe:31cb:3a04]) by smtp.gmail.com with ESMTPSA id d23-20020a170902aa9700b0015e8d4eb2besm2214100plr.264.2022.05.18.15.47.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 May 2022 15:47:31 -0700 (PDT) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa Cc: Ingo Molnar , Peter Zijlstra , LKML , Andi Kleen , Ian Rogers , Song Liu , Hao Luo , Milian Wolff , bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Blake Jones Subject: [PATCH 3/6] perf record: Implement basic filtering for off-cpu Date: Wed, 18 May 2022 15:47:22 -0700 Message-Id: <20220518224725.742882-4-namhyung@kernel.org> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog In-Reply-To: <20220518224725.742882-1-namhyung@kernel.org> References: <20220518224725.742882-1-namhyung@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org It should honor cpu and task filtering with -a, -C or -p, -t options. Signed-off-by: Namhyung Kim --- tools/perf/builtin-record.c | 2 +- tools/perf/util/bpf_off_cpu.c | 78 +++++++++++++++++++++++--- tools/perf/util/bpf_skel/off_cpu.bpf.c | 52 +++++++++++++++-- tools/perf/util/off_cpu.h | 6 +- 4 files changed, 123 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 91f88501412e..7f60d2eac0b4 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -907,7 +907,7 @@ static int record__config_text_poke(struct evlist *evlist) static int record__config_off_cpu(struct record *rec) { - return off_cpu_prepare(rec->evlist); + return off_cpu_prepare(rec->evlist, &rec->opts.target); } static bool record__kcore_readable(struct machine *machine) diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c index 9ed7aca3f4ac..b5e2d038da50 100644 --- a/tools/perf/util/bpf_off_cpu.c +++ b/tools/perf/util/bpf_off_cpu.c @@ -6,6 +6,9 @@ #include "util/off_cpu.h" #include "util/perf-hooks.h" #include "util/session.h" +#include "util/target.h" +#include "util/cpumap.h" +#include "util/thread_map.h" #include #include "bpf_skel/off_cpu.skel.h" @@ -60,8 +63,23 @@ static int off_cpu_config(struct evlist *evlist) return 0; } -static void off_cpu_start(void *arg __maybe_unused) +static void off_cpu_start(void *arg) { + struct evlist *evlist = arg; + + /* update task filter for the given workload */ + if (!skel->bss->has_cpu && !skel->bss->has_task && + perf_thread_map__pid(evlist->core.threads, 0) != -1) { + int fd; + u32 pid; + u8 val = 1; + + skel->bss->has_task = 1; + fd = bpf_map__fd(skel->maps.task_filter); + pid = perf_thread_map__pid(evlist->core.threads, 0); + bpf_map_update_elem(fd, &pid, &val, BPF_ANY); + } + skel->bss->enabled = 1; } @@ -71,31 +89,75 @@ static void off_cpu_finish(void *arg __maybe_unused) off_cpu_bpf__destroy(skel); } -int off_cpu_prepare(struct evlist *evlist) +int off_cpu_prepare(struct evlist *evlist, struct target *target) { - int err; + int err, fd, i; + int ncpus = 1, ntasks = 1; if (off_cpu_config(evlist) < 0) { pr_err("Failed to config off-cpu BPF event\n"); return -1; } - set_max_rlimit(); - - skel = off_cpu_bpf__open_and_load(); + skel = off_cpu_bpf__open(); if (!skel) { pr_err("Failed to open off-cpu BPF skeleton\n"); return -1; } + /* don't need to set cpu filter for system-wide mode */ + if (target->cpu_list) { + ncpus = perf_cpu_map__nr(evlist->core.user_requested_cpus); + bpf_map__set_max_entries(skel->maps.cpu_filter, ncpus); + } + + if (target__has_task(target)) { + ntasks = perf_thread_map__nr(evlist->core.threads); + bpf_map__set_max_entries(skel->maps.task_filter, ntasks); + } + + set_max_rlimit(); + + err = off_cpu_bpf__load(skel); + if (err) { + pr_err("Failed to load off-cpu skeleton\n"); + goto out; + } + + if (target->cpu_list) { + u32 cpu; + u8 val = 1; + + skel->bss->has_cpu = 1; + fd = bpf_map__fd(skel->maps.cpu_filter); + + for (i = 0; i < ncpus; i++) { + cpu = perf_cpu_map__cpu(evlist->core.user_requested_cpus, i).cpu; + bpf_map_update_elem(fd, &cpu, &val, BPF_ANY); + } + } + + if (target__has_task(target)) { + u32 pid; + u8 val = 1; + + skel->bss->has_task = 1; + fd = bpf_map__fd(skel->maps.task_filter); + + for (i = 0; i < ntasks; i++) { + pid = perf_thread_map__pid(evlist->core.threads, i); + bpf_map_update_elem(fd, &pid, &val, BPF_ANY); + } + } + err = off_cpu_bpf__attach(skel); if (err) { pr_err("Failed to attach off-cpu BPF skeleton\n"); goto out; } - if (perf_hooks__set_hook("record_start", off_cpu_start, NULL) || - perf_hooks__set_hook("record_end", off_cpu_finish, NULL)) { + if (perf_hooks__set_hook("record_start", off_cpu_start, evlist) || + perf_hooks__set_hook("record_end", off_cpu_finish, evlist)) { pr_err("Failed to attach off-cpu skeleton\n"); goto out; } diff --git a/tools/perf/util/bpf_skel/off_cpu.bpf.c b/tools/perf/util/bpf_skel/off_cpu.bpf.c index 5173ed882fdf..78cdcc8ff863 100644 --- a/tools/perf/util/bpf_skel/off_cpu.bpf.c +++ b/tools/perf/util/bpf_skel/off_cpu.bpf.c @@ -49,12 +49,28 @@ struct { __uint(max_entries, MAX_ENTRIES); } off_cpu SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} cpu_filter SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} task_filter SEC(".maps"); + /* old kernel task_struct definition */ struct task_struct___old { long state; } __attribute__((preserve_access_index)); int enabled = 0; +int has_cpu = 0; +int has_task = 0; /* * Old kernel used to call it task_struct->state and now it's '__state'. @@ -74,6 +90,37 @@ static inline int get_task_state(struct task_struct *t) return BPF_CORE_READ(t_old, state); } +static inline int can_record(struct task_struct *t, int state) +{ + /* kernel threads don't have user stack */ + if (t->flags & PF_KTHREAD) + return 0; + + if (state != TASK_INTERRUPTIBLE && + state != TASK_UNINTERRUPTIBLE) + return 0; + + if (has_cpu) { + __u32 cpu = bpf_get_smp_processor_id(); + __u8 *ok; + + ok = bpf_map_lookup_elem(&cpu_filter, &cpu); + if (!ok) + return 0; + } + + if (has_task) { + __u8 *ok; + __u32 pid = t->pid; + + ok = bpf_map_lookup_elem(&task_filter, &pid); + if (!ok) + return 0; + } + + return 1; +} + SEC("tp_btf/sched_switch") int on_switch(u64 *ctx) { @@ -92,10 +139,7 @@ int on_switch(u64 *ctx) ts = bpf_ktime_get_ns(); - if (prev->flags & PF_KTHREAD) - goto next; - if (state != TASK_INTERRUPTIBLE && - state != TASK_UNINTERRUPTIBLE) + if (!can_record(prev, state)) goto next; stack_id = bpf_get_stackid(ctx, &stacks, diff --git a/tools/perf/util/off_cpu.h b/tools/perf/util/off_cpu.h index 375d03c424ea..f47af0232e55 100644 --- a/tools/perf/util/off_cpu.h +++ b/tools/perf/util/off_cpu.h @@ -2,15 +2,17 @@ #define PERF_UTIL_OFF_CPU_H struct evlist; +struct target; struct perf_session; #define OFFCPU_EVENT "offcpu-time" #ifdef HAVE_BPF_SKEL -int off_cpu_prepare(struct evlist *evlist); +int off_cpu_prepare(struct evlist *evlist, struct target *target); int off_cpu_write(struct perf_session *session); #else -static inline int off_cpu_prepare(struct evlist *evlist __maybe_unused) +static inline int off_cpu_prepare(struct evlist *evlist __maybe_unused, + struct target *target __maybe_unused) { return -1; } From patchwork Wed May 18 22:47:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 12854208 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 17631C433F5 for ; Wed, 18 May 2022 22:47:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230267AbiERWru (ORCPT ); Wed, 18 May 2022 18:47:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36806 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230223AbiERWrk (ORCPT ); Wed, 18 May 2022 18:47:40 -0400 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6105C149159; Wed, 18 May 2022 15:47:33 -0700 (PDT) Received: by mail-pj1-x102d.google.com with SMTP id pq9-20020a17090b3d8900b001df622bf81dso3472815pjb.3; Wed, 18 May 2022 15:47:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=a//VlMypHjw3Cd3kRCT2B/bQ9DLIRsRYt3Pyz9Ujkpg=; b=YBYFZ/HvKpKBW/+JVtbbfEKcS2R2W4ZNR0VeUUy7ohJ4KL2IYUcVQdb9Bgu0b3f/z8 jHamO32CcL0CgE2Vx22F9uiRtbXH+IzcVodBigYZrX4og4YUlgTh/S2a00Aa3HMFj2IR bRILlt23gobg6JnYzZyJOsiAUD02Pq9d2n81Qg5RUr2hoHUFngb87OYuT8Mxv6EjR52w WpTsNg3wVO05oW3LH7ajZW4C4aIujPMMRd3sI3e4AYRkJVshFViQi+4SrevFCtWmhiID hdYr5gCJ6HnTzd5ffQTZ6uYwyD58c+d2LwGPpaErP0Y2QVPkpK6PyCCVnqbU/h5QnjNS Yf4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=a//VlMypHjw3Cd3kRCT2B/bQ9DLIRsRYt3Pyz9Ujkpg=; b=GES2ewEMbMXCr5DQIyBWli193uxRZ6/JjMEgL9HItM1vbeyPMSxXbpeKeu8Xe5jf84 QGZo4nO58sfD0r4tnl270YL8NLxSBNo0IGTZ4QjUN2WALEaD499NioPaiouGGJ4UNDsU x7ZULF8FKgpXj3b75TuSBMjxDTmC144SArqXQQIk+uDpea0QYHpCQwsFJ58RF6k7Iy7b ARJZDJh4kTeZz6uzkkIP45cDbkCP3odQaeWkufqPTdUqgUqPj6jd46kI/j/37/lji3f3 zZysp3mbgnMGQEciLZAXbFmZY6ILlD0ILQtP8w5ttHqXNyuRezwfpeZjuELl3DaS1LYX MFEA== X-Gm-Message-State: AOAM532gqVsiekPCdh43TXipguqNSJ/zBhTHmgo5vf7lgZ1NarWtdBot tvc1DV+FosYdcsrUWSUQe/g= X-Google-Smtp-Source: ABdhPJxavr7kpoXACNuQHWfwF2pWztidKf2V9Ygml/ydeRNTl4FO2a+wJrFpk9GfDkDz9G/qTU9T8w== X-Received: by 2002:a17:903:230b:b0:15e:bc9c:18c7 with SMTP id d11-20020a170903230b00b0015ebc9c18c7mr1803429plh.29.1652914052889; Wed, 18 May 2022 15:47:32 -0700 (PDT) Received: from balhae.corp.google.com ([2620:15c:2c1:200:a718:cbfe:31cb:3a04]) by smtp.gmail.com with ESMTPSA id d23-20020a170902aa9700b0015e8d4eb2besm2214100plr.264.2022.05.18.15.47.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 May 2022 15:47:32 -0700 (PDT) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa Cc: Ingo Molnar , Peter Zijlstra , LKML , Andi Kleen , Ian Rogers , Song Liu , Hao Luo , Milian Wolff , bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Blake Jones Subject: [PATCH 4/6] perf record: Handle argument change in sched_switch Date: Wed, 18 May 2022 15:47:23 -0700 Message-Id: <20220518224725.742882-5-namhyung@kernel.org> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog In-Reply-To: <20220518224725.742882-1-namhyung@kernel.org> References: <20220518224725.742882-1-namhyung@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Recently sched_switch tracepoint added a new argument for prev_state, but it's hard to handle the change in a BPF program. Instead, we can check the function prototype in BTF before loading the program. Signed-off-by: Namhyung Kim Acked-by: Ian Rogers --- tools/perf/util/bpf_off_cpu.c | 28 +++++++++++++++++++++ tools/perf/util/bpf_skel/off_cpu.bpf.c | 35 ++++++++++++++++++-------- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c index b5e2d038da50..874856c55101 100644 --- a/tools/perf/util/bpf_off_cpu.c +++ b/tools/perf/util/bpf_off_cpu.c @@ -89,6 +89,33 @@ static void off_cpu_finish(void *arg __maybe_unused) off_cpu_bpf__destroy(skel); } +/* v5.18 kernel added prev_state arg, so it needs to check the signature */ +static void check_sched_switch_args(void) +{ + const struct btf *btf = bpf_object__btf(skel->obj); + const struct btf_type *t1, *t2, *t3; + u32 type_id; + + type_id = btf__find_by_name_kind(btf, "bpf_trace_sched_switch", + BTF_KIND_TYPEDEF); + if ((s32)type_id < 0) + return; + + t1 = btf__type_by_id(btf, type_id); + if (t1 == NULL) + return; + + t2 = btf__type_by_id(btf, t1->type); + if (t2 == NULL || !btf_is_ptr(t2)) + return; + + t3 = btf__type_by_id(btf, t2->type); + if (t3 && btf_is_func_proto(t3) && btf_vlen(t3) == 4) { + /* new format: pass prev_state as 4th arg */ + skel->rodata->has_prev_state = true; + } +} + int off_cpu_prepare(struct evlist *evlist, struct target *target) { int err, fd, i; @@ -117,6 +144,7 @@ int off_cpu_prepare(struct evlist *evlist, struct target *target) } set_max_rlimit(); + check_sched_switch_args(); err = off_cpu_bpf__load(skel); if (err) { diff --git a/tools/perf/util/bpf_skel/off_cpu.bpf.c b/tools/perf/util/bpf_skel/off_cpu.bpf.c index 78cdcc8ff863..986d7db6e75d 100644 --- a/tools/perf/util/bpf_skel/off_cpu.bpf.c +++ b/tools/perf/util/bpf_skel/off_cpu.bpf.c @@ -72,6 +72,8 @@ int enabled = 0; int has_cpu = 0; int has_task = 0; +const volatile bool has_prev_state = false; + /* * Old kernel used to call it task_struct->state and now it's '__state'. * Use BPF CO-RE "ignored suffix rule" to deal with it like below: @@ -121,22 +123,13 @@ static inline int can_record(struct task_struct *t, int state) return 1; } -SEC("tp_btf/sched_switch") -int on_switch(u64 *ctx) +static int off_cpu_stat(u64 *ctx, struct task_struct *prev, + struct task_struct *next, int state) { __u64 ts; - int state; __u32 stack_id; - struct task_struct *prev, *next; struct tstamp_data *pelem; - if (!enabled) - return 0; - - prev = (struct task_struct *)ctx[1]; - next = (struct task_struct *)ctx[2]; - state = get_task_state(prev); - ts = bpf_ktime_get_ns(); if (!can_record(prev, state)) @@ -180,4 +173,24 @@ int on_switch(u64 *ctx) return 0; } +SEC("tp_btf/sched_switch") +int on_switch(u64 *ctx) +{ + struct task_struct *prev, *next; + int prev_state; + + if (!enabled) + return 0; + + prev = (struct task_struct *)ctx[1]; + next = (struct task_struct *)ctx[2]; + + if (has_prev_state) + prev_state = (int)ctx[3]; + else + prev_state = get_task_state(prev); + + return off_cpu_stat(ctx, prev, next, prev_state); +} + char LICENSE[] SEC("license") = "Dual BSD/GPL"; From patchwork Wed May 18 22:47:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 12854207 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C97EC433EF for ; Wed, 18 May 2022 22:47:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230335AbiERWrt (ORCPT ); Wed, 18 May 2022 18:47:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36284 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230225AbiERWrk (ORCPT ); Wed, 18 May 2022 18:47:40 -0400 Received: from mail-pl1-x630.google.com (mail-pl1-x630.google.com [IPv6:2607:f8b0:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A12DB14FC8F; Wed, 18 May 2022 15:47:34 -0700 (PDT) Received: by mail-pl1-x630.google.com with SMTP id bh5so3142102plb.6; Wed, 18 May 2022 15:47:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GNIxSJPL7uksAJMx/pU2JN81C2HBSsM0y7AnkRhp5zw=; b=IFb54PswqhNMOfbXf8vQPkueUIJZnvCMw2Ngi/rD581GYDmAzgUEDLtSx0792bhzbx e+pve0X9t8Eek8JFR1A598HKALYuWNDgFlHPiYhL8VYrYLzqNaL8JrlfwnhNjtIFk1Np 4X3I1+bo3U9TH6Gdndr8E1Bl/cDAwXWPeIiRn8xqzNlQ2Fc+1OLQ2YIKOVkgiHG14WQo 2VHnABsB/XKkTRwW8BfI/Ow46I+iU/V8trr80amOEyBmoCpCFkkQkxy0ndEouoYKh33L 1teumz6CmlwuMR7x4/hIA2urAZrG+USvO2ZVPNlEvZ2NjgqBMmGWiKwyTnB7386n1AXd lcxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=GNIxSJPL7uksAJMx/pU2JN81C2HBSsM0y7AnkRhp5zw=; b=kV7ESi1jDKriDTNbKWAfYWNRcsB+4gf6ZIkebzPEXP1BLVKM2ezxxk27zwmcTsL0pT swnVxWCPJnfcLhKfkWfc+lVHNBCt02LowLazlz620rgScUx+XIzTHp1t5VMMtZrCJVO9 eya7OyOlNAQbOqeUU0U4COOV58tZ2hnuB1xDWMgylquAq2rjse41mQmNILyXEDYE89ng U5ifoJBGByTmsS9p5jZXF7P93AAj/tur/P+P6GT14rSqGGjX9l0Q9l1IPyYM9tpTJNZL ZZzKZNxIvzIwHbdJTDqLritfscQVT3zC0OvxqKWoOuGnaGFhHVGNKqWMlneoK4JJaO5J qQTQ== X-Gm-Message-State: AOAM530uiWPLJXoxxJEHityZWOKj0aRJlVAtxG3nu3H578KGgHhXawZh coQirM+TnZaL74Ui/zRK/q4= X-Google-Smtp-Source: ABdhPJyBJDY0NlTKLSW6molk6ZiYvE+eLuBn/Y5rQKWZn4OcGjEsDEca0xpRqvsmPCfXHXoeqb3Ssg== X-Received: by 2002:a17:902:e74d:b0:15e:94f7:611e with SMTP id p13-20020a170902e74d00b0015e94f7611emr1641543plf.37.1652914054133; Wed, 18 May 2022 15:47:34 -0700 (PDT) Received: from balhae.corp.google.com ([2620:15c:2c1:200:a718:cbfe:31cb:3a04]) by smtp.gmail.com with ESMTPSA id d23-20020a170902aa9700b0015e8d4eb2besm2214100plr.264.2022.05.18.15.47.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 May 2022 15:47:33 -0700 (PDT) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa Cc: Ingo Molnar , Peter Zijlstra , LKML , Andi Kleen , Ian Rogers , Song Liu , Hao Luo , Milian Wolff , bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Blake Jones Subject: [PATCH 5/6] perf record: Add cgroup support for off-cpu profiling Date: Wed, 18 May 2022 15:47:24 -0700 Message-Id: <20220518224725.742882-6-namhyung@kernel.org> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog In-Reply-To: <20220518224725.742882-1-namhyung@kernel.org> References: <20220518224725.742882-1-namhyung@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org This covers two different use cases. The first one is cgroup filtering given by -G/--cgroup option which controls the off-cpu profiling for tasks in the given cgroups only. The other use case is cgroup sampling which is enabled by --all-cgroups option and it adds PERF_SAMPLE_CGROUP to the sample_type to set the cgroup id of the task in the sample data. Example output. $ sudo perf record -a --off-cpu --all-cgroups sleep 1 $ sudo perf report --stdio -s comm,cgroup --call-graph=no ... # Samples: 144 of event 'offcpu-time' # Event count (approx.): 48452045427 # # Children Self Command Cgroup # ........ ........ ............... .......................................... # 61.57% 5.60% Chrome_ChildIOT /user.slice/user-657345.slice/user@657345.service/app.slice/... 29.51% 7.38% Web Content /user.slice/user-657345.slice/user@657345.service/app.slice/... 17.48% 1.59% Chrome_IOThread /user.slice/user-657345.slice/user@657345.service/app.slice/... 16.48% 4.12% pipewire-pulse /user.slice/user-657345.slice/user@657345.service/session.slice/... 14.48% 2.07% perf /user.slice/user-657345.slice/user@657345.service/app.slice/... 14.30% 7.15% CompositorTileW /user.slice/user-657345.slice/user@657345.service/app.slice/... 13.33% 6.67% Timer /user.slice/user-657345.slice/user@657345.service/app.slice/... ... Signed-off-by: Namhyung Kim Acked-by: Ian Rogers --- tools/perf/builtin-record.c | 2 +- tools/perf/util/bpf_off_cpu.c | 48 ++++++++++++++++++++++++-- tools/perf/util/bpf_skel/off_cpu.bpf.c | 33 ++++++++++++++++++ tools/perf/util/off_cpu.h | 7 ++-- 4 files changed, 85 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 7f60d2eac0b4..77fa21c2c69f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -907,7 +907,7 @@ static int record__config_text_poke(struct evlist *evlist) static int record__config_off_cpu(struct record *rec) { - return off_cpu_prepare(rec->evlist, &rec->opts.target); + return off_cpu_prepare(rec->evlist, &rec->opts.target, &rec->opts); } static bool record__kcore_readable(struct machine *machine) diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c index 874856c55101..b73e84a02264 100644 --- a/tools/perf/util/bpf_off_cpu.c +++ b/tools/perf/util/bpf_off_cpu.c @@ -5,10 +5,12 @@ #include "util/evlist.h" #include "util/off_cpu.h" #include "util/perf-hooks.h" +#include "util/record.h" #include "util/session.h" #include "util/target.h" #include "util/cpumap.h" #include "util/thread_map.h" +#include "util/cgroup.h" #include #include "bpf_skel/off_cpu.skel.h" @@ -24,6 +26,7 @@ struct off_cpu_key { u32 tgid; u32 stack_id; u32 state; + u64 cgroup_id; }; union off_cpu_data { @@ -116,10 +119,11 @@ static void check_sched_switch_args(void) } } -int off_cpu_prepare(struct evlist *evlist, struct target *target) +int off_cpu_prepare(struct evlist *evlist, struct target *target, + struct record_opts *opts) { int err, fd, i; - int ncpus = 1, ntasks = 1; + int ncpus = 1, ntasks = 1, ncgrps = 1; if (off_cpu_config(evlist) < 0) { pr_err("Failed to config off-cpu BPF event\n"); @@ -143,6 +147,21 @@ int off_cpu_prepare(struct evlist *evlist, struct target *target) bpf_map__set_max_entries(skel->maps.task_filter, ntasks); } + if (evlist__first(evlist)->cgrp) { + ncgrps = evlist->core.nr_entries - 1; /* excluding a dummy */ + bpf_map__set_max_entries(skel->maps.cgroup_filter, ncgrps); + + if (!cgroup_is_v2("perf_event")) + skel->rodata->uses_cgroup_v1 = true; + } + + if (opts->record_cgroup) { + skel->rodata->needs_cgroup = true; + + if (!cgroup_is_v2("perf_event")) + skel->rodata->uses_cgroup_v1 = true; + } + set_max_rlimit(); check_sched_switch_args(); @@ -178,6 +197,29 @@ int off_cpu_prepare(struct evlist *evlist, struct target *target) } } + if (evlist__first(evlist)->cgrp) { + struct evsel *evsel; + u8 val = 1; + + skel->bss->has_cgroup = 1; + fd = bpf_map__fd(skel->maps.cgroup_filter); + + evlist__for_each_entry(evlist, evsel) { + struct cgroup *cgrp = evsel->cgrp; + + if (cgrp == NULL) + continue; + + if (!cgrp->id && read_cgroup_id(cgrp) < 0) { + pr_err("Failed to read cgroup id of %s\n", + cgrp->name); + goto out; + } + + bpf_map_update_elem(fd, &cgrp->id, &val, BPF_ANY); + } + } + err = off_cpu_bpf__attach(skel); if (err) { pr_err("Failed to attach off-cpu BPF skeleton\n"); @@ -275,6 +317,8 @@ int off_cpu_write(struct perf_session *session) /* calculate sample callchain data array length */ n += len + 2; } + if (sample_type & PERF_SAMPLE_CGROUP) + data.array[n++] = key.cgroup_id; /* TODO: handle more sample types */ size = n * sizeof(u64); diff --git a/tools/perf/util/bpf_skel/off_cpu.bpf.c b/tools/perf/util/bpf_skel/off_cpu.bpf.c index 986d7db6e75d..792ae2847080 100644 --- a/tools/perf/util/bpf_skel/off_cpu.bpf.c +++ b/tools/perf/util/bpf_skel/off_cpu.bpf.c @@ -26,6 +26,7 @@ struct offcpu_key { __u32 tgid; __u32 stack_id; __u32 state; + __u64 cgroup_id; }; struct { @@ -63,6 +64,13 @@ struct { __uint(max_entries, 1); } task_filter SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u64)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} cgroup_filter SEC(".maps"); + /* old kernel task_struct definition */ struct task_struct___old { long state; @@ -71,8 +79,11 @@ struct task_struct___old { int enabled = 0; int has_cpu = 0; int has_task = 0; +int has_cgroup = 0; const volatile bool has_prev_state = false; +const volatile bool needs_cgroup = false; +const volatile bool uses_cgroup_v1 = false; /* * Old kernel used to call it task_struct->state and now it's '__state'. @@ -92,6 +103,18 @@ static inline int get_task_state(struct task_struct *t) return BPF_CORE_READ(t_old, state); } +static inline __u64 get_cgroup_id(struct task_struct *t) +{ + struct cgroup *cgrp; + + if (uses_cgroup_v1) + cgrp = BPF_CORE_READ(t, cgroups, subsys[perf_event_cgrp_id], cgroup); + else + cgrp = BPF_CORE_READ(t, cgroups, dfl_cgrp); + + return BPF_CORE_READ(cgrp, kn, id); +} + static inline int can_record(struct task_struct *t, int state) { /* kernel threads don't have user stack */ @@ -120,6 +143,15 @@ static inline int can_record(struct task_struct *t, int state) return 0; } + if (has_cgroup) { + __u8 *ok; + __u64 cgrp_id = get_cgroup_id(t); + + ok = bpf_map_lookup_elem(&cgroup_filter, &cgrp_id); + if (!ok) + return 0; + } + return 1; } @@ -156,6 +188,7 @@ static int off_cpu_stat(u64 *ctx, struct task_struct *prev, .tgid = next->tgid, .stack_id = pelem->stack_id, .state = pelem->state, + .cgroup_id = needs_cgroup ? get_cgroup_id(next) : 0, }; __u64 delta = ts - pelem->timestamp; __u64 *total; diff --git a/tools/perf/util/off_cpu.h b/tools/perf/util/off_cpu.h index f47af0232e55..548008f74d42 100644 --- a/tools/perf/util/off_cpu.h +++ b/tools/perf/util/off_cpu.h @@ -4,15 +4,18 @@ struct evlist; struct target; struct perf_session; +struct record_opts; #define OFFCPU_EVENT "offcpu-time" #ifdef HAVE_BPF_SKEL -int off_cpu_prepare(struct evlist *evlist, struct target *target); +int off_cpu_prepare(struct evlist *evlist, struct target *target, + struct record_opts *opts); int off_cpu_write(struct perf_session *session); #else static inline int off_cpu_prepare(struct evlist *evlist __maybe_unused, - struct target *target __maybe_unused) + struct target *target __maybe_unused, + struct record_opts *opts __maybe_unused) { return -1; } From patchwork Wed May 18 22:47:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 12854209 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B37E7C433FE for ; Wed, 18 May 2022 22:47:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230274AbiERWrv (ORCPT ); Wed, 18 May 2022 18:47:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36850 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230259AbiERWrk (ORCPT ); Wed, 18 May 2022 18:47:40 -0400 Received: from mail-pg1-x533.google.com (mail-pg1-x533.google.com [IPv6:2607:f8b0:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CCD551660A9; Wed, 18 May 2022 15:47:35 -0700 (PDT) Received: by mail-pg1-x533.google.com with SMTP id a9so1398342pgv.12; Wed, 18 May 2022 15:47:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Z1uFAVp5XdqAsqLx9EOJ5fow9Z4hWpN//WzEgscyqLE=; b=fBLYm5nQkrulJpYuqInqIePkrrkle5Xz/TGqXIg7emfJIksvE5oo6jUTglIoDPl37F Taw0pNZU4Av4JhVBYDjpOAqrpBxKc9WXzckJnEgOSmPs6tgWHvmXeepIdbQx0odJO5uS UCY8HjLKxgYytwey/3wUVttqdsa85LrZBaLS6Yd5/cCmqSnaq/SYb9fq0fXe1v1oqxBK +htOZYS4h3n2aRsNyRVhsfwg6VoiWDIj62Ke5TnyGz+VO9gPQlnu7wGRaBFEoTXgSMkb lybadmtzGmFBrb89C9dS/uaq14UMWgieJnIPd3URaW+lHLIB1rQLElVu+tFnFAvHyjGk 1TsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=Z1uFAVp5XdqAsqLx9EOJ5fow9Z4hWpN//WzEgscyqLE=; b=mCx6eheHuEpbpqNbTs6OTTht1UGaa5K9CnFntgp8Yypq52YMaGil158irxNTRfylhM ofzSX/tFrKlmN1KN5erA0ztP5z5UX/XRtAEDNKwpQCYNMvVifCoG7BVj2qDWgIc2n8nN seLScRjnwhzKdgcfcAchcPfpjdHXDyq5G6Jht/IpKOVTyRcthOqJQotF59OLSdhCFVn0 uWSJuLZOTVlnSDR5MSf8Iid7Mu9XSsWcj37Kv2pS+o6dolAE8plVlX1O6z+HK+zBOfA1 8anN98NuMiM3nY3htrmXdgoXXzrRv0FUwPSxIBz3BOCvVbHRaB6XzOgjHI6cdmc7P7ue t2MA== X-Gm-Message-State: AOAM531L1PR0MOalbFXGmgV2YstX1hG4U+c+DogPvn00p+TQTAUCsemU 10fodBJ9lPacFQnbwvNfrF4= X-Google-Smtp-Source: ABdhPJwCafyFUhZ3nZq/yvh5UKIdujWhZkYuJ9C57bFPBhwiP9wXWuv4oXIaiSkjCGcqqZzgrHISFw== X-Received: by 2002:a05:6a00:2908:b0:4fa:9297:f631 with SMTP id cg8-20020a056a00290800b004fa9297f631mr1859997pfb.3.1652914055231; Wed, 18 May 2022 15:47:35 -0700 (PDT) Received: from balhae.corp.google.com ([2620:15c:2c1:200:a718:cbfe:31cb:3a04]) by smtp.gmail.com with ESMTPSA id d23-20020a170902aa9700b0015e8d4eb2besm2214100plr.264.2022.05.18.15.47.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 May 2022 15:47:34 -0700 (PDT) Sender: Namhyung Kim From: Namhyung Kim To: Arnaldo Carvalho de Melo , Jiri Olsa Cc: Ingo Molnar , Peter Zijlstra , LKML , Andi Kleen , Ian Rogers , Song Liu , Hao Luo , Milian Wolff , bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Blake Jones Subject: [PATCH 6/6] perf test: Add a basic offcpu profiling test Date: Wed, 18 May 2022 15:47:25 -0700 Message-Id: <20220518224725.742882-7-namhyung@kernel.org> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog In-Reply-To: <20220518224725.742882-1-namhyung@kernel.org> References: <20220518224725.742882-1-namhyung@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org $ sudo ./perf test -v offcpu 88: perf record offcpu profiling tests : --- start --- test child forked, pid 685966 Basic off-cpu test Basic off-cpu test [Success] test child finished with 0 ---- end ---- perf record offcpu profiling tests: Ok Signed-off-by: Namhyung Kim Acked-by: Ian Rogers --- tools/perf/tests/shell/record_offcpu.sh | 60 +++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100755 tools/perf/tests/shell/record_offcpu.sh diff --git a/tools/perf/tests/shell/record_offcpu.sh b/tools/perf/tests/shell/record_offcpu.sh new file mode 100755 index 000000000000..96e0739f7478 --- /dev/null +++ b/tools/perf/tests/shell/record_offcpu.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# perf record offcpu profiling tests +# SPDX-License-Identifier: GPL-2.0 + +set -e + +err=0 +perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) + +cleanup() { + rm -f ${perfdata} + rm -f ${perfdata}.old + trap - exit term int +} + +trap_cleanup() { + cleanup + exit 1 +} +trap trap_cleanup exit term int + +test_offcpu() { + echo "Basic off-cpu test" + if [ `id -u` != 0 ] + then + echo "Basic off-cpu test [Skipped permission]" + err=2 + return + fi + if perf record --off-cpu -o ${perfdata} --quiet true 2>&1 | grep BUILD_BPF_SKEL + then + echo "Basic off-cpu test [Skipped missing BPF support]" + err=2 + return + fi + if ! perf record --off-cpu -e dummy -o ${perfdata} sleep 1 2> /dev/null + then + echo "Basic off-cpu test [Failed record]" + err=1 + return + fi + if ! perf evlist -i ${perfdata} | grep -q "offcpu-time" + then + echo "Basic off-cpu test [Failed record]" + err=1 + return + fi + if ! perf report -i ${perfdata} -q --percent-limit=90 | egrep -q sleep + then + echo "Basic off-cpu test [Failed missing output]" + err=1 + return + fi + echo "Basic off-cpu test [Success]" +} + +test_offcpu + +cleanup +exit $err