Skip to content

Commit 12ef9bd

Browse files
committed
Merge branch 'bpf-perf-sample-addr'
Teng Qin says: ==================== These patches add support that allows bpf programs attached to perf events to read the address values recorded with the perf events. These values are requested by specifying sample_type with PERF_SAMPLE_ADDR when calling perf_event_open(). The main motivation for these changes is to support building memory or lock access profiling and tracing tools. For example on Intel CPUs, the recorded address values for supported memory or lock access perf events would be the access or lock target addresses from PEBS buffer. Such information would be very valuable for building tools that help understand memory access or lock acquire pattern. ==================== Signed-off-by: Daniel Borkmann <[email protected]>
2 parents a366e30 + 12fe122 commit 12ef9bd

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

include/uapi/linux/bpf_perf_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
struct bpf_perf_event_data {
1414
bpf_user_pt_regs_t regs;
1515
__u64 sample_period;
16+
__u64 addr;
1617
};
1718

1819
#endif /* _UAPI__LINUX_BPF_PERF_EVENT_H__ */

kernel/trace/bpf_trace.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -726,8 +726,7 @@ const struct bpf_prog_ops tracepoint_prog_ops = {
726726
static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type,
727727
struct bpf_insn_access_aux *info)
728728
{
729-
const int size_sp = FIELD_SIZEOF(struct bpf_perf_event_data,
730-
sample_period);
729+
const int size_u64 = sizeof(u64);
731730

732731
if (off < 0 || off >= sizeof(struct bpf_perf_event_data))
733732
return false;
@@ -738,8 +737,13 @@ static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type
738737

739738
switch (off) {
740739
case bpf_ctx_range(struct bpf_perf_event_data, sample_period):
741-
bpf_ctx_record_field_size(info, size_sp);
742-
if (!bpf_ctx_narrow_access_ok(off, size, size_sp))
740+
bpf_ctx_record_field_size(info, size_u64);
741+
if (!bpf_ctx_narrow_access_ok(off, size, size_u64))
742+
return false;
743+
break;
744+
case bpf_ctx_range(struct bpf_perf_event_data, addr):
745+
bpf_ctx_record_field_size(info, size_u64);
746+
if (!bpf_ctx_narrow_access_ok(off, size, size_u64))
743747
return false;
744748
break;
745749
default:
@@ -766,6 +770,14 @@ static u32 pe_prog_convert_ctx_access(enum bpf_access_type type,
766770
bpf_target_off(struct perf_sample_data, period, 8,
767771
target_size));
768772
break;
773+
case offsetof(struct bpf_perf_event_data, addr):
774+
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern,
775+
data), si->dst_reg, si->src_reg,
776+
offsetof(struct bpf_perf_event_data_kern, data));
777+
*insn++ = BPF_LDX_MEM(BPF_DW, si->dst_reg, si->dst_reg,
778+
bpf_target_off(struct perf_sample_data, addr, 8,
779+
target_size));
780+
break;
769781
default:
770782
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern,
771783
regs), si->dst_reg, si->src_reg,

samples/bpf/trace_event_kern.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ int bpf_prog1(struct bpf_perf_event_data *ctx)
3939
{
4040
char time_fmt1[] = "Time Enabled: %llu, Time Running: %llu";
4141
char time_fmt2[] = "Get Time Failed, ErrCode: %d";
42+
char addr_fmt[] = "Address recorded on event: %llx";
4243
char fmt[] = "CPU-%d period %lld ip %llx";
4344
u32 cpu = bpf_get_smp_processor_id();
4445
struct bpf_perf_event_value value_buf;
@@ -64,6 +65,9 @@ int bpf_prog1(struct bpf_perf_event_data *ctx)
6465
else
6566
bpf_trace_printk(time_fmt2, sizeof(time_fmt2), ret);
6667

68+
if (ctx->addr != 0)
69+
bpf_trace_printk(addr_fmt, sizeof(addr_fmt), ctx->addr);
70+
6771
val = bpf_map_lookup_elem(&counts, &key);
6872
if (val)
6973
(*val)++;

samples/bpf/trace_event_user.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,17 @@ static void test_bpf_perf_event(void)
215215
/* Intel Instruction Retired */
216216
.config = 0xc0,
217217
};
218+
struct perf_event_attr attr_type_raw_lock_load = {
219+
.sample_freq = SAMPLE_FREQ,
220+
.freq = 1,
221+
.type = PERF_TYPE_RAW,
222+
/* Intel MEM_UOPS_RETIRED.LOCK_LOADS */
223+
.config = 0x21d0,
224+
/* Request to record lock address from PEBS */
225+
.sample_type = PERF_SAMPLE_ADDR,
226+
/* Record address value requires precise event */
227+
.precise_ip = 2,
228+
};
218229

219230
printf("Test HW_CPU_CYCLES\n");
220231
test_perf_event_all_cpu(&attr_type_hw);
@@ -236,6 +247,10 @@ static void test_bpf_perf_event(void)
236247
test_perf_event_all_cpu(&attr_type_raw);
237248
test_perf_event_task(&attr_type_raw);
238249

250+
printf("Test Lock Load\n");
251+
test_perf_event_all_cpu(&attr_type_raw_lock_load);
252+
test_perf_event_task(&attr_type_raw_lock_load);
253+
239254
printf("*** PASS ***\n");
240255
}
241256

0 commit comments

Comments
 (0)