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 thread: Add optional e_flags output argument to thread__e_machine

The e_flags are needed to accurately compute complete perf register
information for CSKY.

Add the ability to read and have this value associated with a thread.

This change doesn't wire up the use of the e_flags except in disasm
where use already exists but just wasn't set up yet.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Aditya Bodkhe <aditya.b1@linux.ibm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.ibm.com>
Cc: Chun-Tse Shao <ctshao@google.com>
Cc: Guo Ren <guoren@kernel.org>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sergei Trofimovich <slyich@gmail.com>
Cc: Shimin Guo <shimin.guo@skydio.com>
Cc: Stephen Brennan <stephen.s.brennan@oracle.com>
Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
Cc: Tianyou Li <tianyou.li@intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
4e66527f 7d0ebeb6

+122 -48
+10 -4
tools/perf/builtin-script.c
··· 2504 2504 symbol_conf.bt_stop_list, fp); 2505 2505 } 2506 2506 2507 - if (PRINT_FIELD(IREGS)) 2508 - perf_sample__fprintf_iregs(sample, attr, thread__e_machine(thread, machine), fp); 2507 + if (PRINT_FIELD(IREGS)) { 2508 + perf_sample__fprintf_iregs(sample, attr, 2509 + thread__e_machine(thread, machine, /*e_flags=*/NULL), 2510 + fp); 2511 + } 2509 2512 2510 - if (PRINT_FIELD(UREGS)) 2511 - perf_sample__fprintf_uregs(sample, attr, thread__e_machine(thread, machine), fp); 2513 + if (PRINT_FIELD(UREGS)) { 2514 + perf_sample__fprintf_uregs(sample, attr, 2515 + thread__e_machine(thread, machine, /*e_flags=*/NULL), 2516 + fp); 2517 + } 2512 2518 2513 2519 if (PRINT_FIELD(BRSTACK)) 2514 2520 perf_sample__fprintf_brstack(sample, thread, evsel, fp);
+7 -5
tools/perf/builtin-trace.c
··· 2789 2789 struct thread_trace *ttrace; 2790 2790 2791 2791 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 2792 - e_machine = thread__e_machine(thread, trace->host); 2792 + e_machine = thread__e_machine(thread, trace->host, /*e_flags=*/NULL); 2793 2793 sc = trace__syscall_info(trace, evsel, e_machine, id); 2794 2794 if (sc == NULL) 2795 2795 goto out_put; ··· 2868 2868 2869 2869 2870 2870 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 2871 - e_machine = thread__e_machine(thread, trace->host); 2871 + e_machine = thread__e_machine(thread, trace->host, /*e_flags=*/NULL); 2872 2872 sc = trace__syscall_info(trace, evsel, e_machine, id); 2873 2873 if (sc == NULL) 2874 2874 goto out_put; ··· 2934 2934 struct thread_trace *ttrace; 2935 2935 2936 2936 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 2937 - e_machine = thread__e_machine(thread, trace->host); 2937 + e_machine = thread__e_machine(thread, trace->host, /*e_flags=*/NULL); 2938 2938 sc = trace__syscall_info(trace, evsel, e_machine, id); 2939 2939 if (sc == NULL) 2940 2940 goto out_put; ··· 3285 3285 3286 3286 if (evsel == trace->syscalls.events.bpf_output) { 3287 3287 int id = perf_evsel__sc_tp_uint(evsel, id, sample); 3288 - int e_machine = thread ? thread__e_machine(thread, trace->host) : EM_HOST; 3288 + int e_machine = thread 3289 + ? thread__e_machine(thread, trace->host, /*e_flags=*/NULL) 3290 + : EM_HOST; 3289 3291 struct syscall *sc = trace__syscall_info(trace, evsel, e_machine, id); 3290 3292 3291 3293 if (sc) { ··· 4918 4916 { 4919 4917 size_t printed = 0; 4920 4918 struct thread_trace *ttrace = thread__priv(thread); 4921 - int e_machine = thread__e_machine(thread, trace->host); 4919 + int e_machine = thread__e_machine(thread, trace->host, /*e_flags=*/NULL); 4922 4920 double ratio; 4923 4921 4924 4922 if (ttrace == NULL)
+3 -2
tools/perf/util/annotate.c
··· 984 984 { 985 985 const struct arch *arch; 986 986 struct machine *machine; 987 + uint32_t e_flags; 987 988 uint16_t e_machine; 988 989 989 990 if (!thread) { ··· 993 992 } 994 993 995 994 machine = maps__machine(thread__maps(thread)); 996 - e_machine = thread__e_machine(thread, machine); 997 - arch = arch__find(e_machine, machine->env ? machine->env->cpuid : NULL); 995 + e_machine = thread__e_machine(thread, machine, &e_flags); 996 + arch = arch__find(e_machine, e_flags, machine->env ? machine->env->cpuid : NULL); 998 997 if (arch == NULL) { 999 998 pr_err("%s: unsupported arch %d\n", __func__, e_machine); 1000 999 return errno;
+2 -3
tools/perf/util/disasm.c
··· 134 134 return e_machine_and_eflags__cmp(&(*aa)->id, &(*ab)->id); 135 135 } 136 136 137 - const struct arch *arch__find(uint16_t e_machine, const char *cpuid) 137 + const struct arch *arch__find(uint16_t e_machine, uint32_t e_flags, const char *cpuid) 138 138 { 139 139 static const struct arch *(*const arch_new_fn[])(const struct e_machine_and_e_flags *id, 140 140 const char *cpuid) = { ··· 157 157 static size_t num_archs; 158 158 struct e_machine_and_e_flags key = { 159 159 .e_machine = e_machine, 160 - // TODO: e_flags should really come from the same source as e_machine. 161 - .e_flags = EF_HOST, 160 + .e_flags = e_flags, 162 161 }; 163 162 const struct arch *result = NULL, **tmp; 164 163
+1 -1
tools/perf/util/disasm.h
··· 108 108 char *fileloc; 109 109 }; 110 110 111 - const struct arch *arch__find(uint16_t e_machine, const char *cpuid); 111 + const struct arch *arch__find(uint16_t e_machine, uint32_t e_flags, const char *cpuid); 112 112 bool arch__is_x86(const struct arch *arch); 113 113 bool arch__is_powerpc(const struct arch *arch); 114 114
+36 -7
tools/perf/util/dso.c
··· 1220 1220 } 1221 1221 1222 1222 /* Reads e_machine from fd, optionally caching data in dso. */ 1223 - uint16_t dso__read_e_machine(struct dso *optional_dso, int fd) 1223 + uint16_t dso__read_e_machine(struct dso *optional_dso, int fd, uint32_t *e_flags) 1224 1224 { 1225 1225 uint16_t e_machine = EM_NONE; 1226 1226 unsigned char e_ident[EI_NIDENT]; 1227 1227 enum dso_swap_type swap_type; 1228 + bool need_e_flags; 1228 1229 1229 - _Static_assert(offsetof(Elf32_Ehdr, e_ident) == 0, "Unexpected offset"); 1230 - _Static_assert(offsetof(Elf64_Ehdr, e_ident) == 0, "Unexpected offset"); 1230 + if (e_flags) 1231 + *e_flags = 0; 1232 + 1233 + { 1234 + _Static_assert(offsetof(Elf32_Ehdr, e_ident) == 0, "Unexpected offset"); 1235 + _Static_assert(offsetof(Elf64_Ehdr, e_ident) == 0, "Unexpected offset"); 1236 + } 1231 1237 if (pread(fd, &e_ident, sizeof(e_ident), 0) != sizeof(e_ident)) 1232 1238 return EM_NONE; // Read failed. 1233 1239 ··· 1260 1254 { 1261 1255 _Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset"); 1262 1256 _Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset"); 1263 - if (pread(fd, &e_machine, sizeof(e_machine), 18) != sizeof(e_machine)) 1264 - return EM_NONE; // e_machine read failed. 1265 1257 } 1258 + if (pread(fd, &e_machine, sizeof(e_machine), 18) != sizeof(e_machine)) 1259 + return EM_NONE; // e_machine read failed. 1266 1260 1267 1261 e_machine = DSO_SWAP_TYPE__SWAP(swap_type, uint16_t, e_machine); 1268 1262 if (e_machine >= EM_NUM) 1269 1263 return EM_NONE; // Bad ELF machine number. 1270 1264 1265 + #ifdef NDEBUG 1266 + /* In production code the e_flags are only needed on CSKY. */ 1267 + need_e_flags = e_flags && e_machine == EM_CSKY; 1268 + #else 1269 + /* Debug code will always read the e_flags. */ 1270 + need_e_flags = e_flags != NULL; 1271 + #endif 1272 + if (need_e_flags) { 1273 + off_t offset = e_ident[EI_CLASS] == ELFCLASS32 1274 + ? offsetof(Elf32_Ehdr, e_flags) 1275 + : offsetof(Elf64_Ehdr, e_flags); 1276 + 1277 + if (pread(fd, e_flags, sizeof(*e_flags), offset) != sizeof(*e_flags)) { 1278 + *e_flags = 0; 1279 + return EM_NONE; // e_flags read failed. 1280 + } 1281 + } 1271 1282 return e_machine; 1272 1283 } 1273 1284 1274 - uint16_t dso__e_machine(struct dso *dso, struct machine *machine) 1285 + uint16_t dso__e_machine(struct dso *dso, struct machine *machine, uint32_t *e_flags) 1275 1286 { 1276 1287 uint16_t e_machine = EM_NONE; 1277 1288 int fd; ··· 1308 1285 case DSO_BINARY_TYPE__BPF_IMAGE: 1309 1286 case DSO_BINARY_TYPE__OOL: 1310 1287 case DSO_BINARY_TYPE__JAVA_JIT: 1288 + if (e_flags) 1289 + *e_flags = EF_HOST; 1311 1290 return EM_HOST; 1312 1291 case DSO_BINARY_TYPE__DEBUGLINK: 1313 1292 case DSO_BINARY_TYPE__BUILD_ID_CACHE: ··· 1324 1299 break; 1325 1300 case DSO_BINARY_TYPE__NOT_FOUND: 1326 1301 default: 1302 + if (e_flags) 1303 + *e_flags = 0; 1327 1304 return EM_NONE; 1328 1305 } 1329 1306 ··· 1338 1311 try_to_open_dso(dso, machine); 1339 1312 fd = dso__data(dso)->fd; 1340 1313 if (fd >= 0) 1341 - e_machine = dso__read_e_machine(dso, fd); 1314 + e_machine = dso__read_e_machine(dso, fd, e_flags); 1315 + else if (e_flags) 1316 + *e_flags = 0; 1342 1317 1343 1318 mutex_unlock(dso__data_open_lock()); 1344 1319 return e_machine;
+2 -2
tools/perf/util/dso.h
··· 866 866 off_t dso__data_size(struct dso *dso, struct machine *machine); 867 867 ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, 868 868 u64 offset, u8 *data, ssize_t size); 869 - uint16_t dso__read_e_machine(struct dso *optional_dso, int fd); 870 - uint16_t dso__e_machine(struct dso *dso, struct machine *machine); 869 + uint16_t dso__read_e_machine(struct dso *optional_dso, int fd, uint32_t *e_flags); 870 + uint16_t dso__e_machine(struct dso *dso, struct machine *machine, uint32_t *e_flags); 871 871 ssize_t dso__data_read_addr(struct dso *dso, struct map *map, 872 872 struct machine *machine, u64 addr, 873 873 u8 *data, ssize_t size);
+1 -1
tools/perf/util/scripting-engines/trace-event-python.c
··· 925 925 926 926 if (al->thread) { 927 927 machine = maps__machine(thread__maps(al->thread)); 928 - e_machine = thread__e_machine(al->thread, machine); 928 + e_machine = thread__e_machine(al->thread, machine, /*e_flags=*/NULL); 929 929 } 930 930 if (set_regs_in_dict(dict, sample, evsel, e_machine)) 931 931 Py_FatalError("Failed to setting regs in dict");
+2 -2
tools/perf/util/session.c
··· 1124 1124 if (sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_REGS_INTR)) { 1125 1125 struct thread *thread = machine__find_thread(machine, sample->pid, sample->pid); 1126 1126 1127 - e_machine = thread__e_machine(thread, machine); 1127 + e_machine = thread__e_machine(thread, machine, /*e_flags=*/NULL); 1128 1128 } 1129 1129 1130 1130 printf("(IP, 0x%x): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n", ··· 2965 2965 uint16_t *result = arg; 2966 2966 struct machine *machine = maps__machine(thread__maps(thread)); 2967 2967 2968 - *result = thread__e_machine(thread, machine); 2968 + *result = thread__e_machine(thread, machine, /*e_flags=*/NULL); 2969 2969 return *result != EM_NONE ? 1 : 0; 2970 2970 } 2971 2971
+41 -18
tools/perf/util/thread.c
··· 449 449 } 450 450 } 451 451 452 - static uint16_t read_proc_e_machine_for_pid(pid_t pid) 452 + static uint16_t read_proc_e_machine_for_pid(pid_t pid, uint32_t *e_flags) 453 453 { 454 454 char path[6 /* "/proc/" */ + 11 /* max length of pid */ + 5 /* "/exe\0" */]; 455 455 int fd; ··· 458 458 snprintf(path, sizeof(path), "/proc/%d/exe", pid); 459 459 fd = open(path, O_RDONLY); 460 460 if (fd >= 0) { 461 - e_machine = dso__read_e_machine(/*optional_dso=*/NULL, fd); 461 + e_machine = dso__read_e_machine(/*optional_dso=*/NULL, fd, e_flags); 462 462 close(fd); 463 463 } 464 464 return e_machine; 465 465 } 466 466 467 - static int thread__e_machine_callback(struct map *map, void *machine) 467 + struct thread__e_machine_callback_args { 468 + struct machine *machine; 469 + uint32_t e_flags; 470 + uint16_t e_machine; 471 + }; 472 + 473 + static int thread__e_machine_callback(struct map *map, void *_args) 468 474 { 475 + struct thread__e_machine_callback_args *args = _args; 469 476 struct dso *dso = map__dso(map); 470 477 471 - _Static_assert(0 == EM_NONE, "Unexpected EM_NONE"); 472 478 if (!dso) 473 - return EM_NONE; 479 + return 0; // No dso, continue search. 474 480 475 - return dso__e_machine(dso, machine); 481 + args->e_machine = dso__e_machine(dso, args->machine, &args->e_flags); 482 + return args->e_machine != EM_NONE ? 1 /* stop search */ : 0 /* continue search */; 476 483 } 477 484 478 - uint16_t thread__e_machine(struct thread *thread, struct machine *machine) 485 + uint16_t thread__e_machine(struct thread *thread, struct machine *machine, uint32_t *e_flags) 479 486 { 480 487 pid_t tid, pid; 481 488 uint16_t e_machine = RC_CHK_ACCESS(thread)->e_machine; 489 + uint32_t local_e_flags = 0; 490 + struct thread__e_machine_callback_args args = { 491 + .machine = machine, 492 + .e_flags = 0, 493 + .e_machine = EM_NONE, 494 + }; 482 495 483 - if (e_machine != EM_NONE) 496 + if (e_machine != EM_NONE) { 497 + if (e_flags) 498 + *e_flags = thread__e_flags(thread); 484 499 return e_machine; 500 + } 485 501 486 502 tid = thread__tid(thread); 487 503 pid = thread__pid(thread); ··· 505 489 struct thread *parent = machine__findnew_thread(machine, pid, pid); 506 490 507 491 if (parent) { 508 - e_machine = thread__e_machine(parent, machine); 492 + e_machine = thread__e_machine(parent, machine, &local_e_flags); 509 493 thread__put(parent); 510 - thread__set_e_machine(thread, e_machine); 511 - return e_machine; 494 + goto out; 512 495 } 513 496 /* Something went wrong, fallback. */ 514 497 } 515 498 /* Reading on the PID thread. First try to find from the maps. */ 516 - e_machine = maps__for_each_map(thread__maps(thread), 517 - thread__e_machine_callback, 518 - machine); 519 - if (e_machine == EM_NONE) { 499 + maps__for_each_map(thread__maps(thread), thread__e_machine_callback, &args); 500 + 501 + if (args.e_machine != EM_NONE) { 502 + e_machine = args.e_machine; 503 + local_e_flags = args.e_flags; 504 + } else { 520 505 /* Maps failed, perhaps we're live with map events disabled. */ 521 506 bool is_live = machine->machines == NULL; 522 507 ··· 531 514 } 532 515 /* Read from /proc/pid/exe if live. */ 533 516 if (is_live) 534 - e_machine = read_proc_e_machine_for_pid(pid); 517 + e_machine = read_proc_e_machine_for_pid(pid, &local_e_flags); 535 518 } 536 - if (e_machine != EM_NONE) 519 + out: 520 + if (e_machine != EM_NONE) { 537 521 thread__set_e_machine(thread, e_machine); 538 - else 522 + thread__set_e_flags(thread, local_e_flags); 523 + } else { 539 524 e_machine = EM_HOST; 525 + local_e_flags = EF_HOST; 526 + } 527 + if (e_flags) 528 + *e_flags = local_e_flags; 540 529 return e_machine; 541 530 } 542 531
+15 -1
tools/perf/util/thread.h
··· 61 61 bool filter; 62 62 int filter_entry_depth; 63 63 /** 64 + * @e_flags: The ELF EF_* associated with the thread. Valid if e_machine != EM_NONE. 65 + */ 66 + uint16_t e_flags; 67 + /** 64 68 * @e_machine: The ELF EM_* associated with the thread. EM_NONE if not 65 69 * computed. 66 70 */ ··· 311 307 RC_CHK_ACCESS(thread)->filter_entry_depth = depth; 312 308 } 313 309 314 - uint16_t thread__e_machine(struct thread *thread, struct machine *machine); 310 + uint16_t thread__e_machine(struct thread *thread, struct machine *machine, uint32_t *e_flags); 315 311 316 312 static inline void thread__set_e_machine(struct thread *thread, uint16_t e_machine) 317 313 { 318 314 RC_CHK_ACCESS(thread)->e_machine = e_machine; 315 + } 316 + 317 + static inline uint32_t thread__e_flags(const struct thread *thread) 318 + { 319 + return RC_CHK_ACCESS(thread)->e_flags; 320 + } 321 + 322 + static inline void thread__set_e_flags(struct thread *thread, uint32_t e_flags) 323 + { 324 + RC_CHK_ACCESS(thread)->e_flags = e_flags; 319 325 } 320 326 321 327
+2 -2
tools/perf/util/unwind-libdw.c
··· 213 213 { 214 214 struct dwfl_ui_thread_info *dwfl_ui_ti = arg; 215 215 struct unwind_info *ui = dwfl_ui_ti->ui; 216 - uint16_t e_machine = thread__e_machine(ui->thread, ui->machine); 216 + uint16_t e_machine = thread__e_machine(ui->thread, ui->machine, /*e_flags=*/NULL); 217 217 struct stack_dump *stack = &ui->sample->user_stack; 218 218 u64 start, end; 219 219 int offset; ··· 348 348 { 349 349 struct maps *maps = thread__maps(thread); 350 350 struct machine *machine = maps__machine(maps); 351 - uint16_t e_machine = thread__e_machine(thread, machine); 351 + uint16_t e_machine = thread__e_machine(thread, machine, /*e_flags=*/NULL); 352 352 struct dwfl_ui_thread_info *dwfl_ui_ti; 353 353 static struct unwind_info *ui; 354 354 Dwfl *dwfl;