perf/core: Add perf_sample_save_callchain() helper
authorNamhyung Kim <namhyung@kernel.org>
Wed, 18 Jan 2023 06:05:53 +0000 (22:05 -0800)
committerIngo Molnar <mingo@kernel.org>
Wed, 18 Jan 2023 10:57:19 +0000 (11:57 +0100)
When we save the callchain to the perf sample data, we need to update
the sample flags and the dynamic size.  To ensure this is done consistently,
add the perf_sample_save_callchain() helper and convert all call sites.

Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Tested-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Song Liu <song@kernel.org>
Acked-by: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20230118060559.615653-3-namhyung@kernel.org
arch/x86/events/amd/ibs.c
arch/x86/events/intel/ds.c
include/linux/perf_event.h
kernel/events/core.c

index da3f5eb..417c80b 100644 (file)
@@ -1122,10 +1122,8 @@ fail:
         * recorded as part of interrupt regs. Thus we need to use rip from
         * interrupt regs while unwinding call stack.
         */
-       if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
-               data.callchain = perf_callchain(event, iregs);
-               data.sample_flags |= PERF_SAMPLE_CALLCHAIN;
-       }
+       if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
+               perf_sample_save_callchain(&data, event, iregs);
 
        throttle = perf_event_overflow(event, &data, &regs);
 out:
index 6ec326b..158cf84 100644 (file)
@@ -1617,10 +1617,8 @@ static void setup_pebs_fixed_sample_data(struct perf_event *event,
         * previous PMI context or an (I)RET happened between the record and
         * PMI.
         */
-       if (sample_type & PERF_SAMPLE_CALLCHAIN) {
-               data->callchain = perf_callchain(event, iregs);
-               data->sample_flags |= PERF_SAMPLE_CALLCHAIN;
-       }
+       if (sample_type & PERF_SAMPLE_CALLCHAIN)
+               perf_sample_save_callchain(data, event, iregs);
 
        /*
         * We use the interrupt regs as a base because the PEBS record does not
@@ -1795,10 +1793,8 @@ static void setup_pebs_adaptive_sample_data(struct perf_event *event,
         * previous PMI context or an (I)RET happened between the record and
         * PMI.
         */
-       if (sample_type & PERF_SAMPLE_CALLCHAIN) {
-               data->callchain = perf_callchain(event, iregs);
-               data->sample_flags |= PERF_SAMPLE_CALLCHAIN;
-       }
+       if (sample_type & PERF_SAMPLE_CALLCHAIN)
+               perf_sample_save_callchain(data, event, iregs);
 
        *regs = *iregs;
        /* The ip in basic is EventingIP */
index 16b9800..a941960 100644 (file)
@@ -1095,6 +1095,8 @@ int perf_event_read_local(struct perf_event *event, u64 *value,
 extern u64 perf_event_read_value(struct perf_event *event,
                                 u64 *enabled, u64 *running);
 
+extern struct perf_callchain_entry *perf_callchain(struct perf_event *event, struct pt_regs *regs);
+
 
 struct perf_sample_data {
        /*
@@ -1167,6 +1169,19 @@ static inline void perf_sample_data_init(struct perf_sample_data *data,
        }
 }
 
+static inline void perf_sample_save_callchain(struct perf_sample_data *data,
+                                             struct perf_event *event,
+                                             struct pt_regs *regs)
+{
+       int size = 1;
+
+       data->callchain = perf_callchain(event, regs);
+       size += data->callchain->nr;
+
+       data->dyn_size += size * sizeof(u64);
+       data->sample_flags |= PERF_SAMPLE_CALLCHAIN;
+}
+
 /*
  * Clear all bitfields in the perf_branch_entry.
  * The to and from fields are not cleared because they are
@@ -1408,7 +1423,6 @@ extern void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct
 extern struct perf_callchain_entry *
 get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
                   u32 max_stack, bool crosstask, bool add_mark);
-extern struct perf_callchain_entry *perf_callchain(struct perf_event *event, struct pt_regs *regs);
 extern int get_callchain_buffers(int max_stack);
 extern void put_callchain_buffers(void);
 extern struct perf_callchain_entry *get_callchain_entry(int *rctx);
index 827082d..12b7d51 100644 (file)
@@ -7578,16 +7578,8 @@ void perf_prepare_sample(struct perf_event_header *header,
        if (sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_CODE_PAGE_SIZE))
                data->ip = perf_instruction_pointer(regs);
 
-       if (sample_type & PERF_SAMPLE_CALLCHAIN) {
-               int size = 1;
-
-               if (filtered_sample_type & PERF_SAMPLE_CALLCHAIN)
-                       data->callchain = perf_callchain(event, regs);
-
-               size += data->callchain->nr;
-
-               data->dyn_size += size * sizeof(u64);
-       }
+       if (filtered_sample_type & PERF_SAMPLE_CALLCHAIN)
+               perf_sample_save_callchain(data, event, regs);
 
        if (sample_type & PERF_SAMPLE_RAW) {
                struct perf_raw_record *raw = data->raw;