perf bpf filter: Add data_src sample data support
authorNamhyung Kim <namhyung@kernel.org>
Tue, 14 Mar 2023 23:42:34 +0000 (16:42 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 15 Mar 2023 14:08:36 +0000 (11:08 -0300)
The data_src has many entries to express memory behaviors.  Add each
term separately so that users can combine them for their purpose.

I didn't add prefix for the constants for simplicity as they are mostly
distinguishable but I had to use l1_miss and l2_hit for mem_dtlb since
mem_lvl has different values for the same names.  Note that I decided
mem_lvl to be used as an alias of mem_lvlnum as it's deprecated now.
According to the comment in the UAPI header, users should use the mix of
mem_lvlnum, mem_remote and mem_snoop.  Also the SNOOPX bits are
concatenated to mem_snoop for simplicity.

The following terms are used for data_src and the corresponding perf
sample data fields:

 * mem_op : { load, store, pfetch, exec }
 * mem_lvl: { l1, l2, l3, l4, cxl, io, any_cache, lfb, ram, pmem }
 * mem_snoop: { none, hit, miss, hitm, fwd, peer }
 * mem_remote: { remote }
 * mem_lock: { locked }
 * mem_dtlb { l1_hit, l1_miss, l2_hit, l2_miss, any_hit, any_miss, walk, fault }
 * mem_blk { by_data, by_addr }
 * mem_hops { hops0, hops1, hops2, hops3 }

We can now use a filter expression like below:

  'mem_op == load, mem_lvl <= l2, mem_dtlb == l1_hit'
  'mem_dtlb == l2_miss, mem_hops > hops1'
  'mem_lvl == ram, mem_remote == 1'

Note that 'na' is shared among the terms as it has the same value except
for mem_lvl.  I don't have a good idea to handle that for now.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: James Clark <james.clark@arm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Song Liu <song@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: bpf@vger.kernel.org
Link: https://lore.kernel.org/r/20230314234237.3008956-2-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/bpf-filter.l
tools/perf/util/bpf_skel/sample_filter.bpf.c

index 419f923..3e66b7a 100644 (file)
@@ -42,6 +42,12 @@ static int value(int base)
        return BFT_NUM;
 }
 
+static int constant(int val)
+{
+       perf_bpf_filter_lval.num = val;
+       return BFT_NUM;
+}
+
 static int error(const char *str)
 {
        printf("perf_bpf_filter: Unexpected filter %s: %s\n", str, perf_bpf_filter_text);
@@ -80,6 +86,15 @@ retire_lat   { return sample_part(PERF_SAMPLE_WEIGHT_STRUCT, 3); } /* alias for we
 phys_addr      { return sample(PERF_SAMPLE_PHYS_ADDR); }
 code_pgsz      { return sample(PERF_SAMPLE_CODE_PAGE_SIZE); }
 data_pgsz      { return sample(PERF_SAMPLE_DATA_PAGE_SIZE); }
+mem_op         { return sample_part(PERF_SAMPLE_DATA_SRC, 1); }
+mem_lvlnum     { return sample_part(PERF_SAMPLE_DATA_SRC, 2); }
+mem_lvl                { return sample_part(PERF_SAMPLE_DATA_SRC, 2); } /* alias for mem_lvlnum */
+mem_snoop      { return sample_part(PERF_SAMPLE_DATA_SRC, 3); } /* include snoopx */
+mem_remote     { return sample_part(PERF_SAMPLE_DATA_SRC, 4); }
+mem_lock       { return sample_part(PERF_SAMPLE_DATA_SRC, 5); }
+mem_dtlb       { return sample_part(PERF_SAMPLE_DATA_SRC, 6); }
+mem_blk                { return sample_part(PERF_SAMPLE_DATA_SRC, 7); }
+mem_hops       { return sample_part(PERF_SAMPLE_DATA_SRC, 8); }
 
 "=="           { return operator(PBF_OP_EQ); }
 "!="           { return operator(PBF_OP_NEQ); }
@@ -89,6 +104,52 @@ data_pgsz   { return sample(PERF_SAMPLE_DATA_PAGE_SIZE); }
 "<="           { return operator(PBF_OP_LE); }
 "&"            { return operator(PBF_OP_AND); }
 
+na             { return constant(PERF_MEM_OP_NA); }
+load           { return constant(PERF_MEM_OP_LOAD); }
+store          { return constant(PERF_MEM_OP_STORE); }
+pfetch         { return constant(PERF_MEM_OP_PFETCH); }
+exec           { return constant(PERF_MEM_OP_EXEC); }
+
+l1             { return constant(PERF_MEM_LVLNUM_L1); }
+l2             { return constant(PERF_MEM_LVLNUM_L2); }
+l3             { return constant(PERF_MEM_LVLNUM_L3); }
+l4             { return constant(PERF_MEM_LVLNUM_L4); }
+cxl            { return constant(PERF_MEM_LVLNUM_CXL); }
+io             { return constant(PERF_MEM_LVLNUM_IO); }
+any_cache      { return constant(PERF_MEM_LVLNUM_ANY_CACHE); }
+lfb            { return constant(PERF_MEM_LVLNUM_LFB); }
+ram            { return constant(PERF_MEM_LVLNUM_RAM); }
+pmem           { return constant(PERF_MEM_LVLNUM_PMEM); }
+
+none           { return constant(PERF_MEM_SNOOP_NONE); }
+hit            { return constant(PERF_MEM_SNOOP_HIT); }
+miss           { return constant(PERF_MEM_SNOOP_MISS); }
+hitm           { return constant(PERF_MEM_SNOOP_HITM); }
+fwd            { return constant(PERF_MEM_SNOOPX_FWD); }
+peer           { return constant(PERF_MEM_SNOOPX_PEER); }
+
+remote         { return constant(PERF_MEM_REMOTE_REMOTE); }
+
+locked         { return constant(PERF_MEM_LOCK_LOCKED); }
+
+l1_hit         { return constant(PERF_MEM_TLB_L1 | PERF_MEM_TLB_HIT); }
+l1_miss                { return constant(PERF_MEM_TLB_L1 | PERF_MEM_TLB_MISS); }
+l2_hit         { return constant(PERF_MEM_TLB_L2 | PERF_MEM_TLB_HIT); }
+l2_miss                { return constant(PERF_MEM_TLB_L2 | PERF_MEM_TLB_MISS); }
+any_hit                { return constant(PERF_MEM_TLB_HIT); }
+any_miss       { return constant(PERF_MEM_TLB_MISS); }
+walk           { return constant(PERF_MEM_TLB_WK); }
+os             { return constant(PERF_MEM_TLB_OS); }
+fault          { return constant(PERF_MEM_TLB_OS); } /* alias for os */
+
+by_data                { return constant(PERF_MEM_BLK_DATA); }
+by_addr                { return constant(PERF_MEM_BLK_ADDR); }
+
+hops0          { return constant(PERF_MEM_HOPS_0); }
+hops1          { return constant(PERF_MEM_HOPS_1); }
+hops2          { return constant(PERF_MEM_HOPS_2); }
+hops3          { return constant(PERF_MEM_HOPS_3); }
+
 ","            { return ','; }
 
 {ident}                { return error("ident"); }
index d930401..88dbc78 100644 (file)
@@ -70,6 +70,29 @@ static inline __u64 perf_get_sample(struct bpf_perf_event_data_kern *kctx,
                return kctx->data->code_page_size;
        case PERF_SAMPLE_DATA_PAGE_SIZE:
                return kctx->data->data_page_size;
+       case PERF_SAMPLE_DATA_SRC:
+               if (entry->part == 1)
+                       return kctx->data->data_src.mem_op;
+               if (entry->part == 2)
+                       return kctx->data->data_src.mem_lvl_num;
+               if (entry->part == 3) {
+                       __u32 snoop = kctx->data->data_src.mem_snoop;
+                       __u32 snoopx = kctx->data->data_src.mem_snoopx;
+
+                       return (snoopx << 5) | snoop;
+               }
+               if (entry->part == 4)
+                       return kctx->data->data_src.mem_remote;
+               if (entry->part == 5)
+                       return kctx->data->data_src.mem_lock;
+               if (entry->part == 6)
+                       return kctx->data->data_src.mem_dtlb;
+               if (entry->part == 7)
+                       return kctx->data->data_src.mem_blk;
+               if (entry->part == 8)
+                       return kctx->data->data_src.mem_hops;
+               /* return the whole word */
+               return kctx->data->data_src.val;
        default:
                break;
        }