diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c index 0a1832564dd2..e87b6789eb9e 100644 --- a/tools/perf/util/bpf-filter.c +++ b/tools/perf/util/bpf-filter.c @@ -100,6 +100,7 @@ static const struct perf_sample_info { PERF_SAMPLE_TYPE(TRANSACTION, "--transaction"), PERF_SAMPLE_TYPE(CODE_PAGE_SIZE, "--code-page-size"), PERF_SAMPLE_TYPE(DATA_PAGE_SIZE, "--data-page-size"), + PERF_SAMPLE_TYPE(CGROUP, "--all-cgroups"), }; static int get_pinned_fd(const char *name); diff --git a/tools/perf/util/bpf-filter.l b/tools/perf/util/bpf-filter.l index 2a7c839f3fae..f313404f95a9 100644 --- a/tools/perf/util/bpf-filter.l +++ b/tools/perf/util/bpf-filter.l @@ -9,8 +9,11 @@ #include "bpf-filter.h" #include "bpf-filter-bison.h" +extern int perf_bpf_filter_needs_path; + static int sample(enum perf_bpf_filter_term term) { + perf_bpf_filter_needs_path = 0; perf_bpf_filter_lval.sample.term = term; perf_bpf_filter_lval.sample.part = 0; return BFT_SAMPLE; @@ -18,11 +21,20 @@ static int sample(enum perf_bpf_filter_term term) static int sample_part(enum perf_bpf_filter_term term, int part) { + perf_bpf_filter_needs_path = 0; perf_bpf_filter_lval.sample.term = term; perf_bpf_filter_lval.sample.part = part; return BFT_SAMPLE; } +static int sample_path(enum perf_bpf_filter_term term) +{ + perf_bpf_filter_needs_path = 1; + perf_bpf_filter_lval.sample.term = term; + perf_bpf_filter_lval.sample.part = 0; + return BFT_SAMPLE_PATH; +} + static int operator(enum perf_bpf_filter_op op) { perf_bpf_filter_lval.op = op; @@ -48,10 +60,15 @@ static int constant(int val) return BFT_NUM; } -static int error(const char *str) +static int path_or_error(void) { - printf("perf_bpf_filter: Unexpected filter %s: %s\n", str, perf_bpf_filter_text); - return BFT_ERROR; + if (!perf_bpf_filter_needs_path) { + printf("perf_bpf_filter: Error: Unexpected item: %s\n", + perf_bpf_filter_text); + return BFT_ERROR; + } + perf_bpf_filter_lval.path = perf_bpf_filter_text; + return BFT_PATH; } %} @@ -59,6 +76,7 @@ static int error(const char *str) num_dec [0-9]+ num_hex 0[Xx][0-9a-fA-F]+ space [ \t]+ +path [^ \t\n]+ ident [_a-zA-Z][_a-zA-Z0-9]+ %% @@ -97,6 +115,7 @@ mem_blk { return sample_part(PBF_TERM_DATA_SRC, 7); } mem_hops { return sample_part(PBF_TERM_DATA_SRC, 8); } uid { return sample(PBF_TERM_UID); } gid { return sample(PBF_TERM_GID); } +cgroup { return sample_path(PBF_TERM_CGROUP); } "==" { return operator(PBF_OP_EQ); } "!=" { return operator(PBF_OP_NEQ); } @@ -155,7 +174,6 @@ hops3 { return constant(PERF_MEM_HOPS_3); } "," { return ','; } "||" { return BFT_LOGICAL_OR; } -{ident} { return error("ident"); } -. { return error("input"); } +{path} { return path_or_error(); } %% diff --git a/tools/perf/util/bpf-filter.y b/tools/perf/util/bpf-filter.y index 0c56fccb8874..5a79a8e7a45b 100644 --- a/tools/perf/util/bpf-filter.y +++ b/tools/perf/util/bpf-filter.y @@ -12,9 +12,13 @@ #include #include #include "bpf-filter.h" +#include "cgroup.h" int perf_bpf_filter_lex(void); +/* To indicate if the current term needs a pathname or not */ +int perf_bpf_filter_needs_path; + static void perf_bpf_filter_error(struct list_head *expr __maybe_unused, char const *msg) { @@ -26,6 +30,7 @@ static void perf_bpf_filter_error(struct list_head *expr __maybe_unused, %union { unsigned long num; + char *path; struct { enum perf_bpf_filter_term term; int part; @@ -34,12 +39,13 @@ static void perf_bpf_filter_error(struct list_head *expr __maybe_unused, struct perf_bpf_filter_expr *expr; } -%token BFT_SAMPLE BFT_OP BFT_ERROR BFT_NUM BFT_LOGICAL_OR +%token BFT_SAMPLE BFT_SAMPLE_PATH BFT_OP BFT_ERROR BFT_NUM BFT_LOGICAL_OR BFT_PATH %type filter_term filter_expr %destructor { free ($$); } -%type BFT_SAMPLE +%type BFT_SAMPLE BFT_SAMPLE_PATH %type BFT_OP %type BFT_NUM +%type BFT_PATH %% @@ -81,5 +87,23 @@ BFT_SAMPLE BFT_OP BFT_NUM { $$ = perf_bpf_filter_expr__new($1.term, $1.part, $2, $3); } +| +BFT_SAMPLE_PATH BFT_OP BFT_PATH +{ + struct cgroup *cgrp; + unsigned long cgroup_id = 0; + + if ($2 != PBF_OP_EQ && $2 != PBF_OP_NEQ) { + printf("perf_bpf_filter: cgroup accepts '==' or '!=' only\n"); + YYERROR; + } + + cgrp = cgroup__new($3, /*do_open=*/false); + if (cgrp && read_cgroup_id(cgrp) == 0) + cgroup_id = cgrp->id; + + $$ = perf_bpf_filter_expr__new($1.term, $1.part, $2, cgroup_id); + cgroup__put(cgrp); +} %% diff --git a/tools/perf/util/bpf_skel/sample-filter.h b/tools/perf/util/bpf_skel/sample-filter.h index 5f0c8e4e83d3..683fec85e71e 100644 --- a/tools/perf/util/bpf_skel/sample-filter.h +++ b/tools/perf/util/bpf_skel/sample-filter.h @@ -45,7 +45,7 @@ enum perf_bpf_filter_term { __PBF_UNUSED_TERM18 = PBF_TERM_SAMPLE_START + 18, /* SAMPLE_REGS_INTR = 1U << 18 */ PBF_TERM_PHYS_ADDR = PBF_TERM_SAMPLE_START + 19, /* SAMPLE_PHYS_ADDR = 1U << 19 */ __PBF_UNUSED_TERM20 = PBF_TERM_SAMPLE_START + 20, /* SAMPLE_AUX = 1U << 20 */ - __PBF_UNUSED_TERM21 = PBF_TERM_SAMPLE_START + 21, /* SAMPLE_CGROUP = 1U << 21 */ + PBF_TERM_CGROUP = PBF_TERM_SAMPLE_START + 21, /* SAMPLE_CGROUP = 1U << 21 */ PBF_TERM_DATA_PAGE_SIZE = PBF_TERM_SAMPLE_START + 22, /* SAMPLE_DATA_PAGE_SIZE = 1U << 22 */ PBF_TERM_CODE_PAGE_SIZE = PBF_TERM_SAMPLE_START + 23, /* SAMPLE_CODE_PAGE_SIZE = 1U << 23 */ PBF_TERM_WEIGHT_STRUCT = PBF_TERM_SAMPLE_START + 24, /* SAMPLE_WEIGHT_STRUCT = 1U << 24 */ diff --git a/tools/perf/util/bpf_skel/sample_filter.bpf.c b/tools/perf/util/bpf_skel/sample_filter.bpf.c index 4872a16eedfd..b195e6efeb8b 100644 --- a/tools/perf/util/bpf_skel/sample_filter.bpf.c +++ b/tools/perf/util/bpf_skel/sample_filter.bpf.c @@ -93,6 +93,7 @@ static inline __u64 perf_get_sample(struct bpf_perf_event_data_kern *kctx, BUILD_CHECK_SAMPLE(DATA_SRC); BUILD_CHECK_SAMPLE(TRANSACTION); BUILD_CHECK_SAMPLE(PHYS_ADDR); + BUILD_CHECK_SAMPLE(CGROUP); BUILD_CHECK_SAMPLE(DATA_PAGE_SIZE); BUILD_CHECK_SAMPLE(CODE_PAGE_SIZE); BUILD_CHECK_SAMPLE(WEIGHT_STRUCT); @@ -135,6 +136,8 @@ static inline __u64 perf_get_sample(struct bpf_perf_event_data_kern *kctx, return kctx->data->weight.full; case PBF_TERM_PHYS_ADDR: return kctx->data->phys_addr; + case PBF_TERM_CGROUP: + return kctx->data->cgroup; case PBF_TERM_CODE_PAGE_SIZE: return kctx->data->code_page_size; case PBF_TERM_DATA_PAGE_SIZE: @@ -183,7 +186,6 @@ static inline __u64 perf_get_sample(struct bpf_perf_event_data_kern *kctx, case __PBF_UNUSED_TERM16: case __PBF_UNUSED_TERM18: case __PBF_UNUSED_TERM20: - case __PBF_UNUSED_TERM21: default: break; } diff --git a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h index 4fa21468487e..4dcad7b682bd 100644 --- a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h +++ b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h @@ -171,6 +171,7 @@ struct perf_sample_data { u32 cpu; } cpu_entry; u64 phys_addr; + u64 cgroup; u64 data_page_size; u64 code_page_size; } __attribute__((__aligned__(64))) __attribute__((preserve_access_index));