Message ID | 20240427151825.174486-1-dev@der-flo.net (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [bpf-next] bpf: add support to read cpu_entry in bpf program | expand |
On 4/27/24 8:18 AM, Florian Lehner wrote: > Add new field "cpu_entry" to bpf_perf_event_data which could be read by > bpf programs attached to perf events. The value contains the CPU value > recorded by specifying sample_type with PERF_SAMPLE_CPU when calling > perf_event_open(). You can use bpf_cast_to_kern_ctx kfunc which can cast 'struct bpf_perf_event_data' ctx to 'struct bpf_perf_event_data_kern'. struct bpf_perf_event_data_kern { bpf_user_pt_regs_t *regs; struct perf_sample_data *data; struct perf_event *event; }; You can access bpf_perf_event_data_kern->data and then to access 'cpu_entry' field. > > Signed-off-by: Florian Lehner <dev@der-flo.net> > --- > include/uapi/linux/bpf_perf_event.h | 4 ++++ > kernel/trace/bpf_trace.c | 13 +++++++++++++ > tools/include/uapi/linux/bpf_perf_event.h | 4 ++++ > 3 files changed, 21 insertions(+) > > diff --git a/include/uapi/linux/bpf_perf_event.h b/include/uapi/linux/bpf_perf_event.h > index eb1b9d21250c..4856b4396ece 100644 > --- a/include/uapi/linux/bpf_perf_event.h > +++ b/include/uapi/linux/bpf_perf_event.h > @@ -14,6 +14,10 @@ struct bpf_perf_event_data { > bpf_user_pt_regs_t regs; > __u64 sample_period; > __u64 addr; > + struct { > + u32 cpu; > + u32 reserved; > + } cpu_entry; > }; > > #endif /* _UAPI__LINUX_BPF_PERF_EVENT_H__ */ > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c > index afb232b1d7c2..2b303221af5c 100644 > --- a/kernel/trace/bpf_trace.c > +++ b/kernel/trace/bpf_trace.c > @@ -2176,6 +2176,11 @@ static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type > if (!bpf_ctx_narrow_access_ok(off, size, size_u64)) > return false; > break; > + case bpf_ctx_range(struct bpf_perf_event_data, cpu_entry): > + bpf_ctx_record_field_size(info, size_u64); > + if (!bpf_ctx_narrow_access_ok(off, size, size_u64)) > + return false; > + break; > default: > if (size != sizeof(long)) > return false; > @@ -2208,6 +2213,14 @@ static u32 pe_prog_convert_ctx_access(enum bpf_access_type type, > bpf_target_off(struct perf_sample_data, addr, 8, > target_size)); > break; > + case offsetof(struct bpf_perf_event_data, cpu_entry): > + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern, > + data), si->dst_reg, si->src_reg, > + offsetof(struct bpf_perf_event_data_kern, data)); > + *insn++ = BPF_LDX_MEM(BPF_DW, si->dst_reg, si->dst_reg, > + bpf_target_off(struct perf_sample_data, cpu_entry, 8, > + target_size)); > + break; > default: > *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern, > regs), si->dst_reg, si->src_reg, > diff --git a/tools/include/uapi/linux/bpf_perf_event.h b/tools/include/uapi/linux/bpf_perf_event.h > index eb1b9d21250c..4856b4396ece 100644 > --- a/tools/include/uapi/linux/bpf_perf_event.h > +++ b/tools/include/uapi/linux/bpf_perf_event.h > @@ -14,6 +14,10 @@ struct bpf_perf_event_data { > bpf_user_pt_regs_t regs; > __u64 sample_period; > __u64 addr; > + struct { > + u32 cpu; > + u32 reserved; > + } cpu_entry; > }; > > #endif /* _UAPI__LINUX_BPF_PERF_EVENT_H__ */
diff --git a/include/uapi/linux/bpf_perf_event.h b/include/uapi/linux/bpf_perf_event.h index eb1b9d21250c..4856b4396ece 100644 --- a/include/uapi/linux/bpf_perf_event.h +++ b/include/uapi/linux/bpf_perf_event.h @@ -14,6 +14,10 @@ struct bpf_perf_event_data { bpf_user_pt_regs_t regs; __u64 sample_period; __u64 addr; + struct { + u32 cpu; + u32 reserved; + } cpu_entry; }; #endif /* _UAPI__LINUX_BPF_PERF_EVENT_H__ */ diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index afb232b1d7c2..2b303221af5c 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2176,6 +2176,11 @@ static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type if (!bpf_ctx_narrow_access_ok(off, size, size_u64)) return false; break; + case bpf_ctx_range(struct bpf_perf_event_data, cpu_entry): + bpf_ctx_record_field_size(info, size_u64); + if (!bpf_ctx_narrow_access_ok(off, size, size_u64)) + return false; + break; default: if (size != sizeof(long)) return false; @@ -2208,6 +2213,14 @@ static u32 pe_prog_convert_ctx_access(enum bpf_access_type type, bpf_target_off(struct perf_sample_data, addr, 8, target_size)); break; + case offsetof(struct bpf_perf_event_data, cpu_entry): + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern, + data), si->dst_reg, si->src_reg, + offsetof(struct bpf_perf_event_data_kern, data)); + *insn++ = BPF_LDX_MEM(BPF_DW, si->dst_reg, si->dst_reg, + bpf_target_off(struct perf_sample_data, cpu_entry, 8, + target_size)); + break; default: *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_perf_event_data_kern, regs), si->dst_reg, si->src_reg, diff --git a/tools/include/uapi/linux/bpf_perf_event.h b/tools/include/uapi/linux/bpf_perf_event.h index eb1b9d21250c..4856b4396ece 100644 --- a/tools/include/uapi/linux/bpf_perf_event.h +++ b/tools/include/uapi/linux/bpf_perf_event.h @@ -14,6 +14,10 @@ struct bpf_perf_event_data { bpf_user_pt_regs_t regs; __u64 sample_period; __u64 addr; + struct { + u32 cpu; + u32 reserved; + } cpu_entry; }; #endif /* _UAPI__LINUX_BPF_PERF_EVENT_H__ */
Add new field "cpu_entry" to bpf_perf_event_data which could be read by bpf programs attached to perf events. The value contains the CPU value recorded by specifying sample_type with PERF_SAMPLE_CPU when calling perf_event_open(). Signed-off-by: Florian Lehner <dev@der-flo.net> --- include/uapi/linux/bpf_perf_event.h | 4 ++++ kernel/trace/bpf_trace.c | 13 +++++++++++++ tools/include/uapi/linux/bpf_perf_event.h | 4 ++++ 3 files changed, 21 insertions(+)