Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf record --off-cpu: Dump the remaining PERF_SAMPLE_ in sample_type from BPF's stack trace map

Dump the remaining PERF_SAMPLE_ data, as if it is dumping a direct
sample.

Put the stack trace, tid, off-cpu time and cgroup id into the raw_data
section, just like a direct off-cpu sample coming from BPF's
bpf_perf_event_output().

This ensures that evsel__parse_sample() correctly parses both direct
samples and accumulated samples.

Suggested-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Howard Chu <howardchu95@gmail.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Gautam Menghani <gautam@linux.ibm.com>
Tested-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20241108204137.2444151-10-howardchu95@gmail.com
Link: https://lore.kernel.org/r/20250501022809.449767-9-howardchu95@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Howard Chu and committed by
Arnaldo Carvalho de Melo
74069a01 8ae7a576

+33 -22
+33 -22
tools/perf/util/bpf_off_cpu.c
··· 37 37 u64 array[1024 / sizeof(u64)]; 38 38 }; 39 39 40 + u64 off_cpu_raw[MAX_STACKS + 5]; 41 + 40 42 static int off_cpu_config(struct evlist *evlist) 41 43 { 42 44 char off_cpu_event[64]; ··· 315 313 { 316 314 int bytes = 0, size; 317 315 int fd, stack; 316 + u32 raw_size; 318 317 u64 sample_type, val, sid = 0; 319 318 struct evsel *evsel; 320 319 struct perf_data_file *file = &session->data->file; ··· 355 352 356 353 while (!bpf_map_get_next_key(fd, &prev, &key)) { 357 354 int n = 1; /* start from perf_event_header */ 358 - int ip_pos = -1; 359 355 360 356 bpf_map_lookup_elem(fd, &key, &val); 361 357 358 + /* zero-fill some of the fields, will be overwritten by raw_data when parsing */ 362 359 if (sample_type & PERF_SAMPLE_IDENTIFIER) 363 360 data.array[n++] = sid; 364 - if (sample_type & PERF_SAMPLE_IP) { 365 - ip_pos = n; 361 + if (sample_type & PERF_SAMPLE_IP) 366 362 data.array[n++] = 0; /* will be updated */ 367 - } 368 363 if (sample_type & PERF_SAMPLE_TID) 369 - data.array[n++] = (u64)key.pid << 32 | key.tgid; 364 + data.array[n++] = 0; 370 365 if (sample_type & PERF_SAMPLE_TIME) 371 366 data.array[n++] = tstamp; 372 - if (sample_type & PERF_SAMPLE_ID) 373 - data.array[n++] = sid; 374 367 if (sample_type & PERF_SAMPLE_CPU) 375 368 data.array[n++] = 0; 376 369 if (sample_type & PERF_SAMPLE_PERIOD) 377 - data.array[n++] = val; 378 - if (sample_type & PERF_SAMPLE_CALLCHAIN) { 379 - int len = 0; 370 + data.array[n++] = 0; 371 + if (sample_type & PERF_SAMPLE_RAW) { 372 + /* 373 + * [ size ][ data ] 374 + * [ data ] 375 + * [ data ] 376 + * [ data ] 377 + * [ data ][ empty] 378 + */ 379 + int len = 0, i = 0; 380 + void *raw_data = (void *)data.array + n * sizeof(u64); 380 381 381 - /* data.array[n] is callchain->nr (updated later) */ 382 - data.array[n + 1] = PERF_CONTEXT_USER; 383 - data.array[n + 2] = 0; 382 + off_cpu_raw[i++] = (u64)key.pid << 32 | key.tgid; 383 + off_cpu_raw[i++] = val; 384 384 385 - bpf_map_lookup_elem(stack, &key.stack_id, &data.array[n + 2]); 386 - while (data.array[n + 2 + len]) 385 + /* off_cpu_raw[i] is callchain->nr (updated later) */ 386 + off_cpu_raw[i + 1] = PERF_CONTEXT_USER; 387 + off_cpu_raw[i + 2] = 0; 388 + 389 + bpf_map_lookup_elem(stack, &key.stack_id, &off_cpu_raw[i + 2]); 390 + while (off_cpu_raw[i + 2 + len]) 387 391 len++; 388 392 389 - /* update length of callchain */ 390 - data.array[n] = len + 1; 393 + off_cpu_raw[i] = len + 1; 394 + i += len + 2; 391 395 392 - /* update sample ip with the first callchain entry */ 393 - if (ip_pos >= 0) 394 - data.array[ip_pos] = data.array[n + 2]; 396 + off_cpu_raw[i++] = key.cgroup_id; 395 397 396 - /* calculate sample callchain data array length */ 397 - n += len + 2; 398 + raw_size = i * sizeof(u64) + sizeof(u32); /* 4 bytes for alignment */ 399 + memcpy(raw_data, &raw_size, sizeof(raw_size)); 400 + memcpy(raw_data + sizeof(u32), off_cpu_raw, i * sizeof(u64)); 401 + 402 + n += i + 1; 398 403 } 399 404 if (sample_type & PERF_SAMPLE_CGROUP) 400 405 data.array[n++] = key.cgroup_id;