From d37a5467709e627370124d7346ef71ce605ababa Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 4 May 2026 01:12:19 -0700 Subject: [PATCH 001/343] perf dwarf-aux: Fix libdw segmentation fault in cu_walk_functions_at A segmentation fault was observed in `libdw` when running `perf kmem` with `--page stat` on some workloads. The crash occurred deep inside `libdw` (specifically in `dwarf_child` and `dwarf_diename`) when processing DWARF information. The root cause was improper error handling of `dwarf_getfuncs` in `die_find_realfunc` and `die_find_tailfunc`. `dwarf_getfuncs` returns: - `0` on success (when all functions have been processed). - A positive offset if the callback aborts early (e.g., via `DWARF_CB_ABORT` when a match is found). - `-1` on error. The original code used `if (!dwarf_getfuncs(...)) return NULL;`. On error (`-1`), `!-1` evaluates to `0` (false), bypassing the error check. Execution then proceeded as if a match was found, returning uninitialized stack memory (`die_mem`) to the caller (`cu_walk_functions_at`). When `cu_walk_functions_at` passed this uninitialized memory to `libdw` via `dwarf_diename`, it caused a segmentation fault. Fix this by correcting the error check to `if (dwarf_getfuncs(...) <= 0)`. Fixes: e0d153c69040 ("perf-probe: Move dwarf library routines to dwarf-aux.{c, h}") Fixes: d4c537e6bf86 ("perf probe: Ignore tail calls to probed functions") Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Peter Zijlstra Cc: Zecheng Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dwarf-aux.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 92db2fccc788..109a166a6d19 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -171,7 +171,6 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, } return ret; - } /** @@ -620,7 +619,7 @@ Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, ad.addr = addr; ad.die_mem = die_mem; /* dwarf_getscopes can't find subprogram. */ - if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0)) + if (dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0) <= 0) return NULL; else return die_mem; @@ -659,7 +658,7 @@ Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, ad.addr = addr; ad.die_mem = die_mem; /* dwarf_getscopes can't find subprogram. */ - if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0)) + if (dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0) <= 0) return NULL; else return die_mem; From 17e9b4243e76f0a0fe951d30ce990d6081a8b426 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 4 May 2026 01:12:20 -0700 Subject: [PATCH 002/343] perf dwarf-aux: Fix libdw API contract violations Check return values of `dwarf_decl_line` (where non-optional), `dwarf_getfuncs`, and `dwarf_lineaddr` to prevent using uninitialized stack variables or incorrectly reporting success on failure. For the root DIE in `die_walk_lines()`, `dwarf_decl_line` and `die_get_decl_file` are optional and their failures are handled gracefully to avoid breaking line walking on valid functions. Specifically, remove the strict `!decf` (declared file) check that would prematurely abort line walking on generated or artificial functions lacking this optional attribute. Additionally: - Add NULL pointer protection for `strcmp()` in `die_walk_lines()` when `inf` or `decf` are NULL to prevent crashes on generated code. - Use `dwarf_attr_integrate` in `die_get_data_member_location` to correctly resolve inherited member locations (e.g. via abstract origin or specification). Fixes: 57f95bf5f882 ("perf probe: Show correct statement line number by perf probe -l") Fixes: 3f4460a28fb2 ("perf probe: Filter out redundant inline-instances") Fixes: 75186a9b09e4 ("perf probe: Fix to show lines of sys_ functions correctly") Fixes: e0d153c69040 ("perf-probe: Move dwarf library routines to dwarf-aux.{c, h}") Fixes: 6243b9dc4c99 ("perf probe: Move dwarf specific functions to dwarf-aux.c") Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zecheng Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dwarf-aux.c | 34 +++++++++++++++++----------------- tools/perf/util/dwarf-aux.h | 5 +++++ 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 109a166a6d19..d7160f87ac7d 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -125,7 +125,8 @@ int cu_find_lineinfo(Dwarf_Die *cu_die, Dwarf_Addr addr, && die_entrypc(&die_mem, &faddr) == 0 && faddr == addr) { *fname = die_get_decl_file(&die_mem); - dwarf_decl_line(&die_mem, lineno); + if (dwarf_decl_line(&die_mem, lineno) != 0) + return -ENOENT; goto out; } @@ -459,7 +460,7 @@ int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) size_t nexpr; int ret; - if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL) + if (dwarf_attr_integrate(mb_die, DW_AT_data_member_location, &attr) == NULL) return -ENOENT; if (dwarf_formudata(&attr, offs) != 0) { @@ -795,8 +796,7 @@ static int __die_walk_instances_cb(Dwarf_Die *inst, void *data) /* Ignore redundant instances */ if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) { - dwarf_decl_line(origin, &tmp); - if (die_get_call_lineno(inst) == tmp) { + if (dwarf_decl_line(origin, &tmp) == 0 && die_get_call_lineno(inst) == tmp) { tmp = die_get_decl_fileno(origin); if (die_get_call_fileno(inst) == tmp) return DIE_FIND_CB_CONTINUE; @@ -950,11 +950,6 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL); dwarf_decl_line(rt_die, &decl); decf = die_get_decl_file(rt_die); - if (!decf) { - pr_debug2("Failed to get the declared file name of %s\n", - dwarf_diename(rt_die)); - return -EINVAL; - } } else cu_die = rt_die; if (!cu_die) { @@ -998,11 +993,12 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) if (die_find_inlinefunc(rt_die, addr, &die_mem)) { /* Call-site check */ inf = die_get_call_file(&die_mem); - if ((inf && !strcmp(inf, decf)) && + if ((inf == decf || (inf && decf && !strcmp(inf, decf))) && die_get_call_lineno(&die_mem) == lineno) goto found; - dwarf_decl_line(&die_mem, &inl); + if (dwarf_decl_line(&die_mem, &inl) != 0) + inl = 0; if (inl != decl || decf != die_get_decl_file(&die_mem)) continue; @@ -1034,8 +1030,10 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) .data = data, .retval = 0, }; - dwarf_getfuncs(cu_die, __die_walk_culines_cb, ¶m, 0); - ret = param.retval; + if (dwarf_getfuncs(cu_die, __die_walk_culines_cb, ¶m, 0) < 0) + ret = -EINVAL; + else + ret = param.retval; } return ret; @@ -1939,10 +1937,12 @@ static bool die_get_postprologue_addr(unsigned long entrypc_idx, break; } - dwarf_lineaddr(line, postprologue_addr); - if (*postprologue_addr >= highpc) - dwarf_lineaddr(dwarf_onesrcline(lines, i - 1), - postprologue_addr); + if (dwarf_lineaddr(line, postprologue_addr) != 0) + return false; + if (*postprologue_addr >= highpc) { + if (dwarf_lineaddr(dwarf_onesrcline(lines, i - 1), postprologue_addr) != 0) + return false; + } return true; } diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index a79968a2e573..161f0bf980b6 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h @@ -10,6 +10,11 @@ #include #include +static inline const char *die_name(Dwarf_Die *die) +{ + return dwarf_diename(die) ?: ""; +} + struct strbuf; /* Find the realpath of the target file */ From 674dea094ef6594ea1aa0efb074a4646a81350b2 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 4 May 2026 01:12:21 -0700 Subject: [PATCH 003/343] perf srcline: Introduce inline_node__clear_frames() Introduce inline_node__clear_frames() to clean up partial allocations. This is a prerequisite for error handling in libdw inline unwinding. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zecheng Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/srcline.c | 9 ++++++++- tools/perf/util/srcline.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index db164d258163..62884428fb5a 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -429,10 +429,13 @@ struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr, return addr2inlines(dso_name, addr, dso, sym); } -void inline_node__delete(struct inline_node *node) +void inline_node__clear_frames(struct inline_node *node) { struct inline_list *ilist, *tmp; + if (node == NULL) + return; + list_for_each_entry_safe(ilist, tmp, &node->val, list) { list_del_init(&ilist->list); zfree_srcline(&ilist->srcline); @@ -441,7 +444,11 @@ void inline_node__delete(struct inline_node *node) symbol__delete(ilist->symbol); free(ilist); } +} +void inline_node__delete(struct inline_node *node) +{ + inline_node__clear_frames(node); free(node); } diff --git a/tools/perf/util/srcline.h b/tools/perf/util/srcline.h index 7c37b3bf9ce7..1018cbc886d6 100644 --- a/tools/perf/util/srcline.h +++ b/tools/perf/util/srcline.h @@ -47,6 +47,7 @@ struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr, struct symbol *sym); /* free resources associated to the inline node list */ void inline_node__delete(struct inline_node *node); +void inline_node__clear_frames(struct inline_node *node); /* insert the inline node list into the DSO, which will take ownership */ void inlines__tree_insert(struct rb_root_cached *tree, From 0e18b5bb7c9d2b4c6295c5307658759fdc280e39 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 4 May 2026 01:12:22 -0700 Subject: [PATCH 004/343] perf libdw: Fix callchain parent update in ORDER_CALLER mode Fix the parent srcline lookup in `libdw_a2l_cb()` to target the correct parent node depending on the callchain order (ORDER_CALLER/ORDER_CALLEE). This ensures inline callchains are not corrupted when nest depth > 2. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zecheng Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/libdw.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/libdw.c b/tools/perf/util/libdw.c index 216977884103..301642084c69 100644 --- a/tools/perf/util/libdw.c +++ b/tools/perf/util/libdw.c @@ -4,6 +4,7 @@ #include "srcline.h" #include "symbol.h" #include "dwarf-aux.h" +#include "callchain.h" #include #include #include @@ -80,7 +81,6 @@ static int libdw_a2l_cb(Dwarf_Die *die, void *_args) struct symbol *inline_sym = new_inline_sym(args->dso, args->sym, dwarf_diename(die)); const char *call_fname = die_get_call_file(die); char *call_srcline = srcline__unknown; - struct inline_list *ilist; if (!inline_sym) return -ENOMEM; @@ -89,14 +89,20 @@ static int libdw_a2l_cb(Dwarf_Die *die, void *_args) if (call_fname) call_srcline = srcline_from_fileline(call_fname, die_get_call_lineno(die)); - list_for_each_entry(ilist, &args->node->val, list) { - if (args->leaf_srcline == ilist->srcline) + if (!list_empty(&args->node->val)) { + struct inline_list *parent; + + if (callchain_param.order == ORDER_CALLEE) + parent = list_first_entry(&args->node->val, struct inline_list, list); + else + parent = list_last_entry(&args->node->val, struct inline_list, list); + + if (args->leaf_srcline == parent->srcline) args->leaf_srcline_used = false; - else if (ilist->srcline != srcline__unknown) - free(ilist->srcline); - ilist->srcline = call_srcline; + else if (parent->srcline != srcline__unknown) + free(parent->srcline); + parent->srcline = call_srcline; call_srcline = NULL; - break; } if (call_srcline && call_srcline != srcline__unknown) free(call_srcline); From 15f8c22c462b7670d3b047d46419a92f19819fc2 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 4 May 2026 01:12:23 -0700 Subject: [PATCH 005/343] perf libdw: Support DWARF line 0 in inline list Allow DWARF line 0 in `libdw_a2l_cb()`, as it is a valid reference for compiler-generated code. Filter `die_get_call_lineno` error codes (negative values), but fallback to line 0 if `call_fname` is present to preserve the caller's filename instead of discarding it entirely. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zecheng Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/libdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/libdw.c b/tools/perf/util/libdw.c index 301642084c69..196b9cdf51b2 100644 --- a/tools/perf/util/libdw.c +++ b/tools/perf/util/libdw.c @@ -80,6 +80,7 @@ static int libdw_a2l_cb(Dwarf_Die *die, void *_args) struct libdw_a2l_cb_args *args = _args; struct symbol *inline_sym = new_inline_sym(args->dso, args->sym, dwarf_diename(die)); const char *call_fname = die_get_call_file(die); + int call_lineno = die_get_call_lineno(die); char *call_srcline = srcline__unknown; if (!inline_sym) @@ -87,7 +88,7 @@ static int libdw_a2l_cb(Dwarf_Die *die, void *_args) /* Assign caller information to the parent. */ if (call_fname) - call_srcline = srcline_from_fileline(call_fname, die_get_call_lineno(die)); + call_srcline = srcline_from_fileline(call_fname, call_lineno >= 0 ? call_lineno : 0); if (!list_empty(&args->node->val)) { struct inline_list *parent; From 9c6d535ddb794fb540c3b142ab1d7416d469c1de Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 4 May 2026 01:12:24 -0700 Subject: [PATCH 006/343] perf libdw: Fix libdw API contract violations and memory leaks Check return values of `dwfl_report_end` and `dwfl_module_addrdie` to prevent using uninitialized stack variables or reporting success on failure. Additionally: - Ensure `*file` is freed and inline frames are cleared on error in `libdw__addr2line()` to prevent memory leaks and duplicated callchains when falling back to other unwinders. - Use `die_name()` safe wrapper inside the inline function unwinding callback (`libdw_a2l_cb`). - Refactor `libdw_a2l_cb`'s repeated memory error handling/cleanup paths using a cleaner goto control flow. Fixes: b7a2b011e9627ff3 ("perf powerpc: Unify the skip-callchain-idx libdw with that for addr2line") Fixes: 88c51002d06f9a68 ("perf addr2line: Add a libdw implementation") Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zecheng Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/libdw.c | 49 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/libdw.c b/tools/perf/util/libdw.c index 196b9cdf51b2..84713b2a7ad5 100644 --- a/tools/perf/util/libdw.c +++ b/tools/perf/util/libdw.c @@ -61,7 +61,10 @@ struct Dwfl *dso__libdw_dwfl(struct dso *dso) return NULL; } - dwfl_report_end(dwfl, /*removed=*/NULL, /*arg=*/NULL); + if (dwfl_report_end(dwfl, /*removed=*/NULL, /*arg=*/NULL) != 0) { + dwfl_end(dwfl); + return NULL; + } dso__set_libdw(dso, dwfl); return dwfl; @@ -73,18 +76,19 @@ struct libdw_a2l_cb_args { struct inline_node *node; char *leaf_srcline; bool leaf_srcline_used; + int err; }; static int libdw_a2l_cb(Dwarf_Die *die, void *_args) { struct libdw_a2l_cb_args *args = _args; - struct symbol *inline_sym = new_inline_sym(args->dso, args->sym, dwarf_diename(die)); + struct symbol *inline_sym = new_inline_sym(args->dso, args->sym, die_name(die)); const char *call_fname = die_get_call_file(die); int call_lineno = die_get_call_lineno(die); char *call_srcline = srcline__unknown; if (!inline_sym) - return -ENOMEM; + goto abort_enomem; /* Assign caller information to the parent. */ if (call_fname) @@ -110,12 +114,27 @@ static int libdw_a2l_cb(Dwarf_Die *die, void *_args) /* Add this symbol to the chain as the leaf. */ if (!args->leaf_srcline_used) { - inline_list__append_tail(inline_sym, args->leaf_srcline, args->node); + if (inline_list__append_tail(inline_sym, args->leaf_srcline, args->node) != 0) + goto abort_delete_sym; args->leaf_srcline_used = true; } else { - inline_list__append_tail(inline_sym, strdup(args->leaf_srcline), args->node); + char *srcline = strdup(args->leaf_srcline); + + if (!srcline) + goto abort_delete_sym; + if (inline_list__append_tail(inline_sym, srcline, args->node) != 0) { + free(srcline); + goto abort_delete_sym; + } } return 0; + +abort_delete_sym: + if (inline_sym->inlined) + symbol__delete(inline_sym); +abort_enomem: + args->err = -ENOMEM; + return DWARF_CB_ABORT; } int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr, @@ -169,11 +188,29 @@ int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr, .leaf_srcline = srcline_from_fileline(src ?: "", lineno), }; + if (!args.leaf_srcline) { + if (file && *file) { + free(*file); + *file = NULL; + } + return 0; + } + /* Walk from the parent down to the leaf. */ - cu_walk_functions_at(cudie, addr, libdw_a2l_cb, &args); + if (cudie) + cu_walk_functions_at(cudie, addr, libdw_a2l_cb, &args); if (!args.leaf_srcline_used) free(args.leaf_srcline); + + if (args.err) { + if (file && *file) { + free(*file); + *file = NULL; + } + inline_node__clear_frames(node); + return 0; + } } return 1; } From 9a2ef19b5f5218d35c161f272a901f6c070faf79 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 4 May 2026 01:12:25 -0700 Subject: [PATCH 007/343] perf probe-finder: Fix libdw API contract violations Check return values of `dwarf_formsdata`, `dwarf_entrypc`, `dwarf_highpc`, `dwarf_bytesize`, `dwarf_attr`, `dwarf_decl_line`, `dwarf_getfuncs`, and `dwarf_formref_die`. Validate `dwarf_diename` and `dwarf_diecu` results to prevent potential crashes. Fix C90 mixed declarations. Additionally: - Avoid vfprintf undefined behavior with NULL strings by using the `die_name()` helper for `dwarf_diename()` in `pr_*` calls, including when warning about tail calls. - Prevent NULL pointer dereference in `convert_variable_fields()` when processing array elements for variables in registers. - Fallback to offset 0 in `line_range_search_cb()` instead of skipping functions without `DW_AT_decl_line`. - Relax `dwarf_getfuncs` error checking in `find_probe_point_by_func()` and `find_line_range_by_func()` to prevent premature CU search aborts, ensuring robustness against corrupted CUs. Fixes: 66f69b2197167cb9 ("perf probe: Support DW_AT_const_value constant value") Fixes: 3d918a12a1b3088a ("perf probe: Find fentry mcount fuzzed parameter location") Fixes: bcfc082150c6b1e9 ("perf probe: Remove redundant dwarf functions") Fixes: 221d061182b8ff55 ("perf probe: Fix to search local variables in appropriate scope") Fixes: b55a87ade3839c33 ("perf probe: Remove die() from probe-finder code") Fixes: 4c859351226c920b ("perf probe: Support glob wildcards for function name") Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zecheng Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-finder.c | 102 +++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 64328abeef8b..f3f9a1573502 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -79,7 +79,7 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, unsigned int regn; Dwarf_Word offs = 0; bool ref = false; - const char *regs; + const char *regs, *name; int ret, ret2 = 0; if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL) @@ -93,7 +93,8 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, if (!tvar) return 0; - dwarf_formsdata(&attr, &snum); + if (dwarf_formsdata(&attr, &snum) != 0) + return -ENOENT; ret = asprintf(&tvar->value, "\\%ld", (long)snum); return ret < 0 ? -ENOMEM : 0; @@ -103,8 +104,7 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) return -EINVAL; /* Broken DIE ? */ if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) { - ret = dwarf_entrypc(sp_die, &tmp); - if (ret) + if (dwarf_entrypc(sp_die, &tmp) != 0) return -ENOENT; if (probe_conf.show_location_range && @@ -115,8 +115,7 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, return -ENOENT; } - ret = dwarf_highpc(sp_die, &tmp); - if (ret) + if (dwarf_highpc(sp_die, &tmp) != 0) return -ENOENT; /* * This is fuzzed by fentry mcount. We try to find the @@ -138,12 +137,16 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, static_var: if (!tvar) return ret2; + /* Static variables on memory (not stack), make @varname */ - ret = strlen(dwarf_diename(vr_die)); + name = dwarf_diename(vr_die); + if (!name) + return -ENOENT; + ret = strlen(name); tvar->value = zalloc(ret + 2); if (tvar->value == NULL) return -ENOMEM; - snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die)); + snprintf(tvar->value, ret + 2, "@%s", name); tvar->ref = alloc_trace_arg_ref((long)offs); if (tvar->ref == NULL) return -ENOMEM; @@ -234,13 +237,14 @@ static int convert_variable_type(Dwarf_Die *vr_die, } if (die_get_real_type(vr_die, &type) == NULL) { - pr_warning("Failed to get a type information of %s.\n", - dwarf_diename(vr_die)); + const char *name = dwarf_diename(vr_die); + + pr_warning("Failed to get a type information of %s.\n", name ?: ""); return -ENOENT; } pr_debug("%s type is %s.\n", - dwarf_diename(vr_die), dwarf_diename(&type)); + die_name(vr_die), die_name(&type)); if (cast && (!strcmp(cast, "string") || !strcmp(cast, "ustring"))) { /* String type */ @@ -249,7 +253,7 @@ static int convert_variable_type(Dwarf_Die *vr_die, ret != DW_TAG_array_type) { pr_warning("Failed to cast into string: " "%s(%s) is not a pointer nor array.\n", - dwarf_diename(vr_die), dwarf_diename(&type)); + die_name(vr_die), die_name(&type)); return -EINVAL; } if (die_get_real_type(&type, &type) == NULL) { @@ -272,7 +276,7 @@ static int convert_variable_type(Dwarf_Die *vr_die, !die_compare_name(&type, "unsigned char")) { pr_warning("Failed to cast into string: " "%s is not (unsigned) char *.\n", - dwarf_diename(vr_die)); + die_name(vr_die)); return -EINVAL; } tvar->type = strdup(cast); @@ -299,7 +303,7 @@ static int convert_variable_type(Dwarf_Die *vr_die, /* Check the bitwidth */ if (ret > MAX_BASIC_TYPE_BITS) { pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n", - dwarf_diename(&type), MAX_BASIC_TYPE_BITS); + die_name(&type), MAX_BASIC_TYPE_BITS); ret = MAX_BASIC_TYPE_BITS; } ret = snprintf(buf, 16, "%c%d", prefix, ret); @@ -333,12 +337,14 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, pr_warning("Failed to get the type of %s.\n", varname); return -ENOENT; } - pr_debug2("Var real type: %s (%x)\n", dwarf_diename(&type), + pr_debug2("Var real type: %s (%x)\n", die_name(&type), (unsigned)dwarf_dieoffset(&type)); tag = dwarf_tag(&type); if (field->name[0] == '[' && (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { + int bsize; + /* Save original type for next field or type */ memcpy(die_mem, &type, sizeof(*die_mem)); /* Get the type of this array */ @@ -346,7 +352,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, pr_warning("Failed to get the type of %s.\n", varname); return -ENOENT; } - pr_debug2("Array real type: %s (%x)\n", dwarf_diename(&type), + pr_debug2("Array real type: %s (%x)\n", die_name(&type), (unsigned)dwarf_dieoffset(&type)); if (tag == DW_TAG_pointer_type) { ref = zalloc(sizeof(struct probe_trace_arg_ref)); @@ -357,7 +363,15 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, else *ref_ptr = ref; } - ref->offset += dwarf_bytesize(&type) * field->index; + bsize = dwarf_bytesize(&type); + + if (bsize < 0) + return -EINVAL; + if (!ref) { + pr_warning("Array indexing not supported for variables in registers.\n"); + return -ENOTSUP; + } + ref->offset += bsize * field->index; ref->user_access = user_access; goto next; } else if (tag == DW_TAG_pointer_type) { @@ -414,7 +428,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, if (die_find_member(&type, field->name, die_mem) == NULL) { pr_warning("%s(type:%s) has no member %s.\n", varname, - dwarf_diename(&type), field->name); + die_name(&type), field->name); return -EINVAL; } @@ -461,7 +475,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) int ret; pr_debug("Converting variable %s into trace event.\n", - dwarf_diename(vr_die)); + die_name(vr_die)); ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, &pf->sp_die, pf, pf->tvar); @@ -542,7 +556,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, /* Verify the address is correct */ if (!dwarf_haspc(sp_die, paddr)) { pr_warning("Specified offset is out of %s\n", - dwarf_diename(sp_die)); + die_name(sp_die)); return -EINVAL; } @@ -599,7 +613,7 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { if (die_find_tailfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { pr_warning("Ignoring tail call from %s\n", - dwarf_diename(&pf->sp_die)); + die_name(&pf->sp_die)); return 0; } else { pr_warning("Failed to find probe point in any " @@ -611,10 +625,16 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die)); /* Get the frame base attribute/ops from subprogram */ - dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr); - ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); - if (ret <= 0 || nops == 0) { + if (dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr) == NULL) { pf->fb_ops = NULL; + } else { + ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); + if (ret <= 0 || nops == 0) + pf->fb_ops = NULL; + } + + if (pf->fb_ops == NULL) { + /* Not supported */ } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && (pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) { if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 && @@ -667,8 +687,8 @@ static int find_best_scope_cb(Dwarf_Die *fn_die, void *data) } } else { /* With the line number, find the nearest declared DIE */ - dwarf_decl_line(fn_die, &lno); - if (lno < fsp->line && fsp->diff > fsp->line - lno) { + if (dwarf_decl_line(fn_die, &lno) == 0 && lno < fsp->line && + fsp->diff > fsp->line - lno) { /* Keep a candidate and continue */ fsp->diff = fsp->line - lno; memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); @@ -924,12 +944,12 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) /* Get probe address */ if (die_entrypc(in_die, &addr) != 0) { pr_warning("Failed to get entry address of %s.\n", - dwarf_diename(in_die)); + die_name(in_die)); return -ENOENT; } if (addr == 0) { pr_debug("%s has no valid entry address. skipped.\n", - dwarf_diename(in_die)); + die_name(in_die)); return -ENOENT; } pf->addr = addr; @@ -971,12 +991,13 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) if (pp->file && fname && strtailcmp(pp->file, fname)) return DWARF_CB_OK; - pr_debug("Matched function: %s [%lx]\n", dwarf_diename(sp_die), + pr_debug("Matched function: %s [%lx]\n", die_name(sp_die), (unsigned long)dwarf_dieoffset(sp_die)); pf->fname = fname; pf->abstrace_dieoffset = dwarf_dieoffset(sp_die); if (pp->line) { /* Function relative line */ - dwarf_decl_line(sp_die, &pf->lno); + if (dwarf_decl_line(sp_die, &pf->lno) != 0) + return DWARF_CB_OK; pf->lno += pp->line; param->retval = find_probe_point_by_line(pf); } else if (die_is_func_instance(sp_die)) { @@ -985,7 +1006,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) /* But in some case the entry address is 0 */ if (pf->addr == 0) { pr_debug("%s has no entry PC. Skipped\n", - dwarf_diename(sp_die)); + die_name(sp_die)); param->retval = 0; /* Real function */ } else if (pp->lazy_line) @@ -1018,7 +1039,8 @@ static int find_probe_point_by_func(struct probe_finder *pf) { struct dwarf_callback_param _param = {.data = (void *)pf, .retval = 0}; - dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0); + if (dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0) < 0) + pr_debug("Failed to get functions from CU\n"); return _param.retval; } @@ -1207,7 +1229,8 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data) * points to correct die. */ if (dwarf_attr(die_mem, DW_AT_abstract_origin, &attr)) { - dwarf_formref_die(&attr, &var_die); + if (dwarf_formref_die(&attr, &var_die) == NULL) + goto out; if (pf->abstrace_dieoffset != dwarf_dieoffset(&var_die)) goto out; } @@ -1293,13 +1316,16 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) if (ret < 0) goto end; - tev->point.realname = strdup(dwarf_diename(sc_die)); + tev->point.realname = strdup(die_name(sc_die)); if (!tev->point.realname) { ret = -ENOMEM; goto end; } - tev->lang = dwarf_srclang(dwarf_diecu(sc_die, &pf->cu_die, NULL, NULL)); + if (dwarf_diecu(sc_die, &pf->cu_die, NULL, NULL) != NULL) + tev->lang = dwarf_srclang(&pf->cu_die); + else + tev->lang = DW_LANG_C; /* Fallback */ pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, tev->point.offset); @@ -1794,7 +1820,8 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) if (die_match_name(sp_die, lr->function) && die_is_func_def(sp_die)) { lf->fname = die_get_decl_file(sp_die); - dwarf_decl_line(sp_die, &lr->offset); + if (dwarf_decl_line(sp_die, &lr->offset) != 0) + lr->offset = 0; /* Fallback if no line info */ pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); lf->lno_s = lr->offset + lr->start; if (lf->lno_s < 0) /* Overflow */ @@ -1818,7 +1845,8 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) static int find_line_range_by_func(struct line_finder *lf) { struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; - dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0); + if (dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0) < 0) + pr_debug("Failed to get functions from CU\n"); return param.retval; } From 5aa1941900050a2c80d29bc7ee0dfbddbad8f294 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 4 May 2026 01:12:26 -0700 Subject: [PATCH 008/343] perf annotate-data: Fix libdw API contract violations Check return values of `dwarf_aggregate_size` and `dwarf_formudata`. Additionally: - Avoid `vfprintf` undefined behavior with `NULL` strings by using the `die_name()` helper for `dwarf_diename()` in `pr_*` calls. - Use `die_get_data_member_location()` (updated to use `dwarf_attr_integrate`) to correctly parse location expressions for inherited member locations in the fallback path when `dwarf_formudata()` fails. Fixes: 2bc3cf575a162a2c ("perf annotate-data: Improve debug message with location info") Fixes: 4a111cadac85362e ("perf annotate-data: Add member field in the data type") Fixes: 8b1042c425f6a5a9 ("perf annotate-data: Set bitfield member offset and size properly") Fixes: fc044c53b99fad03 ("perf annotate-data: Add dso->data_types tree") Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zecheng Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate-data.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 1eff0a27237d..63e3c54fab42 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -74,7 +74,8 @@ void pr_debug_type_name(Dwarf_Die *die, enum type_state_kind kind) break; } - dwarf_aggregate_size(die, &size); + if (dwarf_aggregate_size(die, &size) != 0) + size = 0; strbuf_init(&sb, 32); die_get_typename_from_type(die, &sb); @@ -146,9 +147,9 @@ static void pr_debug_scope(Dwarf_Die *scope_die) tag = dwarf_tag(scope_die); if (tag == DW_TAG_subprogram) - pr_info("[function] %s\n", dwarf_diename(scope_die)); + pr_info("[function] %s\n", die_name(scope_die)); else if (tag == DW_TAG_inlined_subroutine) - pr_info("[inlined] %s\n", dwarf_diename(scope_die)); + pr_info("[inlined] %s\n", die_name(scope_die)); else if (tag == DW_TAG_lexical_block) pr_info("[block]\n"); else @@ -250,9 +251,12 @@ static int __add_member_cb(Dwarf_Die *die, void *arg) if (dwarf_aggregate_size(&die_mem, &size) < 0) size = 0; - if (dwarf_attr_integrate(die, DW_AT_data_member_location, &attr)) - dwarf_formudata(&attr, &loc); - else { + if (dwarf_attr_integrate(die, DW_AT_data_member_location, &attr)) { + if (dwarf_formudata(&attr, &loc) != 0) { + if (die_get_data_member_location(die, &loc) != 0) + loc = 0; + } + } else { /* bitfield member */ if (dwarf_attr_integrate(die, DW_AT_data_bit_offset, &attr) && dwarf_formudata(&attr, &loc) == 0) @@ -273,7 +277,9 @@ static int __add_member_cb(Dwarf_Die *die, void *arg) dwarf_diename(die), (long)bit_size) < 0) member->var_name = NULL; } else { - member->var_name = strdup(dwarf_diename(die)); + const char *name = dwarf_diename(die); + + member->var_name = name ? strdup(name) : NULL; } if (member->var_name == NULL) { @@ -370,7 +376,8 @@ static struct annotated_data_type *dso__findnew_data_type(struct dso *dso, if (dwarf_tag(type_die) == DW_TAG_typedef) die_get_real_type(type_die, type_die); - dwarf_aggregate_size(type_die, &size); + if (dwarf_aggregate_size(type_die, &size) != 0) + size = 0; /* Check existing nodes in dso->data_types tree */ key.self.type_name = type_name; @@ -1569,7 +1576,7 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) offset = loc->offset; pr_debug_dtp("CU for %s (die:%#lx)\n", - dwarf_diename(&cu_die), (long)dwarf_dieoffset(&cu_die)); + die_name(&cu_die), (long)dwarf_dieoffset(&cu_die)); if (reg == DWARF_REG_PC) { if (get_global_var_type(&cu_die, dloc, dloc->ip, dloc->var_addr, @@ -1636,7 +1643,7 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die) } pr_debug_dtp("found \"%s\" (die: %#lx) in scope=%d/%d (die: %#lx) ", - dwarf_diename(&var_die), (long)dwarf_dieoffset(&var_die), + die_name(&var_die), (long)dwarf_dieoffset(&var_die), i+1, nr_scopes, (long)dwarf_dieoffset(&scopes[i])); if (reg == DWARF_REG_PC) { From 31088ccf0312b1a547046f1f69890ede07834a30 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 4 May 2026 01:12:27 -0700 Subject: [PATCH 009/343] perf debuginfo: Fix libdw API contract violations Check return value of `dwfl_report_end` during offline initialization. Validate `dwfl_module_relocation_info` result before passing to `strcmp` to avoid potential segmentation faults. Additionally: - Fix a file descriptor leak in `debuginfo__init_offline_dwarf()` when `dwfl_report_offline()` or subsequent setup calls fail. Fixes: 6f1b6291cf73cb32 ("perf tools: Add util/debuginfo.[ch] files") Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zecheng Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/debuginfo.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/debuginfo.c b/tools/perf/util/debuginfo.c index 0e35c13abd04..84a78b30ceac 100644 --- a/tools/perf/util/debuginfo.c +++ b/tools/perf/util/debuginfo.c @@ -42,6 +42,7 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, { GElf_Addr dummy; int fd; + bool fd_consumed = false; fd = open(path, O_RDONLY); if (fd < 0) @@ -55,6 +56,7 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); if (!dbg->mod) goto error; + fd_consumed = true; dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias); if (!dbg->dbg) @@ -62,13 +64,14 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy); - dwfl_report_end(dbg->dwfl, NULL, NULL); + if (dwfl_report_end(dbg->dwfl, NULL, NULL) != 0) + goto error; return 0; error: if (dbg->dwfl) dwfl_end(dbg->dwfl); - else + if (!fd_consumed) close(fd); memset(dbg, 0, sizeof(*dbg)); @@ -167,7 +170,7 @@ int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, /* Search the relocation related .text section */ for (i = 0; i < n; i++) { p = dwfl_module_relocation_info(dbg->mod, i, &shndx); - if (strcmp(p, ".text") == 0) { + if (p && strcmp(p, ".text") == 0) { /* OK, get the section header */ scn = elf_getscn(elf, shndx); if (!scn) From ae15db3e9b639491007cc1e9e99638e4b6091781 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Tue, 14 Apr 2026 14:42:41 +0200 Subject: [PATCH 010/343] perf callchain: Handle multiple address spaces perf test 'perf inject to convert DWARF callchains to regular ones' fails on s390. It was introduced with commit 92ea788d2af4e65a ("perf inject: Add --convert-callchain option") The failure comes the difference in output. Without the inject script to convert DWARF the callchains is: # perf record -F 999 --call-graph dwarf -- perf test -w noploop # perf report -i perf.data --stdio --no-children -q \ --percent-limit=1 > /tmp/111 # cat /tmp/111 99.30% perf-noploop perf [.] noploop | ---noploop run_workload (inlined) cmd_test run_builtin (inlined) handle_internal_command run_argv (inlined) main __libc_start_call_main __libc_start_main_impl (inlined) _start # With the inject script step the output is: # perf inject -i perf.data --convert-callchain -o /tmp/perf-inject-1.out # perf report -i /tmp/perf-inject-1.out --stdio --no-children -q \ --percent-limit=1 > /tmp/222 # cat /tmp/222 99.40% perf-noploop perf [.] noploop | ---noploop run_workload (inlined) cmd_test run_builtin (inlined) handle_internal_command run_argv (inlined) main _start # diff /tmp/111 /tmp/222 1c1 < 99.30% perf-noploop perf [.] noploop --- > 99.40% perf-noploop perf [.] noploop 10,11d9 < __libc_start_call_main < __libc_start_main_impl (inlined) # The difference are the symbols __libc_start_call_main and __libc_start_main_impl. On x86_64, kernel and user space share a single virtual address space, with the kernel mapped to the upper end of memory. The instruction pointer value alone is sufficient to distinguish between user space and kernel space addresses. This is not true for s390, which uses separate address spaces for user and kernel. The same virtual address can be valid in both address spaces, so the instruction pointer value alone cannot determine whether an address belongs to the kernel or user space. Instead, perf must rely on the cpumode metadata derived from the processor status word (PSW) at sample time. In function perf_event__convert_sample_callchain() the first part copies a kernel callchain and context entries, if any. It then appends additional entries ignoring the address space architecture. Taking that into account, the symbols at addresses 0x3ff970348cb __libc_start_call_main 0x3ff970349c5 __libc_start_main_impl (located after the kernel address space on s390) are now included. Output before: # perf test 83 83: perf inject to convert DWARF callchains to regular ones : FAILED! Output after: # perf test 83 83: perf inject to convert DWARF callchains to regular ones : Ok Question to Namhyung: In function perf_event__convert_sample_callchain() just before the for() loop this patch modifies, the kernel callchain is copied, see this comment and the next 5 lines: /* copy kernel callchain and context entries */ Then why is machine__kernel_ip() needed in the for() loop, when the kernel entries have been copied just before the loop? Note: This patch was tested on x86_64 virtual machine and succeeded. Fixes: 92ea788d2af4e65a ("perf inject: Add --convert-callchain option") Signed-off-by: Thomas Richter Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Jan Polensky Cc: linux-s390@vger.kernel.org Cc: Sumanth Korikkar Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/common.c | 4 +++- tools/perf/builtin-inject.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index 21836f70f231..ad0cab830a4d 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c @@ -237,5 +237,7 @@ int perf_env__lookup_objdump(struct perf_env *env, char **path) */ bool perf_env__single_address_space(struct perf_env *env) { - return strcmp(perf_env__arch(env), "sparc"); + const char *arch = perf_env__arch(env); + + return strcmp(arch, "s390") && strcmp(arch, "sparc"); } diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index f174bc69cec4..6ab20df358c4 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -438,7 +438,8 @@ static int perf_event__convert_sample_callchain(const struct perf_tool *tool, node = cursor->first; for (k = 0; k < cursor->nr && i < PERF_MAX_STACK_DEPTH; k++) { - if (machine__kernel_ip(machine, node->ip)) + if (machine->single_address_space && + machine__kernel_ip(machine, node->ip)) /* kernel IPs were added already */; else if (node->ms.sym && node->ms.sym->inlined) /* we can't handle inlined callchains */; From 8e32bd775cc882ea591c75cac9e7d9c4ad68f7c6 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 14 Apr 2026 13:47:59 +0100 Subject: [PATCH 011/343] perf arm_spe: Make a function to get the MIDR We'll need the MIDR to dump IMPDEF events in the next commits so extract a function for it. No functional changes intended. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Mark Rutland Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/arm-spe.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index e5835042acdf..39046033e143 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -972,14 +972,9 @@ static void arm_spe__synth_memory_level(struct arm_spe_queue *speq, } } -static void arm_spe__synth_ds(struct arm_spe_queue *speq, - const struct arm_spe_record *record, - union perf_mem_data_src *data_src) +static int arm_spe__get_midr(struct arm_spe *spe, int cpu, u64 *midr) { - struct arm_spe *spe = speq->spe; - u64 *metadata = NULL; - u64 midr; - unsigned int i; + u64 *metadata; /* Metadata version 1 assumes all CPUs are the same (old behavior) */ if (spe->metadata_ver == 1) { @@ -987,15 +982,28 @@ static void arm_spe__synth_ds(struct arm_spe_queue *speq, pr_warning_once("Old SPE metadata, re-record to improve decode accuracy\n"); cpuid = perf_env__cpuid(perf_session__env(spe->session)); - midr = strtol(cpuid, NULL, 16); - } else { - metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu); - if (!metadata) - return; - - midr = metadata[ARM_SPE_CPU_MIDR]; + *midr = strtol(cpuid, NULL, 16); + return 0; } + metadata = arm_spe__get_metadata_by_cpu(spe, cpu); + if (!metadata) + return -EINVAL; + + *midr = metadata[ARM_SPE_CPU_MIDR]; + return 0; +} + +static void arm_spe__synth_ds(struct arm_spe_queue *speq, + const struct arm_spe_record *record, + union perf_mem_data_src *data_src) +{ + u64 midr; + unsigned int i; + + if (arm_spe__get_midr(speq->spe, speq->cpu, &midr)) + return; + for (i = 0; i < ARRAY_SIZE(data_source_handles); i++) { if (is_midr_in_range_list(midr, data_source_handles[i].midr_ranges)) { return data_source_handles[i].ds_synth(record, data_src); From 0c7e4d11fb8d490c8f64ea98d05e441c9e26c6ee Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 14 Apr 2026 13:48:00 +0100 Subject: [PATCH 012/343] perf arm_spe: Handle missing CPU IDs Don't call strtol() with a null pointer to avoid undefined behavior. I'm not sure of the exact scenario for missing CPU IDs but I don't think it happens in practice. SPE decoding can continue without them with reduced functionality, but print an error message anyway. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Mark Rutland Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/arm-spe.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 39046033e143..037c7aa150c1 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -982,16 +982,23 @@ static int arm_spe__get_midr(struct arm_spe *spe, int cpu, u64 *midr) pr_warning_once("Old SPE metadata, re-record to improve decode accuracy\n"); cpuid = perf_env__cpuid(perf_session__env(spe->session)); + if (!cpuid) + goto err; + *midr = strtol(cpuid, NULL, 16); return 0; } metadata = arm_spe__get_metadata_by_cpu(spe, cpu); if (!metadata) - return -EINVAL; + goto err; *midr = metadata[ARM_SPE_CPU_MIDR]; return 0; + +err: + pr_warning_once("Failed to get MIDR for CPU %d\n", cpu); + return -EINVAL; } static void arm_spe__synth_ds(struct arm_spe_queue *speq, From 8cf4d17ec7f0bebff8f3de3131e0c7e422a36da6 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 14 Apr 2026 13:48:01 +0100 Subject: [PATCH 013/343] perf arm_spe: Store MIDR in arm_spe_pkt The MIDR will affect printing of arm_spe_pkts, so store a copy of it there. Technically it's constant for each decoder, but there is no decoder when doing a raw dump, so it has to be stored in every packet. It will only be used in raw dump mode and not in normal decoding for now, but to avoid any surprises, set MIDR properly on the decoder too. Having both the MIDR and the arm_spe_pkt (which has a copy of it) in the decoder seemed a bit weird, so remove arm_spe_pkt from the decoder. The packet is only short lived anyway so probably shouldn't have been there in the first place. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Mark Rutland Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Arnaldo Carvalho de Melo --- .../util/arm-spe-decoder/arm-spe-decoder.c | 17 ++++++++------- .../util/arm-spe-decoder/arm-spe-decoder.h | 3 +-- .../arm-spe-decoder/arm-spe-pkt-decoder.c | 3 ++- .../arm-spe-decoder/arm-spe-pkt-decoder.h | 3 ++- tools/perf/util/arm-spe.c | 21 +++++++++++++------ 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 9e02b2bdd117..7a3a4815fd37 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -120,7 +120,8 @@ static int arm_spe_get_data(struct arm_spe_decoder *decoder) return decoder->len; } -static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder) +static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder, + struct arm_spe_pkt *packet) { int ret; @@ -134,7 +135,8 @@ static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder) } ret = arm_spe_get_packet(decoder->buf, decoder->len, - &decoder->packet); + packet, decoder->midr); + if (ret <= 0) { /* Move forward for 1 byte */ decoder->buf += 1; @@ -144,7 +146,7 @@ static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder) decoder->buf += ret; decoder->len -= ret; - } while (decoder->packet.type == ARM_SPE_PAD); + } while (packet->type == ARM_SPE_PAD); return 1; } @@ -154,19 +156,20 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) int err; int idx; u64 payload, ip; + struct arm_spe_pkt packet; memset(&decoder->record, 0x0, sizeof(decoder->record)); decoder->record.context_id = (u64)-1; while (1) { - err = arm_spe_get_next_packet(decoder); + err = arm_spe_get_next_packet(decoder, &packet); if (err <= 0) return err; - idx = decoder->packet.index; - payload = decoder->packet.payload; + idx = packet.index; + payload = packet.payload; - switch (decoder->packet.type) { + switch (packet.type) { case ARM_SPE_TIMESTAMP: decoder->record.timestamp = payload; return 1; diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index 3310e05122f0..0cbcb501edc9 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -147,8 +147,7 @@ struct arm_spe_decoder { const unsigned char *buf; size_t len; - - struct arm_spe_pkt packet; + u64 midr; }; struct arm_spe_decoder *arm_spe_decoder_new(struct arm_spe_params *params); diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index 5769ba2f4140..718022aecec3 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -222,11 +222,12 @@ static int arm_spe_do_get_packet(const unsigned char *buf, size_t len, } int arm_spe_get_packet(const unsigned char *buf, size_t len, - struct arm_spe_pkt *packet) + struct arm_spe_pkt *packet, u64 midr) { int ret; ret = arm_spe_do_get_packet(buf, len, packet); + packet->midr = midr; /* put multiple consecutive PADs on the same line, up to * the fixed-width output format of 16 bytes per line. */ diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h index adf4cde320aa..a457821f3bcc 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h @@ -35,6 +35,7 @@ struct arm_spe_pkt { enum arm_spe_pkt_type type; unsigned char index; uint64_t payload; + uint64_t midr; }; /* Short header (HEADER0) and extended header (HEADER1) */ @@ -184,7 +185,7 @@ enum arm_spe_events { const char *arm_spe_pkt_name(enum arm_spe_pkt_type); int arm_spe_get_packet(const unsigned char *buf, size_t len, - struct arm_spe_pkt *packet); + struct arm_spe_pkt *packet, u64 midr); int arm_spe_pkt_desc(const struct arm_spe_pkt *packet, char *buf, size_t len); #endif diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 037c7aa150c1..2b31da231ef3 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -134,8 +134,10 @@ struct data_source_handle { .ds_synth = arm_spe__synth_##func, \ } +static int arm_spe__get_midr(struct arm_spe *spe, int cpu, u64 *midr); + static void arm_spe_dump(struct arm_spe *spe __maybe_unused, - unsigned char *buf, size_t len) + unsigned char *buf, size_t len, u64 midr) { struct arm_spe_pkt packet; size_t pos = 0; @@ -148,7 +150,8 @@ static void arm_spe_dump(struct arm_spe *spe __maybe_unused, len); while (len) { - ret = arm_spe_get_packet(buf, len, &packet); + ret = arm_spe_get_packet(buf, len, &packet, midr); + if (ret > 0) pkt_len = ret; else @@ -174,10 +177,10 @@ static void arm_spe_dump(struct arm_spe *spe __maybe_unused, } static void arm_spe_dump_event(struct arm_spe *spe, unsigned char *buf, - size_t len) + size_t len, u64 midr) { printf(".\n"); - arm_spe_dump(spe, buf, len); + arm_spe_dump(spe, buf, len, midr); } static int arm_spe_get_trace(struct arm_spe_buffer *b, void *data) @@ -302,8 +305,10 @@ static void arm_spe_set_pid_tid_cpu(struct arm_spe *spe, if (speq->thread) { speq->pid = thread__pid(speq->thread); - if (queue->cpu == -1) + if (queue->cpu == -1) { speq->cpu = thread__cpu(speq->thread); + arm_spe__get_midr(spe, speq->cpu, &speq->decoder->midr); + } } } @@ -1248,6 +1253,7 @@ static int arm_spe__setup_queue(struct arm_spe *spe, if (queue->cpu != -1) speq->cpu = queue->cpu; + arm_spe__get_midr(spe, queue->cpu, &speq->decoder->midr); if (!speq->on_heap) { int ret; @@ -1490,8 +1496,11 @@ static int arm_spe_process_auxtrace_event(struct perf_session *session, /* Dump here now we have copied a piped trace out of the pipe */ if (dump_trace) { if (auxtrace_buffer__get_data(buffer, fd)) { + u64 midr = 0; + + arm_spe__get_midr(spe, buffer->cpu.cpu, &midr); arm_spe_dump_event(spe, buffer->data, - buffer->size); + buffer->size, midr); auxtrace_buffer__put_data(buffer); } } From 96b4910c3c6c6e9cad9a90f2e01486faef108ca1 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 14 Apr 2026 13:48:02 +0100 Subject: [PATCH 014/343] perf arm_spe: Turn event name mappings into an array This is so we can have a single function that prints events and can be used with multiple mappings from different CPUs. Remove any bit that was printed so that later we can print out the remaining unknown impdef bits. No functional changes intended. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Mark Rutland Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Arnaldo Carvalho de Melo --- .../arm-spe-decoder/arm-spe-pkt-decoder.c | 88 +++++++++---------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index 718022aecec3..67ca356100e5 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -277,6 +277,48 @@ static int arm_spe_pkt_out_string(int *err, char **buf_p, size_t *blen, return ret; } +struct ev_string { + u8 event; + const char *desc; +}; + +static const struct ev_string common_ev_strings[] = { + { .event = EV_EXCEPTION_GEN, .desc = "EXCEPTION-GEN" }, + { .event = EV_RETIRED, .desc = "RETIRED" }, + { .event = EV_L1D_ACCESS, .desc = "L1D-ACCESS" }, + { .event = EV_L1D_REFILL, .desc = "L1D-REFILL" }, + { .event = EV_TLB_ACCESS, .desc = "TLB-ACCESS" }, + { .event = EV_TLB_WALK, .desc = "TLB-REFILL" }, + { .event = EV_NOT_TAKEN, .desc = "NOT-TAKEN" }, + { .event = EV_MISPRED, .desc = "MISPRED" }, + { .event = EV_LLC_ACCESS, .desc = "LLC-ACCESS" }, + { .event = EV_LLC_MISS, .desc = "LLC-REFILL" }, + { .event = EV_REMOTE_ACCESS, .desc = "REMOTE-ACCESS" }, + { .event = EV_ALIGNMENT, .desc = "ALIGNMENT" }, + { .event = EV_TRANSACTIONAL, .desc = "TXN" }, + { .event = EV_PARTIAL_PREDICATE, .desc = "SVE-PARTIAL-PRED" }, + { .event = EV_EMPTY_PREDICATE, .desc = "SVE-EMPTY-PRED" }, + { .event = EV_L2D_ACCESS, .desc = "L2D-ACCESS" }, + { .event = EV_L2D_MISS, .desc = "L2D-MISS" }, + { .event = EV_CACHE_DATA_MODIFIED, .desc = "HITM" }, + { .event = EV_RECENTLY_FETCHED, .desc = "LFB" }, + { .event = EV_DATA_SNOOPED, .desc = "SNOOPED" }, + { .event = EV_STREAMING_SVE_MODE, .desc = "STREAMING-SVE" }, + { .event = EV_SMCU, .desc = "SMCU" }, + { .event = 0, .desc = NULL }, +}; + +static u64 print_event_list(int *err, char **buf, size_t *buf_len, + const struct ev_string *ev_strings, u64 payload) +{ + for (const struct ev_string *ev = ev_strings; ev->desc != NULL; ev++) { + if (payload & BIT_ULL(ev->event)) + arm_spe_pkt_out_string(err, buf, buf_len, " %s", ev->desc); + payload &= ~BIT_ULL(ev->event); + } + return payload; +} + static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet, char *buf, size_t buf_len) { @@ -284,51 +326,7 @@ static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet, int err = 0; arm_spe_pkt_out_string(&err, &buf, &buf_len, "EV"); - - if (payload & BIT(EV_EXCEPTION_GEN)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " EXCEPTION-GEN"); - if (payload & BIT(EV_RETIRED)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " RETIRED"); - if (payload & BIT(EV_L1D_ACCESS)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " L1D-ACCESS"); - if (payload & BIT(EV_L1D_REFILL)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " L1D-REFILL"); - if (payload & BIT(EV_TLB_ACCESS)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " TLB-ACCESS"); - if (payload & BIT(EV_TLB_WALK)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " TLB-REFILL"); - if (payload & BIT(EV_NOT_TAKEN)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " NOT-TAKEN"); - if (payload & BIT(EV_MISPRED)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " MISPRED"); - if (payload & BIT(EV_LLC_ACCESS)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " LLC-ACCESS"); - if (payload & BIT(EV_LLC_MISS)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " LLC-REFILL"); - if (payload & BIT(EV_REMOTE_ACCESS)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " REMOTE-ACCESS"); - if (payload & BIT(EV_ALIGNMENT)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " ALIGNMENT"); - if (payload & BIT(EV_TRANSACTIONAL)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " TXN"); - if (payload & BIT(EV_PARTIAL_PREDICATE)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-PARTIAL-PRED"); - if (payload & BIT(EV_EMPTY_PREDICATE)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " SVE-EMPTY-PRED"); - if (payload & BIT(EV_L2D_ACCESS)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " L2D-ACCESS"); - if (payload & BIT(EV_L2D_MISS)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " L2D-MISS"); - if (payload & BIT(EV_CACHE_DATA_MODIFIED)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " HITM"); - if (payload & BIT(EV_RECENTLY_FETCHED)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " LFB"); - if (payload & BIT(EV_DATA_SNOOPED)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " SNOOPED"); - if (payload & BIT(EV_STREAMING_SVE_MODE)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " STREAMING-SVE"); - if (payload & BIT(EV_SMCU)) - arm_spe_pkt_out_string(&err, &buf, &buf_len, " SMCU"); + print_event_list(&err, &buf, &buf_len, common_ev_strings, payload); return err; } From b566a7404161b680edd259e67375e1d73887f4b3 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 14 Apr 2026 13:48:03 +0100 Subject: [PATCH 015/343] perf arm_spe: Decode Arm N1 IMPDEF events >From the TRM [1], N1 has one IMPDEF event which isn't covered by the common list. Add a framework so that more cores can be added in the future and that the N1 IMPDEF event can be decoded. Also increase the size of the buffer because we're adding more strings and if it gets truncated it falls back to a hex dump only. [1]: https://developer.arm.com/documentation/100616/0401/Statistical-Profiling-Extension/implementation-defined-features-of-SPE Suggested-by: Al Grant Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Mark Rutland Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Link: https://developer.arm.com/documentation/100616/0401/Statistical-Profiling-Extension/implementation-defined-features-of-SPE Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/arm-spe-decoder/Build | 2 + .../arm-spe-decoder/arm-spe-pkt-decoder.c | 39 ++++++++++++++++++- .../arm-spe-decoder/arm-spe-pkt-decoder.h | 2 +- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/arm-spe-decoder/Build b/tools/perf/util/arm-spe-decoder/Build index ab500e0efe24..97a298d1e279 100644 --- a/tools/perf/util/arm-spe-decoder/Build +++ b/tools/perf/util/arm-spe-decoder/Build @@ -1 +1,3 @@ perf-util-y += arm-spe-pkt-decoder.o arm-spe-decoder.o + +CFLAGS_arm-spe-pkt-decoder.o += -I$(srctree)/tools/arch/arm64/include/ -I$(OUTPUT)arch/arm64/include/generated/ diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index 67ca356100e5..b74f887a48f2 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -15,6 +15,8 @@ #include "arm-spe-pkt-decoder.h" +#include "../../arm64/include/asm/cputype.h" + static const char * const arm_spe_packet_name[] = { [ARM_SPE_PAD] = "PAD", [ARM_SPE_END] = "END", @@ -308,6 +310,11 @@ static const struct ev_string common_ev_strings[] = { { .event = 0, .desc = NULL }, }; +static const struct ev_string n1_event_strings[] = { + { .event = 12, .desc = "LATE-PREFETCH" }, + { .event = 0, .desc = NULL }, +}; + static u64 print_event_list(int *err, char **buf, size_t *buf_len, const struct ev_string *ev_strings, u64 payload) { @@ -319,6 +326,26 @@ static u64 print_event_list(int *err, char **buf, size_t *buf_len, return payload; } +struct event_print_handle { + const struct midr_range *midr_ranges; + const struct ev_string *ev_strings; +}; + +#define EV_PRINT(range, strings) \ + { \ + .midr_ranges = range, \ + .ev_strings = strings, \ + } + +static const struct midr_range n1_event_encoding_cpus[] = { + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), + {}, +}; + +static const struct event_print_handle event_print_handles[] = { + EV_PRINT(n1_event_encoding_cpus, n1_event_strings), +}; + static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet, char *buf, size_t buf_len) { @@ -326,7 +353,17 @@ static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet, int err = 0; arm_spe_pkt_out_string(&err, &buf, &buf_len, "EV"); - print_event_list(&err, &buf, &buf_len, common_ev_strings, payload); + payload = print_event_list(&err, &buf, &buf_len, common_ev_strings, + payload); + + /* Try to decode IMPDEF bits for known CPUs */ + for (unsigned int i = 0; i < ARRAY_SIZE(event_print_handles); i++) { + if (is_midr_in_range_list(packet->midr, + event_print_handles[i].midr_ranges)) + payload = print_event_list(&err, &buf, &buf_len, + event_print_handles[i].ev_strings, + payload); + } return err; } diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h index a457821f3bcc..a3300bec4990 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h @@ -11,7 +11,7 @@ #include #include -#define ARM_SPE_PKT_DESC_MAX 256 +#define ARM_SPE_PKT_DESC_MAX 512 #define ARM_SPE_NEED_MORE_BYTES -1 #define ARM_SPE_BAD_PACKET -2 From e7ef461784945e95bb5f137383298cd2d4122a9e Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 14 Apr 2026 13:48:04 +0100 Subject: [PATCH 016/343] perf arm_spe: Print remaining IMPDEF event numbers Any IMPDEF events not printed out from a known core's IMPDEF list or for a completely unknown core will still not be shown to the user. Fix this by printing the remaining bits as comma separated raw numbers, e.g. "IMPDEF:1,2,3,4". Suggested-by: Al Grant Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Mark Rutland Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Arnaldo Carvalho de Melo --- .../util/arm-spe-decoder/arm-spe-pkt-decoder.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index b74f887a48f2..600677318f84 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -365,6 +366,23 @@ static int arm_spe_pkt_desc_event(const struct arm_spe_pkt *packet, payload); } + /* + * Print remaining IMPDEF bits that weren't printed above as raw + * "IMPDEF:1,2,3,4" etc. + */ + if (payload) { + arm_spe_pkt_out_string(&err, &buf, &buf_len, " IMPDEF:"); + for (int i = 0; i < 64; i++) { + const char *sep = payload & (payload - 1) ? "," : ""; + + if (payload & BIT_ULL(i)) { + arm_spe_pkt_out_string(&err, &buf, &buf_len, "%d%s", i, + sep); + payload &= ~BIT_ULL(i); + } + } + } + return err; } From e41cac8617a9b399bf013cda968c53927a9a0f91 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sun, 3 May 2026 23:27:56 -0700 Subject: [PATCH 017/343] perf build: Update error message for BUILD_NONDISTRO=1 It should say binutils-dev(el) instead of plain binutils package as it's mostly installed already and can confuse people like me. :) Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 333ddd0e4bd8..06d7a3f9990c 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -923,7 +923,7 @@ ifdef BUILD_NONDISTRO $(call feature_check,libbfd-liberty-z) ifneq ($(feature-libbfd-threadsafe), 1) - $(error binutils 2.42 or later is required for non-distro builds) + $(error binutils-dev(el) 2.42 or later is required for non-distro builds) endif # we may be on a system that requires -liberty and (maybe) -lz From 53bc032892782e54f33dfe18b86c461492a55fa4 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sun, 3 May 2026 23:27:57 -0700 Subject: [PATCH 018/343] perf build: Add -fms-extensions for GEN_VMLINUX_H=1 On my system, `make GEN_VMLINUX_H=1` fails with a lot of error messages like below: ./util/bpf_skel/vmlinux.h:134488:4: error: declaration does not declare anything [-Werror,-Wmissing-declarations] 134488 | struct freelist_counters; | ^~~~~~~~~~~~~~~~~~~~~~~~ make[2]: *** [Makefile.perf:1249: linux/tools/perf/util/bpf_skel/.tmp/lock_contention.bpf.o] Error 1 I saw commit 835a50753579a ("selftests/bpf: Add -fms-extensions to bpf build flags") also added the same flags to bpf programs. Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index cee19c923c06..0aba14f22a06 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -1249,6 +1249,7 @@ $(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF) $(SKEL_OUT)/vmlinux.h $(QUIET_CLANG)$(CLANG) -g -O2 -fno-stack-protector --target=bpf \ $(CLANG_OPTIONS) $(EXTRA_BPF_FLAGS) $(BPF_INCLUDE) $(TOOLS_UAPI_INCLUDE) \ -include $(OUTPUT)PERF-VERSION-FILE -include util/bpf_skel/perf_version.h \ + -fms-extensions -Wno-microsoft-anon-tag \ -c $(filter util/bpf_skel/%.bpf.c,$^) -o $@ $(SKEL_OUT)/%.skel.h: $(SKEL_TMP_OUT)/%.bpf.o | $(BPFTOOL) From 8c8f2093614373ea8179b562320212a25cf937c0 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sun, 3 May 2026 23:27:58 -0700 Subject: [PATCH 019/343] perf build: Remove NO_GTK2 build test 4751bddd3f983af2 ("perf tools: Make GTK2 support opt-in") changed GTK2 build to be opt-in. So NO_GTK2 is meaningless and we need to pass GTK2=1 to enable it. Let's update the build-test configuration for that. Also make_no_ui is the same as make_no_slang since NO_GTK2 is no-op. Let's get rid of it as well. Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 6587dc326d1b..dbd7c86a2dcc 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -78,8 +78,6 @@ make_libperl := LIBPERL=1 make_no_libpython := NO_LIBPYTHON=1 make_no_scripts := NO_LIBPYTHON=1 make_no_slang := NO_SLANG=1 -make_no_gtk2 := NO_GTK2=1 -make_no_ui := NO_SLANG=1 NO_GTK2=1 make_no_demangle := NO_DEMANGLE=1 make_no_libelf := NO_LIBELF=1 make_no_libdw := NO_LIBDW=1 @@ -118,7 +116,7 @@ make_install_prefix_slash := install prefix=/tmp/krava/ make_static := LDFLAGS=-static NO_PERF_READ_VDSO32=1 NO_PERF_READ_VDSOX32=1 NO_JVMTI=1 NO_LIBTRACEEVENT=1 NO_LIBELF=1 # all the NO_* variable combined -make_minimal := NO_LIBPYTHON=1 NO_GTK2=1 +make_minimal := NO_LIBPYTHON=1 make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_BACKTRACE=1 make_minimal += NO_LIBNUMA=1 NO_LIBBIONIC=1 NO_LIBDW=1 make_minimal += NO_LIBBPF=1 @@ -153,8 +151,6 @@ run += make_libperl run += make_no_libpython run += make_no_scripts run += make_no_slang -run += make_no_gtk2 -run += make_no_ui run += make_no_demangle run += make_no_libelf run += make_no_libdw From a4cbd51862d449e487866c173f5dff46329da76c Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Tue, 28 Apr 2026 16:38:46 +0200 Subject: [PATCH 020/343] perf test: Fix nanosleep check in the ftrace test The perf ftrace test case runs: perf ftrace profile --graph-opts depth=5 sleep 0.1 and checks that the output contains a *clock_nanosleep function with a count of 1. This fails on a risc-v system that uses musl as its C library. musl's nanosleep syscall wrapper uses either the nanosleep or the clock_nanosleep syscall. Filter for sys_*nanosleep to allow both syscalls. Signed-off-by: Martin Kaiser Acked-by: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/ftrace.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/shell/ftrace.sh b/tools/perf/tests/shell/ftrace.sh index 7f8aafcbb761..9f6e590f6437 100755 --- a/tools/perf/tests/shell/ftrace.sh +++ b/tools/perf/tests/shell/ftrace.sh @@ -71,9 +71,10 @@ test_ftrace_profile() { grep ^# "${output}" time_re="[[:space:]]+1[[:digit:]]{5}\.[[:digit:]]{3}" # 100283.000 100283.000 100283.000 1 __x64_sys_clock_nanosleep - # Check for one *clock_nanosleep line with a Count of just 1 that takes a bit more than 0.1 seconds - # Strip the _x64_sys part to work with other architectures - grep -E "^${time_re}${time_re}${time_re}[[:space:]]+1[[:space:]]+.*clock_nanosleep" "${output}" + # Check for one *sys_*nanosleep line with a Count of just 1 that takes a bit more than 0.1 seconds + # Strip the _x64_ part to work with other architectures, strip the clock part to support + # C libraries that use the nanosleep syscall instead of clock_nanosleep + grep -E "^${time_re}${time_re}${time_re}[[:space:]]+1[[:space:]]+.*sys_.*nanosleep" "${output}" echo "perf ftrace profile test [Success]" } From 9a4a67dddc3d88e2e9d3cff462b943f40ea439e4 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Tue, 28 Apr 2026 16:38:47 +0200 Subject: [PATCH 021/343] perf test: Fix sys_enter_openat event test for musl The "syscalls:sys_enter_openat event fields" test calls openat(AT_FDCWD, "/etc/passwd", O_RDONLY | O_DIRECTORY) and verifies that the flags of the captured event are matching. This fails for musl, where the openat syscall wrapper always adds O_LARGEFILE. Update the check to allow for additional flags, the access mode flags must be unchanged. Signed-off-by: Martin Kaiser Acked-by: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/openat-syscall-tp-fields.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 2a139d2781a8..5523cf4e9321 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -120,7 +120,10 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused tp_flags = evsel__intval(evsel, &sample, "flags"); perf_sample__exit(&sample); - if (flags != tp_flags) { + /* C library wrapper may set additional flags, + access mode must be unchanged */ + if ((tp_flags & O_ACCMODE) != (flags & O_ACCMODE) || + (tp_flags & flags) != flags) { pr_debug("%s: Expected flags=%#x, got %#x\n", __func__, flags, tp_flags); goto out_delete_evlist; From e1c19cd376a30cbc893c76eaaa31f0e2fe972ebd Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Tue, 28 Apr 2026 16:38:48 +0200 Subject: [PATCH 022/343] perf test: Fix "trace summary" test for musl-based systems The trace summary test calls /bin/true and filters for open, read and close events. These events are coming from shared library loads. On a musl system, the loader and libc may point to the same file. true needs only libc, no further shared libraries are loaded at startup. The test fails since no open, read and close events are captured. root@host:~# ldd /bin/true /lib/ld-musl-riscv64.so.1 (0x3fb8882000) libc.so => /lib/ld-musl-riscv64.so.1 (0x3fb8882000) root@host:~# file /lib/ld-musl-riscv64.so.1 /lib/ld-musl-riscv64.so.1: symbolic link to /usr/lib/libc.so root@host:~# strace -f /bin/true execve("/bin/true", ["/bin/true", ...], ... /* 18 vars */) = 1 set_tid_address(0x3fa1f7bf70) = 330 mprotect(0x2ad6b8e000, 12288, PROT_READ) = 0 exit_group(0) = ? +++ exited with 0 +++ Run "cat /dev/null" instead of "true". This creates the required events regardless of the C library and it works for cat from busybox or from coreutils. Signed-off-by: Martin Kaiser Acked-by: Ian Rogers Acked-by: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/trace_summary.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/tests/shell/trace_summary.sh b/tools/perf/tests/shell/trace_summary.sh index 22e2651d5919..b80dea77cec6 100755 --- a/tools/perf/tests/shell/trace_summary.sh +++ b/tools/perf/tests/shell/trace_summary.sh @@ -14,7 +14,7 @@ OUTPUT=$(mktemp /tmp/perf_trace_test.XXXXX) test_perf_trace() { args=$1 - workload="true" + workload="cat /dev/null" search="^\s*(open|read|close).*[0-9]+%$" echo "testing: perf trace ${args} -- ${workload}" From 111388a0c01e6c2f9822623a764b3dcf8bc1492c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 5 May 2026 21:10:04 -0700 Subject: [PATCH 023/343] perf sched stats: Fix segmentation faults, memory leaks, and stale pointers in diff mode The patch addresses multiple segmentation fault vectors, out-of-bounds reads, and memory leaks in perf sched stats by adding bounds checks, NULL checks, proper error propagation, and robust memory cleanup. 1. In get_all_cpu_stats(), added assert(!list_empty(head)) to prevent unsafe list_first_entry() calls on empty lists, added a missing NULL check for summary_head->cpu_data allocation, and implemented a cleanup ladder using a temporary list to prevent memory leaks on error paths. 2. In free_schedstat(), fixed memory leaks by ensuring internal domain_data and cpu_data pointers are freed. 3. In show_schedstat_data(), fixed a stale pointer issue where ds2 retained its value from a previous iteration when dptr2 became NULL, and added proper propagation of errors from get_all_cpu_stats(). 4. Propagated show_schedstat_data() errors up to perf_sched__schedstat_diff() and perf_sched__schedstat_live() to prevent output corruption on failure. 5. In show_schedstat_data(), added NULL checks for cd_map1 and cd_map2 to gracefully handle invalid or empty data files. 6. Added parallel iteration termination checks using list_is_last() in show_schedstat_data() for both domain and CPU lists to safely terminate at the end of each list when files contain a different number of CPUs or domains. 7. Added CPU bounds checks (cs1->cpu >= nr1 and cs2->cpu >= nr2) in show_schedstat_data() to prevent out-of-bounds reads from cd_map1 and cd_map2 when comparing files from machines with different CPU counts. 8. Added NULL checks for cd_info1 and cd_info2 to prevent crashes when a CPU has data samples but no corresponding domain info in the header. 9. Added domain bounds checks (ds1->domain >= cd_info1->nr_domains and ds2->domain >= cd_info2->nr_domains) to prevent out-of-bounds array accesses in the domains array. 10. Added NULL checks for dinfo1 and dinfo2 in show_schedstat_data() to prevent crashes when a domain has no corresponding domain info. 11. Zero-initialized the perf_data array in perf_sched__schedstat_diff() to prevent stack garbage from causing perf_data_file__fd() to attempt to use a NULL fptr when use_stdio happened to be non-zero. Assisted-by: Gemini:gemini-3.1-pro-preview Reviewed-by: James Clark Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Athira Rajeev Cc: Ingo Molnar Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Venkat Rao Bagalkote Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 175 +++++++++++++++++++++++++++++-------- 1 file changed, 138 insertions(+), 37 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 555247568e7a..fd679b106582 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -3947,6 +3947,8 @@ static struct schedstat_domain *domain_second_pass; static bool after_workload_flag; static bool verbose_field; +static void free_schedstat(struct list_head *head); + static void store_schedstat_cpu_diff(struct schedstat_cpu *after_workload) { struct perf_record_schedstat_cpu *before = cpu_second_pass->cpu_data; @@ -4170,37 +4172,50 @@ static void summarize_schedstat_domain(struct schedstat_domain *summary_domain, */ static int get_all_cpu_stats(struct list_head *head) { - struct schedstat_cpu *cptr = list_first_entry(head, struct schedstat_cpu, cpu_list); - struct schedstat_cpu *summary_head = NULL; - struct perf_record_schedstat_domain *ds; - struct perf_record_schedstat_cpu *cs; + struct schedstat_cpu *cptr, *summary_head = NULL; struct schedstat_domain *dptr, *tdptr; bool is_last = false; int cnt = 1; int ret = 0; + struct list_head tmp_cleanup_list; - if (cptr) { - summary_head = zalloc(sizeof(*summary_head)); - if (!summary_head) - return -ENOMEM; + assert(!list_empty(head)); + cptr = list_first_entry(head, struct schedstat_cpu, cpu_list); - summary_head->cpu_data = zalloc(sizeof(*cs)); - memcpy(summary_head->cpu_data, cptr->cpu_data, sizeof(*cs)); + INIT_LIST_HEAD(&tmp_cleanup_list); - INIT_LIST_HEAD(&summary_head->domain_head); + summary_head = zalloc(sizeof(*summary_head)); + if (!summary_head) + return -ENOMEM; - list_for_each_entry(dptr, &cptr->domain_head, domain_list) { - tdptr = zalloc(sizeof(*tdptr)); - if (!tdptr) - return -ENOMEM; + INIT_LIST_HEAD(&summary_head->domain_head); + INIT_LIST_HEAD(&summary_head->cpu_list); + list_add(&summary_head->cpu_list, &tmp_cleanup_list); - tdptr->domain_data = zalloc(sizeof(*ds)); - if (!tdptr->domain_data) - return -ENOMEM; + summary_head->cpu_data = zalloc(sizeof(*summary_head->cpu_data)); + if (!summary_head->cpu_data) { + ret = -ENOMEM; + goto out_cleanup; + } + memcpy(summary_head->cpu_data, cptr->cpu_data, sizeof(*summary_head->cpu_data)); - memcpy(tdptr->domain_data, dptr->domain_data, sizeof(*ds)); - list_add_tail(&tdptr->domain_list, &summary_head->domain_head); + list_for_each_entry(dptr, &cptr->domain_head, domain_list) { + tdptr = zalloc(sizeof(*tdptr)); + if (!tdptr) { + ret = -ENOMEM; + goto out_cleanup; } + INIT_LIST_HEAD(&tdptr->domain_list); + + tdptr->domain_data = zalloc(sizeof(*tdptr->domain_data)); + if (!tdptr->domain_data) { + free(tdptr); + ret = -ENOMEM; + goto out_cleanup; + } + + memcpy(tdptr->domain_data, dptr->domain_data, sizeof(*tdptr->domain_data)); + list_add_tail(&tdptr->domain_list, &summary_head->domain_head); } list_for_each_entry(cptr, head, cpu_list) { @@ -4212,32 +4227,52 @@ static int get_all_cpu_stats(struct list_head *head) cnt++; summarize_schedstat_cpu(summary_head, cptr, cnt, is_last); + if (list_empty(&summary_head->domain_head)) + continue; + tdptr = list_first_entry(&summary_head->domain_head, struct schedstat_domain, domain_list); list_for_each_entry(dptr, &cptr->domain_head, domain_list) { summarize_schedstat_domain(tdptr, dptr, cnt, is_last); + if (list_is_last(&tdptr->domain_list, &summary_head->domain_head)) { + tdptr = NULL; + break; + } tdptr = list_next_entry(tdptr, domain_list); } } + list_del_init(&summary_head->cpu_list); list_add(&summary_head->cpu_list, head); + return 0; + +out_cleanup: + free_schedstat(&tmp_cleanup_list); return ret; } -static int show_schedstat_data(struct list_head *head1, struct cpu_domain_map **cd_map1, - struct list_head *head2, struct cpu_domain_map **cd_map2, +static int show_schedstat_data(struct list_head *head1, struct cpu_domain_map **cd_map1, int nr1, + struct list_head *head2, struct cpu_domain_map **cd_map2, int nr2, bool summary_only) { struct schedstat_cpu *cptr1 = list_first_entry(head1, struct schedstat_cpu, cpu_list); struct perf_record_schedstat_domain *ds1 = NULL, *ds2 = NULL; - struct perf_record_schedstat_cpu *cs1 = NULL, *cs2 = NULL; struct schedstat_domain *dptr1 = NULL, *dptr2 = NULL; struct schedstat_cpu *cptr2 = NULL; __u64 jiffies1 = 0, jiffies2 = 0; bool is_summary = true; int ret = 0; + if (!cd_map1) { + pr_err("Error: CPU domain map 1 is missing.\n"); + return -1; + } + if (head2 && !cd_map2) { + pr_err("Error: CPU domain map 2 is missing.\n"); + return -1; + } + printf("Description\n"); print_separator2(SEP_LEN, "", 0); printf("%-30s-> %s\n", "DESC", "Description of the field"); @@ -4260,21 +4295,47 @@ static int show_schedstat_data(struct list_head *head1, struct cpu_domain_map ** printf("\n"); ret = get_all_cpu_stats(head1); + if (ret) + return ret; if (cptr2) { ret = get_all_cpu_stats(head2); + if (ret) + return ret; cptr2 = list_first_entry(head2, struct schedstat_cpu, cpu_list); } list_for_each_entry(cptr1, head1, cpu_list) { struct cpu_domain_map *cd_info1 = NULL, *cd_info2 = NULL; + struct perf_record_schedstat_cpu *cs1 = cptr1->cpu_data; + struct perf_record_schedstat_cpu *cs2 = NULL; - cs1 = cptr1->cpu_data; + dptr2 = NULL; + if (cs1->cpu >= (u32)nr1) { + pr_err("Error: CPU %d exceeds domain map size %d\n", cs1->cpu, nr1); + return -1; + } cd_info1 = cd_map1[cs1->cpu]; + if (!cd_info1) { + pr_err("Error: CPU %d domain info is missing in map 1.\n", + cs1->cpu); + return -1; + } if (cptr2) { cs2 = cptr2->cpu_data; + if (cs2->cpu >= (u32)nr2) { + pr_err("Error: CPU %d exceeds domain map size %d\n", cs2->cpu, nr2); + return -1; + } cd_info2 = cd_map2[cs2->cpu]; - dptr2 = list_first_entry(&cptr2->domain_head, struct schedstat_domain, - domain_list); + if (!cd_info2) { + pr_err("Error: CPU %d domain info is missing in map 2.\n", + cs2->cpu); + return -1; + } + if (!list_empty(&cptr2->domain_head)) + dptr2 = list_first_entry(&cptr2->domain_head, + struct schedstat_domain, + domain_list); } if (cs2 && cs1->cpu != cs2->cpu) { @@ -4302,10 +4363,31 @@ static int show_schedstat_data(struct list_head *head1, struct cpu_domain_map ** struct domain_info *dinfo1 = NULL, *dinfo2 = NULL; ds1 = dptr1->domain_data; + ds2 = NULL; + if (ds1->domain >= cd_info1->nr_domains) { + pr_err("Error: Domain %d exceeds max domains %d for CPU %d in map 1.\n", + ds1->domain, cd_info1->nr_domains, cs1->cpu); + return -1; + } dinfo1 = cd_info1->domains[ds1->domain]; + if (!dinfo1) { + pr_err("Error: Domain %d info is missing for CPU %d in map 1.\n", + ds1->domain, cs1->cpu); + return -1; + } if (dptr2) { ds2 = dptr2->domain_data; + if (ds2->domain >= cd_info2->nr_domains) { + pr_err("Error: Domain %d exceeds max domains %d for CPU %d in map 2.\n", + ds2->domain, cd_info2->nr_domains, cs2->cpu); + return -1; + } dinfo2 = cd_info2->domains[ds2->domain]; + if (!dinfo2) { + pr_err("Error: Domain %d info is missing for CPU %d in map 2.\n", + ds2->domain, cs2->cpu); + return -1; + } } if (dinfo2 && dinfo1->domain != dinfo2->domain) { @@ -4334,14 +4416,22 @@ static int show_schedstat_data(struct list_head *head1, struct cpu_domain_map ** print_domain_stats(ds1, ds2, jiffies1, jiffies2); print_separator2(SEP_LEN, "", 0); - if (dptr2) - dptr2 = list_next_entry(dptr2, domain_list); + if (dptr2) { + if (list_is_last(&dptr2->domain_list, &cptr2->domain_head)) + dptr2 = NULL; + else + dptr2 = list_next_entry(dptr2, domain_list); + } } if (summary_only) break; - if (cptr2) - cptr2 = list_next_entry(cptr2, cpu_list); + if (cptr2) { + if (list_is_last(&cptr2->cpu_list, head2)) + cptr2 = NULL; + else + cptr2 = list_next_entry(cptr2, cpu_list); + } is_summary = false; } @@ -4473,9 +4563,11 @@ static void free_schedstat(struct list_head *head) list_for_each_entry_safe(cptr, n2, head, cpu_list) { list_for_each_entry_safe(dptr, n1, &cptr->domain_head, domain_list) { list_del_init(&dptr->domain_list); + free(dptr->domain_data); free(dptr); } list_del_init(&cptr->cpu_list); + free(cptr->cpu_data); free(cptr); } } @@ -4523,7 +4615,9 @@ static int perf_sched__schedstat_report(struct perf_sched *sched) } cd_map = session->header.env.cpu_domain; - err = show_schedstat_data(&cpu_head, cd_map, NULL, NULL, false); + err = show_schedstat_data(&cpu_head, cd_map, + session->header.env.nr_cpus_avail, + NULL, NULL, 0, false); } out: @@ -4538,7 +4632,7 @@ static int perf_sched__schedstat_diff(struct perf_sched *sched, struct cpu_domain_map **cd_map0 = NULL, **cd_map1 = NULL; struct list_head cpu_head_ses0, cpu_head_ses1; struct perf_session *session[2]; - struct perf_data data[2]; + struct perf_data data[2] = {0}; int ret = 0, err = 0; static const char *defaults[] = { "perf.data.old", @@ -4573,8 +4667,10 @@ static int perf_sched__schedstat_diff(struct perf_sched *sched, } err = perf_session__process_events(session[0]); - if (err) + if (err) { + free_schedstat(&cpu_head); goto out_delete_ses0; + } cd_map0 = session[0]->header.env.cpu_domain; list_replace_init(&cpu_head, &cpu_head_ses0); @@ -4590,8 +4686,10 @@ static int perf_sched__schedstat_diff(struct perf_sched *sched, } err = perf_session__process_events(session[1]); - if (err) + if (err) { + free_schedstat(&cpu_head); goto out_delete_ses1; + } cd_map1 = session[1]->header.env.cpu_domain; list_replace_init(&cpu_head, &cpu_head_ses1); @@ -4607,10 +4705,13 @@ static int perf_sched__schedstat_diff(struct perf_sched *sched, if (list_empty(&cpu_head_ses0)) { pr_err("Data is not available\n"); ret = -1; - goto out_delete_ses0; + goto out_delete_ses1; } - show_schedstat_data(&cpu_head_ses0, cd_map0, &cpu_head_ses1, cd_map1, true); + ret = show_schedstat_data(&cpu_head_ses0, cd_map0, session[0]->header.env.nr_cpus_avail, + &cpu_head_ses1, cd_map1, session[1]->header.env.nr_cpus_avail, true); + if (ret) + goto out_delete_ses1; out_delete_ses1: free_schedstat(&cpu_head_ses1); @@ -4720,7 +4821,7 @@ static int perf_sched__schedstat_live(struct perf_sched *sched, goto out; } - show_schedstat_data(&cpu_head, cd_map, NULL, NULL, false); + err = show_schedstat_data(&cpu_head, cd_map, nr, NULL, NULL, 0, false); free_cpu_domain_info(cd_map, sv, nr); out: free_schedstat(&cpu_head); From 91182741369b261c441e63e6678893032a6d7e4c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 5 May 2026 17:45:42 -0700 Subject: [PATCH 024/343] perf sched: Add missing mmap2 handler in timehist perf_sched__timehist() registers event handlers for options using the sched->tool struct. It registers handlers for MMAP, COMM, EXIT, FORK, etc. but completely omits registering a handler for MMAP2 events. Failing to register both MMAP and MMAP2 handlers causes modern systems (which primarily output MMAP2 records) to silently drop VMA map mappings. This results in uninitialized machine/thread mapping structures, making it impossible to resolve shared library instruction pointers (IPs) to dynamic symbols/DSOs during timehist callchain analysis. Fix this by correctly registering perf_event__process_mmap2 in sched->tool inside perf_sched__timehist(). Fixes: 49394a2a24c78ce0 ("perf sched timehist: Introduce timehist command") Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: David Ahern Cc: Gabriel Marin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index fd679b106582..53a93aa18853 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -3299,6 +3299,7 @@ static int perf_sched__timehist(struct perf_sched *sched) */ sched->tool.sample = perf_timehist__process_sample; sched->tool.mmap = perf_event__process_mmap; + sched->tool.mmap2 = perf_event__process_mmap2; sched->tool.comm = perf_event__process_comm; sched->tool.exit = perf_event__process_exit; sched->tool.fork = perf_event__process_fork; From 09d355618f7ccc27ffc7fc668b2e232872962079 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 5 May 2026 17:45:43 -0700 Subject: [PATCH 025/343] perf tool: Fix missing schedstat delegates and dont_split_sample_group in delegate_tool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit delegate_tool was missing the delegate overrides for schedstat_cpu and schedstat_domain. As a result, when allocated with zalloc, these callbacks defaulted to NULL, causing a segmentation fault crash if any schedstat events were delivered during event processing. Fix this by adding delegate_schedstat_cpu and delegate_schedstat_domain via the CREATE_DELEGATE_OP2 macro, and ensuring delegate_tool__init correctly registers them. Additionally, delegate_tool__init completely omitted copying the dont_split_sample_group property from the delegate. This would cause wrapper tools to default the flag to false, which corrupts piped event processing (e.g., in perf inject) by triggering duplicate event deliveries on split sample values in deliver_sample_group(). Similarly, perf_tool__init() omitted the initialization of this boolean field. On stack-allocated tools that rely on this initializer (like intel-tpebs or __cmd_evlist), this could result in uninitialized stack garbage evaluating to true—silently dropping non-leader event members in deliver_sample_group(). Fix both issues by properly copying the field in delegate_tool__init and initializing it to false in perf_tool__init. Fixes: 6331b266935916bf ("perf tool: Add a delegate_tool that just delegates actions to another tool") Fixes: 79bcd34e0f3da39f ("perf inject: Fix leader sampling inserting additional samples") Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Gabriel Marin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/tool.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c index 013c7839e2cf..ff2150517b75 100644 --- a/tools/perf/util/tool.c +++ b/tools/perf/util/tool.c @@ -285,6 +285,7 @@ void perf_tool__init(struct perf_tool *tool, bool ordered_events) tool->no_warn = false; tool->show_feat_hdr = SHOW_FEAT_NO_HEADER; tool->merge_deferred_callchains = true; + tool->dont_split_sample_group = false; tool->sample = process_event_sample_stub; tool->mmap = process_event_stub; @@ -433,6 +434,8 @@ CREATE_DELEGATE_OP2(stat_config); CREATE_DELEGATE_OP2(stat_round); CREATE_DELEGATE_OP2(thread_map); CREATE_DELEGATE_OP2(time_conv); +CREATE_DELEGATE_OP2(schedstat_cpu); +CREATE_DELEGATE_OP2(schedstat_domain); CREATE_DELEGATE_OP2(tracing_data); #define CREATE_DELEGATE_OP3(name) \ @@ -470,6 +473,7 @@ void delegate_tool__init(struct delegate_tool *tool, struct perf_tool *delegate) tool->tool.no_warn = delegate->no_warn; tool->tool.show_feat_hdr = delegate->show_feat_hdr; tool->tool.merge_deferred_callchains = delegate->merge_deferred_callchains; + tool->tool.dont_split_sample_group = delegate->dont_split_sample_group; tool->tool.sample = delegate_sample; tool->tool.read = delegate_read; @@ -516,4 +520,6 @@ void delegate_tool__init(struct delegate_tool *tool, struct perf_tool *delegate) tool->tool.bpf_metadata = delegate_bpf_metadata; tool->tool.compressed = delegate_compressed; tool->tool.auxtrace = delegate_auxtrace; + tool->tool.schedstat_cpu = delegate_schedstat_cpu; + tool->tool.schedstat_domain = delegate_schedstat_domain; } From 165daffc7c33c94b0b7ef7f5719531f1f8bc0a3a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 11 May 2026 22:41:40 -0700 Subject: [PATCH 026/343] perf record: Refactor ARM64 leaf caller setup out of arch Code in tools/perf/arch causes portability issues/opaqueness and LTO issues due to the use of weak symbols. Move the adding of LR to the sample_user_regs into arm64-frame-pointer-unwind-support.c conditional on EM_HOST == EM_AARCH64 (false on all non-ARM64 builds). This also better encapsulates the use of the sampled registers by get_leaf_frame_caller_aarch64 and the set up by the new add_leaf_frame_caller_opts_aarch64, exposing opportunities for possibly sampling PC and SP to help the unwinder. Reviewed-by: James Clark Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Dapeng Mi Cc: Ingo Molnar Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Mark Rutland Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Shimin Guo Cc: Will Deacon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm64/util/Build | 1 - tools/perf/arch/arm64/util/machine.c | 12 ------------ tools/perf/builtin-record.c | 11 +++++------ tools/perf/util/arm64-frame-pointer-unwind-support.c | 6 ++++++ tools/perf/util/arm64-frame-pointer-unwind-support.h | 2 ++ tools/perf/util/callchain.h | 2 -- 6 files changed, 13 insertions(+), 21 deletions(-) delete mode 100644 tools/perf/arch/arm64/util/machine.c diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build index 4e06a08d281a..638aa6948ab5 100644 --- a/tools/perf/arch/arm64/util/Build +++ b/tools/perf/arch/arm64/util/Build @@ -5,7 +5,6 @@ perf-util-y += ../../arm/util/pmu.o perf-util-y += arm-spe.o perf-util-y += header.o perf-util-y += hisi-ptt.o -perf-util-y += machine.o perf-util-y += mem-events.o perf-util-y += pmu.o perf-util-y += tsc.o diff --git a/tools/perf/arch/arm64/util/machine.c b/tools/perf/arch/arm64/util/machine.c deleted file mode 100644 index 80fb13c958d9..000000000000 --- a/tools/perf/arch/arm64/util/machine.c +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include "callchain.h" // prototype of arch__add_leaf_frame_record_opts -#include "perf_regs.h" -#include "record.h" - -#define SMPL_REG_MASK(b) (1ULL << (b)) - -void arch__add_leaf_frame_record_opts(struct record_opts *opts) -{ - opts->sample_user_regs |= SMPL_REG_MASK(PERF_REG_ARM64_LR); -} diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 4a5eba498c02..272bba7f4b9e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -14,6 +14,7 @@ #include "util/parse-events.h" #include "util/config.h" +#include "util/arm64-frame-pointer-unwind-support.h" #include "util/callchain.h" #include "util/cgroup.h" #include "util/header.h" @@ -3230,10 +3231,6 @@ static int record__parse_off_cpu_thresh(const struct option *opt, return 0; } -void __weak arch__add_leaf_frame_record_opts(struct record_opts *opts __maybe_unused) -{ -} - static int parse_control_option(const struct option *opt, const char *str, int unset __maybe_unused) @@ -4319,8 +4316,10 @@ int cmd_record(int argc, const char **argv) evlist__warn_user_requested_cpus(rec->evlist, rec->opts.target.cpu_list); - if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP) - arch__add_leaf_frame_record_opts(&rec->opts); + if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP) { + if (EM_HOST == EM_AARCH64) + add_leaf_frame_caller_opts_aarch64(&rec->opts); + } err = -ENOMEM; if (evlist__create_maps(rec->evlist, &rec->opts.target) < 0) { diff --git a/tools/perf/util/arm64-frame-pointer-unwind-support.c b/tools/perf/util/arm64-frame-pointer-unwind-support.c index 858ce2b01812..3af8c7a466e0 100644 --- a/tools/perf/util/arm64-frame-pointer-unwind-support.c +++ b/tools/perf/util/arm64-frame-pointer-unwind-support.c @@ -2,6 +2,7 @@ #include "arm64-frame-pointer-unwind-support.h" #include "callchain.h" #include "event.h" +#include "record.h" #include "unwind.h" #include @@ -16,6 +17,11 @@ struct entries { #define SMPL_REG_MASK(b) (1ULL << (b)) +void add_leaf_frame_caller_opts_aarch64(struct record_opts *opts) +{ + opts->sample_user_regs |= SMPL_REG_MASK(PERF_REG_ARM64_LR); +} + static bool get_leaf_frame_caller_enabled(struct perf_sample *sample) { struct regs_dump *regs; diff --git a/tools/perf/util/arm64-frame-pointer-unwind-support.h b/tools/perf/util/arm64-frame-pointer-unwind-support.h index 42d3a45490f5..ba35b295bfcd 100644 --- a/tools/perf/util/arm64-frame-pointer-unwind-support.h +++ b/tools/perf/util/arm64-frame-pointer-unwind-support.h @@ -5,8 +5,10 @@ #include struct perf_sample; +struct record_opts; struct thread; +void add_leaf_frame_caller_opts_aarch64(struct record_opts *opts); u64 get_leaf_frame_caller_aarch64(struct perf_sample *sample, struct thread *thread, int user_idx); #endif /* __PERF_ARM_FRAME_POINTER_UNWIND_SUPPORT_H */ diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 06d463ccc7a0..b7702d65ad60 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -277,8 +277,6 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, } #endif -void arch__add_leaf_frame_record_opts(struct record_opts *opts); - char *callchain_list__sym_name(struct callchain_list *cl, char *bf, size_t bfsize, bool show_dso); char *callchain_node__scnprintf_value(struct callchain_node *node, From 41a543c86d110073275e5294852d692e5faf6b3b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 14 Apr 2026 10:58:55 -0700 Subject: [PATCH 027/343] perf pmu-events AMD: Switch l2_itlb_misses to bp_l1_tlb_miss_l2_tlb_miss.all l2_itlb_misses is a valid legacy cache event name, hence allowing it in all_events in metric.py. l2_itlb_misses was also a json event for AMD zen1, zen2 and zen3. For zen4, zen5 and zen6 the checking that metric events are within the json was skipping l2_itlb_misses as it is a valid legacy event, however, the PMU driver lacks the event mapping causing it to be a bad event when used in the metric. Add bp_l1_tlb_miss_l2_tlb_miss.all as the l2 itlb miss event (bp = branch predictor, the AMD way to say itlb), so that is used in preference to l2_itlb_misses when the event exists. Remove l2_itlb_misses from metric.py as the legacy event isn't used by any metrics and having it is error prone for newer AMD zen models. Fixes: e596f329668ec2b5 ("perf jevents: Add itlb metric group for AMD") Reviewed-by: Sandipan Das Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/amd_metrics.py | 2 +- tools/perf/pmu-events/metric.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/perf/pmu-events/amd_metrics.py b/tools/perf/pmu-events/amd_metrics.py index e2defaffde3e..971f6e7af1f8 100755 --- a/tools/perf/pmu-events/amd_metrics.py +++ b/tools/perf/pmu-events/amd_metrics.py @@ -268,7 +268,7 @@ def AmdDtlb() -> Optional[MetricGroup]: def AmdItlb(): global _zen_model l2h = Event("bp_l1_tlb_miss_l2_tlb_hit", "bp_l1_tlb_miss_l2_hit") - l2m = Event("l2_itlb_misses") + l2m = Event("bp_l1_tlb_miss_l2_tlb_miss.all", "l2_itlb_misses",) l2r = l2h + l2m itlb_l1_mg = None diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index 585454828c2f..ac582db785fc 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -25,7 +25,6 @@ def LoadEvents(directory: str) -> None: "cycles", "duration_time", "instructions", - "l2_itlb_misses", } for file in os.listdir(os.fsencode(directory)): filename = os.fsdecode(file) From e356a67cc4b6af9440a0d86eb6b9bbaa92d42ef4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 30 Apr 2026 09:17:25 -0700 Subject: [PATCH 028/343] perf metricgroup: Avoid scanning unnecessary PMUs for identifier match Only uncore PMUs can have an identifier, so add an optimized perf_pmus__scan routine for that case to avoid all PMU types being created. Reviewed-by: James Clark Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ingo Molnar Cc: Leo Yan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 11 +++-------- tools/perf/util/pmus.c | 18 +++++++++++++++++- tools/perf/util/pmus.h | 1 + 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 4db9578efd81..5a489e97c413 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -415,14 +415,9 @@ static int metricgroup__sys_event_iter(const struct pmu_metric *pm, if (!pm->metric_expr || !pm->compat) return 0; - while ((pmu = perf_pmus__scan(pmu))) { - - if (!pmu->id || !pmu_uncore_identifier_match(pm->compat, pmu->id)) - continue; - - return d->fn(pm, table, d->data); - } - return 0; + /* Only process with the iterator if there is a a PMU that matches the ID. */ + pmu = perf_pmus__scan_for_uncore_id(pmu, pm->compat); + return pmu ? d->fn(pm, table, d->data) : 0; } int metricgroup__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c index 9a2023ceeefd..5e3f571450fe 100644 --- a/tools/perf/util/pmus.c +++ b/tools/perf/util/pmus.c @@ -409,7 +409,7 @@ struct perf_pmu *perf_pmus__scan_matching_wildcard(struct perf_pmu *pmu, const c if (!pmu) { /* * Core PMUs, other sysfs PMUs and tool PMU can have any name or - * aren't wother optimizing for. + * aren't worth optimizing for. */ unsigned int to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK | PERF_TOOL_PMU_TYPE_PE_OTHER_MASK | @@ -486,6 +486,22 @@ static struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu) return NULL; } +struct perf_pmu *perf_pmus__scan_for_uncore_id(struct perf_pmu *pmu, const char *compat) +{ + if (!pmu) { + /* Only uncore PMUs can have identifiers. */ + unsigned int to_read_pmus = PERF_TOOL_PMU_TYPE_PE_OTHER_MASK; + + pmu_read_sysfs(to_read_pmus); + pmu = list_prepare_entry(pmu, &other_pmus, list); + } + list_for_each_entry_continue(pmu, &other_pmus, list) { + if (pmu->id && pmu_uncore_identifier_match(compat, pmu->id)) + return pmu; + } + return NULL; +} + const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str) { struct perf_pmu *pmu = NULL; diff --git a/tools/perf/util/pmus.h b/tools/perf/util/pmus.h index 7cb36863711a..0d55edb3f2fc 100644 --- a/tools/perf/util/pmus.h +++ b/tools/perf/util/pmus.h @@ -23,6 +23,7 @@ struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu); struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu); struct perf_pmu *perf_pmus__scan_for_event(struct perf_pmu *pmu, const char *event); struct perf_pmu *perf_pmus__scan_matching_wildcard(struct perf_pmu *pmu, const char *wildcard); +struct perf_pmu *perf_pmus__scan_for_uncore_id(struct perf_pmu *pmu, const char *compat); const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str); From 4248ae6e799605b3e62855be6085935d89de50d1 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 13 May 2026 16:31:45 -0700 Subject: [PATCH 029/343] perf unwind: Refactor get_entries to allow dynamic libdw/libunwind selection Currently, both libdw and libunwind define 'unwind__get_entries'. This causes a duplicate symbol build failure when both are compiled into perf. This commit refactors the DWARF unwind post-processing to be configurable at runtime via the .perfconfig file option 'unwind.style', or using the argument '--unwind-style' in the commands 'perf report', 'perf script' and 'perf inject', in a similar manner to the addr2line or the disassembler style. The file 'tools/perf/util/unwind.c' adds the top-level dispatch function 'unwind__get_entries'. The backend implementations are renamed to 'libdw__get_entries' and 'libunwind__get_entries'. Both are attempted as fallbacks if not configured, or if the primary backend fails. Fixes: 2e9191573a69ff96 ("perf build: Remove NO_LIBDW_DWARF_UNWIND option") Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andrew Jones Cc: Athira Rajeev Cc: Dapeng Mi Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Florian Fainelli Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: libunwind-devel@nongnu.org Cc: Li Guan Cc: Namhyung Kim Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Shimin Guo Cc: Thomas Richter Cc: Tomas Glozar Cc: Will Deacon [ Don't mix declarations and code, move 'entries' variable to the start of scope ] [ Use pr_warning_once() instead of pr_err() in stubs for get_entries(), suggested by a local sashiko instance ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 4 + tools/perf/builtin-report.c | 4 + tools/perf/builtin-script.c | 4 + tools/perf/util/Build | 1 + tools/perf/util/config.c | 4 + tools/perf/util/symbol_conf.h | 10 +++ tools/perf/util/unwind-libdw.c | 20 ++++- tools/perf/util/unwind-libunwind-local.c | 27 ++++-- tools/perf/util/unwind-libunwind.c | 2 +- tools/perf/util/unwind.c | 104 +++++++++++++++++++++++ tools/perf/util/unwind.h | 65 ++++++++------ 11 files changed, 210 insertions(+), 35 deletions(-) create mode 100644 tools/perf/util/unwind.c diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 6ab20df358c4..a2493f1097df 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -26,6 +26,7 @@ #include "util/synthetic-events.h" #include "util/thread.h" #include "util/namespaces.h" +#include "util/unwind.h" #include "util/util.h" #include "util/tsc.h" @@ -2563,6 +2564,9 @@ int cmd_inject(int argc, const char **argv) OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory", "guest mount directory under which every guest os" " instance has a subdir"), + OPT_CALLBACK(0, "unwind-style", NULL, "unwind style", + "unwind styles (libdw,libunwind)", + unwind__option), OPT_BOOLEAN(0, "convert-callchain", &inject.convert_callchain, "Generate callchains using DWARF and drop register/stack data"), OPT_END() diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 95c0bdba6b11..0b0966d94128 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -48,6 +48,7 @@ #include "util/time-utils.h" #include "util/auxtrace.h" #include "util/units.h" +#include "util/unwind.h" #include "util/util.h" // perf_tip() #include "ui/ui.h" #include "ui/progress.h" @@ -1449,6 +1450,9 @@ int cmd_report(int argc, const char **argv) OPT_CALLBACK(0, "addr2line-style", NULL, "addr2line style", "addr2line styles (libdw,llvm,libbfd,addr2line)", report_parse_addr2line_config), + OPT_CALLBACK(0, "unwind-style", NULL, "unwind style", + "unwind styles (libdw,libunwind)", + unwind__option), OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, "Symbol demangling. Enabled by default, use --no-demangle to disable."), OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index c8ac9f01a36b..fd0b4609516b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -63,6 +63,7 @@ #include #include "util/dlfilter.h" #include "util/record.h" +#include "util/unwind.h" #include "util/util.h" #include "util/cgroup.h" #include "util/annotate.h" @@ -4159,6 +4160,9 @@ int cmd_script(int argc, const char **argv) "Enable symbol demangling"), OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, "Enable kernel symbol demangling"), + OPT_CALLBACK(0, "unwind-style", NULL, "unwind style", + "unwind styles (libdw,libunwind)", + unwind__option), OPT_STRING(0, "addr2line", &symbol_conf.addr2line_path, "path", "addr2line binary to use for line numbers"), OPT_STRING(0, "time", &script.time_str, "str", diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 70cc91d00804..01edfccebb88 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -216,6 +216,7 @@ ifndef CONFIG_SETNS perf-util-y += setns.o endif +perf-util-y += unwind.o perf-util-$(CONFIG_LIBDW) += probe-finder.o perf-util-$(CONFIG_LIBDW) += dwarf-aux.o perf-util-$(CONFIG_LIBDW) += dwarf-regs.o diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 087002fb1b9b..7988149dc7ed 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -23,6 +23,7 @@ #include "build-id.h" #include "debug.h" #include "config.h" +#include "unwind.h" #include #include #include @@ -525,6 +526,9 @@ int perf_default_config(const char *var, const char *value, if (strstarts(var, "addr2line.")) return addr2line_configure(var, value, dummy); + if (strstarts(var, "unwind.")) + return unwind__configure(var, value, dummy); + /* Add other config variables here. */ return 0; } diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h index 6cd454d7c98e..0dee5aa6a534 100644 --- a/tools/perf/util/symbol_conf.h +++ b/tools/perf/util/symbol_conf.h @@ -9,6 +9,15 @@ struct strlist; struct intlist; +enum unwind_style { + UNWIND_STYLE_UNKNOWN = 0, + UNWIND_STYLE_LIBDW, + UNWIND_STYLE_LIBUNWIND, +}; + +#define MAX_UNWIND_STYLE (UNWIND_STYLE_LIBUNWIND + 1) + + enum a2l_style { A2L_STYLE_UNKNOWN = 0, A2L_STYLE_LIBDW, @@ -81,6 +90,7 @@ struct symbol_conf { const char *addr2line_path; enum a2l_style addr2line_style[MAX_A2L_STYLE]; int addr2line_timeout_ms; + enum unwind_style unwind_style[MAX_UNWIND_STYLE]; unsigned long time_quantum; struct strlist *dso_list, *comm_list, diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 05e8e68bd49c..7f35042be567 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -339,7 +339,7 @@ frame_callback(Dwfl_Frame *state, void *arg) DWARF_CB_ABORT : DWARF_CB_OK; } -int unwind__get_entries(unwind_entry_cb_t cb, void *arg, +int libdw__get_entries(unwind_entry_cb_t cb, void *arg, struct thread *thread, struct perf_sample *data, int max_stack, @@ -353,10 +353,10 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, static struct unwind_info *ui; Dwfl *dwfl; Dwarf_Word ip; - int err = -EINVAL, i; + int err = -EINVAL, i, entries; if (!data->user_regs || !data->user_regs->regs) - return -EINVAL; + return 0; ui = zalloc(sizeof(*ui) + sizeof(ui->entries[0]) * max_stack); if (!ui) @@ -430,6 +430,18 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, map_symbol__exit(&ui->entries[i].ms); dwfl_ui_ti->ui = NULL; + entries = (int)ui->idx; free(ui); - return 0; + /* + * Unwinder return contract: + * > 0 : unwinding succeeded (stops fallback). If we found frames but hit an error + * (e.g. truncated stack), report success to preserve existing frames. + * 0 : unwinding failed without yielding frames. Ignore non-fatal errors + * (e.g. missing debug info, DWARF corruption) to allow fallback unwinder or + * kernel callchain resolution to proceed. + * < 0 : fatal error (e.g. -ENOMEM). Aborts unwinding entirely. + */ + if (err) + return (err == -ENOMEM) ? -ENOMEM : (entries > 0 ? 1 : 0); + return entries; } diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c index 87d496e9dfa6..27e2f7b31789 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c @@ -744,7 +744,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), perf_arch_reg_ip(e_machine)); if (ret) - return ret; + return 0; ips[i++] = (unw_word_t) val; @@ -757,7 +757,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, addr_space = maps__addr_space(thread__maps(ui->thread)); if (addr_space == NULL) - return -1; + return 0; ret = unw_init_remote(&c, addr_space, ui); if (ret && !ui->best_effort) @@ -785,15 +785,30 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, /* * Display what we got based on the order setup. */ + int entries = 0; for (i = 0; i < max_stack && !ret; i++) { int j = i; if (callchain_param.order == ORDER_CALLER) j = max_stack - i - 1; - ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0; + if (ips[j]) { + ret = entry(ips[j], ui->thread, cb, arg); + if (ret) + break; + entries++; + } } - return ret; + /* + * Unwinder return contract: + * > 0 : unwinding succeeded (stops fallback). + * 0 : unwinding failed without yielding frames. Ignore non-fatal errors + * (e.g. stepping failure) to allow fallback unwinder or kernel callchains. + * < 0 : fatal error (e.g. -ENOMEM). Aborts unwinding entirely. + */ + if (ret == -ENOMEM) + return -ENOMEM; + return (entries > 0 || ret == 0) ? entries : 0; } static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg, @@ -809,10 +824,10 @@ static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg, }; if (!data->user_regs || !data->user_regs->regs) - return -EINVAL; + return 0; if (max_stack <= 0) - return -EINVAL; + return 0; return get_entries(&ui, cb, arg, max_stack); } diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index cb8be6acfb6f..a0016b897dae 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c @@ -79,7 +79,7 @@ void unwind__finish_access(struct maps *maps) ops->finish_access(maps); } -int unwind__get_entries(unwind_entry_cb_t cb, void *arg, +int libunwind__get_entries(unwind_entry_cb_t cb, void *arg, struct thread *thread, struct perf_sample *data, int max_stack, bool best_effort) diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c new file mode 100644 index 000000000000..4ed4b1d55c69 --- /dev/null +++ b/tools/perf/util/unwind.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "debug.h" +#include "symbol_conf.h" +#include "unwind.h" +#include +#include +#include + +int unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, void *arg __maybe_unused, + struct thread *thread __maybe_unused, + struct perf_sample *data __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused) +{ + int ret = 0; + +#if defined(HAVE_LIBDW_SUPPORT) || defined(HAVE_LIBUNWIND_SUPPORT) + if (symbol_conf.unwind_style[0] == UNWIND_STYLE_UNKNOWN) { + int i = 0; +#ifdef HAVE_LIBDW_SUPPORT + symbol_conf.unwind_style[i++] = UNWIND_STYLE_LIBDW; +#endif +#ifdef HAVE_LIBUNWIND_SUPPORT + symbol_conf.unwind_style[i++] = UNWIND_STYLE_LIBUNWIND; +#endif + } +#endif //defined(HAVE_LIBDW_SUPPORT) || defined(HAVE_LIBUNWIND_SUPPORT) + + for (size_t i = 0; i < ARRAY_SIZE(symbol_conf.unwind_style); i++) { + switch (symbol_conf.unwind_style[i]) { + case UNWIND_STYLE_LIBDW: + ret = libdw__get_entries(cb, arg, thread, data, max_stack, best_effort); + break; + case UNWIND_STYLE_LIBUNWIND: + ret = libunwind__get_entries(cb, arg, thread, data, max_stack, best_effort); + break; + case UNWIND_STYLE_UNKNOWN: + default: +#if !defined(HAVE_LIBDW_SUPPORT) && !defined(HAVE_LIBUNWIND_SUPPORT) + pr_warning_once( + "Error: dwarf unwinding not supported, build perf with libdw or libunwind.\n"); +#endif + ret = 0; + break; + } + if (ret > 0) { + ret = 0; + break; + } + if (ret < 0) + break; + } + return ret; +} + +int unwind__configure(const char *var, const char *value, void *cb __maybe_unused) +{ + static const char * const unwind_style_names[] = { + [UNWIND_STYLE_LIBDW] = "libdw", + [UNWIND_STYLE_LIBUNWIND] = "libunwind", + NULL + }; + char *s, *p, *saveptr; + size_t i = 0; + + if (strcmp(var, "unwind.style")) + return 0; + + if (!value) + return -1; + + s = strdup(value); + if (!s) + return -1; + + memset(symbol_conf.unwind_style, 0, sizeof(symbol_conf.unwind_style)); + + p = strtok_r(s, ",", &saveptr); + while (p && i < ARRAY_SIZE(symbol_conf.unwind_style)) { + bool found = false; + char *q = strim(p); + + for (size_t j = UNWIND_STYLE_LIBDW; j < MAX_UNWIND_STYLE; j++) { + if (!strcasecmp(q, unwind_style_names[j])) { + symbol_conf.unwind_style[i++] = j; + found = true; + break; + } + } + if (!found) + pr_warning("Unknown unwind style: %s\n", q); + p = strtok_r(NULL, ",", &saveptr); + } + + free(s); + return 0; +} + +int unwind__option(const struct option *opt __maybe_unused, + const char *arg, + int unset __maybe_unused) +{ + return unwind__configure("unwind.style", arg, NULL); +} diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index 9f7164c6d9aa..69ba08afda79 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -4,9 +4,10 @@ #include #include -#include "util/map_symbol.h" +#include "map_symbol.h" struct maps; +struct option; struct perf_sample; struct thread; @@ -26,7 +27,9 @@ struct unwind_libunwind_ops { struct perf_sample *data, int max_stack, bool best_effort); }; -#ifdef HAVE_DWARF_UNWIND_SUPPORT +int unwind__configure(const char *var, const char *value, void *cb); +int unwind__option(const struct option *opt, const char *arg, int unset); + /* * When best_effort is set, don't report errors and fail silently. This could * be expanded in the future to be more permissive about things other than @@ -36,8 +39,31 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, struct thread *thread, struct perf_sample *data, int max_stack, bool best_effort); -/* libunwind specific */ + +#ifdef HAVE_LIBDW_SUPPORT +int libdw__get_entries(unwind_entry_cb_t cb, void *arg, + struct thread *thread, + struct perf_sample *data, int max_stack, + bool best_effort); +#else +#include "debug.h" +static inline int libdw__get_entries(unwind_entry_cb_t cb __maybe_unused, void *arg __maybe_unused, + struct thread *thread __maybe_unused, + struct perf_sample *data __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused) +{ + pr_warning_once("Error: libdw dwarf unwinding not built into perf\n"); + return 0; +} +#endif + #ifdef HAVE_LIBUNWIND_SUPPORT +/* libunwind specific */ +int libunwind__get_entries(unwind_entry_cb_t cb, void *arg, + struct thread *thread, + struct perf_sample *data, int max_stack, + bool best_effort); #ifndef LIBUNWIND__ARCH_REG_ID #define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arch_reg_id(regnum) #endif @@ -47,6 +73,18 @@ int unwind__prepare_access(struct maps *maps, struct map *map, bool *initialized void unwind__flush_access(struct maps *maps); void unwind__finish_access(struct maps *maps); #else +#include "debug.h" +static inline int libunwind__get_entries(unwind_entry_cb_t cb __maybe_unused, + void *arg __maybe_unused, + struct thread *thread __maybe_unused, + struct perf_sample *data __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused) +{ + pr_warning_once("Error: libunwind dwarf unwinding not built into perf\n"); + return 0; +} + static inline int unwind__prepare_access(struct maps *maps __maybe_unused, struct map *map __maybe_unused, bool *initialized __maybe_unused) @@ -57,26 +95,5 @@ static inline int unwind__prepare_access(struct maps *maps __maybe_unused, static inline void unwind__flush_access(struct maps *maps __maybe_unused) {} static inline void unwind__finish_access(struct maps *maps __maybe_unused) {} #endif -#else -static inline int -unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, - void *arg __maybe_unused, - struct thread *thread __maybe_unused, - struct perf_sample *data __maybe_unused, - int max_stack __maybe_unused, - bool best_effort __maybe_unused) -{ - return 0; -} -static inline int unwind__prepare_access(struct maps *maps __maybe_unused, - struct map *map __maybe_unused, - bool *initialized __maybe_unused) -{ - return 0; -} - -static inline void unwind__flush_access(struct maps *maps __maybe_unused) {} -static inline void unwind__finish_access(struct maps *maps __maybe_unused) {} -#endif /* HAVE_DWARF_UNWIND_SUPPORT */ #endif /* __UNWIND_H */ From 6d13d53be9ddab1425e0c2789788adc4d6f05d74 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 13 May 2026 16:31:46 -0700 Subject: [PATCH 030/343] tools build: Deduplicate test-libunwind for different architectures The separate test files only exist to pass a different #include, instead have a single source file and pass -include to $(CC) to include the relevant header file for the architecture being tested. Generate the rules using a foreach loop. Include tests for all current libunwind architectures. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andrew Jones Cc: Athira Rajeev Cc: Dapeng Mi Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Florian Fainelli Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Li Guan Cc: Namhyung Kim Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Shimin Guo Cc: Thomas Richter Cc: Tomas Glozar Cc: Will Deacon Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Makefile.feature | 12 +++++- tools/build/feature/Makefile | 40 +++++++++---------- tools/build/feature/test-libunwind-aarch64.c | 27 ------------- tools/build/feature/test-libunwind-arm.c | 28 ------------- .../test-libunwind-debug-frame-aarch64.c | 17 -------- .../feature/test-libunwind-debug-frame-arm.c | 17 -------- .../feature/test-libunwind-debug-frame.c | 1 - tools/build/feature/test-libunwind-x86.c | 28 ------------- tools/build/feature/test-libunwind-x86_64.c | 28 ------------- tools/build/feature/test-libunwind.c | 1 - 10 files changed, 29 insertions(+), 170 deletions(-) delete mode 100644 tools/build/feature/test-libunwind-aarch64.c delete mode 100644 tools/build/feature/test-libunwind-arm.c delete mode 100644 tools/build/feature/test-libunwind-debug-frame-aarch64.c delete mode 100644 tools/build/feature/test-libunwind-debug-frame-arm.c delete mode 100644 tools/build/feature/test-libunwind-x86.c delete mode 100644 tools/build/feature/test-libunwind-x86_64.c diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 2f192d3bf61b..af79c6cf0229 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -104,6 +104,9 @@ FEATURE_TESTS_BASIC := \ # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list # of all feature tests + +LIBUNWIND_ARCHS:=aarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x86 x86_64 + FEATURE_TESTS_EXTRA := \ bionic \ compile-32 \ @@ -127,7 +130,10 @@ FEATURE_TESTS_EXTRA := \ libpfm4 \ libdebuginfod \ clang-bpf-co-re \ - bpftool-skeletons + bpftool-skeletons \ + libunwind \ + libunwind-debug-frame \ + $(foreach arch,$(LIBUNWIND_ARCHS),libunwind-$(arch) libunwind-debug-frame-$(arch)) FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC) @@ -212,6 +218,10 @@ ifeq ($(feature-all), 1) $(call feature_check,compile-x32) $(call feature_check,bionic) $(call feature_check,libbabeltrace) + $(call feature_check,libunwind) + $(call feature_check,libunwind-debug-frame) + $(foreach arch,$(LIBUNWIND_ARCHS),$(call feature_check,libunwind-$(arch))) + $(foreach arch,$(LIBUNWIND_ARCHS),$(call feature_check,libunwind-debug-frame-$(arch))) else $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat))) endif diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 704c687ed3ad..4e4a92ef5e1e 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 include ../../scripts/Makefile.include +LIBUNWIND_ARCHS:=aarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x86 x86_64 + FILES= \ test-all.bin \ test-backtrace.bin \ @@ -38,12 +40,7 @@ FILES= \ test-libtracefs.bin \ test-libunwind.bin \ test-libunwind-debug-frame.bin \ - test-libunwind-x86.bin \ - test-libunwind-x86_64.bin \ - test-libunwind-arm.bin \ - test-libunwind-aarch64.bin \ - test-libunwind-debug-frame-arm.bin \ - test-libunwind-debug-frame-aarch64.bin \ + $(foreach arch,$(LIBUNWIND_ARCHS),test-libunwind-$(arch).bin test-libunwind-debug-frame-$(arch).bin) \ test-pthread-attr-setaffinity-np.bin \ test-pthread-barrier.bin \ test-stackprotector-all.bin \ @@ -211,27 +208,26 @@ $(OUTPUT)test-numa_num_possible_cpus.bin: $(BUILD) -lnuma $(OUTPUT)test-libunwind.bin: - $(BUILD) -lelf -llzma + $(BUILD) -include libunwind.h -lelf -llzma -lunwind $(OUTPUT)test-libunwind-debug-frame.bin: - $(BUILD) -lelf -llzma -$(OUTPUT)test-libunwind-x86.bin: - $(BUILD) -lelf -llzma -lunwind-x86 + $(BUILD) -include libunwind.h -lelf -llzma -lunwind -$(OUTPUT)test-libunwind-x86_64.bin: - $(BUILD) -lelf -llzma -lunwind-x86_64 +define LIBUNWIND_RULE +$$(OUTPUT)test-libunwind-$(1).bin: + $$(CC) $$(CFLAGS) -MD -Wall -Werror -include libunwind-$(1).h -o $$@ \ + test-libunwind.c $$(LDFLAGS) -lelf -llzma -lunwind-$(1) \ + > $$(@:.bin=.make.output) 2>&1 -$(OUTPUT)test-libunwind-arm.bin: - $(BUILD) -lelf -llzma -lunwind-arm +$$(OUTPUT)test-libunwind-debug-frame-$(1).bin: + $$(CC) $$(CFLAGS) -MD -Wall -Werror -include libunwind-$(1).h -o $$@ \ + test-libunwind-debug-frame.c $$(LDFLAGS) -lelf -llzma -lunwind-$(1) \ + > $$(@:.bin=.make.output) 2>&1 -$(OUTPUT)test-libunwind-aarch64.bin: - $(BUILD) -lelf -llzma -lunwind-aarch64 - -$(OUTPUT)test-libunwind-debug-frame-arm.bin: - $(BUILD) -lelf -llzma -lunwind-arm - -$(OUTPUT)test-libunwind-debug-frame-aarch64.bin: - $(BUILD) -lelf -llzma -lunwind-aarch64 +endef +$(foreach arch,$(LIBUNWIND_ARCHS), \ + $(eval $(call LIBUNWIND_RULE,$(arch))) \ +) $(OUTPUT)test-libslang.bin: $(BUILD) -lslang diff --git a/tools/build/feature/test-libunwind-aarch64.c b/tools/build/feature/test-libunwind-aarch64.c deleted file mode 100644 index 323803f49212..000000000000 --- a/tools/build/feature/test-libunwind-aarch64.c +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include - -extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); - -#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) - -static unw_accessors_t accessors; - -int main(void) -{ - unw_addr_space_t addr_space; - - addr_space = unw_create_addr_space(&accessors, 0); - if (addr_space) - return 0; - - unw_init_remote(NULL, addr_space, NULL); - dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL); - - return 0; -} diff --git a/tools/build/feature/test-libunwind-arm.c b/tools/build/feature/test-libunwind-arm.c deleted file mode 100644 index cb378b7d6866..000000000000 --- a/tools/build/feature/test-libunwind-arm.c +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include - -extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); - - -#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) - -static unw_accessors_t accessors; - -int main(void) -{ - unw_addr_space_t addr_space; - - addr_space = unw_create_addr_space(&accessors, 0); - if (addr_space) - return 0; - - unw_init_remote(NULL, addr_space, NULL); - dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL); - - return 0; -} diff --git a/tools/build/feature/test-libunwind-debug-frame-aarch64.c b/tools/build/feature/test-libunwind-debug-frame-aarch64.c deleted file mode 100644 index 36d6646c185e..000000000000 --- a/tools/build/feature/test-libunwind-debug-frame-aarch64.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include - -extern int -UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, - unw_word_t ip, unw_word_t segbase, - const char *obj_name, unw_word_t start, - unw_word_t end); - -#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) - -int main(void) -{ - dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0); - return 0; -} diff --git a/tools/build/feature/test-libunwind-debug-frame-arm.c b/tools/build/feature/test-libunwind-debug-frame-arm.c deleted file mode 100644 index 8696e48e1268..000000000000 --- a/tools/build/feature/test-libunwind-debug-frame-arm.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include - -extern int -UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, - unw_word_t ip, unw_word_t segbase, - const char *obj_name, unw_word_t start, - unw_word_t end); - -#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) - -int main(void) -{ - dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0); - return 0; -} diff --git a/tools/build/feature/test-libunwind-debug-frame.c b/tools/build/feature/test-libunwind-debug-frame.c index efb55cdd8d01..4c57e37004b3 100644 --- a/tools/build/feature/test-libunwind-debug-frame.c +++ b/tools/build/feature/test-libunwind-debug-frame.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 -#include #include extern int diff --git a/tools/build/feature/test-libunwind-x86.c b/tools/build/feature/test-libunwind-x86.c deleted file mode 100644 index e5e0f6c89637..000000000000 --- a/tools/build/feature/test-libunwind-x86.c +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include - -extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); - - -#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) - -static unw_accessors_t accessors; - -int main(void) -{ - unw_addr_space_t addr_space; - - addr_space = unw_create_addr_space(&accessors, 0); - if (addr_space) - return 0; - - unw_init_remote(NULL, addr_space, NULL); - dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL); - - return 0; -} diff --git a/tools/build/feature/test-libunwind-x86_64.c b/tools/build/feature/test-libunwind-x86_64.c deleted file mode 100644 index 62ae4db597dc..000000000000 --- a/tools/build/feature/test-libunwind-x86_64.c +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include - -extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); - - -#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) - -static unw_accessors_t accessors; - -int main(void) -{ - unw_addr_space_t addr_space; - - addr_space = unw_create_addr_space(&accessors, 0); - if (addr_space) - return 0; - - unw_init_remote(NULL, addr_space, NULL); - dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL); - - return 0; -} diff --git a/tools/build/feature/test-libunwind.c b/tools/build/feature/test-libunwind.c index 53fd26614ff0..5af5dc3a73d4 100644 --- a/tools/build/feature/test-libunwind.c +++ b/tools/build/feature/test-libunwind.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 -#include #include extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, From 444508cd7c7b4f052553af204cc73d5ac4d19901 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 13 May 2026 16:31:47 -0700 Subject: [PATCH 031/343] perf build: Be more programmatic when setting up libunwind variables Iterate LIBUNWIND_ARCHS when setting up CONFIG_ and HAVE_ definitions rather than treating each architecture individually. This sets up the libunwind build variables and C definitions beyond x86 and arm/aarch64. The existing naming convention is followed for compatibility. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andrew Jones Cc: Athira Rajeev Cc: Dapeng Mi Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Florian Fainelli Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Li Guan Cc: Namhyung Kim Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Shimin Guo Cc: Thomas Richter Cc: Tomas Glozar Cc: Will Deacon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 228 ++++++++++++++++--------------------- 1 file changed, 101 insertions(+), 127 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 06d7a3f9990c..7a0e372824c6 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -65,45 +65,13 @@ $(call detected_var,SRCARCH) CFLAGS += -I$(OUTPUT)arch/$(SRCARCH)/include/generated -# Additional ARCH settings for ppc -ifeq ($(SRCARCH),powerpc) - ifndef NO_LIBUNWIND - LIBUNWIND_LIBS := -lunwind -lunwind-ppc64 - endif -endif - # Additional ARCH settings for x86 ifeq ($(SRCARCH),x86) $(call detected,CONFIG_X86) ifeq (${IS_64_BIT}, 1) CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S - ifndef NO_LIBUNWIND - LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma - endif $(call detected,CONFIG_X86_64) - else - ifndef NO_LIBUNWIND - LIBUNWIND_LIBS = -lunwind-x86 -llzma -lunwind - endif - endif -endif - -ifeq ($(SRCARCH),arm) - ifndef NO_LIBUNWIND - LIBUNWIND_LIBS = -lunwind -lunwind-arm - endif -endif - -ifeq ($(SRCARCH),arm64) - ifndef NO_LIBUNWIND - LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 - endif -endif - -ifeq ($(SRCARCH),loongarch) - ifndef NO_LIBUNWIND - LIBUNWIND_LIBS = -lunwind -lunwind-loongarch64 endif endif @@ -111,49 +79,69 @@ ifeq ($(ARCH),s390) CFLAGS += -fPIC endif -ifeq ($(ARCH),mips) - ifndef NO_LIBUNWIND - LIBUNWIND_LIBS = -lunwind -lunwind-mips - endif -endif - ifneq ($(LIBUNWIND),1) NO_LIBUNWIND := 1 endif -ifeq ($(LIBUNWIND_LIBS),) - NO_LIBUNWIND := 1 +ifndef NO_LIBUNWIND + ifeq ($(SRCARCH),arm) + LIBUNWIND_LIBS = -lunwind -lunwind-arm + endif + ifeq ($(SRCARCH),arm64) + LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 + endif + ifeq ($(SRCARCH),loongarch) + LIBUNWIND_LIBS = -lunwind -lunwind-loongarch64 + endif + ifeq ($(ARCH),mips) + LIBUNWIND_LIBS = -lunwind -lunwind-mips + endif + ifeq ($(SRCARCH),powerpc) + LIBUNWIND_LIBS := -lunwind -lunwind-ppc64 + endif + ifeq ($(SRCARCH),riscv) + LIBUNWIND_LIBS := -lunwind -lunwind-riscv + endif + ifeq ($(SRCARCH),s390) + LIBUNWIND_LIBS := -lunwind -lunwind-s390x + endif + ifeq ($(SRCARCH),x86) + ifeq (${IS_64_BIT}, 1) + LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma + else + LIBUNWIND_LIBS = -lunwind-x86 -lunwind -llzma + endif + endif + ifeq ($(LIBUNWIND_LIBS),) + NO_LIBUNWIND := 1 + endif endif + # # For linking with debug library, run like: # # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ # - -libunwind_arch_set_flags = $(eval $(libunwind_arch_set_flags_code)) -define libunwind_arch_set_flags_code - FEATURE_CHECK_CFLAGS-libunwind-$(1) = -I$(LIBUNWIND_DIR)/include - FEATURE_CHECK_LDFLAGS-libunwind-$(1) = -L$(LIBUNWIND_DIR)/lib -endef - -ifdef LIBUNWIND_DIR - LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include - LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib - LIBUNWIND_ARCHS = x86 x86_64 arm aarch64 debug-frame-arm debug-frame-aarch64 loongarch - $(foreach libunwind_arch,$(LIBUNWIND_ARCHS),$(call libunwind_arch_set_flags,$(libunwind_arch))) -endif +LIBUNWIND_ARCHS:=aarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x86 x86_64 ifndef NO_LIBUNWIND - # Set per-feature check compilation flags FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) - - FEATURE_CHECK_LDFLAGS-libunwind-arm += -lunwind -lunwind-arm - FEATURE_CHECK_LDFLAGS-libunwind-aarch64 += -lunwind -lunwind-aarch64 - FEATURE_CHECK_LDFLAGS-libunwind-x86 += -lunwind -llzma -lunwind-x86 - FEATURE_CHECK_LDFLAGS-libunwind-x86_64 += -lunwind -llzma -lunwind-x86_64 + + ifdef LIBUNWIND_DIR + LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include + LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib + + define libunwind_arch_set_flags + FEATURE_CHECK_CFLAGS-libunwind-$(1) = -I$(LIBUNWIND_DIR)/include + FEATURE_CHECK_LDFLAGS-libunwind-$(1) = -L$(LIBUNWIND_DIR)/lib -lunwind -lunwind-$(1) + endef + $(foreach arch,$(LIBUNWIND_ARCHS), \ + $(eval $(call libunwind_arch_set_flags,$(arch))) \ + ) + endif endif ifdef CSINCLUDES @@ -638,49 +626,6 @@ ifeq ($(SRCARCH),powerpc) endif endif -ifndef NO_LIBUNWIND - have_libunwind := - - $(call feature_check,libunwind) - - $(call feature_check,libunwind-x86) - ifeq ($(feature-libunwind-x86), 1) - $(call detected,CONFIG_LIBUNWIND_X86) - CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT - LDFLAGS += -lunwind-x86 - EXTLIBS_LIBUNWIND += -lunwind-x86 - have_libunwind = 1 - endif - - $(call feature_check,libunwind-aarch64) - ifeq ($(feature-libunwind-aarch64), 1) - $(call detected,CONFIG_LIBUNWIND_AARCH64) - CFLAGS += -DHAVE_LIBUNWIND_AARCH64_SUPPORT - LDFLAGS += -lunwind-aarch64 - EXTLIBS_LIBUNWIND += -lunwind-aarch64 - have_libunwind = 1 - $(call feature_check,libunwind-debug-frame-aarch64) - ifneq ($(feature-libunwind-debug-frame-aarch64), 1) - $(warning No debug_frame support found in libunwind-aarch64) - CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_AARCH64 - endif - endif - - ifneq ($(feature-libunwind), 1) - $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR and set LIBUNWIND=1 in the make command line as it is opt-in now) - NO_LOCAL_LIBUNWIND := 1 - else - have_libunwind := 1 - $(call detected,CONFIG_LOCAL_LIBUNWIND) - endif - - ifneq ($(have_libunwind), 1) - NO_LIBUNWIND := 1 - endif -else - NO_LOCAL_LIBUNWIND := 1 -endif - ifndef NO_LIBBPF ifneq ($(feature-bpf), 1) $(warning BPF API too old. Please install recent kernel headers. BPF support in 'perf record' is disabled.) @@ -739,6 +684,60 @@ ifndef GEN_VMLINUX_H VMLINUX_H=$(src-perf)/util/bpf_skel/vmlinux/vmlinux.h endif +ifndef NO_LIBUNWIND + have_libunwind := + + $(call feature_check,libunwind) + ifneq ($(feature-libunwind), 1) + $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR and set LIBUNWIND=1 in the make command line as it is opt-in now) + NO_LOCAL_LIBUNWIND := 1 + else + have_libunwind := 1 + $(call detected,CONFIG_LOCAL_LIBUNWIND) + CFLAGS += -DHAVE_LIBUNWIND_SUPPORT + CFLAGS += $(LIBUNWIND_CFLAGS) + LDFLAGS += $(LIBUNWIND_LDFLAGS) + EXTLIBS_LIBUNWIND := $(LIBUNWIND_LIBS) + $(call feature_check,libunwind-debug-frame) + ifneq ($(feature-libunwind-debug-frame), 1) + CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME + endif + endif + + define PROCESS_REMOTE_LIBUNWIND_ARCH + $(call feature_check,libunwind-$(1)) + + ifeq ($$(feature-libunwind-$(1)), 1) + upper_arch := $$(shell echo $(1) | tr '[:lower:]' '[:upper:]') + $$(call detected,CONFIG_LIBUNWIND_$$(upper_arch)) + + CFLAGS += -DHAVE_LIBUNWIND_$$(upper_arch)_SUPPORT + LDFLAGS += -lunwind-$(1) + EXTLIBS_LIBUNWIND += -lunwind-$(1) + have_libunwind := 1 + + $$(call feature_check,libunwind-debug-frame-$(1)) + ifneq ($$(feature-libunwind-debug-frame-$(1)), 1) + CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_$$(upper_arch) + endif + endif + endef + $(foreach arch,$(LIBUNWIND_ARCHS), \ + $(eval $(call PROCESS_REMOTE_LIBUNWIND_ARCH,$(arch))) \ + ) + + EXTLIBS += $(EXTLIBS_LIBUNWIND) + + ifeq ($(findstring -static,${LDFLAGS}),-static) + # gcc -static links libgcc_eh which contains piece of libunwind + LIBUNWIND_LDFLAGS += -Wl,--allow-multiple-definition + endif + + ifneq ($(have_libunwind), 1) + NO_LIBUNWIND := 1 + endif +endif + dwarf-post-unwind := 1 dwarf-post-unwind-text := BUG @@ -761,31 +760,6 @@ ifeq ($(dwarf-post-unwind),1) $(call detected,CONFIG_DWARF_UNWIND) endif -ifndef NO_LIBUNWIND - ifndef NO_LOCAL_LIBUNWIND - ifeq ($(SRCARCH),$(filter $(SRCARCH),arm arm64)) - $(call feature_check,libunwind-debug-frame) - ifneq ($(feature-libunwind-debug-frame), 1) - $(warning No debug_frame support found in libunwind) - CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME - endif - else - # non-ARM has no dwarf_find_debug_frame() function: - CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME - endif - EXTLIBS += $(LIBUNWIND_LIBS) - LDFLAGS += $(LIBUNWIND_LIBS) - endif - ifeq ($(findstring -static,${LDFLAGS}),-static) - # gcc -static links libgcc_eh which contans piece of libunwind - LIBUNWIND_LDFLAGS += -Wl,--allow-multiple-definition - endif - CFLAGS += -DHAVE_LIBUNWIND_SUPPORT - CFLAGS += $(LIBUNWIND_CFLAGS) - LDFLAGS += $(LIBUNWIND_LDFLAGS) - EXTLIBS += $(EXTLIBS_LIBUNWIND) -endif - ifneq ($(NO_LIBTRACEEVENT),1) $(call detected,CONFIG_TRACE) endif From fdf08e4b5a33e840b6c2a988cd4392b4443ca51b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 13 May 2026 16:31:48 -0700 Subject: [PATCH 032/343] perf unwind-libunwind: Make libunwind register reading cross platform Move the libunwind register to perf register mapping functions in arch/../util/unwind-libunwind.c into a new libunwind-arch directory. Rename the functions to __get_perf_regnum_for_unw_regnum_. Add untested ppc32 and s390 functions. Add a get_perf_regnum_for_unw_regnum function that takes an ELF machine as well as a register number and chooses the appropriate architecture implementation. Split the x86 and powerpc 32 and 64-bit implementations apart so that a single libunwind-.h header is included. Move the e_machine into the unwind_info struct to make it easier to pass. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andrew Jones Cc: Athira Rajeev Cc: Dapeng Mi Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Florian Fainelli Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Li Guan Cc: Namhyung Kim Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Shimin Guo Cc: Thomas Richter Cc: Tomas Glozar Cc: Will Deacon [ Map UNW_PPC32_NIP to PERF_REG_POWERPC_NIP like done for 64-bit, pointed out by a local sashiko ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/Build | 2 - tools/perf/arch/arm/util/unwind-libunwind.c | 50 -------- tools/perf/arch/arm64/util/Build | 1 - tools/perf/arch/arm64/util/unwind-libunwind.c | 17 --- tools/perf/arch/loongarch/util/Build | 2 - .../arch/loongarch/util/unwind-libunwind.c | 82 ------------- tools/perf/arch/mips/Build | 1 - tools/perf/arch/mips/util/Build | 1 - tools/perf/arch/mips/util/unwind-libunwind.c | 22 ---- tools/perf/arch/powerpc/util/Build | 1 - .../perf/arch/powerpc/util/unwind-libunwind.c | 92 -------------- tools/perf/arch/x86/util/Build | 3 - tools/perf/arch/x86/util/unwind-libunwind.c | 115 ------------------ tools/perf/util/Build | 1 + tools/perf/util/libunwind-arch/Build | 10 ++ .../perf/util/libunwind-arch/libunwind-arch.c | 32 +++++ .../perf/util/libunwind-arch/libunwind-arch.h | 16 +++ .../perf/util/libunwind-arch/libunwind-arm.c | 15 +++ .../util/libunwind-arch/libunwind-arm64.c | 14 +++ .../perf/util/libunwind-arch/libunwind-i386.c | 43 +++++++ .../util/libunwind-arch/libunwind-loongarch.c | 27 ++++ .../perf/util/libunwind-arch/libunwind-mips.c | 29 +++++ .../util/libunwind-arch/libunwind-ppc32.c | 33 +++++ .../util/libunwind-arch/libunwind-ppc64.c | 33 +++++ .../perf/util/libunwind-arch/libunwind-s390.c | 29 +++++ .../util/libunwind-arch/libunwind-x86_64.c | 52 ++++++++ tools/perf/util/libunwind/arm64.c | 5 - tools/perf/util/libunwind/x86_32.c | 12 -- tools/perf/util/unwind-libunwind-local.c | 12 +- tools/perf/util/unwind.h | 5 - 30 files changed, 340 insertions(+), 417 deletions(-) delete mode 100644 tools/perf/arch/arm/util/unwind-libunwind.c delete mode 100644 tools/perf/arch/arm64/util/unwind-libunwind.c delete mode 100644 tools/perf/arch/loongarch/util/unwind-libunwind.c delete mode 100644 tools/perf/arch/mips/Build delete mode 100644 tools/perf/arch/mips/util/Build delete mode 100644 tools/perf/arch/mips/util/unwind-libunwind.c delete mode 100644 tools/perf/arch/powerpc/util/unwind-libunwind.c delete mode 100644 tools/perf/arch/x86/util/unwind-libunwind.c create mode 100644 tools/perf/util/libunwind-arch/Build create mode 100644 tools/perf/util/libunwind-arch/libunwind-arch.c create mode 100644 tools/perf/util/libunwind-arch/libunwind-arch.h create mode 100644 tools/perf/util/libunwind-arch/libunwind-arm.c create mode 100644 tools/perf/util/libunwind-arch/libunwind-arm64.c create mode 100644 tools/perf/util/libunwind-arch/libunwind-i386.c create mode 100644 tools/perf/util/libunwind-arch/libunwind-loongarch.c create mode 100644 tools/perf/util/libunwind-arch/libunwind-mips.c create mode 100644 tools/perf/util/libunwind-arch/libunwind-ppc32.c create mode 100644 tools/perf/util/libunwind-arch/libunwind-ppc64.c create mode 100644 tools/perf/util/libunwind-arch/libunwind-s390.c create mode 100644 tools/perf/util/libunwind-arch/libunwind-x86_64.c diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build index b94bf3c5279a..768ae5d16553 100644 --- a/tools/perf/arch/arm/util/Build +++ b/tools/perf/arch/arm/util/Build @@ -1,3 +1 @@ -perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o - perf-util-y += pmu.o auxtrace.o cs-etm.o diff --git a/tools/perf/arch/arm/util/unwind-libunwind.c b/tools/perf/arch/arm/util/unwind-libunwind.c deleted file mode 100644 index 438906bf0014..000000000000 --- a/tools/perf/arch/arm/util/unwind-libunwind.c +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include -#include -#include "perf_regs.h" -#include "../../../util/unwind.h" -#include "../../../util/debug.h" - -int libunwind__arch_reg_id(int regnum) -{ - switch (regnum) { - case UNW_ARM_R0: - return PERF_REG_ARM_R0; - case UNW_ARM_R1: - return PERF_REG_ARM_R1; - case UNW_ARM_R2: - return PERF_REG_ARM_R2; - case UNW_ARM_R3: - return PERF_REG_ARM_R3; - case UNW_ARM_R4: - return PERF_REG_ARM_R4; - case UNW_ARM_R5: - return PERF_REG_ARM_R5; - case UNW_ARM_R6: - return PERF_REG_ARM_R6; - case UNW_ARM_R7: - return PERF_REG_ARM_R7; - case UNW_ARM_R8: - return PERF_REG_ARM_R8; - case UNW_ARM_R9: - return PERF_REG_ARM_R9; - case UNW_ARM_R10: - return PERF_REG_ARM_R10; - case UNW_ARM_R11: - return PERF_REG_ARM_FP; - case UNW_ARM_R12: - return PERF_REG_ARM_IP; - case UNW_ARM_R13: - return PERF_REG_ARM_SP; - case UNW_ARM_R14: - return PERF_REG_ARM_LR; - case UNW_ARM_R15: - return PERF_REG_ARM_PC; - default: - pr_err("unwind: invalid reg id %d\n", regnum); - return -EINVAL; - } - - return -EINVAL; -} diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build index 638aa6948ab5..15b7340b70f7 100644 --- a/tools/perf/arch/arm64/util/Build +++ b/tools/perf/arch/arm64/util/Build @@ -1,4 +1,3 @@ -perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o perf-util-y += ../../arm/util/auxtrace.o perf-util-y += ../../arm/util/cs-etm.o perf-util-y += ../../arm/util/pmu.o diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c deleted file mode 100644 index 871af5992298..000000000000 --- a/tools/perf/arch/arm64/util/unwind-libunwind.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include - -#ifndef REMOTE_UNWIND_LIBUNWIND -#include -#include "perf_regs.h" -#include "../../../util/unwind.h" -#endif -#include "../../../util/debug.h" - -int LIBUNWIND__ARCH_REG_ID(int regnum) -{ - if (regnum < 0 || regnum >= PERF_REG_ARM64_EXTENDED_MAX) - return -EINVAL; - - return regnum; -} diff --git a/tools/perf/arch/loongarch/util/Build b/tools/perf/arch/loongarch/util/Build index 8d91e78d31c9..2328fb9a30a3 100644 --- a/tools/perf/arch/loongarch/util/Build +++ b/tools/perf/arch/loongarch/util/Build @@ -1,3 +1 @@ perf-util-y += header.o - -perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o diff --git a/tools/perf/arch/loongarch/util/unwind-libunwind.c b/tools/perf/arch/loongarch/util/unwind-libunwind.c deleted file mode 100644 index f693167b86ef..000000000000 --- a/tools/perf/arch/loongarch/util/unwind-libunwind.c +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include -#include -#include "perf_regs.h" -#include "../../util/unwind.h" -#include "util/debug.h" - -int libunwind__arch_reg_id(int regnum) -{ - switch (regnum) { - case UNW_LOONGARCH64_R1: - return PERF_REG_LOONGARCH_R1; - case UNW_LOONGARCH64_R2: - return PERF_REG_LOONGARCH_R2; - case UNW_LOONGARCH64_R3: - return PERF_REG_LOONGARCH_R3; - case UNW_LOONGARCH64_R4: - return PERF_REG_LOONGARCH_R4; - case UNW_LOONGARCH64_R5: - return PERF_REG_LOONGARCH_R5; - case UNW_LOONGARCH64_R6: - return PERF_REG_LOONGARCH_R6; - case UNW_LOONGARCH64_R7: - return PERF_REG_LOONGARCH_R7; - case UNW_LOONGARCH64_R8: - return PERF_REG_LOONGARCH_R8; - case UNW_LOONGARCH64_R9: - return PERF_REG_LOONGARCH_R9; - case UNW_LOONGARCH64_R10: - return PERF_REG_LOONGARCH_R10; - case UNW_LOONGARCH64_R11: - return PERF_REG_LOONGARCH_R11; - case UNW_LOONGARCH64_R12: - return PERF_REG_LOONGARCH_R12; - case UNW_LOONGARCH64_R13: - return PERF_REG_LOONGARCH_R13; - case UNW_LOONGARCH64_R14: - return PERF_REG_LOONGARCH_R14; - case UNW_LOONGARCH64_R15: - return PERF_REG_LOONGARCH_R15; - case UNW_LOONGARCH64_R16: - return PERF_REG_LOONGARCH_R16; - case UNW_LOONGARCH64_R17: - return PERF_REG_LOONGARCH_R17; - case UNW_LOONGARCH64_R18: - return PERF_REG_LOONGARCH_R18; - case UNW_LOONGARCH64_R19: - return PERF_REG_LOONGARCH_R19; - case UNW_LOONGARCH64_R20: - return PERF_REG_LOONGARCH_R20; - case UNW_LOONGARCH64_R21: - return PERF_REG_LOONGARCH_R21; - case UNW_LOONGARCH64_R22: - return PERF_REG_LOONGARCH_R22; - case UNW_LOONGARCH64_R23: - return PERF_REG_LOONGARCH_R23; - case UNW_LOONGARCH64_R24: - return PERF_REG_LOONGARCH_R24; - case UNW_LOONGARCH64_R25: - return PERF_REG_LOONGARCH_R25; - case UNW_LOONGARCH64_R26: - return PERF_REG_LOONGARCH_R26; - case UNW_LOONGARCH64_R27: - return PERF_REG_LOONGARCH_R27; - case UNW_LOONGARCH64_R28: - return PERF_REG_LOONGARCH_R28; - case UNW_LOONGARCH64_R29: - return PERF_REG_LOONGARCH_R29; - case UNW_LOONGARCH64_R30: - return PERF_REG_LOONGARCH_R30; - case UNW_LOONGARCH64_R31: - return PERF_REG_LOONGARCH_R31; - case UNW_LOONGARCH64_PC: - return PERF_REG_LOONGARCH_PC; - default: - pr_err("unwind: invalid reg id %d\n", regnum); - return -EINVAL; - } - - return -EINVAL; -} diff --git a/tools/perf/arch/mips/Build b/tools/perf/arch/mips/Build deleted file mode 100644 index e63eabc2c8f4..000000000000 --- a/tools/perf/arch/mips/Build +++ /dev/null @@ -1 +0,0 @@ -perf-util-y += util/ diff --git a/tools/perf/arch/mips/util/Build b/tools/perf/arch/mips/util/Build deleted file mode 100644 index 818b808a8247..000000000000 --- a/tools/perf/arch/mips/util/Build +++ /dev/null @@ -1 +0,0 @@ -perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o diff --git a/tools/perf/arch/mips/util/unwind-libunwind.c b/tools/perf/arch/mips/util/unwind-libunwind.c deleted file mode 100644 index 0d8c99c29da6..000000000000 --- a/tools/perf/arch/mips/util/unwind-libunwind.c +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include -#include -#include "perf_regs.h" -#include "../../util/unwind.h" -#include "util/debug.h" - -int libunwind__arch_reg_id(int regnum) -{ - switch (regnum) { - case UNW_MIPS_R1 ... UNW_MIPS_R25: - return regnum - UNW_MIPS_R1 + PERF_REG_MIPS_R1; - case UNW_MIPS_R28 ... UNW_MIPS_R31: - return regnum - UNW_MIPS_R28 + PERF_REG_MIPS_R28; - case UNW_MIPS_PC: - return PERF_REG_MIPS_PC; - default: - pr_err("unwind: invalid reg id %d\n", regnum); - return -EINVAL; - } -} diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build index d66574cbb9a9..ae928050e07a 100644 --- a/tools/perf/arch/powerpc/util/Build +++ b/tools/perf/arch/powerpc/util/Build @@ -6,5 +6,4 @@ perf-util-y += evsel.o perf-util-$(CONFIG_LIBDW) += skip-callchain-idx.o -perf-util-$(CONFIG_LIBUNWIND) += unwind-libunwind.o perf-util-y += auxtrace.o diff --git a/tools/perf/arch/powerpc/util/unwind-libunwind.c b/tools/perf/arch/powerpc/util/unwind-libunwind.c deleted file mode 100644 index 90a6beda20de..000000000000 --- a/tools/perf/arch/powerpc/util/unwind-libunwind.c +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2016 Chandan Kumar, IBM Corporation. - */ - -#include -#include -#include -#include "../../util/unwind.h" -#include "../../util/debug.h" - -int libunwind__arch_reg_id(int regnum) -{ - switch (regnum) { - case UNW_PPC64_R0: - return PERF_REG_POWERPC_R0; - case UNW_PPC64_R1: - return PERF_REG_POWERPC_R1; - case UNW_PPC64_R2: - return PERF_REG_POWERPC_R2; - case UNW_PPC64_R3: - return PERF_REG_POWERPC_R3; - case UNW_PPC64_R4: - return PERF_REG_POWERPC_R4; - case UNW_PPC64_R5: - return PERF_REG_POWERPC_R5; - case UNW_PPC64_R6: - return PERF_REG_POWERPC_R6; - case UNW_PPC64_R7: - return PERF_REG_POWERPC_R7; - case UNW_PPC64_R8: - return PERF_REG_POWERPC_R8; - case UNW_PPC64_R9: - return PERF_REG_POWERPC_R9; - case UNW_PPC64_R10: - return PERF_REG_POWERPC_R10; - case UNW_PPC64_R11: - return PERF_REG_POWERPC_R11; - case UNW_PPC64_R12: - return PERF_REG_POWERPC_R12; - case UNW_PPC64_R13: - return PERF_REG_POWERPC_R13; - case UNW_PPC64_R14: - return PERF_REG_POWERPC_R14; - case UNW_PPC64_R15: - return PERF_REG_POWERPC_R15; - case UNW_PPC64_R16: - return PERF_REG_POWERPC_R16; - case UNW_PPC64_R17: - return PERF_REG_POWERPC_R17; - case UNW_PPC64_R18: - return PERF_REG_POWERPC_R18; - case UNW_PPC64_R19: - return PERF_REG_POWERPC_R19; - case UNW_PPC64_R20: - return PERF_REG_POWERPC_R20; - case UNW_PPC64_R21: - return PERF_REG_POWERPC_R21; - case UNW_PPC64_R22: - return PERF_REG_POWERPC_R22; - case UNW_PPC64_R23: - return PERF_REG_POWERPC_R23; - case UNW_PPC64_R24: - return PERF_REG_POWERPC_R24; - case UNW_PPC64_R25: - return PERF_REG_POWERPC_R25; - case UNW_PPC64_R26: - return PERF_REG_POWERPC_R26; - case UNW_PPC64_R27: - return PERF_REG_POWERPC_R27; - case UNW_PPC64_R28: - return PERF_REG_POWERPC_R28; - case UNW_PPC64_R29: - return PERF_REG_POWERPC_R29; - case UNW_PPC64_R30: - return PERF_REG_POWERPC_R30; - case UNW_PPC64_R31: - return PERF_REG_POWERPC_R31; - case UNW_PPC64_LR: - return PERF_REG_POWERPC_LINK; - case UNW_PPC64_CTR: - return PERF_REG_POWERPC_CTR; - case UNW_PPC64_XER: - return PERF_REG_POWERPC_XER; - case UNW_PPC64_NIP: - return PERF_REG_POWERPC_NIP; - default: - pr_err("unwind: invalid reg id %d\n", regnum); - return -EINVAL; - } - return -EINVAL; -} diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build index b94c91984c66..7f89fffe4615 100644 --- a/tools/perf/arch/x86/util/Build +++ b/tools/perf/arch/x86/util/Build @@ -8,9 +8,6 @@ perf-util-y += evlist.o perf-util-y += mem-events.o perf-util-y += evsel.o perf-util-y += iostat.o - -perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o - perf-util-y += auxtrace.o perf-util-y += intel-pt.o perf-util-y += intel-bts.o diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c deleted file mode 100644 index 47357973b55b..000000000000 --- a/tools/perf/arch/x86/util/unwind-libunwind.c +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include -#include "../../util/debug.h" -#ifndef REMOTE_UNWIND_LIBUNWIND -#include -#include "perf_regs.h" -#include "../../util/unwind.h" -#endif - -#ifdef HAVE_ARCH_X86_64_SUPPORT -int LIBUNWIND__ARCH_REG_ID(int regnum) -{ - int id; - - switch (regnum) { - case UNW_X86_64_RAX: - id = PERF_REG_X86_AX; - break; - case UNW_X86_64_RDX: - id = PERF_REG_X86_DX; - break; - case UNW_X86_64_RCX: - id = PERF_REG_X86_CX; - break; - case UNW_X86_64_RBX: - id = PERF_REG_X86_BX; - break; - case UNW_X86_64_RSI: - id = PERF_REG_X86_SI; - break; - case UNW_X86_64_RDI: - id = PERF_REG_X86_DI; - break; - case UNW_X86_64_RBP: - id = PERF_REG_X86_BP; - break; - case UNW_X86_64_RSP: - id = PERF_REG_X86_SP; - break; - case UNW_X86_64_R8: - id = PERF_REG_X86_R8; - break; - case UNW_X86_64_R9: - id = PERF_REG_X86_R9; - break; - case UNW_X86_64_R10: - id = PERF_REG_X86_R10; - break; - case UNW_X86_64_R11: - id = PERF_REG_X86_R11; - break; - case UNW_X86_64_R12: - id = PERF_REG_X86_R12; - break; - case UNW_X86_64_R13: - id = PERF_REG_X86_R13; - break; - case UNW_X86_64_R14: - id = PERF_REG_X86_R14; - break; - case UNW_X86_64_R15: - id = PERF_REG_X86_R15; - break; - case UNW_X86_64_RIP: - id = PERF_REG_X86_IP; - break; - default: - pr_err("unwind: invalid reg id %d\n", regnum); - return -EINVAL; - } - - return id; -} -#else -int LIBUNWIND__ARCH_REG_ID(int regnum) -{ - int id; - - switch (regnum) { - case UNW_X86_EAX: - id = PERF_REG_X86_AX; - break; - case UNW_X86_EDX: - id = PERF_REG_X86_DX; - break; - case UNW_X86_ECX: - id = PERF_REG_X86_CX; - break; - case UNW_X86_EBX: - id = PERF_REG_X86_BX; - break; - case UNW_X86_ESI: - id = PERF_REG_X86_SI; - break; - case UNW_X86_EDI: - id = PERF_REG_X86_DI; - break; - case UNW_X86_EBP: - id = PERF_REG_X86_BP; - break; - case UNW_X86_ESP: - id = PERF_REG_X86_SP; - break; - case UNW_X86_EIP: - id = PERF_REG_X86_IP; - break; - default: - pr_err("unwind: invalid reg id %d\n", regnum); - return -EINVAL; - } - - return id; -} -#endif /* HAVE_ARCH_X86_64_SUPPORT */ diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 01edfccebb88..bf4204135ccb 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -228,6 +228,7 @@ perf-util-$(CONFIG_LIBDW) += unwind-libdw.o perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o perf-util-$(CONFIG_LIBUNWIND) += unwind-libunwind.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-arch/ perf-util-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o perf-util-$(CONFIG_LIBUNWIND_AARCH64) += libunwind/arm64.o diff --git a/tools/perf/util/libunwind-arch/Build b/tools/perf/util/libunwind-arch/Build new file mode 100644 index 000000000000..87fd657a3248 --- /dev/null +++ b/tools/perf/util/libunwind-arch/Build @@ -0,0 +1,10 @@ +perf-util-$(CONFIG_LIBUNWIND) += libunwind-arch.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-arm64.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-arm.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-loongarch.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-mips.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-ppc32.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-ppc64.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-s390.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-i386.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-x86_64.o diff --git a/tools/perf/util/libunwind-arch/libunwind-arch.c b/tools/perf/util/libunwind-arch/libunwind-arch.c new file mode 100644 index 000000000000..5439bf90d161 --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-arch.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libunwind-arch.h" +#include "../debug.h" +#include +#include + +int get_perf_regnum_for_unw_regnum(unsigned int e_machine, int unw_regnum) +{ + switch (e_machine) { + case EM_ARM: + return __get_perf_regnum_for_unw_regnum_arm(unw_regnum); + case EM_AARCH64: + return __get_perf_regnum_for_unw_regnum_arm64(unw_regnum); + case EM_LOONGARCH: + return __get_perf_regnum_for_unw_regnum_loongarch(unw_regnum); + case EM_MIPS: + return __get_perf_regnum_for_unw_regnum_mips(unw_regnum); + case EM_PPC: + return __get_perf_regnum_for_unw_regnum_ppc32(unw_regnum); + case EM_PPC64: + return __get_perf_regnum_for_unw_regnum_ppc64(unw_regnum); + case EM_S390: + return __get_perf_regnum_for_unw_regnum_s390(unw_regnum); + case EM_386: + return __get_perf_regnum_for_unw_regnum_i386(unw_regnum); + case EM_X86_64: + return __get_perf_regnum_for_unw_regnum_x86_64(unw_regnum); + default: + pr_err("ELF MACHINE %x is not supported.\n", e_machine); + return -EINVAL; + } +} diff --git a/tools/perf/util/libunwind-arch/libunwind-arch.h b/tools/perf/util/libunwind-arch/libunwind-arch.h new file mode 100644 index 000000000000..e1009c6cb965 --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-arch.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBUNWIND_ARCH_H +#define __LIBUNWIND_ARCH_H + +int __get_perf_regnum_for_unw_regnum_arm(int unw_regnum); +int __get_perf_regnum_for_unw_regnum_arm64(int unw_regnum); +int __get_perf_regnum_for_unw_regnum_loongarch(int unw_regnum); +int __get_perf_regnum_for_unw_regnum_mips(int unw_regnum); +int __get_perf_regnum_for_unw_regnum_ppc32(int unw_regnum); +int __get_perf_regnum_for_unw_regnum_ppc64(int unw_regnum); +int __get_perf_regnum_for_unw_regnum_s390(int unw_regnum); +int __get_perf_regnum_for_unw_regnum_i386(int unw_regnum); +int __get_perf_regnum_for_unw_regnum_x86_64(int unw_regnum); +int get_perf_regnum_for_unw_regnum(unsigned int e_machine, int unw_regnum); + +#endif /* __LIBUNWIND_ARCH_H */ diff --git a/tools/perf/util/libunwind-arch/libunwind-arm.c b/tools/perf/util/libunwind-arch/libunwind-arm.c new file mode 100644 index 000000000000..6740ee55b043 --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-arm.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libunwind-arch.h" +#include "../debug.h" +#include "../../../arch/arm/include/uapi/asm/perf_regs.h" +#include +#include + +int __get_perf_regnum_for_unw_regnum_arm(int unw_regnum) +{ + if (unw_regnum < 0 || unw_regnum >= PERF_REG_ARM_MAX) { + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } + return unw_regnum; +} diff --git a/tools/perf/util/libunwind-arch/libunwind-arm64.c b/tools/perf/util/libunwind-arch/libunwind-arm64.c new file mode 100644 index 000000000000..53b1877dfa04 --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-arm64.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libunwind-arch.h" +#include "../debug.h" +#include "../../../arch/arm64/include/uapi/asm/perf_regs.h" +#include + +int __get_perf_regnum_for_unw_regnum_arm64(int unw_regnum) +{ + if (unw_regnum < 0 || unw_regnum >= PERF_REG_ARM64_EXTENDED_MAX) { + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } + return unw_regnum; +} diff --git a/tools/perf/util/libunwind-arch/libunwind-i386.c b/tools/perf/util/libunwind-arch/libunwind-i386.c new file mode 100644 index 000000000000..a41f7c3c2fa5 --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-i386.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libunwind-arch.h" +#include "../debug.h" +#include "../../../arch/x86/include/uapi/asm/perf_regs.h" +#include +#include +#include + +#ifdef HAVE_LIBUNWIND_X86_SUPPORT +#include +#endif + +int __get_perf_regnum_for_unw_regnum_i386(int unw_regnum __maybe_unused) +{ +#ifndef HAVE_LIBUNWIND_X86_SUPPORT + return -EINVAL; +#else + static const int perf_i386_regnums[] = { +#define REGNUM(reg) [UNW_X86_E ## reg] = PERF_REG_X86_ ## reg + REGNUM(AX), + REGNUM(DX), + REGNUM(CX), + REGNUM(BX), + REGNUM(SI), + REGNUM(DI), + REGNUM(BP), + REGNUM(SP), + REGNUM(IP), +#undef REGNUM + }; + + if (unw_regnum == UNW_X86_EAX) + return PERF_REG_X86_AX; + + if (unw_regnum < 0 || unw_regnum >= (int)ARRAY_SIZE(perf_i386_regnums) || + perf_i386_regnums[unw_regnum] == 0) { + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } + + return perf_i386_regnums[unw_regnum]; +#endif // HAVE_LIBUNWIND_X86_SUPPORT +} diff --git a/tools/perf/util/libunwind-arch/libunwind-loongarch.c b/tools/perf/util/libunwind-arch/libunwind-loongarch.c new file mode 100644 index 000000000000..0431757505f9 --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-loongarch.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libunwind-arch.h" +#include "../debug.h" +#include "../../../arch/loongarch/include/uapi/asm/perf_regs.h" +#include +#include + +#ifdef HAVE_LIBUNWIND_LOONGARCH64_SUPPORT +#include +#endif + +int __get_perf_regnum_for_unw_regnum_loongarch(int unw_regnum __maybe_unused) +{ +#ifndef HAVE_LIBUNWIND_LOONGARCH64_SUPPORT + return -EINVAL; +#else + switch (unw_regnum) { + case UNW_LOONGARCH64_R1 ... UNW_LOONGARCH64_R31: + return unw_regnum - UNW_LOONGARCH64_R1 + PERF_REG_LOONGARCH_R1; + case UNW_LOONGARCH64_PC: + return PERF_REG_LOONGARCH_PC; + default: + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } +#endif // HAVE_LIBUNWIND_LOONGARCH64_SUPPORT +} diff --git a/tools/perf/util/libunwind-arch/libunwind-mips.c b/tools/perf/util/libunwind-arch/libunwind-mips.c new file mode 100644 index 000000000000..01a506c8079c --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-mips.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libunwind-arch.h" +#include "../debug.h" +#include "../../../arch/mips/include/uapi/asm/perf_regs.h" +#include +#include + +#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT +#include +#endif + +int __get_perf_regnum_for_unw_regnum_mips(int unw_regnum __maybe_unused) +{ +#ifndef HAVE_LIBUNWIND_MIPS_SUPPORT + return -EINVAL; +#else + switch (unw_regnum) { + case UNW_MIPS_R1 ... UNW_MIPS_R25: + return unw_regnum - UNW_MIPS_R1 + PERF_REG_MIPS_R1; + case UNW_MIPS_R28 ... UNW_MIPS_R31: + return unw_regnum - UNW_MIPS_R28 + PERF_REG_MIPS_R28; + case UNW_MIPS_PC: + return PERF_REG_MIPS_PC; + default: + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } +#endif // HAVE_LIBUNWIND_MIPS_SUPPORT +} diff --git a/tools/perf/util/libunwind-arch/libunwind-ppc32.c b/tools/perf/util/libunwind-arch/libunwind-ppc32.c new file mode 100644 index 000000000000..976a16030407 --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-ppc32.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include "libunwind-arch.h" +#include "../debug.h" +#include "../../../arch/powerpc/include/uapi/asm/perf_regs.h" +#include +#include + +#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT +#include +#endif + +int __get_perf_regnum_for_unw_regnum_ppc32(int unw_regnum __maybe_unused) +{ +#ifndef HAVE_LIBUNWIND_PPC32_SUPPORT + return -EINVAL; +#else + switch (unw_regnum) { + case UNW_PPC32_R0 ... UNW_PPC32_R31: + return unw_regnum - UNW_PPC32_R0 + PERF_REG_POWERPC_R0; + case UNW_PPC32_LR: + return PERF_REG_POWERPC_LINK; + case UNW_PPC32_CTR: + return PERF_REG_POWERPC_CTR; + case UNW_PPC32_XER: + return PERF_REG_POWERPC_XER; + case UNW_PPC32_NIP: + return PERF_REG_POWERPC_NIP; + default: + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } +#endif // HAVE_LIBUNWIND_PPC32_SUPPORT +} diff --git a/tools/perf/util/libunwind-arch/libunwind-ppc64.c b/tools/perf/util/libunwind-arch/libunwind-ppc64.c new file mode 100644 index 000000000000..c508dc89615b --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-ppc64.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include "libunwind-arch.h" +#include "../debug.h" +#include "../../../arch/powerpc/include/uapi/asm/perf_regs.h" +#include +#include + +#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT +#include +#endif + +int __get_perf_regnum_for_unw_regnum_ppc64(int unw_regnum __maybe_unused) +{ +#ifndef HAVE_LIBUNWIND_PPC64_SUPPORT + return -EINVAL; +#else + switch (unw_regnum) { + case UNW_PPC64_R0 ... UNW_PPC64_R31: + return unw_regnum - UNW_PPC64_R0 + PERF_REG_POWERPC_R0; + case UNW_PPC64_LR: + return PERF_REG_POWERPC_LINK; + case UNW_PPC64_CTR: + return PERF_REG_POWERPC_CTR; + case UNW_PPC64_XER: + return PERF_REG_POWERPC_XER; + case UNW_PPC64_NIP: + return PERF_REG_POWERPC_NIP; + default: + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } +#endif // HAVE_LIBUNWIND_PPC64_SUPPORT +} diff --git a/tools/perf/util/libunwind-arch/libunwind-s390.c b/tools/perf/util/libunwind-arch/libunwind-s390.c new file mode 100644 index 000000000000..7088991015e6 --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-s390.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libunwind-arch.h" +#include "../debug.h" +#include "../../../arch/s390/include/uapi/asm/perf_regs.h" +#include +#include + +#ifdef HAVE_LIBUNWIND_S390X_SUPPORT +#include +#endif + +int __get_perf_regnum_for_unw_regnum_s390(int unw_regnum __maybe_unused) +{ +#ifndef HAVE_LIBUNWIND_S390X_SUPPORT + return -EINVAL; +#else + switch (unw_regnum) { + case UNW_S390X_R0 ... UNW_S390X_R15: + return unw_regnum - UNW_S390X_R0 + PERF_REG_S390_R0; + case UNW_S390X_F0 ... UNW_S390X_F15: + return unw_regnum - UNW_S390X_F0 + PERF_REG_S390_FP0; + case UNW_S390X_IP: + return PERF_REG_S390_PC; + default: + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } +#endif // HAVE_LIBUNWIND_S390X_SUPPORT +} diff --git a/tools/perf/util/libunwind-arch/libunwind-x86_64.c b/tools/perf/util/libunwind-arch/libunwind-x86_64.c new file mode 100644 index 000000000000..82dfb2c7152a --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-x86_64.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libunwind-arch.h" +#include "../debug.h" +#include "../../../arch/x86/include/uapi/asm/perf_regs.h" +#include +#include +#include + +#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT +#include +#endif + +int __get_perf_regnum_for_unw_regnum_x86_64(int unw_regnum __maybe_unused) +{ +#ifndef HAVE_LIBUNWIND_X86_64_SUPPORT + return -EINVAL; +#else + static const int perf_x86_64_regnums[] = { +#define REGNUM(reg) [UNW_X86_64_R ## reg] = PERF_REG_X86_ ## reg + REGNUM(AX), + REGNUM(DX), + REGNUM(CX), + REGNUM(BX), + REGNUM(SI), + REGNUM(DI), + REGNUM(BP), + REGNUM(SP), + REGNUM(IP), +#undef REGNUM +#define REGNUM(reg) [UNW_X86_64_ ## reg] = PERF_REG_X86_ ## reg + REGNUM(R8), + REGNUM(R9), + REGNUM(R10), + REGNUM(R11), + REGNUM(R12), + REGNUM(R13), + REGNUM(R14), + REGNUM(R15), +#undef REGNUM + }; + + if (unw_regnum == UNW_X86_64_RAX) + return PERF_REG_X86_AX; + + if (unw_regnum < 0 || unw_regnum >= (int)ARRAY_SIZE(perf_x86_64_regnums) || + perf_x86_64_regnums[unw_regnum] == 0) { + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } + return perf_x86_64_regnums[unw_regnum]; +#endif // HAVE_LIBUNWIND_X86_64_SUPPORT +} diff --git a/tools/perf/util/libunwind/arm64.c b/tools/perf/util/libunwind/arm64.c index 37ecef0c53b9..15670a964495 100644 --- a/tools/perf/util/libunwind/arm64.c +++ b/tools/perf/util/libunwind/arm64.c @@ -14,11 +14,6 @@ #define REMOTE_UNWIND_LIBUNWIND -/* Define arch specific functions & regs for libunwind, should be - * defined before including "unwind.h" - */ -#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arm64_reg_id(regnum) - #include "unwind.h" #include "libunwind-aarch64.h" #define perf_event_arm_regs perf_event_arm64_regs diff --git a/tools/perf/util/libunwind/x86_32.c b/tools/perf/util/libunwind/x86_32.c index 1697dece1b74..1e9fb8bfec44 100644 --- a/tools/perf/util/libunwind/x86_32.c +++ b/tools/perf/util/libunwind/x86_32.c @@ -14,20 +14,8 @@ #define REMOTE_UNWIND_LIBUNWIND -/* Define arch specific functions & regs for libunwind, should be - * defined before including "unwind.h" - */ -#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__x86_reg_id(regnum) - #include "unwind.h" #include "libunwind-x86.h" -#include <../../../../arch/x86/include/uapi/asm/perf_regs.h> - -/* HAVE_ARCH_X86_64_SUPPORT is used in'arch/x86/util/unwind-libunwind.c' - * for x86_32, we undef it to compile code for x86_32 only. - */ -#undef HAVE_ARCH_X86_64_SUPPORT -#include "../../arch/x86/util/unwind-libunwind.c" /* Explicitly define NO_LIBUNWIND_DEBUG_FRAME, because non-ARM has no * dwarf_find_debug_frame() function. diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c index 27e2f7b31789..adc6e82b5f27 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c @@ -39,6 +39,7 @@ #include "debug.h" #include "asm/bug.h" #include "dso.h" +#include "libunwind-arch/libunwind-arch.h" extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, @@ -95,6 +96,7 @@ struct unwind_info { struct perf_sample *sample; struct machine *machine; struct thread *thread; + uint16_t e_machine; bool best_effort; }; @@ -583,9 +585,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as, } ret = perf_reg_value(&start, perf_sample__user_regs(ui->sample), - perf_arch_reg_sp(thread__e_machine(ui->thread, - ui->machine, - /*e_flags=*/NULL))); + perf_arch_reg_sp(ui->e_machine)); if (ret) return ret; @@ -633,7 +633,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as, return 0; } - id = LIBUNWIND__ARCH_REG_ID(regnum); + id = get_perf_regnum_for_unw_regnum(ui->e_machine, regnum); if (id < 0) return -EINVAL; @@ -734,7 +734,6 @@ static void _unwind__finish_access(struct maps *maps) static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, void *arg, int max_stack) { - uint16_t e_machine = thread__e_machine(ui->thread, ui->machine, /*e_flags=*/NULL); u64 val; unw_word_t ips[max_stack]; unw_addr_space_t addr_space; @@ -742,7 +741,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, int ret, i = 0; ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), - perf_arch_reg_ip(e_machine)); + perf_arch_reg_ip(ui->e_machine)); if (ret) return 0; @@ -820,6 +819,7 @@ static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg, .sample = data, .thread = thread, .machine = maps__machine(thread__maps(thread)), + .e_machine = thread__e_machine(thread, /*machine=*/NULL, /*e_flags=*/NULL), .best_effort = best_effort }; diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index 69ba08afda79..ce256b00b6d2 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -64,11 +64,6 @@ int libunwind__get_entries(unwind_entry_cb_t cb, void *arg, struct thread *thread, struct perf_sample *data, int max_stack, bool best_effort); -#ifndef LIBUNWIND__ARCH_REG_ID -#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arch_reg_id(regnum) -#endif - -int LIBUNWIND__ARCH_REG_ID(int regnum); int unwind__prepare_access(struct maps *maps, struct map *map, bool *initialized); void unwind__flush_access(struct maps *maps); void unwind__finish_access(struct maps *maps); From 2723e9f8b5cf36b8c49b9798fdbe326cf2b70785 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 13 May 2026 16:31:49 -0700 Subject: [PATCH 033/343] perf unwind-libunwind: Move flush/finish access out of local Flush and finish access are relatively simple calls into libunwind, move them out struct unwind_libunwind_ops. So that the correct version can be called, add an e_machine variable to maps. This size regression will go away when the unwind_libunwind_ops no longer need stashing in the maps. To set the e_machine up pass it into unwind__prepare_access, which no longer needs to determine the unwind operations based on a map dso because of this. This also means the maps copying code can call unwind__prepare_access once for the e_machine rather than once per map. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andrew Jones Cc: Athira Rajeev Cc: Dapeng Mi Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Florian Fainelli Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Li Guan Cc: Namhyung Kim Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Shimin Guo Cc: Thomas Richter Cc: Tomas Glozar Cc: Will Deacon Signed-off-by: Arnaldo Carvalho de Melo --- .../perf/util/libunwind-arch/libunwind-arch.c | 82 +++++++++++++++++++ .../perf/util/libunwind-arch/libunwind-arch.h | 24 ++++++ .../perf/util/libunwind-arch/libunwind-arm.c | 19 +++++ .../util/libunwind-arch/libunwind-arm64.c | 20 +++++ .../perf/util/libunwind-arch/libunwind-i386.c | 15 ++++ .../util/libunwind-arch/libunwind-loongarch.c | 15 ++++ .../perf/util/libunwind-arch/libunwind-mips.c | 15 ++++ .../util/libunwind-arch/libunwind-ppc32.c | 15 ++++ .../util/libunwind-arch/libunwind-ppc64.c | 15 ++++ .../perf/util/libunwind-arch/libunwind-s390.c | 15 ++++ .../util/libunwind-arch/libunwind-x86_64.c | 15 ++++ tools/perf/util/maps.c | 36 +++++--- tools/perf/util/maps.h | 2 + tools/perf/util/thread.c | 32 ++------ tools/perf/util/unwind-libunwind-local.c | 12 --- tools/perf/util/unwind-libunwind.c | 59 ++++++------- tools/perf/util/unwind.h | 8 +- 17 files changed, 309 insertions(+), 90 deletions(-) diff --git a/tools/perf/util/libunwind-arch/libunwind-arch.c b/tools/perf/util/libunwind-arch/libunwind-arch.c index 5439bf90d161..9692e6c81492 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arch.c +++ b/tools/perf/util/libunwind-arch/libunwind-arch.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include #include @@ -30,3 +31,84 @@ int get_perf_regnum_for_unw_regnum(unsigned int e_machine, int unw_regnum) return -EINVAL; } } + + +void libunwind_arch__flush_access(struct maps *maps) +{ + unsigned int e_machine = maps__e_machine(maps); + + switch (e_machine) { + case EM_NONE: + break; // No libunwind info on the maps. + case EM_ARM: + __libunwind_arch__flush_access_arm(maps); + break; + case EM_AARCH64: + __libunwind_arch__flush_access_arm64(maps); + break; + case EM_LOONGARCH: + __libunwind_arch__flush_access_loongarch(maps); + break; + case EM_MIPS: + __libunwind_arch__flush_access_mips(maps); + break; + case EM_PPC: + __libunwind_arch__flush_access_ppc32(maps); + break; + case EM_PPC64: + __libunwind_arch__flush_access_ppc64(maps); + break; + case EM_S390: + __libunwind_arch__flush_access_s390(maps); + break; + case EM_386: + __libunwind_arch__flush_access_i386(maps); + break; + case EM_X86_64: + __libunwind_arch__flush_access_x86_64(maps); + break; + default: + pr_err("ELF MACHINE %x is not supported.\n", e_machine); + break; + } +} + +void libunwind_arch__finish_access(struct maps *maps) +{ + unsigned int e_machine = maps__e_machine(maps); + + switch (e_machine) { + case EM_NONE: + break; // No libunwind info on the maps. + case EM_ARM: + __libunwind_arch__finish_access_arm(maps); + break; + case EM_AARCH64: + __libunwind_arch__finish_access_arm64(maps); + break; + case EM_LOONGARCH: + __libunwind_arch__finish_access_loongarch(maps); + break; + case EM_MIPS: + __libunwind_arch__finish_access_mips(maps); + break; + case EM_PPC: + __libunwind_arch__finish_access_ppc32(maps); + break; + case EM_PPC64: + __libunwind_arch__finish_access_ppc64(maps); + break; + case EM_S390: + __libunwind_arch__finish_access_s390(maps); + break; + case EM_386: + __libunwind_arch__finish_access_i386(maps); + break; + case EM_X86_64: + __libunwind_arch__finish_access_x86_64(maps); + break; + default: + pr_err("ELF MACHINE %x is not supported.\n", e_machine); + break; + } +} diff --git a/tools/perf/util/libunwind-arch/libunwind-arch.h b/tools/perf/util/libunwind-arch/libunwind-arch.h index e1009c6cb965..c00277a5e914 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arch.h +++ b/tools/perf/util/libunwind-arch/libunwind-arch.h @@ -2,6 +2,8 @@ #ifndef __LIBUNWIND_ARCH_H #define __LIBUNWIND_ARCH_H +struct maps; + int __get_perf_regnum_for_unw_regnum_arm(int unw_regnum); int __get_perf_regnum_for_unw_regnum_arm64(int unw_regnum); int __get_perf_regnum_for_unw_regnum_loongarch(int unw_regnum); @@ -13,4 +15,26 @@ int __get_perf_regnum_for_unw_regnum_i386(int unw_regnum); int __get_perf_regnum_for_unw_regnum_x86_64(int unw_regnum); int get_perf_regnum_for_unw_regnum(unsigned int e_machine, int unw_regnum); +void __libunwind_arch__flush_access_arm(struct maps *maps); +void __libunwind_arch__flush_access_arm64(struct maps *maps); +void __libunwind_arch__flush_access_loongarch(struct maps *maps); +void __libunwind_arch__flush_access_mips(struct maps *maps); +void __libunwind_arch__flush_access_ppc32(struct maps *maps); +void __libunwind_arch__flush_access_ppc64(struct maps *maps); +void __libunwind_arch__flush_access_s390(struct maps *maps); +void __libunwind_arch__flush_access_i386(struct maps *maps); +void __libunwind_arch__flush_access_x86_64(struct maps *maps); +void libunwind_arch__flush_access(struct maps *maps); + +void __libunwind_arch__finish_access_arm(struct maps *maps); +void __libunwind_arch__finish_access_arm64(struct maps *maps); +void __libunwind_arch__finish_access_loongarch(struct maps *maps); +void __libunwind_arch__finish_access_mips(struct maps *maps); +void __libunwind_arch__finish_access_ppc32(struct maps *maps); +void __libunwind_arch__finish_access_ppc64(struct maps *maps); +void __libunwind_arch__finish_access_s390(struct maps *maps); +void __libunwind_arch__finish_access_i386(struct maps *maps); +void __libunwind_arch__finish_access_x86_64(struct maps *maps); +void libunwind_arch__finish_access(struct maps *maps); + #endif /* __LIBUNWIND_ARCH_H */ diff --git a/tools/perf/util/libunwind-arch/libunwind-arm.c b/tools/perf/util/libunwind-arch/libunwind-arm.c index 6740ee55b043..bbaf01406c52 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arm.c +++ b/tools/perf/util/libunwind-arch/libunwind-arm.c @@ -1,10 +1,15 @@ // SPDX-License-Identifier: GPL-2.0 #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include "../../../arch/arm/include/uapi/asm/perf_regs.h" #include #include +#ifdef HAVE_LIBUNWIND_ARM_SUPPORT +#include +#endif + int __get_perf_regnum_for_unw_regnum_arm(int unw_regnum) { if (unw_regnum < 0 || unw_regnum >= PERF_REG_ARM_MAX) { @@ -13,3 +18,17 @@ int __get_perf_regnum_for_unw_regnum_arm(int unw_regnum) } return unw_regnum; } + +void __libunwind_arch__flush_access_arm(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_ARM_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_arm(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_ARM_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-arm64.c b/tools/perf/util/libunwind-arch/libunwind-arm64.c index 53b1877dfa04..8ba510089736 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arm64.c +++ b/tools/perf/util/libunwind-arch/libunwind-arm64.c @@ -1,9 +1,15 @@ // SPDX-License-Identifier: GPL-2.0 #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include "../../../arch/arm64/include/uapi/asm/perf_regs.h" +#include #include +#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT +#include +#endif + int __get_perf_regnum_for_unw_regnum_arm64(int unw_regnum) { if (unw_regnum < 0 || unw_regnum >= PERF_REG_ARM64_EXTENDED_MAX) { @@ -12,3 +18,17 @@ int __get_perf_regnum_for_unw_regnum_arm64(int unw_regnum) } return unw_regnum; } + +void __libunwind_arch__flush_access_arm64(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_arm64(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-i386.c b/tools/perf/util/libunwind-arch/libunwind-i386.c index a41f7c3c2fa5..383f0a44d290 100644 --- a/tools/perf/util/libunwind-arch/libunwind-i386.c +++ b/tools/perf/util/libunwind-arch/libunwind-i386.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include "../../../arch/x86/include/uapi/asm/perf_regs.h" #include #include @@ -41,3 +42,17 @@ int __get_perf_regnum_for_unw_regnum_i386(int unw_regnum __maybe_unused) return perf_i386_regnums[unw_regnum]; #endif // HAVE_LIBUNWIND_X86_SUPPORT } + +void __libunwind_arch__flush_access_i386(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_i386(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-loongarch.c b/tools/perf/util/libunwind-arch/libunwind-loongarch.c index 0431757505f9..7ff459849930 100644 --- a/tools/perf/util/libunwind-arch/libunwind-loongarch.c +++ b/tools/perf/util/libunwind-arch/libunwind-loongarch.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include "../../../arch/loongarch/include/uapi/asm/perf_regs.h" #include #include @@ -25,3 +26,17 @@ int __get_perf_regnum_for_unw_regnum_loongarch(int unw_regnum __maybe_unused) } #endif // HAVE_LIBUNWIND_LOONGARCH64_SUPPORT } + +void __libunwind_arch__flush_access_loongarch(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_LOONGARCH64_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_loongarch(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_LOONGARCH64_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-mips.c b/tools/perf/util/libunwind-arch/libunwind-mips.c index 01a506c8079c..1fa81742ff4a 100644 --- a/tools/perf/util/libunwind-arch/libunwind-mips.c +++ b/tools/perf/util/libunwind-arch/libunwind-mips.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include "../../../arch/mips/include/uapi/asm/perf_regs.h" #include #include @@ -27,3 +28,17 @@ int __get_perf_regnum_for_unw_regnum_mips(int unw_regnum __maybe_unused) } #endif // HAVE_LIBUNWIND_MIPS_SUPPORT } + +void __libunwind_arch__flush_access_mips(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_mips(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-ppc32.c b/tools/perf/util/libunwind-arch/libunwind-ppc32.c index 976a16030407..deb49a44c257 100644 --- a/tools/perf/util/libunwind-arch/libunwind-ppc32.c +++ b/tools/perf/util/libunwind-arch/libunwind-ppc32.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include "../../../arch/powerpc/include/uapi/asm/perf_regs.h" #include #include @@ -31,3 +32,17 @@ int __get_perf_regnum_for_unw_regnum_ppc32(int unw_regnum __maybe_unused) } #endif // HAVE_LIBUNWIND_PPC32_SUPPORT } + +void __libunwind_arch__flush_access_ppc32(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_ppc32(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-ppc64.c b/tools/perf/util/libunwind-arch/libunwind-ppc64.c index c508dc89615b..9d7321214fac 100644 --- a/tools/perf/util/libunwind-arch/libunwind-ppc64.c +++ b/tools/perf/util/libunwind-arch/libunwind-ppc64.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include "../../../arch/powerpc/include/uapi/asm/perf_regs.h" #include #include @@ -31,3 +32,17 @@ int __get_perf_regnum_for_unw_regnum_ppc64(int unw_regnum __maybe_unused) } #endif // HAVE_LIBUNWIND_PPC64_SUPPORT } + +void __libunwind_arch__flush_access_ppc64(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_ppc64(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-s390.c b/tools/perf/util/libunwind-arch/libunwind-s390.c index 7088991015e6..ab296931dbbc 100644 --- a/tools/perf/util/libunwind-arch/libunwind-s390.c +++ b/tools/perf/util/libunwind-arch/libunwind-s390.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include "../../../arch/s390/include/uapi/asm/perf_regs.h" #include #include @@ -27,3 +28,17 @@ int __get_perf_regnum_for_unw_regnum_s390(int unw_regnum __maybe_unused) } #endif // HAVE_LIBUNWIND_S390X_SUPPORT } + +void __libunwind_arch__flush_access_s390(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_S390X_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_s390(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_S390X_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-x86_64.c b/tools/perf/util/libunwind-arch/libunwind-x86_64.c index 82dfb2c7152a..2caca0b7b384 100644 --- a/tools/perf/util/libunwind-arch/libunwind-x86_64.c +++ b/tools/perf/util/libunwind-arch/libunwind-x86_64.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "libunwind-arch.h" #include "../debug.h" +#include "../maps.h" #include "../../../arch/x86/include/uapi/asm/perf_regs.h" #include #include @@ -50,3 +51,17 @@ int __get_perf_regnum_for_unw_regnum_x86_64(int unw_regnum __maybe_unused) return perf_x86_64_regnums[unw_regnum]; #endif // HAVE_LIBUNWIND_X86_64_SUPPORT } + +void __libunwind_arch__flush_access_x86_64(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_x86_64(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c index 81a97ac34077..27924c70e0e1 100644 --- a/tools/perf/util/maps.c +++ b/tools/perf/util/maps.c @@ -40,6 +40,7 @@ DECLARE_RC_STRUCT(maps) { #ifdef HAVE_LIBUNWIND_SUPPORT void *addr_space; const struct unwind_libunwind_ops *unwind_libunwind_ops; + uint16_t e_machine; #endif #ifdef HAVE_LIBDW_SUPPORT void *libdw_addr_space_dwfl; @@ -206,6 +207,16 @@ void maps__set_unwind_libunwind_ops(struct maps *maps, const struct unwind_libun { RC_CHK_ACCESS(maps)->unwind_libunwind_ops = ops; } + +uint16_t maps__e_machine(const struct maps *maps) +{ + return RC_CHK_ACCESS(maps)->e_machine; +} + +void maps__set_e_machine(struct maps *maps, uint16_t e_machine) +{ + RC_CHK_ACCESS(maps)->e_machine = e_machine; +} #endif #ifdef HAVE_LIBDW_SUPPORT void *maps__libdw_addr_space_dwfl(const struct maps *maps) @@ -1039,6 +1050,14 @@ int maps__copy_from(struct maps *dest, struct maps *parent) down_write(maps__lock(dest)); down_read(maps__lock(parent)); +#ifdef HAVE_LIBUNWIND_SUPPORT + err = unwind__prepare_access(dest, maps__e_machine(parent)); + if (err) { + up_read(maps__lock(parent)); + up_write(maps__lock(dest)); + return err; + } +#endif parent_maps_by_address = maps__maps_by_address(parent); n = maps__nr_maps(parent); if (maps__nr_maps(dest) == 0) { @@ -1068,14 +1087,11 @@ int maps__copy_from(struct maps *dest, struct maps *parent) if (!new) err = -ENOMEM; else { - err = unwind__prepare_access(dest, new, NULL); - if (!err) { - dest_maps_by_address[i] = new; - map__set_kmap_maps(new, dest); - if (dest_maps_by_name) - dest_maps_by_name[i] = map__get(new); - RC_CHK_ACCESS(dest)->nr_maps = i + 1; - } + dest_maps_by_address[i] = new; + map__set_kmap_maps(new, dest); + if (dest_maps_by_name) + dest_maps_by_name[i] = map__get(new); + RC_CHK_ACCESS(dest)->nr_maps = i + 1; } if (err) map__put(new); @@ -1093,9 +1109,7 @@ int maps__copy_from(struct maps *dest, struct maps *parent) if (!new) err = -ENOMEM; else { - err = unwind__prepare_access(dest, new, NULL); - if (!err) - err = __maps__insert(dest, new); + err = __maps__insert(dest, new); } map__put(new); } diff --git a/tools/perf/util/maps.h b/tools/perf/util/maps.h index 20c52084ba9e..6469f62c41a8 100644 --- a/tools/perf/util/maps.h +++ b/tools/perf/util/maps.h @@ -51,6 +51,8 @@ void *maps__addr_space(const struct maps *maps); void maps__set_addr_space(struct maps *maps, void *addr_space); const struct unwind_libunwind_ops *maps__unwind_libunwind_ops(const struct maps *maps); void maps__set_unwind_libunwind_ops(struct maps *maps, const struct unwind_libunwind_ops *ops); +uint16_t maps__e_machine(const struct maps *maps); +void maps__set_e_machine(struct maps *maps, uint16_t e_machine); #endif #ifdef HAVE_LIBDW_SUPPORT void *maps__libdw_addr_space_dwfl(const struct maps *maps); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 22be77225bb0..aac9cb75dcf4 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -358,41 +358,21 @@ size_t thread__fprintf(struct thread *thread, FILE *fp) int thread__insert_map(struct thread *thread, struct map *map) { int ret; + uint16_t e_machine; - ret = unwind__prepare_access(thread__maps(thread), map, NULL); + ret = maps__fixup_overlap_and_insert(thread__maps(thread), map); if (ret) return ret; - return maps__fixup_overlap_and_insert(thread__maps(thread), map); -} - -struct thread__prepare_access_maps_cb_args { - int err; - struct maps *maps; -}; - -static int thread__prepare_access_maps_cb(struct map *map, void *data) -{ - bool initialized = false; - struct thread__prepare_access_maps_cb_args *args = data; - - args->err = unwind__prepare_access(args->maps, map, &initialized); - - return (args->err || initialized) ? 1 : 0; + e_machine = thread__e_machine(thread, /*machine=*/NULL, /*e_flags=*/NULL); + return unwind__prepare_access(thread__maps(thread), e_machine); } static int thread__prepare_access(struct thread *thread) { - struct thread__prepare_access_maps_cb_args args = { - .err = 0, - }; + uint16_t e_machine = thread__e_machine(thread, /*machine=*/NULL, /*e_flags=*/NULL); - if (dwarf_callchain_users) { - args.maps = thread__maps(thread); - maps__for_each_map(thread__maps(thread), thread__prepare_access_maps_cb, &args); - } - - return args.err; + return unwind__prepare_access(thread__maps(thread), e_machine); } static int thread__clone_maps(struct thread *thread, struct thread *parent, bool do_maps_clone) diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c index adc6e82b5f27..a9af2839e828 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c @@ -721,16 +721,6 @@ static int _unwind__prepare_access(struct maps *maps) return 0; } -static void _unwind__flush_access(struct maps *maps) -{ - unw_flush_cache(maps__addr_space(maps), 0, 0); -} - -static void _unwind__finish_access(struct maps *maps) -{ - unw_destroy_addr_space(maps__addr_space(maps)); -} - static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, void *arg, int max_stack) { @@ -835,8 +825,6 @@ static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg, static struct unwind_libunwind_ops _unwind_libunwind_ops = { .prepare_access = _unwind__prepare_access, - .flush_access = _unwind__flush_access, - .finish_access = _unwind__finish_access, .get_entries = _unwind__get_entries, }; diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index a0016b897dae..00be1286b799 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c @@ -7,76 +7,63 @@ #include "debug.h" #include "env.h" #include "callchain.h" +#include "libunwind-arch/libunwind-arch.h" +#include +#include struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops; struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops; struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops; -int unwind__prepare_access(struct maps *maps, struct map *map, bool *initialized) +int unwind__prepare_access(struct maps *maps, uint16_t e_machine) { - const char *arch; - enum dso_type dso_type; struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops; - struct dso *dso = map__dso(map); - struct machine *machine; - int err; if (!dwarf_callchain_users) return 0; if (maps__addr_space(maps)) { - pr_debug("unwind: thread map already set, dso=%s\n", dso__name(dso)); - if (initialized) - *initialized = true; + pr_debug3("unwind: thread map already set\n"); return 0; } - machine = maps__machine(maps); - /* env->arch is NULL for live-mode (i.e. perf top) */ - if (!machine->env || !machine->env->arch) - goto out_register; - - dso_type = dso__type(dso, machine); - if (dso_type == DSO__TYPE_UNKNOWN) + if (e_machine == EM_NONE) return 0; - arch = perf_env__arch(machine->env); - - if (!strcmp(arch, "x86")) { - if (dso_type != DSO__TYPE_64BIT) + if (e_machine != EM_HOST) { + /* If not live/local mode. */ + switch (e_machine) { + case EM_386: ops = x86_32_unwind_libunwind_ops; - } else if (!strcmp(arch, "arm64") || !strcmp(arch, "arm")) { - if (dso_type == DSO__TYPE_64BIT) + break; + case EM_AARCH64: ops = arm64_unwind_libunwind_ops; + break; + default: + pr_warning_once("unwind: ELF machine type %d is not supported\n", + e_machine); + return 0; + } } if (!ops) { - pr_warning_once("unwind: target platform=%s is not supported\n", arch); + pr_warning_once("unwind: target platform is not supported\n"); return 0; } -out_register: maps__set_unwind_libunwind_ops(maps, ops); + maps__set_e_machine(maps, e_machine); - err = maps__unwind_libunwind_ops(maps)->prepare_access(maps); - if (initialized) - *initialized = err ? false : true; - return err; + return ops->prepare_access(maps); } void unwind__flush_access(struct maps *maps) { - const struct unwind_libunwind_ops *ops = maps__unwind_libunwind_ops(maps); - - if (ops) - ops->flush_access(maps); + libunwind_arch__flush_access(maps); } void unwind__finish_access(struct maps *maps) { - const struct unwind_libunwind_ops *ops = maps__unwind_libunwind_ops(maps); - - if (ops) - ops->finish_access(maps); + libunwind_arch__finish_access(maps); } int libunwind__get_entries(unwind_entry_cb_t cb, void *arg, diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index ce256b00b6d2..6a0f117898b2 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -2,6 +2,7 @@ #ifndef __UNWIND_H #define __UNWIND_H +#include #include #include #include "map_symbol.h" @@ -20,8 +21,6 @@ typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); struct unwind_libunwind_ops { int (*prepare_access)(struct maps *maps); - void (*flush_access)(struct maps *maps); - void (*finish_access)(struct maps *maps); int (*get_entries)(unwind_entry_cb_t cb, void *arg, struct thread *thread, struct perf_sample *data, int max_stack, bool best_effort); @@ -64,7 +63,7 @@ int libunwind__get_entries(unwind_entry_cb_t cb, void *arg, struct thread *thread, struct perf_sample *data, int max_stack, bool best_effort); -int unwind__prepare_access(struct maps *maps, struct map *map, bool *initialized); +int unwind__prepare_access(struct maps *maps, uint16_t e_machine); void unwind__flush_access(struct maps *maps); void unwind__finish_access(struct maps *maps); #else @@ -81,8 +80,7 @@ static inline int libunwind__get_entries(unwind_entry_cb_t cb __maybe_unused, } static inline int unwind__prepare_access(struct maps *maps __maybe_unused, - struct map *map __maybe_unused, - bool *initialized __maybe_unused) + uint16_t e_machine __maybe_unused) { return 0; } From 88b4275ff542510fa80c32c863571c71d60f8766 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 13 May 2026 16:31:50 -0700 Subject: [PATCH 034/343] perf unwind-libunwind: Remove libunwind-local Local unwinding only works on the machine libunwind is built for, rather than cross platform, the APIs for remote and local unwinding are similar but types like unw_word_t depend on the included header. Place the architecture specific code into the appropriate libunwind-.c file. Put generic code in unwind-libunwind.c and use libunwind-arch to choose the correct implementation based on the thread's e_machine. Structuring the code this way avoids including the unwind-libunwind-local.c for each architecture of remote unwinding. Data is moved into the struct unwind_info to simplify the architecture and generic code, trying to keep as much code as possible generic. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andrew Jones Cc: Athira Rajeev Cc: Dapeng Mi Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Florian Fainelli Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Li Guan Cc: Namhyung Kim Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Shimin Guo Cc: Thomas Richter Cc: Tomas Glozar Cc: Will Deacon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 3 - .../perf/util/libunwind-arch/libunwind-arch.c | 184 ++++ .../perf/util/libunwind-arch/libunwind-arch.h | 234 +++++ .../perf/util/libunwind-arch/libunwind-arm.c | 256 ++++++ .../util/libunwind-arch/libunwind-arm64.c | 255 ++++++ .../perf/util/libunwind-arch/libunwind-i386.c | 254 ++++++ .../util/libunwind-arch/libunwind-loongarch.c | 255 ++++++ .../perf/util/libunwind-arch/libunwind-mips.c | 255 ++++++ .../util/libunwind-arch/libunwind-ppc32.c | 255 ++++++ .../util/libunwind-arch/libunwind-ppc64.c | 255 ++++++ .../perf/util/libunwind-arch/libunwind-s390.c | 255 ++++++ .../util/libunwind-arch/libunwind-x86_64.c | 253 ++++++ tools/perf/util/libunwind/arm64.c | 35 - tools/perf/util/libunwind/x86_32.c | 29 - tools/perf/util/maps.c | 10 - tools/perf/util/maps.h | 2 - tools/perf/util/unwind-libunwind-local.c | 834 ------------------ tools/perf/util/unwind-libunwind.c | 680 +++++++++++++- tools/perf/util/unwind.h | 7 - 19 files changed, 3353 insertions(+), 958 deletions(-) delete mode 100644 tools/perf/util/libunwind/arm64.c delete mode 100644 tools/perf/util/libunwind/x86_32.c delete mode 100644 tools/perf/util/unwind-libunwind-local.c diff --git a/tools/perf/util/Build b/tools/perf/util/Build index bf4204135ccb..2bb60f50f62d 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -226,11 +226,8 @@ perf-util-$(CONFIG_LIBDW) += annotate-data.o perf-util-$(CONFIG_LIBDW) += libdw.o perf-util-$(CONFIG_LIBDW) += unwind-libdw.o -perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o perf-util-$(CONFIG_LIBUNWIND) += unwind-libunwind.o perf-util-$(CONFIG_LIBUNWIND) += libunwind-arch/ -perf-util-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o -perf-util-$(CONFIG_LIBUNWIND_AARCH64) += libunwind/arm64.o ifeq ($(CONFIG_LIBTRACEEVENT),y) perf-util-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o diff --git a/tools/perf/util/libunwind-arch/libunwind-arch.c b/tools/perf/util/libunwind-arch/libunwind-arch.c index 9692e6c81492..8539b4233df4 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arch.c +++ b/tools/perf/util/libunwind-arch/libunwind-arch.c @@ -112,3 +112,187 @@ void libunwind_arch__finish_access(struct maps *maps) break; } } + +void *libunwind_arch__create_addr_space(unsigned int e_machine) +{ + switch (e_machine) { + case EM_ARM: + return __libunwind_arch__create_addr_space_arm(); + case EM_AARCH64: + return __libunwind_arch__create_addr_space_arm64(); + case EM_LOONGARCH: + return __libunwind_arch__create_addr_space_loongarch(); + case EM_MIPS: + return __libunwind_arch__create_addr_space_mips(); + case EM_PPC: + return __libunwind_arch__create_addr_space_ppc32(); + case EM_PPC64: + return __libunwind_arch__create_addr_space_ppc64(); + case EM_S390: + return __libunwind_arch__create_addr_space_s390(); + case EM_386: + return __libunwind_arch__create_addr_space_i386(); + case EM_X86_64: + return __libunwind_arch__create_addr_space_x86_64(); + default: + pr_err("ELF MACHINE %x is not supported.\n", e_machine); + return NULL; + } +} + +int libunwind_arch__dwarf_search_unwind_table(unsigned int e_machine, + void *as, + uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg) +{ + switch (e_machine) { + case EM_ARM: + return __libunwind_arch__dwarf_search_unwind_table_arm(as, ip, di, pi, + need_unwind_info, arg); + case EM_AARCH64: + return __libunwind_arch__dwarf_search_unwind_table_arm64(as, ip, di, pi, + need_unwind_info, arg); + case EM_LOONGARCH: + return __libunwind_arch__dwarf_search_unwind_table_loongarch(as, ip, di, pi, + need_unwind_info, arg); + case EM_MIPS: + return __libunwind_arch__dwarf_search_unwind_table_mips(as, ip, di, pi, + need_unwind_info, arg); + case EM_PPC: + return __libunwind_arch__dwarf_search_unwind_table_ppc32(as, ip, di, pi, + need_unwind_info, arg); + case EM_PPC64: + return __libunwind_arch__dwarf_search_unwind_table_ppc64(as, ip, di, pi, + need_unwind_info, arg); + case EM_S390: + return __libunwind_arch__dwarf_search_unwind_table_s390(as, ip, di, pi, + need_unwind_info, arg); + case EM_386: + return __libunwind_arch__dwarf_search_unwind_table_i386(as, ip, di, pi, + need_unwind_info, arg); + case EM_X86_64: + return __libunwind_arch__dwarf_search_unwind_table_x86_64(as, ip, di, pi, + need_unwind_info, arg); + default: + pr_err("ELF MACHINE %x is not supported.\n", e_machine); + return -EINVAL; + } +} + +int libunwind_arch__dwarf_find_debug_frame(unsigned int e_machine, + int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end) +{ + switch (e_machine) { + case EM_ARM: + return __libunwind_arch__dwarf_find_debug_frame_arm(found, di_debug, ip, segbase, + obj_name, start, end); + case EM_AARCH64: + return __libunwind_arch__dwarf_find_debug_frame_arm64(found, di_debug, ip, segbase, + obj_name, start, end); + case EM_LOONGARCH: + return __libunwind_arch__dwarf_find_debug_frame_loongarch(found, di_debug, ip, + segbase, obj_name, + start, end); + case EM_MIPS: + return __libunwind_arch__dwarf_find_debug_frame_mips(found, di_debug, ip, segbase, + obj_name, start, end); + case EM_PPC: + return __libunwind_arch__dwarf_find_debug_frame_ppc32(found, di_debug, ip, segbase, + obj_name, start, end); + case EM_PPC64: + return __libunwind_arch__dwarf_find_debug_frame_ppc64(found, di_debug, ip, segbase, + obj_name, start, end); + case EM_S390: + return __libunwind_arch__dwarf_find_debug_frame_s390(found, di_debug, ip, segbase, + obj_name, start, end); + case EM_386: + return __libunwind_arch__dwarf_find_debug_frame_i386(found, di_debug, ip, segbase, + obj_name, start, end); + case EM_X86_64: + return __libunwind_arch__dwarf_find_debug_frame_x86_64(found, di_debug, ip, segbase, + obj_name, start, end); + default: + pr_err("ELF MACHINE %x is not supported.\n", e_machine); + return -EINVAL; + } +} + +struct unwind_info *libunwind_arch_unwind_info__new(struct thread *thread, + struct perf_sample *sample, int max_stack, + bool best_effort, uint16_t e_machine, + uint64_t first_ip) +{ + switch (e_machine) { + case EM_ARM: + return __libunwind_arch_unwind_info__new_arm(thread, sample, max_stack, + best_effort, first_ip); + case EM_AARCH64: + return __libunwind_arch_unwind_info__new_arm64(thread, sample, max_stack, + best_effort, first_ip); + case EM_LOONGARCH: + return __libunwind_arch_unwind_info__new_loongarch(thread, sample, max_stack, + best_effort, first_ip); + case EM_MIPS: + return __libunwind_arch_unwind_info__new_mips(thread, sample, max_stack, + best_effort, first_ip); + case EM_PPC: + return __libunwind_arch_unwind_info__new_ppc32(thread, sample, max_stack, + best_effort, first_ip); + case EM_PPC64: + return __libunwind_arch_unwind_info__new_ppc64(thread, sample, max_stack, + best_effort, first_ip); + case EM_S390: + return __libunwind_arch_unwind_info__new_s390(thread, sample, max_stack, + best_effort, first_ip); + case EM_386: + return __libunwind_arch_unwind_info__new_i386(thread, sample, max_stack, + best_effort, first_ip); + case EM_X86_64: + return __libunwind_arch_unwind_info__new_x86_64(thread, sample, max_stack, + best_effort, first_ip); + default: + pr_err("ELF MACHINE %x is not supported.\n", e_machine); + return NULL; + } +} + +void libunwind_arch_unwind_info__delete(struct unwind_info *ui) +{ + free(ui); +} + +int libunwind_arch__unwind_step(struct unwind_info *ui) +{ + switch (ui->e_machine) { + case EM_ARM: + return __libunwind_arch__unwind_step_arm(ui); + case EM_AARCH64: + return __libunwind_arch__unwind_step_arm64(ui); + case EM_LOONGARCH: + return __libunwind_arch__unwind_step_loongarch(ui); + case EM_MIPS: + return __libunwind_arch__unwind_step_mips(ui); + case EM_PPC: + return __libunwind_arch__unwind_step_ppc32(ui); + case EM_PPC64: + return __libunwind_arch__unwind_step_ppc64(ui); + case EM_S390: + return __libunwind_arch__unwind_step_s390(ui); + case EM_386: + return __libunwind_arch__unwind_step_i386(ui); + case EM_X86_64: + return __libunwind_arch__unwind_step_x86_64(ui); + default: + pr_err("ELF MACHINE %x is not supported.\n", ui->e_machine); + return -EINVAL; + } +} diff --git a/tools/perf/util/libunwind-arch/libunwind-arch.h b/tools/perf/util/libunwind-arch/libunwind-arch.h index c00277a5e914..2bf7fc33313b 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arch.h +++ b/tools/perf/util/libunwind-arch/libunwind-arch.h @@ -2,7 +2,36 @@ #ifndef __LIBUNWIND_ARCH_H #define __LIBUNWIND_ARCH_H +#include +#include +#include + +struct machine; struct maps; +struct perf_sample; +struct thread; + +struct unwind_info { + struct machine *machine; + struct thread *thread; + struct perf_sample *sample; + void *cursor; + uint64_t *ips; + int cur_ip; + int max_ips; + unsigned int unw_word_t_size; + uint16_t e_machine; + bool best_effort; +}; + +struct libarch_unwind__dyn_info { + uint64_t start_ip; + uint64_t end_ip; + uint64_t segbase; + uint64_t table_data; + uint64_t table_len; +}; +struct libarch_unwind__proc_info; int __get_perf_regnum_for_unw_regnum_arm(int unw_regnum); int __get_perf_regnum_for_unw_regnum_arm64(int unw_regnum); @@ -37,4 +66,209 @@ void __libunwind_arch__finish_access_i386(struct maps *maps); void __libunwind_arch__finish_access_x86_64(struct maps *maps); void libunwind_arch__finish_access(struct maps *maps); +void *__libunwind_arch__create_addr_space_arm(void); +void *__libunwind_arch__create_addr_space_arm64(void); +void *__libunwind_arch__create_addr_space_loongarch(void); +void *__libunwind_arch__create_addr_space_mips(void); +void *__libunwind_arch__create_addr_space_ppc32(void); +void *__libunwind_arch__create_addr_space_ppc64(void); +void *__libunwind_arch__create_addr_space_s390(void); +void *__libunwind_arch__create_addr_space_i386(void); +void *__libunwind_arch__create_addr_space_x86_64(void); +void *libunwind_arch__create_addr_space(unsigned int e_machine); + +int __libunwind__find_proc_info(void *as, uint64_t ip, void *pi, int need_unwind_info, void *arg); +int __libunwind__access_mem(void *as, uint64_t addr, void *valp_word, int __write, void *arg); +int __libunwind__access_reg(void *as, int regnum, void *valp_word, int __write, void *arg); + +int __libunwind_arch__dwarf_search_unwind_table_arm(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); +int __libunwind_arch__dwarf_search_unwind_table_arm64(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); +int __libunwind_arch__dwarf_search_unwind_table_loongarch(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); +int __libunwind_arch__dwarf_search_unwind_table_mips(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); +int __libunwind_arch__dwarf_search_unwind_table_ppc32(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); +int __libunwind_arch__dwarf_search_unwind_table_ppc64(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); +int __libunwind_arch__dwarf_search_unwind_table_s390(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); +int __libunwind_arch__dwarf_search_unwind_table_i386(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); +int __libunwind_arch__dwarf_search_unwind_table_x86_64(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); +int libunwind_arch__dwarf_search_unwind_table(unsigned int e_machine, + void *as, + uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); + +int __libunwind_arch__dwarf_find_debug_frame_arm(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); +int __libunwind_arch__dwarf_find_debug_frame_arm64(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); +int __libunwind_arch__dwarf_find_debug_frame_loongarch(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); +int __libunwind_arch__dwarf_find_debug_frame_mips(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); +int __libunwind_arch__dwarf_find_debug_frame_ppc32(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); +int __libunwind_arch__dwarf_find_debug_frame_ppc64(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); +int __libunwind_arch__dwarf_find_debug_frame_s390(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); +int __libunwind_arch__dwarf_find_debug_frame_i386(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); +int __libunwind_arch__dwarf_find_debug_frame_x86_64(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); +int libunwind_arch__dwarf_find_debug_frame(unsigned int e_machine, + int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); + +struct unwind_info *__libunwind_arch_unwind_info__new_arm(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); +struct unwind_info *__libunwind_arch_unwind_info__new_arm64(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); +struct unwind_info *__libunwind_arch_unwind_info__new_loongarch(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); +struct unwind_info *__libunwind_arch_unwind_info__new_mips(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); +struct unwind_info *__libunwind_arch_unwind_info__new_ppc32(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); +struct unwind_info *__libunwind_arch_unwind_info__new_ppc64(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); +struct unwind_info *__libunwind_arch_unwind_info__new_s390(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); +struct unwind_info *__libunwind_arch_unwind_info__new_i386(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); +struct unwind_info *__libunwind_arch_unwind_info__new_x86_64(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); +struct unwind_info *libunwind_arch_unwind_info__new(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint16_t e_machine, + uint64_t first_ip); + +void libunwind_arch_unwind_info__delete(struct unwind_info *ui); + +int __libunwind_arch__unwind_step_arm(struct unwind_info *ui); +int __libunwind_arch__unwind_step_arm64(struct unwind_info *ui); +int __libunwind_arch__unwind_step_loongarch(struct unwind_info *ui); +int __libunwind_arch__unwind_step_mips(struct unwind_info *ui); +int __libunwind_arch__unwind_step_ppc32(struct unwind_info *ui); +int __libunwind_arch__unwind_step_ppc64(struct unwind_info *ui); +int __libunwind_arch__unwind_step_s390(struct unwind_info *ui); +int __libunwind_arch__unwind_step_i386(struct unwind_info *ui); +int __libunwind_arch__unwind_step_x86_64(struct unwind_info *ui); +int libunwind_arch__unwind_step(struct unwind_info *ui); + #endif /* __LIBUNWIND_ARCH_H */ diff --git a/tools/perf/util/libunwind-arch/libunwind-arm.c b/tools/perf/util/libunwind-arch/libunwind-arm.c index bbaf01406c52..61b1c5a70b7f 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arm.c +++ b/tools/perf/util/libunwind-arch/libunwind-arm.c @@ -2,8 +2,12 @@ #include "libunwind-arch.h" #include "../debug.h" #include "../maps.h" +#include "../thread.h" #include "../../../arch/arm/include/uapi/asm/perf_regs.h" #include +#include +#include +#include #include #ifdef HAVE_LIBUNWIND_ARM_SUPPORT @@ -32,3 +36,255 @@ void __libunwind_arch__finish_access_arm(struct maps *maps __maybe_unused) unw_destroy_addr_space(maps__addr_space(maps)); #endif } + + +#ifdef HAVE_LIBUNWIND_ARM_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_arm(void) +{ +#ifdef HAVE_LIBUNWIND_ARM_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_ARM_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_arm(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_ARM_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_ARM_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_ARM) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_arm(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_ARM_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_ARM) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_arm(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_ARM_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_ARM; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_arm(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_ARM_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-arm64.c b/tools/perf/util/libunwind-arch/libunwind-arm64.c index 8ba510089736..4d467dd440a1 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arm64.c +++ b/tools/perf/util/libunwind-arch/libunwind-arm64.c @@ -2,8 +2,12 @@ #include "libunwind-arch.h" #include "../debug.h" #include "../maps.h" +#include "../thread.h" #include "../../../arch/arm64/include/uapi/asm/perf_regs.h" #include +#include +#include +#include #include #ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT @@ -32,3 +36,254 @@ void __libunwind_arch__finish_access_arm64(struct maps *maps __maybe_unused) unw_destroy_addr_space(maps__addr_space(maps)); #endif } + +#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_arm64(void) +{ +#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_ARM64_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_arm64(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_ARM64_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_ARM64_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_ARM64) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_arm64(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_ARM64_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_ARM64) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_arm64(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_ARM64_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_AARCH64; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_arm64(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_ARM64_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-i386.c b/tools/perf/util/libunwind-arch/libunwind-i386.c index 383f0a44d290..3423be45096a 100644 --- a/tools/perf/util/libunwind-arch/libunwind-i386.c +++ b/tools/perf/util/libunwind-arch/libunwind-i386.c @@ -2,9 +2,12 @@ #include "libunwind-arch.h" #include "../debug.h" #include "../maps.h" +#include "../thread.h" #include "../../../arch/x86/include/uapi/asm/perf_regs.h" #include #include +#include +#include #include #ifdef HAVE_LIBUNWIND_X86_SUPPORT @@ -56,3 +59,254 @@ void __libunwind_arch__finish_access_i386(struct maps *maps __maybe_unused) unw_destroy_addr_space(maps__addr_space(maps)); #endif } + +#ifdef HAVE_LIBUNWIND_X86_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_i386(void) +{ +#ifdef HAVE_LIBUNWIND_X86_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_X86_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_i386(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_X86_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_X86) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_i386(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_X86_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_X86) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_i386(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_I386; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_i386(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-loongarch.c b/tools/perf/util/libunwind-arch/libunwind-loongarch.c index 7ff459849930..ff225a540b43 100644 --- a/tools/perf/util/libunwind-arch/libunwind-loongarch.c +++ b/tools/perf/util/libunwind-arch/libunwind-loongarch.c @@ -2,8 +2,12 @@ #include "libunwind-arch.h" #include "../debug.h" #include "../maps.h" +#include "../thread.h" #include "../../../arch/loongarch/include/uapi/asm/perf_regs.h" #include +#include +#include +#include #include #ifdef HAVE_LIBUNWIND_LOONGARCH64_SUPPORT @@ -40,3 +44,254 @@ void __libunwind_arch__finish_access_loongarch(struct maps *maps __maybe_unused) unw_destroy_addr_space(maps__addr_space(maps)); #endif } + +#ifdef HAVE_LIBUNWIND_LOONGARCH64_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_loongarch(void) +{ +#ifdef HAVE_LIBUNWIND_LOONGARCH64_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_LOONGARCH_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_loongarch(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_LOONGARCH_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_LOONGARCH_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_LOONGARCH) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_loongarch(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_LOONGARCH_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_LOONGARCH) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_loongarch(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_LOONGARCH_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_LOONGARCH; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_loongarch(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_LOONGARCH_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-mips.c b/tools/perf/util/libunwind-arch/libunwind-mips.c index 1fa81742ff4a..ed14a8f94fa7 100644 --- a/tools/perf/util/libunwind-arch/libunwind-mips.c +++ b/tools/perf/util/libunwind-arch/libunwind-mips.c @@ -2,8 +2,12 @@ #include "libunwind-arch.h" #include "../debug.h" #include "../maps.h" +#include "../thread.h" #include "../../../arch/mips/include/uapi/asm/perf_regs.h" #include +#include +#include +#include #include #ifdef HAVE_LIBUNWIND_MIPS_SUPPORT @@ -42,3 +46,254 @@ void __libunwind_arch__finish_access_mips(struct maps *maps __maybe_unused) unw_destroy_addr_space(maps__addr_space(maps)); #endif } + +#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_mips(void) +{ +#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_mips(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_MIPS_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_MIPS) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_mips(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_MIPS_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_MIPS) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_mips(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_MIPS; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_mips(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-ppc32.c b/tools/perf/util/libunwind-arch/libunwind-ppc32.c index deb49a44c257..289a3b8cde75 100644 --- a/tools/perf/util/libunwind-arch/libunwind-ppc32.c +++ b/tools/perf/util/libunwind-arch/libunwind-ppc32.c @@ -2,8 +2,12 @@ #include "libunwind-arch.h" #include "../debug.h" #include "../maps.h" +#include "../thread.h" #include "../../../arch/powerpc/include/uapi/asm/perf_regs.h" #include +#include +#include +#include #include #ifdef HAVE_LIBUNWIND_PPC32_SUPPORT @@ -46,3 +50,254 @@ void __libunwind_arch__finish_access_ppc32(struct maps *maps __maybe_unused) unw_destroy_addr_space(maps__addr_space(maps)); #endif } + +#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_ppc32(void) +{ +#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_ppc32(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_PPC32_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_PPC32) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_ppc32(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_PPC32_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_PPC32) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_ppc32(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_PPC; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_ppc32(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-ppc64.c b/tools/perf/util/libunwind-arch/libunwind-ppc64.c index 9d7321214fac..a4c9b6cc3c00 100644 --- a/tools/perf/util/libunwind-arch/libunwind-ppc64.c +++ b/tools/perf/util/libunwind-arch/libunwind-ppc64.c @@ -2,8 +2,12 @@ #include "libunwind-arch.h" #include "../debug.h" #include "../maps.h" +#include "../thread.h" #include "../../../arch/powerpc/include/uapi/asm/perf_regs.h" #include +#include +#include +#include #include #ifdef HAVE_LIBUNWIND_PPC64_SUPPORT @@ -46,3 +50,254 @@ void __libunwind_arch__finish_access_ppc64(struct maps *maps __maybe_unused) unw_destroy_addr_space(maps__addr_space(maps)); #endif } + +#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_ppc64(void) +{ +#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_ppc64(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_PPC64_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_PPC64) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_ppc64(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_PPC64_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_PPC64) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_ppc64(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_PPC64; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_ppc64(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-s390.c b/tools/perf/util/libunwind-arch/libunwind-s390.c index ab296931dbbc..3e57cfc451c6 100644 --- a/tools/perf/util/libunwind-arch/libunwind-s390.c +++ b/tools/perf/util/libunwind-arch/libunwind-s390.c @@ -2,8 +2,12 @@ #include "libunwind-arch.h" #include "../debug.h" #include "../maps.h" +#include "../thread.h" #include "../../../arch/s390/include/uapi/asm/perf_regs.h" #include +#include +#include +#include #include #ifdef HAVE_LIBUNWIND_S390X_SUPPORT @@ -42,3 +46,254 @@ void __libunwind_arch__finish_access_s390(struct maps *maps __maybe_unused) unw_destroy_addr_space(maps__addr_space(maps)); #endif } + +#ifdef HAVE_LIBUNWIND_S390X_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_s390(void) +{ +#ifdef HAVE_LIBUNWIND_S390X_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_S390X_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_s390(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_S390X_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_S390X_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_S390X) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_s390(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_S390X_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_S390X) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_s390(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_S390X_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_S390; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_s390(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_S390X_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} diff --git a/tools/perf/util/libunwind-arch/libunwind-x86_64.c b/tools/perf/util/libunwind-arch/libunwind-x86_64.c index 2caca0b7b384..b13e9b1cc7a3 100644 --- a/tools/perf/util/libunwind-arch/libunwind-x86_64.c +++ b/tools/perf/util/libunwind-arch/libunwind-x86_64.c @@ -2,9 +2,12 @@ #include "libunwind-arch.h" #include "../debug.h" #include "../maps.h" +#include "../thread.h" #include "../../../arch/x86/include/uapi/asm/perf_regs.h" #include #include +#include +#include #include #ifdef HAVE_LIBUNWIND_X86_64_SUPPORT @@ -65,3 +68,253 @@ void __libunwind_arch__finish_access_x86_64(struct maps *maps __maybe_unused) unw_destroy_addr_space(maps__addr_space(maps)); #endif } + +#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_x86_64(void) +{ +#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_x86_64(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_X86_64_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_X86_64) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_x86_64(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_X86_64_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_X86_64) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_x86_64(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_X86_64; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_x86_64(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} diff --git a/tools/perf/util/libunwind/arm64.c b/tools/perf/util/libunwind/arm64.c deleted file mode 100644 index 15670a964495..000000000000 --- a/tools/perf/util/libunwind/arm64.c +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file setups defines to compile arch specific binary from the - * generic one. - * - * The function 'LIBUNWIND__ARCH_REG_ID' name is set according to arch - * name and the definition of this function is included directly from - * 'arch/arm64/util/unwind-libunwind.c', to make sure that this function - * is defined no matter what arch the host is. - * - * Finally, the arch specific unwind methods are exported which will - * be assigned to each arm64 thread. - */ - -#define REMOTE_UNWIND_LIBUNWIND - -#include "unwind.h" -#include "libunwind-aarch64.h" -#define perf_event_arm_regs perf_event_arm64_regs -#include <../../../arch/arm64/include/uapi/asm/perf_regs.h> -#undef perf_event_arm_regs -#include "../../arch/arm64/util/unwind-libunwind.c" - -/* NO_LIBUNWIND_DEBUG_FRAME is a feature flag for local libunwind, - * assign NO_LIBUNWIND_DEBUG_FRAME_AARCH64 to it for compiling arm64 - * unwind methods. - */ -#undef NO_LIBUNWIND_DEBUG_FRAME -#ifdef NO_LIBUNWIND_DEBUG_FRAME_AARCH64 -#define NO_LIBUNWIND_DEBUG_FRAME -#endif -#include "util/unwind-libunwind-local.c" - -struct unwind_libunwind_ops * -arm64_unwind_libunwind_ops = &_unwind_libunwind_ops; diff --git a/tools/perf/util/libunwind/x86_32.c b/tools/perf/util/libunwind/x86_32.c deleted file mode 100644 index 1e9fb8bfec44..000000000000 --- a/tools/perf/util/libunwind/x86_32.c +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file setups defines to compile arch specific binary from the - * generic one. - * - * The function 'LIBUNWIND__ARCH_REG_ID' name is set according to arch - * name and the definition of this function is included directly from - * 'arch/x86/util/unwind-libunwind.c', to make sure that this function - * is defined no matter what arch the host is. - * - * Finally, the arch specific unwind methods are exported which will - * be assigned to each x86 thread. - */ - -#define REMOTE_UNWIND_LIBUNWIND - -#include "unwind.h" -#include "libunwind-x86.h" - -/* Explicitly define NO_LIBUNWIND_DEBUG_FRAME, because non-ARM has no - * dwarf_find_debug_frame() function. - */ -#ifndef NO_LIBUNWIND_DEBUG_FRAME -#define NO_LIBUNWIND_DEBUG_FRAME -#endif -#include "util/unwind-libunwind-local.c" - -struct unwind_libunwind_ops * -x86_32_unwind_libunwind_ops = &_unwind_libunwind_ops; diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c index 27924c70e0e1..923935ee21b6 100644 --- a/tools/perf/util/maps.c +++ b/tools/perf/util/maps.c @@ -198,16 +198,6 @@ void maps__set_addr_space(struct maps *maps, void *addr_space) RC_CHK_ACCESS(maps)->addr_space = addr_space; } -const struct unwind_libunwind_ops *maps__unwind_libunwind_ops(const struct maps *maps) -{ - return RC_CHK_ACCESS(maps)->unwind_libunwind_ops; -} - -void maps__set_unwind_libunwind_ops(struct maps *maps, const struct unwind_libunwind_ops *ops) -{ - RC_CHK_ACCESS(maps)->unwind_libunwind_ops = ops; -} - uint16_t maps__e_machine(const struct maps *maps) { return RC_CHK_ACCESS(maps)->e_machine; diff --git a/tools/perf/util/maps.h b/tools/perf/util/maps.h index 6469f62c41a8..5b80b199685e 100644 --- a/tools/perf/util/maps.h +++ b/tools/perf/util/maps.h @@ -49,8 +49,6 @@ refcount_t *maps__refcnt(struct maps *maps); /* Test only. */ #ifdef HAVE_LIBUNWIND_SUPPORT void *maps__addr_space(const struct maps *maps); void maps__set_addr_space(struct maps *maps, void *addr_space); -const struct unwind_libunwind_ops *maps__unwind_libunwind_ops(const struct maps *maps); -void maps__set_unwind_libunwind_ops(struct maps *maps, const struct unwind_libunwind_ops *ops); uint16_t maps__e_machine(const struct maps *maps); void maps__set_e_machine(struct maps *maps, uint16_t e_machine); #endif diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c deleted file mode 100644 index a9af2839e828..000000000000 --- a/tools/perf/util/unwind-libunwind-local.c +++ /dev/null @@ -1,834 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps. - * - * Lots of this code have been borrowed or heavily inspired from parts of - * the libunwind 0.99 code which are (amongst other contributors I may have - * forgotten): - * - * Copyright (C) 2002-2007 Hewlett-Packard Co - * Contributed by David Mosberger-Tang - * - * And the bugs have been added by: - * - * Copyright (C) 2010, Frederic Weisbecker - * Copyright (C) 2012, Jiri Olsa - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef REMOTE_UNWIND_LIBUNWIND -#include -#include -#endif -#include "callchain.h" -#include "thread.h" -#include "session.h" -#include "perf_regs.h" -#include "unwind.h" -#include "map.h" -#include "symbol.h" -#include "debug.h" -#include "asm/bug.h" -#include "dso.h" -#include "libunwind-arch/libunwind-arch.h" - -extern int -UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); - -#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) - -extern int -UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, - unw_word_t ip, - unw_word_t segbase, - const char *obj_name, unw_word_t start, - unw_word_t end); - -#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) - -#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ -#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ - -/* Pointer-encoding formats: */ -#define DW_EH_PE_omit 0xff -#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */ -#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */ -#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */ -#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */ -#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */ - -/* Pointer-encoding application: */ -#define DW_EH_PE_absptr 0x00 /* absolute value */ -#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */ - -/* - * The following are not documented by LSB v1.3, yet they are used by - * GCC, presumably they aren't documented by LSB since they aren't - * used on Linux: - */ -#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */ -#define DW_EH_PE_aligned 0x50 /* aligned pointer */ - -/* Flags intentionally not handled, since they're not needed: - * #define DW_EH_PE_indirect 0x80 - * #define DW_EH_PE_uleb128 0x01 - * #define DW_EH_PE_udata2 0x02 - * #define DW_EH_PE_sleb128 0x09 - * #define DW_EH_PE_sdata2 0x0a - * #define DW_EH_PE_textrel 0x20 - * #define DW_EH_PE_datarel 0x30 - */ - -struct unwind_info { - struct perf_sample *sample; - struct machine *machine; - struct thread *thread; - uint16_t e_machine; - bool best_effort; -}; - -#define dw_read(ptr, type, end) ({ \ - type *__p = (type *) ptr; \ - type __v; \ - if ((__p + 1) > (type *) end) \ - return -EINVAL; \ - __v = *__p++; \ - ptr = (typeof(ptr)) __p; \ - __v; \ - }) - -static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, - u8 encoding) -{ - u8 *cur = *p; - *val = 0; - - switch (encoding) { - case DW_EH_PE_omit: - *val = 0; - goto out; - case DW_EH_PE_ptr: - *val = dw_read(cur, unsigned long, end); - goto out; - default: - break; - } - - switch (encoding & DW_EH_PE_APPL_MASK) { - case DW_EH_PE_absptr: - break; - case DW_EH_PE_pcrel: - *val = (unsigned long) cur; - break; - default: - return -EINVAL; - } - - if ((encoding & 0x07) == 0x00) - encoding |= DW_EH_PE_udata4; - - switch (encoding & DW_EH_PE_FORMAT_MASK) { - case DW_EH_PE_sdata4: - *val += dw_read(cur, s32, end); - break; - case DW_EH_PE_udata4: - *val += dw_read(cur, u32, end); - break; - case DW_EH_PE_sdata8: - *val += dw_read(cur, s64, end); - break; - case DW_EH_PE_udata8: - *val += dw_read(cur, u64, end); - break; - default: - return -EINVAL; - } - - out: - *p = cur; - return 0; -} - -#define dw_read_encoded_value(ptr, end, enc) ({ \ - u64 __v; \ - if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \ - return -EINVAL; \ - } \ - __v; \ - }) - -static int elf_section_address_and_offset(int fd, const char *name, u64 *address, u64 *offset) -{ - Elf *elf; - GElf_Ehdr ehdr; - GElf_Shdr shdr; - int ret = -1; - - elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); - if (elf == NULL) - return -1; - - if (gelf_getehdr(elf, &ehdr) == NULL) - goto out_err; - - if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL)) - goto out_err; - - *address = shdr.sh_addr; - *offset = shdr.sh_offset; - ret = 0; -out_err: - elf_end(elf); - return ret; -} - -#ifndef NO_LIBUNWIND_DEBUG_FRAME -static u64 elf_section_offset(int fd, const char *name) -{ - u64 address, offset = 0; - - if (elf_section_address_and_offset(fd, name, &address, &offset)) - return 0; - - return offset; -} -#endif - -static u64 elf_base_address(int fd) -{ - Elf *elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); - GElf_Phdr phdr; - u64 retval = 0; - size_t i, phdrnum = 0; - - if (elf == NULL) - return 0; - (void)elf_getphdrnum(elf, &phdrnum); - /* PT_LOAD segments are sorted by p_vaddr, so the first has the minimum p_vaddr. */ - for (i = 0; i < phdrnum; i++) { - if (gelf_getphdr(elf, i, &phdr) && phdr.p_type == PT_LOAD) { - retval = phdr.p_vaddr & -getpagesize(); - break; - } - } - - elf_end(elf); - return retval; -} - -#ifndef NO_LIBUNWIND_DEBUG_FRAME -static int elf_is_exec(int fd, const char *name) -{ - Elf *elf; - GElf_Ehdr ehdr; - int retval = 0; - - elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); - if (elf == NULL) - return 0; - if (gelf_getehdr(elf, &ehdr) == NULL) - goto out; - - retval = (ehdr.e_type == ET_EXEC); - -out: - elf_end(elf); - pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval); - return retval; -} -#endif - -struct table_entry { - u32 start_ip_offset; - u32 fde_offset; -}; - -struct eh_frame_hdr { - unsigned char version; - unsigned char eh_frame_ptr_enc; - unsigned char fde_count_enc; - unsigned char table_enc; - - /* - * The rest of the header is variable-length and consists of the - * following members: - * - * encoded_t eh_frame_ptr; - * encoded_t fde_count; - */ - - /* A single encoded pointer should not be more than 8 bytes. */ - u64 enc[2]; - - /* - * struct { - * encoded_t start_ip; - * encoded_t fde_addr; - * } binary_search_table[fde_count]; - */ - char data[]; -} __packed; - -static int unwind_spec_ehframe(struct dso *dso, struct machine *machine, - u64 offset, u64 *table_data_offset, u64 *fde_count) -{ - struct eh_frame_hdr hdr; - u8 *enc = (u8 *) &hdr.enc; - u8 *end = (u8 *) &hdr.data; - ssize_t r; - - r = dso__data_read_offset(dso, machine, offset, - (u8 *) &hdr, sizeof(hdr)); - if (r != sizeof(hdr)) - return -EINVAL; - - /* We dont need eh_frame_ptr, just skip it. */ - dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc); - - *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc); - *table_data_offset = enc - (u8 *) &hdr; - return 0; -} - -struct read_unwind_spec_eh_frame_maps_cb_args { - struct dso *dso; - u64 base_addr; -}; - -static int read_unwind_spec_eh_frame_maps_cb(struct map *map, void *data) -{ - - struct read_unwind_spec_eh_frame_maps_cb_args *args = data; - - if (map__dso(map) == args->dso && map__start(map) - map__pgoff(map) < args->base_addr) - args->base_addr = map__start(map) - map__pgoff(map); - - return 0; -} - - -static int read_unwind_spec_eh_frame(struct dso *dso, struct unwind_info *ui, - u64 *table_data, u64 *segbase, - u64 *fde_count) -{ - struct read_unwind_spec_eh_frame_maps_cb_args args = { - .dso = dso, - .base_addr = UINT64_MAX, - }; - int ret, fd; - - if (dso__data(dso)->eh_frame_hdr_offset == 0) { - if (!dso__data_get_fd(dso, ui->machine, &fd)) - return -EINVAL; - - /* Check the .eh_frame section for unwinding info */ - ret = elf_section_address_and_offset(fd, ".eh_frame_hdr", - &dso__data(dso)->eh_frame_hdr_addr, - &dso__data(dso)->eh_frame_hdr_offset); - dso__data(dso)->elf_base_addr = elf_base_address(fd); - dso__data_put_fd(dso); - if (ret || dso__data(dso)->eh_frame_hdr_offset == 0) - return -EINVAL; - } - - maps__for_each_map(thread__maps(ui->thread), read_unwind_spec_eh_frame_maps_cb, &args); - - args.base_addr -= dso__data(dso)->elf_base_addr; - /* Address of .eh_frame_hdr */ - *segbase = args.base_addr + dso__data(dso)->eh_frame_hdr_addr; - ret = unwind_spec_ehframe(dso, ui->machine, dso__data(dso)->eh_frame_hdr_offset, - table_data, fde_count); - if (ret) - return ret; - /* binary_search_table offset plus .eh_frame_hdr address */ - *table_data += *segbase; - return 0; -} - -#ifndef NO_LIBUNWIND_DEBUG_FRAME -static int read_unwind_spec_debug_frame(struct dso *dso, - struct machine *machine, u64 *offset) -{ - int fd; - u64 ofs = dso__data(dso)->debug_frame_offset; - - /* debug_frame can reside in: - * - dso - * - debug pointed by symsrc_filename - * - gnu_debuglink, which doesn't necessary - * has to be pointed by symsrc_filename - */ - if (ofs == 0) { - if (dso__data_get_fd(dso, machine, &fd)) { - ofs = elf_section_offset(fd, ".debug_frame"); - dso__data_put_fd(dso); - } - - if (ofs <= 0) { - fd = open(dso__symsrc_filename(dso), O_RDONLY); - if (fd >= 0) { - ofs = elf_section_offset(fd, ".debug_frame"); - close(fd); - } - } - - if (ofs <= 0) { - char *debuglink = malloc(PATH_MAX); - int ret = 0; - - if (debuglink == NULL) { - pr_err("unwind: Can't read unwind spec debug frame.\n"); - return -ENOMEM; - } - - ret = dso__read_binary_type_filename( - dso, DSO_BINARY_TYPE__DEBUGLINK, - machine->root_dir, debuglink, PATH_MAX); - if (!ret) { - fd = open(debuglink, O_RDONLY); - if (fd >= 0) { - ofs = elf_section_offset(fd, - ".debug_frame"); - close(fd); - } - } - if (ofs > 0) { - if (dso__symsrc_filename(dso) != NULL) { - pr_warning( - "%s: overwrite symsrc(%s,%s)\n", - __func__, - dso__symsrc_filename(dso), - debuglink); - dso__free_symsrc_filename(dso); - } - dso__set_symsrc_filename(dso, debuglink); - } else { - free(debuglink); - } - } - - dso__data(dso)->debug_frame_offset = ofs; - } - - *offset = ofs; - if (*offset) - return 0; - - return -EINVAL; -} -#endif - -static struct map *find_map(unw_word_t ip, struct unwind_info *ui) -{ - struct addr_location al; - struct map *ret; - - addr_location__init(&al); - thread__find_map(ui->thread, PERF_RECORD_MISC_USER, ip, &al); - ret = map__get(al.map); - addr_location__exit(&al); - return ret; -} - -static int -find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - struct unwind_info *ui = arg; - struct map *map; - struct dso *dso; - unw_dyn_info_t di; - u64 table_data, segbase, fde_count; - int ret = -EINVAL; - - map = find_map(ip, ui); - if (!map) - return -EINVAL; - - dso = map__dso(map); - if (!dso) { - map__put(map); - return -EINVAL; - } - - pr_debug("unwind: find_proc_info dso %s\n", dso__name(dso)); - - /* Check the .eh_frame section for unwinding info */ - if (!read_unwind_spec_eh_frame(dso, ui, &table_data, &segbase, &fde_count)) { - memset(&di, 0, sizeof(di)); - di.format = UNW_INFO_FORMAT_REMOTE_TABLE; - di.start_ip = map__start(map); - di.end_ip = map__end(map); - di.u.rti.segbase = segbase; - di.u.rti.table_data = table_data; - di.u.rti.table_len = fde_count * sizeof(struct table_entry) - / sizeof(unw_word_t); - ret = dwarf_search_unwind_table(as, ip, &di, pi, - need_unwind_info, arg); - } - -#ifndef NO_LIBUNWIND_DEBUG_FRAME - /* Check the .debug_frame section for unwinding info */ - if (ret < 0 && - !read_unwind_spec_debug_frame(dso, ui->machine, &segbase)) { - int fd; - u64 start = map__start(map); - unw_word_t base = start; - const char *symfile; - - if (dso__data_get_fd(dso, ui->machine, &fd)) { - if (elf_is_exec(fd, dso__name(dso))) - base = 0; - dso__data_put_fd(dso); - } - - symfile = dso__symsrc_filename(dso) ?: dso__name(dso); - - memset(&di, 0, sizeof(di)); - if (dwarf_find_debug_frame(0, &di, ip, base, symfile, start, map__end(map))) - ret = dwarf_search_unwind_table(as, ip, &di, pi, - need_unwind_info, arg); - } -#endif - map__put(map); - return ret; -} - -static int access_fpreg(unw_addr_space_t __maybe_unused as, - unw_regnum_t __maybe_unused num, - unw_fpreg_t __maybe_unused *val, - int __maybe_unused __write, - void __maybe_unused *arg) -{ - pr_err("unwind: access_fpreg unsupported\n"); - return -UNW_EINVAL; -} - -static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, - unw_word_t __maybe_unused *dil_addr, - void __maybe_unused *arg) -{ - return -UNW_ENOINFO; -} - -static int resume(unw_addr_space_t __maybe_unused as, - unw_cursor_t __maybe_unused *cu, - void __maybe_unused *arg) -{ - pr_err("unwind: resume unsupported\n"); - return -UNW_EINVAL; -} - -static int -get_proc_name(unw_addr_space_t __maybe_unused as, - unw_word_t __maybe_unused addr, - char __maybe_unused *bufp, size_t __maybe_unused buf_len, - unw_word_t __maybe_unused *offp, void __maybe_unused *arg) -{ - pr_err("unwind: get_proc_name unsupported\n"); - return -UNW_EINVAL; -} - -static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, - unw_word_t *data) -{ - struct map *map; - struct dso *dso; - ssize_t size; - - map = find_map(addr, ui); - if (!map) { - pr_debug("unwind: no map for %lx\n", (unsigned long)addr); - return -1; - } - - dso = map__dso(map); - - if (!dso) { - map__put(map); - return -1; - } - - size = dso__data_read_addr(dso, map, ui->machine, - addr, (u8 *) data, sizeof(*data)); - map__put(map); - return !(size == sizeof(*data)); -} - -static int access_mem(unw_addr_space_t __maybe_unused as, - unw_word_t addr, unw_word_t *valp, - int __write, void *arg) -{ - struct unwind_info *ui = arg; - struct stack_dump *stack = &ui->sample->user_stack; - u64 start, end; - int offset; - int ret; - - /* Don't support write, probably not needed. */ - if (__write || !stack || !ui->sample->user_regs || !ui->sample->user_regs->regs) { - *valp = 0; - return 0; - } - - ret = perf_reg_value(&start, perf_sample__user_regs(ui->sample), - perf_arch_reg_sp(ui->e_machine)); - if (ret) - return ret; - - end = start + stack->size; - - /* Check overflow. */ - if (addr + sizeof(unw_word_t) < addr) - return -EINVAL; - - if (addr < start || addr + sizeof(unw_word_t) >= end) { - ret = access_dso_mem(ui, addr, valp); - if (ret) { - pr_debug("unwind: access_mem %p not inside range" - " 0x%" PRIx64 "-0x%" PRIx64 "\n", - (void *) (uintptr_t) addr, start, end); - *valp = 0; - return ret; - } - return 0; - } - - offset = addr - start; - *valp = *(unw_word_t *)&stack->data[offset]; - pr_debug("unwind: access_mem addr %p val %lx, offset %d\n", - (void *) (uintptr_t) addr, (unsigned long)*valp, offset); - return 0; -} - -static int access_reg(unw_addr_space_t __maybe_unused as, - unw_regnum_t regnum, unw_word_t *valp, - int __write, void *arg) -{ - struct unwind_info *ui = arg; - int id, ret; - u64 val; - - /* Don't support write, I suspect we don't need it. */ - if (__write) { - pr_err("unwind: access_reg w %d\n", regnum); - return 0; - } - - if (!ui->sample->user_regs || !ui->sample->user_regs->regs) { - *valp = 0; - return 0; - } - - id = get_perf_regnum_for_unw_regnum(ui->e_machine, regnum); - if (id < 0) - return -EINVAL; - - ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), id); - if (ret) { - if (!ui->best_effort) - pr_err("unwind: can't read reg %d\n", regnum); - return ret; - } - - *valp = (unw_word_t) val; - pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp); - return 0; -} - -static void put_unwind_info(unw_addr_space_t __maybe_unused as, - unw_proc_info_t *pi __maybe_unused, - void *arg __maybe_unused) -{ - pr_debug("unwind: put_unwind_info called\n"); -} - -static int entry(u64 ip, struct thread *thread, - unwind_entry_cb_t cb, void *arg) -{ - struct unwind_entry e; - struct addr_location al; - int ret; - - addr_location__init(&al); - e.ms.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); - e.ip = ip; - e.ms.map = al.map; - e.ms.thread = thread__get(al.thread); - - pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", - al.sym ? al.sym->name : "''", - ip, - al.map ? map__map_ip(al.map, ip) : (u64) 0); - - ret = cb(&e, arg); - addr_location__exit(&al); - return ret; -} - -static void display_error(int err) -{ - switch (err) { - case UNW_EINVAL: - pr_err("unwind: Only supports local.\n"); - break; - case UNW_EUNSPEC: - pr_err("unwind: Unspecified error.\n"); - break; - case UNW_EBADREG: - pr_err("unwind: Register unavailable.\n"); - break; - default: - break; - } -} - -static unw_accessors_t accessors = { - .find_proc_info = find_proc_info, - .put_unwind_info = put_unwind_info, - .get_dyn_info_list_addr = get_dyn_info_list_addr, - .access_mem = access_mem, - .access_reg = access_reg, - .access_fpreg = access_fpreg, - .resume = resume, - .get_proc_name = get_proc_name, -}; - -static int _unwind__prepare_access(struct maps *maps) -{ - void *addr_space = unw_create_addr_space(&accessors, 0); - - maps__set_addr_space(maps, addr_space); - if (!addr_space) { - pr_err("unwind: Can't create unwind address space.\n"); - return -ENOMEM; - } - - unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); - return 0; -} - -static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, - void *arg, int max_stack) -{ - u64 val; - unw_word_t ips[max_stack]; - unw_addr_space_t addr_space; - unw_cursor_t c; - int ret, i = 0; - - ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), - perf_arch_reg_ip(ui->e_machine)); - if (ret) - return 0; - - ips[i++] = (unw_word_t) val; - - /* - * If we need more than one entry, do the DWARF - * unwind itself. - */ - if (max_stack - 1 > 0) { - WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL"); - addr_space = maps__addr_space(thread__maps(ui->thread)); - - if (addr_space == NULL) - return 0; - - ret = unw_init_remote(&c, addr_space, ui); - if (ret && !ui->best_effort) - display_error(ret); - - while (!ret && (unw_step(&c) > 0) && i < max_stack) { - unw_get_reg(&c, UNW_REG_IP, &ips[i]); - - /* - * Decrement the IP for any non-activation frames. - * this is required to properly find the srcline - * for caller frames. - * See also the documentation for dwfl_frame_pc(), - * which this code tries to replicate. - */ - if (unw_is_signal_frame(&c) <= 0) - --ips[i]; - - ++i; - } - - max_stack = i; - } - - /* - * Display what we got based on the order setup. - */ - int entries = 0; - for (i = 0; i < max_stack && !ret; i++) { - int j = i; - - if (callchain_param.order == ORDER_CALLER) - j = max_stack - i - 1; - if (ips[j]) { - ret = entry(ips[j], ui->thread, cb, arg); - if (ret) - break; - entries++; - } - } - - /* - * Unwinder return contract: - * > 0 : unwinding succeeded (stops fallback). - * 0 : unwinding failed without yielding frames. Ignore non-fatal errors - * (e.g. stepping failure) to allow fallback unwinder or kernel callchains. - * < 0 : fatal error (e.g. -ENOMEM). Aborts unwinding entirely. - */ - if (ret == -ENOMEM) - return -ENOMEM; - return (entries > 0 || ret == 0) ? entries : 0; -} - -static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg, - struct thread *thread, - struct perf_sample *data, int max_stack, - bool best_effort) -{ - struct unwind_info ui = { - .sample = data, - .thread = thread, - .machine = maps__machine(thread__maps(thread)), - .e_machine = thread__e_machine(thread, /*machine=*/NULL, /*e_flags=*/NULL), - .best_effort = best_effort - }; - - if (!data->user_regs || !data->user_regs->regs) - return 0; - - if (max_stack <= 0) - return 0; - - return get_entries(&ui, cb, arg, max_stack); -} - -static struct unwind_libunwind_ops -_unwind_libunwind_ops = { - .prepare_access = _unwind__prepare_access, - .get_entries = _unwind__get_entries, -}; - -#ifndef REMOTE_UNWIND_LIBUNWIND -struct unwind_libunwind_ops * -local_unwind_libunwind_ops = &_unwind_libunwind_ops; -#endif diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 00be1286b799..73d191ce51a5 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c @@ -1,23 +1,560 @@ // SPDX-License-Identifier: GPL-2.0 -#include "unwind.h" -#include "dso.h" -#include "map.h" -#include "thread.h" -#include "session.h" -#include "debug.h" -#include "env.h" #include "callchain.h" +#include "debug.h" +#include "dso.h" +#include "env.h" +#include "map.h" +#include "perf_regs.h" +#include "session.h" +#include "symbol.h" +#include "thread.h" +#include "unwind.h" #include "libunwind-arch/libunwind-arch.h" #include #include +#include +#include +#include -struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops; -struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops; -struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops; +#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ +#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ + +/* Pointer-encoding formats: */ +#define DW_EH_PE_omit 0xff +#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */ +#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */ +#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */ +#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */ +#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */ + +/* Pointer-encoding application: */ +#define DW_EH_PE_absptr 0x00 /* absolute value */ +#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */ + +/* + * The following are not documented by LSB v1.3, yet they are used by + * GCC, presumably they aren't documented by LSB since they aren't + * used on Linux: + */ +#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */ +#define DW_EH_PE_aligned 0x50 /* aligned pointer */ + +/* Flags intentionally not handled, since they're not needed: + * #define DW_EH_PE_indirect 0x80 + * #define DW_EH_PE_uleb128 0x01 + * #define DW_EH_PE_udata2 0x02 + * #define DW_EH_PE_sleb128 0x09 + * #define DW_EH_PE_sdata2 0x0a + * #define DW_EH_PE_textrel 0x20 + * #define DW_EH_PE_datarel 0x30 + */ + +#define dw_read(ptr, type, end) ({ \ + type *__p = (type *) ptr; \ + type __v; \ + if ((__p + 1) > (type *) end) \ + return -EINVAL; \ + __v = *__p++; \ + ptr = (typeof(ptr)) __p; \ + __v; \ + }) + +static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, + u8 encoding) +{ + u8 *cur = *p; + *val = 0; + + switch (encoding) { + case DW_EH_PE_omit: + *val = 0; + goto out; + case DW_EH_PE_ptr: + *val = dw_read(cur, unsigned long, end); + goto out; + default: + break; + } + + switch (encoding & DW_EH_PE_APPL_MASK) { + case DW_EH_PE_absptr: + break; + case DW_EH_PE_pcrel: + *val = (unsigned long) cur; + break; + default: + return -EINVAL; + } + + if ((encoding & 0x07) == 0x00) + encoding |= DW_EH_PE_udata4; + + switch (encoding & DW_EH_PE_FORMAT_MASK) { + case DW_EH_PE_sdata4: + *val += dw_read(cur, s32, end); + break; + case DW_EH_PE_udata4: + *val += dw_read(cur, u32, end); + break; + case DW_EH_PE_sdata8: + *val += dw_read(cur, s64, end); + break; + case DW_EH_PE_udata8: + *val += dw_read(cur, u64, end); + break; + default: + return -EINVAL; + } + + out: + *p = cur; + return 0; +} + +#define dw_read_encoded_value(ptr, end, enc) ({ \ + u64 __v; \ + if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \ + return -EINVAL; \ + } \ + __v; \ + }) + +static u64 elf_base_address(int fd) +{ + Elf *elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + GElf_Phdr phdr; + u64 retval = 0; + size_t i, phdrnum = 0; + + if (elf == NULL) + return 0; + (void)elf_getphdrnum(elf, &phdrnum); + /* PT_LOAD segments are sorted by p_vaddr, so the first has the minimum p_vaddr. */ + for (i = 0; i < phdrnum; i++) { + if (gelf_getphdr(elf, i, &phdr) && phdr.p_type == PT_LOAD) { + retval = phdr.p_vaddr & -getpagesize(); + break; + } + } + + elf_end(elf); + return retval; +} + +static int unwind_spec_ehframe(struct dso *dso, struct machine *machine, + u64 offset, u64 *table_data_offset, u64 *fde_count) +{ + struct eh_frame_hdr { + unsigned char version; + unsigned char eh_frame_ptr_enc; + unsigned char fde_count_enc; + unsigned char table_enc; + + /* + * The rest of the header is variable-length and consists of the + * following members: + * + * encoded_t eh_frame_ptr; + * encoded_t fde_count; + */ + + /* A single encoded pointer should not be more than 8 bytes. */ + u64 enc[2]; + + /* + * struct { + * encoded_t start_ip; + * encoded_t fde_addr; + * } binary_search_table[fde_count]; + */ + char data[]; + } __packed hdr; + u8 *enc = (u8 *) &hdr.enc; + u8 *end = (u8 *) &hdr.data; + ssize_t r; + + r = dso__data_read_offset(dso, machine, offset, (u8 *) &hdr, sizeof(hdr)); + if (r != sizeof(hdr)) + return -EINVAL; + + /* We dont need eh_frame_ptr, just skip it. */ + dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc); + + *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc); + *table_data_offset = enc - (u8 *) &hdr; + return 0; +} + +struct read_unwind_spec_eh_frame_maps_cb_args { + struct dso *dso; + u64 base_addr; +}; + +static int read_unwind_spec_eh_frame_maps_cb(struct map *map, void *data) +{ + + struct read_unwind_spec_eh_frame_maps_cb_args *args = data; + + if (map__dso(map) == args->dso && map__start(map) - map__pgoff(map) < args->base_addr) + args->base_addr = map__start(map) - map__pgoff(map); + + return 0; +} + +static int elf_section_address_and_offset(int fd, const char *name, u64 *address, u64 *offset) +{ + Elf *elf; + GElf_Ehdr ehdr; + GElf_Shdr shdr; + int ret = -1; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) + return -1; + + if (gelf_getehdr(elf, &ehdr) == NULL) + goto out_err; + + if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL)) + goto out_err; + + *address = shdr.sh_addr; + *offset = shdr.sh_offset; + ret = 0; +out_err: + elf_end(elf); + return ret; +} + +static int read_unwind_spec_eh_frame(struct dso *dso, struct unwind_info *ui, + u64 *table_data, u64 *segbase, + u64 *fde_count) +{ + struct read_unwind_spec_eh_frame_maps_cb_args args = { + .dso = dso, + .base_addr = UINT64_MAX, + }; + int ret, fd; + + if (dso__data(dso)->eh_frame_hdr_offset == 0) { + if (!dso__data_get_fd(dso, ui->machine, &fd)) + return -EINVAL; + + /* Check the .eh_frame section for unwinding info */ + ret = elf_section_address_and_offset(fd, ".eh_frame_hdr", + &dso__data(dso)->eh_frame_hdr_addr, + &dso__data(dso)->eh_frame_hdr_offset); + dso__data(dso)->elf_base_addr = elf_base_address(fd); + dso__data_put_fd(dso); + if (ret || dso__data(dso)->eh_frame_hdr_offset == 0) + return -EINVAL; + } + + maps__for_each_map(thread__maps(ui->thread), read_unwind_spec_eh_frame_maps_cb, &args); + + args.base_addr -= dso__data(dso)->elf_base_addr; + /* Address of .eh_frame_hdr */ + *segbase = args.base_addr + dso__data(dso)->eh_frame_hdr_addr; + ret = unwind_spec_ehframe(dso, ui->machine, dso__data(dso)->eh_frame_hdr_offset, + table_data, fde_count); + if (ret) + return ret; + /* binary_search_table offset plus .eh_frame_hdr address */ + *table_data += *segbase; + return 0; +} + +static u64 elf_section_offset(int fd, const char *name) +{ + u64 address, offset = 0; + + if (elf_section_address_and_offset(fd, name, &address, &offset)) + return 0; + + return offset; +} + +static int read_unwind_spec_debug_frame(struct dso *dso, + struct machine *machine, u64 *offset) +{ + int fd; + u64 ofs = dso__data(dso)->debug_frame_offset; + + /* debug_frame can reside in: + * - dso + * - debug pointed by symsrc_filename + * - gnu_debuglink, which doesn't necessary + * has to be pointed by symsrc_filename + */ + if (ofs == 0) { + if (dso__data_get_fd(dso, machine, &fd)) { + ofs = elf_section_offset(fd, ".debug_frame"); + dso__data_put_fd(dso); + } + + if (ofs <= 0) { + fd = open(dso__symsrc_filename(dso), O_RDONLY); + if (fd >= 0) { + ofs = elf_section_offset(fd, ".debug_frame"); + close(fd); + } + } + + if (ofs <= 0) { + char *debuglink = malloc(PATH_MAX); + int ret = 0; + + if (debuglink == NULL) { + pr_err("unwind: Can't read unwind spec debug frame.\n"); + return -ENOMEM; + } + + ret = dso__read_binary_type_filename( + dso, DSO_BINARY_TYPE__DEBUGLINK, + machine->root_dir, debuglink, PATH_MAX); + if (!ret) { + fd = open(debuglink, O_RDONLY); + if (fd >= 0) { + ofs = elf_section_offset(fd, + ".debug_frame"); + close(fd); + } + } + if (ofs > 0) { + if (dso__symsrc_filename(dso) != NULL) { + pr_warning( + "%s: overwrite symsrc(%s,%s)\n", + __func__, + dso__symsrc_filename(dso), + debuglink); + dso__free_symsrc_filename(dso); + } + dso__set_symsrc_filename(dso, debuglink); + } else { + free(debuglink); + } + } + + dso__data(dso)->debug_frame_offset = ofs; + } + + *offset = ofs; + if (*offset) + return 0; + + return -EINVAL; +} + +static struct map *find_map(uint64_t ip, struct unwind_info *ui) +{ + struct addr_location al; + struct map *ret; + + addr_location__init(&al); + thread__find_map(ui->thread, PERF_RECORD_MISC_USER, ip, &al); + ret = map__get(al.map); + addr_location__exit(&al); + return ret; +} + +static int elf_is_exec(int fd, const char *name) +{ + Elf *elf; + GElf_Ehdr ehdr; + int retval = 0; + + elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); + if (elf == NULL) + return 0; + if (gelf_getehdr(elf, &ehdr) == NULL) + goto out; + + retval = (ehdr.e_type == ET_EXEC); + +out: + elf_end(elf); + pr_debug3("unwind: elf_is_exec(%s): %d\n", name, retval); + return retval; +} + +int __libunwind__find_proc_info(void *as, uint64_t ip, void *pi, int need_unwind_info, void *arg) +{ + struct unwind_info *ui = arg; + struct map *map; + struct dso *dso; + u64 table_data, segbase, fde_count; + int ret = -EINVAL; + + map = find_map(ip, ui); + if (!map) + return -EINVAL; + + dso = map__dso(map); + if (!dso) { + map__put(map); + return -EINVAL; + } + + pr_debug3("unwind: find_proc_info dso %s\n", dso__name(dso)); + + /* Check the .eh_frame section for unwinding info */ + if (!read_unwind_spec_eh_frame(dso, ui, &table_data, &segbase, &fde_count)) { + struct table_entry { + u32 start_ip_offset; + u32 fde_offset; + }; + struct libarch_unwind__dyn_info di = { + .start_ip = map__start(map), + .end_ip = map__end(map), + .segbase = segbase, + .table_data = table_data, + .table_len = fde_count * sizeof(struct table_entry) / ui->unw_word_t_size, + }; + + ret = libunwind_arch__dwarf_search_unwind_table(ui->e_machine, as, ip, &di, pi, + need_unwind_info, arg); + } + + /* Check the .debug_frame section for unwinding info */ + if (ret < 0 && !read_unwind_spec_debug_frame(dso, ui->machine, &segbase)) { + int fd; + u64 start = map__start(map); + u64 base = start; + const char *symfile; + struct libarch_unwind__dyn_info di = {}; + + if (dso__data_get_fd(dso, ui->machine, &fd)) { + if (elf_is_exec(fd, dso__name(dso))) + base = 0; + dso__data_put_fd(dso); + } + + symfile = dso__symsrc_filename(dso) ?: dso__name(dso); + + if (libunwind_arch__dwarf_find_debug_frame(ui->e_machine, /*found=*/0, &di, ip, + base, symfile, start, map__end(map))) { + ret = libunwind_arch__dwarf_search_unwind_table(ui->e_machine, as, ip, &di, pi, + need_unwind_info, arg); + } + } + map__put(map); + return ret; +} + +static int access_dso_mem(struct unwind_info *ui, uint64_t addr, void *data_word) +{ + struct map *map; + struct dso *dso; + ssize_t size; + + map = find_map(addr, ui); + if (!map) { + pr_debug("unwind: no map for %lx\n", (unsigned long)addr); + return -1; + } + + dso = map__dso(map); + + if (!dso) { + map__put(map); + return -1; + } + + size = dso__data_read_addr(dso, map, ui->machine, + addr, + (u8 *) data_word, + ui->unw_word_t_size); + map__put(map); + return !((size_t)size == ui->unw_word_t_size); +} + +int __libunwind__access_mem(void *as __maybe_unused, uint64_t addr, void *valp_word, + int __write, void *arg) +{ + struct unwind_info *ui = arg; + struct stack_dump *stack = &ui->sample->user_stack; + u64 start, end; + int offset; + int ret; + + /* Don't support write, probably not needed. */ + if (__write || !stack || !ui->sample->user_regs || !ui->sample->user_regs->regs) { + uint64_t zero = 0; + + memcpy(valp_word, &zero, ui->unw_word_t_size); + return 0; + } + + ret = perf_reg_value(&start, perf_sample__user_regs(ui->sample), + perf_arch_reg_sp(ui->e_machine)); + if (ret) + return ret; + + end = start + stack->size; + + /* Check overflow. */ + if (addr + ui->unw_word_t_size < addr) + return -EINVAL; + + if (addr < start || addr + ui->unw_word_t_size >= end) { + ret = access_dso_mem(ui, addr, valp_word); + if (ret) { + pr_debug3("unwind: access_mem %p not inside range" + " 0x%" PRIx64 "-0x%" PRIx64 "\n", + (void *) (uintptr_t) addr, start, end); + memset(valp_word, 0, ui->unw_word_t_size); + return ret; + } + return 0; + } + + offset = addr - start; + memcpy(valp_word, &stack->data[offset], ui->unw_word_t_size); + pr_debug3("unwind: access_mem addr %p val %lx, offset %d\n", + (void *) (uintptr_t) addr, *((unsigned long *)valp_word), offset); + return 0; +} + +int __libunwind__access_reg(void *as __maybe_unused, int regnum, void *valp_word, int __write, + void *arg) +{ + struct unwind_info *ui = arg; + int id, ret; + u64 val; + + /* Don't support write, I suspect we don't need it. */ + if (__write) { + pr_err("unwind: access_reg w %d\n", regnum); + return 0; + } + + if (!ui->sample->user_regs || !ui->sample->user_regs->regs) { + memset(valp_word, 0, ui->unw_word_t_size); + return 0; + } + + id = get_perf_regnum_for_unw_regnum(ui->e_machine, regnum); + if (id < 0) + return -EINVAL; + + ret = perf_reg_value(&val, perf_sample__user_regs(ui->sample), id); + if (ret) { + if (!ui->best_effort) + pr_err("unwind: can't read reg %d\n", regnum); + return ret; + } + + if (ui->unw_word_t_size == 8) + *(uint64_t *)valp_word = val; + else + *(uint32_t *)valp_word = (uint32_t)val; + pr_debug3("unwind: reg %d, val %lx\n", regnum, val); + return 0; +} int unwind__prepare_access(struct maps *maps, uint16_t e_machine) { - struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops; + void *addr_space; if (!dwarf_callchain_users) return 0; @@ -30,30 +567,16 @@ int unwind__prepare_access(struct maps *maps, uint16_t e_machine) if (e_machine == EM_NONE) return 0; - if (e_machine != EM_HOST) { - /* If not live/local mode. */ - switch (e_machine) { - case EM_386: - ops = x86_32_unwind_libunwind_ops; - break; - case EM_AARCH64: - ops = arm64_unwind_libunwind_ops; - break; - default: - pr_warning_once("unwind: ELF machine type %d is not supported\n", - e_machine); - return 0; - } - } - - if (!ops) { - pr_warning_once("unwind: target platform is not supported\n"); - return 0; - } - maps__set_unwind_libunwind_ops(maps, ops); maps__set_e_machine(maps, e_machine); + addr_space = libunwind_arch__create_addr_space(e_machine); - return ops->prepare_access(maps); + maps__set_addr_space(maps, addr_space); + if (!addr_space) { + pr_err("unwind: Can't create unwind address space.\n"); + return -ENOMEM; + } + + return 0; } void unwind__flush_access(struct maps *maps) @@ -66,14 +589,95 @@ void unwind__finish_access(struct maps *maps) libunwind_arch__finish_access(maps); } +static int entry(uint64_t ip, struct thread *thread, unwind_entry_cb_t cb, void *arg) +{ + struct unwind_entry e; + struct addr_location al; + int ret; + + addr_location__init(&al); + e.ms.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); + e.ip = ip; + e.ms.map = al.map; + e.ms.thread = thread__get(al.thread); + + pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", + al.sym ? al.sym->name : "''", + ip, + al.map ? map__map_ip(al.map, ip) : (u64) 0); + + ret = cb(&e, arg); + addr_location__exit(&al); + return ret; +} + int libunwind__get_entries(unwind_entry_cb_t cb, void *arg, struct thread *thread, - struct perf_sample *data, int max_stack, + struct perf_sample *sample, int max_stack, bool best_effort) { - const struct unwind_libunwind_ops *ops = maps__unwind_libunwind_ops(thread__maps(thread)); + struct unwind_info *ui; + uint64_t first_ip; + int ret, i = 0, entries = 0; + uint16_t e_machine; - if (ops) - return ops->get_entries(cb, arg, thread, data, max_stack, best_effort); - return 0; + if (!sample->user_regs || !sample->user_regs->regs) + return 0; + + if (max_stack <= 0) + return 0; + + if (!thread) { + pr_warning_once("WARNING: thread is NULL"); + return 0; + } + + e_machine = thread__e_machine(thread, /*machine=*/NULL, /*e_flags=*/NULL); + ret = perf_reg_value(&first_ip, perf_sample__user_regs(sample), + perf_arch_reg_ip(e_machine)); + if (ret) + return 0; + + if (max_stack == 1) { + /* Special case for a single entry. */ + ret = entry(first_ip, thread, cb, arg); + return ret ? (ret == -ENOMEM ? -ENOMEM : 0) : 1; + } + + ui = libunwind_arch_unwind_info__new(thread, sample, max_stack, best_effort, e_machine, first_ip); + if (!ui) + return -ENOMEM; + + do { + ret = libunwind_arch__unwind_step(ui); + if (ret < 0) + goto out; + + } while (ret); + + /* + * Display what we got based on the order setup. + */ + for (i = 0; i < ui->cur_ip; i++) { + int j = callchain_param.order == ORDER_CALLEE ? i : ui->cur_ip - i - 1; + + if (ui->ips[j]) { + ret = entry(ui->ips[j], thread, cb, arg); + if (ret) + break; + entries++; + } + } +out: + libunwind_arch_unwind_info__delete(ui); + /* + * Unwinder return contract: + * > 0 : unwinding succeeded (stops fallback). + * 0 : unwinding failed without yielding frames. Ignore non-fatal errors + * (e.g. stepping failure) to allow fallback unwinder or kernel callchains. + * < 0 : fatal error (e.g. -ENOMEM). Aborts unwinding entirely. + */ + if (ret == -ENOMEM) + return -ENOMEM; + return (entries > 0 || ret == 0) ? entries : 0; } diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index 6a0f117898b2..a2d4af694fde 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -19,13 +19,6 @@ struct unwind_entry { typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); -struct unwind_libunwind_ops { - int (*prepare_access)(struct maps *maps); - int (*get_entries)(unwind_entry_cb_t cb, void *arg, - struct thread *thread, - struct perf_sample *data, int max_stack, bool best_effort); -}; - int unwind__configure(const char *var, const char *value, void *cb); int unwind__option(const struct option *opt, const char *arg, int unset); From 834c557167a9236d8d8fe858b7b2d71ce6df7545 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 13 May 2026 16:31:51 -0700 Subject: [PATCH 035/343] perf unwind-libunwind: Add RISC-V libunwind support Add a RISC-V implementation for unwinding. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andrew Jones Cc: Athira Rajeev Cc: Dapeng Mi Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Florian Fainelli Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Li Guan Cc: Namhyung Kim Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Shimin Guo Cc: Thomas Richter Cc: Tomas Glozar Cc: Will Deacon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/libunwind-arch/Build | 1 + .../perf/util/libunwind-arch/libunwind-arch.c | 21 ++ .../perf/util/libunwind-arch/libunwind-arch.h | 22 ++ .../util/libunwind-arch/libunwind-riscv.c | 297 ++++++++++++++++++ 4 files changed, 341 insertions(+) create mode 100644 tools/perf/util/libunwind-arch/libunwind-riscv.c diff --git a/tools/perf/util/libunwind-arch/Build b/tools/perf/util/libunwind-arch/Build index 87fd657a3248..80d3571918b1 100644 --- a/tools/perf/util/libunwind-arch/Build +++ b/tools/perf/util/libunwind-arch/Build @@ -5,6 +5,7 @@ perf-util-$(CONFIG_LIBUNWIND) += libunwind-loongarch.o perf-util-$(CONFIG_LIBUNWIND) += libunwind-mips.o perf-util-$(CONFIG_LIBUNWIND) += libunwind-ppc32.o perf-util-$(CONFIG_LIBUNWIND) += libunwind-ppc64.o +perf-util-$(CONFIG_LIBUNWIND) += libunwind-riscv.o perf-util-$(CONFIG_LIBUNWIND) += libunwind-s390.o perf-util-$(CONFIG_LIBUNWIND) += libunwind-i386.o perf-util-$(CONFIG_LIBUNWIND) += libunwind-x86_64.o diff --git a/tools/perf/util/libunwind-arch/libunwind-arch.c b/tools/perf/util/libunwind-arch/libunwind-arch.c index 8539b4233df4..9a74cf3c8729 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arch.c +++ b/tools/perf/util/libunwind-arch/libunwind-arch.c @@ -20,6 +20,8 @@ int get_perf_regnum_for_unw_regnum(unsigned int e_machine, int unw_regnum) return __get_perf_regnum_for_unw_regnum_ppc32(unw_regnum); case EM_PPC64: return __get_perf_regnum_for_unw_regnum_ppc64(unw_regnum); + case EM_RISCV: + return __get_perf_regnum_for_unw_regnum_riscv(unw_regnum); case EM_S390: return __get_perf_regnum_for_unw_regnum_s390(unw_regnum); case EM_386: @@ -58,6 +60,9 @@ void libunwind_arch__flush_access(struct maps *maps) case EM_PPC64: __libunwind_arch__flush_access_ppc64(maps); break; + case EM_RISCV: + __libunwind_arch__flush_access_riscv(maps); + break; case EM_S390: __libunwind_arch__flush_access_s390(maps); break; @@ -98,6 +103,9 @@ void libunwind_arch__finish_access(struct maps *maps) case EM_PPC64: __libunwind_arch__finish_access_ppc64(maps); break; + case EM_RISCV: + __libunwind_arch__finish_access_riscv(maps); + break; case EM_S390: __libunwind_arch__finish_access_s390(maps); break; @@ -128,6 +136,8 @@ void *libunwind_arch__create_addr_space(unsigned int e_machine) return __libunwind_arch__create_addr_space_ppc32(); case EM_PPC64: return __libunwind_arch__create_addr_space_ppc64(); + case EM_RISCV: + return __libunwind_arch__create_addr_space_riscv(); case EM_S390: return __libunwind_arch__create_addr_space_s390(); case EM_386: @@ -167,6 +177,9 @@ int libunwind_arch__dwarf_search_unwind_table(unsigned int e_machine, case EM_PPC64: return __libunwind_arch__dwarf_search_unwind_table_ppc64(as, ip, di, pi, need_unwind_info, arg); + case EM_RISCV: + return __libunwind_arch__dwarf_search_unwind_table_riscv(as, ip, di, pi, + need_unwind_info, arg); case EM_S390: return __libunwind_arch__dwarf_search_unwind_table_s390(as, ip, di, pi, need_unwind_info, arg); @@ -211,6 +224,9 @@ int libunwind_arch__dwarf_find_debug_frame(unsigned int e_machine, case EM_PPC64: return __libunwind_arch__dwarf_find_debug_frame_ppc64(found, di_debug, ip, segbase, obj_name, start, end); + case EM_RISCV: + return __libunwind_arch__dwarf_find_debug_frame_riscv(found, di_debug, ip, segbase, + obj_name, start, end); case EM_S390: return __libunwind_arch__dwarf_find_debug_frame_s390(found, di_debug, ip, segbase, obj_name, start, end); @@ -250,6 +266,9 @@ struct unwind_info *libunwind_arch_unwind_info__new(struct thread *thread, case EM_PPC64: return __libunwind_arch_unwind_info__new_ppc64(thread, sample, max_stack, best_effort, first_ip); + case EM_RISCV: + return __libunwind_arch_unwind_info__new_riscv(thread, sample, max_stack, + best_effort, first_ip); case EM_S390: return __libunwind_arch_unwind_info__new_s390(thread, sample, max_stack, best_effort, first_ip); @@ -285,6 +304,8 @@ int libunwind_arch__unwind_step(struct unwind_info *ui) return __libunwind_arch__unwind_step_ppc32(ui); case EM_PPC64: return __libunwind_arch__unwind_step_ppc64(ui); + case EM_RISCV: + return __libunwind_arch__unwind_step_riscv(ui); case EM_S390: return __libunwind_arch__unwind_step_s390(ui); case EM_386: diff --git a/tools/perf/util/libunwind-arch/libunwind-arch.h b/tools/perf/util/libunwind-arch/libunwind-arch.h index 2bf7fc33313b..74a09cd58f38 100644 --- a/tools/perf/util/libunwind-arch/libunwind-arch.h +++ b/tools/perf/util/libunwind-arch/libunwind-arch.h @@ -39,6 +39,7 @@ int __get_perf_regnum_for_unw_regnum_loongarch(int unw_regnum); int __get_perf_regnum_for_unw_regnum_mips(int unw_regnum); int __get_perf_regnum_for_unw_regnum_ppc32(int unw_regnum); int __get_perf_regnum_for_unw_regnum_ppc64(int unw_regnum); +int __get_perf_regnum_for_unw_regnum_riscv(int unw_regnum); int __get_perf_regnum_for_unw_regnum_s390(int unw_regnum); int __get_perf_regnum_for_unw_regnum_i386(int unw_regnum); int __get_perf_regnum_for_unw_regnum_x86_64(int unw_regnum); @@ -50,6 +51,7 @@ void __libunwind_arch__flush_access_loongarch(struct maps *maps); void __libunwind_arch__flush_access_mips(struct maps *maps); void __libunwind_arch__flush_access_ppc32(struct maps *maps); void __libunwind_arch__flush_access_ppc64(struct maps *maps); +void __libunwind_arch__flush_access_riscv(struct maps *maps); void __libunwind_arch__flush_access_s390(struct maps *maps); void __libunwind_arch__flush_access_i386(struct maps *maps); void __libunwind_arch__flush_access_x86_64(struct maps *maps); @@ -61,6 +63,7 @@ void __libunwind_arch__finish_access_loongarch(struct maps *maps); void __libunwind_arch__finish_access_mips(struct maps *maps); void __libunwind_arch__finish_access_ppc32(struct maps *maps); void __libunwind_arch__finish_access_ppc64(struct maps *maps); +void __libunwind_arch__finish_access_riscv(struct maps *maps); void __libunwind_arch__finish_access_s390(struct maps *maps); void __libunwind_arch__finish_access_i386(struct maps *maps); void __libunwind_arch__finish_access_x86_64(struct maps *maps); @@ -72,6 +75,7 @@ void *__libunwind_arch__create_addr_space_loongarch(void); void *__libunwind_arch__create_addr_space_mips(void); void *__libunwind_arch__create_addr_space_ppc32(void); void *__libunwind_arch__create_addr_space_ppc64(void); +void *__libunwind_arch__create_addr_space_riscv(void); void *__libunwind_arch__create_addr_space_s390(void); void *__libunwind_arch__create_addr_space_i386(void); void *__libunwind_arch__create_addr_space_x86_64(void); @@ -111,6 +115,11 @@ int __libunwind_arch__dwarf_search_unwind_table_ppc64(void *as, uint64_t ip, void *pi, int need_unwind_info, void *arg); +int __libunwind_arch__dwarf_search_unwind_table_riscv(void *as, uint64_t ip, + struct libarch_unwind__dyn_info *di, + void *pi, + int need_unwind_info, + void *arg); int __libunwind_arch__dwarf_search_unwind_table_s390(void *as, uint64_t ip, struct libarch_unwind__dyn_info *di, void *pi, @@ -176,6 +185,13 @@ int __libunwind_arch__dwarf_find_debug_frame_ppc64(int found, const char *obj_name, uint64_t start, uint64_t end); +int __libunwind_arch__dwarf_find_debug_frame_riscv(int found, + struct libarch_unwind__dyn_info *di_debug, + uint64_t ip, + uint64_t segbase, + const char *obj_name, + uint64_t start, + uint64_t end); int __libunwind_arch__dwarf_find_debug_frame_s390(int found, struct libarch_unwind__dyn_info *di_debug, uint64_t ip, @@ -236,6 +252,11 @@ struct unwind_info *__libunwind_arch_unwind_info__new_ppc64(struct thread *threa int max_stack, bool best_effort, uint64_t first_ip); +struct unwind_info *__libunwind_arch_unwind_info__new_riscv(struct thread *thread, + struct perf_sample *sample, + int max_stack, + bool best_effort, + uint64_t first_ip); struct unwind_info *__libunwind_arch_unwind_info__new_s390(struct thread *thread, struct perf_sample *sample, int max_stack, @@ -266,6 +287,7 @@ int __libunwind_arch__unwind_step_loongarch(struct unwind_info *ui); int __libunwind_arch__unwind_step_mips(struct unwind_info *ui); int __libunwind_arch__unwind_step_ppc32(struct unwind_info *ui); int __libunwind_arch__unwind_step_ppc64(struct unwind_info *ui); +int __libunwind_arch__unwind_step_riscv(struct unwind_info *ui); int __libunwind_arch__unwind_step_s390(struct unwind_info *ui); int __libunwind_arch__unwind_step_i386(struct unwind_info *ui); int __libunwind_arch__unwind_step_x86_64(struct unwind_info *ui); diff --git a/tools/perf/util/libunwind-arch/libunwind-riscv.c b/tools/perf/util/libunwind-arch/libunwind-riscv.c new file mode 100644 index 000000000000..3220690cd7d1 --- /dev/null +++ b/tools/perf/util/libunwind-arch/libunwind-riscv.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libunwind-arch.h" +#include "../debug.h" +#include "../maps.h" +#include "../thread.h" +#include "../../../arch/riscv/include/uapi/asm/perf_regs.h" +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBUNWIND_RISCV_SUPPORT +#include +#endif + +int __get_perf_regnum_for_unw_regnum_riscv(int unw_regnum __maybe_unused) +{ +#ifndef HAVE_LIBUNWIND_RISCV_SUPPORT + return -EINVAL; +#else + switch (unw_regnum) { + case UNW_RISCV_X1 ... UNW_RISCV_X31: + return unw_regnum - UNW_RISCV_X1 + PERF_REG_RISCV_RA; + case UNW_RISCV_PC: + return PERF_REG_RISCV_PC; + default: + pr_err("unwind: invalid reg id %d\n", unw_regnum); + return -EINVAL; + } +#endif // HAVE_LIBUNWIND_RISCV_SUPPORT +} + +void __libunwind_arch__flush_access_riscv(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_RISCV_SUPPORT + unw_flush_cache(maps__addr_space(maps), 0, 0); +#endif +} + +void __libunwind_arch__finish_access_riscv(struct maps *maps __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_RISCV_SUPPORT + unw_destroy_addr_space(maps__addr_space(maps)); +#endif +} + +#ifdef HAVE_LIBUNWIND_RISCV_SUPPORT +static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + return __libunwind__find_proc_info(as, ip, pi, need_unwind_info, arg); +} + +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) +{ + pr_debug("unwind: put_unwind_info called\n"); +} + +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) +{ + return -UNW_ENOINFO; +} + +static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_mem(as, addr, valp, __write, arg); +} + +static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, + int __write, void *arg) +{ + return __libunwind__access_reg(as, regnum, valp, __write, arg); +} + +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) +{ + pr_err("unwind: access_fpreg unsupported\n"); + return -UNW_EINVAL; +} + +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) +{ + pr_err("unwind: resume unsupported\n"); + return -UNW_EINVAL; +} + +static int get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) +{ + pr_err("unwind: get_proc_name unsupported\n"); + return -UNW_EINVAL; +} +#endif + +void *__libunwind_arch__create_addr_space_riscv(void) +{ +#ifdef HAVE_LIBUNWIND_RISCV_SUPPORT + static unw_accessors_t accessors = { + .find_proc_info = find_proc_info, + .put_unwind_info = put_unwind_info, + .get_dyn_info_list_addr = get_dyn_info_list_addr, + .access_mem = access_mem, + .access_reg = access_reg, + .access_fpreg = access_fpreg, + .resume = resume, + .get_proc_name = get_proc_name, + }; + unw_addr_space_t addr_space; + + addr_space = unw_create_addr_space(&accessors, /*byte_order=*/0); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + return addr_space; +#else + return NULL; +#endif +} + +#ifdef HAVE_LIBUNWIND_RISCV_SUPPORT +extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, + unw_word_t ip, + unw_dyn_info_t *di, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) +#endif + +int __libunwind_arch__dwarf_search_unwind_table_riscv(void *as __maybe_unused, + uint64_t ip __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + void *pi __maybe_unused, + int need_unwind_info __maybe_unused, + void *arg __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_RISCV_SUPPORT + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.rti.segbase; + _di->table_data = di.u.rti.table_data; + _di->table_len = di.u.rti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +#if defined(HAVE_LIBUNWIND_RISCV_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_RISCV) +extern int UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, + unw_word_t ip, + unw_word_t segbase, + const char *obj_name, unw_word_t start, + unw_word_t end); +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) +#endif + +int __libunwind_arch__dwarf_find_debug_frame_riscv(int found __maybe_unused, + struct libarch_unwind__dyn_info *_di __maybe_unused, + uint64_t ip __maybe_unused, + uint64_t segbase __maybe_unused, + const char *obj_name __maybe_unused, + uint64_t start __maybe_unused, + uint64_t end __maybe_unused) +{ +#if defined(HAVE_LIBUNWIND_RISCV_SUPPORT) && !defined(NO_LIBUNWIND_DEBUG_FRAME_RISCV) + unw_dyn_info_t di = { + .format = UNW_INFO_FORMAT_REMOTE_TABLE, + .start_ip = _di->start_ip, + .end_ip = _di->end_ip, + .u = { + .rti = { + .segbase = _di->segbase, + .table_data = _di->table_data, + .table_len = _di->table_len, + }, + }, + }; + int ret = dwarf_find_debug_frame(found, &di, ip, segbase, obj_name, start, end); + + _di->start_ip = di.start_ip; + _di->end_ip = di.end_ip; + _di->segbase = di.u.ti.segbase; + _di->table_data = di.u.ti.table_data; + _di->table_len = di.u.ti.table_len; + return ret; +#else + return -EINVAL; +#endif +} + +struct unwind_info *__libunwind_arch_unwind_info__new_riscv(struct thread *thread __maybe_unused, + struct perf_sample *sample __maybe_unused, + int max_stack __maybe_unused, + bool best_effort __maybe_unused, + uint64_t first_ip __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_RISCV_SUPPORT + struct arch_unwind_info { + struct unwind_info ui; + unw_cursor_t _cursor; + uint64_t _ips[]; + }; + + struct maps *maps = thread__maps(thread); + void *addr_space = maps__addr_space(maps); + struct arch_unwind_info *ui; + int ret; + + if (addr_space == NULL) + return NULL; + + ui = zalloc(sizeof(*ui) + sizeof(ui->_ips[0]) * max_stack); + if (!ui) + return NULL; + + ui->ui.machine = maps__machine(maps); + ui->ui.thread = thread; + ui->ui.sample = sample; + ui->ui.cursor = &ui->_cursor; + ui->ui.ips = &ui->_ips[0]; + ui->ui.ips[0] = first_ip; + ui->ui.cur_ip = 1; + ui->ui.max_ips = max_stack; + ui->ui.unw_word_t_size = sizeof(unw_word_t); + ui->ui.e_machine = EM_RISCV; + ui->ui.best_effort = best_effort; + + ret = unw_init_remote(&ui->_cursor, addr_space, &ui->ui); + if (ret) { + if (!best_effort) + pr_err("libunwind: %s\n", unw_strerror(ret)); + free(ui); + return NULL; + } + + return &ui->ui; +#else + return NULL; +#endif +} + +int __libunwind_arch__unwind_step_riscv(struct unwind_info *ui __maybe_unused) +{ +#ifdef HAVE_LIBUNWIND_RISCV_SUPPORT + int ret; + + if (ui->cur_ip >= ui->max_ips) + return 0; + + ret = unw_step(ui->cursor); + if (ret > 0) { + uint64_t ip; + + unw_get_reg(ui->cursor, UNW_REG_IP, &ip); + + if (unw_is_signal_frame(ui->cursor) <= 0) { + /* + * Decrement the IP for any non-activation frames. This + * is required to properly find the srcline for caller + * frames. See also the documentation for + * dwfl_frame_pc(), which this code tries to replicate. + */ + --ip; + } + ui->ips[ui->cur_ip++] = ip; + } + return ret; +#else + return -EINVAL; +#endif +} From 7ee7f48413c42b90230de4a8e40898b757bc8e82 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 13 May 2026 12:23:46 -0700 Subject: [PATCH 036/343] perf trace beauty fcntl: Fix build with older kernel headers Toolchains with older kernel headers that do not include upstream commit c75b1d9421f80f41 ("fs: add fcntl() interface for setting/getting write life time hints") will now fail to build perf due to missing definitions for F_GET_RW_HINT/F_SET_RW_HINT/F_GET_FILE_RW_HINT/F_SET_FILE_RW_HINT. Provide a fallback definition for these when they are not already defined. Fixes: 9c47f66748381ecb ("perf trace beauty fcntl: Basic 'arg' beautifier") Reviewed-by: Ian Rogers Signed-off-by: Florian Fainelli Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Markus Mayer Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/trace/beauty/fcntl.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c index d075904dccce..e1b99b8f55eb 100644 --- a/tools/perf/trace/beauty/fcntl.c +++ b/tools/perf/trace/beauty/fcntl.c @@ -9,6 +9,22 @@ #include #include +#ifndef F_GET_RW_HINT +#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11) +#endif + +#ifndef F_SET_RW_HINT +#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12) +#endif + +#ifndef F_GET_FILE_RW_HINT +#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13) +#endif + +#ifndef F_SET_FILE_RW_HINT +#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14) +#endif + static size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size, bool show_prefix) { return val ? scnprintf(bf, size, "%s", "0") : From 2e2ba7d1ea554ee6e9e751a53eebf3e9270b0670 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Fri, 10 Apr 2026 12:13:44 +0100 Subject: [PATCH 037/343] perf pmu: Skip test on Arm64 when #slots is zero Some Arm64 PMUs expose 'caps/slots' as 0 when the slot count is not implemented, tool_pmu__read_event() currently returns false for this, so metrics that reference #slots are reported as syntax error. Since the commit 3a61fd866ef9 ("perf expr: Return -EINVAL for syntax error in expr__find_ids()"), these syntax errors are populated as failures and make the PMU metric test fail: 9.3: Parsing of PMU event table metrics: --- start --- ... Found metric 'backend_bound' metric expr 100 * (stall_slot_backend / (#slots * cpu_cycles)) for backend_bound parsing metric: 100 * (stall_slot_backend / (#slots * cpu_cycles)) Failure to read '#slots' literal: #slots = nan syntax error Fail to parse metric or group `backend_bound' ... ---- end(-1) ---- 9.3: Parsing of PMU event table metrics : FAILED! This commit introduces a new function is_expected_broken_metric() to identify broken metrics, and treats metrics containing "#slots" as expected broken when #slots == 0 on Arm64 platforms. Fixes: 3a61fd866ef9aaa1 ("perf expr: Return -EINVAL for syntax error in expr__find_ids()") Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Leo Yan Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index a99716862168..b1609a7e1d8c 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -15,6 +15,7 @@ #include "util/expr.h" #include "util/hashmap.h" #include "util/parse-events.h" +#include "util/tool_pmu.h" #include "metricgroup.h" #include "stat.h" @@ -817,6 +818,26 @@ struct metric { struct metric_ref metric_ref; }; +static bool is_expected_broken_metric(const struct pmu_metric *pm) +{ + if (!strcmp(pm->metric_name, "M1") || !strcmp(pm->metric_name, "M2") || + !strcmp(pm->metric_name, "M3")) + return true; + +#if defined(__aarch64__) + /* + * Arm64 platforms may return "#slots == 0", which is treated as a + * syntax error by the parser. Don't test these metrics when running + * on such platforms. + */ + if (strstr(pm->metric_expr, "#slots") && + !tool_pmu__cpu_slots_per_cycle()) + return true; +#endif + + return false; +} + static int test__parsing_callback(const struct pmu_metric *pm, const struct pmu_metrics_table *table, void *data) @@ -852,8 +873,7 @@ static int test__parsing_callback(const struct pmu_metric *pm, err = metricgroup__parse_groups_test(evlist, table, pm->metric_name); if (err) { - if (!strcmp(pm->metric_name, "M1") || !strcmp(pm->metric_name, "M2") || - !strcmp(pm->metric_name, "M3")) { + if (is_expected_broken_metric(pm)) { (*failures)--; pr_debug("Expected broken metric %s skipping\n", pm->metric_name); err = 0; From e445b78ffb8d43440b9f417d6701826746114a0d Mon Sep 17 00:00:00 2001 From: Aaron Tomlin Date: Fri, 24 Apr 2026 17:29:33 -0400 Subject: [PATCH 038/343] perf trace: Introduce --show-cpu option to display cpu id When tracing system-wide workloads or specific events, it is highly valuable to know exactly which CPU executed a specific event. Currently, perf trace output defaults to omitting CPU information. Introduce a new "--show-cpu" command-line option. When provided, this flag extracts the CPU from the perf sample and prints it in a "[000]" format immediately following the timestamp. This mirrors the behaviour of other tracing tools like ftrace and perf script. For example: # perf trace -e sched:sched_switch --max-events 5 --show-cpu 0.000 [002] :0/0 sched:sched_switch(prev_comm: "swapper/2", prev_prio: 120, next_comm: "rcu_preempt", next_pid: 16 (rcu_preempt), next_prio: 120) 0.009 [002] rcu_preempt/16 sched:sched_switch(prev_comm: "rcu_preempt", prev_pid: 16 (rcu_preempt), prev_prio: 120, prev_state: 128, next_comm: "swapper/2", next_prio: 120) 0.033 [002] :0/0 sched:sched_switch(prev_comm: "swapper/2", prev_prio: 120, next_comm: "kworker/u32:48", next_pid: 35840 (kworker/u32:48-), next_prio: 120) 0.041 [002] kworker/u32:48/35840 sched:sched_switch(prev_comm: "kworker/u32:48", prev_pid: 35840 (kworker/u32:48-), prev_prio: 120, prev_state: 128, next_comm: "swapper/2", next_prio: 120) 0.045 [002] :0/0 sched:sched_switch(prev_comm: "swapper/2", prev_prio: 120, next_comm: "kworker/u32:48", next_pid: 35840 (kworker/u32:48-), next_prio: 120) The feature is implemented strictly as an opt-in toggle to prevent cluttering the standard output and to preserve backwards compatibility for scripts parsing the default output format. Signed-off-by: Aaron Tomlin Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Daniel Vacek Cc: Howard Chu Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Sean Ashe Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 3 ++ tools/perf/builtin-trace.c | 51 ++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 892c82a9bf40..d0b6c771a1b9 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -199,6 +199,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. --show-on-off-events:: Show the --switch-on/off events too. +--show-cpu:: + Show cpu id. + --max-stack:: Set the stack depth limit when parsing the callchain, anything beyond the specified depth will be ignored. Note that at this point diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index e58c49d047a2..e9cc870a5acd 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -217,6 +217,7 @@ struct trace { bool kernel_syscallchains; s16 args_alignment; bool show_tstamp; + bool show_cpu; bool show_duration; bool show_zeros; bool show_arg_names; @@ -1531,6 +1532,7 @@ static size_t fprintf_duration(unsigned long t, bool calculated, FILE *fp) */ struct thread_trace { u64 entry_time; + u32 entry_cpu; bool entry_pending; unsigned long nr_events; unsigned long pfmaj, pfmin; @@ -1893,6 +1895,27 @@ static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp) return fprintf(fp, " ? "); } +/** + * trace__fprintf_cpu - Print the CPU ID to a given file stream + * @cpu: The CPU ID to print + * @fp: The file stream to write to + * + * Formats and prints the specified CPU ID enclosed in brackets + * (e.g., "[003] ") to the provided file pointer. It is used to + * align and display the CPU ID consistently within the trace output. + * + * Return: The number of characters printed. + */ +static size_t trace__fprintf_cpu(u32 cpu, FILE *fp) +{ + size_t printed = 0; + + if (cpu != (u32)-1) + printed += fprintf(fp, "[%03u] ", cpu); + + return printed; +} + static pid_t workload_pid = -1; static volatile sig_atomic_t done = false; static volatile sig_atomic_t interrupted = false; @@ -1923,12 +1946,15 @@ static size_t trace__fprintf_comm_tid(struct trace *trace, struct thread *thread } static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread, - u64 duration, bool duration_calculated, u64 tstamp, FILE *fp) + u64 duration, bool duration_calculated, + u64 tstamp, u32 cpu, FILE *fp) { size_t printed = 0; if (trace->show_tstamp) printed = trace__fprintf_tstamp(trace, tstamp, fp); + if (trace->show_cpu && cpu != (u32)-1) + printed += trace__fprintf_cpu(cpu, fp); if (trace->show_duration) printed += fprintf_duration(duration, duration_calculated, fp); return printed + trace__fprintf_comm_tid(trace, thread, fp); @@ -2707,7 +2733,9 @@ static int trace__printf_interrupted_entry(struct trace *trace) if (!ttrace->entry_pending) return 0; - printed = trace__fprintf_entry_head(trace, trace->current, 0, false, ttrace->entry_time, trace->output); + printed = trace__fprintf_entry_head(trace, trace->current, 0, false, + ttrace->entry_time, ttrace->entry_cpu, + trace->output); printed += len = fprintf(trace->output, "%s)", ttrace->entry_str); if (len < trace->args_alignment - 4) @@ -2825,6 +2853,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel, if (evsel != trace->syscalls.events.sys_enter) augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size); ttrace->entry_time = sample->time; + ttrace->entry_cpu = sample->cpu; msg = ttrace->entry_str; printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name); @@ -2835,7 +2864,9 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel, if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) { int alignment = 0; - trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output); + trace__fprintf_entry_head(trace, thread, 0, false, + ttrace->entry_time, + sample->cpu, trace->output); printed = fprintf(trace->output, "%s)", ttrace->entry_str); if (trace->args_alignment > printed) alignment = trace->args_alignment - printed; @@ -2980,7 +3011,9 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel, if (trace->summary_only || (ret >= 0 && trace->failure_only)) goto out; - trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output); + trace__fprintf_entry_head(trace, thread, duration, + duration_calculated, ttrace->entry_time, + sample->cpu, trace->output); if (ttrace->entry_pending) { printed = fprintf(trace->output, "%s", ttrace->entry_str); @@ -3280,6 +3313,9 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel, trace__printf_interrupted_entry(trace); trace__fprintf_tstamp(trace, sample->time, trace->output); + if (trace->show_cpu) + trace__fprintf_cpu(sample->cpu, trace->output); + if (trace->trace_syscalls && trace->show_duration) fprintf(trace->output, "( ): "); @@ -3405,7 +3441,8 @@ static int trace__pgfault(struct trace *trace, thread__find_symbol(thread, sample->cpumode, sample->ip, &al); - trace__fprintf_entry_head(trace, thread, 0, true, sample->time, trace->output); + trace__fprintf_entry_head(trace, thread, 0, true, sample->time, + sample->cpu, trace->output); fprintf(trace->output, "%sfault [", evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ? @@ -5432,6 +5469,7 @@ int cmd_trace(int argc, const char **argv) OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages", "number of mmap data pages", evlist__parse_mmap_pages), OPT_STRING('u', "uid", &trace.uid_str, "user", "user to profile"), + OPT_BOOLEAN(0, "show-cpu", &trace.show_cpu, "show cpu id"), OPT_CALLBACK(0, "duration", &trace, "float", "show only events with duration > N.M ms", trace__set_duration), @@ -5566,6 +5604,9 @@ int cmd_trace(int argc, const char **argv) goto out; } + if (trace.show_cpu) + trace.opts.sample_cpu = true; + if ((nr_cgroups || trace.cgroup) && !trace.opts.target.system_wide) { usage_with_options_msg(trace_usage, trace_options, "cgroup monitoring only available in system-wide mode"); From 6a082433bcc749f3e07bd2e28a733758ee875373 Mon Sep 17 00:00:00 2001 From: Chen Pei Date: Wed, 20 May 2026 21:40:04 +0800 Subject: [PATCH 039/343] perf riscv: Add SDT argument parsing for RISC-V Implement __perf_sdt_arg_parse_op_riscv() to convert RISC-V GCC-generated SDT probe operands into uprobe-compatible format, and register it in the perf_sdt_arg_parse_op() dispatcher for EM_RISCV. RISC-V GCC uses the 'nor' constraint for SDT arguments, producing operands in the following formats: Format Example Uprobe format ----------- ----------- ------------- register a0 %a0 memory (+) 8(a0) +8(%a0) memory (-) -20(s0) -20(%s0) constant 99 (skip, not supported by uprobe) Key differences from other architectures: - Register names use ABI aliases (a0-a7, t0-t6, s0-s11, sp, ra, etc.) without any '%' prefix, unlike x86 (%rax) or arm64 (x0). - Memory operands use OFFSET(REG) syntax where OFFSET may be negative, unlike arm64's [sp, NUM] or powerpc's NUM(%rREG). Two regexes are used: - SDT_OP_REGEX1: matches RISC-V ABI register names saved in pt_regs - SDT_OP_REGEX2: matches [-]NUM(REG) memory operands Reviewed-by: Guo Ren Reviewed-by: Ian Rogers Signed-off-by: Chen Pei Cc: Alexandre Ghiti Cc: Dapeng Mi Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Walmsley Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- .../util/perf-regs-arch/perf_regs_riscv.c | 128 ++++++++++++++++++ tools/perf/util/perf_regs.c | 3 + tools/perf/util/perf_regs.h | 1 + 3 files changed, 132 insertions(+) diff --git a/tools/perf/util/perf-regs-arch/perf_regs_riscv.c b/tools/perf/util/perf-regs-arch/perf_regs_riscv.c index 5b5f21fcba8c..bf769304c97c 100644 --- a/tools/perf/util/perf-regs-arch/perf_regs_riscv.c +++ b/tools/perf/util/perf-regs-arch/perf_regs_riscv.c @@ -1,8 +1,136 @@ // SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include + +#include "../debug.h" #include "../perf_regs.h" #include "../../arch/riscv/include/perf_regs.h" +/* + * RISC-V SDT argument formats (GCC 'nor' constraint): + * + * Register: REG e.g. a0, t1, s0, sp + * Memory: NUM(REG) e.g. 8(a0), -20(s0) + * Constant: NUM e.g. 99 (not supported by uprobe, skip) + * + * Note: 'zero' (x0) is hardwired to 0 and not in pt_regs; skip it. + * + * Uprobe target format: + * Register: %REG e.g. %a0 + * Memory: +NUM(%REG) or -NUM(%REG) + */ + +/* RISC-V register ABI names: ra, sp, gp, tp, t0-t6, s0-s11, a0-a7 */ +#define SDT_OP_REGEX1 "^(ra|sp|gp|tp|t[0-6]|s[0-9]|s1[01]|a[0-7])$" + +/* RISC-V memory operand: [-]NUM(REG) */ +#define SDT_OP_REGEX2 "^(\\-)?([0-9]+)\\((ra|sp|gp|tp|t[0-6]|s[0-9]|s1[01]|a[0-7])\\)$" + +static regex_t sdt_op_regex1, sdt_op_regex2; + +static int sdt_init_op_regex(void) +{ + static int initialized; + int ret = 0; + + if (initialized) + return 0; + + ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED); + if (ret) + goto error; + + ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED); + if (ret) + goto free_regex1; + + initialized = 1; + return 0; + +free_regex1: + regfree(&sdt_op_regex1); +error: + pr_debug4("Regex compilation error.\n"); + return -ret; +} + +/* + * Parse OP and convert it into uprobe format. + * Possible variants of OP (RISC-V, GCC 'nor' constraint): + * + * Format Example Uprobe + * ---------------------------------------- + * REG a0 %a0 + * NUM(REG) 8(a0) +8(%a0) + * -NUM(REG) -20(s0) -20(%s0) + * NUM 99 (skip, constant not supported) + */ +int __perf_sdt_arg_parse_op_riscv(char *old_op, char **new_op) +{ + int ret, new_len; + regmatch_t rm[4]; + char prefix; + + /* + * Constant argument: pure integer with no trailing '(' (e.g. "99", "-1"). + * uprobe does not support immediate values, so skip them. + * Memory operands like "8(a0)" or "-20(s0)" contain '(' so are NOT + * treated as constants here; they will be matched by REGEX2 below. + */ + if (strchr(old_op, '(') == NULL && + ((*old_op >= '0' && *old_op <= '9') || + (*old_op == '-' && old_op[1] >= '0' && old_op[1] <= '9'))) { + pr_debug4("Skipping unsupported SDT argument: %s\n", old_op); + return SDT_ARG_SKIP; + } + + ret = sdt_init_op_regex(); + if (ret < 0) + return ret; + + if (!regexec(&sdt_op_regex1, old_op, 2, rm, 0)) { + /* REG --> %REG */ + new_len = 2; /* % NULL */ + new_len += (int)(rm[1].rm_eo - rm[1].rm_so); + + *new_op = zalloc(new_len); + if (!*new_op) + return -ENOMEM; + + scnprintf(*new_op, new_len, "%%%.*s", + (int)(rm[1].rm_eo - rm[1].rm_so), old_op + rm[1].rm_so); + } else if (!regexec(&sdt_op_regex2, old_op, 4, rm, 0)) { + /* + * NUM(REG) or -NUM(REG) --> +NUM(%REG) or -NUM(%REG) + * rm[1]: optional '-' + * rm[2]: decimal offset + * rm[3]: register name + */ + prefix = (rm[1].rm_so == -1) ? '+' : '-'; + + new_len = 5; /* sign ( % ) NULL */ + new_len += (int)(rm[2].rm_eo - rm[2].rm_so); + new_len += (int)(rm[3].rm_eo - rm[3].rm_so); + + *new_op = zalloc(new_len); + if (!*new_op) + return -ENOMEM; + + scnprintf(*new_op, new_len, "%c%.*s(%%%.*s)", prefix, + (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so, + (int)(rm[3].rm_eo - rm[3].rm_so), old_op + rm[3].rm_so); + } else { + pr_debug4("Skipping unsupported SDT argument: %s\n", old_op); + return SDT_ARG_SKIP; + } + + return SDT_ARG_VALID; +} + uint64_t __perf_reg_mask_riscv(bool intr __maybe_unused) { return PERF_REGS_MASK; diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c index f52b0e1f7fc7..558c143abbab 100644 --- a/tools/perf/util/perf_regs.c +++ b/tools/perf/util/perf_regs.c @@ -19,6 +19,9 @@ int perf_sdt_arg_parse_op(uint16_t e_machine, char *old_op, char **new_op) case EM_PPC64: ret = __perf_sdt_arg_parse_op_powerpc(old_op, new_op); break; + case EM_RISCV: + ret = __perf_sdt_arg_parse_op_riscv(old_op, new_op); + break; case EM_386: case EM_X86_64: ret = __perf_sdt_arg_parse_op_x86(old_op, new_op); diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index 573f0d1dfe04..79be2b791509 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h @@ -53,6 +53,7 @@ const char *__perf_reg_name_powerpc(int id); uint64_t __perf_reg_ip_powerpc(void); uint64_t __perf_reg_sp_powerpc(void); +int __perf_sdt_arg_parse_op_riscv(char *old_op, char **new_op); uint64_t __perf_reg_mask_riscv(bool intr); const char *__perf_reg_name_riscv(int id); uint64_t __perf_reg_ip_riscv(void); From b5050b133e7ab3f49ac391f9e812a227ae09e01e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 27 Apr 2026 23:54:32 -0700 Subject: [PATCH 040/343] perf clang-format: Add a perf clang-format that overrides some kernel behaviors In particular, header file ordering is an issue in the tools/perf directory given the larger number of depended upon libraries. The order of header file includes was proposed in: https://lore.kernel.org/linux-perf-users/CAP-5=fUitzKwJONTngiW17XkS7kVr2cDS4cDL_HccJKcnR2EgQ@mail.gmail.com/ Sorting headers is desirable to avoid issues like duplicate includes. Signed-off-by: Ian Rogers Cc: Andrew Morton Cc: Bill Wendling Cc: Joe Perches Cc: Justin Stitt Cc: Namhyung Kim Cc: Nathan Chancellor Cc: Nick Desaulniers Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/.clang-format | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tools/perf/.clang-format diff --git a/tools/perf/.clang-format b/tools/perf/.clang-format new file mode 100644 index 000000000000..902b2f7456f6 --- /dev/null +++ b/tools/perf/.clang-format @@ -0,0 +1,20 @@ +BasedOnStyle: InheritParentConfig +SortIncludes: true +IncludeBlocks: Regroup +IncludeCategories: + # Implicitly the corresponding header for the C file has Priority 0 + # C Standard Library Headers + - Regex: '^<(assert|complex|ctype|errno|fenv|float|inttypes|iso646|limits|locale|math|setjmp|signal|stdalign|stdarg|stdatomic|stdbool|stddef|stdint|stdio|stdlib|stdnoreturn|string|tgmath|threads|time|uchar|wchar|wctype)\.h>' + Priority: 1 + # OS/System-Specific Headers (directories) + - Regex: '^<(sys|linux|asm|arpa|net|netinet|x86_64|machine)/.*>' + Priority: 2 + # OS/System-Specific Headers (POSIX/System flat headers) + - Regex: '^<(unistd|pthread|fcntl|dirent|dlfcn|poll|sched|semaphore|spawn|syslog|termios|pwd|grp|netdb|sysexits|err|paths|pty|utmp|resolv|ifaddrs|elf|libelf|gelf)\.h>' + Priority: 2 + # Third-Party Library Headers + - Regex: '^<.*>' + Priority: 3 + # Your Project's Other Headers + - Regex: '^".*"' + Priority: 4 From 017bca78e4d72b1ff027d368c20a1b2c654edaf7 Mon Sep 17 00:00:00 2001 From: Michael Petlan Date: Wed, 20 May 2026 00:38:55 +0200 Subject: [PATCH 041/343] perf build-id: Fix off-by-one bug when printing kernel/module build-id When changing sprintf functions to snprintf, one byte got lost. Since snprintf ones do not handle the '\0' terminating character, the number of printed characters is 40, while sizeof(sbuild_id) is 41, including the terminating '\0' character. This makes the later check fail so that nothing is printed. Fix that. Before: [Michael@Carbon ~]$ perf buildid-list -k [Michael@Carbon ~]$ After: [Michael@Carbon ~]$ perf buildid-list -k a527806324d543c4bc3ff2f9c9519d494fed5f68 [Michael@Carbon ~]$ Fixes: fccaaf6fbbc59910 ("perf build-id: Change sprintf functions to snprintf") Signed-off-by: Michael Petlan Tested-by: Ian Rogers Cc: Ian Rogers Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-buildid-list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index a91bbb34ac94..e0881b0ac38f 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -61,7 +61,7 @@ static int sysfs__fprintf_build_id(FILE *fp) int ret; ret = sysfs__snprintf_build_id("/", sbuild_id, sizeof(sbuild_id)); - if (ret != sizeof(sbuild_id)) + if (ret + 1 != sizeof(sbuild_id)) return ret < 0 ? ret : -EINVAL; return fprintf(fp, "%s\n", sbuild_id); @@ -73,7 +73,7 @@ static int filename__fprintf_build_id(const char *name, FILE *fp) int ret; ret = filename__snprintf_build_id(name, sbuild_id, sizeof(sbuild_id)); - if (ret != sizeof(sbuild_id)) + if (ret + 1 != sizeof(sbuild_id)) return ret < 0 ? ret : -EINVAL; return fprintf(fp, "%s\n", sbuild_id); From 059e9100d82aae2254f1b06835a55755936b1417 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 15:43:24 -0700 Subject: [PATCH 042/343] perf event: Fix size of synthesized sample with branch stacks Synthesizing branch stacks for Intel-PT highlighted an issue where PERF_SAMPLE_BRANCH_HW_INDEX was assumed to always be set in the perf_event_attr branch_sample_type. This caused an incorrect size calculation. Fix the writing of the nr and hw_idx values during sample event synthesis by passing the branch_sample_type into the sample size and synthesis functions. Also update hardware tracers (Intel PT, ARM SPE, CS-ETM) to retrieve and pass their branch_sample_type dynamically to prevent payload misalignment. Fixes: d3f85437ad6a5511 ("perf evsel: Support PERF_SAMPLE_BRANCH_HW_INDEX") Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Dapeng Mi Cc: Ingo Molnar Cc: James Clark Cc: Kan Liang Cc: Leo Yan Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/inject-buildid.c | 9 ++++++--- tools/perf/builtin-inject.c | 12 +++++++++--- tools/perf/tests/dlfilter-test.c | 8 ++++++-- tools/perf/tests/sample-parsing.c | 5 +++-- tools/perf/util/arm-spe.c | 28 ++++++++++++++++++++++++---- tools/perf/util/cs-etm.c | 28 +++++++++++++++++++++++----- tools/perf/util/intel-bts.c | 3 ++- tools/perf/util/intel-pt.c | 27 +++++++++++++++++++++++---- tools/perf/util/synthetic-events.c | 25 ++++++++++++++++++------- tools/perf/util/synthetic-events.h | 6 ++++-- 10 files changed, 118 insertions(+), 33 deletions(-) diff --git a/tools/perf/bench/inject-buildid.c b/tools/perf/bench/inject-buildid.c index aad572a78d7f..bfd2c5ec9488 100644 --- a/tools/perf/bench/inject-buildid.c +++ b/tools/perf/bench/inject-buildid.c @@ -228,9 +228,12 @@ static ssize_t synthesize_sample(struct bench_data *data, struct bench_dso *dso, event.header.type = PERF_RECORD_SAMPLE; event.header.misc = PERF_RECORD_MISC_USER; - event.header.size = perf_event__sample_event_size(&sample, bench_sample_type, 0); - - perf_event__synthesize_sample(&event, bench_sample_type, 0, &sample); + event.header.size = perf_event__sample_event_size(&sample, bench_sample_type, + /*read_format=*/0, + /*branch_sample_type=*/0); + perf_event__synthesize_sample(&event, bench_sample_type, + /*read_format=*/0, + /*branch_sample_type=*/0, &sample); return writen(data->input_pipe[1], &event, event.header.size); } diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index a2493f1097df..2f20e782c7f2 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -465,8 +465,13 @@ static int perf_event__convert_sample_callchain(const struct perf_tool *tool, /* remove sample_type {STACK,REGS}_USER for synthesize */ sample_type &= ~(PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER); - perf_event__synthesize_sample(event_copy, sample_type, - evsel->core.attr.read_format, sample); + ret = perf_event__synthesize_sample(event_copy, sample_type, + evsel->core.attr.read_format, + evsel->core.attr.branch_sample_type, sample); + if (ret) { + pr_err("Failed to synthesize sample\n"); + return ret; + } return perf_event__repipe_synth(tool, event_copy); } @@ -1102,7 +1107,8 @@ static int perf_inject__sched_stat(const struct perf_tool *tool, sample_sw.period = sample->period; sample_sw.time = sample->time; perf_event__synthesize_sample(event_sw, evsel->core.attr.sample_type, - evsel->core.attr.read_format, &sample_sw); + evsel->core.attr.read_format, + evsel->core.attr.branch_sample_type, &sample_sw); build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine); ret = perf_event__repipe(tool, event_sw, &sample_sw, machine); perf_sample__exit(&sample_sw); diff --git a/tools/perf/tests/dlfilter-test.c b/tools/perf/tests/dlfilter-test.c index e63790c61d53..204663571943 100644 --- a/tools/perf/tests/dlfilter-test.c +++ b/tools/perf/tests/dlfilter-test.c @@ -188,8 +188,12 @@ static int write_sample(struct test_data *td, u64 sample_type, u64 id, pid_t pid event->header.type = PERF_RECORD_SAMPLE; event->header.misc = PERF_RECORD_MISC_USER; - event->header.size = perf_event__sample_event_size(&sample, sample_type, 0); - err = perf_event__synthesize_sample(event, sample_type, 0, &sample); + event->header.size = perf_event__sample_event_size(&sample, sample_type, + /*read_format=*/0, + /*branch_sample_type=*/0); + err = perf_event__synthesize_sample(event, sample_type, + /*read_format=*/0, + /*branch_sample_type=*/0, &sample); if (err) return test_result("perf_event__synthesize_sample() failed", TEST_FAIL); diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index a7327c942ca2..55f0b73ca20e 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -310,7 +310,8 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) sample.read.one.lost = 1; } - sz = perf_event__sample_event_size(&sample, sample_type, read_format); + sz = perf_event__sample_event_size(&sample, sample_type, read_format, + evsel.core.attr.branch_sample_type); bufsz = sz + 4096; /* Add a bit for overrun checking */ event = malloc(bufsz); if (!event) { @@ -324,7 +325,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) event->header.size = sz; err = perf_event__synthesize_sample(event, sample_type, read_format, - &sample); + evsel.core.attr.branch_sample_type, &sample); if (err) { pr_debug("%s failed for sample_type %#"PRIx64", error %d\n", "perf_event__synthesize_sample", sample_type, err); diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 2b31da231ef3..31f05f467810 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -487,10 +487,30 @@ static void arm_spe__prep_branch_stack(struct arm_spe_queue *speq) bstack->hw_idx = -1ULL; } -static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type) +static int arm_spe__inject_event(struct arm_spe *spe, union perf_event *event, + struct perf_sample *sample, u64 type) { - event->header.size = perf_event__sample_event_size(sample, type, 0); - return perf_event__synthesize_sample(event, type, 0, sample); + struct evsel *evsel = sample->evsel; + u64 branch_sample_type = 0; + size_t sz; + + if (!evsel && spe->session && spe->session->evlist) + evsel = evlist__id2evsel(spe->session->evlist, sample->id); + + if (evsel) + branch_sample_type = evsel->core.attr.branch_sample_type; + + event->header.type = PERF_RECORD_SAMPLE; + sz = perf_event__sample_event_size(sample, type, /*read_format=*/0, + branch_sample_type); + if (sz >= PERF_SAMPLE_MAX_SIZE) { + pr_err("Sample size %zu exceeds max size %d\n", sz, PERF_SAMPLE_MAX_SIZE); + return -EFAULT; + } + event->header.size = sz; + + return perf_event__synthesize_sample(event, type, /*read_format=*/0, + branch_sample_type, sample); } static inline int @@ -502,7 +522,7 @@ arm_spe_deliver_synth_event(struct arm_spe *spe, int ret; if (spe->synth_opts.inject) { - ret = arm_spe__inject_event(event, sample, spe->sample_type); + ret = arm_spe__inject_event(spe, event, sample, spe->sample_type); if (ret) return ret; } diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 8a639d2e51a4..6ec48de29441 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -1422,11 +1422,29 @@ static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq, bs->nr += 1; } -static int cs_etm__inject_event(union perf_event *event, +static int cs_etm__inject_event(struct cs_etm_auxtrace *etm, union perf_event *event, struct perf_sample *sample, u64 type) { - event->header.size = perf_event__sample_event_size(sample, type, 0); - return perf_event__synthesize_sample(event, type, 0, sample); + struct evsel *evsel = sample->evsel; + u64 branch_sample_type = 0; + size_t sz; + + if (!evsel && etm->session && etm->session->evlist) + evsel = evlist__id2evsel(etm->session->evlist, sample->id); + + if (evsel) + branch_sample_type = evsel->core.attr.branch_sample_type; + + sz = perf_event__sample_event_size(sample, type, /*read_format=*/0, + branch_sample_type); + if (sz >= PERF_SAMPLE_MAX_SIZE) { + pr_err("Sample size %zu exceeds max size %d\n", sz, PERF_SAMPLE_MAX_SIZE); + return -EFAULT; + } + event->header.size = sz; + + return perf_event__synthesize_sample(event, type, /*read_format=*/0, + branch_sample_type, sample); } @@ -1592,7 +1610,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq, sample.branch_stack = tidq->last_branch; if (etm->synth_opts.inject) { - ret = cs_etm__inject_event(event, &sample, + ret = cs_etm__inject_event(etm, event, &sample, etm->instructions_sample_type); if (ret) return ret; @@ -1667,7 +1685,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, } if (etm->synth_opts.inject) { - ret = cs_etm__inject_event(event, &sample, + ret = cs_etm__inject_event(etm, event, &sample, etm->branches_sample_type); if (ret) return ret; diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index 382255393fb3..0b18ebd13f7c 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c @@ -303,7 +303,8 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq, event.sample.header.size = bts->branches_event_size; ret = perf_event__synthesize_sample(&event, bts->branches_sample_type, - 0, &sample); + /*read_format=*/0, /*branch_sample_type=*/0, + &sample); if (ret) return ret; } diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index fc9eec8b54b8..dd2637678b40 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -1728,11 +1728,30 @@ static void intel_pt_prep_b_sample(struct intel_pt *pt, event->sample.header.misc = sample->cpumode; } -static int intel_pt_inject_event(union perf_event *event, +static int intel_pt_inject_event(struct intel_pt *pt, union perf_event *event, struct perf_sample *sample, u64 type) { - event->header.size = perf_event__sample_event_size(sample, type, 0); - return perf_event__synthesize_sample(event, type, 0, sample); + struct evsel *evsel = sample->evsel; + u64 branch_sample_type = 0; + size_t sz; + + if (!evsel && pt->session && pt->session->evlist) + evsel = evlist__id2evsel(pt->session->evlist, sample->id); + + if (evsel) + branch_sample_type = evsel->core.attr.branch_sample_type; + + event->header.type = PERF_RECORD_SAMPLE; + sz = perf_event__sample_event_size(sample, type, /*read_format=*/0, + branch_sample_type); + if (sz >= PERF_SAMPLE_MAX_SIZE) { + pr_err("Sample size %zu exceeds max size %d\n", sz, PERF_SAMPLE_MAX_SIZE); + return -EFAULT; + } + event->header.size = sz; + + return perf_event__synthesize_sample(event, type, /*read_format=*/0, + branch_sample_type, sample); } static inline int intel_pt_opt_inject(struct intel_pt *pt, @@ -1742,7 +1761,7 @@ static inline int intel_pt_opt_inject(struct intel_pt *pt, if (!pt->synth_opts.inject) return 0; - return intel_pt_inject_event(event, sample, type); + return intel_pt_inject_event(pt, event, sample, type); } static int intel_pt_deliver_synth_event(struct intel_pt *pt, diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index 85bee747f4cd..2461f25a4d7d 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -1455,7 +1455,8 @@ int perf_event__synthesize_stat_round(const struct perf_tool *tool, return process(tool, (union perf_event *) &event, NULL, machine); } -size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, u64 read_format) +size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, u64 read_format, + u64 branch_sample_type) { size_t sz, result = sizeof(struct perf_record_sample); @@ -1515,8 +1516,10 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, if (type & PERF_SAMPLE_BRANCH_STACK) { sz = sample->branch_stack->nr * sizeof(struct branch_entry); - /* nr, hw_idx */ - sz += 2 * sizeof(u64); + /* nr */ + sz += sizeof(u64); + if (branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX) + sz += sizeof(u64); result += sz; } @@ -1605,7 +1608,7 @@ static __u64 *copy_read_group_values(__u64 *array, __u64 read_format, } int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format, - const struct perf_sample *sample) + u64 branch_sample_type, const struct perf_sample *sample) { __u64 *array; size_t sz; @@ -1719,9 +1722,17 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_fo if (type & PERF_SAMPLE_BRANCH_STACK) { sz = sample->branch_stack->nr * sizeof(struct branch_entry); - /* nr, hw_idx */ - sz += 2 * sizeof(u64); - memcpy(array, sample->branch_stack, sz); + + *array++ = sample->branch_stack->nr; + + if (branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX) { + if (sample->no_hw_idx) + *array++ = 0; + else + *array++ = sample->branch_stack->hw_idx; + } + + memcpy(array, perf_sample__branch_entries((struct perf_sample *)sample), sz); array = (void *)array + sz; } diff --git a/tools/perf/util/synthetic-events.h b/tools/perf/util/synthetic-events.h index b0edad0c3100..8c7f49f9ccf5 100644 --- a/tools/perf/util/synthetic-events.h +++ b/tools/perf/util/synthetic-events.h @@ -81,7 +81,8 @@ int perf_event__synthesize_mmap_events(const struct perf_tool *tool, union perf_ int perf_event__synthesize_modules(const struct perf_tool *tool, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_namespaces(const struct perf_tool *tool, union perf_event *event, pid_t pid, pid_t tgid, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_cgroups(const struct perf_tool *tool, perf_event__handler_t process, struct machine *machine); -int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format, const struct perf_sample *sample); +int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format, + u64 branch_sample_type, const struct perf_sample *sample); int perf_event__synthesize_stat_config(const struct perf_tool *tool, struct perf_stat_config *config, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_stat_events(struct perf_stat_config *config, const struct perf_tool *tool, struct evlist *evlist, perf_event__handler_t process, bool attrs); int perf_event__synthesize_stat_round(const struct perf_tool *tool, u64 time, u64 type, perf_event__handler_t process, struct machine *machine); @@ -97,7 +98,8 @@ void perf_event__synthesize_final_bpf_metadata(struct perf_session *session, int perf_tool__process_synth_event(const struct perf_tool *tool, union perf_event *event, struct machine *machine, perf_event__handler_t process); -size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, u64 read_format); +size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, + u64 read_format, u64 branch_sample_type); int __machine__synthesize_threads(struct machine *machine, const struct perf_tool *tool, struct target *target, struct perf_thread_map *threads, From daac18e7c42c012e289bfd310503f9417e4a9481 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 15:43:25 -0700 Subject: [PATCH 043/343] perf inject: Fix itrace branch stack synthesis When using "perf inject --itrace=L" to synthesize branch stacks from AUX data, several issues caused failures with the generated file: 1. The synthesized samples were delivered without the PERF_SAMPLE_BRANCH_STACK flag if it was not in the original event's sample_type. Fixed by using sample_type | evsel->synth_sample_type in intel_pt_do_synth_pebs_sample. 2. Modifying evsel->core.attr.sample_type early in __cmd_inject caused parse failures for subsequent records in the input file. Fixed by moving this modification to just before writing the header. 3. perf_event__repipe_sample was narrowed to only synthesize samples when branch stack injection was requested, and restored the use of perf_inject__cut_auxtrace_sample as a fallback to preserve functionality. 4. Potential Heap Overflow in perf_event__repipe_sample: Addressed by adding a check that prints an error and returns -EFAULT if the calculated event size exceeds PERF_SAMPLE_MAX_SIZE. 5. Header vs Payload Mismatch in __cmd_inject: Addressed by narrowing the condition so that HEADER_BRANCH_STACK is only set in the file header if add_last_branch was true. 6. NULL Pointer Dereference in intel-pt.c: When branch stack injection is requested (add_last_branch is true) but last_branch is false (e.g., perf inject --itrace=L), ptq->last_branch was not allocated. However, PEBS branch stack synthesis (via synth_sample_type) still forced LBR handling in do_synth_pebs_sample(), dereferencing the NULL ptq->last_branch pointer. Guarding the dereference is not sufficient because downstream sample size calculation and synthesis strictly require a non-NULL branch_stack when the bit is set. Fixed by ensuring ptq->last_branch is allocated in intel_pt_alloc_queue() when add_last_branch is requested. 7. Modifying event attributes in perf_event__repipe_attr in-place caused SIGSEGV on read-only mmap buffers in file mode and downstream parser breakage in pipe mode. Fixed by processing the unmodified attribute first, returning immediately in non-pipe mode, and correctly synthesizing a new attribute event for pipe output using perf_event__synthesize_attr. Also: - Added a size validation check and integer underflow protection when parsing n_ids. - Prevented Trailing ID memory corruption by zero-initializing the local attr copy and safely copying using min_t(size_t, sizeof(attr), event->attr.attr.size). - Resolved ID array parsing mismatch downstream by expanding attr.size to sizeof(struct perf_event_attr) before synthesis to guarantee perfect header/attribute size alignment. 8. Potential dangling pointer vulnerability in perf_event__repipe_sample: Addressed by restoring the original sample->branch_stack pointer before returning, including on early error return paths. 9. Off-by-one error in sample size check in perf_event__repipe_sample: Fixed by checking if sz >= PERF_SAMPLE_MAX_SIZE instead of >. 10. Unadvertised size field left in payload by cut_auxtrace_sample: Addressed by excluding the 8-byte size field from the copied payload to correctly match the cleared PERF_SAMPLE_AUX bit. Cut the AUX sample payload even if size is 0. 11. Inaccurate sample size calculation and uninitialized memory leaks in convert_sample_callchain: Fixed by replacing manual arithmetic with perf_event__sample_event_size and adding a bounds check against PERF_SAMPLE_MAX_SIZE. 12. Omission of branch_sample_type in file headers: Addressed by expanding older, smaller attributes to PERF_ATTR_SIZE_VER2 in __cmd_inject to ensure branch_sample_type is not silently omitted. Fixes: 0f0aa5e0693ce400 ("perf inject: Add Instruction Tracing support") Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Dapeng Mi Cc: Ingo Molnar Cc: James Clark Cc: Leo Yan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 153 ++++++++++++++++++++++++++++++++---- tools/perf/util/intel-pt.c | 8 +- 2 files changed, 142 insertions(+), 19 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 2f20e782c7f2..7a64935b7e2b 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -216,12 +216,23 @@ static int perf_event__repipe_op4_synth(const struct perf_tool *tool, return perf_event__repipe_synth(tool, event); } +static int perf_event__repipe_synth_cb(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) +{ + return perf_event__repipe_synth(tool, event); +} + static int perf_event__repipe_attr(const struct perf_tool *tool, union perf_event *event, struct evlist **pevlist) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); + struct perf_event_attr attr; + size_t n_ids; + u64 *ids; int ret; ret = perf_event__process_attr(tool, event, pevlist); @@ -232,7 +243,37 @@ static int perf_event__repipe_attr(const struct perf_tool *tool, if (!inject->output.is_pipe) return 0; - return perf_event__repipe_synth(tool, event); + if (!inject->itrace_synth_opts.set) + return perf_event__repipe_synth(tool, event); + + if (event->header.size < sizeof(struct perf_event_header) + sizeof(u64)) { + pr_err("Attribute event size %u is too small\n", event->header.size); + return -EINVAL; + } + + if (event->header.size - sizeof(event->header) < event->attr.attr.size) { + pr_err("Attribute event size %u is too small for attr.size %u\n", + event->header.size, event->attr.attr.size); + return -EINVAL; + } + + memset(&attr, 0, sizeof(attr)); + memcpy(&attr, &event->attr.attr, + min_t(size_t, sizeof(attr), (size_t)event->attr.attr.size)); + + n_ids = event->header.size - sizeof(event->header) - event->attr.attr.size; + n_ids /= sizeof(u64); + ids = perf_record_header_attr_id(event); + + attr.size = sizeof(struct perf_event_attr); + attr.sample_type &= ~PERF_SAMPLE_AUX; + + if (inject->itrace_synth_opts.add_last_branch) { + attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; + attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX; + } + return perf_event__synthesize_attr(tool, &attr, (u32)n_ids, ids, + perf_event__repipe_synth_cb); } static int perf_event__repipe_event_update(const struct perf_tool *tool, @@ -331,8 +372,8 @@ perf_inject__cut_auxtrace_sample(struct perf_inject *inject, union perf_event *event, struct perf_sample *sample) { - size_t sz1 = sample->aux_sample.data - (void *)event; - size_t sz2 = event->header.size - sample->aux_sample.size - sz1; + size_t sz1 = sample->aux_sample.data - (void *)event - sizeof(u64); + size_t sz2 = event->header.size - sample->aux_sample.size - (sz1 + sizeof(u64)); union perf_event *ev; if (inject->event_copy == NULL) { @@ -343,13 +384,12 @@ perf_inject__cut_auxtrace_sample(struct perf_inject *inject, ev = (union perf_event *)inject->event_copy; if (sz1 > event->header.size || sz2 > event->header.size || sz1 + sz2 > event->header.size || - sz1 < sizeof(struct perf_event_header) + sizeof(u64)) + sz1 < sizeof(struct perf_event_header)) return event; memcpy(ev, event, sz1); memcpy((void *)ev + sz1, (void *)event + event->header.size - sz2, sz2); ev->header.size = sz1 + sz2; - ((u64 *)((void *)ev + sz1))[-1] = 0; return ev; } @@ -369,14 +409,77 @@ static int perf_event__repipe_sample(const struct perf_tool *tool, struct perf_inject *inject = container_of(tool, struct perf_inject, tool); - if (evsel && evsel->handler) { + if (evsel == NULL) + return perf_event__repipe_synth(tool, event); + + if (evsel->handler) { inject_handler f = evsel->handler; return f(tool, event, sample, evsel, machine); } build_id__mark_dso_hit(tool, event, sample, evsel, machine); - if (inject->itrace_synth_opts.set && sample->aux_sample.size) { + if (inject->itrace_synth_opts.set && + (inject->itrace_synth_opts.last_branch || + inject->itrace_synth_opts.add_last_branch)) { + union perf_event *event_copy = (void *)inject->event_copy; + struct branch_stack dummy_bs = { .nr = 0, .hw_idx = 0 }; + int err; + size_t sz; + u64 orig_type = evsel->core.attr.sample_type; + u64 orig_branch_type = evsel->core.attr.branch_sample_type; + + struct branch_stack *orig_bs = sample->branch_stack; + + if (event_copy == NULL) { + inject->event_copy = malloc(PERF_SAMPLE_MAX_SIZE); + if (!inject->event_copy) + return -ENOMEM; + + event_copy = (void *)inject->event_copy; + } + + if (!sample->branch_stack) + sample->branch_stack = &dummy_bs; + + if (inject->itrace_synth_opts.add_last_branch) { + /* Temporarily add in type bits for synthesis. */ + evsel->core.attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; + evsel->core.attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX; + } + evsel->core.attr.sample_type &= ~PERF_SAMPLE_AUX; + + sz = perf_event__sample_event_size(sample, evsel->core.attr.sample_type, + evsel->core.attr.read_format, + evsel->core.attr.branch_sample_type); + + if (sz >= PERF_SAMPLE_MAX_SIZE) { + pr_err("Sample size %zu exceeds max size %d\n", sz, PERF_SAMPLE_MAX_SIZE); + evsel->core.attr.sample_type = orig_type; + evsel->core.attr.branch_sample_type = orig_branch_type; + sample->branch_stack = orig_bs; + return -EFAULT; + } + + event_copy->header.type = PERF_RECORD_SAMPLE; + event_copy->header.misc = event->header.misc; + event_copy->header.size = sz; + + err = perf_event__synthesize_sample(event_copy, evsel->core.attr.sample_type, + evsel->core.attr.read_format, + evsel->core.attr.branch_sample_type, sample); + + evsel->core.attr.sample_type = orig_type; + evsel->core.attr.branch_sample_type = orig_branch_type; + sample->branch_stack = orig_bs; + + if (err) { + pr_err("Failed to synthesize sample\n"); + return err; + } + event = event_copy; + } else if (inject->itrace_synth_opts.set && + (evsel->core.attr.sample_type & PERF_SAMPLE_AUX)) { event = perf_inject__cut_auxtrace_sample(inject, event, sample); if (IS_ERR(event)) return PTR_ERR(event); @@ -397,7 +500,7 @@ static int perf_event__convert_sample_callchain(const struct perf_tool *tool, struct callchain_cursor_node *node; struct thread *thread; u64 sample_type = evsel->core.attr.sample_type; - u32 sample_size = event->header.size; + size_t sz; u64 i, k; int ret; @@ -456,15 +559,18 @@ static int perf_event__convert_sample_callchain(const struct perf_tool *tool, out: memcpy(event_copy, event, sizeof(event->header)); - /* adjust sample size for stack and regs */ - sample_size -= sample->user_stack.size; - sample_size -= (hweight64(evsel->core.attr.sample_regs_user) + 1) * sizeof(u64); - sample_size += (sample->callchain->nr + 1) * sizeof(u64); - event_copy->header.size = sample_size; - /* remove sample_type {STACK,REGS}_USER for synthesize */ sample_type &= ~(PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER); + sz = perf_event__sample_event_size(sample, sample_type, + evsel->core.attr.read_format, + evsel->core.attr.branch_sample_type); + if (sz >= PERF_SAMPLE_MAX_SIZE) { + pr_err("Sample size %zu exceeds max size %d\n", sz, PERF_SAMPLE_MAX_SIZE); + return -EFAULT; + } + event_copy->header.size = sz; + ret = perf_event__synthesize_sample(event_copy, sample_type, evsel->core.attr.read_format, evsel->core.attr.branch_sample_type, sample); @@ -2442,12 +2548,27 @@ static int __cmd_inject(struct perf_inject *inject) * synthesized hardware events, so clear the feature flag. */ if (inject->itrace_synth_opts.set) { + struct evsel *evsel; + perf_header__clear_feat(&session->header, HEADER_AUXTRACE); - if (inject->itrace_synth_opts.last_branch || - inject->itrace_synth_opts.add_last_branch) + + evlist__for_each_entry(session->evlist, evsel) { + evsel->core.attr.sample_type &= ~PERF_SAMPLE_AUX; + } + + if (inject->itrace_synth_opts.add_last_branch) { perf_header__set_feat(&session->header, HEADER_BRANCH_STACK); + + evlist__for_each_entry(session->evlist, evsel) { + evsel->core.attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; + if (evsel->core.attr.size < PERF_ATTR_SIZE_VER2) + evsel->core.attr.size = PERF_ATTR_SIZE_VER2; + evsel->core.attr.branch_sample_type |= + PERF_SAMPLE_BRANCH_HW_INDEX; + } + } } /* diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index dd2637678b40..d9c86ac49748 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -1307,7 +1307,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, goto out_free; } - if (pt->synth_opts.last_branch || pt->synth_opts.other_events) { + if (pt->synth_opts.last_branch || pt->synth_opts.add_last_branch || + pt->synth_opts.other_events) { unsigned int entry_cnt = max(LBRS_MAX, pt->br_stack_sz); ptq->last_branch = intel_pt_alloc_br_stack(entry_cnt); @@ -2505,7 +2506,7 @@ static int intel_pt_do_synth_pebs_sample(struct intel_pt_queue *ptq, struct evse intel_pt_add_xmm(intr_regs, pos, items, regs_mask); } - if (sample_type & PERF_SAMPLE_BRANCH_STACK) { + if ((sample_type | evsel->synth_sample_type) & PERF_SAMPLE_BRANCH_STACK) { if (items->mask[INTEL_PT_LBR_0_POS] || items->mask[INTEL_PT_LBR_1_POS] || items->mask[INTEL_PT_LBR_2_POS]) { @@ -2576,7 +2577,8 @@ static int intel_pt_do_synth_pebs_sample(struct intel_pt_queue *ptq, struct evse sample.transaction = txn; } - ret = intel_pt_deliver_synth_event(pt, event, &sample, sample_type); + ret = intel_pt_deliver_synth_event(pt, event, &sample, + sample_type | evsel->synth_sample_type); perf_sample__exit(&sample); return ret; } From fc444d05b4e4bfa4aaec4efa1365c0be134fc3c8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:07 -0700 Subject: [PATCH 044/343] perf tool: Remove evsel from tool APIs that pass the sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from tool-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze [ Fixed up conflict with "perf inject: Fix itrace branch stack synthesis" series ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 3 +-- tools/perf/builtin-c2c.c | 2 +- tools/perf/builtin-diff.c | 2 +- tools/perf/builtin-inject.c | 19 ++++++--------- tools/perf/builtin-kmem.c | 2 +- tools/perf/builtin-kvm.c | 5 ++-- tools/perf/builtin-kwork.c | 2 +- tools/perf/builtin-lock.c | 2 +- tools/perf/builtin-mem.c | 1 - tools/perf/builtin-record.c | 3 +-- tools/perf/builtin-report.c | 10 +++----- tools/perf/builtin-sched.c | 4 +-- tools/perf/builtin-script.c | 4 +-- tools/perf/builtin-timechart.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/util/build-id.c | 3 +-- tools/perf/util/build-id.h | 7 +----- tools/perf/util/data-convert-bt.c | 2 +- tools/perf/util/data-convert-json.c | 5 ++-- tools/perf/util/intel-tpebs.c | 3 +-- tools/perf/util/jitdump.c | 2 +- tools/perf/util/session.c | 38 ++++++++++++++--------------- tools/perf/util/tool.c | 4 +-- tools/perf/util/tool.h | 4 +-- 24 files changed, 55 insertions(+), 76 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 5e57b78548f4..58e56f826367 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -283,7 +283,6 @@ static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample, static int process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool); @@ -302,7 +301,7 @@ static int process_sample_event(const struct perf_tool *tool, goto out_put; if (!al.filtered && - evsel__add_sample(evsel, sample, &al, ann, machine)) { + evsel__add_sample(sample->evsel, sample, &al, ann, machine)) { pr_warning("problem incrementing symbol count, " "skipping event\n"); ret = -1; diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 72a7802775ee..7593e5908fcc 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -314,9 +314,9 @@ static void perf_c2c__evsel_hists_inc_stats(struct evsel *evsel, static int process_sample_event(const struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { + struct evsel *evsel = sample->evsel; struct c2c_hists *c2c_hists = &c2c.hists; struct c2c_hist_entry *c2c_he; struct c2c_stats stats = { .nr_entries = 0, }; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 1b3df868849a..82e9e514922b 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -390,11 +390,11 @@ static struct hist_entry_ops block_hist_ops = { static int diff__process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct perf_diff *pdiff = container_of(tool, struct perf_diff, tool); struct addr_location al; + struct evsel *evsel = sample->evsel; struct hists *hists = evsel__hists(evsel); struct hist_entry_iter iter = { .evsel = evsel, diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 7a64935b7e2b..e8cf8d399528 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -403,11 +403,10 @@ typedef int (*inject_handler)(const struct perf_tool *tool, static int perf_event__repipe_sample(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { - struct perf_inject *inject = container_of(tool, struct perf_inject, - tool); + struct perf_inject *inject = container_of(tool, struct perf_inject, tool); + struct evsel *evsel = sample->evsel; if (evsel == NULL) return perf_event__repipe_synth(tool, event); @@ -417,7 +416,7 @@ static int perf_event__repipe_sample(const struct perf_tool *tool, return f(tool, event, sample, evsel, machine); } - build_id__mark_dso_hit(tool, event, sample, evsel, machine); + build_id__mark_dso_hit(tool, event, sample, machine); if (inject->itrace_synth_opts.set && (inject->itrace_synth_opts.last_branch || @@ -491,10 +490,10 @@ static int perf_event__repipe_sample(const struct perf_tool *tool, static int perf_event__convert_sample_callchain(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); + struct evsel *evsel = sample->evsel; struct callchain_cursor *cursor = get_tls_callchain_cursor(); union perf_event *event_copy = (void *)inject->event_copy; struct callchain_cursor_node *node; @@ -1100,10 +1099,8 @@ static int mark_dso_hit_callback(struct callchain_cursor_node *node, void *data) args->mmap_evsel, map, /*sample_in_dso=*/false); } -int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample, - struct evsel *evsel __maybe_unused, - struct machine *machine) +static int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *event, + struct perf_sample *sample, struct machine *machine) { struct addr_location al; struct thread *thread; @@ -1133,7 +1130,7 @@ int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *e /*sample_in_dso=*/true); } - sample__for_each_callchain_node(thread, evsel, sample, PERF_MAX_STACK_DEPTH, + sample__for_each_callchain_node(thread, sample->evsel, sample, PERF_MAX_STACK_DEPTH, /*symbols=*/false, mark_dso_hit_callback, &args); thread__put(thread); repipe: @@ -1215,7 +1212,7 @@ static int perf_inject__sched_stat(const struct perf_tool *tool, perf_event__synthesize_sample(event_sw, evsel->core.attr.sample_type, evsel->core.attr.read_format, evsel->core.attr.branch_sample_type, &sample_sw); - build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine); + build_id__mark_dso_hit(tool, event_sw, &sample_sw, machine); ret = perf_event__repipe(tool, event_sw, &sample_sw, machine); perf_sample__exit(&sample_sw); return ret; diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 9c64a0d74823..45b383fa9ce9 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -960,9 +960,9 @@ typedef int (*tracepoint_handler)(struct evsel *evsel, static int process_sample_event(const struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { + struct evsel *evsel = sample->evsel; int err = 0; struct thread *thread = machine__findnew_thread(machine, sample->pid, sample->tid); diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 0c5e6b3aac74..5e8e6fde097a 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -941,9 +941,9 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread, static bool handle_kvm_event(struct perf_kvm_stat *kvm, struct thread *thread, - struct evsel *evsel, struct perf_sample *sample) { + struct evsel *evsel = sample->evsel; struct vcpu_event_record *vcpu_record; struct event_key key = { .key = INVALID_KEY, .exit_reasons = kvm->exit_reasons }; @@ -1133,7 +1133,6 @@ static bool skip_sample(struct perf_kvm_stat *kvm, static int process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { int err = 0; @@ -1156,7 +1155,7 @@ static int process_sample_event(const struct perf_tool *tool, return -1; } - if (!handle_kvm_event(kvm, thread, evsel, sample)) + if (!handle_kvm_event(kvm, thread, sample)) err = -1; thread__put(thread); diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index 9d3a4c779a41..d4bb19ed91b5 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -1955,9 +1955,9 @@ typedef int (*tracepoint_handler)(const struct perf_tool *tool, static int perf_kwork__process_tracepoint_sample(const struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { + struct evsel *evsel = sample->evsel; int err = 0; if (evsel->handler != NULL) { diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 5585aeb97684..4d8ddf6391e8 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -1430,9 +1430,9 @@ typedef int (*tracepoint_handler)(struct evsel *evsel, static int process_sample_event(const struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { + struct evsel *evsel = sample->evsel; int err = 0; struct thread *thread = machine__findnew_thread(machine, sample->pid, sample->tid); diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index d43500b92a7b..6101a26b3a78 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -255,7 +255,6 @@ dump_raw_samples(const struct perf_tool *tool, static int process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel __maybe_unused, struct machine *machine) { return dump_raw_samples(tool, event, sample, machine); diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 272bba7f4b9e..cc601796b2c8 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1490,7 +1490,6 @@ static void set_timestamp_boundary(struct record *rec, u64 sample_time) static int process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct record *rec = container_of(tool, struct record, tool); @@ -1501,7 +1500,7 @@ static int process_sample_event(const struct perf_tool *tool, return 0; rec->samples++; - return build_id__mark_dso_hit(tool, event, sample, evsel, machine); + return build_id__mark_dso_hit(tool, event, sample, machine); } static int process_buildids(struct record *rec) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 0b0966d94128..9955ce8cce00 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -265,10 +265,10 @@ static int process_feature_event(const struct perf_tool *tool, static int process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct report *rep = container_of(tool, struct report, tool); + struct evsel *evsel = sample->evsel; struct addr_location al; struct hist_entry_iter iter = { .evsel = evsel, @@ -345,7 +345,6 @@ static int process_sample_event(const struct perf_tool *tool, static int process_read_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, - struct evsel *evsel, struct machine *machine __maybe_unused) { struct report *rep = container_of(tool, struct report, tool); @@ -353,7 +352,7 @@ static int process_read_event(const struct perf_tool *tool, if (rep->show_threads) { int err = perf_read_values_add_value(&rep->show_threads_values, event->read.pid, event->read.tid, - evsel, + sample->evsel, event->read.value); if (err) @@ -779,11 +778,10 @@ static void report__output_resort(struct report *rep) static int count_sample_event(const struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, - struct perf_sample *sample __maybe_unused, - struct evsel *evsel, + struct perf_sample *sample, struct machine *machine __maybe_unused) { - struct hists *hists = evsel__hists(evsel); + struct hists *hists = evsel__hists(sample->evsel); hists__inc_nr_events(hists); return 0; diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 53a93aa18853..2950c5c3026e 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1867,9 +1867,9 @@ typedef int (*tracepoint_handler)(const struct perf_tool *tool, static int perf_sched__process_tracepoint_sample(const struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { + struct evsel *evsel = sample->evsel; int err = 0; if (evsel->handler != NULL) { @@ -3184,10 +3184,10 @@ typedef int (*sched_handler)(const struct perf_tool *tool, static int perf_timehist__process_sample(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + struct evsel *evsel = sample->evsel; int err = 0; struct perf_cpu this_cpu = { .cpu = sample->cpu, diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index fd0b4609516b..d4e8f49a8751 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2646,10 +2646,10 @@ static bool filter_cpu(struct perf_sample *sample) static int process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct perf_script *scr = container_of(tool, struct perf_script, tool); + struct evsel *evsel = sample->evsel; struct addr_location al; struct addr_location addr_al; int ret = 0; @@ -2730,10 +2730,10 @@ static int process_sample_event(const struct perf_tool *tool, static int process_deferred_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct perf_script *scr = container_of(tool, struct perf_script, tool); + struct evsel *evsel = sample->evsel; struct perf_event_attr *attr = &evsel->core.attr; struct evsel_script *es = evsel->priv; unsigned int type = output_type(attr->type); diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 28f33e39895d..8692d11ccd29 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -574,10 +574,10 @@ typedef int (*tracepoint_handler)(struct timechart *tchart, static int process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct timechart *tchart = container_of(tool, struct timechart, tool); + struct evsel *evsel = sample->evsel; if (evsel->core.attr.sample_type & PERF_SAMPLE_TIME) { if (!tchart->first_time || tchart->first_time > sample->time) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index e9cc870a5acd..1aafa77f72cf 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3501,10 +3501,10 @@ static void trace__set_base_time(struct trace *trace, static int trace__process_sample(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine __maybe_unused) { struct trace *trace = container_of(tool, struct trace, tool); + struct evsel *evsel = sample->evsel; struct thread *thread; int err = 0; diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index fdb35133fde4..55b72235f891 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -55,7 +55,6 @@ static int mark_dso_hit_callback(struct callchain_cursor_node *node, void *data int build_id__mark_dso_hit(const struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct addr_location al; @@ -74,7 +73,7 @@ int build_id__mark_dso_hit(const struct perf_tool *tool __maybe_unused, addr_location__exit(&al); - sample__for_each_callchain_node(thread, evsel, sample, PERF_MAX_STACK_DEPTH, + sample__for_each_callchain_node(thread, sample->evsel, sample, PERF_MAX_STACK_DEPTH, /*symbols=*/false, mark_dso_hit_callback, /*data=*/NULL); diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 47e621cebe1b..73bad90b06f9 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h @@ -34,12 +34,7 @@ char *__dso__build_id_filename(const struct dso *dso, char *bf, size_t size, bool is_debug, bool is_kallsyms); int build_id__mark_dso_hit(const struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample, struct evsel *evsel, - struct machine *machine); - -int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample, struct evsel *evsel, - struct machine *machine); + struct perf_sample *sample, struct machine *machine); bool perf_session__read_build_ids(struct perf_session *session, bool with_hits); int perf_session__write_buildid_table(struct perf_session *session, diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 3b8f2df823a9..b3f745cff2a7 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -803,10 +803,10 @@ static bool is_flush_needed(struct ctf_stream *cs) static int process_sample_event(const struct perf_tool *tool, union perf_event *_event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine __maybe_unused) { struct convert *c = container_of(tool, struct convert, tool); + struct evsel *evsel = sample->evsel; struct evsel_priv *priv = evsel->priv; struct ctf_writer *cw = &c->writer; struct ctf_stream *cs; diff --git a/tools/perf/util/data-convert-json.c b/tools/perf/util/data-convert-json.c index d526c91312ed..a7da93a7ff0e 100644 --- a/tools/perf/util/data-convert-json.c +++ b/tools/perf/util/data-convert-json.c @@ -159,13 +159,12 @@ static void output_sample_callchain_entry(const struct perf_tool *tool, static int process_sample_event(const struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, - struct evsel *evsel __maybe_unused, struct machine *machine) { struct convert_json *c = container_of(tool, struct convert_json, tool); FILE *out = c->out; struct addr_location al; - u64 sample_type = __evlist__combined_sample_type(evsel->evlist); + u64 sample_type = __evlist__combined_sample_type(sample->evsel->evlist); u8 cpumode = PERF_RECORD_MISC_USER; addr_location__init(&al); @@ -245,7 +244,7 @@ static int process_sample_event(const struct perf_tool *tool, #ifdef HAVE_LIBTRACEEVENT if (sample->raw_data) { - struct tep_event *tp_format = evsel__tp_format(evsel); + struct tep_event *tp_format = evsel__tp_format(sample->evsel); struct tep_format_field **fields = tp_format ? tep_event_fields(tp_format) : NULL; if (fields) { diff --git a/tools/perf/util/intel-tpebs.c b/tools/perf/util/intel-tpebs.c index 8b615dc94e9e..ed8cfe2ba2fa 100644 --- a/tools/perf/util/intel-tpebs.c +++ b/tools/perf/util/intel-tpebs.c @@ -185,7 +185,6 @@ static bool should_ignore_sample(const struct perf_sample *sample, const struct static int process_sample_event(const struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine __maybe_unused) { struct tpebs_retire_lat *t; @@ -196,7 +195,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, mutex_unlock(tpebs_mtx_get()); return 0; } - t = tpebs_retire_lat__find(evsel); + t = tpebs_retire_lat__find(sample->evsel); if (!t) { mutex_unlock(tpebs_mtx_get()); return -EINVAL; diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index e0ce8b904729..52e6ffac2b3e 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -642,7 +642,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) ret = jit_inject_event(jd, event); if (!ret) - build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine); + build_id__mark_dso_hit(tool, event, &sample, jd->machine); out: perf_sample__exit(&sample); return ret; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index fe0de2a0277f..1e25892963b7 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1117,9 +1117,10 @@ char *get_page_size_name(u64 size, char *str) return str; } -static void dump_sample(struct machine *machine, struct evsel *evsel, union perf_event *event, +static void dump_sample(struct machine *machine, union perf_event *event, struct perf_sample *sample) { + struct evsel *evsel = sample->evsel; u64 sample_type; char str[PAGE_SIZE_NAME_LEN]; uint16_t e_machine = EM_NONE; @@ -1183,9 +1184,10 @@ static void dump_sample(struct machine *machine, struct evsel *evsel, union perf sample_read__printf(sample, evsel->core.attr.read_format); } -static void dump_deferred_callchain(struct evsel *evsel, union perf_event *event, - struct perf_sample *sample) +static void dump_deferred_callchain(union perf_event *event, struct perf_sample *sample) { + struct evsel *evsel = sample->evsel; + if (!dump_trace) return; @@ -1291,7 +1293,7 @@ static int deliver_sample_value(struct evlist *evlist, return 0; sample->evsel = container_of(sid->evsel, struct evsel, core); - ret = tool->sample(tool, event, sample, sample->evsel, machine); + ret = tool->sample(tool, event, sample, machine); sample->evsel = saved_evsel; return ret; } @@ -1323,8 +1325,9 @@ static int deliver_sample_group(struct evlist *evlist, static int evlist__deliver_sample(struct evlist *evlist, const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) + struct machine *machine) { + struct evsel *evsel = sample->evsel; /* We know evsel != NULL. */ u64 sample_type = evsel->core.attr.sample_type; u64 read_format = evsel->core.attr.read_format; @@ -1332,7 +1335,7 @@ static int evlist__deliver_sample(struct evlist *evlist, const struct perf_tool /* Standard sample delivery. */ if (!(sample_type & PERF_SAMPLE_READ)) - return tool->sample(tool, event, sample, evsel, machine); + return tool->sample(tool, event, sample, machine); /* For PERF_SAMPLE_READ we have either single or group mode. */ if (read_format & PERF_FORMAT_GROUP) @@ -1371,8 +1374,7 @@ static int evlist__deliver_deferred_callchain(struct evlist *evlist, struct evsel *saved_evsel = sample->evsel; sample->evsel = evlist__id2evsel(evlist, sample->id); - ret = tool->callchain_deferred(tool, event, sample, - sample->evsel, machine); + ret = tool->callchain_deferred(tool, event, sample, machine); sample->evsel = saved_evsel; return ret; } @@ -1400,7 +1402,7 @@ static int evlist__deliver_deferred_callchain(struct evlist *evlist, orig_sample.evsel = evlist__id2evsel(evlist, orig_sample.id); ret = evlist__deliver_sample(evlist, tool, de->event, - &orig_sample, orig_sample.evsel, machine); + &orig_sample, machine); perf_sample__exit(&orig_sample); list_del(&de->list); @@ -1438,7 +1440,7 @@ static int session__flush_deferred_samples(struct perf_session *session, sample.evsel = evlist__id2evsel(evlist, sample.id); ret = evlist__deliver_sample(evlist, tool, de->event, - &sample, sample.evsel, machine); + &sample, machine); perf_sample__exit(&sample); list_del(&de->list); @@ -1458,7 +1460,6 @@ static int machines__deliver_event(struct machines *machines, const struct perf_tool *tool, u64 file_offset, const char *file_path) { - struct evsel *evsel; struct machine *machine; dump_event(evlist, event, file_offset, sample, file_path); @@ -1468,21 +1469,20 @@ static int machines__deliver_event(struct machines *machines, else assert(sample->evsel == evlist__id2evsel(evlist, sample->id)); - evsel = sample->evsel; machine = machines__find_for_cpumode(machines, event, sample); switch (event->header.type) { case PERF_RECORD_SAMPLE: - if (evsel == NULL) { + if (sample->evsel == NULL) { ++evlist->stats.nr_unknown_id; return 0; } if (machine == NULL) { ++evlist->stats.nr_unprocessable_samples; - dump_sample(machine, evsel, event, sample); + dump_sample(machine, event, sample); return 0; } - dump_sample(machine, evsel, event, sample); + dump_sample(machine, event, sample); if (sample->deferred_callchain && tool->merge_deferred_callchains) { struct deferred_event *de = malloc(sizeof(*de)); size_t sz = event->header.size; @@ -1499,7 +1499,7 @@ static int machines__deliver_event(struct machines *machines, list_add_tail(&de->list, &evlist->deferred_samples); return 0; } - return evlist__deliver_sample(evlist, tool, event, sample, evsel, machine); + return evlist__deliver_sample(evlist, tool, event, sample, machine); case PERF_RECORD_MMAP: return tool->mmap(tool, event, sample, machine); case PERF_RECORD_MMAP2: @@ -1527,8 +1527,8 @@ static int machines__deliver_event(struct machines *machines, evlist->stats.total_lost_samples += event->lost_samples.lost; return tool->lost_samples(tool, event, sample, machine); case PERF_RECORD_READ: - dump_read(evsel, event); - return tool->read(tool, event, sample, evsel, machine); + dump_read(sample->evsel, event); + return tool->read(tool, event, sample, machine); case PERF_RECORD_THROTTLE: return tool->throttle(tool, event, sample, machine); case PERF_RECORD_UNTHROTTLE: @@ -1557,7 +1557,7 @@ static int machines__deliver_event(struct machines *machines, case PERF_RECORD_AUX_OUTPUT_HW_ID: return tool->aux_output_hw_id(tool, event, sample, machine); case PERF_RECORD_CALLCHAIN_DEFERRED: - dump_deferred_callchain(evsel, event, sample); + dump_deferred_callchain(event, sample); return evlist__deliver_deferred_callchain(evlist, tool, event, sample, machine); default: diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c index ff2150517b75..225a77d530ce 100644 --- a/tools/perf/util/tool.c +++ b/tools/perf/util/tool.c @@ -110,7 +110,6 @@ static int process_event_synth_event_update_stub(const struct perf_tool *tool __ int process_event_sample_stub(const struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, - struct evsel *evsel __maybe_unused, struct machine *machine __maybe_unused) { dump_printf(": unhandled!\n"); @@ -349,12 +348,11 @@ bool perf_tool__compressed_is_stub(const struct perf_tool *tool) static int delegate_ ## name(const struct perf_tool *tool, \ union perf_event *event, \ struct perf_sample *sample, \ - struct evsel *evsel, \ struct machine *machine) \ { \ struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); \ struct perf_tool *delegate = del_tool->delegate; \ - return delegate->name(delegate, event, sample, evsel, machine); \ + return delegate->name(delegate, event, sample, machine); \ } CREATE_DELEGATE_SAMPLE(read); CREATE_DELEGATE_SAMPLE(sample); diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 2d9a4b1ca9d0..2a4f124ffd8d 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -9,7 +9,6 @@ struct perf_session; union perf_event; struct evlist; -struct evsel; struct perf_sample; struct perf_tool; struct machine; @@ -17,7 +16,7 @@ struct ordered_events; typedef int (*event_sample)(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine); + struct machine *machine); typedef int (*event_op)(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine); @@ -103,7 +102,6 @@ bool perf_tool__compressed_is_stub(const struct perf_tool *tool); int process_event_sample_stub(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine); struct delegate_tool { From 1c8b07788618a30bd0bb6d83aeb39d07b8d57bbf Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:08 -0700 Subject: [PATCH 045/343] perf kvm: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from kvm-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 19 +++-- .../perf/util/kvm-stat-arch/kvm-stat-arm64.c | 17 +++-- .../util/kvm-stat-arch/kvm-stat-loongarch.c | 17 ++--- .../util/kvm-stat-arch/kvm-stat-powerpc.c | 17 ++--- .../perf/util/kvm-stat-arch/kvm-stat-riscv.c | 18 +++-- tools/perf/util/kvm-stat-arch/kvm-stat-s390.c | 20 +++--- tools/perf/util/kvm-stat-arch/kvm-stat-x86.c | 70 ++++++++----------- tools/perf/util/kvm-stat.c | 19 +++-- tools/perf/util/kvm-stat.h | 18 ++--- 9 files changed, 89 insertions(+), 126 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 5e8e6fde097a..d9b9792894a8 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -806,7 +806,6 @@ static bool update_kvm_event(struct perf_kvm_stat *kvm, } static bool is_child_event(struct perf_kvm_stat *kvm, - struct evsel *evsel, struct perf_sample *sample, struct event_key *key) { @@ -818,8 +817,8 @@ static bool is_child_event(struct perf_kvm_stat *kvm, return false; for (; child_ops->name; child_ops++) { - if (evsel__name_is(evsel, child_ops->name)) { - child_ops->get_key(evsel, sample, key); + if (evsel__name_is(sample->evsel, child_ops->name)) { + child_ops->get_key(sample, key); return true; } } @@ -917,11 +916,10 @@ static bool handle_end_event(struct perf_kvm_stat *kvm, static struct vcpu_event_record *per_vcpu_record(struct thread *thread, - struct evsel *evsel, struct perf_sample *sample) { /* Only kvm_entry records vcpu id. */ - if (!thread__priv(thread) && kvm_entry_event(evsel)) { + if (!thread__priv(thread) && kvm_entry_event(sample->evsel)) { struct vcpu_event_record *vcpu_record; struct machine *machine = maps__machine(thread__maps(thread)); uint16_t e_machine = thread__e_machine(thread, machine, /*e_flags=*/NULL); @@ -932,7 +930,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread, return NULL; } - vcpu_record->vcpu_id = evsel__intval(evsel, sample, vcpu_id_str(e_machine)); + vcpu_record->vcpu_id = evsel__intval(sample->evsel, sample, vcpu_id_str(e_machine)); thread__set_priv(thread, vcpu_record); } @@ -943,12 +941,11 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm, struct thread *thread, struct perf_sample *sample) { - struct evsel *evsel = sample->evsel; struct vcpu_event_record *vcpu_record; struct event_key key = { .key = INVALID_KEY, .exit_reasons = kvm->exit_reasons }; - vcpu_record = per_vcpu_record(thread, evsel, sample); + vcpu_record = per_vcpu_record(thread, sample); if (!vcpu_record) return true; @@ -957,13 +954,13 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm, (kvm->trace_vcpu != vcpu_record->vcpu_id)) return true; - if (kvm->events_ops->is_begin_event(evsel, sample, &key)) + if (kvm->events_ops->is_begin_event(sample, &key)) return handle_begin_event(kvm, vcpu_record, &key, sample); - if (is_child_event(kvm, evsel, sample, &key)) + if (is_child_event(kvm, sample, &key)) return handle_child_event(kvm, vcpu_record, &key, sample); - if (kvm->events_ops->is_end_event(evsel, sample, &key)) + if (kvm->events_ops->is_end_event(sample, &key)) return handle_end_event(kvm, vcpu_record, &key, sample); return true; diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-arm64.c b/tools/perf/util/kvm-stat-arch/kvm-stat-arm64.c index c640dcd8af7c..1e76906f719c 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-arm64.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-arm64.c @@ -17,10 +17,11 @@ static const char * const __kvm_events_tp[] = { NULL, }; -static void event_get_key(struct evsel *evsel, - struct perf_sample *sample, +static void event_get_key(struct perf_sample *sample, struct event_key *key) { + struct evsel *evsel = sample->evsel; + key->info = 0; key->key = evsel__intval(evsel, sample, kvm_exit_reason(EM_AARCH64)); key->exit_reasons = arm64_exit_reasons; @@ -36,19 +37,17 @@ static void event_get_key(struct evsel *evsel, } } -static bool event_begin(struct evsel *evsel, - struct perf_sample *sample __maybe_unused, +static bool event_begin(struct perf_sample *sample, struct event_key *key __maybe_unused) { - return evsel__name_is(evsel, kvm_entry_trace(EM_AARCH64)); + return evsel__name_is(sample->evsel, kvm_entry_trace(EM_AARCH64)); } -static bool event_end(struct evsel *evsel, - struct perf_sample *sample, +static bool event_end(struct perf_sample *sample, struct event_key *key) { - if (evsel__name_is(evsel, kvm_exit_trace(EM_AARCH64))) { - event_get_key(evsel, sample, key); + if (evsel__name_is(sample->evsel, kvm_exit_trace(EM_AARCH64))) { + event_get_key(sample, key); return true; } return false; diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-loongarch.c b/tools/perf/util/kvm-stat-arch/kvm-stat-loongarch.c index b802e516b138..9d6265290f6d 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-loongarch.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-loongarch.c @@ -53,14 +53,12 @@ static const char * const __kvm_events_tp[] = { NULL, }; -static bool event_begin(struct evsel *evsel, - struct perf_sample *sample, struct event_key *key) +static bool event_begin(struct perf_sample *sample, struct event_key *key) { - return exit_event_begin(evsel, sample, key); + return exit_event_begin(sample, key); } -static bool event_end(struct evsel *evsel, - struct perf_sample *sample __maybe_unused, +static bool event_end(struct perf_sample *sample, struct event_key *key __maybe_unused) { /* @@ -71,17 +69,16 @@ static bool event_end(struct evsel *evsel, * kvm:kvm_enter means returning to vmm and then to guest * kvm:kvm_reenter means returning to guest immediately */ - return evsel__name_is(evsel, kvm_entry_trace(EM_LOONGARCH)) || - evsel__name_is(evsel, kvm_reenter_trace); + return evsel__name_is(sample->evsel, kvm_entry_trace(EM_LOONGARCH)) || + evsel__name_is(sample->evsel, kvm_reenter_trace); } -static void event_gspr_get_key(struct evsel *evsel, - struct perf_sample *sample, struct event_key *key) +static void event_gspr_get_key(struct perf_sample *sample, struct event_key *key) { unsigned int insn; key->key = LOONGARCH_EXCEPTION_OTHERS; - insn = evsel__intval(evsel, sample, "inst_word"); + insn = evsel__intval(sample->evsel, sample, "inst_word"); switch (insn >> 24) { case 0: diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c b/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c index 42182d70beb6..5158d7e88ee6 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c @@ -28,12 +28,11 @@ static const char * const ppc_book3s_hv_kvm_tp[] = { /* 1 extra placeholder for NULL */ static const char *__kvm_events_tp[NR_TPS + 1]; -static void hcall_event_get_key(struct evsel *evsel, - struct perf_sample *sample, +static void hcall_event_get_key(struct perf_sample *sample, struct event_key *key) { key->info = 0; - key->key = evsel__intval(evsel, sample, "req"); + key->key = evsel__intval(sample->evsel, sample, "req"); } static const char *get_hcall_exit_reason(u64 exit_code) @@ -51,18 +50,16 @@ static const char *get_hcall_exit_reason(u64 exit_code) return "UNKNOWN"; } -static bool hcall_event_end(struct evsel *evsel, - struct perf_sample *sample __maybe_unused, +static bool hcall_event_end(struct perf_sample *sample, struct event_key *key __maybe_unused) { - return evsel__name_is(evsel, __kvm_events_tp[3]); + return evsel__name_is(sample->evsel, __kvm_events_tp[3]); } -static bool hcall_event_begin(struct evsel *evsel, - struct perf_sample *sample, struct event_key *key) +static bool hcall_event_begin(struct perf_sample *sample, struct event_key *key) { - if (evsel__name_is(evsel, __kvm_events_tp[2])) { - hcall_event_get_key(evsel, sample, key); + if (evsel__name_is(sample->evsel, __kvm_events_tp[2])) { + hcall_event_get_key(sample, key); return true; } diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-riscv.c b/tools/perf/util/kvm-stat-arch/kvm-stat-riscv.c index 8d4d5d6ce720..e8db8b4f8e2e 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-riscv.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-riscv.c @@ -20,30 +20,28 @@ static const char * const __kvm_events_tp[] = { NULL, }; -static void event_get_key(struct evsel *evsel, - struct perf_sample *sample, +static void event_get_key(struct perf_sample *sample, struct event_key *key) { int xlen = 64; // TODO: 32-bit support. key->info = 0; - key->key = evsel__intval(evsel, sample, kvm_exit_reason(EM_RISCV)) & ~CAUSE_IRQ_FLAG(xlen); + key->key = evsel__intval(sample->evsel, sample, + kvm_exit_reason(EM_RISCV)) & ~CAUSE_IRQ_FLAG(xlen); key->exit_reasons = riscv_exit_reasons; } -static bool event_begin(struct evsel *evsel, - struct perf_sample *sample __maybe_unused, +static bool event_begin(struct perf_sample *sample, struct event_key *key __maybe_unused) { - return evsel__name_is(evsel, kvm_entry_trace(EM_RISCV)); + return evsel__name_is(sample->evsel, kvm_entry_trace(EM_RISCV)); } -static bool event_end(struct evsel *evsel, - struct perf_sample *sample, +static bool event_end(struct perf_sample *sample, struct event_key *key) { - if (evsel__name_is(evsel, kvm_exit_trace(EM_RISCV))) { - event_get_key(evsel, sample, key); + if (evsel__name_is(sample->evsel, kvm_exit_trace(EM_RISCV))) { + event_get_key(sample, key); return true; } return false; diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-s390.c b/tools/perf/util/kvm-stat-arch/kvm-stat-s390.c index 7e29169f5bb0..158372ba0205 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-s390.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-s390.c @@ -18,38 +18,34 @@ define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes); define_exit_reasons_table(sie_diagnose_codes, diagnose_codes); define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes); -static void event_icpt_insn_get_key(struct evsel *evsel, - struct perf_sample *sample, +static void event_icpt_insn_get_key(struct perf_sample *sample, struct event_key *key) { u64 insn; - insn = evsel__intval(evsel, sample, "instruction"); + insn = evsel__intval(sample->evsel, sample, "instruction"); key->key = icpt_insn_decoder(insn); key->exit_reasons = sie_icpt_insn_codes; } -static void event_sigp_get_key(struct evsel *evsel, - struct perf_sample *sample, +static void event_sigp_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(evsel, sample, "order_code"); + key->key = evsel__intval(sample->evsel, sample, "order_code"); key->exit_reasons = sie_sigp_order_codes; } -static void event_diag_get_key(struct evsel *evsel, - struct perf_sample *sample, +static void event_diag_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(evsel, sample, "code"); + key->key = evsel__intval(sample->evsel, sample, "code"); key->exit_reasons = sie_diagnose_codes; } -static void event_icpt_prog_get_key(struct evsel *evsel, - struct perf_sample *sample, +static void event_icpt_prog_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(evsel, sample, "code"); + key->key = evsel__intval(sample->evsel, sample, "code"); key->exit_reasons = sie_icpt_prog_codes; } diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c b/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c index 0f626db3a439..0ce543d82850 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c @@ -24,45 +24,43 @@ static const struct kvm_events_ops exit_events = { * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...). */ -static void mmio_event_get_key(struct evsel *evsel, struct perf_sample *sample, +static void mmio_event_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(evsel, sample, "gpa"); - key->info = evsel__intval(evsel, sample, "type"); + key->key = evsel__intval(sample->evsel, sample, "gpa"); + key->info = evsel__intval(sample->evsel, sample, "type"); } #define KVM_TRACE_MMIO_READ_UNSATISFIED 0 #define KVM_TRACE_MMIO_READ 1 #define KVM_TRACE_MMIO_WRITE 2 -static bool mmio_event_begin(struct evsel *evsel, - struct perf_sample *sample, struct event_key *key) +static bool mmio_event_begin(struct perf_sample *sample, struct event_key *key) { /* MMIO read begin event in kernel. */ - if (kvm_exit_event(evsel)) + if (kvm_exit_event(sample->evsel)) return true; /* MMIO write begin event in kernel. */ - if (evsel__name_is(evsel, "kvm:kvm_mmio") && - evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) { - mmio_event_get_key(evsel, sample, key); + if (evsel__name_is(sample->evsel, "kvm:kvm_mmio") && + evsel__intval(sample->evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) { + mmio_event_get_key(sample, key); return true; } return false; } -static bool mmio_event_end(struct evsel *evsel, struct perf_sample *sample, - struct event_key *key) +static bool mmio_event_end(struct perf_sample *sample, struct event_key *key) { /* MMIO write end event in kernel. */ - if (kvm_entry_event(evsel)) + if (kvm_entry_event(sample->evsel)) return true; /* MMIO read end event in kernel.*/ - if (evsel__name_is(evsel, "kvm:kvm_mmio") && - evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_READ) { - mmio_event_get_key(evsel, sample, key); + if (evsel__name_is(sample->evsel, "kvm:kvm_mmio") && + evsel__intval(sample->evsel, sample, "type") == KVM_TRACE_MMIO_READ) { + mmio_event_get_key(sample, key); return true; } @@ -86,31 +84,27 @@ static const struct kvm_events_ops mmio_events = { }; /* The time of emulation pio access is from kvm_pio to kvm_entry. */ -static void ioport_event_get_key(struct evsel *evsel, - struct perf_sample *sample, +static void ioport_event_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(evsel, sample, "port"); - key->info = evsel__intval(evsel, sample, "rw"); + key->key = evsel__intval(sample->evsel, sample, "port"); + key->info = evsel__intval(sample->evsel, sample, "rw"); } -static bool ioport_event_begin(struct evsel *evsel, - struct perf_sample *sample, +static bool ioport_event_begin(struct perf_sample *sample, struct event_key *key) { - if (evsel__name_is(evsel, "kvm:kvm_pio")) { - ioport_event_get_key(evsel, sample, key); + if (evsel__name_is(sample->evsel, "kvm:kvm_pio")) { + ioport_event_get_key(sample, key); return true; } return false; } -static bool ioport_event_end(struct evsel *evsel, - struct perf_sample *sample __maybe_unused, - struct event_key *key __maybe_unused) +static bool ioport_event_end(struct perf_sample *sample, struct event_key *key __maybe_unused) { - return kvm_entry_event(evsel); + return kvm_entry_event(sample->evsel); } static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, @@ -130,31 +124,25 @@ static const struct kvm_events_ops ioport_events = { }; /* The time of emulation msr is from kvm_msr to kvm_entry. */ -static void msr_event_get_key(struct evsel *evsel, - struct perf_sample *sample, - struct event_key *key) +static void msr_event_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(evsel, sample, "ecx"); - key->info = evsel__intval(evsel, sample, "write"); + key->key = evsel__intval(sample->evsel, sample, "ecx"); + key->info = evsel__intval(sample->evsel, sample, "write"); } -static bool msr_event_begin(struct evsel *evsel, - struct perf_sample *sample, - struct event_key *key) +static bool msr_event_begin(struct perf_sample *sample, struct event_key *key) { - if (evsel__name_is(evsel, "kvm:kvm_msr")) { - msr_event_get_key(evsel, sample, key); + if (evsel__name_is(sample->evsel, "kvm:kvm_msr")) { + msr_event_get_key(sample, key); return true; } return false; } -static bool msr_event_end(struct evsel *evsel, - struct perf_sample *sample __maybe_unused, - struct event_key *key __maybe_unused) +static bool msr_event_end(struct perf_sample *sample, struct event_key *key __maybe_unused) { - return kvm_entry_event(evsel); + return kvm_entry_event(sample->evsel); } static void msr_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, diff --git a/tools/perf/util/kvm-stat.c b/tools/perf/util/kvm-stat.c index 27f16810498c..f17a6132958d 100644 --- a/tools/perf/util/kvm-stat.c +++ b/tools/perf/util/kvm-stat.c @@ -11,22 +11,20 @@ bool kvm_exit_event(struct evsel *evsel) return evsel__name_is(evsel, kvm_exit_trace(e_machine)); } -void exit_event_get_key(struct evsel *evsel, - struct perf_sample *sample, +void exit_event_get_key(struct perf_sample *sample, struct event_key *key) { - uint16_t e_machine = evsel__e_machine(evsel, /*e_flags=*/NULL); + uint16_t e_machine = evsel__e_machine(sample->evsel, /*e_flags=*/NULL); key->info = 0; - key->key = evsel__intval(evsel, sample, kvm_exit_reason(e_machine)); + key->key = evsel__intval(sample->evsel, sample, kvm_exit_reason(e_machine)); } -bool exit_event_begin(struct evsel *evsel, - struct perf_sample *sample, struct event_key *key) +bool exit_event_begin(struct perf_sample *sample, struct event_key *key) { - if (kvm_exit_event(evsel)) { - exit_event_get_key(evsel, sample, key); + if (kvm_exit_event(sample->evsel)) { + exit_event_get_key(sample, key); return true; } @@ -40,11 +38,10 @@ bool kvm_entry_event(struct evsel *evsel) return evsel__name_is(evsel, kvm_entry_trace(e_machine)); } -bool exit_event_end(struct evsel *evsel, - struct perf_sample *sample __maybe_unused, +bool exit_event_end(struct perf_sample *sample, struct event_key *key __maybe_unused) { - return kvm_entry_event(evsel); + return kvm_entry_event(sample->evsel); } static const char *get_exit_reason(struct perf_kvm_stat *kvm, diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h index 4a998aaece5d..cdbd921a555f 100644 --- a/tools/perf/util/kvm-stat.h +++ b/tools/perf/util/kvm-stat.h @@ -53,18 +53,15 @@ struct kvm_event { }; struct child_event_ops { - void (*get_key)(struct evsel *evsel, - struct perf_sample *sample, + void (*get_key)(struct perf_sample *sample, struct event_key *key); const char *name; }; struct kvm_events_ops { - bool (*is_begin_event)(struct evsel *evsel, - struct perf_sample *sample, + bool (*is_begin_event)(struct perf_sample *sample, struct event_key *key); - bool (*is_end_event)(struct evsel *evsel, - struct perf_sample *sample, struct event_key *key); + bool (*is_end_event)(struct perf_sample *sample, struct event_key *key); const struct child_event_ops *child_ops; void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key, char *decode); @@ -116,14 +113,11 @@ struct kvm_reg_events_ops { #ifdef HAVE_LIBTRACEEVENT -void exit_event_get_key(struct evsel *evsel, - struct perf_sample *sample, +void exit_event_get_key(struct perf_sample *sample, struct event_key *key); -bool exit_event_begin(struct evsel *evsel, - struct perf_sample *sample, +bool exit_event_begin(struct perf_sample *sample, struct event_key *key); -bool exit_event_end(struct evsel *evsel, - struct perf_sample *sample, +bool exit_event_end(struct perf_sample *sample, struct event_key *key); void exit_event_decode_key(struct perf_kvm_stat *kvm, struct event_key *key, From fd7dd303c430bf230b2192eb06696a7361f19850 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:09 -0700 Subject: [PATCH 046/343] perf evsel: Refactor evsel tracepoint sample accessors perf_sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The evsel argument to evsel__intval, evsel__rawptr, and similar functions, is unnecessary as it can be read from the sample. Remove the evsel and rename the function to match that the data is coming from the sample. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 2 +- tools/perf/builtin-kmem.c | 34 +++---- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-kwork.c | 29 +++--- tools/perf/builtin-lock.c | 32 +++---- tools/perf/builtin-sched.c | 92 +++++++++---------- tools/perf/builtin-timechart.c | 88 +++++++++--------- tools/perf/builtin-trace.c | 12 +-- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/tests/switch-tracking.c | 4 +- tools/perf/util/evsel.c | 22 ++--- tools/perf/util/evsel.h | 12 +-- tools/perf/util/intel-pt.c | 2 +- .../perf/util/kvm-stat-arch/kvm-stat-arm64.c | 6 +- .../util/kvm-stat-arch/kvm-stat-loongarch.c | 2 +- .../util/kvm-stat-arch/kvm-stat-powerpc.c | 2 +- .../perf/util/kvm-stat-arch/kvm-stat-riscv.c | 3 +- tools/perf/util/kvm-stat-arch/kvm-stat-s390.c | 8 +- tools/perf/util/kvm-stat-arch/kvm-stat-x86.c | 16 ++-- tools/perf/util/kvm-stat.c | 2 +- 20 files changed, 183 insertions(+), 189 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index e8cf8d399528..1d245d509b20 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -1194,7 +1194,7 @@ static int perf_inject__sched_stat(const struct perf_tool *tool, union perf_event *event_sw; struct perf_sample sample_sw; struct perf_inject *inject = container_of(tool, struct perf_inject, tool); - u32 pid = evsel__intval(evsel, sample, "pid"); + u32 pid = perf_sample__intval(sample, "pid"); int ret; list_for_each_entry(ent, &inject->samples, node) { diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 45b383fa9ce9..d7233a8b43be 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -173,10 +173,10 @@ static int insert_caller_stat(unsigned long call_site, static int evsel__process_alloc_event(struct evsel *evsel, struct perf_sample *sample) { - unsigned long ptr = evsel__intval(evsel, sample, "ptr"), - call_site = evsel__intval(evsel, sample, "call_site"); - int bytes_req = evsel__intval(evsel, sample, "bytes_req"), - bytes_alloc = evsel__intval(evsel, sample, "bytes_alloc"); + unsigned long ptr = perf_sample__intval(sample, "ptr"), + call_site = perf_sample__intval(sample, "call_site"); + int bytes_req = perf_sample__intval(sample, "bytes_req"), + bytes_alloc = perf_sample__intval(sample, "bytes_alloc"); if (insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, sample->cpu) || insert_caller_stat(call_site, bytes_req, bytes_alloc)) @@ -202,7 +202,7 @@ static int evsel__process_alloc_event(struct evsel *evsel, struct perf_sample *s int node1, node2; node1 = cpu__get_node((struct perf_cpu){.cpu = sample->cpu}); - node2 = evsel__intval(evsel, sample, "node"); + node2 = perf_sample__intval(sample, "node"); /* * If the field "node" is NUMA_NO_NODE (-1), we don't take it @@ -243,9 +243,9 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr, return NULL; } -static int evsel__process_free_event(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_free_event(struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - unsigned long ptr = evsel__intval(evsel, sample, "ptr"); + unsigned long ptr = perf_sample__intval(sample, "ptr"); struct alloc_stat *s_alloc, *s_caller; s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp); @@ -808,10 +808,9 @@ static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample, static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_sample *sample) { u64 page; - unsigned int order = evsel__intval(evsel, sample, "order"); - unsigned int gfp_flags = evsel__intval(evsel, sample, "gfp_flags"); - unsigned int migrate_type = evsel__intval(evsel, sample, - "migratetype"); + unsigned int order = perf_sample__intval(sample, "order"); + unsigned int gfp_flags = perf_sample__intval(sample, "gfp_flags"); + unsigned int migrate_type = perf_sample__intval(sample, "migratetype"); u64 bytes = kmem_page_size << order; u64 callsite; struct page_stat *pstat; @@ -822,9 +821,9 @@ static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_samp }; if (use_pfn) - page = evsel__intval(evsel, sample, "pfn"); + page = perf_sample__intval(sample, "pfn"); else - page = evsel__intval(evsel, sample, "page"); + page = perf_sample__intval(sample, "page"); nr_page_allocs++; total_page_alloc_bytes += bytes; @@ -877,10 +876,11 @@ static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_samp return 0; } -static int evsel__process_page_free_event(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_page_free_event(struct evsel *evsel __maybe_unused, + struct perf_sample *sample) { u64 page; - unsigned int order = evsel__intval(evsel, sample, "order"); + unsigned int order = perf_sample__intval(sample, "order"); u64 bytes = kmem_page_size << order; struct page_stat *pstat; struct page_stat this = { @@ -888,9 +888,9 @@ static int evsel__process_page_free_event(struct evsel *evsel, struct perf_sampl }; if (use_pfn) - page = evsel__intval(evsel, sample, "pfn"); + page = perf_sample__intval(sample, "pfn"); else - page = evsel__intval(evsel, sample, "page"); + page = perf_sample__intval(sample, "page"); nr_page_frees++; total_page_free_bytes += bytes; diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index d9b9792894a8..dd2ed21596aa 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -930,7 +930,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread, return NULL; } - vcpu_record->vcpu_id = evsel__intval(sample->evsel, sample, vcpu_id_str(e_machine)); + vcpu_record->vcpu_id = perf_sample__intval(sample, vcpu_id_str(e_machine)); thread__set_priv(thread, vcpu_record); } diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index d4bb19ed91b5..ab4519287f47 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -1006,7 +1006,7 @@ static void irq_work_init(struct perf_kwork *kwork, struct kwork_class *class, struct kwork_work *work, enum kwork_trace_type src_type __maybe_unused, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine __maybe_unused) { @@ -1014,11 +1014,11 @@ static void irq_work_init(struct perf_kwork *kwork, work->cpu = sample->cpu; if (kwork->report == KWORK_REPORT_TOP) { - work->id = evsel__intval_common(evsel, sample, "common_pid"); + work->id = perf_sample__intval_common(sample, "common_pid"); work->name = NULL; } else { - work->id = evsel__intval(evsel, sample, "irq"); - work->name = evsel__strval(evsel, sample, "name"); + work->id = perf_sample__intval(sample, "irq"); + work->name = perf_sample__strval(sample, "name"); } } @@ -1144,10 +1144,10 @@ static void softirq_work_init(struct perf_kwork *kwork, work->cpu = sample->cpu; if (kwork->report == KWORK_REPORT_TOP) { - work->id = evsel__intval_common(evsel, sample, "common_pid"); + work->id = perf_sample__intval_common(sample, "common_pid"); work->name = NULL; } else { - num = evsel__intval(evsel, sample, "vec"); + num = perf_sample__intval(sample, "vec"); work->id = num; work->name = evsel__softirq_name(evsel, num); } @@ -1234,17 +1234,16 @@ static void workqueue_work_init(struct perf_kwork *kwork __maybe_unused, struct kwork_class *class, struct kwork_work *work, enum kwork_trace_type src_type __maybe_unused, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { char *modp = NULL; - unsigned long long function_addr = evsel__intval(evsel, - sample, "function"); + unsigned long long function_addr = perf_sample__intval(sample, "function"); work->class = class; work->cpu = sample->cpu; - work->id = evsel__intval(evsel, sample, "work"); + work->id = perf_sample__intval(sample, "work"); work->name = function_addr == 0 ? NULL : machine__resolve_kernel_addr(machine, &function_addr, &modp); } @@ -1302,7 +1301,7 @@ static void sched_work_init(struct perf_kwork *kwork __maybe_unused, struct kwork_class *class, struct kwork_work *work, enum kwork_trace_type src_type, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine __maybe_unused) { @@ -1310,11 +1309,11 @@ static void sched_work_init(struct perf_kwork *kwork __maybe_unused, work->cpu = sample->cpu; if (src_type == KWORK_TRACE_EXIT) { - work->id = evsel__intval(evsel, sample, "prev_pid"); - work->name = strdup(evsel__strval(evsel, sample, "prev_comm")); + work->id = perf_sample__intval(sample, "prev_pid"); + work->name = strdup(perf_sample__strval(sample, "prev_comm")); } else if (src_type == KWORK_TRACE_ENTRY) { - work->id = evsel__intval(evsel, sample, "next_pid"); - work->name = strdup(evsel__strval(evsel, sample, "next_comm")); + work->id = perf_sample__intval(sample, "next_pid"); + work->name = strdup(perf_sample__strval(sample, "next_comm")); } } diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 4d8ddf6391e8..cbf3a39c7837 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -563,15 +563,15 @@ static int get_key_by_aggr_mode(u64 *key, u64 addr, struct evsel *evsel, return get_key_by_aggr_mode_simple(key, addr, sample->tid); } -static int report_lock_acquire_event(struct evsel *evsel, +static int report_lock_acquire_event(struct evsel *evsel __maybe_unused, struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; struct lock_seq_stat *seq; - const char *name = evsel__strval(evsel, sample, "name"); - u64 addr = evsel__intval(evsel, sample, "lockdep_addr"); - int flag = evsel__intval(evsel, sample, "flags"); + const char *name = perf_sample__strval(sample, "name"); + u64 addr = perf_sample__intval(sample, "lockdep_addr"); + int flag = perf_sample__intval(sample, "flags"); u64 key; int ret; @@ -638,15 +638,15 @@ static int report_lock_acquire_event(struct evsel *evsel, return 0; } -static int report_lock_acquired_event(struct evsel *evsel, +static int report_lock_acquired_event(struct evsel *evsel __maybe_unused, struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; struct lock_seq_stat *seq; u64 contended_term; - const char *name = evsel__strval(evsel, sample, "name"); - u64 addr = evsel__intval(evsel, sample, "lockdep_addr"); + const char *name = perf_sample__strval(sample, "name"); + u64 addr = perf_sample__intval(sample, "lockdep_addr"); u64 key; int ret; @@ -704,14 +704,14 @@ static int report_lock_acquired_event(struct evsel *evsel, return 0; } -static int report_lock_contended_event(struct evsel *evsel, +static int report_lock_contended_event(struct evsel *evsel __maybe_unused, struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; struct lock_seq_stat *seq; - const char *name = evsel__strval(evsel, sample, "name"); - u64 addr = evsel__intval(evsel, sample, "lockdep_addr"); + const char *name = perf_sample__strval(sample, "name"); + u64 addr = perf_sample__intval(sample, "lockdep_addr"); u64 key; int ret; @@ -762,14 +762,14 @@ static int report_lock_contended_event(struct evsel *evsel, return 0; } -static int report_lock_release_event(struct evsel *evsel, +static int report_lock_release_event(struct evsel *evsel __maybe_unused, struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; struct lock_seq_stat *seq; - const char *name = evsel__strval(evsel, sample, "name"); - u64 addr = evsel__intval(evsel, sample, "lockdep_addr"); + const char *name = perf_sample__strval(sample, "name"); + u64 addr = perf_sample__intval(sample, "lockdep_addr"); u64 key; int ret; @@ -969,8 +969,8 @@ static int report_lock_contention_begin_event(struct evsel *evsel, struct lock_stat *ls; struct thread_stat *ts; struct lock_seq_stat *seq; - u64 addr = evsel__intval(evsel, sample, "lock_addr"); - unsigned int flags = evsel__intval(evsel, sample, "flags"); + u64 addr = perf_sample__intval(sample, "lock_addr"); + unsigned int flags = perf_sample__intval(sample, "flags"); u64 key; int i, ret; static bool kmap_loaded; @@ -1134,7 +1134,7 @@ static int report_lock_contention_end_event(struct evsel *evsel, struct thread_stat *ts; struct lock_seq_stat *seq; u64 contended_term; - u64 addr = evsel__intval(evsel, sample, "lock_addr"); + u64 addr = perf_sample__intval(sample, "lock_addr"); u64 key; int ret; diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 2950c5c3026e..01228f630121 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -829,8 +829,8 @@ replay_wakeup_event(struct perf_sched *sched, struct evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused) { - const char *comm = evsel__strval(evsel, sample, "comm"); - const u32 pid = evsel__intval(evsel, sample, "pid"); + const char *comm = perf_sample__strval(sample, "comm"); + const u32 pid = perf_sample__intval(sample, "pid"); struct task_desc *waker, *wakee; if (verbose > 0) { @@ -851,10 +851,10 @@ static int replay_switch_event(struct perf_sched *sched, struct perf_sample *sample, struct machine *machine __maybe_unused) { - const char *prev_comm = evsel__strval(evsel, sample, "prev_comm"), - *next_comm = evsel__strval(evsel, sample, "next_comm"); - const u32 prev_pid = evsel__intval(evsel, sample, "prev_pid"), - next_pid = evsel__intval(evsel, sample, "next_pid"); + const char *prev_comm = perf_sample__strval(sample, "prev_comm"), + *next_comm = perf_sample__strval(sample, "next_comm"); + const u32 prev_pid = perf_sample__intval(sample, "prev_pid"), + next_pid = perf_sample__intval(sample, "next_pid"); struct task_desc *prev, __maybe_unused *next; u64 timestamp0, timestamp = sample->time; int cpu = sample->cpu; @@ -1134,13 +1134,13 @@ static void free_work_atoms(struct work_atoms *atoms) } static int latency_switch_event(struct perf_sched *sched, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { - const u32 prev_pid = evsel__intval(evsel, sample, "prev_pid"), - next_pid = evsel__intval(evsel, sample, "next_pid"); - const char prev_state = evsel__taskstate(evsel, sample, "prev_state"); + const u32 prev_pid = perf_sample__intval(sample, "prev_pid"), + next_pid = perf_sample__intval(sample, "next_pid"); + const char prev_state = perf_sample__taskstate(sample, "prev_state"); struct work_atoms *out_events, *in_events; struct thread *sched_out, *sched_in; u64 timestamp0, timestamp = sample->time; @@ -1204,12 +1204,12 @@ static int latency_switch_event(struct perf_sched *sched, } static int latency_runtime_event(struct perf_sched *sched, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { - const u32 pid = evsel__intval(evsel, sample, "pid"); - const u64 runtime = evsel__intval(evsel, sample, "runtime"); + const u32 pid = perf_sample__intval(sample, "pid"); + const u64 runtime = perf_sample__intval(sample, "runtime"); struct thread *thread = machine__findnew_thread(machine, -1, pid); struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); u64 timestamp = sample->time; @@ -1239,11 +1239,11 @@ static int latency_runtime_event(struct perf_sched *sched, } static int latency_wakeup_event(struct perf_sched *sched, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { - const u32 pid = evsel__intval(evsel, sample, "pid"); + const u32 pid = perf_sample__intval(sample, "pid"); struct work_atoms *atoms; struct work_atom *atom; struct thread *wakee; @@ -1300,11 +1300,11 @@ static int latency_wakeup_event(struct perf_sched *sched, } static int latency_migrate_task_event(struct perf_sched *sched, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { - const u32 pid = evsel__intval(evsel, sample, "pid"); + const u32 pid = perf_sample__intval(sample, "pid"); u64 timestamp = sample->time; struct work_atoms *atoms; struct work_atom *atom; @@ -1626,11 +1626,11 @@ static void print_sched_map(struct perf_sched *sched, struct perf_cpu this_cpu, } } -static int map_switch_event(struct perf_sched *sched, struct evsel *evsel, +static int map_switch_event(struct perf_sched *sched, struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { - const u32 next_pid = evsel__intval(evsel, sample, "next_pid"); - const u32 prev_pid = evsel__intval(evsel, sample, "prev_pid"); + const u32 next_pid = perf_sample__intval(sample, "next_pid"); + const u32 prev_pid = perf_sample__intval(sample, "prev_pid"); struct thread *sched_in, *sched_out; struct thread_runtime *tr; int new_shortname; @@ -1797,8 +1797,8 @@ static int process_sched_switch_event(const struct perf_tool *tool, { struct perf_sched *sched = container_of(tool, struct perf_sched, tool); int this_cpu = sample->cpu, err = 0; - u32 prev_pid = evsel__intval(evsel, sample, "prev_pid"), - next_pid = evsel__intval(evsel, sample, "next_pid"); + u32 prev_pid = perf_sample__intval(sample, "prev_pid"), + next_pid = perf_sample__intval(sample, "next_pid"); if (sched->curr_pid[this_cpu] != (u32)-1) { /* @@ -2068,12 +2068,11 @@ static char *timehist_get_commstr(struct thread *thread) /* prio field format: xxx or xxx->yyy */ #define MAX_PRIO_STR_LEN 8 -static char *timehist_get_priostr(struct evsel *evsel, - struct thread *thread, +static char *timehist_get_priostr(struct thread *thread, struct perf_sample *sample) { static char prio_str[16]; - int prev_prio = (int)evsel__intval(evsel, sample, "prev_prio"); + int prev_prio = (int)perf_sample__intval(sample, "prev_prio"); struct thread_runtime *tr = thread__priv(thread); if (tr->prio != prev_prio && tr->prio != -1) @@ -2161,15 +2160,14 @@ static void timehist_header(struct perf_sched *sched) } static void timehist_print_sample(struct perf_sched *sched, - struct evsel *evsel, struct perf_sample *sample, struct addr_location *al, struct thread *thread, u64 t, const char state) { struct thread_runtime *tr = thread__priv(thread); - const char *next_comm = evsel__strval(evsel, sample, "next_comm"); - const u32 next_pid = evsel__intval(evsel, sample, "next_pid"); + const char *next_comm = perf_sample__strval(sample, "next_comm"); + const u32 next_pid = perf_sample__intval(sample, "next_pid"); u32 max_cpus = sched->max_cpu.cpu + 1; char tstr[64]; char nstr[30]; @@ -2198,14 +2196,15 @@ static void timehist_print_sample(struct perf_sched *sched, } if (!thread__comm_set(thread)) { - const char *prev_comm = evsel__strval(evsel, sample, "prev_comm"); - thread__set_comm(thread, prev_comm, sample->time); + const char *prev_comm = perf_sample__strval(sample, "prev_comm"); + + thread__set_comm(thread, prev_comm, sample->time); } printf(" %-*s ", comm_width, timehist_get_commstr(thread)); if (sched->show_prio) - printf(" %-*s ", MAX_PRIO_STR_LEN, timehist_get_priostr(evsel, thread, sample)); + printf(" %-*s ", MAX_PRIO_STR_LEN, timehist_get_priostr(thread, sample)); wait_time = tr->dt_sleep + tr->dt_iowait + tr->dt_preempt; print_sched_time(wait_time, 6); @@ -2319,7 +2318,7 @@ static bool is_idle_sample(struct perf_sample *sample, { /* pid 0 == swapper == idle task */ if (evsel__name_is(evsel, "sched:sched_switch")) - return evsel__intval(evsel, sample, "prev_pid") == 0; + return perf_sample__intval(sample, "prev_pid") == 0; return sample->pid == 0; } @@ -2539,7 +2538,7 @@ static struct thread *timehist_get_thread(struct perf_sched *sched, itr->last_thread = thread__get(thread); /* copy task callchain when entering to idle */ - if (evsel__intval(evsel, sample, "next_pid") == 0) + if (perf_sample__intval(sample, "next_pid") == 0) save_idle_callchain(sched, itr, sample); } } @@ -2572,7 +2571,7 @@ static bool timehist_skip_sample(struct perf_sched *sched, if (tr && tr->prio != -1) prio = tr->prio; else if (evsel__name_is(evsel, "sched:sched_switch")) - prio = evsel__intval(evsel, sample, "prev_prio"); + prio = perf_sample__intval(sample, "prev_prio"); if (prio != -1 && !test_bit(prio, sched->prio_bitmap)) { rc = true; @@ -2583,8 +2582,8 @@ static bool timehist_skip_sample(struct perf_sched *sched, if (sched->idle_hist) { if (!evsel__name_is(evsel, "sched:sched_switch")) rc = true; - else if (evsel__intval(evsel, sample, "prev_pid") != 0 && - evsel__intval(evsel, sample, "next_pid") != 0) + else if (perf_sample__intval(sample, "prev_pid") != 0 && + perf_sample__intval(sample, "next_pid") != 0) rc = true; } @@ -2647,7 +2646,7 @@ static int timehist_sched_wakeup_event(const struct perf_tool *tool, struct thread *thread; struct thread_runtime *tr = NULL; /* want pid of awakened task not pid in sample */ - const u32 pid = evsel__intval(evsel, sample, "pid"); + const u32 pid = perf_sample__intval(sample, "pid"); thread = machine__findnew_thread(machine, 0, pid); if (thread == NULL) @@ -2686,8 +2685,8 @@ static void timehist_print_migration_event(struct perf_sched *sched, return; max_cpus = sched->max_cpu.cpu + 1; - ocpu = evsel__intval(evsel, sample, "orig_cpu"); - dcpu = evsel__intval(evsel, sample, "dest_cpu"); + ocpu = perf_sample__intval(sample, "orig_cpu"); + dcpu = perf_sample__intval(sample, "dest_cpu"); thread = machine__findnew_thread(machine, sample->pid, sample->tid); if (thread == NULL) @@ -2736,7 +2735,7 @@ static int timehist_migrate_task_event(const struct perf_tool *tool, struct thread *thread; struct thread_runtime *tr = NULL; /* want pid of migrated task not pid in sample */ - const u32 pid = evsel__intval(evsel, sample, "pid"); + const u32 pid = perf_sample__intval(sample, "pid"); thread = machine__findnew_thread(machine, 0, pid); if (thread == NULL) @@ -2761,14 +2760,13 @@ static int timehist_migrate_task_event(const struct perf_tool *tool, return 0; } -static void timehist_update_task_prio(struct evsel *evsel, - struct perf_sample *sample, +static void timehist_update_task_prio(struct perf_sample *sample, struct machine *machine) { struct thread *thread; struct thread_runtime *tr = NULL; - const u32 next_pid = evsel__intval(evsel, sample, "next_pid"); - const u32 next_prio = evsel__intval(evsel, sample, "next_prio"); + const u32 next_pid = perf_sample__intval(sample, "next_pid"); + const u32 next_prio = perf_sample__intval(sample, "next_prio"); if (next_pid == 0) thread = get_idle_thread(sample->cpu); @@ -2798,7 +2796,7 @@ static int timehist_sched_change_event(const struct perf_tool *tool, struct thread_runtime *tr = NULL; u64 tprev, t = sample->time; int rc = 0; - const char state = evsel__taskstate(evsel, sample, "prev_state"); + const char state = perf_sample__taskstate(sample, "prev_state"); addr_location__init(&al); if (machine__resolve(machine, &al, sample) < 0) { @@ -2809,7 +2807,7 @@ static int timehist_sched_change_event(const struct perf_tool *tool, } if (sched->show_prio || sched->prio_str) - timehist_update_task_prio(evsel, sample, machine); + timehist_update_task_prio(sample, machine); thread = timehist_get_thread(sched, sample, machine, evsel); if (thread == NULL) { @@ -2891,7 +2889,7 @@ static int timehist_sched_change_event(const struct perf_tool *tool, } if (!sched->summary_only) - timehist_print_sample(sched, evsel, sample, &al, thread, t, state); + timehist_print_sample(sched, sample, &al, thread, t, state); } out: diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 8692d11ccd29..034e0ba3f9cb 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -597,12 +597,12 @@ static int process_sample_event(const struct perf_tool *tool, static int process_sample_cpu_idle(struct timechart *tchart __maybe_unused, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { - u32 state = evsel__intval(evsel, sample, "state"); - u32 cpu_id = evsel__intval(evsel, sample, "cpu_id"); + u32 state = perf_sample__intval(sample, "state"); + u32 cpu_id = perf_sample__intval(sample, "cpu_id"); if (state == (u32)PWR_EVENT_EXIT) c_state_end(tchart, cpu_id, sample->time); @@ -613,12 +613,12 @@ process_sample_cpu_idle(struct timechart *tchart __maybe_unused, static int process_sample_cpu_frequency(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { - u32 state = evsel__intval(evsel, sample, "state"); - u32 cpu_id = evsel__intval(evsel, sample, "cpu_id"); + u32 state = perf_sample__intval(sample, "state"); + u32 cpu_id = perf_sample__intval(sample, "cpu_id"); p_state_change(tchart, cpu_id, sample->time, state); return 0; @@ -626,13 +626,13 @@ process_sample_cpu_frequency(struct timechart *tchart, static int process_sample_sched_wakeup(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace) { - u8 flags = evsel__intval(evsel, sample, "common_flags"); - int waker = evsel__intval(evsel, sample, "common_pid"); - int wakee = evsel__intval(evsel, sample, "pid"); + u8 flags = perf_sample__intval(sample, "common_flags"); + int waker = perf_sample__intval(sample, "common_pid"); + int wakee = perf_sample__intval(sample, "pid"); sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace); return 0; @@ -640,13 +640,13 @@ process_sample_sched_wakeup(struct timechart *tchart, static int process_sample_sched_switch(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace) { - int prev_pid = evsel__intval(evsel, sample, "prev_pid"); - int next_pid = evsel__intval(evsel, sample, "next_pid"); - u64 prev_state = evsel__intval(evsel, sample, "prev_state"); + int prev_pid = perf_sample__intval(sample, "prev_pid"); + int next_pid = perf_sample__intval(sample, "next_pid"); + u64 prev_state = perf_sample__intval(sample, "prev_state"); sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid, prev_state, backtrace); @@ -656,12 +656,12 @@ process_sample_sched_switch(struct timechart *tchart, #ifdef SUPPORT_OLD_POWER_EVENTS static int process_sample_power_start(struct timechart *tchart __maybe_unused, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { - u64 cpu_id = evsel__intval(evsel, sample, "cpu_id"); - u64 value = evsel__intval(evsel, sample, "value"); + u64 cpu_id = perf_sample__intval(sample, "cpu_id"); + u64 value = perf_sample__intval(sample, "value"); c_state_start(cpu_id, sample->time, value); return 0; @@ -679,12 +679,12 @@ process_sample_power_end(struct timechart *tchart, static int process_sample_power_frequency(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { - u64 cpu_id = evsel__intval(evsel, sample, "cpu_id"); - u64 value = evsel__intval(evsel, sample, "value"); + u64 cpu_id = perf_sample__intval(sample, "cpu_id"); + u64 value = perf_sample__intval(sample, "value"); p_state_change(tchart, cpu_id, sample->time, value); return 0; @@ -849,120 +849,120 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type, static int process_enter_read(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long fd = evsel__intval(evsel, sample, "fd"); + long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_READ, sample->time, fd); } static int process_exit_read(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long ret = evsel__intval(evsel, sample, "ret"); + long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_READ, sample->time, ret); } static int process_enter_write(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long fd = evsel__intval(evsel, sample, "fd"); + long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_WRITE, sample->time, fd); } static int process_exit_write(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long ret = evsel__intval(evsel, sample, "ret"); + long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_WRITE, sample->time, ret); } static int process_enter_sync(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long fd = evsel__intval(evsel, sample, "fd"); + long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_SYNC, sample->time, fd); } static int process_exit_sync(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long ret = evsel__intval(evsel, sample, "ret"); + long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_SYNC, sample->time, ret); } static int process_enter_tx(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long fd = evsel__intval(evsel, sample, "fd"); + long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_TX, sample->time, fd); } static int process_exit_tx(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long ret = evsel__intval(evsel, sample, "ret"); + long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_TX, sample->time, ret); } static int process_enter_rx(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long fd = evsel__intval(evsel, sample, "fd"); + long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_RX, sample->time, fd); } static int process_exit_rx(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long ret = evsel__intval(evsel, sample, "ret"); + long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_RX, sample->time, ret); } static int process_enter_poll(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long fd = evsel__intval(evsel, sample, "fd"); + long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_POLL, sample->time, fd); } static int process_exit_poll(struct timechart *tchart, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct perf_sample *sample) { - long ret = evsel__intval(evsel, sample, "ret"); + long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_POLL, sample->time, ret); } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 1aafa77f72cf..e8aabd7a72fe 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3094,7 +3094,7 @@ errno_print: { return err; } -static int trace__vfs_getname(struct trace *trace, struct evsel *evsel, +static int trace__vfs_getname(struct trace *trace, struct evsel *evsel __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -3103,7 +3103,7 @@ static int trace__vfs_getname(struct trace *trace, struct evsel *evsel, size_t filename_len, entry_str_len, to_move; ssize_t remaining_space; char *pos; - const char *filename = evsel__rawptr(evsel, sample, "pathname"); + const char *filename = perf_sample__strval(sample, "pathname"); if (!thread) goto out; @@ -3159,7 +3159,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { - u64 runtime = evsel__intval(evsel, sample, "runtime"); + u64 runtime = perf_sample__intval(sample, "runtime"); double runtime_ms = (double)runtime / NSEC_PER_MSEC; struct thread *thread = machine__findnew_thread(trace->host, sample->pid, @@ -3178,10 +3178,10 @@ static int trace__sched_stat_runtime(struct trace *trace, struct evsel *evsel, out_dump: fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n", evsel->name, - evsel__strval(evsel, sample, "comm"), - (pid_t)evsel__intval(evsel, sample, "pid"), + perf_sample__strval(sample, "comm"), + (pid_t)perf_sample__intval(sample, "pid"), runtime, - evsel__intval(evsel, sample, "vruntime")); + perf_sample__intval(sample, "vruntime")); goto out_put; } diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 5523cf4e9321..9ff8caff98c3 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -118,7 +118,7 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused goto out_delete_evlist; } - tp_flags = evsel__intval(evsel, &sample, "flags"); + tp_flags = perf_sample__intval(&sample, "flags"); perf_sample__exit(&sample); /* C library wrapper may set additional flags, access mode must be unchanged */ diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 72a8289e846d..22b0302252db 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -140,8 +140,8 @@ static int process_sample_event(struct evlist *evlist, evsel = evlist__id2evsel(evlist, sample.id); if (evsel == switch_tracking->switch_evsel) { - next_tid = evsel__intval(evsel, &sample, "next_pid"); - prev_tid = evsel__intval(evsel, &sample, "prev_pid"); + next_tid = perf_sample__intval(&sample, "next_pid"); + prev_tid = perf_sample__intval(&sample, "prev_pid"); cpu = sample.cpu; pr_debug3("sched_switch: cpu: %d prev_tid %d next_tid %d\n", cpu, prev_tid, next_tid); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 2ee87fd84d3e..ee30e15af054 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3687,9 +3687,9 @@ struct tep_format_field *evsel__common_field(struct evsel *evsel, const char *na return tp_format ? tep_find_common_field(tp_format, name) : NULL; } -void *evsel__rawptr(struct evsel *evsel, struct perf_sample *sample, const char *name) +void *perf_sample__rawptr(struct perf_sample *sample, const char *name) { - struct tep_format_field *field = evsel__field(evsel, name); + struct tep_format_field *field = evsel__field(sample->evsel, name); int offset; if (!field) @@ -3746,21 +3746,21 @@ u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sam return 0; } -u64 evsel__intval(struct evsel *evsel, struct perf_sample *sample, const char *name) +u64 perf_sample__intval(struct perf_sample *sample, const char *name) { - struct tep_format_field *field = evsel__field(evsel, name); + struct tep_format_field *field = evsel__field(sample->evsel, name); - return field ? format_field__intval(field, sample, evsel->needs_swap) : 0; + return field ? format_field__intval(field, sample, sample->evsel->needs_swap) : 0; } -u64 evsel__intval_common(struct evsel *evsel, struct perf_sample *sample, const char *name) +u64 perf_sample__intval_common(struct perf_sample *sample, const char *name) { - struct tep_format_field *field = evsel__common_field(evsel, name); + struct tep_format_field *field = evsel__common_field(sample->evsel, name); - return field ? format_field__intval(field, sample, evsel->needs_swap) : 0; + return field ? format_field__intval(field, sample, sample->evsel->needs_swap) : 0; } -char evsel__taskstate(struct evsel *evsel, struct perf_sample *sample, const char *name) +char perf_sample__taskstate(struct perf_sample *sample, const char *name) { static struct tep_format_field *prev_state_field; static const char *states; @@ -3769,7 +3769,7 @@ char evsel__taskstate(struct evsel *evsel, struct perf_sample *sample, const cha unsigned int bit; char state = '?'; /* '?' denotes unknown task state */ - field = evsel__field(evsel, name); + field = evsel__field(sample->evsel, name); if (!field) return state; @@ -3788,7 +3788,7 @@ char evsel__taskstate(struct evsel *evsel, struct perf_sample *sample, const cha * * We can change this if we have a good reason in the future. */ - val = evsel__intval(evsel, sample, name); + val = perf_sample__intval(sample, name); bit = val ? ffs(val) : 0; state = (!bit || bit > strlen(states)) ? 'R' : states[bit-1]; return state; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 339b5c08a33d..927e5b4756cc 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -371,14 +371,14 @@ bool evsel__precise_ip_fallback(struct evsel *evsel); struct perf_sample; #ifdef HAVE_LIBTRACEEVENT -void *evsel__rawptr(struct evsel *evsel, struct perf_sample *sample, const char *name); -u64 evsel__intval(struct evsel *evsel, struct perf_sample *sample, const char *name); -u64 evsel__intval_common(struct evsel *evsel, struct perf_sample *sample, const char *name); -char evsel__taskstate(struct evsel *evsel, struct perf_sample *sample, const char *name); +void *perf_sample__rawptr(struct perf_sample *sample, const char *name); +u64 perf_sample__intval(struct perf_sample *sample, const char *name); +u64 perf_sample__intval_common(struct perf_sample *sample, const char *name); +char perf_sample__taskstate(struct perf_sample *sample, const char *name); -static inline char *evsel__strval(struct evsel *evsel, struct perf_sample *sample, const char *name) +static inline char *perf_sample__strval(struct perf_sample *sample, const char *name) { - return evsel__rawptr(evsel, sample, name); + return perf_sample__rawptr(sample, name); } #endif diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index d9c86ac49748..b8add2b20033 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -3447,7 +3447,7 @@ static int intel_pt_process_switch(struct intel_pt *pt, if (evsel != pt->switch_evsel) return 0; - tid = evsel__intval(evsel, sample, "next_pid"); + tid = perf_sample__intval(sample, "next_pid"); cpu = sample->cpu; intel_pt_log("sched_switch: cpu %d tid %d time %"PRIu64" tsc %#"PRIx64"\n", diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-arm64.c b/tools/perf/util/kvm-stat-arch/kvm-stat-arm64.c index 1e76906f719c..018b0db0e6e7 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-arm64.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-arm64.c @@ -20,10 +20,8 @@ static const char * const __kvm_events_tp[] = { static void event_get_key(struct perf_sample *sample, struct event_key *key) { - struct evsel *evsel = sample->evsel; - key->info = 0; - key->key = evsel__intval(evsel, sample, kvm_exit_reason(EM_AARCH64)); + key->key = perf_sample__intval(sample, kvm_exit_reason(EM_AARCH64)); key->exit_reasons = arm64_exit_reasons; /* @@ -32,7 +30,7 @@ static void event_get_key(struct perf_sample *sample, * properly decode event's est_ec. */ if (key->key == ARM_EXCEPTION_TRAP) { - key->key = evsel__intval(evsel, sample, kvm_trap_exit_reason); + key->key = perf_sample__intval(sample, kvm_trap_exit_reason); key->exit_reasons = arm64_trap_exit_reasons; } } diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-loongarch.c b/tools/perf/util/kvm-stat-arch/kvm-stat-loongarch.c index 9d6265290f6d..a04cd09e3361 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-loongarch.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-loongarch.c @@ -78,7 +78,7 @@ static void event_gspr_get_key(struct perf_sample *sample, struct event_key *key unsigned int insn; key->key = LOONGARCH_EXCEPTION_OTHERS; - insn = evsel__intval(sample->evsel, sample, "inst_word"); + insn = perf_sample__intval(sample, "inst_word"); switch (insn >> 24) { case 0: diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c b/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c index 5158d7e88ee6..96d9c4ae0209 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-powerpc.c @@ -32,7 +32,7 @@ static void hcall_event_get_key(struct perf_sample *sample, struct event_key *key) { key->info = 0; - key->key = evsel__intval(sample->evsel, sample, "req"); + key->key = perf_sample__intval(sample, "req"); } static const char *get_hcall_exit_reason(u64 exit_code) diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-riscv.c b/tools/perf/util/kvm-stat-arch/kvm-stat-riscv.c index e8db8b4f8e2e..967bba261a47 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-riscv.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-riscv.c @@ -26,8 +26,7 @@ static void event_get_key(struct perf_sample *sample, int xlen = 64; // TODO: 32-bit support. key->info = 0; - key->key = evsel__intval(sample->evsel, sample, - kvm_exit_reason(EM_RISCV)) & ~CAUSE_IRQ_FLAG(xlen); + key->key = perf_sample__intval(sample, kvm_exit_reason(EM_RISCV)) & ~CAUSE_IRQ_FLAG(xlen); key->exit_reasons = riscv_exit_reasons; } diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-s390.c b/tools/perf/util/kvm-stat-arch/kvm-stat-s390.c index 158372ba0205..4771fc69fa39 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-s390.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-s390.c @@ -23,7 +23,7 @@ static void event_icpt_insn_get_key(struct perf_sample *sample, { u64 insn; - insn = evsel__intval(sample->evsel, sample, "instruction"); + insn = perf_sample__intval(sample, "instruction"); key->key = icpt_insn_decoder(insn); key->exit_reasons = sie_icpt_insn_codes; } @@ -31,21 +31,21 @@ static void event_icpt_insn_get_key(struct perf_sample *sample, static void event_sigp_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(sample->evsel, sample, "order_code"); + key->key = perf_sample__intval(sample, "order_code"); key->exit_reasons = sie_sigp_order_codes; } static void event_diag_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(sample->evsel, sample, "code"); + key->key = perf_sample__intval(sample, "code"); key->exit_reasons = sie_diagnose_codes; } static void event_icpt_prog_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(sample->evsel, sample, "code"); + key->key = perf_sample__intval(sample, "code"); key->exit_reasons = sie_icpt_prog_codes; } diff --git a/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c b/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c index 0ce543d82850..788d216f0852 100644 --- a/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c +++ b/tools/perf/util/kvm-stat-arch/kvm-stat-x86.c @@ -27,8 +27,8 @@ static const struct kvm_events_ops exit_events = { static void mmio_event_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(sample->evsel, sample, "gpa"); - key->info = evsel__intval(sample->evsel, sample, "type"); + key->key = perf_sample__intval(sample, "gpa"); + key->info = perf_sample__intval(sample, "type"); } #define KVM_TRACE_MMIO_READ_UNSATISFIED 0 @@ -43,7 +43,7 @@ static bool mmio_event_begin(struct perf_sample *sample, struct event_key *key) /* MMIO write begin event in kernel. */ if (evsel__name_is(sample->evsel, "kvm:kvm_mmio") && - evsel__intval(sample->evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) { + perf_sample__intval(sample, "type") == KVM_TRACE_MMIO_WRITE) { mmio_event_get_key(sample, key); return true; } @@ -59,7 +59,7 @@ static bool mmio_event_end(struct perf_sample *sample, struct event_key *key) /* MMIO read end event in kernel.*/ if (evsel__name_is(sample->evsel, "kvm:kvm_mmio") && - evsel__intval(sample->evsel, sample, "type") == KVM_TRACE_MMIO_READ) { + perf_sample__intval(sample, "type") == KVM_TRACE_MMIO_READ) { mmio_event_get_key(sample, key); return true; } @@ -87,8 +87,8 @@ static const struct kvm_events_ops mmio_events = { static void ioport_event_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(sample->evsel, sample, "port"); - key->info = evsel__intval(sample->evsel, sample, "rw"); + key->key = perf_sample__intval(sample, "port"); + key->info = perf_sample__intval(sample, "rw"); } static bool ioport_event_begin(struct perf_sample *sample, @@ -126,8 +126,8 @@ static const struct kvm_events_ops ioport_events = { /* The time of emulation msr is from kvm_msr to kvm_entry. */ static void msr_event_get_key(struct perf_sample *sample, struct event_key *key) { - key->key = evsel__intval(sample->evsel, sample, "ecx"); - key->info = evsel__intval(sample->evsel, sample, "write"); + key->key = perf_sample__intval(sample, "ecx"); + key->info = perf_sample__intval(sample, "write"); } static bool msr_event_begin(struct perf_sample *sample, struct event_key *key) diff --git a/tools/perf/util/kvm-stat.c b/tools/perf/util/kvm-stat.c index f17a6132958d..755ab659a05c 100644 --- a/tools/perf/util/kvm-stat.c +++ b/tools/perf/util/kvm-stat.c @@ -17,7 +17,7 @@ void exit_event_get_key(struct perf_sample *sample, uint16_t e_machine = evsel__e_machine(sample->evsel, /*e_flags=*/NULL); key->info = 0; - key->key = evsel__intval(sample->evsel, sample, kvm_exit_reason(e_machine)); + key->key = perf_sample__intval(sample, kvm_exit_reason(e_machine)); } From a50a9b0d6e9bbf537ae2f581d63671394f98bffa Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:10 -0700 Subject: [PATCH 047/343] perf trace: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from trace-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 55 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index e8aabd7a72fe..eca578212def 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -536,12 +536,12 @@ static struct evsel *perf_evsel__raw_syscall_newtp(const char *direction, void * return NULL; } -#define perf_evsel__sc_tp_uint(evsel, name, sample) \ - ({ struct syscall_tp *fields = __evsel__syscall_tp(evsel); \ +#define perf_evsel__sc_tp_uint(name, sample) \ + ({ struct syscall_tp *fields = __evsel__syscall_tp(sample->evsel); \ fields->name.integer(&fields->name, sample); }) -#define perf_evsel__sc_tp_ptr(evsel, name, sample) \ - ({ struct syscall_tp *fields = __evsel__syscall_tp(evsel); \ +#define perf_evsel__sc_tp_ptr(name, sample) \ + ({ struct syscall_tp *fields = __evsel__syscall_tp(sample->evsel); \ fields->name.pointer(&fields->name, sample); }) size_t strarray__scnprintf_suffix(struct strarray *sa, char *bf, size_t size, const char *intfmt, bool show_suffix, int val) @@ -2749,8 +2749,8 @@ static int trace__printf_interrupted_entry(struct trace *trace) return printed; } -static int trace__fprintf_sample(struct trace *trace, struct evsel *evsel, - struct perf_sample *sample, struct thread *thread) +static int trace__fprintf_sample(struct trace *trace, struct perf_sample *sample, + struct thread *thread) { int printed = 0; @@ -2758,7 +2758,7 @@ static int trace__fprintf_sample(struct trace *trace, struct evsel *evsel, double ts = (double)sample->time / NSEC_PER_MSEC; printed += fprintf(trace->output, "%22s %10.3f %s %d/%d [%d]\n", - evsel__name(evsel), ts, + evsel__name(sample->evsel), ts, thread__comm_str(thread), sample->pid, sample->tid, sample->cpu); } @@ -2813,7 +2813,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel, void *args; int printed = 0; struct thread *thread; - int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; + int id = perf_evsel__sc_tp_uint(id, sample), err = -1; int augmented_args_size = 0, e_machine; void *augmented_args = NULL; struct syscall *sc; @@ -2828,9 +2828,9 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel, if (ttrace == NULL) goto out_put; - trace__fprintf_sample(trace, evsel, sample, thread); + trace__fprintf_sample(trace, sample, thread); - args = perf_evsel__sc_tp_ptr(evsel, args, sample); + args = perf_evsel__sc_tp_ptr(args, sample); if (ttrace->entry_str == NULL) { ttrace->entry_str = malloc(trace__entry_str_size); @@ -2888,12 +2888,11 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel, return err; } -static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel, - struct perf_sample *sample) +static int trace__fprintf_sys_enter(struct trace *trace, struct perf_sample *sample) { struct thread_trace *ttrace; struct thread *thread; - int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; + int id = perf_evsel__sc_tp_uint(id, sample), err = -1; struct syscall *sc; char msg[1024]; void *args, *augmented_args = NULL; @@ -2903,7 +2902,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel, thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); e_machine = thread__e_machine(thread, trace->host, /*e_flags=*/NULL); - sc = trace__syscall_info(trace, evsel, e_machine, id); + sc = trace__syscall_info(trace, sample->evsel, e_machine, id); if (sc == NULL) goto out_put; ttrace = thread__trace(thread, trace); @@ -2914,7 +2913,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel, if (ttrace == NULL) goto out_put; - args = perf_evsel__sc_tp_ptr(evsel, args, sample); + args = perf_evsel__sc_tp_ptr(args, sample); augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size); printed += syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread); fprintf(trace->output, "%.*s", (int)printed, msg); @@ -2924,10 +2923,11 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel, return err; } -static int trace__resolve_callchain(struct trace *trace, struct evsel *evsel, +static int trace__resolve_callchain(struct trace *trace, struct perf_sample *sample, struct callchain_cursor *cursor) { + struct evsel *evsel = sample->evsel; struct addr_location al; int max_stack = evsel->core.attr.sample_max_stack ? evsel->core.attr.sample_max_stack : @@ -2962,7 +2962,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel, u64 duration = 0; bool duration_calculated = false; struct thread *thread; - int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0; + int id = perf_evsel__sc_tp_uint(id, sample), err = -1, callchain_ret = 0, printed = 0; int alignment = trace->args_alignment, e_machine; struct syscall *sc; struct thread_trace *ttrace; @@ -2976,9 +2976,9 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel, if (ttrace == NULL) goto out_put; - trace__fprintf_sample(trace, evsel, sample, thread); + trace__fprintf_sample(trace, sample, thread); - ret = perf_evsel__sc_tp_uint(evsel, ret, sample); + ret = perf_evsel__sc_tp_uint(ret, sample); if (trace->summary) thread__update_stats(thread, ttrace, id, sample, ret, trace); @@ -3000,7 +3000,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel, if (sample->callchain) { struct callchain_cursor *cursor = get_tls_callchain_cursor(); - callchain_ret = trace__resolve_callchain(trace, evsel, sample, cursor); + callchain_ret = trace__resolve_callchain(trace, sample, cursor); if (callchain_ret == 0) { if (cursor->nr < trace->min_stack) goto out; @@ -3217,9 +3217,10 @@ static void bpf_output__fprintf(struct trace *trace, ++trace->nr_events_printed; } -static size_t trace__fprintf_tp_fields(struct trace *trace, struct evsel *evsel, struct perf_sample *sample, +static size_t trace__fprintf_tp_fields(struct trace *trace, struct perf_sample *sample, struct thread *thread, void *augmented_args, int augmented_args_size) { + struct evsel *evsel = sample->evsel; char bf[2048]; size_t size = sizeof(bf); const struct tep_event *tp_format = evsel__tp_format(evsel); @@ -3302,7 +3303,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel, if (sample->callchain) { struct callchain_cursor *cursor = get_tls_callchain_cursor(); - callchain_ret = trace__resolve_callchain(trace, evsel, sample, cursor); + callchain_ret = trace__resolve_callchain(trace, sample, cursor); if (callchain_ret == 0) { if (cursor->nr < trace->min_stack) goto out; @@ -3323,7 +3324,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel, trace__fprintf_comm_tid(trace, thread, trace->output); if (evsel == trace->syscalls.events.bpf_output) { - int id = perf_evsel__sc_tp_uint(evsel, id, sample); + int id = perf_evsel__sc_tp_uint(id, sample); int e_machine = thread ? thread__e_machine(thread, trace->host, /*e_flags=*/NULL) : EM_HOST; @@ -3331,7 +3332,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel, if (sc) { fprintf(trace->output, "%s(", sc->name); - trace__fprintf_sys_enter(trace, evsel, sample); + trace__fprintf_sys_enter(trace, sample); fputc(')', trace->output); goto newline; } @@ -3351,13 +3352,13 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel, const struct tep_event *tp_format = evsel__tp_format(evsel); if (tp_format && (strncmp(tp_format->name, "sys_enter_", 10) || - trace__fprintf_sys_enter(trace, evsel, sample))) { + trace__fprintf_sys_enter(trace, sample))) { if (trace->libtraceevent_print) { event_format__fprintf(tp_format, sample->cpu, sample->raw_data, sample->raw_size, trace->output); } else { - trace__fprintf_tp_fields(trace, evsel, sample, thread, NULL, 0); + trace__fprintf_tp_fields(trace, sample, thread, NULL, 0); } } } @@ -3416,7 +3417,7 @@ static int trace__pgfault(struct trace *trace, if (sample->callchain) { struct callchain_cursor *cursor = get_tls_callchain_cursor(); - callchain_ret = trace__resolve_callchain(trace, evsel, sample, cursor); + callchain_ret = trace__resolve_callchain(trace, sample, cursor); if (callchain_ret == 0) { if (cursor->nr < trace->min_stack) goto out_put; From 859e49597088b445173ed45cf4c4a44aff5e3f5a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:11 -0700 Subject: [PATCH 048/343] perf callchain: Don't pass evsel and sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from callchain-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 2 +- tools/perf/builtin-inject.c | 4 ++-- tools/perf/builtin-kmem.c | 6 ++--- tools/perf/builtin-kwork.c | 5 ++-- tools/perf/builtin-lock.c | 24 +++++++++---------- tools/perf/builtin-sched.c | 5 ++-- tools/perf/builtin-script.c | 6 ++--- tools/perf/builtin-trace.c | 2 +- tools/perf/util/build-id.c | 2 +- tools/perf/util/callchain.c | 8 +++---- tools/perf/util/callchain.h | 6 ++--- tools/perf/util/db-export.c | 8 +++---- tools/perf/util/hist.c | 2 +- tools/perf/util/machine.c | 14 +++++------ tools/perf/util/machine.h | 3 --- .../util/scripting-engines/trace-event-perl.c | 4 ++-- .../scripting-engines/trace-event-python.c | 4 ++-- 17 files changed, 48 insertions(+), 57 deletions(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 7593e5908fcc..2fa3d7ec8a09 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -339,7 +339,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, cursor = get_tls_callchain_cursor(); ret = sample__resolve_callchain(sample, cursor, NULL, - evsel, &al, sysctl_perf_event_max_stack); + &al, sysctl_perf_event_max_stack); if (ret) goto out; diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 1d245d509b20..92ce2be1e5e2 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -521,7 +521,7 @@ static int perf_event__convert_sample_callchain(const struct perf_tool *tool, goto out; /* this will parse DWARF using stack and register data */ - ret = thread__resolve_callchain(thread, cursor, evsel, sample, + ret = thread__resolve_callchain(thread, cursor, sample, /*parent=*/NULL, /*root_al=*/NULL, PERF_MAX_STACK_DEPTH); thread__put(thread); @@ -1130,7 +1130,7 @@ static int perf_event__inject_buildid(const struct perf_tool *tool, union perf_e /*sample_in_dso=*/true); } - sample__for_each_callchain_node(thread, sample->evsel, sample, PERF_MAX_STACK_DEPTH, + sample__for_each_callchain_node(thread, sample, PERF_MAX_STACK_DEPTH, /*symbols=*/false, mark_dso_hit_callback, &args); thread__put(thread); repipe: diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index d7233a8b43be..2cdc56bc2616 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -394,7 +394,7 @@ static int build_alloc_func_list(void) * Find first non-memory allocation function from callchain. * The allocation functions are in the 'alloc_func_list'. */ -static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample) +static u64 find_callsite(struct perf_sample *sample) { struct addr_location al; struct machine *machine = &kmem_session->machines.host; @@ -414,7 +414,7 @@ static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample) if (cursor == NULL) goto out; - sample__resolve_callchain(sample, cursor, NULL, evsel, &al, 16); + sample__resolve_callchain(sample, cursor, /*parent=*/NULL, &al, 16); callchain_cursor_commit(cursor); while (true) { @@ -838,7 +838,7 @@ static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_samp if (parse_gfp_flags(evsel, sample, gfp_flags) < 0) return -1; - callsite = find_callsite(evsel, sample); + callsite = find_callsite(sample); /* * This is to find the current page (with correct gfp flags and diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index ab4519287f47..4b312afed830 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -688,7 +688,6 @@ static int latency_entry_event(struct perf_kwork *kwork, static void timehist_save_callchain(struct perf_kwork *kwork, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct symbol *sym; @@ -708,7 +707,7 @@ static void timehist_save_callchain(struct perf_kwork *kwork, cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(thread, cursor, evsel, sample, + if (thread__resolve_callchain(thread, cursor, sample, NULL, NULL, kwork->max_stack + 2) != 0) { pr_debug("Failed to resolve callchain, skipping\n"); goto out_put; @@ -838,7 +837,7 @@ static int timehist_entry_event(struct perf_kwork *kwork, return ret; if (work != NULL) - timehist_save_callchain(kwork, sample, evsel, machine); + timehist_save_callchain(kwork, sample, machine); return 0; } diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index cbf3a39c7837..e2b585e528ac 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -551,13 +551,13 @@ static int get_key_by_aggr_mode_simple(u64 *key, u64 addr, u32 tid) return 0; } -static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample); +static u64 callchain_id(struct perf_sample *sample); -static int get_key_by_aggr_mode(u64 *key, u64 addr, struct evsel *evsel, +static int get_key_by_aggr_mode(u64 *key, u64 addr, struct perf_sample *sample) { if (aggr_mode == LOCK_AGGR_CALLER) { - *key = callchain_id(evsel, sample); + *key = callchain_id(sample); return 0; } return get_key_by_aggr_mode_simple(key, addr, sample->tid); @@ -841,7 +841,7 @@ static int get_symbol_name_offset(struct map *map, struct symbol *sym, u64 ip, else return strlcpy(buf, sym->name, size); } -static int lock_contention_caller(struct evsel *evsel, struct perf_sample *sample, +static int lock_contention_caller(struct perf_sample *sample, char *buf, int size) { struct thread *thread; @@ -862,7 +862,7 @@ static int lock_contention_caller(struct evsel *evsel, struct perf_sample *sampl cursor = get_tls_callchain_cursor(); /* use caller function name from the callchain */ - ret = thread__resolve_callchain(thread, cursor, evsel, sample, + ret = thread__resolve_callchain(thread, cursor, sample, NULL, NULL, max_stack_depth); if (ret != 0) { thread__put(thread); @@ -896,7 +896,7 @@ static int lock_contention_caller(struct evsel *evsel, struct perf_sample *sampl return -1; } -static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample) +static u64 callchain_id(struct perf_sample *sample) { struct callchain_cursor *cursor; struct machine *machine = &session->machines.host; @@ -911,7 +911,7 @@ static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample) cursor = get_tls_callchain_cursor(); /* use caller function name from the callchain */ - ret = thread__resolve_callchain(thread, cursor, evsel, sample, + ret = thread__resolve_callchain(thread, cursor, sample, NULL, NULL, max_stack_depth); thread__put(thread); @@ -963,7 +963,7 @@ static u64 *get_callstack(struct perf_sample *sample, int max_stack) return callstack; } -static int report_lock_contention_begin_event(struct evsel *evsel, +static int report_lock_contention_begin_event(struct evsel *evsel __maybe_unused, struct perf_sample *sample) { struct lock_stat *ls; @@ -978,7 +978,7 @@ static int report_lock_contention_begin_event(struct evsel *evsel, struct map *kmap; struct symbol *sym; - ret = get_key_by_aggr_mode(&key, addr, evsel, sample); + ret = get_key_by_aggr_mode(&key, addr, sample); if (ret < 0) return ret; @@ -1025,7 +1025,7 @@ static int report_lock_contention_begin_event(struct evsel *evsel, break; case LOCK_AGGR_CALLER: name = buf; - if (lock_contention_caller(evsel, sample, buf, sizeof(buf)) < 0) + if (lock_contention_caller(sample, buf, sizeof(buf)) < 0) name = "Unknown"; break; case LOCK_AGGR_CGROUP: @@ -1127,7 +1127,7 @@ static int report_lock_contention_begin_event(struct evsel *evsel, return 0; } -static int report_lock_contention_end_event(struct evsel *evsel, +static int report_lock_contention_end_event(struct evsel *evsel __maybe_unused, struct perf_sample *sample) { struct lock_stat *ls; @@ -1138,7 +1138,7 @@ static int report_lock_contention_end_event(struct evsel *evsel, u64 key; int ret; - ret = get_key_by_aggr_mode(&key, addr, evsel, sample); + ret = get_key_by_aggr_mode(&key, addr, sample); if (ret < 0) return ret; diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 01228f630121..2a971081918b 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2325,7 +2325,6 @@ static bool is_idle_sample(struct perf_sample *sample, static void save_task_callchain(struct perf_sched *sched, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct callchain_cursor *cursor; @@ -2345,7 +2344,7 @@ static void save_task_callchain(struct perf_sched *sched, cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(thread, cursor, evsel, sample, + if (thread__resolve_callchain(thread, cursor, sample, NULL, NULL, sched->max_stack + 2) != 0) { if (verbose > 0) pr_err("Failed to resolve callchain. Skipping\n"); @@ -2519,7 +2518,7 @@ static struct thread *timehist_get_thread(struct perf_sched *sched, sample->tid); } - save_task_callchain(sched, sample, evsel, machine); + save_task_callchain(sched, sample, machine); if (sched->idle_hist) { struct thread *idle; struct idle_thread_runtime *itr; diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index d4e8f49a8751..b94a199ffcc9 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1684,7 +1684,7 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample, if (symbol_conf.use_callchain && sample->callchain) { cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(al->thread, cursor, evsel, + if (thread__resolve_callchain(al->thread, cursor, sample, NULL, NULL, scripting_max_stack)) cursor = NULL; @@ -2507,7 +2507,7 @@ static void process_event(struct perf_script *script, if (symbol_conf.use_callchain && sample->callchain) { cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(al->thread, cursor, evsel, + if (thread__resolve_callchain(al->thread, cursor, sample, NULL, NULL, scripting_max_stack)) cursor = NULL; @@ -2792,7 +2792,7 @@ static int process_deferred_sample_event(const struct perf_tool *tool, if (symbol_conf.use_callchain && sample->callchain) { cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(al.thread, cursor, evsel, + if (thread__resolve_callchain(al.thread, cursor, sample, NULL, NULL, scripting_max_stack)) { pr_info("cannot resolve deferred callchains\n"); diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index eca578212def..4bc30ad8fb07 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2938,7 +2938,7 @@ static int trace__resolve_callchain(struct trace *trace, if (machine__resolve(trace->host, &al, sample) < 0) goto out; - err = thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack); + err = thread__resolve_callchain(al.thread, cursor, sample, NULL, NULL, max_stack); out: addr_location__exit(&al); return err; diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 55b72235f891..af4d874f1381 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -73,7 +73,7 @@ int build_id__mark_dso_hit(const struct perf_tool *tool __maybe_unused, addr_location__exit(&al); - sample__for_each_callchain_node(thread, sample->evsel, sample, PERF_MAX_STACK_DEPTH, + sample__for_each_callchain_node(thread, sample, PERF_MAX_STACK_DEPTH, /*symbols=*/false, mark_dso_hit_callback, /*data=*/NULL); diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index f031cbbeeba8..5c2282051e39 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -1170,7 +1170,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor, int sample__resolve_callchain(struct perf_sample *sample, struct callchain_cursor *cursor, struct symbol **parent, - struct evsel *evsel, struct addr_location *al, + struct addr_location *al, int max_stack) { if (sample->callchain == NULL && !symbol_conf.show_branchflag_count) @@ -1178,7 +1178,7 @@ int sample__resolve_callchain(struct perf_sample *sample, if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || perf_hpp_list.parent || symbol_conf.show_branchflag_count) { - return thread__resolve_callchain(al->thread, cursor, evsel, sample, + return thread__resolve_callchain(al->thread, cursor, sample, parent, al, max_stack); } return 0; @@ -1853,7 +1853,7 @@ s64 callchain_avg_cycles(struct callchain_node *cnode) return cycles; } -int sample__for_each_callchain_node(struct thread *thread, struct evsel *evsel, +int sample__for_each_callchain_node(struct thread *thread, struct perf_sample *sample, int max_stack, bool symbols, callchain_iter_fn cb, void *data) { @@ -1864,7 +1864,7 @@ int sample__for_each_callchain_node(struct thread *thread, struct evsel *evsel, return -ENOMEM; /* Fill in the callchain. */ - ret = __thread__resolve_callchain(thread, cursor, evsel, sample, + ret = __thread__resolve_callchain(thread, cursor, sample, /*parent=*/NULL, /*root_al=*/NULL, max_stack, symbols); if (ret) diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index b7702d65ad60..0eb5d7a1a41d 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -8,11 +8,9 @@ #include "branch.h" struct addr_location; -struct evsel; struct hist_entry; struct hists; struct ip_callchain; -struct map; struct perf_sample; struct record_opts; struct thread; @@ -245,7 +243,7 @@ int record_opts__parse_callchain(struct record_opts *record, int sample__resolve_callchain(struct perf_sample *sample, struct callchain_cursor *cursor, struct symbol **parent, - struct evsel *evsel, struct addr_location *al, + struct addr_location *al, int max_stack); int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample); int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node, @@ -306,7 +304,7 @@ s64 callchain_avg_cycles(struct callchain_node *cnode); typedef int (*callchain_iter_fn)(struct callchain_cursor_node *node, void *data); -int sample__for_each_callchain_node(struct thread *thread, struct evsel *evsel, +int sample__for_each_callchain_node(struct thread *thread, struct perf_sample *sample, int max_stack, bool symbols, callchain_iter_fn cb, void *data); diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index cc2bb1af4243..d991e3168aed 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c @@ -208,8 +208,7 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al, static struct call_path *call_path_from_sample(struct db_export *dbe, struct machine *machine, struct thread *thread, - struct perf_sample *sample, - struct evsel *evsel) + struct perf_sample *sample) { u64 kernel_start = machine__kernel_start(machine); struct call_path *current = &dbe->cpr->call_path; @@ -227,7 +226,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe, */ callchain_param.order = ORDER_CALLER; cursor = get_tls_callchain_cursor(); - err = thread__resolve_callchain(thread, cursor, evsel, + err = thread__resolve_callchain(thread, cursor, sample, NULL, NULL, PERF_MAX_STACK_DEPTH); if (err) { callchain_param.order = saved_order; @@ -390,8 +389,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event, if (dbe->cpr) { struct call_path *cp = call_path_from_sample(dbe, machine, - thread, sample, - evsel); + thread, sample); if (cp) { db_export__call_path(dbe, cp); es.call_path_id = cp->db_id; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 747fdc455c80..f641cf321ace 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1342,7 +1342,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, alm = map__get(al->map); err = sample__resolve_callchain(iter->sample, get_tls_callchain_cursor(), &iter->parent, - iter->evsel, al, max_stack_depth); + al, max_stack_depth); if (err) { map__put(alm); return err; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index e76f8c86e62a..c2e0a99efe97 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2778,13 +2778,13 @@ static u64 get_leaf_frame_caller(struct perf_sample *sample, static int thread__resolve_callchain_sample(struct thread *thread, struct callchain_cursor *cursor, - struct evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, int max_stack, bool symbols) { + struct evsel *evsel = sample->evsel; struct branch_stack *branch = sample->branch_stack; struct branch_entry *entries = perf_sample__branch_entries(sample); struct ip_callchain *chain = sample->callchain; @@ -2986,10 +2986,11 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) static int thread__resolve_callchain_unwind(struct thread *thread, struct callchain_cursor *cursor, - struct evsel *evsel, struct perf_sample *sample, int max_stack, bool symbols) { + struct evsel *evsel = sample->evsel; + /* Can we do dwarf post unwind? */ if (!((evsel->core.attr.sample_type & PERF_SAMPLE_REGS_USER) && (evsel->core.attr.sample_type & PERF_SAMPLE_STACK_USER))) @@ -3009,7 +3010,6 @@ static int thread__resolve_callchain_unwind(struct thread *thread, int __thread__resolve_callchain(struct thread *thread, struct callchain_cursor *cursor, - struct evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, @@ -3025,22 +3025,22 @@ int __thread__resolve_callchain(struct thread *thread, if (callchain_param.order == ORDER_CALLEE) { ret = thread__resolve_callchain_sample(thread, cursor, - evsel, sample, + sample, parent, root_al, max_stack, symbols); if (ret) return ret; ret = thread__resolve_callchain_unwind(thread, cursor, - evsel, sample, + sample, max_stack, symbols); } else { ret = thread__resolve_callchain_unwind(thread, cursor, - evsel, sample, + sample, max_stack, symbols); if (ret) return ret; ret = thread__resolve_callchain_sample(thread, cursor, - evsel, sample, + sample, parent, root_al, max_stack, symbols); } diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 22a42c5825fa..048b24e9bd38 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -187,7 +187,6 @@ struct callchain_cursor; int __thread__resolve_callchain(struct thread *thread, struct callchain_cursor *cursor, - struct evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, @@ -196,7 +195,6 @@ int __thread__resolve_callchain(struct thread *thread, static inline int thread__resolve_callchain(struct thread *thread, struct callchain_cursor *cursor, - struct evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, @@ -204,7 +202,6 @@ static inline int thread__resolve_callchain(struct thread *thread, { return __thread__resolve_callchain(thread, cursor, - evsel, sample, parent, root_al, diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index e261a57b87d4..af0d514b2397 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -257,7 +257,7 @@ static void define_event_symbols(struct tep_event *event, } static SV *perl_process_callchain(struct perf_sample *sample, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct addr_location *al) { struct callchain_cursor *cursor; @@ -272,7 +272,7 @@ static SV *perl_process_callchain(struct perf_sample *sample, cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(al->thread, cursor, evsel, + if (thread__resolve_callchain(al->thread, cursor, sample, NULL, NULL, scripting_max_stack) != 0) { pr_err("Failed to resolve callchain. Skipping\n"); goto exit; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 5a30caaec73e..1537122167d5 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -390,7 +390,7 @@ static unsigned long get_offset(struct symbol *sym, struct addr_location *al) } static PyObject *python_process_callchain(struct perf_sample *sample, - struct evsel *evsel, + struct evsel *evsel __maybe_unused, struct addr_location *al) { PyObject *pylist; @@ -404,7 +404,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, goto exit; cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(al->thread, cursor, evsel, + if (thread__resolve_callchain(al->thread, cursor, sample, NULL, NULL, scripting_max_stack) != 0) { pr_err("Failed to resolve callchain. Skipping\n"); From 9d491ab9ede2a3ecc573fc77418ccb7f214eefd3 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:12 -0700 Subject: [PATCH 049/343] perf lock: Only pass sample to handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The evsel is within the sample and so only the sample needs to be passed. Remove the parameter and fix call site. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-lock.c | 65 ++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index e2b585e528ac..b6533483ba64 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -473,28 +473,22 @@ static struct lock_stat *pop_from_result(void) struct trace_lock_handler { /* it's used on CONFIG_LOCKDEP */ - int (*acquire_event)(struct evsel *evsel, - struct perf_sample *sample); + int (*acquire_event)(struct perf_sample *sample); /* it's used on CONFIG_LOCKDEP && CONFIG_LOCK_STAT */ - int (*acquired_event)(struct evsel *evsel, - struct perf_sample *sample); + int (*acquired_event)(struct perf_sample *sample); /* it's used on CONFIG_LOCKDEP && CONFIG_LOCK_STAT */ - int (*contended_event)(struct evsel *evsel, - struct perf_sample *sample); + int (*contended_event)(struct perf_sample *sample); /* it's used on CONFIG_LOCKDEP */ - int (*release_event)(struct evsel *evsel, - struct perf_sample *sample); + int (*release_event)(struct perf_sample *sample); /* it's used when CONFIG_LOCKDEP is off */ - int (*contention_begin_event)(struct evsel *evsel, - struct perf_sample *sample); + int (*contention_begin_event)(struct perf_sample *sample); /* it's used when CONFIG_LOCKDEP is off */ - int (*contention_end_event)(struct evsel *evsel, - struct perf_sample *sample); + int (*contention_end_event)(struct perf_sample *sample); }; static struct lock_seq_stat *get_seq(struct thread_stat *ts, u64 addr) @@ -563,8 +557,7 @@ static int get_key_by_aggr_mode(u64 *key, u64 addr, return get_key_by_aggr_mode_simple(key, addr, sample->tid); } -static int report_lock_acquire_event(struct evsel *evsel __maybe_unused, - struct perf_sample *sample) +static int report_lock_acquire_event(struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; @@ -638,8 +631,7 @@ static int report_lock_acquire_event(struct evsel *evsel __maybe_unused, return 0; } -static int report_lock_acquired_event(struct evsel *evsel __maybe_unused, - struct perf_sample *sample) +static int report_lock_acquired_event(struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; @@ -704,8 +696,7 @@ static int report_lock_acquired_event(struct evsel *evsel __maybe_unused, return 0; } -static int report_lock_contended_event(struct evsel *evsel __maybe_unused, - struct perf_sample *sample) +static int report_lock_contended_event(struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; @@ -762,8 +753,7 @@ static int report_lock_contended_event(struct evsel *evsel __maybe_unused, return 0; } -static int report_lock_release_event(struct evsel *evsel __maybe_unused, - struct perf_sample *sample) +static int report_lock_release_event(struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; @@ -963,8 +953,7 @@ static u64 *get_callstack(struct perf_sample *sample, int max_stack) return callstack; } -static int report_lock_contention_begin_event(struct evsel *evsel __maybe_unused, - struct perf_sample *sample) +static int report_lock_contention_begin_event(struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; @@ -1127,8 +1116,7 @@ static int report_lock_contention_begin_event(struct evsel *evsel __maybe_unused return 0; } -static int report_lock_contention_end_event(struct evsel *evsel __maybe_unused, - struct perf_sample *sample) +static int report_lock_contention_end_event(struct perf_sample *sample) { struct lock_stat *ls; struct thread_stat *ts; @@ -1208,45 +1196,45 @@ static struct trace_lock_handler contention_lock_ops = { static struct trace_lock_handler *trace_handler; -static int evsel__process_lock_acquire(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_lock_acquire(struct perf_sample *sample) { if (trace_handler->acquire_event) - return trace_handler->acquire_event(evsel, sample); + return trace_handler->acquire_event(sample); return 0; } -static int evsel__process_lock_acquired(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_lock_acquired(struct perf_sample *sample) { if (trace_handler->acquired_event) - return trace_handler->acquired_event(evsel, sample); + return trace_handler->acquired_event(sample); return 0; } -static int evsel__process_lock_contended(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_lock_contended(struct perf_sample *sample) { if (trace_handler->contended_event) - return trace_handler->contended_event(evsel, sample); + return trace_handler->contended_event(sample); return 0; } -static int evsel__process_lock_release(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_lock_release(struct perf_sample *sample) { if (trace_handler->release_event) - return trace_handler->release_event(evsel, sample); + return trace_handler->release_event(sample); return 0; } -static int evsel__process_contention_begin(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_contention_begin(struct perf_sample *sample) { if (trace_handler->contention_begin_event) - return trace_handler->contention_begin_event(evsel, sample); + return trace_handler->contention_begin_event(sample); return 0; } -static int evsel__process_contention_end(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_contention_end(struct perf_sample *sample) { if (trace_handler->contention_end_event) - return trace_handler->contention_end_event(evsel, sample); + return trace_handler->contention_end_event(sample); return 0; } @@ -1424,8 +1412,7 @@ static int process_event_update(const struct perf_tool *tool, return 0; } -typedef int (*tracepoint_handler)(struct evsel *evsel, - struct perf_sample *sample); +typedef int (*tracepoint_handler)(struct perf_sample *sample); static int process_sample_event(const struct perf_tool *tool __maybe_unused, union perf_event *event, @@ -1445,7 +1432,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, if (evsel->handler != NULL) { tracepoint_handler f = evsel->handler; - err = f(evsel, sample); + err = f(sample); } thread__put(thread); From 05e1a8077146e8c7385565d36a47e66b88d1090b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:13 -0700 Subject: [PATCH 050/343] perf hist: Remove evsel parameter from inc samples functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from hist-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 7 +++---- tools/perf/builtin-c2c.c | 2 +- tools/perf/builtin-report.c | 18 ++++++++---------- tools/perf/builtin-top.c | 6 +++--- tools/perf/util/annotate.c | 19 +++++++++---------- tools/perf/util/annotate.h | 6 ++---- 6 files changed, 26 insertions(+), 32 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 58e56f826367..ee1ba2dc35f4 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -176,16 +176,15 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, struct hist_entry *he = iter->he; struct branch_info *bi; struct perf_sample *sample = iter->sample; - struct evsel *evsel = iter->evsel; int err; bi = he->branch_info; - err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); + err = addr_map_symbol__inc_samples(&bi->from, sample); if (err) goto out; - err = addr_map_symbol__inc_samples(&bi->to, sample, evsel); + err = addr_map_symbol__inc_samples(&bi->to, sample); out: return err; @@ -275,7 +274,7 @@ static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample, if (he == NULL) return -ENOMEM; - ret = hist_entry__inc_addr_samples(he, sample, evsel, al->addr); + ret = hist_entry__inc_addr_samples(he, sample, al->addr); hists__inc_nr_samples(hists, true); return ret; } diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 2fa3d7ec8a09..36f386949923 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -371,7 +371,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, if (perf_c2c__has_annotation(NULL)) { perf_c2c__evsel_hists_inc_stats(evsel, he, sample); - addr_map_symbol__inc_samples(mem_info__iaddr(mi), sample, evsel); + addr_map_symbol__inc_samples(mem_info__iaddr(mi), sample); } ret = hist_entry__append_callchain(he, sample); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 9955ce8cce00..cc3ee712fe62 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -171,7 +171,6 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter, int err = 0; struct report *rep = arg; struct hist_entry *he = iter->he; - struct evsel *evsel = iter->evsel; struct perf_sample *sample = iter->sample; struct mem_info *mi; struct branch_info *bi; @@ -181,25 +180,25 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter, if (sort__mode == SORT_MODE__BRANCH) { bi = he->branch_info; - err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); + err = addr_map_symbol__inc_samples(&bi->from, sample); if (err) goto out; - err = addr_map_symbol__inc_samples(&bi->to, sample, evsel); + err = addr_map_symbol__inc_samples(&bi->to, sample); } else if (rep->mem_mode) { mi = he->mem_info; - err = addr_map_symbol__inc_samples(mem_info__daddr(mi), sample, evsel); + err = addr_map_symbol__inc_samples(mem_info__daddr(mi), sample); if (err) goto out; - err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr); + err = hist_entry__inc_addr_samples(he, sample, al->addr); } else if (symbol_conf.cumulate_callchain) { if (single) - err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr); + err = hist_entry__inc_addr_samples(he, sample, al->addr); } else { - err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr); + err = hist_entry__inc_addr_samples(he, sample, al->addr); } out: @@ -215,7 +214,6 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, struct report *rep = arg; struct branch_info *bi = he->branch_info; struct perf_sample *sample = iter->sample; - struct evsel *evsel = iter->evsel; int err; branch_type_count(&rep->brtype_stat, &bi->flags, @@ -224,11 +222,11 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, if (!ui__has_annotation() && !rep->symbol_ipc) return 0; - err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); + err = addr_map_symbol__inc_samples(&bi->from, sample); if (err) goto out; - err = addr_map_symbol__inc_samples(&bi->to, sample, evsel); + err = addr_map_symbol__inc_samples(&bi->to, sample); out: return err; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index f6eb543de537..b4fc991b4eeb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -199,7 +199,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip) static void perf_top__record_precise_ip(struct perf_top *top, struct hist_entry *he, struct perf_sample *sample, - struct evsel *evsel, u64 ip) + u64 ip) EXCLUSIVE_LOCKS_REQUIRED(he->hists->lock) { struct annotation *notes; @@ -216,7 +216,7 @@ static void perf_top__record_precise_ip(struct perf_top *top, if (!annotation__trylock(notes)) return; - err = hist_entry__inc_addr_samples(he, sample, evsel, ip); + err = hist_entry__inc_addr_samples(he, sample, ip); annotation__unlock(notes); @@ -735,7 +735,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter, struct evsel *evsel = iter->evsel; if (perf_hpp_list.sym && single) - perf_top__record_precise_ip(top, iter->he, iter->sample, evsel, al->addr); + perf_top__record_precise_ip(top, iter->he, iter->sample, al->addr); hist__account_cycles(iter->sample->branch_stack, al, iter->sample, !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY), diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index e745f3034a0e..470569745abe 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -213,9 +213,10 @@ static int __symbol__account_cycles(struct cyc_hist *ch, } static int __symbol__inc_addr_samples(struct map_symbol *ms, - struct annotated_source *src, struct evsel *evsel, u64 addr, + struct annotated_source *src, u64 addr, struct perf_sample *sample) { + struct evsel *evsel = sample->evsel; struct symbol *sym = ms->sym; long hash_key; u64 offset; @@ -318,7 +319,7 @@ struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists) } static int symbol__inc_addr_samples(struct map_symbol *ms, - struct evsel *evsel, u64 addr, + u64 addr, struct perf_sample *sample) { struct symbol *sym = ms->sym; @@ -326,8 +327,8 @@ static int symbol__inc_addr_samples(struct map_symbol *ms, if (sym == NULL) return 0; - src = symbol__hists(sym, evsel->evlist->core.nr_entries); - return src ? __symbol__inc_addr_samples(ms, src, evsel, addr, sample) : 0; + src = symbol__hists(sym, sample->evsel->evlist->core.nr_entries); + return src ? __symbol__inc_addr_samples(ms, src, addr, sample) : 0; } static int symbol__account_br_cntr(struct annotated_branch *branch, @@ -581,16 +582,14 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size, return 0; } -int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, - struct evsel *evsel) +int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample) { - return symbol__inc_addr_samples(&ams->ms, evsel, ams->al_addr, sample); + return symbol__inc_addr_samples(&ams->ms, ams->al_addr, sample); } -int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, - struct evsel *evsel, u64 ip) +int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, u64 ip) { - return symbol__inc_addr_samples(&he->ms, evsel, ip, sample); + return symbol__inc_addr_samples(&he->ms, ip, sample); } diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 696e36dbf013..1aa6df7d1618 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -422,8 +422,7 @@ static inline struct annotation *symbol__annotation(struct symbol *sym) return (void *)sym - symbol_conf.priv_size; } -int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, - struct evsel *evsel); +int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample); struct annotated_branch *annotation__get_branch(struct annotation *notes); @@ -433,8 +432,7 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams, struct evsel *evsel, u64 br_cntr); -int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, - struct evsel *evsel, u64 addr); +int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, u64 addr); struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists); void symbol__annotate_zero_histograms(struct symbol *sym); From 948b5874ef5e6e5c3d9eeb62df52472cedc23b04 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:14 -0700 Subject: [PATCH 051/343] perf db-export: Remove evsel from struct export_sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from db-export-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/db-export.c | 5 ++--- tools/perf/util/db-export.h | 3 +-- tools/perf/util/scripting-engines/trace-event-python.c | 8 ++++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index d991e3168aed..ba54b1119ee6 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c @@ -344,14 +344,13 @@ static int db_export__threads(struct db_export *dbe, struct thread *thread, } int db_export__sample(struct db_export *dbe, union perf_event *event, - struct perf_sample *sample, struct evsel *evsel, + struct perf_sample *sample, struct addr_location *al, struct addr_location *addr_al) { struct thread *thread = al->thread; struct export_sample es = { .event = event, .sample = sample, - .evsel = evsel, .al = al, }; struct thread *main_thread; @@ -364,7 +363,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event, if (!machine) return -1; - err = db_export__evsel(dbe, evsel); + err = db_export__evsel(dbe, sample->evsel); if (err) return err; diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h index 23983cb35706..1abbfd398e3a 100644 --- a/tools/perf/util/db-export.h +++ b/tools/perf/util/db-export.h @@ -25,7 +25,6 @@ struct call_return; struct export_sample { union perf_event *event; struct perf_sample *sample; - struct evsel *evsel; struct addr_location *al; u64 db_id; u64 comm_db_id; @@ -96,7 +95,7 @@ int db_export__symbol(struct db_export *dbe, struct symbol *sym, int db_export__branch_type(struct db_export *dbe, u32 branch_type, const char *name); int db_export__sample(struct db_export *dbe, union perf_event *event, - struct perf_sample *sample, struct evsel *evsel, + struct perf_sample *sample, struct addr_location *al, struct addr_location *addr_al); int db_export__branch_types(struct db_export *dbe); diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 1537122167d5..9e1069ec0578 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -1312,7 +1312,7 @@ static void python_export_sample_table(struct db_export *dbe, t = tuple_new(28); tuple_set_d64(t, 0, es->db_id); - tuple_set_d64(t, 1, es->evsel->db_id); + tuple_set_d64(t, 1, es->sample->evsel->db_id); tuple_set_d64(t, 2, maps__machine(thread__maps(es->al->thread))->db_id); tuple_set_d64(t, 3, thread__db_id(es->al->thread)); tuple_set_d64(t, 4, es->comm_db_id); @@ -1353,7 +1353,7 @@ static void python_export_synth(struct db_export *dbe, struct export_sample *es) t = tuple_new(3); tuple_set_d64(t, 0, es->db_id); - tuple_set_d64(t, 1, es->evsel->core.attr.config); + tuple_set_d64(t, 1, es->sample->evsel->core.attr.config); tuple_set_bytes(t, 2, es->sample->raw_data, es->sample->raw_size); call_object(tables->synth_handler, t, "synth_data"); @@ -1368,7 +1368,7 @@ static int python_export_sample(struct db_export *dbe, python_export_sample_table(dbe, es); - if (es->evsel->core.attr.type == PERF_TYPE_SYNTH && tables->synth_handler) + if (es->sample->evsel->core.attr.type == PERF_TYPE_SYNTH && tables->synth_handler) python_export_synth(dbe, es); return 0; @@ -1517,7 +1517,7 @@ static void python_process_event(union perf_event *event, /* Reserve for future process_hw/sw/raw APIs */ default: if (tables->db_export_mode) - db_export__sample(&tables->dbe, event, sample, evsel, al, addr_al); + db_export__sample(&tables->dbe, event, sample, al, addr_al); else python_process_general_event(sample, evsel, al, addr_al); } From 7e0e6ac66cc44ab06ba70b28cdfabdbef8538c29 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:15 -0700 Subject: [PATCH 052/343] perf hist: Remove evsel from struct hist_entry_iter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from hist-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 10 ++++------ tools/perf/builtin-diff.c | 3 +-- tools/perf/builtin-report.c | 6 ++---- tools/perf/builtin-top.c | 9 +++------ tools/perf/tests/hists_cumulate.c | 1 - tools/perf/tests/hists_filter.c | 1 - tools/perf/tests/hists_output.c | 1 - tools/perf/util/hist.c | 24 ++++++++++++------------ tools/perf/util/hist.h | 3 +-- 9 files changed, 23 insertions(+), 35 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index ee1ba2dc35f4..6f8be9ead43b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -190,14 +190,12 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, return err; } -static int process_branch_callback(struct evsel *evsel, - struct perf_sample *sample, +static int process_branch_callback(struct perf_sample *sample, struct addr_location *al, struct perf_annotate *ann, struct machine *machine) { struct hist_entry_iter iter = { - .evsel = evsel, .sample = sample, .add_entry_cb = hist_iter__branch_callback, .hide_unresolved = symbol_conf.hide_unresolved, @@ -220,8 +218,8 @@ static int process_branch_callback(struct evsel *evsel, if (a.map != NULL) dso__set_hit(map__dso(a.map)); - hist__account_cycles(sample->branch_stack, al, sample, false, - NULL, evsel); + hist__account_cycles(sample->branch_stack, al, sample, /*nonany_branch_mode=*/false, + /*total_cycles=*/NULL); ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann); out: @@ -268,7 +266,7 @@ static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample, process_branch_stack(sample->branch_stack, al, sample); if (ann->has_br_stack && has_annotation(ann)) - return process_branch_callback(evsel, sample, al, ann, machine); + return process_branch_callback(sample, al, ann, machine); he = hists__add_entry(hists, al, NULL, NULL, NULL, NULL, sample, true); if (he == NULL) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 82e9e514922b..b4ff863b304c 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -397,7 +397,6 @@ static int diff__process_sample_event(const struct perf_tool *tool, struct evsel *evsel = sample->evsel; struct hists *hists = evsel__hists(evsel); struct hist_entry_iter iter = { - .evsel = evsel, .sample = sample, .ops = &hist_iter_normal, }; @@ -431,7 +430,7 @@ static int diff__process_sample_event(const struct perf_tool *tool, } hist__account_cycles(sample->branch_stack, &al, sample, - false, NULL, evsel); + /*nonany_branch_mode=*/false, /*total_cycles=*/NULL); break; case COMPUTE_STREAM: diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index cc3ee712fe62..11c7eff92b95 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -266,10 +266,8 @@ static int process_sample_event(const struct perf_tool *tool, struct machine *machine) { struct report *rep = container_of(tool, struct report, tool); - struct evsel *evsel = sample->evsel; struct addr_location al; struct hist_entry_iter iter = { - .evsel = evsel, .sample = sample, .hide_unresolved = symbol_conf.hide_unresolved, .add_entry_cb = hist_iter__report_callback, @@ -281,7 +279,7 @@ static int process_sample_event(const struct perf_tool *tool, return 0; } - if (evswitch__discard(&rep->evswitch, evsel)) + if (evswitch__discard(&rep->evswitch, sample->evsel)) return 0; addr_location__init(&al); @@ -325,7 +323,7 @@ static int process_sample_event(const struct perf_tool *tool, if (ui__has_annotation() || rep->symbol_ipc || rep->total_cycles_mode) { hist__account_cycles(sample->branch_stack, &al, sample, rep->nonany_branch_mode, - &rep->total_cycles, evsel); + &rep->total_cycles); } rep->total_samples++; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index b4fc991b4eeb..6cf73bb0c7af 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -732,20 +732,18 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter, EXCLUSIVE_LOCKS_REQUIRED(iter->he->hists->lock) { struct perf_top *top = arg; - struct evsel *evsel = iter->evsel; if (perf_hpp_list.sym && single) perf_top__record_precise_ip(top, iter->he, iter->sample, al->addr); hist__account_cycles(iter->sample->branch_stack, al, iter->sample, !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY), - NULL, evsel); + /*total_cycles=*/NULL); return 0; } static void perf_event__process_sample(const struct perf_tool *tool, const union perf_event *event, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -831,9 +829,8 @@ static void perf_event__process_sample(const struct perf_tool *tool, } if (al.sym == NULL || !al.sym->idle) { - struct hists *hists = evsel__hists(evsel); + struct hists *hists = evsel__hists(sample->evsel); struct hist_entry_iter iter = { - .evsel = evsel, .sample = sample, .add_entry_cb = hist_iter__top_callback, }; @@ -1211,7 +1208,7 @@ static int deliver_event(struct ordered_events *qe, } if (event->header.type == PERF_RECORD_SAMPLE) { - perf_event__process_sample(&top->tool, event, evsel, + perf_event__process_sample(&top->tool, event, &sample, machine); } else if (event->header.type == PERF_RECORD_LOST) { perf_top__process_lost(top, event, evsel); diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index 606aa926a8fc..267cbc24691a 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c @@ -87,7 +87,6 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) addr_location__init(&al); for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { struct hist_entry_iter iter = { - .evsel = evsel, .sample = &sample, .hide_unresolved = false, }; diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index cc6b26e373d1..002e3a4c1ca5 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c @@ -63,7 +63,6 @@ static int add_hist_entries(struct evlist *evlist, evlist__for_each_entry(evlist, evsel) { for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { struct hist_entry_iter iter = { - .evsel = evsel, .sample = &sample, .ops = &hist_iter_normal, .hide_unresolved = false, diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index 7818950d786e..fa683fd7b1e5 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c @@ -57,7 +57,6 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) addr_location__init(&al); for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { struct hist_entry_iter iter = { - .evsel = evsel, .sample = &sample, .ops = &hist_iter_normal, .hide_unresolved = false, diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index f641cf321ace..811d68fa6770 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -935,8 +935,8 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al { u64 cost; struct mem_info *mi = iter->mi; - struct hists *hists = evsel__hists(iter->evsel); struct perf_sample *sample = iter->sample; + struct hists *hists = evsel__hists(sample->evsel); struct hist_entry *he; if (mi == NULL) @@ -968,7 +968,7 @@ static int iter_finish_mem_entry(struct hist_entry_iter *iter, struct addr_location *al __maybe_unused) { - struct evsel *evsel = iter->evsel; + struct evsel *evsel = iter->sample->evsel; struct hists *hists = evsel__hists(evsel); struct hist_entry *he = iter->he; int err = -EINVAL; @@ -1036,9 +1036,9 @@ static int iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al) { struct branch_info *bi; - struct evsel *evsel = iter->evsel; - struct hists *hists = evsel__hists(evsel); struct perf_sample *sample = iter->sample; + struct evsel *evsel = sample->evsel; + struct hists *hists = evsel__hists(evsel); struct hist_entry *he = NULL; int i = iter->curr; int err = 0; @@ -1078,7 +1078,7 @@ static int iter_finish_branch_entry(struct hist_entry_iter *iter, struct addr_location *al __maybe_unused) { - struct evsel *evsel = iter->evsel; + struct evsel *evsel = iter->sample->evsel; struct hists *hists = evsel__hists(evsel); for (int i = 0; i < iter->total; i++) @@ -1103,8 +1103,8 @@ iter_prepare_normal_entry(struct hist_entry_iter *iter __maybe_unused, static int iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location *al) { - struct evsel *evsel = iter->evsel; struct perf_sample *sample = iter->sample; + struct evsel *evsel = sample->evsel; struct hist_entry *he; he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, @@ -1121,8 +1121,8 @@ iter_finish_normal_entry(struct hist_entry_iter *iter, struct addr_location *al __maybe_unused) { struct hist_entry *he = iter->he; - struct evsel *evsel = iter->evsel; struct perf_sample *sample = iter->sample; + struct evsel *evsel = sample->evsel; if (he == NULL) return 0; @@ -1165,9 +1165,9 @@ static int iter_add_single_cumulative_entry(struct hist_entry_iter *iter, struct addr_location *al) { - struct evsel *evsel = iter->evsel; - struct hists *hists = evsel__hists(evsel); struct perf_sample *sample = iter->sample; + struct evsel *evsel = sample->evsel; + struct hists *hists = evsel__hists(evsel); struct hist_entry **he_cache = iter->he_cache; struct hist_entry *he; int err = 0; @@ -1224,8 +1224,8 @@ static int iter_add_next_cumulative_entry(struct hist_entry_iter *iter, struct addr_location *al) { - struct evsel *evsel = iter->evsel; struct perf_sample *sample = iter->sample; + struct evsel *evsel = sample->evsel; struct hist_entry **he_cache = iter->he_cache; struct hist_entry *he; struct hist_entry he_tmp = { @@ -2826,7 +2826,7 @@ int hists__unlink(struct hists *hists) void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, struct perf_sample *sample, bool nonany_branch_mode, - u64 *total_cycles, struct evsel *evsel) + u64 *total_cycles) { struct branch_info *bi; struct branch_entry *entries = perf_sample__branch_entries(sample); @@ -2850,7 +2850,7 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, for (int i = bs->nr - 1; i >= 0; i--) { addr_map_symbol__account_cycles(&bi[i].from, nonany_branch_mode ? NULL : prev, - bi[i].flags.cycles, evsel, + bi[i].flags.cycles, sample->evsel, bi[i].branch_stack_cntr); prev = &bi[i].to; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index d97a4efb9250..8fb89d81ef06 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -156,7 +156,6 @@ struct hist_entry_iter { int total; int curr; - struct evsel *evsel; struct perf_sample *sample; struct hist_entry *he; struct symbol *parent; @@ -799,7 +798,7 @@ unsigned int hists__overhead_width(struct hists *hists); void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, struct perf_sample *sample, bool nonany_branch_mode, - u64 *total_cycles, struct evsel *evsel); + u64 *total_cycles); struct option; int parse_filter_percentage(const struct option *opt, const char *arg, int unset); From a8cb37a5b050598234d8da0790df0aef5f6acf31 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:16 -0700 Subject: [PATCH 053/343] perf report: Directly use sample->evsel to avoid computing from sample->id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In count_lost_samples_events try to avoid searching for the evsel for the sample, just use the variable within the sample. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 11c7eff92b95..973d97af8501 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -789,9 +789,11 @@ static int count_lost_samples_event(const struct perf_tool *tool, struct machine *machine __maybe_unused) { struct report *rep = container_of(tool, struct report, tool); - struct evsel *evsel; + struct evsel *evsel = sample->evsel; + + if (!evsel) + evsel = evlist__id2evsel(rep->session->evlist, sample->id); - evsel = evlist__id2evsel(rep->session->evlist, sample->id); if (evsel) { struct hists *hists = evsel__hists(evsel); u32 count = event->lost_samples.lost; From 603495ab589dc94eecf7f438779a1c8080bc9257 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:17 -0700 Subject: [PATCH 054/343] perf annotate: Don't pass evsel to add_sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from annotate-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6f8be9ead43b..719b36d4eed5 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -232,11 +232,11 @@ static bool has_annotation(struct perf_annotate *ann) return ui__has_annotation() || ann->use_stdio2; } -static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample, - struct addr_location *al, struct perf_annotate *ann, - struct machine *machine) +static int add_sample(struct perf_sample *sample, + struct addr_location *al, struct perf_annotate *ann, + struct machine *machine) { - struct hists *hists = evsel__hists(evsel); + struct hists *hists = evsel__hists(sample->evsel); struct hist_entry *he; int ret; @@ -298,7 +298,7 @@ static int process_sample_event(const struct perf_tool *tool, goto out_put; if (!al.filtered && - evsel__add_sample(sample->evsel, sample, &al, ann, machine)) { + add_sample(sample, &al, ann, machine)) { pr_warning("problem incrementing symbol count, " "skipping event\n"); ret = -1; From ed9475b215d5fbe8412fb9c52cf34dd6a3f2f350 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:18 -0700 Subject: [PATCH 055/343] perf inject: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from inject-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 52 ++++++++++++++++-------------- tools/perf/util/synthetic-events.c | 30 ++++++++--------- tools/perf/util/synthetic-events.h | 2 -- 3 files changed, 40 insertions(+), 44 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 92ce2be1e5e2..41a3721a194d 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -147,14 +147,12 @@ struct event_entry { static int tool__inject_build_id(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine, - const struct evsel *evsel, __u16 misc, const char *filename, struct dso *dso, u32 flags); static int tool__inject_mmap2_build_id(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine, - const struct evsel *evsel, __u16 misc, __u32 pid, __u32 tid, __u64 start, __u64 len, __u64 pgoff, @@ -397,7 +395,6 @@ perf_inject__cut_auxtrace_sample(struct perf_inject *inject, typedef int (*inject_handler)(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine); static int perf_event__repipe_sample(const struct perf_tool *tool, @@ -413,7 +410,7 @@ static int perf_event__repipe_sample(const struct perf_tool *tool, if (evsel->handler) { inject_handler f = evsel->handler; - return f(tool, event, sample, evsel, machine); + return f(tool, event, sample, machine); } build_id__mark_dso_hit(tool, event, sample, machine); @@ -696,11 +693,12 @@ static int perf_event__repipe_common_mmap(const struct perf_tool *tool, } if (dso && !dso__hit(dso)) { - struct evsel *evsel = evlist__event2evsel(inject->session->evlist, event); + if (!sample->evsel) + sample->evsel = evlist__event2evsel(inject->session->evlist, event); - if (evsel) { + if (sample->evsel) { dso__set_hit(dso); - tool__inject_build_id(tool, sample, machine, evsel, + tool__inject_build_id(tool, sample, machine, /*misc=*/sample->cpumode, filename, dso, flags); } @@ -727,23 +725,26 @@ static int perf_event__repipe_common_mmap(const struct perf_tool *tool, } if ((inject->build_id_style == BID_RWS__MMAP2_BUILDID_ALL) && !(event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) { - struct evsel *evsel = evlist__event2evsel(inject->session->evlist, event); + struct evsel *saved_evsel = sample->evsel; - if (evsel && !dso_sought) { + sample->evsel = evlist__event2evsel(inject->session->evlist, event); + if (sample->evsel && !dso_sought) { dso = findnew_dso(pid, tid, filename, dso_id, machine); dso_sought = true; } - if (evsel && dso && - !tool__inject_mmap2_build_id(tool, sample, machine, evsel, + if (sample->evsel && dso && + !tool__inject_mmap2_build_id(tool, sample, machine, sample->cpumode | PERF_RECORD_MISC_MMAP_BUILD_ID, pid, tid, start, len, pgoff, dso, prot, flags, filename)) { /* Injected mmap2 so no need to repipe. */ + sample->evsel = saved_evsel; dso__put(dso); return 0; } + sample->evsel = saved_evsel; } dso__put(dso); if (inject->build_id_style == BID_RWS__MMAP2_BUILDID_LAZY) @@ -948,7 +949,6 @@ static bool perf_inject__lookup_known_build_id(struct perf_inject *inject, static int tool__inject_build_id(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine, - const struct evsel *evsel, __u16 misc, const char *filename, struct dso *dso, u32 flags) @@ -972,7 +972,7 @@ static int tool__inject_build_id(const struct perf_tool *tool, err = perf_event__synthesize_build_id(tool, sample, machine, perf_event__repipe, - evsel, misc, dso__bid(dso), + misc, dso__bid(dso), filename); if (err) { pr_err("Can't synthesize build_id event for %s\n", filename); @@ -985,7 +985,6 @@ static int tool__inject_build_id(const struct perf_tool *tool, static int tool__inject_mmap2_build_id(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine, - const struct evsel *evsel, __u16 misc, __u32 pid, __u32 tid, __u64 start, __u64 len, __u64 pgoff, @@ -1008,7 +1007,6 @@ static int tool__inject_mmap2_build_id(const struct perf_tool *tool, err = perf_event__synthesize_mmap2_build_id(tool, sample, machine, perf_event__repipe, - evsel, misc, pid, tid, start, len, pgoff, dso__bid(dso), @@ -1025,7 +1023,7 @@ static int mark_dso_hit(const struct perf_inject *inject, const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine, - const struct evsel *mmap_evsel, + struct evsel *mmap_evsel, struct map *map, bool sample_in_dso) { struct dso *dso; @@ -1053,9 +1051,13 @@ static int mark_dso_hit(const struct perf_inject *inject, dso = map__dso(map); if (inject->build_id_style == BID_RWS__INJECT_HEADER_LAZY) { if (dso && !dso__hit(dso)) { + /* + * The sample is just read for identifiers which we want + * to match the for the event of the sample. + */ dso__set_hit(dso); tool__inject_build_id(tool, sample, machine, - mmap_evsel, misc, dso__long_name(dso), dso, + misc, dso__long_name(dso), dso, map__flags(map)); } } else if (inject->build_id_style == BID_RWS__MMAP2_BUILDID_LAZY) { @@ -1063,11 +1065,13 @@ static int mark_dso_hit(const struct perf_inject *inject, const struct build_id null_bid = { .size = 0 }; const struct build_id *bid = dso ? dso__bid(dso) : &null_bid; const char *filename = dso ? dso__long_name(dso) : ""; + struct evsel *saved_evsel = sample->evsel; map__set_hit(map); + /* Creating a new mmap2 event which has an evsel for the mmap event. */ + sample->evsel = mmap_evsel; perf_event__synthesize_mmap2_build_id(tool, sample, machine, perf_event__repipe, - mmap_evsel, misc, sample->pid, sample->tid, map__start(map), @@ -1077,6 +1081,7 @@ static int mark_dso_hit(const struct perf_inject *inject, map__prot(map), map__flags(map), filename); + sample->evsel = saved_evsel; } } return 0; @@ -1087,7 +1092,7 @@ struct mark_dso_hit_args { const struct perf_tool *tool; struct perf_sample *sample; struct machine *machine; - const struct evsel *mmap_evsel; + struct evsel *mmap_evsel; }; static int mark_dso_hit_callback(struct callchain_cursor_node *node, void *data) @@ -1142,7 +1147,6 @@ static int perf_event__inject_buildid(const struct perf_tool *tool, union perf_e static int perf_inject__sched_process_exit(const struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, - struct evsel *evsel __maybe_unused, struct machine *machine __maybe_unused) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); @@ -1162,13 +1166,12 @@ static int perf_inject__sched_process_exit(const struct perf_tool *tool, static int perf_inject__sched_switch(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); struct event_entry *ent; - perf_inject__sched_process_exit(tool, event, sample, evsel, machine); + perf_inject__sched_process_exit(tool, event, sample, machine); ent = malloc(event->header.size + sizeof(struct event_entry)); if (ent == NULL) { @@ -1187,13 +1190,13 @@ static int perf_inject__sched_switch(const struct perf_tool *tool, static int perf_inject__sched_stat(const struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct event_entry *ent; union perf_event *event_sw; struct perf_sample sample_sw; struct perf_inject *inject = container_of(tool, struct perf_inject, tool); + struct evsel *evsel = sample->evsel; u32 pid = perf_sample__intval(sample, "pid"); int ret; @@ -1559,7 +1562,7 @@ static int synthesize_build_id(struct perf_inject *inject, struct dso *dso, pid_ dso__set_hit(dso); return perf_event__synthesize_build_id(&inject->tool, &synth_sample, machine, - process_build_id, inject__mmap_evsel(inject), + process_build_id, /*misc=*/synth_sample.cpumode, dso__bid(dso), dso__long_name(dso)); } @@ -2121,7 +2124,6 @@ static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char * static int drop_sample(const struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, - struct evsel *evsel __maybe_unused, struct machine *machine __maybe_unused) { return 0; diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index 2461f25a4d7d..fd1d4c0345d6 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -2263,13 +2263,15 @@ int perf_event__synthesize_build_id(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine, perf_event__handler_t process, - const struct evsel *evsel, __u16 misc, const struct build_id *bid, const char *filename) { union perf_event ev; size_t len; + u64 sample_type = sample->evsel ? sample->evsel->core.attr.sample_type : 0; + void *array = &ev; + int ret; len = sizeof(ev.build_id) + strlen(filename) + 1; len = PERF_ALIGN(len, sizeof(u64)); @@ -2286,23 +2288,17 @@ int perf_event__synthesize_build_id(const struct perf_tool *tool, ev.build_id.header.size = len; strcpy(ev.build_id.filename, filename); - if (evsel) { - void *array = &ev; - int ret; + array += ev.header.size; + ret = perf_event__synthesize_id_sample(array, sample_type, sample); + if (ret < 0) + return ret; - array += ev.header.size; - ret = perf_event__synthesize_id_sample(array, evsel->core.attr.sample_type, sample); - if (ret < 0) - return ret; - - if (ret & 7) { - pr_err("Bad id sample size %d\n", ret); - return -EINVAL; - } - - ev.header.size += ret; + if (ret & 7) { + pr_err("Bad id sample size %d\n", ret); + return -EINVAL; } + ev.header.size += ret; return process(tool, &ev, sample, machine); } @@ -2310,7 +2306,6 @@ int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine, perf_event__handler_t process, - const struct evsel *evsel, __u16 misc, __u32 pid, __u32 tid, __u64 start, __u64 len, __u64 pgoff, @@ -2320,6 +2315,7 @@ int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool, { union perf_event ev; size_t ev_len; + u64 sample_type = sample->evsel ? sample->evsel->core.attr.sample_type : 0; void *array; int ret; @@ -2350,7 +2346,7 @@ int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool, array = &ev; array += ev.header.size; - ret = perf_event__synthesize_id_sample(array, evsel->core.attr.sample_type, sample); + ret = perf_event__synthesize_id_sample(array, sample_type, sample); if (ret < 0) return ret; diff --git a/tools/perf/util/synthetic-events.h b/tools/perf/util/synthetic-events.h index 8c7f49f9ccf5..243115ea61ae 100644 --- a/tools/perf/util/synthetic-events.h +++ b/tools/perf/util/synthetic-events.h @@ -50,7 +50,6 @@ int perf_event__synthesize_build_id(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine, perf_event__handler_t process, - const struct evsel *evsel, __u16 misc, const struct build_id *bid, const char *filename); @@ -58,7 +57,6 @@ int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine, perf_event__handler_t process, - const struct evsel *evsel, __u16 misc, __u32 pid, __u32 tid, __u64 start, __u64 len, __u64 pgoff, From 511bcd0ca0fff7c47658eb80faff867830a24148 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:19 -0700 Subject: [PATCH 056/343] perf kmem: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from kmem-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 2cdc56bc2616..68a39f56204d 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -171,7 +171,7 @@ static int insert_caller_stat(unsigned long call_site, return 0; } -static int evsel__process_alloc_event(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_alloc_event(struct perf_sample *sample) { unsigned long ptr = perf_sample__intval(sample, "ptr"), call_site = perf_sample__intval(sample, "call_site"); @@ -198,7 +198,7 @@ static int evsel__process_alloc_event(struct evsel *evsel, struct perf_sample *s * If the tracepoint contains the field "node" the tool stats the * cross allocation. */ - if (evsel__field(evsel, "node")) { + if (evsel__field(sample->evsel, "node")) { int node1, node2; node1 = cpu__get_node((struct perf_cpu){.cpu = sample->cpu}); @@ -243,7 +243,7 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr, return NULL; } -static int evsel__process_free_event(struct evsel *evsel __maybe_unused, struct perf_sample *sample) +static int evsel__process_free_event(struct perf_sample *sample) { unsigned long ptr = perf_sample__intval(sample, "ptr"); struct alloc_stat *s_alloc, *s_caller; @@ -751,8 +751,7 @@ static char *compact_gfp_string(unsigned long gfp_flags) return NULL; } -static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample, - unsigned int gfp_flags) +static int parse_gfp_flags(struct perf_sample *sample, unsigned int gfp_flags) { struct tep_record record = { .cpu = sample->cpu, @@ -773,7 +772,7 @@ static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample, } trace_seq_init(&seq); - tp_format = evsel__tp_format(evsel); + tp_format = evsel__tp_format(sample->evsel); if (tp_format) tep_print_event(tp_format->tep, &seq, &record, "%s", TEP_PRINT_INFO); @@ -805,7 +804,7 @@ static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample, return 0; } -static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_sample *sample) +static int evsel__process_page_alloc_event(struct perf_sample *sample) { u64 page; unsigned int order = perf_sample__intval(sample, "order"); @@ -835,7 +834,7 @@ static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_samp return 0; } - if (parse_gfp_flags(evsel, sample, gfp_flags) < 0) + if (parse_gfp_flags(sample, gfp_flags) < 0) return -1; callsite = find_callsite(sample); @@ -876,8 +875,7 @@ static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_samp return 0; } -static int evsel__process_page_free_event(struct evsel *evsel __maybe_unused, - struct perf_sample *sample) +static int evsel__process_page_free_event(struct perf_sample *sample) { u64 page; unsigned int order = perf_sample__intval(sample, "order"); @@ -954,8 +952,7 @@ static bool perf_kmem__skip_sample(struct perf_sample *sample) return false; } -typedef int (*tracepoint_handler)(struct evsel *evsel, - struct perf_sample *sample); +typedef int (*tracepoint_handler)(struct perf_sample *sample); static int process_sample_event(const struct perf_tool *tool __maybe_unused, union perf_event *event, @@ -973,14 +970,15 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, return -1; } - if (perf_kmem__skip_sample(sample)) + if (perf_kmem__skip_sample(sample)) { return 0; + } dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread__tid(thread)); if (evsel->handler != NULL) { tracepoint_handler f = evsel->handler; - err = f(evsel, sample); + err = f(sample); } thread__put(thread); From bad8999c68895c151ad7c0d9495e59a88787e6ca Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:20 -0700 Subject: [PATCH 057/343] perf kwork: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from kwork-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kwork.c | 74 +++++++++++++------------------------- tools/perf/util/kwork.h | 9 +++-- 2 files changed, 28 insertions(+), 55 deletions(-) diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index 4b312afed830..59a54d11f7fa 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -448,7 +448,6 @@ static int work_push_atom(struct perf_kwork *kwork, struct kwork_class *class, enum kwork_trace_type src_type, enum kwork_trace_type dst_type, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine, struct kwork_work **ret_work, @@ -458,7 +457,7 @@ static int work_push_atom(struct perf_kwork *kwork, struct kwork_work *work, key; BUG_ON(class->work_init == NULL); - class->work_init(kwork, class, &key, src_type, evsel, sample, machine); + class->work_init(kwork, class, &key, src_type, sample, machine); atom = atom_new(kwork, sample); if (atom == NULL) @@ -507,7 +506,6 @@ static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork, struct kwork_class *class, enum kwork_trace_type src_type, enum kwork_trace_type dst_type, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine, struct kwork_work **ret_work) @@ -516,7 +514,7 @@ static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork, struct kwork_work *work, key; BUG_ON(class->work_init == NULL); - class->work_init(kwork, class, &key, src_type, evsel, sample, machine); + class->work_init(kwork, class, &key, src_type, sample, machine); work = work_findnew(&class->work_root, &key, &kwork->cmp_id); if (ret_work != NULL) @@ -599,18 +597,16 @@ static void report_update_exit_event(struct kwork_work *work, static int report_entry_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { return work_push_atom(kwork, class, KWORK_TRACE_ENTRY, - KWORK_TRACE_MAX, evsel, sample, + KWORK_TRACE_MAX, sample, machine, NULL, true); } static int report_exit_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -618,7 +614,7 @@ static int report_exit_event(struct perf_kwork *kwork, struct kwork_work *work = NULL; atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT, - KWORK_TRACE_ENTRY, evsel, sample, + KWORK_TRACE_ENTRY, sample, machine, &work); if (work == NULL) return -1; @@ -654,18 +650,16 @@ static void latency_update_entry_event(struct kwork_work *work, static int latency_raise_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { return work_push_atom(kwork, class, KWORK_TRACE_RAISE, - KWORK_TRACE_MAX, evsel, sample, + KWORK_TRACE_MAX, sample, machine, NULL, true); } static int latency_entry_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -673,7 +667,7 @@ static int latency_entry_event(struct perf_kwork *kwork, struct kwork_work *work = NULL; atom = work_pop_atom(kwork, class, KWORK_TRACE_ENTRY, - KWORK_TRACE_RAISE, evsel, sample, + KWORK_TRACE_RAISE, sample, machine, &work); if (work == NULL) return -1; @@ -812,18 +806,16 @@ static void timehist_print_event(struct perf_kwork *kwork, static int timehist_raise_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { return work_push_atom(kwork, class, KWORK_TRACE_RAISE, - KWORK_TRACE_MAX, evsel, sample, + KWORK_TRACE_MAX, sample, machine, NULL, true); } static int timehist_entry_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -831,7 +823,7 @@ static int timehist_entry_event(struct perf_kwork *kwork, struct kwork_work *work = NULL; ret = work_push_atom(kwork, class, KWORK_TRACE_ENTRY, - KWORK_TRACE_RAISE, evsel, sample, + KWORK_TRACE_RAISE, sample, machine, &work, true); if (ret) return ret; @@ -844,7 +836,6 @@ static int timehist_entry_event(struct perf_kwork *kwork, static int timehist_exit_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -861,7 +852,7 @@ static int timehist_exit_event(struct perf_kwork *kwork, } atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT, - KWORK_TRACE_ENTRY, evsel, sample, + KWORK_TRACE_ENTRY, sample, machine, &work); if (work == NULL) { ret = -1; @@ -895,18 +886,16 @@ static void top_update_runtime(struct kwork_work *work, static int top_entry_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { return work_push_atom(kwork, class, KWORK_TRACE_ENTRY, - KWORK_TRACE_MAX, evsel, sample, + KWORK_TRACE_MAX, sample, machine, NULL, true); } static int top_exit_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -915,7 +904,7 @@ static int top_exit_event(struct perf_kwork *kwork, struct kwork_atom *atom; atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT, - KWORK_TRACE_ENTRY, evsel, sample, + KWORK_TRACE_ENTRY, sample, machine, &work); if (!work) return -1; @@ -936,7 +925,6 @@ static int top_exit_event(struct perf_kwork *kwork, static int top_sched_switch_event(struct perf_kwork *kwork, struct kwork_class *class, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -944,7 +932,7 @@ static int top_sched_switch_event(struct perf_kwork *kwork, struct kwork_work *work; atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT, - KWORK_TRACE_ENTRY, evsel, sample, + KWORK_TRACE_ENTRY, sample, machine, &work); if (!work) return -1; @@ -954,12 +942,11 @@ static int top_sched_switch_event(struct perf_kwork *kwork, atom_del(atom); } - return top_entry_event(kwork, class, evsel, sample, machine); + return top_entry_event(kwork, class, sample, machine); } static struct kwork_class kwork_irq; static int process_irq_handler_entry_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -967,12 +954,11 @@ static int process_irq_handler_entry_event(const struct perf_tool *tool, if (kwork->tp_handler->entry_event) return kwork->tp_handler->entry_event(kwork, &kwork_irq, - evsel, sample, machine); + sample, machine); return 0; } static int process_irq_handler_exit_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -980,7 +966,7 @@ static int process_irq_handler_exit_event(const struct perf_tool *tool, if (kwork->tp_handler->exit_event) return kwork->tp_handler->exit_event(kwork, &kwork_irq, - evsel, sample, machine); + sample, machine); return 0; } @@ -1005,7 +991,6 @@ static void irq_work_init(struct perf_kwork *kwork, struct kwork_class *class, struct kwork_work *work, enum kwork_trace_type src_type __maybe_unused, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine __maybe_unused) { @@ -1038,7 +1023,6 @@ static struct kwork_class kwork_irq = { static struct kwork_class kwork_softirq; static int process_softirq_raise_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1046,13 +1030,12 @@ static int process_softirq_raise_event(const struct perf_tool *tool, if (kwork->tp_handler->raise_event) return kwork->tp_handler->raise_event(kwork, &kwork_softirq, - evsel, sample, machine); + sample, machine); return 0; } static int process_softirq_entry_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1060,13 +1043,12 @@ static int process_softirq_entry_event(const struct perf_tool *tool, if (kwork->tp_handler->entry_event) return kwork->tp_handler->entry_event(kwork, &kwork_softirq, - evsel, sample, machine); + sample, machine); return 0; } static int process_softirq_exit_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1074,7 +1056,7 @@ static int process_softirq_exit_event(const struct perf_tool *tool, if (kwork->tp_handler->exit_event) return kwork->tp_handler->exit_event(kwork, &kwork_softirq, - evsel, sample, machine); + sample, machine); return 0; } @@ -1133,7 +1115,6 @@ static void softirq_work_init(struct perf_kwork *kwork, struct kwork_class *class, struct kwork_work *work, enum kwork_trace_type src_type __maybe_unused, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused) { @@ -1148,7 +1129,7 @@ static void softirq_work_init(struct perf_kwork *kwork, } else { num = perf_sample__intval(sample, "vec"); work->id = num; - work->name = evsel__softirq_name(evsel, num); + work->name = evsel__softirq_name(sample->evsel, num); } } @@ -1169,7 +1150,6 @@ static struct kwork_class kwork_softirq = { static struct kwork_class kwork_workqueue; static int process_workqueue_activate_work_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1177,13 +1157,12 @@ static int process_workqueue_activate_work_event(const struct perf_tool *tool, if (kwork->tp_handler->raise_event) return kwork->tp_handler->raise_event(kwork, &kwork_workqueue, - evsel, sample, machine); + sample, machine); return 0; } static int process_workqueue_execute_start_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1191,13 +1170,12 @@ static int process_workqueue_execute_start_event(const struct perf_tool *tool, if (kwork->tp_handler->entry_event) return kwork->tp_handler->entry_event(kwork, &kwork_workqueue, - evsel, sample, machine); + sample, machine); return 0; } static int process_workqueue_execute_end_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1205,7 +1183,7 @@ static int process_workqueue_execute_end_event(const struct perf_tool *tool, if (kwork->tp_handler->exit_event) return kwork->tp_handler->exit_event(kwork, &kwork_workqueue, - evsel, sample, machine); + sample, machine); return 0; } @@ -1233,7 +1211,6 @@ static void workqueue_work_init(struct perf_kwork *kwork __maybe_unused, struct kwork_class *class, struct kwork_work *work, enum kwork_trace_type src_type __maybe_unused, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { @@ -1267,7 +1244,6 @@ static struct kwork_class kwork_workqueue = { static struct kwork_class kwork_sched; static int process_sched_switch_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1275,7 +1251,7 @@ static int process_sched_switch_event(const struct perf_tool *tool, if (kwork->tp_handler->sched_switch_event) return kwork->tp_handler->sched_switch_event(kwork, &kwork_sched, - evsel, sample, machine); + sample, machine); return 0; } @@ -1300,7 +1276,6 @@ static void sched_work_init(struct perf_kwork *kwork __maybe_unused, struct kwork_class *class, struct kwork_work *work, enum kwork_trace_type src_type, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine __maybe_unused) { @@ -1946,7 +1921,6 @@ static int perf_kwork__report(struct perf_kwork *kwork) } typedef int (*tracepoint_handler)(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine); @@ -1961,7 +1935,7 @@ static int perf_kwork__process_tracepoint_sample(const struct perf_tool *tool, if (evsel->handler != NULL) { tracepoint_handler f = evsel->handler; - err = f(tool, evsel, sample, machine); + err = f(tool, sample, machine); } return err; diff --git a/tools/perf/util/kwork.h b/tools/perf/util/kwork.h index db00269b73f2..abf637d44794 100644 --- a/tools/perf/util/kwork.h +++ b/tools/perf/util/kwork.h @@ -157,7 +157,6 @@ struct kwork_class { struct kwork_class *class, struct kwork_work *work, enum kwork_trace_type src_type, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine); @@ -167,19 +166,19 @@ struct kwork_class { struct trace_kwork_handler { int (*raise_event)(struct perf_kwork *kwork, - struct kwork_class *class, struct evsel *evsel, + struct kwork_class *class, struct perf_sample *sample, struct machine *machine); int (*entry_event)(struct perf_kwork *kwork, - struct kwork_class *class, struct evsel *evsel, + struct kwork_class *class, struct perf_sample *sample, struct machine *machine); int (*exit_event)(struct perf_kwork *kwork, - struct kwork_class *class, struct evsel *evsel, + struct kwork_class *class, struct perf_sample *sample, struct machine *machine); int (*sched_switch_event)(struct perf_kwork *kwork, - struct kwork_class *class, struct evsel *evsel, + struct kwork_class *class, struct perf_sample *sample, struct machine *machine); }; From 1ac10645bb29265048b3e982d0de6b06ccb4cf2d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:21 -0700 Subject: [PATCH 058/343] perf sched: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from sched-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 92 ++++++++++++++------------------------ 1 file changed, 34 insertions(+), 58 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 2a971081918b..d984e58c7dbf 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -129,21 +129,20 @@ typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *); struct perf_sched; struct trace_sched_handler { - int (*switch_event)(struct perf_sched *sched, struct evsel *evsel, - struct perf_sample *sample, struct machine *machine); + int (*switch_event)(struct perf_sched *sched, struct perf_sample *sample, + struct machine *machine); - int (*runtime_event)(struct perf_sched *sched, struct evsel *evsel, - struct perf_sample *sample, struct machine *machine); + int (*runtime_event)(struct perf_sched *sched, struct perf_sample *sample, + struct machine *machine); - int (*wakeup_event)(struct perf_sched *sched, struct evsel *evsel, - struct perf_sample *sample, struct machine *machine); + int (*wakeup_event)(struct perf_sched *sched, struct perf_sample *sample, + struct machine *machine); /* PERF_RECORD_FORK event, not sched_process_fork tracepoint */ int (*fork_event)(struct perf_sched *sched, union perf_event *event, struct machine *machine); int (*migrate_task_event)(struct perf_sched *sched, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine); }; @@ -826,7 +825,7 @@ static void test_calibrations(struct perf_sched *sched) static int replay_wakeup_event(struct perf_sched *sched, - struct evsel *evsel, struct perf_sample *sample, + struct perf_sample *sample, struct machine *machine __maybe_unused) { const char *comm = perf_sample__strval(sample, "comm"); @@ -834,7 +833,7 @@ replay_wakeup_event(struct perf_sched *sched, struct task_desc *waker, *wakee; if (verbose > 0) { - printf("sched_wakeup event %p\n", evsel); + printf("sched_wakeup event %p\n", sample->evsel); printf(" ... pid %d woke up %s/%d\n", sample->tid, comm, pid); } @@ -847,7 +846,6 @@ replay_wakeup_event(struct perf_sched *sched, } static int replay_switch_event(struct perf_sched *sched, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused) { @@ -861,7 +859,7 @@ static int replay_switch_event(struct perf_sched *sched, s64 delta; if (verbose > 0) - printf("sched_switch event %p\n", evsel); + printf("sched_switch event %p\n", sample->evsel); if (cpu >= MAX_CPUS || cpu < 0) return 0; @@ -1134,7 +1132,6 @@ static void free_work_atoms(struct work_atoms *atoms) } static int latency_switch_event(struct perf_sched *sched, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { @@ -1204,7 +1201,6 @@ static int latency_switch_event(struct perf_sched *sched, } static int latency_runtime_event(struct perf_sched *sched, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { @@ -1239,7 +1235,6 @@ static int latency_runtime_event(struct perf_sched *sched, } static int latency_wakeup_event(struct perf_sched *sched, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { @@ -1300,7 +1295,6 @@ static int latency_wakeup_event(struct perf_sched *sched, } static int latency_migrate_task_event(struct perf_sched *sched, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, struct machine *machine) { @@ -1519,20 +1513,18 @@ static void perf_sched__sort_lat(struct perf_sched *sched) } static int process_sched_wakeup_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { struct perf_sched *sched = container_of(tool, struct perf_sched, tool); if (sched->tp_handler->wakeup_event) - return sched->tp_handler->wakeup_event(sched, evsel, sample, machine); + return sched->tp_handler->wakeup_event(sched, sample, machine); return 0; } static int process_sched_wakeup_ignore(const struct perf_tool *tool __maybe_unused, - struct evsel *evsel __maybe_unused, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) { @@ -1626,8 +1618,8 @@ static void print_sched_map(struct perf_sched *sched, struct perf_cpu this_cpu, } } -static int map_switch_event(struct perf_sched *sched, struct evsel *evsel __maybe_unused, - struct perf_sample *sample, struct machine *machine) +static int map_switch_event(struct perf_sched *sched, struct perf_sample *sample, + struct machine *machine) { const u32 next_pid = perf_sample__intval(sample, "next_pid"); const u32 prev_pid = perf_sample__intval(sample, "prev_pid"); @@ -1791,7 +1783,6 @@ static int map_switch_event(struct perf_sched *sched, struct evsel *evsel __mayb } static int process_sched_switch_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -1810,21 +1801,20 @@ static int process_sched_switch_event(const struct perf_tool *tool, } if (sched->tp_handler->switch_event) - err = sched->tp_handler->switch_event(sched, evsel, sample, machine); + err = sched->tp_handler->switch_event(sched, sample, machine); sched->curr_pid[this_cpu] = next_pid; return err; } static int process_sched_runtime_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { struct perf_sched *sched = container_of(tool, struct perf_sched, tool); if (sched->tp_handler->runtime_event) - return sched->tp_handler->runtime_event(sched, evsel, sample, machine); + return sched->tp_handler->runtime_event(sched, sample, machine); return 0; } @@ -1847,20 +1837,18 @@ static int perf_sched__process_fork_event(const struct perf_tool *tool, } static int process_sched_migrate_task_event(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { struct perf_sched *sched = container_of(tool, struct perf_sched, tool); if (sched->tp_handler->migrate_task_event) - return sched->tp_handler->migrate_task_event(sched, evsel, sample, machine); + return sched->tp_handler->migrate_task_event(sched, sample, machine); return 0; } typedef int (*tracepoint_handler)(const struct perf_tool *tool, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine); @@ -1874,7 +1862,7 @@ static int perf_sched__process_tracepoint_sample(const struct perf_tool *tool __ if (evsel->handler != NULL) { tracepoint_handler f = evsel->handler; - err = f(tool, evsel, sample, machine); + err = f(tool, sample, machine); } return err; @@ -2313,11 +2301,10 @@ static void timehist_update_runtime_stats(struct thread_runtime *r, r->total_pre_mig_time += r->dt_pre_mig; } -static bool is_idle_sample(struct perf_sample *sample, - struct evsel *evsel) +static bool is_idle_sample(struct perf_sample *sample) { /* pid 0 == swapper == idle task */ - if (evsel__name_is(evsel, "sched:sched_switch")) + if (evsel__name_is(sample->evsel, "sched:sched_switch")) return perf_sample__intval(sample, "prev_pid") == 0; return sample->pid == 0; @@ -2499,12 +2486,11 @@ static void save_idle_callchain(struct perf_sched *sched, static struct thread *timehist_get_thread(struct perf_sched *sched, struct perf_sample *sample, - struct machine *machine, - struct evsel *evsel) + struct machine *machine) { struct thread *thread; - if (is_idle_sample(sample, evsel)) { + if (is_idle_sample(sample)) { thread = get_idle_thread(sample->cpu); if (thread == NULL) pr_err("Failed to get idle thread for cpu %d.\n", sample->cpu); @@ -2547,7 +2533,6 @@ static struct thread *timehist_get_thread(struct perf_sched *sched, static bool timehist_skip_sample(struct perf_sched *sched, struct thread *thread, - struct evsel *evsel, struct perf_sample *sample) { bool rc = false; @@ -2569,7 +2554,7 @@ static bool timehist_skip_sample(struct perf_sched *sched, tr = thread__get_runtime(thread); if (tr && tr->prio != -1) prio = tr->prio; - else if (evsel__name_is(evsel, "sched:sched_switch")) + else if (evsel__name_is(sample->evsel, "sched:sched_switch")) prio = perf_sample__intval(sample, "prev_prio"); if (prio != -1 && !test_bit(prio, sched->prio_bitmap)) { @@ -2579,7 +2564,7 @@ static bool timehist_skip_sample(struct perf_sched *sched, } if (sched->idle_hist) { - if (!evsel__name_is(evsel, "sched:sched_switch")) + if (!evsel__name_is(sample->evsel, "sched:sched_switch")) rc = true; else if (perf_sample__intval(sample, "prev_pid") != 0 && perf_sample__intval(sample, "next_pid") != 0) @@ -2590,7 +2575,6 @@ static bool timehist_skip_sample(struct perf_sched *sched, } static void timehist_print_wakeup_event(struct perf_sched *sched, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine, struct thread *awakened) @@ -2603,8 +2587,8 @@ static void timehist_print_wakeup_event(struct perf_sched *sched, return; /* show wakeup unless both awakee and awaker are filtered */ - if (timehist_skip_sample(sched, thread, evsel, sample) && - timehist_skip_sample(sched, awakened, evsel, sample)) { + if (timehist_skip_sample(sched, thread, sample) && + timehist_skip_sample(sched, awakened, sample)) { thread__put(thread); return; } @@ -2628,7 +2612,6 @@ static void timehist_print_wakeup_event(struct perf_sched *sched, static int timehist_sched_wakeup_ignore(const struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, - struct evsel *evsel __maybe_unused, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) { @@ -2637,7 +2620,6 @@ static int timehist_sched_wakeup_ignore(const struct perf_tool *tool __maybe_unu static int timehist_sched_wakeup_event(const struct perf_tool *tool, union perf_event *event __maybe_unused, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -2663,14 +2645,13 @@ static int timehist_sched_wakeup_event(const struct perf_tool *tool, /* show wakeups if requested */ if (sched->show_wakeups && !perf_time__skip_sample(&sched->ptime, sample->time)) - timehist_print_wakeup_event(sched, evsel, sample, machine, thread); + timehist_print_wakeup_event(sched, sample, machine, thread); thread__put(thread); return 0; } static void timehist_print_migration_event(struct perf_sched *sched, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine, struct thread *migrated) @@ -2691,8 +2672,8 @@ static void timehist_print_migration_event(struct perf_sched *sched, if (thread == NULL) return; - if (timehist_skip_sample(sched, thread, evsel, sample) && - timehist_skip_sample(sched, migrated, evsel, sample)) { + if (timehist_skip_sample(sched, thread, sample) && + timehist_skip_sample(sched, migrated, sample)) { thread__put(thread); return; } @@ -2726,7 +2707,6 @@ static void timehist_print_migration_event(struct perf_sched *sched, static int timehist_migrate_task_event(const struct perf_tool *tool, union perf_event *event __maybe_unused, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -2751,8 +2731,7 @@ static int timehist_migrate_task_event(const struct perf_tool *tool, /* show migrations if requested */ if (sched->show_migrations) { - timehist_print_migration_event(sched, evsel, sample, - machine, thread); + timehist_print_migration_event(sched, sample, machine, thread); } thread__put(thread); @@ -2784,7 +2763,6 @@ static void timehist_update_task_prio(struct perf_sample *sample, static int timehist_sched_change_event(const struct perf_tool *tool, union perf_event *event, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine) { @@ -2808,13 +2786,13 @@ static int timehist_sched_change_event(const struct perf_tool *tool, if (sched->show_prio || sched->prio_str) timehist_update_task_prio(sample, machine); - thread = timehist_get_thread(sched, sample, machine, evsel); + thread = timehist_get_thread(sched, sample, machine); if (thread == NULL) { rc = -1; goto out; } - if (timehist_skip_sample(sched, thread, evsel, sample)) + if (timehist_skip_sample(sched, thread, sample)) goto out; tr = thread__get_runtime(thread); @@ -2823,7 +2801,7 @@ static int timehist_sched_change_event(const struct perf_tool *tool, goto out; } - tprev = evsel__get_time(evsel, sample->cpu); + tprev = evsel__get_time(sample->evsel, sample->cpu); /* * If start time given: @@ -2913,7 +2891,7 @@ static int timehist_sched_change_event(const struct perf_tool *tool, tr->migrated = 0; } - evsel__save_time(evsel, sample->time, sample->cpu); + evsel__save_time(sample->evsel, sample->time, sample->cpu); thread__put(thread); addr_location__exit(&al); @@ -2922,11 +2900,10 @@ static int timehist_sched_change_event(const struct perf_tool *tool, static int timehist_sched_switch_event(const struct perf_tool *tool, union perf_event *event, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused) { - return timehist_sched_change_event(tool, event, evsel, sample, machine); + return timehist_sched_change_event(tool, event, sample, machine); } static int process_lost(const struct perf_tool *tool __maybe_unused, @@ -3174,7 +3151,6 @@ static void timehist_print_summary(struct perf_sched *sched, typedef int (*sched_handler)(const struct perf_tool *tool, union perf_event *event, - struct evsel *evsel, struct perf_sample *sample, struct machine *machine); @@ -3196,7 +3172,7 @@ static int perf_timehist__process_sample(const struct perf_tool *tool, if (evsel->handler != NULL) { sched_handler f = evsel->handler; - err = f(tool, event, evsel, sample, machine); + err = f(tool, event, sample, machine); } return err; From 6d2b06b4ef18f690beaf04d7f648c73ac2893ac5 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:22 -0700 Subject: [PATCH 059/343] perf timechart: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from timechart-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-timechart.c | 60 +++++++++++++++------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 034e0ba3f9cb..1d24d8738519 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -567,7 +567,6 @@ static const char *cat_backtrace(union perf_event *event, } typedef int (*tracepoint_handler)(struct timechart *tchart, - struct evsel *evsel, struct perf_sample *sample, const char *backtrace); @@ -588,8 +587,8 @@ static int process_sample_event(const struct perf_tool *tool, if (evsel->handler != NULL) { tracepoint_handler f = evsel->handler; - return f(tchart, evsel, sample, - cat_backtrace(event, sample, machine)); + + return f(tchart, sample, cat_backtrace(event, sample, machine)); } return 0; @@ -597,7 +596,6 @@ static int process_sample_event(const struct perf_tool *tool, static int process_sample_cpu_idle(struct timechart *tchart __maybe_unused, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -613,7 +611,6 @@ process_sample_cpu_idle(struct timechart *tchart __maybe_unused, static int process_sample_cpu_frequency(struct timechart *tchart, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -626,7 +623,6 @@ process_sample_cpu_frequency(struct timechart *tchart, static int process_sample_sched_wakeup(struct timechart *tchart, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace) { @@ -640,7 +636,6 @@ process_sample_sched_wakeup(struct timechart *tchart, static int process_sample_sched_switch(struct timechart *tchart, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace) { @@ -656,7 +651,6 @@ process_sample_sched_switch(struct timechart *tchart, #ifdef SUPPORT_OLD_POWER_EVENTS static int process_sample_power_start(struct timechart *tchart __maybe_unused, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -669,7 +663,6 @@ process_sample_power_start(struct timechart *tchart __maybe_unused, static int process_sample_power_end(struct timechart *tchart, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -679,7 +672,6 @@ process_sample_power_end(struct timechart *tchart, static int process_sample_power_frequency(struct timechart *tchart, - struct evsel *evsel __maybe_unused, struct perf_sample *sample, const char *backtrace __maybe_unused) { @@ -849,8 +841,8 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type, static int process_enter_read(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_READ, @@ -859,8 +851,8 @@ process_enter_read(struct timechart *tchart, static int process_exit_read(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_READ, @@ -869,8 +861,8 @@ process_exit_read(struct timechart *tchart, static int process_enter_write(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_WRITE, @@ -879,8 +871,8 @@ process_enter_write(struct timechart *tchart, static int process_exit_write(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_WRITE, @@ -889,8 +881,8 @@ process_exit_write(struct timechart *tchart, static int process_enter_sync(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_SYNC, @@ -899,8 +891,8 @@ process_enter_sync(struct timechart *tchart, static int process_exit_sync(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_SYNC, @@ -909,8 +901,8 @@ process_exit_sync(struct timechart *tchart, static int process_enter_tx(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_TX, @@ -919,8 +911,8 @@ process_enter_tx(struct timechart *tchart, static int process_exit_tx(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_TX, @@ -929,8 +921,8 @@ process_exit_tx(struct timechart *tchart, static int process_enter_rx(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_RX, @@ -939,8 +931,8 @@ process_enter_rx(struct timechart *tchart, static int process_exit_rx(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_RX, @@ -949,8 +941,8 @@ process_exit_rx(struct timechart *tchart, static int process_enter_poll(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long fd = perf_sample__intval(sample, "fd"); return pid_begin_io_sample(tchart, sample->tid, IOTYPE_POLL, @@ -959,8 +951,8 @@ process_enter_poll(struct timechart *tchart, static int process_exit_poll(struct timechart *tchart, - struct evsel *evsel __maybe_unused, - struct perf_sample *sample) + struct perf_sample *sample, + const char *backtrace __maybe_unused) { long ret = perf_sample__intval(sample, "ret"); return pid_end_io_sample(tchart, sample->tid, IOTYPE_POLL, From 1f44e8fe3d128915d3bbdc7203833eead721a309 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:23 -0700 Subject: [PATCH 060/343] perf trace: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from trace-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 52 ++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 4bc30ad8fb07..d4fafae853d4 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2608,7 +2608,7 @@ static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, i return sc; } -typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel, +typedef int (*tracepoint_handler)(struct trace *trace, union perf_event *event, struct perf_sample *sample); @@ -2805,10 +2805,11 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam return NULL; } -static int trace__sys_enter(struct trace *trace, struct evsel *evsel, +static int trace__sys_enter(struct trace *trace, union perf_event *event __maybe_unused, struct perf_sample *sample) { + struct evsel *evsel = sample->evsel; char *msg; void *args; int printed = 0; @@ -2954,10 +2955,11 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sam return sample__fprintf_callchain(sample, 38, print_opts, get_tls_callchain_cursor(), symbol_conf.bt_stop_list, trace->output); } -static int trace__sys_exit(struct trace *trace, struct evsel *evsel, +static int trace__sys_exit(struct trace *trace, union perf_event *event __maybe_unused, struct perf_sample *sample) { + struct evsel *evsel = sample->evsel; long ret; u64 duration = 0; bool duration_calculated = false; @@ -3094,7 +3096,7 @@ errno_print: { return err; } -static int trace__vfs_getname(struct trace *trace, struct evsel *evsel __maybe_unused, +static int trace__vfs_getname(struct trace *trace, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -3155,7 +3157,7 @@ static int trace__vfs_getname(struct trace *trace, struct evsel *evsel __maybe_u return 0; } -static int trace__sched_stat_runtime(struct trace *trace, struct evsel *evsel, +static int trace__sched_stat_runtime(struct trace *trace, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -3177,7 +3179,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct evsel *evsel, out_dump: fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n", - evsel->name, + sample->evsel->name, perf_sample__strval(sample, "comm"), (pid_t)perf_sample__intval(sample, "pid"), runtime, @@ -3288,10 +3290,11 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct perf_sample * return fprintf(trace->output, "%.*s", (int)printed, bf); } -static int trace__event_handler(struct trace *trace, struct evsel *evsel, +static int trace__event_handler(struct trace *trace, union perf_event *event __maybe_unused, struct perf_sample *sample) { + struct evsel *evsel = sample->evsel; struct thread *thread; int callchain_ret = 0; @@ -3400,7 +3403,6 @@ static void print_location(FILE *f, struct perf_sample *sample, } static int trace__pgfault(struct trace *trace, - struct evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) { @@ -3429,7 +3431,7 @@ static int trace__pgfault(struct trace *trace, if (ttrace == NULL) goto out_put; - if (evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ) { + if (sample->evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ) { ttrace->pfmaj++; trace->pfmaj++; } else { @@ -3446,7 +3448,7 @@ static int trace__pgfault(struct trace *trace, sample->cpu, trace->output); fprintf(trace->output, "%sfault [", - evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ? + sample->evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ? "maj" : "min"); print_location(trace->output, sample, &al, false, true); @@ -3471,7 +3473,8 @@ static int trace__pgfault(struct trace *trace, if (callchain_ret > 0) trace__fprintf_callchain(trace, sample); else if (callchain_ret < 0) - pr_err("Problem processing %s callchain, skipping...\n", evsel__name(evsel)); + pr_err("Problem processing %s callchain, skipping...\n", + evsel__name(sample->evsel)); ++trace->nr_events_printed; out: @@ -3483,7 +3486,6 @@ static int trace__pgfault(struct trace *trace, } static void trace__set_base_time(struct trace *trace, - struct evsel *evsel, struct perf_sample *sample) { /* @@ -3495,7 +3497,7 @@ static void trace__set_base_time(struct trace *trace, * appears in our event stream (vfs_getname comes to mind). */ if (trace->base_time == 0 && !trace->full_time && - (evsel->core.attr.sample_type & PERF_SAMPLE_TIME)) + (sample->evsel->core.attr.sample_type & PERF_SAMPLE_TIME)) trace->base_time = sample->time; } @@ -3515,11 +3517,11 @@ static int trace__process_sample(const struct perf_tool *tool, if (thread && thread__is_filtered(thread)) goto out; - trace__set_base_time(trace, evsel, sample); + trace__set_base_time(trace, sample); if (handler) { ++trace->nr_events; - handler(trace, evsel, event, sample); + handler(trace, event, sample); } out: thread__put(thread); @@ -3661,32 +3663,34 @@ static void evlist__free_syscall_tp_fields(struct evlist *evlist) static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) { const u32 type = event->header.type; - struct evsel *evsel; if (type != PERF_RECORD_SAMPLE) { trace__process_event(trace, trace->host, event, sample); return; } - evsel = evlist__id2evsel(trace->evlist, sample->id); - if (evsel == NULL) { + if (sample->evsel == NULL) + sample->evsel = evlist__id2evsel(trace->evlist, sample->id); + + if (sample->evsel == NULL) { fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id); return; } - if (evswitch__discard(&trace->evswitch, evsel)) + if (evswitch__discard(&trace->evswitch, sample->evsel)) return; - trace__set_base_time(trace, evsel, sample); + trace__set_base_time(trace, sample); - if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT && + if (sample->evsel->core.attr.type == PERF_TYPE_TRACEPOINT && sample->raw_data == NULL) { fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", - evsel__name(evsel), sample->tid, + evsel__name(sample->evsel), sample->tid, sample->cpu, sample->raw_size); } else { - tracepoint_handler handler = evsel->handler; - handler(trace, evsel, event, sample); + tracepoint_handler handler = sample->evsel->handler; + + handler(trace, event, sample); } if (trace->nr_events_printed >= trace->max_events && trace->max_events != ULONG_MAX) From 675073ddf8779593ca32ee0cdf5371a420b87dd5 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:24 -0700 Subject: [PATCH 061/343] perf evlist: Try to avoid computing evsel from sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from evlist-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 4 +++- tools/perf/tests/mmap-basic.c | 4 +++- tools/perf/tests/switch-tracking.c | 5 ++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 6cf73bb0c7af..c8474f7ac658 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1164,7 +1164,9 @@ static int deliver_event(struct ordered_events *qe, goto next_event; } - evsel = evlist__id2evsel(session->evlist, sample.id); + evsel = sample.evsel; + if (!evsel) + evsel = evlist__id2evsel(session->evlist, sample.id); assert(evsel != NULL); if (event->header.type == PERF_RECORD_SAMPLE) { diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 3313c236104e..a18d84d858aa 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -142,7 +142,9 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest } err = -1; - evsel = evlist__id2evsel(evlist, sample.id); + evsel = sample.evsel; + if (!evsel) + evsel = evlist__id2evsel(evlist, sample.id); perf_sample__exit(&sample); if (evsel == NULL) { pr_debug("event with id %" PRIu64 diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 22b0302252db..e32331fee277 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -138,7 +138,10 @@ static int process_sample_event(struct evlist *evlist, goto out; } - evsel = evlist__id2evsel(evlist, sample.id); + evsel = sample.evsel; + if (!evsel) + evsel = evlist__id2evsel(evlist, sample.id); + if (evsel == switch_tracking->switch_evsel) { next_tid = perf_sample__intval(&sample, "next_pid"); prev_tid = perf_sample__intval(&sample, "prev_pid"); From 5e807647e155c5b2ae256849965e8311b3916d70 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:25 -0700 Subject: [PATCH 062/343] perf script: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from script-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 12 ++++-- .../util/scripting-engines/trace-event-perl.c | 21 +++++------ .../scripting-engines/trace-event-python.c | 37 ++++++++----------- tools/perf/util/trace-event-scripting.c | 5 +-- tools/perf/util/trace-event.h | 3 -- 5 files changed, 33 insertions(+), 45 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index b94a199ffcc9..c0918006e0ab 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2419,12 +2419,13 @@ static bool show_event(struct perf_sample *sample, } static void process_event(struct perf_script *script, - struct perf_sample *sample, struct evsel *evsel, + struct perf_sample *sample, struct addr_location *al, struct addr_location *addr_al, struct machine *machine) { struct thread *thread = al->thread; + struct evsel *evsel = sample->evsel; struct perf_event_attr *attr = &evsel->core.attr; unsigned int type = evsel__output_type(evsel); struct evsel_script *es = evsel->priv; @@ -2716,9 +2717,9 @@ static int process_sample_event(const struct perf_tool *tool, thread__resolve(al.thread, &addr_al, sample); addr_al_ptr = &addr_al; } - scripting_ops->process_event(event, sample, evsel, &al, addr_al_ptr); + scripting_ops->process_event(event, sample, &al, addr_al_ptr); } else { - process_event(scr, sample, evsel, &al, &addr_al, machine); + process_event(scr, sample, &al, &addr_al, machine); } out_put: @@ -2894,9 +2895,12 @@ static int print_event_with_time(const struct perf_tool *tool, { struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct evsel *evsel = evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = sample->evsel; struct thread *thread = NULL; + if (!evsel) + evsel = evlist__id2evsel(session->evlist, sample->id); + if (evsel && !evsel->core.attr.sample_id_all) { sample->cpu = 0; sample->time = timestamp; diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index af0d514b2397..7a18ea4b7d50 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -257,7 +257,6 @@ static void define_event_symbols(struct tep_event *event, } static SV *perl_process_callchain(struct perf_sample *sample, - struct evsel *evsel __maybe_unused, struct addr_location *al) { struct callchain_cursor *cursor; @@ -340,7 +339,6 @@ static SV *perl_process_callchain(struct perf_sample *sample, } static void perl_process_tracepoint(struct perf_sample *sample, - struct evsel *evsel, struct addr_location *al) { struct thread *thread = al->thread; @@ -355,6 +353,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, unsigned long long nsecs = sample->time; const char *comm = thread__comm_str(thread); DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX); + struct evsel *evsel = sample->evsel; bitmap_zero(events_defined, TRACE_EVENT_TYPE_MAX); dSP; @@ -389,7 +388,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, XPUSHs(sv_2mortal(newSVuv(ns))); XPUSHs(sv_2mortal(newSViv(pid))); XPUSHs(sv_2mortal(newSVpv(comm, 0))); - XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al))); + XPUSHs(sv_2mortal(perl_process_callchain(sample, al))); /* common fields other than pid can be accessed via xsub fns */ @@ -426,7 +425,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, XPUSHs(sv_2mortal(newSVuv(nsecs))); XPUSHs(sv_2mortal(newSViv(pid))); XPUSHs(sv_2mortal(newSVpv(comm, 0))); - XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al))); + XPUSHs(sv_2mortal(perl_process_callchain(sample, al))); call_pv("main::trace_unhandled", G_SCALAR); } SPAGAIN; @@ -435,9 +434,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, LEAVE; } -static void perl_process_event_generic(union perf_event *event, - struct perf_sample *sample, - struct evsel *evsel) +static void perl_process_event_generic(union perf_event *event, struct perf_sample *sample) { dSP; @@ -448,7 +445,8 @@ static void perl_process_event_generic(union perf_event *event, SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpvn((const char *)event, event->header.size))); - XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->core.attr, sizeof(evsel->core.attr)))); + XPUSHs(sv_2mortal(newSVpvn((const char *)&sample->evsel->core.attr, + sizeof(sample->evsel->core.attr)))); XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample)))); XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size))); PUTBACK; @@ -461,13 +459,12 @@ static void perl_process_event_generic(union perf_event *event, static void perl_process_event(union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct addr_location *al, struct addr_location *addr_al) { - scripting_context__update(scripting_context, event, sample, evsel, al, addr_al); - perl_process_tracepoint(sample, evsel, al); - perl_process_event_generic(event, sample, evsel); + scripting_context__update(scripting_context, event, sample, al, addr_al); + perl_process_tracepoint(sample, al); + perl_process_event_generic(event, sample); } static void run_start_sub(void) diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 9e1069ec0578..8edd2f36e5a9 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -390,7 +390,6 @@ static unsigned long get_offset(struct symbol *sym, struct addr_location *al) } static PyObject *python_process_callchain(struct perf_sample *sample, - struct evsel *evsel __maybe_unused, struct addr_location *al) { PyObject *pylist; @@ -651,11 +650,9 @@ static PyObject *get_sample_value_as_tuple(struct sample_read_value *value, return t; } -static void set_sample_read_in_dict(PyObject *dict_sample, - struct perf_sample *sample, - struct evsel *evsel) +static void set_sample_read_in_dict(PyObject *dict_sample, struct perf_sample *sample) { - u64 read_format = evsel->core.attr.read_format; + u64 read_format = sample->evsel->core.attr.read_format; PyObject *values; unsigned int i; @@ -741,11 +738,10 @@ static void regs_map(struct regs_dump *regs, uint64_t mask, uint16_t e_machine, static int set_regs_in_dict(PyObject *dict, struct perf_sample *sample, - struct evsel *evsel, uint16_t e_machine, uint32_t e_flags) { - struct perf_event_attr *attr = &evsel->core.attr; + struct perf_event_attr *attr = &sample->evsel->core.attr; int size = (__sw_hweight64(attr->sample_regs_intr) * MAX_REG_SIZE) + 1; char *bf = NULL; @@ -831,7 +827,6 @@ static void python_process_sample_flags(struct perf_sample *sample, PyObject *di } static PyObject *get_perf_sample_dict(struct perf_sample *sample, - struct evsel *evsel, struct addr_location *al, struct addr_location *addr_al, PyObject *callchain) @@ -839,6 +834,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, PyObject *dict, *dict_sample, *brstack, *brstacksym; uint16_t e_machine = EM_HOST; uint32_t e_flags = EF_HOST; + struct evsel *evsel = sample->evsel; dict = PyDict_New(); if (!dict) @@ -871,7 +867,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, PyLong_FromUnsignedLongLong(sample->phys_addr)); pydict_set_item_string_decref(dict_sample, "addr", PyLong_FromUnsignedLongLong(sample->addr)); - set_sample_read_in_dict(dict_sample, sample, evsel); + set_sample_read_in_dict(dict_sample, sample); pydict_set_item_string_decref(dict_sample, "weight", PyLong_FromUnsignedLongLong(sample->weight)); pydict_set_item_string_decref(dict_sample, "ins_lat", @@ -928,7 +924,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, if (al->thread) e_machine = thread__e_machine(al->thread, /*machine=*/NULL, &e_flags); - if (set_regs_in_dict(dict, sample, evsel, e_machine, e_flags)) + if (set_regs_in_dict(dict, sample, e_machine, e_flags)) Py_FatalError("Failed to setting regs in dict"); return dict; @@ -936,7 +932,6 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, #ifdef HAVE_LIBTRACEEVENT static void python_process_tracepoint(struct perf_sample *sample, - struct evsel *evsel, struct addr_location *al, struct addr_location *addr_al) { @@ -954,6 +949,7 @@ static void python_process_tracepoint(struct perf_sample *sample, const char *comm = thread__comm_str(al->thread); const char *default_handler_name = "trace_unhandled"; DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX); + struct evsel *evsel = sample->evsel; bitmap_zero(events_defined, TRACE_EVENT_TYPE_MAX); @@ -995,7 +991,7 @@ static void python_process_tracepoint(struct perf_sample *sample, PyTuple_SetItem(t, n++, context); /* ip unwinding */ - callchain = python_process_callchain(sample, evsel, al); + callchain = python_process_callchain(sample, al); /* Need an additional reference for the perf_sample dict */ Py_INCREF(callchain); @@ -1051,7 +1047,7 @@ static void python_process_tracepoint(struct perf_sample *sample, PyTuple_SetItem(t, n++, dict); if (get_argument_count(handler) == (int) n + 1) { - all_entries_dict = get_perf_sample_dict(sample, evsel, al, addr_al, + all_entries_dict = get_perf_sample_dict(sample, al, addr_al, callchain); PyTuple_SetItem(t, n++, all_entries_dict); } else { @@ -1070,7 +1066,6 @@ static void python_process_tracepoint(struct perf_sample *sample, } #else static void python_process_tracepoint(struct perf_sample *sample __maybe_unused, - struct evsel *evsel __maybe_unused, struct addr_location *al __maybe_unused, struct addr_location *addr_al __maybe_unused) { @@ -1465,7 +1460,6 @@ static int python_process_call_return(struct call_return *cr, u64 *parent_db_id, } static void python_process_general_event(struct perf_sample *sample, - struct evsel *evsel, struct addr_location *al, struct addr_location *addr_al) { @@ -1488,8 +1482,8 @@ static void python_process_general_event(struct perf_sample *sample, Py_FatalError("couldn't create Python tuple"); /* ip unwinding */ - callchain = python_process_callchain(sample, evsel, al); - dict = get_perf_sample_dict(sample, evsel, al, addr_al, callchain); + callchain = python_process_callchain(sample, al); + dict = get_perf_sample_dict(sample, al, addr_al, callchain); PyTuple_SetItem(t, n++, dict); if (_PyTuple_Resize(&t, n) == -1) @@ -1502,24 +1496,23 @@ static void python_process_general_event(struct perf_sample *sample, static void python_process_event(union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct addr_location *al, struct addr_location *addr_al) { struct tables *tables = &tables_global; - scripting_context__update(scripting_context, event, sample, evsel, al, addr_al); + scripting_context__update(scripting_context, event, sample, al, addr_al); - switch (evsel->core.attr.type) { + switch (sample->evsel->core.attr.type) { case PERF_TYPE_TRACEPOINT: - python_process_tracepoint(sample, evsel, al, addr_al); + python_process_tracepoint(sample, al, addr_al); break; /* Reserve for future process_hw/sw/raw APIs */ default: if (tables->db_export_mode) db_export__sample(&tables->dbe, event, sample, al, addr_al); else - python_process_general_event(sample, evsel, al, addr_al); + python_process_general_event(sample, al, addr_al); } } diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index fa850e44cb46..dc584ac316a3 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -103,12 +103,11 @@ int script_spec__for_each(int (*cb)(struct scripting_ops *ops, const char *spec) void scripting_context__update(struct scripting_context *c, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct addr_location *al, struct addr_location *addr_al) { #ifdef HAVE_LIBTRACEEVENT - const struct tep_event *tp_format = evsel__tp_format(evsel); + const struct tep_event *tp_format = evsel__tp_format(sample->evsel); c->pevent = tp_format ? tp_format->tep : NULL; #else @@ -117,7 +116,6 @@ void scripting_context__update(struct scripting_context *c, c->event_data = sample->raw_data; c->event = event; c->sample = sample; - c->evsel = evsel; c->al = al; c->addr_al = addr_al; } @@ -134,7 +132,6 @@ static int stop_script_unsupported(void) static void process_event_unsupported(union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, - struct evsel *evsel __maybe_unused, struct addr_location *al __maybe_unused, struct addr_location *addr_al __maybe_unused) { diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 914d9b69ed62..720121c74f1d 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -94,7 +94,6 @@ struct scripting_ops { int (*stop_script) (void); void (*process_event) (union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct addr_location *al, struct addr_location *addr_al); void (*process_switch)(union perf_event *event, @@ -124,7 +123,6 @@ struct scripting_context { void *event_data; union perf_event *event; struct perf_sample *sample; - struct evsel *evsel; struct addr_location *al; struct addr_location *addr_al; struct perf_session *session; @@ -133,7 +131,6 @@ struct scripting_context { void scripting_context__update(struct scripting_context *scripting_context, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct addr_location *al, struct addr_location *addr_al); From ec319c4d35523e12630631b3ae875758cfa3c6e0 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:26 -0700 Subject: [PATCH 063/343] perf s390-sample-raw: Don't pass evsel or its PMU with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from s390-sample-raw-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/s390-sample-raw.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c index c6ae0ae8d86a..52bbca5c56c8 100644 --- a/tools/perf/util/s390-sample-raw.c +++ b/tools/perf/util/s390-sample-raw.c @@ -222,8 +222,9 @@ static char *get_counter_name(int set, int nr, struct perf_pmu *pmu) return result; } -static void s390_cpumcfdg_dump(struct perf_pmu *pmu, struct perf_sample *sample) +static void s390_cpumcfdg_dump(struct perf_sample *sample) { + struct perf_pmu *pmu = sample->evsel->pmu; size_t i, len = sample->raw_size, offset = 0; unsigned char *buf = sample->raw_data; const char *color = PERF_COLOR_BLUE; @@ -284,8 +285,9 @@ static bool s390_pai_all_test(struct perf_sample *sample) return true; } -static void s390_pai_all_dump(struct evsel *evsel, struct perf_sample *sample) +static void s390_pai_all_dump(struct perf_sample *sample) { + struct evsel *evsel = sample->evsel; size_t len = sample->raw_size, offset = 0; unsigned char *p = sample->raw_data; const char *color = PERF_COLOR_BLUE; @@ -332,31 +334,32 @@ void evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) { const char *pai_name; - struct evsel *evsel; if (event->header.type != PERF_RECORD_SAMPLE) return; - evsel = evlist__event2evsel(evlist, event); - if (!evsel) - return; + if (!sample->evsel) { + sample->evsel = evlist__event2evsel(evlist, event); + if (!sample->evsel) + return; + } /* Check for raw data in sample */ if (!sample->raw_size || !sample->raw_data) return; /* Display raw data on screen */ - if (evsel->core.attr.config == PERF_EVENT_CPUM_CF_DIAG) { - if (!evsel->pmu) - evsel->pmu = perf_pmus__find("cpum_cf"); + if (sample->evsel->core.attr.config == PERF_EVENT_CPUM_CF_DIAG) { + if (!sample->evsel->pmu) + sample->evsel->pmu = perf_pmus__find("cpum_cf"); if (!s390_cpumcfdg_testctr(sample)) pr_err("Invalid counter set data encountered\n"); else - s390_cpumcfdg_dump(evsel->pmu, sample); + s390_cpumcfdg_dump(sample); return; } - switch (evsel->core.attr.config) { + switch (sample->evsel->core.attr.config) { case PERF_EVENT_PAI_NNPA_ALL: pai_name = "NNPA_ALL"; break; @@ -370,8 +373,8 @@ void evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, if (!s390_pai_all_test(sample)) { pr_err("Invalid %s raw data encountered\n", pai_name); } else { - if (!evsel->pmu) - evsel->pmu = perf_pmus__find_by_type(evsel->core.attr.type); - s390_pai_all_dump(evsel, sample); + if (!sample->evsel->pmu) + sample->evsel->pmu = perf_pmus__find_by_type(sample->evsel->core.attr.type); + s390_pai_all_dump(sample); } } From 2856524e4ef76938b7d509b8120b65c93b552525 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:27 -0700 Subject: [PATCH 064/343] perf evsel: Don't pass evsel with sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As struct perf_sample now directly contains its own resolved evsel pointer, passing the evsel separately is redundant and clutters the interface. Remove the redundant evsel parameter from evsel-specific handlers and structures, ensuring the tool always directly accesses the evsel bound to the sample. This simplifies the API signatures and eliminates the risk of passing an inconsistent evsel. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 61 +++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index ee30e15af054..bb48568b8101 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3003,52 +3003,62 @@ int evsel__open_per_thread(struct evsel *evsel, struct perf_thread_map *threads) return ret; } -static int perf_evsel__parse_id_sample(const struct evsel *evsel, - const union perf_event *event, +static int perf_evsel__parse_id_sample(const union perf_event *event, struct perf_sample *sample) { + const struct evsel *evsel = sample->evsel; u64 type = evsel->core.attr.sample_type; const __u64 *array = event->sample.array; bool swapped = evsel->needs_swap; union u64_swap u; - - array += ((event->header.size - - sizeof(event->header)) / sizeof(u64)) - 1; + int i = ((event->header.size - sizeof(event->header)) / sizeof(u64)) - 1; if (type & PERF_SAMPLE_IDENTIFIER) { - sample->id = *array; - array--; + if (i < 0) + return -EFAULT; + + sample->id = array[i--]; } if (type & PERF_SAMPLE_CPU) { - u.val64 = *array; + if (i < 0) + return -EFAULT; + + u.val64 = array[i--]; if (swapped) { /* undo swap of u64, then swap on individual u32s */ u.val64 = bswap_64(u.val64); u.val32[0] = bswap_32(u.val32[0]); } - sample->cpu = u.val32[0]; - array--; } if (type & PERF_SAMPLE_STREAM_ID) { - sample->stream_id = *array; - array--; + if (i < 0) + return -EFAULT; + + sample->stream_id = array[i--]; } if (type & PERF_SAMPLE_ID) { - sample->id = *array; - array--; + if (i < 0) + return -EFAULT; + + sample->id = array[i--]; } if (type & PERF_SAMPLE_TIME) { - sample->time = *array; - array--; + if (i < 0) + return -EFAULT; + + sample->time = array[i--]; } if (type & PERF_SAMPLE_TID) { - u.val64 = *array; + if (i < 0) + return -EFAULT; + + u.val64 = array[i--]; if (swapped) { /* undo swap of u64, then swap on individual u32s */ u.val64 = bswap_64(u.val64); @@ -3058,7 +3068,6 @@ static int perf_evsel__parse_id_sample(const struct evsel *evsel, sample->pid = u.val32[0]; sample->tid = u.val32[1]; - array--; } return 0; @@ -3244,15 +3253,18 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event, data->deferred_cookie = event->callchain_deferred.cookie; - if (evsel->core.attr.sample_id_all) - perf_evsel__parse_id_sample(evsel, event, data); - + if (evsel->core.attr.sample_id_all) { + if (perf_evsel__parse_id_sample(event, data)) + goto out_efault; + } return 0; } if (event->header.type != PERF_RECORD_SAMPLE) { - if (evsel->core.attr.sample_id_all) - perf_evsel__parse_id_sample(evsel, event, data); + if (evsel->core.attr.sample_id_all) { + if (perf_evsel__parse_id_sample(event, data)) + goto out_efault; + } return 0; } @@ -3614,12 +3626,13 @@ int evsel__parse_sample_timestamp(struct evsel *evsel, union perf_event *event, if (event->header.type != PERF_RECORD_SAMPLE) { struct perf_sample data = { + .evsel = evsel, .time = -1ULL, }; if (!evsel->core.attr.sample_id_all) return -1; - if (perf_evsel__parse_id_sample(evsel, event, &data)) + if (perf_evsel__parse_id_sample(event, &data)) return -1; *timestamp = data.time; From 9890b403d49eb6caf2d58224ade744aa06646260 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:28 -0700 Subject: [PATCH 065/343] perf lock: Constify trace_lock_handler variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Constify the static trace_lock_handler structures. Since the trace lock handler callbacks and definitions do not change at runtime, declare them const to enforce read-only memory placement and improve safety. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-lock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index b6533483ba64..89a40d385b27 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -1179,7 +1179,7 @@ static int report_lock_contention_end_event(struct perf_sample *sample) /* lock oriented handlers */ /* TODO: handlers for CPU oriented, thread oriented */ -static struct trace_lock_handler report_lock_ops = { +static const struct trace_lock_handler report_lock_ops = { .acquire_event = report_lock_acquire_event, .acquired_event = report_lock_acquired_event, .contended_event = report_lock_contended_event, @@ -1188,13 +1188,13 @@ static struct trace_lock_handler report_lock_ops = { .contention_end_event = report_lock_contention_end_event, }; -static struct trace_lock_handler contention_lock_ops = { +static const struct trace_lock_handler contention_lock_ops = { .contention_begin_event = report_lock_contention_begin_event, .contention_end_event = report_lock_contention_end_event, }; -static struct trace_lock_handler *trace_handler; +static const struct trace_lock_handler *trace_handler; static int evsel__process_lock_acquire(struct perf_sample *sample) { From 8dca7ad2c2576b721e78244206143832d46a3b83 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:29 -0700 Subject: [PATCH 066/343] perf lock: Avoid segv if event is missing a callchain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid a potential segmentation fault if a parsed sample unexpectedly lacks a valid callchain pointer. Add a check for a NULL sample->callchain pointer in get_callstack(). If the callchain is missing, return NULL to safely skip the event and log a debug warning rather than causing a tool segfault. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-lock.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 89a40d385b27..064b3aa4bad7 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -938,9 +938,16 @@ static u64 *get_callstack(struct perf_sample *sample, int max_stack) u64 i; int c; - callstack = calloc(max_stack, sizeof(*callstack)); - if (callstack == NULL) + if (!sample->callchain) { + pr_debug("Sample unexpectedly missing callchain\n"); return NULL; + } + + callstack = calloc(max_stack, sizeof(*callstack)); + if (callstack == NULL) { + pr_debug("Failed to allocate callstack\n"); + return NULL; + } for (i = 0, c = 0; i < sample->callchain->nr && c < max_stack; i++) { u64 ip = sample->callchain->ips[i]; @@ -1059,7 +1066,7 @@ static int report_lock_contention_begin_event(struct perf_sample *sample) if (needs_callstack()) { u64 *callstack = get_callstack(sample, max_stack_depth); if (callstack == NULL) - return -ENOMEM; + return 0; if (!match_callstack_filter(machine, callstack, max_stack_depth)) { free(callstack); From 00b36b394c15f625fa166ba3b399cad5bd5065f9 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:30 -0700 Subject: [PATCH 067/343] perf timechart: Fix memory leaks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve a major execution-time leak of backtrace strings in the timechart tool. - Modify cat_backtrace() to return dynamically allocated memory via open_memstream(), transferring ownership to the caller. - Free the returned backtrace string inside process_sample_event() immediately after invoking the tracepoint handler. - In handlers like pid_put_sample() and sched_wakeup(), make a separate copy of the backtrace using strdup() if it needs to be persisted in the sample struct, preventing lifetime issues and double-free vulnerabilities. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-timechart.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 1d24d8738519..d2e15d02304e 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -299,7 +299,7 @@ static void pid_put_sample(struct timechart *tchart, int pid, int type, sample->type = type; sample->next = c->samples; sample->cpu = cpu; - sample->backtrace = backtrace; + sample->backtrace = backtrace ? strdup(backtrace) : NULL; c->samples = sample; if (sample->type == TYPE_RUNNING && end > start && start > 0) { @@ -433,7 +433,7 @@ static void sched_wakeup(struct timechart *tchart, int cpu, u64 timestamp, we->time = timestamp; we->waker = waker; - we->backtrace = backtrace; + we->backtrace = backtrace ? strdup(backtrace) : NULL; if ((flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ)) we->waker = -1; @@ -489,9 +489,9 @@ static void sched_switch(struct timechart *tchart, int cpu, u64 timestamp, } } -static const char *cat_backtrace(union perf_event *event, - struct perf_sample *sample, - struct machine *machine) +static char *cat_backtrace(union perf_event *event, + struct perf_sample *sample, + struct machine *machine) { struct addr_location al; unsigned int i; @@ -577,6 +577,7 @@ static int process_sample_event(const struct perf_tool *tool, { struct timechart *tchart = container_of(tool, struct timechart, tool); struct evsel *evsel = sample->evsel; + int ret = 0; if (evsel->core.attr.sample_type & PERF_SAMPLE_TIME) { if (!tchart->first_time || tchart->first_time > sample->time) @@ -587,11 +588,13 @@ static int process_sample_event(const struct perf_tool *tool, if (evsel->handler != NULL) { tracepoint_handler f = evsel->handler; + char *backtrace = cat_backtrace(event, sample, machine); - return f(tchart, sample, cat_backtrace(event, sample, machine)); + ret = f(tchart, sample, backtrace); + free(backtrace); } - return 0; + return ret; } static int From b3ab668761786f9df9e19dd2805e657af2f19c41 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:31 -0700 Subject: [PATCH 068/343] perf kmem: Fix memory leaks on error path and when skipping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix memory leaks on the error paths and skipped sample handling paths in the perf kmem tool. Ensure that all allocated GFP flags and thread references are properly freed and released via thread__put() when skipping samples or encountering parsing failures, preventing long-term memory usage leaks during large trace analyses. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 68a39f56204d..daf2272c7337 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -783,17 +783,21 @@ static int parse_gfp_flags(struct perf_sample *sample, unsigned int gfp_flags) new = realloc(gfps, (nr_gfps + 1) * sizeof(*gfps)); if (new == NULL) - return -ENOMEM; + goto err_out; gfps = new; - new += nr_gfps++; + new += nr_gfps; new->flags = gfp_flags; new->human_readable = strdup(str + 10); + if (!new->human_readable) + goto err_out; new->compact_str = compact_gfp_flags(str + 10); - if (!new->human_readable || !new->compact_str) - return -ENOMEM; - + if (!new->compact_str) { + free(new->human_readable); + goto err_out; + } + nr_gfps++; qsort(gfps, nr_gfps, sizeof(*gfps), gfpcmp); } @@ -802,6 +806,9 @@ static int parse_gfp_flags(struct perf_sample *sample, unsigned int gfp_flags) trace_seq_destroy(&seq); return 0; +err_out: + trace_seq_destroy(&seq); + return -ENOMEM; } static int evsel__process_page_alloc_event(struct perf_sample *sample) @@ -971,6 +978,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, } if (perf_kmem__skip_sample(sample)) { + thread__put(thread); return 0; } From e454fef5d2c6e3fc89bd87a2da491dae3977a9ed Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:32 -0700 Subject: [PATCH 069/343] perf synthetic-events: Bound check when synthesizing mmap2 and build_id events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add robust boundary checks when synthesizing mmap2 and build_id events to ensure that filename fields do not overflow the fixed-size stack allocations or the synthesized event structures. Verify that the filename fits safely within the allocated boundaries of the mmap2 event structure, and prevent potential heap/stack overflow corruptions from excessively long or corrupted kernel filenames. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/synthetic-events.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index fd1d4c0345d6..d665b0f94b32 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -2268,14 +2268,20 @@ int perf_event__synthesize_build_id(const struct perf_tool *tool, const char *filename) { union perf_event ev; - size_t len; + size_t len, filename_len = strlen(filename); u64 sample_type = sample->evsel ? sample->evsel->core.attr.sample_type : 0; void *array = &ev; int ret; - len = sizeof(ev.build_id) + strlen(filename) + 1; + if (filename_len >= PATH_MAX) + return -EINVAL; + + len = sizeof(ev.build_id) + filename_len + 1; len = PERF_ALIGN(len, sizeof(u64)); + if (len + MAX_ID_HDR_ENTRIES * sizeof(__u64) > sizeof(ev)) + return -E2BIG; + memset(&ev, 0, len); ev.build_id.size = bid->size; @@ -2314,14 +2320,21 @@ int perf_event__synthesize_mmap2_build_id(const struct perf_tool *tool, const char *filename) { union perf_event ev; + size_t filename_len = strlen(filename); size_t ev_len; u64 sample_type = sample->evsel ? sample->evsel->core.attr.sample_type : 0; void *array; int ret; - ev_len = sizeof(ev.mmap2) - sizeof(ev.mmap2.filename) + strlen(filename) + 1; + if (filename_len >= sizeof(ev.mmap2.filename)) + return -EINVAL; + + ev_len = sizeof(ev.mmap2) - sizeof(ev.mmap2.filename) + filename_len + 1; ev_len = PERF_ALIGN(ev_len, sizeof(u64)); + if (ev_len + MAX_ID_HDR_ENTRIES * sizeof(__u64) > sizeof(ev)) + return -E2BIG; + memset(&ev, 0, ev_len); ev.mmap2.header.type = PERF_RECORD_MMAP2; From 1bd2c9403ec5fe42bc2828b52c253e7cfed101e8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:33 -0700 Subject: [PATCH 070/343] perf kmem: Add bounds checks to tracepoint read values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sanitize order and migrate_type values from tracepoint payloads before using them as array indexes. When processing page_alloc_event and page_free_event, verify that 'order' is less than MAX_PAGE_ORDER and 'migrate_type' is less than MAX_MIGRATE_TYPES. This guarantees that indexing into order_stats[MAX_PAGE_ORDER][MAX_MIGRATE_TYPES] remains strictly within bounds, avoiding out-of-bound heap or static segment accesses. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index daf2272c7337..33585e353efe 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -826,6 +826,16 @@ static int evsel__process_page_alloc_event(struct perf_sample *sample) .migrate_type = migrate_type, }; + if (order >= MAX_PAGE_ORDER) { + pr_debug("Out-of-bounds order %u\n", order); + return -1; + } + + if (migrate_type >= MAX_MIGRATE_TYPES) { + pr_debug("Out-of-bounds migratetype %u\n", migrate_type); + return -1; + } + if (use_pfn) page = perf_sample__intval(sample, "pfn"); else @@ -892,6 +902,11 @@ static int evsel__process_page_free_event(struct perf_sample *sample) .order = order, }; + if (order >= MAX_PAGE_ORDER) { + pr_debug("Out-of-bounds order %u\n", order); + return -1; + } + if (use_pfn) page = perf_sample__intval(sample, "pfn"); else From 16ccbec0f3e14f6ad06af6112ea4fa5668cab46a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:34 -0700 Subject: [PATCH 071/343] perf sched: Bounds check CPU in sched switch events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure CPU indexes parsed from sched switch and runtime events fit within the MAX_CPUS limit to prevent out-of-bounds indexing. Add explicit bounds checks for sample->cpu against MAX_CPUS inside process_sched_switch_event, process_sched_runtime_event, and timehist_sched_change_event. This prevents indexing beyond the boundaries of the sched->curr_pid tracking array, avoiding potential memory corruption or undefined behavior. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index d984e58c7dbf..9d73c7043182 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1791,6 +1791,11 @@ static int process_sched_switch_event(const struct perf_tool *tool, u32 prev_pid = perf_sample__intval(sample, "prev_pid"), next_pid = perf_sample__intval(sample, "next_pid"); + if (this_cpu < 0 || this_cpu >= MAX_CPUS) { + pr_warning("Out-of-bound sample CPU %d. Skipping sample\n", this_cpu); + return 0; + } + if (sched->curr_pid[this_cpu] != (u32)-1) { /* * Are we trying to switch away a PID that is @@ -1813,6 +1818,11 @@ static int process_sched_runtime_event(const struct perf_tool *tool, { struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + if (sample->cpu >= MAX_CPUS) { + pr_warning("Out-of-bound sample CPU %u. Skipping sample\n", sample->cpu); + return 0; + } + if (sched->tp_handler->runtime_event) return sched->tp_handler->runtime_event(sched, sample, machine); @@ -2775,6 +2785,11 @@ static int timehist_sched_change_event(const struct perf_tool *tool, int rc = 0; const char state = perf_sample__taskstate(sample, "prev_state"); + if (sample->cpu >= MAX_CPUS) { + pr_warning("Out-of-bound sample CPU %d. Skipping sample\n", sample->cpu); + return 0; + } + addr_location__init(&al); if (machine__resolve(machine, &al, sample) < 0) { pr_err("problem processing %d event. skipping it\n", From a41a462334a239511bad6f4509c8625a46d36c84 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:35 -0700 Subject: [PATCH 072/343] perf timechart: Bounds check CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent out-of-bounds writes/reads in CPU state tracking arrays by enforcing strict MAX_CPUS bounds checks in timechart's tracepoint handlers. Ensure that cpu_id retrieved from idle/frequency and sched tracepoints is less than MAX_CPUS before indexing into cpus_cstate_state, cpus_cstate_start_times, and similar tracking arrays. Also, fix an off-by-one error in the CPU iteration loop inside end_sample_processing() by changing the loop condition from 'cpu <= tchart->numcpus' to 'cpu < tchart->numcpus'. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-timechart.c | 35 +++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index d2e15d02304e..630756bebe32 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -605,6 +605,10 @@ process_sample_cpu_idle(struct timechart *tchart __maybe_unused, u32 state = perf_sample__intval(sample, "state"); u32 cpu_id = perf_sample__intval(sample, "cpu_id"); + if (cpu_id >= MAX_CPUS) { + pr_debug("Out-of-bounds cpu_id %u\n", cpu_id); + return -1; + } if (state == (u32)PWR_EVENT_EXIT) c_state_end(tchart, cpu_id, sample->time); else @@ -620,6 +624,10 @@ process_sample_cpu_frequency(struct timechart *tchart, u32 state = perf_sample__intval(sample, "state"); u32 cpu_id = perf_sample__intval(sample, "cpu_id"); + if (cpu_id >= MAX_CPUS) { + pr_debug("Out-of-bounds cpu_id %u\n", cpu_id); + return -1; + } p_state_change(tchart, cpu_id, sample->time, state); return 0; } @@ -633,6 +641,10 @@ process_sample_sched_wakeup(struct timechart *tchart, int waker = perf_sample__intval(sample, "common_pid"); int wakee = perf_sample__intval(sample, "pid"); + if (sample->cpu >= MAX_CPUS) { + pr_debug("Out-of-bounds cpu %u\n", sample->cpu); + return -1; + } sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace); return 0; } @@ -646,6 +658,10 @@ process_sample_sched_switch(struct timechart *tchart, int next_pid = perf_sample__intval(sample, "next_pid"); u64 prev_state = perf_sample__intval(sample, "prev_state"); + if (sample->cpu >= MAX_CPUS) { + pr_debug("Out-of-bounds cpu %u\n", sample->cpu); + return -1; + } sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid, prev_state, backtrace); return 0; @@ -660,6 +676,10 @@ process_sample_power_start(struct timechart *tchart __maybe_unused, u64 cpu_id = perf_sample__intval(sample, "cpu_id"); u64 value = perf_sample__intval(sample, "value"); + if (cpu_id >= MAX_CPUS) { + pr_debug("Out-of-bounds cpu_id %llu\n", (unsigned long long)cpu_id); + return -1; + } c_state_start(cpu_id, sample->time, value); return 0; } @@ -669,6 +689,10 @@ process_sample_power_end(struct timechart *tchart, struct perf_sample *sample, const char *backtrace __maybe_unused) { + if (sample->cpu >= MAX_CPUS) { + pr_debug("Out-of-bounds cpu %u\n", sample->cpu); + return -1; + } c_state_end(tchart, sample->cpu, sample->time); return 0; } @@ -681,6 +705,10 @@ process_sample_power_frequency(struct timechart *tchart, u64 cpu_id = perf_sample__intval(sample, "cpu_id"); u64 value = perf_sample__intval(sample, "value"); + if (cpu_id >= MAX_CPUS) { + pr_debug("Out-of-bounds cpu_id %llu\n", (unsigned long long)cpu_id); + return -1; + } p_state_change(tchart, cpu_id, sample->time, value); return 0; } @@ -692,10 +720,9 @@ process_sample_power_frequency(struct timechart *tchart, */ static void end_sample_processing(struct timechart *tchart) { - u64 cpu; - struct power_event *pwr; + for (u64 cpu = 0; cpu < tchart->numcpus; cpu++) { + struct power_event *pwr; - for (cpu = 0; cpu <= tchart->numcpus; cpu++) { /* C state */ #if 0 pwr = zalloc(sizeof(*pwr)); @@ -1515,6 +1542,8 @@ static int process_header(struct perf_file_section *section __maybe_unused, switch (feat) { case HEADER_NRCPUS: tchart->numcpus = ph->env.nr_cpus_avail; + if (tchart->numcpus > MAX_CPUS) + tchart->numcpus = MAX_CPUS; break; case HEADER_CPU_TOPOLOGY: From 9aa1ec2e1d21be400767aa9b754adbae7d8e1d32 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 20 May 2026 12:05:36 -0700 Subject: [PATCH 073/343] perf evsel: Add bounds checking to trace point raw data accessors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent out-of-bounds memory reads when parsing corrupted or maliciously crafted perf.data files by introducing robust bounds validation to raw data accessors. - Add a helper out_of_bounds() to check if field offsets and sizes exceed the sample's raw_size boundary, preventing heap read overflows. - In perf_sample__rawptr(), properly resolve newer relative dynamic tracepoint fields (__rel_loc) by checking the boundaries before and after reading the dynamic field descriptor. - Byte-swap dynamic field offsets and sizes dynamically when endianness varies, ensuring cross-endian parsing is robust. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Albert Ou Cc: Alexander Shishkin Cc: Alexandre Ghiti Cc: Andi Kleen Cc: Andrew Jones Cc: Anup Patel Cc: Athira Rajeev Cc: Blake Jones Cc: Chen Ni Cc: Chun-Tse Shao Cc: Dapeng Mi Cc: Derek Foreman Cc: Dmitriy Vyukov Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Hrishikesh Suresh Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Krzysztof Łopatowski Cc: Leo Yan Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quan Zhou Cc: Ravi Bangoria Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tianyou Li Cc: Yujie Liu Cc: tanze Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 54 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index bb48568b8101..713a250c7374 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3700,22 +3700,63 @@ struct tep_format_field *evsel__common_field(struct evsel *evsel, const char *na return tp_format ? tep_find_common_field(tp_format, name) : NULL; } +static bool out_of_bounds(const struct tep_format_field *field, int offset, int size, u32 raw_size) +{ + if (offset < 0) { + pr_warning("Negative trace point field offset %d in %s\n", + offset, field->name); + return true; + } + if (size < 0) { + pr_warning("Negative trace point field size %d in %s\n", + size, field->name); + return true; + } + if ((u32)offset + (u32)size > raw_size) { + pr_warning("Out of bound tracepoint field (%s) offset %d size %d in %u\n", + field->name, offset, size, raw_size); + return true; + } + return false; +} + void *perf_sample__rawptr(struct perf_sample *sample, const char *name) { struct tep_format_field *field = evsel__field(sample->evsel, name); - int offset; + int offset, size; if (!field) return NULL; offset = field->offset; - + size = field->size; if (field->flags & TEP_FIELD_IS_DYNAMIC) { - offset = *(int *)(sample->raw_data + field->offset); - offset &= 0xffff; - if (tep_field_is_relative(field->flags)) + int dynamic_data; + + if (out_of_bounds(field, offset, 4, sample->raw_size)) + return NULL; + + dynamic_data = *(int *)(sample->raw_data + field->offset); + + if (sample->evsel->needs_swap) + dynamic_data = bswap_32(dynamic_data); + + offset = dynamic_data & 0xffff; + size = (dynamic_data >> 16) & 0xffff; + + if (tep_field_is_relative(field->flags)) { + /* + * Newer kernel feature: Relative offsets (__rel_loc). + * If the relative flag is set, the parsed offset is not + * absolute from the start of the record. Instead, it is + * relative to the *end* of the dynamic field descriptor + * itself. + */ offset += field->offset + field->size; + } } + if (out_of_bounds(field, offset, size, sample->raw_size)) + return NULL; return sample->raw_data + offset; } @@ -3726,6 +3767,9 @@ u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sam u64 value; void *ptr = sample->raw_data + field->offset; + if (out_of_bounds(field, field->offset, field->size, sample->raw_size)) + return 0; + switch (field->size) { case 1: return *(u8 *)ptr; From 9416008e5462cf7a1da62bbaca915f483cea8b77 Mon Sep 17 00:00:00 2001 From: Swapnil Sapkal Date: Wed, 20 May 2026 10:20:15 +0000 Subject: [PATCH 074/343] perf sched stats: Fix SIGCHLD vs pause() race in schedstat_record() If the profiled workload exits very quickly, SIGCHLD can be delivered and consumed by the empty signal handler before the process enters pause(), causing an indefinite hang. Fix this with a simpler approach: - The signal handler now sets a 'volatile sig_atomic_t done' flag. Reset 'done' before registering signal handlers so that an early signal during setup is not discarded by a later reset. - Replace pause() with a loop that checks 'done' and uses waitpid(WNOHANG) to detect child exit without blocking. This handles both workload mode (child exits) and system-wide mode (user sends SIGINT/SIGTERM). Using WNOHANG avoids the SA_RESTART problem where a blocking waitpid() would auto-restart and ignore the done flag if the child doesn't exit on signal. Suggested-by: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Swapnil Sapkal Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Cc: Ravi Bangoria Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 9d73c7043182..4f54a08e6672 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -3746,8 +3747,11 @@ static int process_synthesized_schedstat_event(const struct perf_tool *tool, return 0; } +static volatile sig_atomic_t done; + static void sighandler(int sig __maybe_unused) { + done = 1; } static int enable_sched_schedstats(int *reset) @@ -3807,6 +3811,7 @@ static int perf_sched__schedstat_record(struct perf_sched *sched, .mode = PERF_DATA_MODE_WRITE, }; + done = 0; signal(SIGINT, sighandler); signal(SIGCHLD, sighandler); signal(SIGTERM, sighandler); @@ -3891,8 +3896,11 @@ static int perf_sched__schedstat_record(struct perf_sched *sched, if (argc) evlist__start_workload(evlist); - /* wait for signal */ - pause(); + while (!done) { + if (argc && waitpid(evlist->workload.pid, NULL, WNOHANG) > 0) + break; + sleep(1); + } if (reset) { err = disable_sched_schedstat(); From 5b8c90e06622308ff4b6c14260baee6fad064289 Mon Sep 17 00:00:00 2001 From: Swapnil Sapkal Date: Wed, 20 May 2026 10:20:16 +0000 Subject: [PATCH 075/343] perf sched stats: Fix SIGCHLD vs pause() race in schedstat_live() perf_sched__schedstat_live() has the same lost-wakeup race as perf_sched__schedstat_record(): a short-lived workload's SIGCHLD can be consumed by the signal handler before pause() is entered, hanging the process. Apply the same fix: replace pause() with a loop checking the 'done' flag and using waitpid(WNOHANG) for the workload case. Suggested-by: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Swapnil Sapkal Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Cc: Ravi Bangoria Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 4f54a08e6672..812a1b0d56d6 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -4743,6 +4743,7 @@ static int perf_sched__schedstat_live(struct perf_sched *sched, int reset = 0; int err = 0; + done = 0; signal(SIGINT, sighandler); signal(SIGCHLD, sighandler); signal(SIGTERM, sighandler); @@ -4788,8 +4789,11 @@ static int perf_sched__schedstat_live(struct perf_sched *sched, if (argc) evlist__start_workload(evlist); - /* wait for signal */ - pause(); + while (!done) { + if (argc && waitpid(evlist->workload.pid, NULL, WNOHANG) > 0) + break; + sleep(1); + } if (reset) { err = disable_sched_schedstat(); From 35c9fb22000f1ce10c0f3627d30fa8763e721719 Mon Sep 17 00:00:00 2001 From: Swapnil Sapkal Date: Wed, 20 May 2026 10:20:17 +0000 Subject: [PATCH 076/343] perf lock contention: Fix SIGCHLD vs pause() race in __cmd_contention() __cmd_contention() suffers from the same lost-wakeup race as the perf sched stats paths: SIGCHLD can be consumed by the signal handler before pause() is entered, hanging the process. Apply the same fix: replace pause() with a loop checking the 'done' flag and using waitpid(WNOHANG) for the workload case. Suggested-by: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Swapnil Sapkal Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Cc: Ravi Bangoria Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-lock.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 064b3aa4bad7..94a8c35abb0b 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1915,8 +1916,11 @@ static int __cmd_report(bool display_info) return err; } +static volatile sig_atomic_t done; + static void sighandler(int sig __maybe_unused) { + done = 1; } static int check_lock_contention_options(const struct option *options, @@ -2054,6 +2058,7 @@ static int __cmd_contention(int argc, const char **argv) goto out_delete; } + done = 0; signal(SIGINT, sighandler); signal(SIGCHLD, sighandler); signal(SIGTERM, sighandler); @@ -2121,8 +2126,11 @@ static int __cmd_contention(int argc, const char **argv) if (argc) evlist__start_workload(con.evlist); - /* wait for signal */ - pause(); + while (!done) { + if (argc && waitpid(con.evlist->workload.pid, NULL, WNOHANG) > 0) + break; + sleep(1); + } lock_contention_stop(); lock_contention_read(&con); From 537609924c43715e39a41762d3e3d3c7c534bb71 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:26 -0700 Subject: [PATCH 077/343] perf trace beauty: Make beauty generated C code standalone .o files Previously, builtin-trace.c directly included 15 embedded C files (e.g. trace/beauty/mmap.c and fsconfig_arrays.c), which in turn depend on dozens of generated beauty script arrays. To satisfy these embedded inclusions, the global Makefile.perf would define all the generator variables/rules and include them in the prepare umbrella target, choking parallel build startup. Furthermore, tools/perf/util/syscalltbl.c included its own generated mapper, and util/env.c conditionally included arch_errno_names.c inline, splitting consumers across directories and preventing clean Make encapsulation. Refactor the framework to achieve better encapsulation: 1. Move util/syscalltbl.[ch] into trace/beauty/ to co-locate with all generated code consumers. 2. Create fsconfig.c and flatten embedded beauty .c files to compile as independent standalone objects via trace/beauty/Build, exporting their formatting functions via beauty.h and env.h. Switch arch_errno_names.o and syscalltbl.o assignments directly to perf-util-y and add an unconditional top-level recursive kbuild hook (perf-util-y += trace/beauty/) to compile them into libperf-util.a, resolving remote linkage for util/env.c, util/bpf-trace-summary.c, and standalone python extensions. 3. Bridge private opaque references (struct trace) securely via accessors trace__show_zeros() and trace__host(), avoiding header entanglements. 4. Consolidate all generator variables, script paths, and array generation rules entirely out of Makefile.perf and place them directly inside the exact local Build files where their output objects are compiled (trace/beauty/Build and trace/beauty/tracepoints/Build), binding prerequisites locally. Use directly inside generator recipes to guarantee dynamic directory creation before script redirection, and append across all rules to print clean, standardized GEN ... file.c output during compilation. 5. Clean up clean target to recursively remove the generated directory instead of relying on dozens of individual variables. This unchokes the "prepare" target parallel barrier, allows make to evaluate generation scripts purely locally where consumed, and flattens the tracepoint formatting architecture. Testing a parallel build (make -j28 all from scratch) shows improvements: Before: real 0m28.689s user 2m38.490s sys 0m30.148s After: real 0m27.642s user 2m32.356s sys 0m26.683s So reclaiming ~9.6 seconds of raw CPU time and over 1 full second off overall real-world build latency, by overlapping sub-make startup and avoiding top-level double-parsing overhead. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Build | 2 + tools/perf/Makefile.perf | 282 +----------------- tools/perf/builtin-trace.c | 32 +- tools/perf/trace/beauty/Build | 276 +++++++++++++++++ tools/perf/trace/beauty/arch_errno_names.c | 2 + tools/perf/trace/beauty/arch_errno_names.sh | 2 +- tools/perf/trace/beauty/beauty.h | 60 ++++ tools/perf/trace/beauty/eventfd.c | 6 +- tools/perf/trace/beauty/fsconfig.c | 5 + tools/perf/trace/beauty/futex_op.c | 5 +- tools/perf/trace/beauty/futex_val3.c | 5 +- tools/perf/trace/beauty/mmap.c | 24 +- tools/perf/trace/beauty/mode_t.c | 6 +- tools/perf/trace/beauty/msg_flags.c | 8 +- tools/perf/trace/beauty/open_flags.c | 2 + tools/perf/trace/beauty/perf_event_open.c | 21 +- tools/perf/trace/beauty/pid.c | 5 +- tools/perf/trace/beauty/sched_policy.c | 8 +- tools/perf/trace/beauty/seccomp.c | 12 +- tools/perf/trace/beauty/signum.c | 6 +- tools/perf/trace/beauty/socket_type.c | 6 +- .../perf/{util => trace/beauty}/syscalltbl.c | 0 .../perf/{util => trace/beauty}/syscalltbl.h | 0 tools/perf/trace/beauty/tracepoints/Build | 21 ++ tools/perf/trace/beauty/waitid_options.c | 8 +- tools/perf/util/Build | 4 +- tools/perf/util/bpf-trace-summary.c | 2 +- tools/perf/util/env.c | 4 - tools/perf/util/env.h | 1 + 29 files changed, 447 insertions(+), 368 deletions(-) create mode 100644 tools/perf/trace/beauty/fsconfig.c rename tools/perf/{util => trace/beauty}/syscalltbl.c (100%) rename tools/perf/{util => trace/beauty}/syscalltbl.h (100%) diff --git a/tools/perf/Build b/tools/perf/Build index b03cc59dabf8..e18c80a5c1bc 100644 --- a/tools/perf/Build +++ b/tools/perf/Build @@ -34,6 +34,8 @@ ifeq ($(CONFIG_LIBTRACEEVENT),y) perf-$(CONFIG_TRACE) += trace/beauty/ endif +perf-util-y += trace/beauty/ + perf-$(CONFIG_LIBELF) += builtin-probe.o perf-bench-y += bench/ diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 0aba14f22a06..c81797ceec42 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -509,225 +509,6 @@ arm64-sysreg-defs-clean: $(Q)$(MAKE) -C $(arm64_gen_sysreg_dir) O=$(arm64_gen_sysreg_outdir) \ prefix= subdir= clean > /dev/null -beauty_linux_dir := $(srctree)/tools/perf/trace/beauty/include/linux/ -beauty_uapi_linux_dir := $(srctree)/tools/perf/trace/beauty/include/uapi/linux/ -beauty_uapi_sound_dir := $(srctree)/tools/perf/trace/beauty/include/uapi/sound/ -beauty_arch_asm_dir := $(srctree)/tools/perf/trace/beauty/arch/x86/include/asm/ -beauty_x86_arch_asm_uapi_dir := $(srctree)/tools/perf/trace/beauty/arch/x86/include/uapi/asm/ - -linux_uapi_dir := $(srctree)/tools/include/uapi/linux -asm_generic_uapi_dir := $(srctree)/tools/include/uapi/asm-generic -arch_asm_uapi_dir := $(srctree)/tools/arch/$(SRCARCH)/include/uapi/asm/ -x86_arch_asm_dir := $(srctree)/tools/arch/x86/include/asm/ - -beauty_outdir := $(OUTPUT)trace/beauty/generated -beauty_ioctl_outdir := $(beauty_outdir)/ioctl - -# Create output directory if not already present -$(shell [ -d '$(beauty_ioctl_outdir)' ] || mkdir -p '$(beauty_ioctl_outdir)') - -syscall_array := $(beauty_outdir)/syscalltbl.c -syscall_tbl := $(srctree)/tools/perf/trace/beauty/syscalltbl.sh -syscall_tbl_data := $(srctree)/tools/scripts/syscall.tbl \ - $(wildcard $(srctree)/tools/perf/arch/*/entry/syscalls/syscall*.tbl) - -$(syscall_array): $(syscall_tbl) $(syscall_tbl_data) - $(Q)$(SHELL) '$(syscall_tbl)' $(srctree)/tools $@ - -fs_at_flags_array := $(beauty_outdir)/fs_at_flags_array.c -fs_at_flags_tbl := $(srctree)/tools/perf/trace/beauty/fs_at_flags.sh - -$(fs_at_flags_array): $(beauty_uapi_linux_dir)/fcntl.h $(fs_at_flags_tbl) - $(Q)$(SHELL) '$(fs_at_flags_tbl)' $(beauty_uapi_linux_dir) > $@ - -clone_flags_array := $(beauty_outdir)/clone_flags_array.c -clone_flags_tbl := $(srctree)/tools/perf/trace/beauty/clone.sh - -$(clone_flags_array): $(beauty_uapi_linux_dir)/sched.h $(clone_flags_tbl) - $(Q)$(SHELL) '$(clone_flags_tbl)' $(beauty_uapi_linux_dir) > $@ - -drm_ioctl_array := $(beauty_ioctl_outdir)/drm_ioctl_array.c -drm_hdr_dir := $(srctree)/tools/perf/trace/beauty/include/uapi/drm -drm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/drm_ioctl.sh - -$(drm_ioctl_array): $(drm_hdr_dir)/drm.h $(drm_hdr_dir)/i915_drm.h $(drm_ioctl_tbl) - $(Q)$(SHELL) '$(drm_ioctl_tbl)' $(drm_hdr_dir) > $@ - -fadvise_advice_array := $(beauty_outdir)/fadvise_advice_array.c -fadvise_advice_tbl := $(srctree)/tools/perf/trace/beauty/fadvise.sh - -$(fadvise_advice_array): $(beauty_uapi_linux_dir)/fadvise.h $(fadvise_advice_tbl) - $(Q)$(SHELL) '$(fadvise_advice_tbl)' $(beauty_uapi_linux_dir) > $@ - -fsmount_arrays := $(beauty_outdir)/fsmount_arrays.c -fsmount_tbls := $(srctree)/tools/perf/trace/beauty/fsmount.sh - -$(fsmount_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsmount_tbls) - $(Q)$(SHELL) '$(fsmount_tbls)' $(beauty_uapi_linux_dir) > $@ - -fspick_arrays := $(beauty_outdir)/fspick_arrays.c -fspick_tbls := $(srctree)/tools/perf/trace/beauty/fspick.sh - -$(fspick_arrays): $(beauty_uapi_linux_dir)/mount.h $(fspick_tbls) - $(Q)$(SHELL) '$(fspick_tbls)' $(beauty_uapi_linux_dir) > $@ - -fsconfig_arrays := $(beauty_outdir)/fsconfig_arrays.c -fsconfig_tbls := $(srctree)/tools/perf/trace/beauty/fsconfig.sh - -$(fsconfig_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsconfig_tbls) - $(Q)$(SHELL) '$(fsconfig_tbls)' $(beauty_uapi_linux_dir) > $@ - -pkey_alloc_access_rights_array := $(beauty_outdir)/pkey_alloc_access_rights_array.c -asm_generic_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/ -pkey_alloc_access_rights_tbl := $(srctree)/tools/perf/trace/beauty/pkey_alloc_access_rights.sh - -$(pkey_alloc_access_rights_array): $(asm_generic_hdr_dir)/mman-common.h $(pkey_alloc_access_rights_tbl) - $(Q)$(SHELL) '$(pkey_alloc_access_rights_tbl)' $(asm_generic_hdr_dir) > $@ - -sndrv_ctl_ioctl_array := $(beauty_ioctl_outdir)/sndrv_ctl_ioctl_array.c -sndrv_ctl_hdr_dir := $(srctree)/tools/include/uapi/sound -sndrv_ctl_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh - -$(sndrv_ctl_ioctl_array): $(beauty_uapi_sound_dir)/asound.h $(sndrv_ctl_ioctl_tbl) - $(Q)$(SHELL) '$(sndrv_ctl_ioctl_tbl)' $(beauty_uapi_sound_dir) > $@ - -sndrv_pcm_ioctl_array := $(beauty_ioctl_outdir)/sndrv_pcm_ioctl_array.c -sndrv_pcm_hdr_dir := $(srctree)/tools/include/uapi/sound -sndrv_pcm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh - -$(sndrv_pcm_ioctl_array): $(beauty_uapi_sound_dir)/asound.h $(sndrv_pcm_ioctl_tbl) - $(Q)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(beauty_uapi_sound_dir) > $@ - -kcmp_type_array := $(beauty_outdir)/kcmp_type_array.c -kcmp_hdr_dir := $(srctree)/tools/include/uapi/linux/ -kcmp_type_tbl := $(srctree)/tools/perf/trace/beauty/kcmp_type.sh - -$(kcmp_type_array): $(kcmp_hdr_dir)/kcmp.h $(kcmp_type_tbl) - $(Q)$(SHELL) '$(kcmp_type_tbl)' $(kcmp_hdr_dir) > $@ - -kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c -kvm_hdr_dir := $(srctree)/tools/include/uapi/linux -kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh - -$(kvm_ioctl_array): $(kvm_hdr_dir)/kvm.h $(kvm_ioctl_tbl) - $(Q)$(SHELL) '$(kvm_ioctl_tbl)' $(kvm_hdr_dir) > $@ - -socket_arrays := $(beauty_outdir)/socket.c -socket_tbl := $(srctree)/tools/perf/trace/beauty/socket.sh - -$(socket_arrays): $(linux_uapi_dir)/in.h $(beauty_linux_dir)/socket.h $(socket_tbl) - $(Q)$(SHELL) '$(socket_tbl)' $(linux_uapi_dir) $(beauty_linux_dir) > $@ - -sockaddr_arrays := $(beauty_outdir)/sockaddr.c -sockaddr_tbl := $(srctree)/tools/perf/trace/beauty/sockaddr.sh - -$(sockaddr_arrays): $(beauty_linux_dir)/socket.h $(sockaddr_tbl) - $(Q)$(SHELL) '$(sockaddr_tbl)' $(beauty_linux_dir) > $@ - -vhost_virtio_ioctl_array := $(beauty_ioctl_outdir)/vhost_virtio_ioctl_array.c -vhost_virtio_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/vhost_virtio_ioctl.sh - -$(vhost_virtio_ioctl_array): $(beauty_uapi_linux_dir)/vhost.h $(vhost_virtio_ioctl_tbl) - $(Q)$(SHELL) '$(vhost_virtio_ioctl_tbl)' $(beauty_uapi_linux_dir) > $@ - -perf_ioctl_array := $(beauty_ioctl_outdir)/perf_ioctl_array.c -perf_hdr_dir := $(srctree)/tools/include/uapi/linux -perf_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/perf_ioctl.sh - -$(perf_ioctl_array): $(perf_hdr_dir)/perf_event.h $(perf_ioctl_tbl) - $(Q)$(SHELL) '$(perf_ioctl_tbl)' $(perf_hdr_dir) > $@ - -madvise_behavior_array := $(beauty_outdir)/madvise_behavior_array.c -madvise_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/ -madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh - -$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl) - $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@ - -mmap_flags_array := $(beauty_outdir)/mmap_flags_array.c -mmap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mmap_flags.sh - -$(mmap_flags_array): $(linux_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(mmap_flags_tbl) - $(Q)$(SHELL) '$(mmap_flags_tbl)' $(linux_uapi_dir) $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@ - -mremap_flags_array := $(beauty_outdir)/mremap_flags_array.c -mremap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mremap_flags.sh - -$(mremap_flags_array): $(linux_uapi_dir)/mman.h $(mremap_flags_tbl) - $(Q)$(SHELL) '$(mremap_flags_tbl)' $(linux_uapi_dir) > $@ - -mount_flags_array := $(beauty_outdir)/mount_flags_array.c -mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/mount_flags.sh - -$(mount_flags_array): $(beauty_uapi_linux_dir)/mount.h $(mount_flags_tbl) - $(Q)$(SHELL) '$(mount_flags_tbl)' $(beauty_uapi_linux_dir) > $@ - -move_mount_flags_array := $(beauty_outdir)/move_mount_flags_array.c -move_mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/move_mount_flags.sh - -$(move_mount_flags_array): $(beauty_uapi_linux_dir)/mount.h $(move_mount_flags_tbl) - $(Q)$(SHELL) '$(move_mount_flags_tbl)' $(beauty_uapi_linux_dir) > $@ - -mmap_prot_array := $(beauty_outdir)/mmap_prot_array.c -mmap_prot_tbl := $(srctree)/tools/perf/trace/beauty/mmap_prot.sh - -$(mmap_prot_array): $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(mmap_prot_tbl) - $(Q)$(SHELL) '$(mmap_prot_tbl)' $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@ - -prctl_option_array := $(beauty_outdir)/prctl_option_array.c -prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh - -$(prctl_option_array): $(beauty_uapi_linux_dir)/prctl.h $(prctl_option_tbl) - $(Q)$(SHELL) '$(prctl_option_tbl)' $(beauty_uapi_linux_dir) > $@ - -usbdevfs_ioctl_array := $(beauty_ioctl_outdir)/usbdevfs_ioctl_array.c -usbdevfs_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/usbdevfs_ioctl.sh - -$(usbdevfs_ioctl_array): $(beauty_uapi_linux_dir)/usbdevice_fs.h $(usbdevfs_ioctl_tbl) - $(Q)$(SHELL) '$(usbdevfs_ioctl_tbl)' $(beauty_uapi_linux_dir) > $@ - -x86_arch_prctl_code_array := $(beauty_outdir)/x86_arch_prctl_code_array.c -x86_arch_prctl_code_tbl := $(srctree)/tools/perf/trace/beauty/x86_arch_prctl.sh - -$(x86_arch_prctl_code_array): $(beauty_x86_arch_asm_uapi_dir)/prctl.h $(x86_arch_prctl_code_tbl) - $(Q)$(SHELL) '$(x86_arch_prctl_code_tbl)' $(beauty_x86_arch_asm_uapi_dir) > $@ - -x86_arch_irq_vectors_array := $(beauty_outdir)/x86_arch_irq_vectors_array.c -x86_arch_irq_vectors_tbl := $(srctree)/tools/perf/trace/beauty/tracepoints/x86_irq_vectors.sh - -$(x86_arch_irq_vectors_array): $(beauty_arch_asm_dir)/irq_vectors.h $(x86_arch_irq_vectors_tbl) - $(Q)$(SHELL) '$(x86_arch_irq_vectors_tbl)' $(beauty_arch_asm_dir) > $@ - -x86_arch_MSRs_array := $(beauty_outdir)/x86_arch_MSRs_array.c -x86_arch_MSRs_tbl := $(srctree)/tools/perf/trace/beauty/tracepoints/x86_msr.sh - -$(x86_arch_MSRs_array): $(x86_arch_asm_dir)/msr-index.h $(x86_arch_MSRs_tbl) - $(Q)$(SHELL) '$(x86_arch_MSRs_tbl)' $(x86_arch_asm_dir) > $@ - -rename_flags_array := $(beauty_outdir)/rename_flags_array.c -rename_flags_tbl := $(srctree)/tools/perf/trace/beauty/rename_flags.sh - -$(rename_flags_array): $(beauty_uapi_linux_dir)/fs.h $(rename_flags_tbl) - $(Q)$(SHELL) '$(rename_flags_tbl)' $(beauty_uapi_linux_dir) > $@ - -arch_errno_name_array := $(beauty_outdir)/arch_errno_name_array.c -arch_errno_hdr_dir := $(srctree)/tools -arch_errno_tbl := $(srctree)/tools/perf/trace/beauty/arch_errno_names.sh - -$(arch_errno_name_array): $(arch_errno_tbl) - $(Q)$(SHELL) '$(arch_errno_tbl)' '$(patsubst -%,,$(CC))' $(arch_errno_hdr_dir) > $@ - -statx_mask_array := $(beauty_outdir)/statx_mask_array.c -statx_mask_tbl := $(srctree)/tools/perf/trace/beauty/statx_mask.sh - -$(statx_mask_array): $(beauty_uapi_linux_dir)/stat.h $(statx_mask_tbl) - $(Q)$(SHELL) '$(statx_mask_tbl)' $(beauty_uapi_linux_dir) > $@ - -sync_file_range_arrays := $(beauty_outdir)/sync_file_range_arrays.c -sync_file_range_tbls := $(srctree)/tools/perf/trace/beauty/sync_file_range.sh - -$(sync_file_range_arrays): $(beauty_uapi_linux_dir)/fs.h $(sync_file_range_tbls) - $(Q)$(SHELL) '$(sync_file_range_tbls)' $(beauty_uapi_linux_dir) > $@ TESTS_CORESIGHT_DIR := $(srctree)/tools/perf/tests/shell/coresight @@ -848,38 +629,6 @@ build-dir = $(or $(__build-dir),.) prepare: $(OUTPUT)PERF-VERSION-FILE archheaders \ arm64-sysreg-defs \ - $(syscall_array) \ - $(fs_at_flags_array) \ - $(clone_flags_array) \ - $(drm_ioctl_array) \ - $(fadvise_advice_array) \ - $(fsconfig_arrays) \ - $(fsmount_arrays) \ - $(fspick_arrays) \ - $(pkey_alloc_access_rights_array) \ - $(sndrv_pcm_ioctl_array) \ - $(sndrv_ctl_ioctl_array) \ - $(kcmp_type_array) \ - $(kvm_ioctl_array) \ - $(socket_arrays) \ - $(sockaddr_arrays) \ - $(vhost_virtio_ioctl_array) \ - $(madvise_behavior_array) \ - $(mmap_flags_array) \ - $(mmap_prot_array) \ - $(mremap_flags_array) \ - $(mount_flags_array) \ - $(move_mount_flags_array) \ - $(perf_ioctl_array) \ - $(prctl_option_array) \ - $(usbdevfs_ioctl_array) \ - $(x86_arch_irq_vectors_array) \ - $(x86_arch_MSRs_array) \ - $(x86_arch_prctl_code_array) \ - $(rename_flags_array) \ - $(arch_errno_name_array) \ - $(statx_mask_array) \ - $(sync_file_range_arrays) \ $(LIBAPI) \ $(LIBPERF) \ $(LIBSUBCMD) \ @@ -1299,35 +1048,8 @@ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $( TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE \ $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \ $(OUTPUT)util/intel-pt-decoder/inat-tables.c \ - $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ - $(OUTPUT)$(fadvise_advice_array) \ - $(OUTPUT)$(fsconfig_arrays) \ - $(OUTPUT)$(fsmount_arrays) \ - $(OUTPUT)$(fspick_arrays) \ - $(OUTPUT)$(madvise_behavior_array) \ - $(OUTPUT)$(mmap_flags_array) \ - $(OUTPUT)$(mmap_prot_array) \ - $(OUTPUT)$(mremap_flags_array) \ - $(OUTPUT)$(mount_flags_array) \ - $(OUTPUT)$(move_mount_flags_array) \ - $(OUTPUT)$(drm_ioctl_array) \ - $(OUTPUT)$(pkey_alloc_access_rights_array) \ - $(OUTPUT)$(sndrv_ctl_ioctl_array) \ - $(OUTPUT)$(sndrv_pcm_ioctl_array) \ - $(OUTPUT)$(kvm_ioctl_array) \ - $(OUTPUT)$(kcmp_type_array) \ - $(OUTPUT)$(socket_arrays) \ - $(OUTPUT)$(sockaddr_arrays) \ - $(OUTPUT)$(vhost_virtio_ioctl_array) \ - $(OUTPUT)$(perf_ioctl_array) \ - $(OUTPUT)$(prctl_option_array) \ - $(OUTPUT)$(usbdevfs_ioctl_array) \ - $(OUTPUT)$(x86_arch_irq_vectors_array) \ - $(OUTPUT)$(x86_arch_MSRs_array) \ - $(OUTPUT)$(x86_arch_prctl_code_array) \ - $(OUTPUT)$(rename_flags_array) \ - $(OUTPUT)$(arch_errno_name_array) \ - $(OUTPUT)$(sync_file_range_arrays) + $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c + $(Q)$(RM) -r $(OUTPUT)trace/beauty/generated $(call QUIET_CLEAN, Documentation) \ $(MAKE) -C $(DOC_DIR) O=$(OUTPUT) clean >/dev/null diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index d4fafae853d4..0730c1d9f0b3 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -60,12 +60,13 @@ #include "callchain.h" #include "print_binary.h" #include "string2.h" -#include "syscalltbl.h" +#include "trace/beauty/syscalltbl.h" #include "../perf.h" #include "trace_augment.h" #include "dwarf-regs.h" #include +#include #include #include #include @@ -235,6 +236,16 @@ struct trace { const char *uid_str; }; +bool trace__show_zeros(const struct trace *trace) +{ + return trace->show_zeros; +} + +struct machine *trace__host(const struct trace *trace) +{ + return trace->host; +} + static void trace__load_vmlinux_btf(struct trace *trace __maybe_unused) { #ifdef HAVE_LIBBPF_SUPPORT @@ -777,10 +788,6 @@ static const char *fsmount_flags[] = { }; static DEFINE_STRARRAY(fsmount_flags, "FSMOUNT_"); -#include "trace/beauty/generated/fsconfig_arrays.c" - -static DEFINE_STRARRAY(fsconfig_cmds, "FSCONFIG_"); - static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", }; static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, "EPOLL_CTL_", 1); @@ -1129,21 +1136,6 @@ static bool syscall_arg__strtoul_btf_type(char *bf __maybe_unused, size_t size _ .parm = &strarray__##array, \ .show_zero = true, } -#include "trace/beauty/eventfd.c" -#include "trace/beauty/futex_op.c" -#include "trace/beauty/futex_val3.c" -#include "trace/beauty/mmap.c" -#include "trace/beauty/mode_t.c" -#include "trace/beauty/msg_flags.c" -#include "trace/beauty/open_flags.c" -#include "trace/beauty/perf_event_open.c" -#include "trace/beauty/pid.c" -#include "trace/beauty/sched_policy.c" -#include "trace/beauty/seccomp.c" -#include "trace/beauty/signum.c" -#include "trace/beauty/socket_type.c" -#include "trace/beauty/waitid_options.c" - static const struct syscall_fmt syscall_fmts[] = { { .name = "access", .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build index 561590ee8cda..93cde93461a3 100644 --- a/tools/perf/trace/beauty/Build +++ b/tools/perf/trace/beauty/Build @@ -19,6 +19,23 @@ perf-y += socket.o perf-y += statx.o perf-y += sync_file_range.o perf-y += timespec.o +perf-util-y += syscalltbl.o +perf-y += fsconfig.o +perf-y += eventfd.o +perf-y += futex_op.o +perf-y += futex_val3.o +perf-y += mmap.o +perf-y += mode_t.o +perf-y += msg_flags.o +perf-y += open_flags.o +perf-y += perf_event_open.o +perf-y += pid.o +perf-y += sched_policy.o +perf-y += seccomp.o +perf-y += signum.o +perf-y += socket_type.o +perf-y += waitid_options.o +perf-util-y += arch_errno_names.o perf-y += tracepoints/ ifdef SHELLCHECK @@ -34,3 +51,262 @@ $(OUTPUT)%.shellcheck_log: % $(Q)$(call echo-cmd,test)$(SHELLCHECK) "$<" > $@ || (cat $@ && rm $@ && false) perf-y += $(SHELL_TEST_LOGS) + +beauty_linux_dir := $(srctree)/tools/perf/trace/beauty/include/linux/ +beauty_uapi_linux_dir := $(srctree)/tools/perf/trace/beauty/include/uapi/linux/ +beauty_uapi_sound_dir := $(srctree)/tools/perf/trace/beauty/include/uapi/sound/ +beauty_arch_asm_dir := $(srctree)/tools/perf/trace/beauty/arch/x86/include/asm/ +beauty_x86_arch_asm_uapi_dir := $(srctree)/tools/perf/trace/beauty/arch/x86/include/uapi/asm/ + +linux_uapi_dir := $(srctree)/tools/include/uapi/linux +asm_generic_uapi_dir := $(srctree)/tools/include/uapi/asm-generic +arch_asm_uapi_dir := $(srctree)/tools/arch/$(SRCARCH)/include/uapi/asm/ +x86_arch_asm_dir := $(srctree)/tools/arch/x86/include/asm/ + +beauty_outdir := $(OUTPUT)trace/beauty/generated +beauty_ioctl_outdir := $(beauty_outdir)/ioctl + +syscall_array := $(beauty_outdir)/syscalltbl.c +syscall_tbl := $(srctree)/tools/perf/trace/beauty/syscalltbl.sh +syscall_tbl_data := $(srctree)/tools/scripts/syscall.tbl \ + $(wildcard $(srctree)/tools/perf/arch/*/entry/syscalls/syscall*.tbl) + +$(syscall_array): $(syscall_tbl) $(syscall_tbl_data) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(syscall_tbl)' $(srctree)/tools $@ + +fs_at_flags_array := $(beauty_outdir)/fs_at_flags_array.c +fs_at_flags_tbl := $(srctree)/tools/perf/trace/beauty/fs_at_flags.sh + +$(fs_at_flags_array): $(beauty_uapi_linux_dir)/fcntl.h $(fs_at_flags_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(fs_at_flags_tbl)' $(beauty_uapi_linux_dir) > $@ + +clone_flags_array := $(beauty_outdir)/clone_flags_array.c +clone_flags_tbl := $(srctree)/tools/perf/trace/beauty/clone.sh + +$(clone_flags_array): $(beauty_uapi_linux_dir)/sched.h $(clone_flags_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(clone_flags_tbl)' $(beauty_uapi_linux_dir) > $@ + +drm_ioctl_array := $(beauty_ioctl_outdir)/drm_ioctl_array.c +drm_hdr_dir := $(srctree)/tools/perf/trace/beauty/include/uapi/drm +drm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/drm_ioctl.sh + +$(drm_ioctl_array): $(drm_hdr_dir)/drm.h $(drm_hdr_dir)/i915_drm.h $(drm_ioctl_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(drm_ioctl_tbl)' $(drm_hdr_dir) > $@ + +fadvise_advice_array := $(beauty_outdir)/fadvise_advice_array.c +fadvise_advice_tbl := $(srctree)/tools/perf/trace/beauty/fadvise.sh + +$(fadvise_advice_array): $(beauty_uapi_linux_dir)/fadvise.h $(fadvise_advice_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(fadvise_advice_tbl)' $(beauty_uapi_linux_dir) > $@ + +fsmount_arrays := $(beauty_outdir)/fsmount_arrays.c +fsmount_tbls := $(srctree)/tools/perf/trace/beauty/fsmount.sh + +$(fsmount_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsmount_tbls) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(fsmount_tbls)' $(beauty_uapi_linux_dir) > $@ + +fspick_arrays := $(beauty_outdir)/fspick_arrays.c +fspick_tbls := $(srctree)/tools/perf/trace/beauty/fspick.sh + +$(fspick_arrays): $(beauty_uapi_linux_dir)/mount.h $(fspick_tbls) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(fspick_tbls)' $(beauty_uapi_linux_dir) > $@ + +fsconfig_arrays := $(beauty_outdir)/fsconfig_arrays.c +fsconfig_tbls := $(srctree)/tools/perf/trace/beauty/fsconfig.sh + +$(fsconfig_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsconfig_tbls) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(fsconfig_tbls)' $(beauty_uapi_linux_dir) > $@ + +pkey_alloc_access_rights_array := $(beauty_outdir)/pkey_alloc_access_rights_array.c +asm_generic_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/ +pkey_alloc_access_rights_tbl := $(srctree)/tools/perf/trace/beauty/pkey_alloc_access_rights.sh + +$(pkey_alloc_access_rights_array): $(asm_generic_hdr_dir)/mman-common.h $(pkey_alloc_access_rights_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(pkey_alloc_access_rights_tbl)' $(asm_generic_hdr_dir) > $@ + +sndrv_ctl_ioctl_array := $(beauty_ioctl_outdir)/sndrv_ctl_ioctl_array.c +sndrv_ctl_hdr_dir := $(srctree)/tools/include/uapi/sound +sndrv_ctl_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh + +$(sndrv_ctl_ioctl_array): $(beauty_uapi_sound_dir)/asound.h $(sndrv_ctl_ioctl_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(sndrv_ctl_ioctl_tbl)' $(beauty_uapi_sound_dir) > $@ + +sndrv_pcm_ioctl_array := $(beauty_ioctl_outdir)/sndrv_pcm_ioctl_array.c +sndrv_pcm_hdr_dir := $(srctree)/tools/include/uapi/sound +sndrv_pcm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh + +$(sndrv_pcm_ioctl_array): $(beauty_uapi_sound_dir)/asound.h $(sndrv_pcm_ioctl_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(beauty_uapi_sound_dir) > $@ + +kcmp_type_array := $(beauty_outdir)/kcmp_type_array.c +kcmp_hdr_dir := $(srctree)/tools/include/uapi/linux/ +kcmp_type_tbl := $(srctree)/tools/perf/trace/beauty/kcmp_type.sh + +$(kcmp_type_array): $(kcmp_hdr_dir)/kcmp.h $(kcmp_type_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(kcmp_type_tbl)' $(kcmp_hdr_dir) > $@ + +kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c +kvm_hdr_dir := $(srctree)/tools/include/uapi/linux +kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh + +$(kvm_ioctl_array): $(kvm_hdr_dir)/kvm.h $(kvm_ioctl_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(kvm_ioctl_tbl)' $(kvm_hdr_dir) > $@ + +socket_arrays := $(beauty_outdir)/socket.c +socket_tbl := $(srctree)/tools/perf/trace/beauty/socket.sh + +$(socket_arrays): $(linux_uapi_dir)/in.h $(beauty_linux_dir)/socket.h $(socket_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(socket_tbl)' $(linux_uapi_dir) $(beauty_linux_dir) > $@ + +sockaddr_arrays := $(beauty_outdir)/sockaddr.c +sockaddr_tbl := $(srctree)/tools/perf/trace/beauty/sockaddr.sh + +$(sockaddr_arrays): $(beauty_linux_dir)/socket.h $(sockaddr_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(sockaddr_tbl)' $(beauty_linux_dir) > $@ + +vhost_virtio_ioctl_array := $(beauty_ioctl_outdir)/vhost_virtio_ioctl_array.c +vhost_virtio_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/vhost_virtio_ioctl.sh + +$(vhost_virtio_ioctl_array): $(beauty_uapi_linux_dir)/vhost.h $(vhost_virtio_ioctl_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(vhost_virtio_ioctl_tbl)' $(beauty_uapi_linux_dir) > $@ + +perf_ioctl_array := $(beauty_ioctl_outdir)/perf_ioctl_array.c +perf_hdr_dir := $(srctree)/tools/include/uapi/linux +perf_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/perf_ioctl.sh + +$(perf_ioctl_array): $(perf_hdr_dir)/perf_event.h $(perf_ioctl_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(perf_ioctl_tbl)' $(perf_hdr_dir) > $@ + +madvise_behavior_array := $(beauty_outdir)/madvise_behavior_array.c +madvise_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/ +madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh + +$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@ + +mmap_flags_array := $(beauty_outdir)/mmap_flags_array.c +mmap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mmap_flags.sh + +$(mmap_flags_array): $(linux_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(mmap_flags_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(mmap_flags_tbl)' $(linux_uapi_dir) $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@ + +mremap_flags_array := $(beauty_outdir)/mremap_flags_array.c +mremap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mremap_flags.sh + +$(mremap_flags_array): $(linux_uapi_dir)/mman.h $(mremap_flags_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(mremap_flags_tbl)' $(linux_uapi_dir) > $@ + +mount_flags_array := $(beauty_outdir)/mount_flags_array.c +mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/mount_flags.sh + +$(mount_flags_array): $(beauty_uapi_linux_dir)/mount.h $(mount_flags_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(mount_flags_tbl)' $(beauty_uapi_linux_dir) > $@ + +move_mount_flags_array := $(beauty_outdir)/move_mount_flags_array.c +move_mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/move_mount_flags.sh + +$(move_mount_flags_array): $(beauty_uapi_linux_dir)/mount.h $(move_mount_flags_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(move_mount_flags_tbl)' $(beauty_uapi_linux_dir) > $@ + +mmap_prot_array := $(beauty_outdir)/mmap_prot_array.c +mmap_prot_tbl := $(srctree)/tools/perf/trace/beauty/mmap_prot.sh + +$(mmap_prot_array): $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(mmap_prot_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(mmap_prot_tbl)' $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@ + +prctl_option_array := $(beauty_outdir)/prctl_option_array.c +prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh + +$(prctl_option_array): $(beauty_uapi_linux_dir)/prctl.h $(prctl_option_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(prctl_option_tbl)' $(beauty_uapi_linux_dir) > $@ + +usbdevfs_ioctl_array := $(beauty_ioctl_outdir)/usbdevfs_ioctl_array.c +usbdevfs_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/usbdevfs_ioctl.sh + +$(usbdevfs_ioctl_array): $(beauty_uapi_linux_dir)/usbdevice_fs.h $(usbdevfs_ioctl_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(usbdevfs_ioctl_tbl)' $(beauty_uapi_linux_dir) > $@ + +x86_arch_prctl_code_array := $(beauty_outdir)/x86_arch_prctl_code_array.c +x86_arch_prctl_code_tbl := $(srctree)/tools/perf/trace/beauty/x86_arch_prctl.sh + +$(x86_arch_prctl_code_array): $(beauty_x86_arch_asm_uapi_dir)/prctl.h $(x86_arch_prctl_code_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(x86_arch_prctl_code_tbl)' $(beauty_x86_arch_asm_uapi_dir) > $@ + + +rename_flags_array := $(beauty_outdir)/rename_flags_array.c +rename_flags_tbl := $(srctree)/tools/perf/trace/beauty/rename_flags.sh + +$(rename_flags_array): $(beauty_uapi_linux_dir)/fs.h $(rename_flags_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(rename_flags_tbl)' $(beauty_uapi_linux_dir) > $@ + + +statx_mask_array := $(beauty_outdir)/statx_mask_array.c +statx_mask_tbl := $(srctree)/tools/perf/trace/beauty/statx_mask.sh + +$(statx_mask_array): $(beauty_uapi_linux_dir)/stat.h $(statx_mask_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(statx_mask_tbl)' $(beauty_uapi_linux_dir) > $@ + +sync_file_range_arrays := $(beauty_outdir)/sync_file_range_arrays.c +sync_file_range_tbls := $(srctree)/tools/perf/trace/beauty/sync_file_range.sh + +$(sync_file_range_arrays): $(beauty_uapi_linux_dir)/fs.h $(sync_file_range_tbls) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(sync_file_range_tbls)' $(beauty_uapi_linux_dir) > $@ + +$(OUTPUT)trace/beauty/syscalltbl.o: $(syscall_array) +$(OUTPUT)trace/beauty/fsconfig.o: $(fsconfig_arrays) +$(OUTPUT)trace/beauty/clone.o: $(clone_flags_array) +$(OUTPUT)trace/beauty/fs_at_flags.o: $(fs_at_flags_array) +$(OUTPUT)trace/beauty/fsmount.o: $(fsmount_arrays) +$(OUTPUT)trace/beauty/fspick.o: $(fspick_arrays) +$(OUTPUT)trace/beauty/ioctl.o: $(drm_ioctl_array) $(sndrv_pcm_ioctl_array) $(sndrv_ctl_ioctl_array) $(kvm_ioctl_array) $(vhost_virtio_ioctl_array) $(perf_ioctl_array) $(usbdevfs_ioctl_array) +$(OUTPUT)trace/beauty/kcmp.o: $(kcmp_type_array) +$(OUTPUT)trace/beauty/mmap.o: $(mmap_prot_array) $(mmap_flags_array) $(mremap_flags_array) $(madvise_behavior_array) +$(OUTPUT)trace/beauty/mount_flags.o: $(mount_flags_array) +$(OUTPUT)trace/beauty/move_mount.o: $(move_mount_flags_array) +$(OUTPUT)trace/beauty/pkey_alloc.o: $(pkey_alloc_access_rights_array) +$(OUTPUT)trace/beauty/prctl.o: $(prctl_option_array) +$(OUTPUT)trace/beauty/renameat.o: $(rename_flags_array) +$(OUTPUT)trace/beauty/sockaddr.o: $(sockaddr_arrays) +$(OUTPUT)trace/beauty/socket.o: $(socket_arrays) +$(OUTPUT)trace/beauty/statx.o: $(statx_mask_array) +$(OUTPUT)trace/beauty/sync_file_range.o: $(sync_file_range_arrays) +$(OUTPUT)trace/beauty/arch_prctl.o: $(x86_arch_prctl_code_array) + +arch_errno_name_array := $(beauty_outdir)/arch_errno_name_array.c +arch_errno_hdr_dir := $(srctree)/tools +arch_errno_tbl := $(srctree)/tools/perf/trace/beauty/arch_errno_names.sh + +$(arch_errno_name_array): $(arch_errno_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(arch_errno_tbl)' '$(patsubst -%,,$(CC))' $(arch_errno_hdr_dir) > $@ + +$(OUTPUT)trace/beauty/arch_errno_names.o: $(arch_errno_name_array) diff --git a/tools/perf/trace/beauty/arch_errno_names.c b/tools/perf/trace/beauty/arch_errno_names.c index ede031c3a9e0..156c6537e747 100644 --- a/tools/perf/trace/beauty/arch_errno_names.c +++ b/tools/perf/trace/beauty/arch_errno_names.c @@ -1 +1,3 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "util/env.h" #include "trace/beauty/generated/arch_errno_name_array.c" diff --git a/tools/perf/trace/beauty/arch_errno_names.sh b/tools/perf/trace/beauty/arch_errno_names.sh index b22890b8d272..d48d8561a7bb 100755 --- a/tools/perf/trace/beauty/arch_errno_names.sh +++ b/tools/perf/trace/beauty/arch_errno_names.sh @@ -57,7 +57,7 @@ create_arch_errno_table_func() archlist="$1" default="$2" - printf 'static arch_syscalls__strerrno_t *\n' + printf 'arch_syscalls__strerrno_t *\n' printf 'arch_syscalls__strerrno_function(const char *arch)\n' printf '{\n' for arch in $archlist; do diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h index 0a07ad158f87..931c4a80fea9 100644 --- a/tools/perf/trace/beauty/beauty.h +++ b/tools/perf/trace/beauty/beauty.h @@ -35,6 +35,8 @@ bool strarray__strtoul(struct strarray *sa, char *bf, size_t size, u64 *ret); bool strarray__strtoul_flags(struct strarray *sa, char *bf, size_t size, u64 *ret); struct trace; +bool trace__show_zeros(const struct trace *trace); +struct machine *trace__host(const struct trace *trace); struct thread; struct file { @@ -265,4 +267,62 @@ size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool sh void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg, size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg)); +extern struct strarray strarray__fsconfig_cmds; + +size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags + +size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op + +size_t syscall_arg__scnprintf_futex_val3(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_FUTEX_VAL3 syscall_arg__scnprintf_futex_val3 + +size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot + +extern struct strarray strarray__mmap_flags; + +size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags + +size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags + +size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior + +size_t syscall_arg__scnprintf_mode_t(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_MODE_T syscall_arg__scnprintf_mode_t + +size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags + +size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags + +size_t syscall_arg__scnprintf_perf_event_attr(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_PERF_ATTR syscall_arg__scnprintf_perf_event_attr +#define SCA_PERF_ATTR_FROM_USER(argname) \ + { .scnprintf = SCA_PERF_ATTR, \ + .from_user = true, } + +size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_SCHED_POLICY syscall_arg__scnprintf_sched_policy + +size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op + +size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags + +size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_SIGNUM syscall_arg__scnprintf_signum + +size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type + +size_t syscall_arg__scnprintf_waitid_options(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_WAITID_OPTIONS syscall_arg__scnprintf_waitid_options + #endif /* _PERF_TRACE_BEAUTY_H */ diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c index 4bab106213c6..18b661282834 100644 --- a/tools/perf/trace/beauty/eventfd.c +++ b/tools/perf/trace/beauty/eventfd.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" + #ifndef EFD_SEMAPHORE #define EFD_SEMAPHORE 1 #endif @@ -11,7 +13,7 @@ #define EFD_CLOEXEC 02000000 #endif -static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "EFD_"; @@ -35,5 +37,3 @@ static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, struct return printed; } - -#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags diff --git a/tools/perf/trace/beauty/fsconfig.c b/tools/perf/trace/beauty/fsconfig.c new file mode 100644 index 000000000000..98aa05315673 --- /dev/null +++ b/tools/perf/trace/beauty/fsconfig.c @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" +#include "trace/beauty/generated/fsconfig_arrays.c" + +DEFINE_STRARRAY(fsconfig_cmds, "FSCONFIG_"); diff --git a/tools/perf/trace/beauty/futex_op.c b/tools/perf/trace/beauty/futex_op.c index 00365156782b..05d2111e504b 100644 --- a/tools/perf/trace/beauty/futex_op.c +++ b/tools/perf/trace/beauty/futex_op.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" #include #ifndef FUTEX_WAIT_BITSET @@ -17,7 +18,7 @@ #define FUTEX_CLOCK_REALTIME 256 #endif -static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "FUTEX_"; @@ -59,5 +60,3 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct sysc return printed; } - -#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op diff --git a/tools/perf/trace/beauty/futex_val3.c b/tools/perf/trace/beauty/futex_val3.c index 9114f7620571..fe4e82741ffc 100644 --- a/tools/perf/trace/beauty/futex_val3.c +++ b/tools/perf/trace/beauty/futex_val3.c @@ -1,11 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" #include #ifndef FUTEX_BITSET_MATCH_ANY #define FUTEX_BITSET_MATCH_ANY 0xffffffff #endif -static size_t syscall_arg__scnprintf_futex_val3(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_futex_val3(char *bf, size_t size, struct syscall_arg *arg) { const char *prefix = "FUTEX_BITSET_"; unsigned int bitset = arg->val; @@ -15,5 +16,3 @@ static size_t syscall_arg__scnprintf_futex_val3(char *bf, size_t size, struct sy return scnprintf(bf, size, "%#xd", bitset); } - -#define SCA_FUTEX_VAL3 syscall_arg__scnprintf_futex_val3 diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c index 3c5e97b93dd5..c8a4cd49c845 100644 --- a/tools/perf/trace/beauty/mmap.c +++ b/tools/perf/trace/beauty/mmap.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1 #include +#include "trace/beauty/beauty.h" #include "trace/beauty/generated/mmap_prot_array.c" static DEFINE_STRARRAY(mmap_prot, "PROT_"); @@ -8,8 +9,7 @@ static size_t mmap__scnprintf_prot(unsigned long prot, char *bf, size_t size, bo { return strarray__scnprintf_flags(&strarray__mmap_prot, bf, size, show_prefix, prot); } - -static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, struct syscall_arg *arg) { unsigned long prot = arg->val; @@ -19,18 +19,18 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, struct sys return mmap__scnprintf_prot(prot, bf, size, arg->show_string_prefix); } -#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot + #include "trace/beauty/generated/mmap_flags_array.c" -static DEFINE_STRARRAY(mmap_flags, "MAP_"); +DEFINE_STRARRAY(mmap_flags, "MAP_"); static size_t mmap__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix) { return strarray__scnprintf_flags(&strarray__mmap_flags, bf, size, show_prefix, flags); } -static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, - struct syscall_arg *arg) +size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, + struct syscall_arg *arg) { unsigned long flags = arg->val; @@ -40,7 +40,7 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, return mmap__scnprintf_flags(flags, bf, size, arg->show_string_prefix); } -#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags + #include "trace/beauty/generated/mremap_flags_array.c" static DEFINE_STRARRAY(mremap_flags, "MREMAP_"); @@ -50,7 +50,7 @@ static size_t mremap__scnprintf_flags(unsigned long flags, char *bf, size_t size return strarray__scnprintf_flags(&strarray__mremap_flags, bf, size, show_prefix, flags); } -static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, struct syscall_arg *arg) { unsigned long flags = arg->val; @@ -60,7 +60,7 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, struct return mremap__scnprintf_flags(flags, bf, size, arg->show_string_prefix); } -#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags + static size_t madvise__scnprintf_behavior(int behavior, char *bf, size_t size) { @@ -73,10 +73,8 @@ static size_t madvise__scnprintf_behavior(int behavior, char *bf, size_t size) return scnprintf(bf, size, "%#", behavior); } -static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, - struct syscall_arg *arg) +size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, + struct syscall_arg *arg) { return madvise__scnprintf_behavior(arg->val, bf, size); } - -#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior diff --git a/tools/perf/trace/beauty/mode_t.c b/tools/perf/trace/beauty/mode_t.c index 29a8fadfb7f9..9304b0bf3094 100644 --- a/tools/perf/trace/beauty/mode_t.c +++ b/tools/perf/trace/beauty/mode_t.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" + #include #include #include @@ -20,7 +22,7 @@ #define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) #endif -static size_t syscall_arg__scnprintf_mode_t(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_mode_t(char *bf, size_t size, struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "S_"; @@ -67,5 +69,3 @@ static size_t syscall_arg__scnprintf_mode_t(char *bf, size_t size, struct syscal return printed; } - -#define SCA_MODE_T syscall_arg__scnprintf_mode_t diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c index 2da581ff0c80..be7f82677cbf 100644 --- a/tools/perf/trace/beauty/msg_flags.c +++ b/tools/perf/trace/beauty/msg_flags.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" + #include #include @@ -27,8 +29,8 @@ # define MSG_CMSG_CLOEXEC 0x40000000 #endif -static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size, - struct syscall_arg *arg) +size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size, + struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "MSG_"; @@ -72,5 +74,3 @@ static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size, return printed; } - -#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c index 78f6566ef110..c2c7769e6595 100644 --- a/tools/perf/trace/beauty/open_flags.c +++ b/tools/perf/trace/beauty/open_flags.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" + #include #include #include diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c index 9f1ed989c775..c1c7445dcff9 100644 --- a/tools/perf/trace/beauty/perf_event_open.c +++ b/tools/perf/trace/beauty/perf_event_open.c @@ -1,4 +1,8 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" +#include "util/evsel_fprintf.h" +#include + #ifndef PERF_FLAG_FD_NO_GROUP # define PERF_FLAG_FD_NO_GROUP (1UL << 0) #endif @@ -15,8 +19,8 @@ # define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */ #endif -static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size, - struct syscall_arg *arg) +size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size, + struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "PERF_"; @@ -43,7 +47,7 @@ static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size, return printed; } -#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags + struct attr_fprintf_args { size_t size, printed; @@ -76,19 +80,14 @@ static size_t perf_event_attr___scnprintf(struct perf_event_attr *attr, char *bf static size_t syscall_arg__scnprintf_augmented_perf_event_attr(struct syscall_arg *arg, char *bf, size_t size) { - return perf_event_attr___scnprintf((void *)arg->augmented.args->value, bf, size, arg->trace->show_zeros); + return perf_event_attr___scnprintf((void *)arg->augmented.args->value, bf, size, + trace__show_zeros(arg->trace)); } -static size_t syscall_arg__scnprintf_perf_event_attr(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_perf_event_attr(char *bf, size_t size, struct syscall_arg *arg) { if (arg->augmented.args) return syscall_arg__scnprintf_augmented_perf_event_attr(arg, bf, size); return scnprintf(bf, size, "%#lx", arg->val); } - -#define SCA_PERF_ATTR syscall_arg__scnprintf_perf_event_attr -// 'argname' is just documentational at this point, to remove the previous comment with that info -#define SCA_PERF_ATTR_FROM_USER(argname) \ - { .scnprintf = SCA_PERF_ATTR, \ - .from_user = true, } diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c index 8f9c9950f8ba..cca4a3a5d9bd 100644 --- a/tools/perf/trace/beauty/pid.c +++ b/tools/perf/trace/beauty/pid.c @@ -1,11 +1,14 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" +#include "util/machine.h" +#include "util/thread.h" size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg) { int pid = arg->val; struct trace *trace = arg->trace; size_t printed = scnprintf(bf, size, "%d", pid); - struct thread *thread = machine__findnew_thread(trace->host, pid, pid); + struct thread *thread = machine__findnew_thread(trace__host(trace), pid, pid); if (thread != NULL) { if (!thread__comm_set(thread)) diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c index 68aa59eeed8d..3fb6d9e0fae9 100644 --- a/tools/perf/trace/beauty/sched_policy.c +++ b/tools/perf/trace/beauty/sched_policy.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" + #include /* @@ -14,8 +16,8 @@ #define SCHED_RESET_ON_FORK 0x40000000 #endif -static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, - struct syscall_arg *arg) +size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, + struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "SCHED_"; @@ -46,5 +48,3 @@ static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, return printed; } - -#define SCA_SCHED_POLICY syscall_arg__scnprintf_sched_policy diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c index 637722e2796b..f345c66c1bfa 100644 --- a/tools/perf/trace/beauty/seccomp.c +++ b/tools/perf/trace/beauty/seccomp.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" + #ifndef SECCOMP_SET_MODE_STRICT #define SECCOMP_SET_MODE_STRICT 0 #endif @@ -6,7 +8,7 @@ #define SECCOMP_SET_MODE_FILTER 1 #endif -static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "SECCOMP_SET_MODE_"; @@ -24,14 +26,14 @@ static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct sy return printed; } -#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op + #ifndef SECCOMP_FILTER_FLAG_TSYNC #define SECCOMP_FILTER_FLAG_TSYNC 1 #endif -static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size, - struct syscall_arg *arg) +size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size, + struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "SECCOMP_FILTER_FLAG_"; @@ -51,5 +53,3 @@ static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size, return printed; } - -#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags diff --git a/tools/perf/trace/beauty/signum.c b/tools/perf/trace/beauty/signum.c index 21220c56500a..6817e9febab9 100644 --- a/tools/perf/trace/beauty/signum.c +++ b/tools/perf/trace/beauty/signum.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" + #include -static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "SIG"; @@ -53,5 +55,3 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal return scnprintf(bf, size, "%#x", sig); } - -#define SCA_SIGNUM syscall_arg__scnprintf_signum diff --git a/tools/perf/trace/beauty/socket_type.c b/tools/perf/trace/beauty/socket_type.c index bed8d5761ca8..059e3041d338 100644 --- a/tools/perf/trace/beauty/socket_type.c +++ b/tools/perf/trace/beauty/socket_type.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" + #include #include @@ -18,7 +20,7 @@ #define SOCK_TYPE_MASK 0xf #endif -static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, struct syscall_arg *arg) +size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "SOCK_"; @@ -59,5 +61,3 @@ static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, struct s return printed; } - -#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/trace/beauty/syscalltbl.c similarity index 100% rename from tools/perf/util/syscalltbl.c rename to tools/perf/trace/beauty/syscalltbl.c diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/trace/beauty/syscalltbl.h similarity index 100% rename from tools/perf/util/syscalltbl.h rename to tools/perf/trace/beauty/syscalltbl.h diff --git a/tools/perf/trace/beauty/tracepoints/Build b/tools/perf/trace/beauty/tracepoints/Build index e35087fdd108..9924ad24a6f1 100644 --- a/tools/perf/trace/beauty/tracepoints/Build +++ b/tools/perf/trace/beauty/tracepoints/Build @@ -1,2 +1,23 @@ perf-y += x86_irq_vectors.o perf-y += x86_msr.o + +beauty_outdir := $(OUTPUT)trace/beauty/generated +beauty_arch_asm_dir := $(srctree)/tools/perf/trace/beauty/arch/x86/include/asm/ +x86_arch_asm_dir := $(srctree)/tools/arch/x86/include/asm/ + +x86_arch_irq_vectors_array := $(beauty_outdir)/x86_arch_irq_vectors_array.c +x86_arch_irq_vectors_tbl := $(srctree)/tools/perf/trace/beauty/tracepoints/x86_irq_vectors.sh + +$(x86_arch_irq_vectors_array): $(beauty_arch_asm_dir)/irq_vectors.h $(x86_arch_irq_vectors_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(x86_arch_irq_vectors_tbl)' $(beauty_arch_asm_dir) > $@ + +x86_arch_MSRs_array := $(beauty_outdir)/x86_arch_MSRs_array.c +x86_arch_MSRs_tbl := $(srctree)/tools/perf/trace/beauty/tracepoints/x86_msr.sh + +$(x86_arch_MSRs_array): $(x86_arch_asm_dir)/msr-index.h $(x86_arch_MSRs_tbl) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(x86_arch_MSRs_tbl)' $(x86_arch_asm_dir) > $@ + +$(OUTPUT)trace/beauty/tracepoints/x86_irq_vectors.o: $(x86_arch_irq_vectors_array) +$(OUTPUT)trace/beauty/tracepoints/x86_msr.o: $(x86_arch_MSRs_array) diff --git a/tools/perf/trace/beauty/waitid_options.c b/tools/perf/trace/beauty/waitid_options.c index d4d10b33ba0e..78ead5df985a 100644 --- a/tools/perf/trace/beauty/waitid_options.c +++ b/tools/perf/trace/beauty/waitid_options.c @@ -1,9 +1,11 @@ // SPDX-License-Identifier: LGPL-2.1 +#include "trace/beauty/beauty.h" + #include #include -static size_t syscall_arg__scnprintf_waitid_options(char *bf, size_t size, - struct syscall_arg *arg) +size_t syscall_arg__scnprintf_waitid_options(char *bf, size_t size, + struct syscall_arg *arg) { bool show_prefix = arg->show_string_prefix; const char *prefix = "W"; @@ -25,5 +27,3 @@ static size_t syscall_arg__scnprintf_waitid_options(char *bf, size_t size, return printed; } - -#define SCA_WAITID_OPTIONS syscall_arg__scnprintf_waitid_options diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 2bb60f50f62d..797d7bc909be 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -75,7 +75,7 @@ perf-util-y += sample.o perf-util-y += sample-raw.o perf-util-y += s390-sample-raw.o perf-util-y += amd-sample-raw.o -perf-util-$(CONFIG_TRACE) += syscalltbl.o + perf-util-y += ordered-events.o perf-util-y += namespaces.o perf-util-y += comm.o @@ -440,3 +440,5 @@ $(OUTPUT)%.pylint_log: % $(Q)$(call echo-cmd,test)pylint "$<" > $@ || (cat $@ && rm $@ && false) perf-util-y += $(PYLINT_TEST_LOGS) + + diff --git a/tools/perf/util/bpf-trace-summary.c b/tools/perf/util/bpf-trace-summary.c index cf6e1e4402d5..9a31dbf06cbb 100644 --- a/tools/perf/util/bpf-trace-summary.c +++ b/tools/perf/util/bpf-trace-summary.c @@ -6,7 +6,7 @@ #include #include "dwarf-regs.h" /* for EM_HOST */ -#include "syscalltbl.h" +#include "trace/beauty/syscalltbl.h" #include "util/cgroup.h" #include "util/hashmap.h" #include "util/trace.h" diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 1e54e2c86360..20953ef7b9d8 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -635,10 +635,6 @@ const char *perf_env__arch(struct perf_env *env) return normalize_arch(arch_name); } -#if defined(HAVE_LIBTRACEEVENT) -#include "trace/beauty/arch_errno_names.c" -#endif - const char *perf_env__arch_strerrno(struct perf_env *env __maybe_unused, int err __maybe_unused) { #if defined(HAVE_LIBTRACEEVENT) diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index c7052ac1f856..739d884fc236 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -189,6 +189,7 @@ void cpu_cache_level__free(struct cpu_cache_level *cache); const char *perf_env__arch(struct perf_env *env); const char *perf_env__arch_strerrno(struct perf_env *env, int err); +arch_syscalls__strerrno_t *arch_syscalls__strerrno_function(const char *arch); const char *perf_env__cpuid(struct perf_env *env); const char *perf_env__raw_arch(struct perf_env *env); int perf_env__nr_cpus_avail(struct perf_env *env); From b9453fa7726a225de8f80279e6085e164b3fc5a1 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:27 -0700 Subject: [PATCH 078/343] perf build: Decouple pmu-events from prepare umbrella target Currently, the $(LIBPMU_EVENTS_IN) sub-make depends on the massive "prepare" umbrella target. Because "prepare" depends on external libraries (libapi, libperf, etc.) as well as dozens of generated headers, make completely serializes the launch of the pmu-events sub-make behind some of those unrelated prerequisites. Since pmu-events is a large compilation unit, unblock its startup by binding it directly to only $(LIBPERF) instead of prepare. This allows background python generation scripts to overlap simultaneously with the rest of the build. Testing a parallel build (make -j28 clean all) shows improvements: Before: real 0m27.642s user 2m32.356s sys 0m26.683s After: real 0m22.254s user 2m32.810s sys 0m24.646s This reclaims over 5 full seconds of build latency (~19.5% overall reduction) by elevating average CPU concurrency from ~5.5 active cores up to ~8 active cores. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index c81797ceec42..c66af4c825fd 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -550,7 +550,7 @@ build := -f $(srctree)/tools/build/Makefile.build dir=. obj $(PERF_IN): prepare FORCE $(Q)$(MAKE) $(build)=perf -$(LIBPMU_EVENTS_IN): FORCE prepare +$(LIBPMU_EVENTS_IN): FORCE $(LIBPERF) $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=pmu-events $(LIBPMU_EVENTS): $(LIBPMU_EVENTS_IN) From 5af31e15732e343528058f987bc54175bb9a8588 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:28 -0700 Subject: [PATCH 079/343] perf build: Remove empty archheaders target Remove empty target that doesn't do anything. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index c66af4c825fd..24581941e912 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -627,7 +627,7 @@ endif __build-dir = $(subst $(OUTPUT),,$(dir $@)) build-dir = $(or $(__build-dir),.) -prepare: $(OUTPUT)PERF-VERSION-FILE archheaders \ +prepare: $(OUTPUT)PERF-VERSION-FILE \ arm64-sysreg-defs \ $(LIBAPI) \ $(LIBPERF) \ @@ -1070,7 +1070,7 @@ FORCE: .PHONY: all install clean config-clean strip install-gtk .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell .PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope FORCE prepare -.PHONY: archheaders python_perf_target +.PHONY: python_perf_target endif # force_fixdep From 713eeb2279402758bbfba301be6fae62c729b34e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:29 -0700 Subject: [PATCH 080/343] perf build: Move BPF skeleton generation out of Makefile.perf Currently, the top-level Makefile.perf defines a massive global bpf-skel umbrella target that pre-compiles all 12+ BPF skeletons (%.skel.h) upfront before launching sub-makes. This forces unrelated sub-makes to serialize behind bpftool and clang BPF target evaluations, causing parallel build bottlenecks. Furthermore, bench_uprobe.bpf.c lived inside util/bpf_skel/, breaking conceptual directory encapsulation since it is consumed purely by bench/uprobe.c. Refactor the BPF skeletons to better achieve directory isolation: 1. Move tools/perf/util/bpf_skel/bench_uprobe.bpf.c directly into tools/perf/bench/bpf_skel/. 2. Extract the skeleton generation infrastructure out of Makefile.perf into a shared inclusion file tools/perf/bpf_skel.mak. 3. Include bpf_skel.mak locally inside tools/perf/util/Build and tools/perf/bench/Build and bind precise local prerequisites. 4. Safely synchronize the shared bpftool bootstrap and vmlinux.h targets via the conditional prepare: umbrella to avoid parallel sub-make races, while evaluating the actual skeletons completely locally on demand. A later patch will move these targets into bpf_skel.mak. 5. Export CLANG from the global Makefile to ensure accurate tool propagation. 6. Clean up Makefile.perf by stripping the global bpf-skel umbrella target and its SKELETONS list. While removing code from Makefile.perf generally helps build performance, the impact here is minimal. The main motivation for the change is to better encapsulate things in the build and simplify Makefile.perf that has around 50 lines removed. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 59 ++----------------- tools/perf/bench/Build | 6 ++ .../bpf_skel/bench_uprobe.bpf.c | 0 tools/perf/bench/uprobe.c | 2 +- tools/perf/bpf_skel.mak | 54 +++++++++++++++++ tools/perf/util/Build | 13 ++++ 6 files changed, 78 insertions(+), 56 deletions(-) rename tools/perf/{util => bench}/bpf_skel/bench_uprobe.bpf.c (100%) create mode 100644 tools/perf/bpf_skel.mak diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 24581941e912..373eae7fb72a 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -274,7 +274,7 @@ ifeq ($(PYLINT),1) PYLINT := $(shell which pylint 2> /dev/null) endif -export srctree OUTPUT RM CC CXX RUSTC LD AR CFLAGS CXXFLAGS RUST_FLAGS V BISON FLEX AWK +export srctree OUTPUT RM CC CXX RUSTC CLANG LD AR CFLAGS CXXFLAGS RUST_FLAGS V BISON FLEX AWK LIBBPF export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK MYPY PYLINT include $(srctree)/tools/build/Makefile.include @@ -632,8 +632,7 @@ prepare: $(OUTPUT)PERF-VERSION-FILE \ $(LIBAPI) \ $(LIBPERF) \ $(LIBSUBCMD) \ - $(LIBSYMBOL) \ - bpf-skel + $(LIBSYMBOL) ifdef LIBBPF_STATIC prepare: $(LIBBPF) @@ -914,44 +913,13 @@ python-clean: SKEL_OUT := $(abspath $(OUTPUT)util/bpf_skel) SKEL_TMP_OUT := $(abspath $(SKEL_OUT)/.tmp) -SKELETONS := $(SKEL_OUT)/bpf_prog_profiler.skel.h -SKELETONS += $(SKEL_OUT)/bperf_leader.skel.h $(SKEL_OUT)/bperf_follower.skel.h -SKELETONS += $(SKEL_OUT)/bperf_cgroup.skel.h $(SKEL_OUT)/func_latency.skel.h -SKELETONS += $(SKEL_OUT)/off_cpu.skel.h $(SKEL_OUT)/lock_contention.skel.h -SKELETONS += $(SKEL_OUT)/kwork_trace.skel.h $(SKEL_OUT)/sample_filter.skel.h -SKELETONS += $(SKEL_OUT)/kwork_top.skel.h $(SKEL_OUT)/syscall_summary.skel.h -SKELETONS += $(SKEL_OUT)/bench_uprobe.skel.h -SKELETONS += $(SKEL_OUT)/augmented_raw_syscalls.skel.h $(SKEL_TMP_OUT) $(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_OUTPUT) $(LIBSYMBOL_OUTPUT): $(Q)$(MKDIR) -p $@ ifeq ($(CONFIG_PERF_BPF_SKEL),y) +prepare: $(BPFTOOL) $(SKEL_OUT)/vmlinux.h BPFTOOL := $(SKEL_TMP_OUT)/bootstrap/bpftool -# Get Clang's default includes on this system, as opposed to those seen by -# '--target=bpf'. This fixes "missing" files on some architectures/distros, -# such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc. -# -# Use '-idirafter': Don't interfere with include mechanics except where the -# build would have failed anyways. -define get_sys_includes -$(shell $(1) $(2) -v -E - &1 \ - | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \ -$(shell $(1) $(2) -dM -E - $@ - -bpf-skel: $(SKELETONS) - -.PRECIOUS: $(SKEL_TMP_OUT)/%.bpf.o - -else # CONFIG_PERF_BPF_SKEL - -bpf-skel: - endif # CONFIG_PERF_BPF_SKEL bpf-skel-clean: - $(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TMP_OUT) $(SKELETONS) $(SKEL_OUT)/vmlinux.h + $(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TMP_OUT) $(SKEL_OUT)/*.skel.h $(SKEL_OUT)/vmlinux.h $(OUTPUT)bench/bpf_skel/*.skel.h $(OUTPUT)bench/bpf_skel/.tmp pmu-events-clean: ifeq ($(OUTPUT),) diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build index b558ab98719f..67b76fe20ba6 100644 --- a/tools/perf/bench/Build +++ b/tools/perf/bench/Build @@ -24,3 +24,9 @@ perf-bench-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o perf-bench-$(CONFIG_X86_64) += mem-memset-x86-64-asm.o perf-bench-$(CONFIG_NUMA) += numa.o + +ifeq ($(CONFIG_PERF_BPF_SKEL),y) +include $(srctree)/tools/perf/bpf_skel.mak + +$(OUTPUT)bench/uprobe.o: $(SKEL_OUT)/bench_uprobe.skel.h +endif diff --git a/tools/perf/util/bpf_skel/bench_uprobe.bpf.c b/tools/perf/bench/bpf_skel/bench_uprobe.bpf.c similarity index 100% rename from tools/perf/util/bpf_skel/bench_uprobe.bpf.c rename to tools/perf/bench/bpf_skel/bench_uprobe.bpf.c diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c index 89697ff788ef..616873bca243 100644 --- a/tools/perf/bench/uprobe.c +++ b/tools/perf/bench/uprobe.c @@ -44,7 +44,7 @@ static const char * const bench_uprobe_usage[] = { }; #ifdef HAVE_BPF_SKEL -#include "bpf_skel/bench_uprobe.skel.h" +#include "bench/bpf_skel/bench_uprobe.skel.h" #define bench_uprobe__attach_uprobe(prog) \ skel->links.prog = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.prog, \ diff --git a/tools/perf/bpf_skel.mak b/tools/perf/bpf_skel.mak new file mode 100644 index 000000000000..aa04d8b3ee07 --- /dev/null +++ b/tools/perf/bpf_skel.mak @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0 +# Shared BPF Skeleton Generator Rules + +include $(srctree)/tools/scripts/Makefile.include + +# Shared foundational tooling always lives in util/bpf_skel +SKEL_TOOL_OUT := $(abspath $(OUTPUT)util/bpf_skel) +SKEL_TOOL_TMP_OUT := $(abspath $(SKEL_TOOL_OUT)/.tmp) + +# Component specific output lives in $(dir)/bpf_skel +SKEL_OUT := $(abspath $(OUTPUT)$(dir)/bpf_skel) +SKEL_TMP_OUT := $(abspath $(SKEL_OUT)/.tmp) + +ifeq ($(CONFIG_PERF_BPF_SKEL),y) +BPFTOOL := $(SKEL_TOOL_TMP_OUT)/bootstrap/bpftool +VMLINUX_H := $(SKEL_TOOL_OUT)/vmlinux.h + +define get_sys_includes +$(shell $(1) $(2) -v -E - &1 \ + | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \ +$(shell $(1) $(2) -dM -E - $@ + +.PRECIOUS: $(SKEL_TMP_OUT)/%.bpf.o +endif # CONFIG_PERF_BPF_SKEL diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 797d7bc909be..4bbc78b1f741 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -441,4 +441,17 @@ $(OUTPUT)%.pylint_log: % perf-util-y += $(PYLINT_TEST_LOGS) +ifeq ($(CONFIG_PERF_BPF_SKEL),y) +include $(srctree)/tools/perf/bpf_skel.mak +$(OUTPUT)util/bpf_ftrace.o: $(SKEL_OUT)/func_latency.skel.h +$(OUTPUT)util/bpf-filter.o: $(SKEL_OUT)/sample_filter.skel.h +$(OUTPUT)util/bpf_kwork_top.o: $(SKEL_OUT)/kwork_top.skel.h +$(OUTPUT)util/bpf_off_cpu.o: $(SKEL_OUT)/off_cpu.skel.h +$(OUTPUT)util/bpf-trace-summary.o: $(SKEL_OUT)/syscall_summary.skel.h +$(OUTPUT)util/bpf_counter_cgroup.o: $(SKEL_OUT)/bperf_cgroup.skel.h +$(OUTPUT)util/bpf_trace_augment.o: $(SKEL_OUT)/augmented_raw_syscalls.skel.h +$(OUTPUT)util/bpf_counter.o: $(SKEL_OUT)/bpf_prog_profiler.skel.h $(SKEL_OUT)/bperf_leader.skel.h $(SKEL_OUT)/bperf_follower.skel.h +$(OUTPUT)util/bpf_lock_contention.o: $(SKEL_OUT)/lock_contention.skel.h +$(OUTPUT)util/bpf_kwork.o: $(SKEL_OUT)/kwork_trace.skel.h +endif From 9798ac0128daf35cb52ca648b1d93f0d40bd0cf5 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:30 -0700 Subject: [PATCH 081/343] perf build: Encapsulate vmlinux.h and bpftool in bpf_skel.mak Currently, bpftool and vmlinux.h are prerequisites of the top-level prepare target in Makefile.perf. This unnecessarily blocks the massive parallel C compilation of libraries (perf-util, perf-ui, pmu-events) during the initial startup phase. Move all bpftool and vmlinux.h generation rules down into tools/perf/bpf_skel.mak to encapsulate BPF tooling completely within the skeleton framework. Remove them entirely from prepare to unblock immediate parallel build execution. To prevent parallel sub-makes (perf-util and perf-bench) from racing to build shared prerequisites concurrently, while maintaining strict directory encapsulation without top-level inclusions, serialize bench after the util static archive finishes using an order-only prerequisite: $(LIBPERF_BENCH_IN): FORCE prepare | $(LIBPERF_UTIL) Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 2 +- tools/perf/Makefile.perf | 61 +++++--------------------------------- tools/perf/bpf_skel.mak | 47 +++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 7a0e372824c6..8437c3f72125 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -681,7 +681,7 @@ ifeq ($(BUILD_BPF_SKEL),1) endif ifndef GEN_VMLINUX_H - VMLINUX_H=$(src-perf)/util/bpf_skel/vmlinux/vmlinux.h + VMLINUX_H_FILE=$(src-perf)/util/bpf_skel/vmlinux/vmlinux.h endif ifndef NO_LIBUNWIND diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 373eae7fb72a..ec0e91bedce1 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -274,7 +274,7 @@ ifeq ($(PYLINT),1) PYLINT := $(shell which pylint 2> /dev/null) endif -export srctree OUTPUT RM CC CXX RUSTC CLANG LD AR CFLAGS CXXFLAGS RUST_FLAGS V BISON FLEX AWK LIBBPF +export srctree OUTPUT RM CC CXX RUSTC CLANG LD AR CFLAGS CXXFLAGS RUST_FLAGS V BISON FLEX AWK LIBBPF READELF export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK MYPY PYLINT include $(srctree)/tools/build/Makefile.include @@ -324,7 +324,7 @@ else FEATURE_DUMP_EXPORT := $(realpath $(FEATURES_DUMP)) endif -export prefix bindir sharedir sysconfdir DESTDIR +export prefix bindir sharedir sysconfdir DESTDIR VMLINUX_H_FILE # sparse is architecture-neutral, which means that we need to tell it # explicitly what architecture to check for. Fix this up for yours.. @@ -556,7 +556,9 @@ $(LIBPMU_EVENTS_IN): FORCE $(LIBPERF) $(LIBPMU_EVENTS): $(LIBPMU_EVENTS_IN) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $< -$(LIBPERF_BENCH_IN): FORCE prepare +# The $(LIBPERF_UTIL) dependency is to ensure bpftool and vmlinux.h +# aren't racily built for bench/bpf_skel/bench_uprobe.bpf.c +$(LIBPERF_BENCH_IN): FORCE prepare | $(LIBPERF_UTIL) $(Q)$(MAKE) $(build)=perf-bench $(LIBPERF_BENCH): $(LIBPERF_BENCH_IN) @@ -911,60 +913,11 @@ $(INSTALL_DOC_TARGETS): python-clean: $(python-clean) -SKEL_OUT := $(abspath $(OUTPUT)util/bpf_skel) -SKEL_TMP_OUT := $(abspath $(SKEL_OUT)/.tmp) - -$(SKEL_TMP_OUT) $(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_OUTPUT) $(LIBSYMBOL_OUTPUT): +$(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_OUTPUT) $(LIBSYMBOL_OUTPUT): $(Q)$(MKDIR) -p $@ -ifeq ($(CONFIG_PERF_BPF_SKEL),y) -prepare: $(BPFTOOL) $(SKEL_OUT)/vmlinux.h -BPFTOOL := $(SKEL_TMP_OUT)/bootstrap/bpftool - -$(BPFTOOL): | $(SKEL_TMP_OUT) - $(Q)CFLAGS= $(MAKE) -C ../bpf/bpftool \ - OUTPUT=$(SKEL_TMP_OUT)/ bootstrap - -# Paths to search for a kernel to generate vmlinux.h from. -VMLINUX_BTF_ELF_PATHS ?= $(if $(O),$(O)/vmlinux) \ - $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \ - ../../vmlinux \ - /boot/vmlinux-$(shell uname -r) - -# Paths to BTF information. -VMLINUX_BTF_BTF_PATHS ?= /sys/kernel/btf/vmlinux - -# Filter out kernels that don't exist or without a BTF section. -VMLINUX_BTF_ELF_ABSPATHS ?= $(abspath $(wildcard $(VMLINUX_BTF_ELF_PATHS))) -VMLINUX_BTF_PATHS ?= $(shell for file in $(VMLINUX_BTF_ELF_ABSPATHS); \ - do \ - if [ -f $$file ] && ($(READELF) -S "$$file" | grep -q .BTF); \ - then \ - echo "$$file"; \ - fi; \ - done) \ - $(wildcard $(VMLINUX_BTF_BTF_PATHS)) - -# Select the first as the source of vmlinux.h. -VMLINUX_BTF ?= $(firstword $(VMLINUX_BTF_PATHS)) - -ifeq ($(VMLINUX_H),) - ifeq ($(VMLINUX_BTF),) - $(error Missing bpftool input for generating vmlinux.h) - endif -endif - -$(SKEL_OUT)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) $(VMLINUX_H) -ifeq ($(VMLINUX_H),) - $(QUIET_GEN)$(BPFTOOL) btf dump file $< format c > $@ -else - $(Q)cp "$(VMLINUX_H)" $@ -endif - -endif # CONFIG_PERF_BPF_SKEL - bpf-skel-clean: - $(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TMP_OUT) $(SKEL_OUT)/*.skel.h $(SKEL_OUT)/vmlinux.h $(OUTPUT)bench/bpf_skel/*.skel.h $(OUTPUT)bench/bpf_skel/.tmp + $(Q)$(MAKE) -f bpf_skel.mak clean pmu-events-clean: ifeq ($(OUTPUT),) diff --git a/tools/perf/bpf_skel.mak b/tools/perf/bpf_skel.mak index aa04d8b3ee07..30924ad140c4 100644 --- a/tools/perf/bpf_skel.mak +++ b/tools/perf/bpf_skel.mak @@ -35,6 +35,47 @@ ifneq ($(WERROR),0) CLANG_OPTIONS += -Werror endif +$(BPFTOOL): + $(Q)mkdir -p $(SKEL_TOOL_TMP_OUT) + $(Q)CFLAGS= $(MAKE) -C ../bpf/bpftool OUTPUT=$(SKEL_TOOL_TMP_OUT)/ bootstrap + +# Paths to search for a kernel to generate vmlinux.h from. +VMLINUX_BTF_ELF_PATHS ?= $(if $(O),$(O)/vmlinux) \ + $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \ + ../../vmlinux \ + /boot/vmlinux-$(shell uname -r) + +# Paths to BTF information. +VMLINUX_BTF_BTF_PATHS ?= /sys/kernel/btf/vmlinux + +# Filter out kernels that don't exist or without a BTF section. +VMLINUX_BTF_ELF_ABSPATHS ?= $(abspath $(wildcard $(VMLINUX_BTF_ELF_PATHS))) +VMLINUX_BTF_PATHS ?= $(shell for file in $(VMLINUX_BTF_ELF_ABSPATHS); \ + do \ + if [ -f $$file ] && ($(READELF) -S "$$file" | grep -q .BTF); \ + then \ + echo "$$file"; \ + fi; \ + done) \ + $(wildcard $(VMLINUX_BTF_BTF_PATHS)) + +# Select the first as the source of vmlinux.h. +VMLINUX_BTF ?= $(firstword $(VMLINUX_BTF_PATHS)) + +ifeq ($(VMLINUX_H_FILE),) + ifeq ($(VMLINUX_BTF),) + $(error Missing bpftool input for generating vmlinux.h) + endif +endif + +$(VMLINUX_H): $(VMLINUX_BTF) $(BPFTOOL) $(VMLINUX_H_FILE) + $(call rule_mkdir) +ifeq ($(VMLINUX_H_FILE),) + $(QUIET_GEN)$(BPFTOOL) btf dump file $< format c > $@ +else + $(Q)cp "$(VMLINUX_H_FILE)" $@ +endif + # Consolidated Pattern rule for $(dir)/bpf_skel/ $(SKEL_TMP_OUT)/%.bpf.o: $(srctree)/tools/perf/$(dir)/bpf_skel/%.bpf.c $(LIBBPF) $(VMLINUX_H) $(OUTPUT)PERF-VERSION-FILE util/bpf_skel/perf_version.h $(call rule_mkdir) @@ -51,4 +92,10 @@ $(SKEL_OUT)/%.skel.h: $(SKEL_TMP_OUT)/%.bpf.o $(BPFTOOL) $(Q)$(BPFTOOL) gen skeleton $< > $@ .PRECIOUS: $(SKEL_TMP_OUT)/%.bpf.o + endif # CONFIG_PERF_BPF_SKEL + +clean: + $(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TOOL_TMP_OUT) $(OUTPUT)bench/bpf_skel/.tmp $(SKEL_TOOL_OUT)/*.skel.h $(OUTPUT)bench/bpf_skel/*.skel.h $(SKEL_TOOL_OUT)/vmlinux.h + +.PHONY: clean From 32969ef6e3e1979a903a53a2287dffa6fdcb74d4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:31 -0700 Subject: [PATCH 082/343] perf build: Pre-generate BPF skeleton tooling during umbrella prepare phase Currently, BPF skeleton generation rules (bpf_skel.mak) are evaluated as part of util/Build. However, because LIBPERF_UTIL_IN explicitly depends on the top-level static libbpf archive, Make completely blocked the execution of bpftool bootstrap and skeleton generation until libbpf finished compiling midway through the build. Since bpftool bootstrap compiles its own independent copy of libbpf.a, it does not depend on the top-level libbpf target. Decouple early skeleton tooling generation by attaching bpf-skel-prepare to the umbrella prepare target, exporting CONFIG_PERF_BPF_SKEL to ensure accurate feature propagation. This allows Make to compile bpftool and dump vmlinux.h in the background at build startup, eliminating the initial sub-make startup bottleneck before BPF object compilation while keeping 100% of tooling rules perfectly encapsulated in bpf_skel.mak. Provide an empty fallback target to ensure builds succeed when BPF skeletons are disabled. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 8 ++++++-- tools/perf/bpf_skel.mak | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index ec0e91bedce1..876065a02de6 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -275,7 +275,7 @@ ifeq ($(PYLINT),1) endif export srctree OUTPUT RM CC CXX RUSTC CLANG LD AR CFLAGS CXXFLAGS RUST_FLAGS V BISON FLEX AWK LIBBPF READELF -export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK MYPY PYLINT +export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK MYPY PYLINT CONFIG_PERF_BPF_SKEL include $(srctree)/tools/build/Makefile.include @@ -629,8 +629,12 @@ endif __build-dir = $(subst $(OUTPUT),,$(dir $@)) build-dir = $(or $(__build-dir),.) +bpf-skel-prepare: + $(Q)$(MAKE) -f bpf_skel.mak bpf-skel-prepare + prepare: $(OUTPUT)PERF-VERSION-FILE \ arm64-sysreg-defs \ + bpf-skel-prepare \ $(LIBAPI) \ $(LIBPERF) \ $(LIBSUBCMD) \ @@ -971,7 +975,7 @@ FORCE: .PHONY: all install clean config-clean strip install-gtk .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell -.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope FORCE prepare +.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope FORCE prepare bpf-skel-prepare .PHONY: python_perf_target endif # force_fixdep diff --git a/tools/perf/bpf_skel.mak b/tools/perf/bpf_skel.mak index 30924ad140c4..7704e7e635d8 100644 --- a/tools/perf/bpf_skel.mak +++ b/tools/perf/bpf_skel.mak @@ -15,6 +15,10 @@ ifeq ($(CONFIG_PERF_BPF_SKEL),y) BPFTOOL := $(SKEL_TOOL_TMP_OUT)/bootstrap/bpftool VMLINUX_H := $(SKEL_TOOL_OUT)/vmlinux.h +.PHONY: bpf-skel-prepare +bpf-skel-prepare: $(BPFTOOL) $(VMLINUX_H) + @: + define get_sys_includes $(shell $(1) $(2) -v -E - &1 \ | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \ @@ -93,6 +97,10 @@ $(SKEL_OUT)/%.skel.h: $(SKEL_TMP_OUT)/%.bpf.o $(BPFTOOL) .PRECIOUS: $(SKEL_TMP_OUT)/%.bpf.o +else # CONFIG_PERF_BPF_SKEL +.PHONY: bpf-skel-prepare +bpf-skel-prepare: + @: endif # CONFIG_PERF_BPF_SKEL clean: From 96e808e5671dc6a72a392dd7696bbad92b3171f8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:32 -0700 Subject: [PATCH 083/343] perf build: Move libsymbol dependency out of prepare step The prepare step is a large serialization point before parallel sub-makes build the perf tool. The libsymbol headers are used in the bench and util libraries. Move the libsymbol dependency out of the prepare step and into the dependencies for those targets to avoid it being a source of serialization in the prepare step. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 876065a02de6..96a68723109f 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -558,7 +558,7 @@ $(LIBPMU_EVENTS): $(LIBPMU_EVENTS_IN) # The $(LIBPERF_UTIL) dependency is to ensure bpftool and vmlinux.h # aren't racily built for bench/bpf_skel/bench_uprobe.bpf.c -$(LIBPERF_BENCH_IN): FORCE prepare | $(LIBPERF_UTIL) +$(LIBPERF_BENCH_IN): FORCE prepare $(LIBSYMBOL) | $(LIBPERF_UTIL) $(Q)$(MAKE) $(build)=perf-bench $(LIBPERF_BENCH): $(LIBPERF_BENCH_IN) @@ -576,7 +576,7 @@ $(LIBPERF_UI_IN): FORCE prepare $(LIBPERF_UI): $(LIBPERF_UI_IN) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $< -$(LIBPERF_UTIL_IN): FORCE prepare +$(LIBPERF_UTIL_IN): FORCE prepare $(LIBSYMBOL) $(Q)$(MAKE) $(build)=perf-util $(LIBPERF_UTIL): $(LIBPERF_UTIL_IN) @@ -637,8 +637,7 @@ prepare: $(OUTPUT)PERF-VERSION-FILE \ bpf-skel-prepare \ $(LIBAPI) \ $(LIBPERF) \ - $(LIBSUBCMD) \ - $(LIBSYMBOL) + $(LIBSUBCMD) ifdef LIBBPF_STATIC prepare: $(LIBBPF) From 29331b2edb861e1a7e2fadc8d06403c460eb6064 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:33 -0700 Subject: [PATCH 084/343] perf build: Remove redundant libbpf feature check for static builds By default, the perf tool compiles and statically links against its own internal copy of libbpf (tools/lib/bpf/libbpf.a), setting LIBBPF_STATIC=1. Despite this static linkage, Makefile.config unconditionally executed $(call feature_check,libbpf), which forced a synchronous sub-make fork during AST parsing to detect dynamic system libbpf libraries. As noted in the internal Makefile comments, this check was executed purely so that running `make VF=1` would display the detection status of system libbpf. During standard builds without LIBBPF_DYNAMIC=1, the detection result was entirely ignored. Wrap the libbpf feature check inside LIBBPF_DYNAMIC=1 so Make avoids the redundant sub-make fork overhead during standard static builds. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 8437c3f72125..26de7528d6ce 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -575,10 +575,8 @@ ifndef NO_LIBELF ifndef NO_LIBBPF ifeq ($(feature-bpf), 1) - # detecting libbpf without LIBBPF_DYNAMIC, so make VF=1 shows libbpf detection status - $(call feature_check,libbpf) - ifdef LIBBPF_DYNAMIC + $(call feature_check,libbpf) ifeq ($(feature-libbpf), 1) EXTLIBS += -lbpf CFLAGS += -DHAVE_LIBBPF_SUPPORT From bb922345eec1fdef5b094bbb739caa136c8e8213 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:34 -0700 Subject: [PATCH 085/343] perf pmu-events: Split big_c_string storage into standalone compilation unit Currently, jevents.py emits both the massive 2.8 MB big_c_string literal and tens of thousands of compact_pmu_event struct arrays into a single pmu-events.c compilation unit. Compiling this giant file takes ~2.2 seconds on a single CPU core during Kbuild startup. Refactor jevents.py to emit big_c_string into a dedicated pmu-events-string.c compilation unit. This allows Kbuild to compile pmu-events.o and pmu-events-string.o simultaneously in parallel across two separate CPU cores, preserving 100% string deduplication and zero dynamic ELF relocations while cutting C compilation latency in half. Add pmu-events-string.c to tools/perf/.gitignore to ensure in-tree Kbuild runs do not leave untracked generated files in the working directory. To guarantee 100% backward compatibility with GNU Make 4.0+ (avoiding the Make 4.3+ grouped target &: syntax which causes older Make versions like 4.2.1 to spawn multiple concurrent jevents.py processes during parallel builds), implement a robust dependency chaining pattern: $(PMU_EVENTS_C): $(JEVENTS_DEPS) $(PMU_EVENTS_STRING_C): $(PMU_EVENTS_C) @: This ensures jevents.py is invoked exactly once. If jevents.py aborts early, Make's .DELETE_ON_ERROR: purges pmu-events.c, guaranteeing that subsequent Make invocations correctly re-execute the script and overwrite pmu-events-string.c. In jevents.py, explicitly close output_file first and output_string_file second at the tail of main() to guarantee that pmu-events-string.c receives a filesystem timestamp greater than or equal to pmu-events.c, completely avoiding redundant incremental rebuilds. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/.gitignore | 1 + tools/perf/Makefile.perf | 4 ++-- tools/perf/pmu-events/Build | 16 +++++++++++++++- tools/perf/pmu-events/jevents.py | 23 +++++++++++++++++++---- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index 0f9451a6e39c..3b968c5158b8 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore @@ -38,6 +38,7 @@ arch/*/include/generated/ trace/beauty/generated/ pmu-events/arch/common/common/legacy-cache.json pmu-events/pmu-events.c +pmu-events/pmu-events-string.c pmu-events/jevents pmu-events/metric_test.log pmu-events/empty-pmu-events.log diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 96a68723109f..b8a81c9749a8 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -925,7 +925,7 @@ bpf-skel-clean: pmu-events-clean: ifeq ($(OUTPUT),) $(call QUIET_CLEAN, pmu-events) $(RM) \ - pmu-events/pmu-events.c \ + pmu-events/pmu-events*.c \ pmu-events/metric_test.log \ pmu-events/test-empty-pmu-events.c \ pmu-events/empty-pmu-events.log @@ -933,7 +933,7 @@ ifeq ($(OUTPUT),) -name 'extra-metricgroups.json' -delete else # When an OUTPUT directory is present, clean up the copied pmu-events/arch directory. $(call QUIET_CLEAN, pmu-events) $(RM) -r $(OUTPUT)pmu-events/arch \ - $(OUTPUT)pmu-events/pmu-events.c \ + $(OUTPUT)pmu-events/pmu-events*.c \ $(OUTPUT)pmu-events/metric_test.log \ $(OUTPUT)pmu-events/test-empty-pmu-events.c \ $(OUTPUT)pmu-events/empty-pmu-events.log diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build index dc1df2d57ddc..95172a2a851f 100644 --- a/tools/perf/pmu-events/Build +++ b/tools/perf/pmu-events/Build @@ -1,7 +1,12 @@ EMPTY_PMU_EVENTS_C = pmu-events/empty-pmu-events.c # pmu-events.c will be generated by jevents.py or copied from EMPTY_PMU_EVENTS_C PMU_EVENTS_C = $(OUTPUT)pmu-events/pmu-events.c +PMU_EVENTS_STRING_C = $(OUTPUT)pmu-events/pmu-events-string.c + pmu-events-y += pmu-events.o +ifneq ($(NO_JEVENTS),1) +pmu-events-y += pmu-events-string.o +endif # pmu-events.c file is generated in the OUTPUT directory so it needs a # separate rule to depend on it properly @@ -9,6 +14,10 @@ $(OUTPUT)pmu-events/pmu-events.o: $(PMU_EVENTS_C) $(call rule_mkdir) $(call if_changed_dep,cc_o_c) +$(OUTPUT)pmu-events/pmu-events-string.o: $(PMU_EVENTS_STRING_C) + $(call rule_mkdir) + $(call if_changed_dep,cc_o_c) + # Message for $(call echo-cmd,cp), possibly remove the src file from # the destination to save space in the build log. quiet_cmd_cp = COPY $(patsubst %$<,%,$@) <- $< @@ -118,6 +127,7 @@ CUR_OUT_JSON := $(shell [ -d $(OUT_DIR) ] && find $(OUT_DIR) -type f) # Things in the OUTPUT directory but shouldn't be there as computed by # OUT_JSON and GEN_JSON. + ORPHAN_FILES := $(filter-out $(OUT_JSON) $(GEN_JSON),$(CUR_OUT_JSON)) # Message for $(call echo-cmd,mkd). There is already a mkdir message @@ -224,6 +234,10 @@ endif # and inputs are dependencies. $(PMU_EVENTS_C): $(JEVENTS_DEPS) $(call rule_mkdir) - $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) $(OUT_DIR) $@ + $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) \ + $(OUT_DIR) $(PMU_EVENTS_C) $(PMU_EVENTS_STRING_C) + +$(PMU_EVENTS_STRING_C): $(PMU_EVENTS_C) + @: endif # ifeq ($(NO_JEVENTS),1) diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 3a1bcdcdc685..7344940e776a 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -1422,6 +1422,8 @@ such as "arm/cortex-a34".''', ) ap.add_argument( 'output_file', type=argparse.FileType('w', encoding='utf-8'), nargs='?', default=sys.stdout) + ap.add_argument( + 'output_string_file', type=argparse.FileType('w', encoding='utf-8'), nargs='?', default=None) _args = ap.parse_args() _args.output_file.write(f""" @@ -1463,10 +1465,20 @@ struct pmu_table_entry { ftw(arch_path, [], preprocess_one_file) _bcs.compute() - _args.output_file.write('static const char *const big_c_string =\n') - for s in _bcs.big_string: - _args.output_file.write(s) - _args.output_file.write(';\n\n') + if not _args.output_string_file: + _args.output_file.write('static const char *const big_c_string =\n') + for s in _bcs.big_string: + _args.output_file.write(s) + _args.output_file.write(';\n\n') + else: + _args.output_string_file.write('/* SPDX-License-Identifier: GPL-2.0 */\n') + _args.output_string_file.write('/* Autogenerated by jevents.py */\n') + _args.output_string_file.write('extern const char big_c_string[];\n') + _args.output_string_file.write('const char big_c_string[] =\n') + for s in _bcs.big_string: + _args.output_string_file.write(s) + _args.output_string_file.write(';\n') + _args.output_file.write('extern const char big_c_string[];\n\n') for arch in archs: arch_path = f'{_args.starting_dir}/{arch}' ftw(arch_path, [], process_one_file) @@ -1476,6 +1488,9 @@ struct pmu_table_entry { print_mapping_table(archs) print_system_mapping_table() print_metricgroups() + _args.output_file.close() + if _args.output_string_file: + _args.output_string_file.close() if __name__ == '__main__': main() From 90a815a22abfd3d90436c021a5e8f7b8207df2be Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:37 -0700 Subject: [PATCH 086/343] perf pmu-events: Convert recursive shell assignments and macros to Make built-ins In pmu-events/Build, ZENS, ARMS, and INTELS were assigned using recursive assignment (=), and model_name/vendor_name were evaluated using shell macros (echo ... | sed ...). Because these variables were expanded inside the COPY_RULE dependency evaluation loop across hundreds of PMU JSON files and inside every metric generation recipe, Kbuild continuously re-executed 'ls', 'grep', and 'sed' shell forks thousands of times during AST parsing and execution. Convert ZENS, ARMS, and INTELS to simply expanded variables (:=) and replace model_name/vendor_name with pure GNU Make string functions. This guarantees Make executes directory probing shell forks exactly once when the Build file is parsed and evaluates path macros purely in memory, completely eliminating over 7,800 redundant sub-processes during build startup. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/Build | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build index 95172a2a851f..372773b998e4 100644 --- a/tools/perf/pmu-events/Build +++ b/tools/perf/pmu-events/Build @@ -56,12 +56,12 @@ $(LEGACY_CACHE_JSON): $(LEGACY_CACHE_PY) # Python to generate architectural metrics GEN_METRIC_DEPS := pmu-events/metric.py pmu-events/common_metrics.py # Functions to extract the model from an extra-metrics.json or extra-metricgroups.json path. -model_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/extra-metric.*\.json@\1@') -vendor_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/[^/]*/extra-metric.*\.json@\1@') +model_name = $(notdir $(patsubst %/,%,$(dir $(1)))) +vendor_name = $(notdir $(patsubst %/,%,$(dir $(patsubst %/,%,$(dir $(1)))))) ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all)) # Generate AMD Json -ZENS = $(shell ls -d pmu-events/arch/x86/amdzen*) +ZENS := $(shell ls -d pmu-events/arch/x86/amdzen*) ZEN_METRICS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metrics.json) ZEN_METRICGROUPS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metricgroups.json) GEN_JSON += $(ZEN_METRICS) $(ZEN_METRICGROUPS) @@ -78,7 +78,7 @@ endif ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),arm64 all)) # Generate ARM Json -ARMS = $(shell ls -d pmu-events/arch/arm64/arm/*|grep -v cmn) +ARMS := $(shell ls -d pmu-events/arch/arm64/arm/*|grep -v cmn) ARM_METRICS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metrics.json) ARM_METRICGROUPS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metricgroups.json) GEN_JSON += $(ARM_METRICS) $(ARM_METRICGROUPS) @@ -95,7 +95,7 @@ endif ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all)) # Generate Intel Json -INTELS = $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v mapfile.csv) +INTELS := $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v mapfile.csv) INTEL_METRICS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metrics.json) INTEL_METRICGROUPS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metricgroups.json) GEN_JSON += $(INTEL_METRICS) $(INTEL_METRICGROUPS) From 98e68cb7782347a07ab1a94f8f5b629c59df1a73 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:38 -0700 Subject: [PATCH 087/343] perf build: Convert llvm-config shell queries to simply expanded variables In Makefile.config, CFLAGS, CXXFLAGS, LIBLLVM, and EXTLIBS were assigned using recursive expansion or appended with raw $(shell $(LLVM_CONFIG) ...) calls. Because these variables were expanded during dependency evaluation across every single object file compilation rule, Kbuild continuously re-executed llvm-config forks nearly 200 times during incremental builds. Convert llvm-config shell queries to simply expanded variables (:=) to ensure Make evaluates LLVM compiler flags and library paths exactly once when Makefile.config is parsed, eliminating ~185 redundant sub-processes during build startup. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 26de7528d6ce..b56fa8419f7d 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -925,11 +925,14 @@ ifndef NO_LIBLLVM $(call feature_check,llvm-perf) ifeq ($(feature-llvm-perf), 1) CFLAGS += -DHAVE_LIBLLVM_SUPPORT - CFLAGS += $(shell $(LLVM_CONFIG) --cflags) - CXXFLAGS += -DHAVE_LIBLLVM_SUPPORT - CXXFLAGS += $(shell $(LLVM_CONFIG) --cxxflags) - LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) --system-libs) - EXTLIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM) + LLVM_CFLAGS := $(shell $(LLVM_CONFIG) --cflags 2>/dev/null) + LLVM_CXXFLAGS := $(shell $(LLVM_CONFIG) --cxxflags 2>/dev/null) + LLVM_LIBLLVM := $(shell $(LLVM_CONFIG) --libs all 2>/dev/null) $(shell $(LLVM_CONFIG) --system-libs 2>/dev/null) + LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null) + CFLAGS += $(LLVM_CFLAGS) + CXXFLAGS += -DHAVE_LIBLLVM_SUPPORT $(LLVM_CXXFLAGS) + LIBLLVM := $(LLVM_LIBLLVM) + EXTLIBS += -L$(LLVM_LIBDIR) $(LIBLLVM) EXTLIBS += -lstdc++ $(call detected,CONFIG_LIBLLVM) else From 9f116f4b811b5846808e27507a3aa2824819edeb Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 17 May 2026 23:29:03 -0700 Subject: [PATCH 088/343] perf tests: Add test for uncore event sorting Add a test for uncore event sorting matching multiple PMUs. Uncore PMUs may have a common prefix, like the PMUs uncore_imc_free_running_0 and uncore_imc_free_running_1 have a prefix of uncore_imc_free_running. Parsing an event group like "{data_read,data_write}" for those PMUs should result with two groups: "{uncore_imc_free_running_0/data_read/,uncore_imc_free_running_0/data_write/}, {uncore_imc_free_running_1/data_read/,uncore_imc_free_running_1/data_write/}" which means the evsels need resorting as when initially parsed the evsels are ordered with mixed PMUs: "{uncore_imc_free_running_0/data_read/,uncore_imc_free_running_1/data_read/, uncore_imc_free_running_0/data_write/,uncore_imc_free_running_1/data_write/}". Signed-off-by: Ian Rogers Tested-by: Zide Chen Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Collin Funk Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: German Gomez Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 1 + tools/perf/tests/tests.h | 1 + tools/perf/tests/uncore-event-sorting.c | 176 ++++++++++++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 tools/perf/tests/uncore-event-sorting.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index c2a67ce45941..66944a4f4968 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -3,6 +3,7 @@ perf-test-y += builtin-test.o perf-test-y += tests-scripts.o perf-test-y += parse-events.o +perf-test-y += uncore-event-sorting.o perf-test-y += dso-data.o perf-test-y += vmlinux-kallsyms.o perf-test-y += openat-syscall.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 06507066213b..f2c135891477 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -71,6 +71,7 @@ static struct test_suite *generic_tests[] = { &suite__basic_mmap, &suite__mem, &suite__parse_events, + &suite__uncore_event_sorting, &suite__expr, &suite__PERF_RECORD, &suite__pmu, diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index f5f1238d1f7f..ee00518bf36f 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -177,6 +177,7 @@ DECLARE_SUITE(sigtrap); DECLARE_SUITE(event_groups); DECLARE_SUITE(symbols); DECLARE_SUITE(util); +DECLARE_SUITE(uncore_event_sorting); DECLARE_SUITE(subcmd_help); DECLARE_SUITE(kallsyms_split); diff --git a/tools/perf/tests/uncore-event-sorting.c b/tools/perf/tests/uncore-event-sorting.c new file mode 100644 index 000000000000..7d2fc304e21f --- /dev/null +++ b/tools/perf/tests/uncore-event-sorting.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +#include + +#include "debug.h" +#include "evlist.h" +#include "parse-events.h" +#include "pmu.h" +#include "pmus.h" +#include "tests.h" + +struct match_state { + char *event1; + char *event2; +}; + +static char *clean_event_name(struct pmu_event_info *info) +{ + const char *name = info->name; + const char *pmu_name = info->pmu->name; + size_t pmu_len = strlen(pmu_name); + char *res; + size_t len; + + if (!strncmp(name, pmu_name, pmu_len) && name[pmu_len] == '/') + name += pmu_len + 1; + + res = strdup(name); + if (!res) + return NULL; + + len = strlen(res); + if (len > 0 && res[len - 1] == '/') + res[len - 1] = '\0'; + + return res; +} + +static int event_cb(void *state, struct pmu_event_info *info) +{ + struct match_state *m = state; + char *clean_name; + + if (m->event1 && m->event2) + return 1; + + clean_name = clean_event_name(info); + if (!clean_name) + return 0; + + if (!m->event1) { + m->event1 = clean_name; + } else { + if (strcmp(m->event1, clean_name)) { + m->event2 = clean_name; + return 1; + } + free(clean_name); + } + return 0; +} + +#define CHECK_COND(cond, text) \ +do { \ + if (!(cond)) { \ + pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ + ret = TEST_FAIL; \ + goto out_err; \ + } \ +} while (0) + +#define CHECK_EQUAL(val, expected, text) \ +do { \ + if ((val) != (expected)) { \ + pr_debug("FAILED %s:%d %s (%d != %d)\n", \ + __FILE__, __LINE__, text, (val), (expected)); \ + ret = TEST_FAIL; \ + goto out_err; \ + } \ +} while (0) + +static int test__uncore_event_sorting(struct test_suite *test __maybe_unused, + int subtest __maybe_unused) +{ + struct evlist *evlist = NULL; + struct parse_events_error err; + struct evsel *evsel; + struct perf_pmu *pmu = NULL; + char *pmu_prefix = NULL; + struct match_state m = { NULL, NULL }; + char buf[1024]; + int ret; + + parse_events_error__init(&err); + + while ((pmu = perf_pmus__scan(pmu)) != NULL) { + size_t len; + struct perf_pmu *sibling; + + if (pmu->is_core) + continue; + + len = pmu_name_len_no_suffix(pmu->name); + if (len == strlen(pmu->name)) + continue; + + sibling = pmu; + while ((sibling = perf_pmus__scan(sibling)) != NULL) { + if (sibling->is_core) + continue; + if (pmu_name_len_no_suffix(sibling->name) == len && + !strncmp(pmu->name, sibling->name, len)) + break; + } + + if (!sibling) + continue; + + m.event1 = m.event2 = NULL; + perf_pmu__for_each_event(pmu, false, &m, event_cb); + + if (m.event1 && m.event2) { + pmu_prefix = strndup(pmu->name, len); + break; + } + zfree(&m.event1); + } + + if (!pmu_prefix) { + pr_debug("No suitable uncore PMU found\n"); + ret = TEST_SKIP; + goto out_err; + } + + evlist = evlist__new(); + if (!evlist) { + ret = TEST_FAIL; + goto out_err; + } + + snprintf(buf, sizeof(buf), "{%s/%s/,%s/%s/}", pmu_prefix, m.event1, pmu_prefix, m.event2); + pr_debug("Parsing: %s\n", buf); + + ret = parse_events(evlist, buf, &err); + if (ret) { + pr_debug("parse_events failed\n"); + ret = TEST_FAIL; + goto out_err; + } + + CHECK_COND(evlist->core.nr_entries >= 4, "Number of events is >= 4"); + CHECK_EQUAL(evlist->core.nr_entries % 2, 0, "Number of events is a multiple of 2"); + + evlist__for_each_entry(evlist, evsel) { + struct evsel *next; + + if (!evsel__is_group_leader(evsel)) + continue; + + next = evsel__next(evsel); + CHECK_EQUAL(evsel->core.nr_members, 2, "Group size is 2"); + CHECK_COND(evsel->pmu == next->pmu, "PMU match"); + CHECK_COND(strstr(evsel__name(evsel), m.event1) != NULL, "First event name"); + CHECK_COND(strstr(evsel__name(next), m.event2) != NULL, "Second event name"); + } + ret = TEST_OK; + +out_err: + evlist__delete(evlist); + parse_events_error__exit(&err); + zfree(&pmu_prefix); + zfree(&m.event1); + zfree(&m.event2); + return ret; +} + +DEFINE_SUITE("Uncore event sorting", uncore_event_sorting); From b439c20b2fe1cfed2210e50c06006845ae424c48 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 17 May 2026 23:29:04 -0700 Subject: [PATCH 089/343] perf arch x86 tests: Add test for topdown event sorting Add a test to capture the comment in tools/perf/arch/x86/util/evlist.c. Test that slots and topdown-retiring get appropriately sorted with respect to instructions when they're all specified together. When the PMU requires topdown event grouping (indicated by the pressence of the slots event) metric events should be after slots, which should be the group leader. Add a related test that when the slots event isn't given it is injected into the appropriate group. Signed-off-by: Ian Rogers Tested-by: Zide Chen Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Collin Funk Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: German Gomez Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/topdown.c | 166 +++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/tools/perf/arch/x86/tests/topdown.c b/tools/perf/arch/x86/tests/topdown.c index 3ee4e5e71be3..221f2c4bbb61 100644 --- a/tools/perf/arch/x86/tests/topdown.c +++ b/tools/perf/arch/x86/tests/topdown.c @@ -75,4 +75,168 @@ static int test__x86_topdown(struct test_suite *test __maybe_unused, int subtest return ret; } -DEFINE_SUITE("x86 topdown", x86_topdown); +#define CHECK_COND(cond, text) \ +do { \ + if (!(cond)) { \ + pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ + ret = TEST_FAIL; \ + goto out_err; \ + } \ +} while (0) + +#define CHECK_EQUAL(val, expected, text) \ +do { \ + if ((val) != (expected)) { \ + pr_debug("FAILED %s:%d %s (%d != %d)\n", \ + __FILE__, __LINE__, text, (val), (expected)); \ + ret = TEST_FAIL; \ + goto out_err; \ + } \ +} while (0) + +static int test_sort(const char *str, int expected_slots_group_size, + int expected_instructions_group_size) +{ + struct evlist *evlist = NULL; + struct parse_events_error err; + struct evsel *evsel; + int ret = TEST_FAIL; + bool slots_seen = false; + + parse_events_error__init(&err); + + evlist = evlist__new(); + if (!evlist) + goto out_err; + + if (parse_events(evlist, str, &err)) { + pr_debug("parse_events failed for %s\n", str); + goto out_err; + } + + evlist__for_each_entry(evlist, evsel) { + if (!evsel__is_group_leader(evsel)) + continue; + + if (strstr(evsel__name(evsel), "slots")) { + /* + * Slots as a leader means the PMU is for a perf metric + * group as the slots event isn't present when not. + */ + slots_seen = true; + CHECK_EQUAL(evsel->core.nr_members, expected_slots_group_size, + "slots group size"); + if (expected_slots_group_size == 3) { + struct evsel *next = evsel__next(evsel); + struct evsel *next2 = evsel__next(next); + + CHECK_COND(strstr(evsel__name(next), "instructions") != NULL, + "slots second event is instructions"); + CHECK_COND(strstr(evsel__name(next2), "topdown-retiring") != NULL, + "slots third event is topdown-retiring"); + } else if (expected_slots_group_size == 2) { + struct evsel *next = evsel__next(evsel); + + CHECK_COND(strstr(evsel__name(next), "topdown-retiring") != NULL, + "slots second event is topdown-retiring"); + } + } else if (strstr(evsel__name(evsel), "instructions")) { + CHECK_EQUAL(evsel->core.nr_members, expected_instructions_group_size, + "instructions group size"); + if (expected_instructions_group_size == 2) { + /* + * On Intel hybrid CPUs (e.g., Alder Lake/ + * Raptor Lake), E-cores (cpu_atom) do not + * support/enforce the slots event. When + * parsing event groups containing slots + * across all PMUs, slots is automatically + * filtered out from cpu_atom, leaving + * {cpu_atom/instructions/, + * cpu_atom/topdown-retiring/}. On cpu_atom, + * instructions correctly leads this group of + * 2 without slots reordering. + */ + struct evsel *next = evsel__next(evsel); + + CHECK_COND(strstr(evsel__name(next), "topdown-retiring") != NULL, + "instructions second event is topdown-retiring"); + } + } else if (strstr(evsel__name(evsel), "topdown-retiring")) { + /* + * A perf metric event where the PMU doesn't require + * slots as a leader. + */ + CHECK_EQUAL(evsel->core.nr_members, 1, "topdown-retiring group size"); + } else if (strstr(evsel__name(evsel), "cycles")) { + CHECK_EQUAL(evsel->core.nr_members, 1, "cycles group size"); + } + } + CHECK_COND(slots_seen, "slots seen"); + ret = TEST_OK; +out_err: + evlist__delete(evlist); + parse_events_error__exit(&err); + return ret; +} + +static int test__x86_topdown_sorting(struct test_suite *test __maybe_unused, + int subtest __maybe_unused) +{ + int ret; + + if (!topdown_sys_has_perf_metrics()) + return TEST_OK; + + ret = test_sort("{instructions,topdown-retiring,slots}", 3, 2); + TEST_ASSERT_EQUAL("all events in a group", ret, TEST_OK); + ret = test_sort("instructions,topdown-retiring,slots", 2, 1); + TEST_ASSERT_EQUAL("all events not in a group", ret, TEST_OK); + ret = test_sort("{instructions,slots},topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("slots event in a group but topdown metrics events outside the group", + ret, TEST_OK); + ret = test_sort("{instructions,slots},{topdown-retiring}", 2, 1); + TEST_ASSERT_EQUAL("slots event and topdown metrics events in two groups", + ret, TEST_OK); + ret = test_sort("{instructions,slots},cycles,topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("slots event and metrics event are not in a group and not adjacent", + ret, TEST_OK); + + return TEST_OK; +} + +static int test__x86_topdown_slots_injection(struct test_suite *test __maybe_unused, + int subtest __maybe_unused) +{ + int ret; + + if (!topdown_sys_has_perf_metrics()) + return TEST_OK; + + ret = test_sort("{instructions,topdown-retiring}", 3, 2); + TEST_ASSERT_EQUAL("all events in a group", ret, TEST_OK); + ret = test_sort("instructions,topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("all events not in a group", ret, TEST_OK); + ret = test_sort("{instructions},topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("event in a group but topdown metrics events outside the group", + ret, TEST_OK); + ret = test_sort("{instructions},{topdown-retiring}", 2, 1); + TEST_ASSERT_EQUAL("event and topdown metrics events in two groups", + ret, TEST_OK); + ret = test_sort("{instructions},cycles,topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("event and metrics event are not in a group and not adjacent", + ret, TEST_OK); + + return TEST_OK; +} + +static struct test_case x86_topdown_tests[] = { + TEST_CASE("topdown events", x86_topdown), + TEST_CASE("topdown sorting", x86_topdown_sorting), + TEST_CASE("topdown slots injection", x86_topdown_slots_injection), + { .name = NULL, } +}; + +struct test_suite suite__x86_topdown = { + .desc = "x86 topdown", + .test_cases = x86_topdown_tests, +}; From 85cc481af5ffa23809b7bb100aa774172369983c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 08:46:36 -0700 Subject: [PATCH 090/343] perf build: Prefix SCRIPTS with output directory to fix continuous rebuilds In Makefile.perf, ALL_PROGRAMS includes SCRIPTS (perf-archive, perf-iostat). However, unlike PROGRAMS and DLFILTERS, SCRIPTS was not prefixed with $(OUTPUT). During out-of-tree builds (or when O= is specified), Make checked for the unprefixed target 'tools/perf/perf-archive'. Since the actual script was installed into $(OUTPUT)perf-archive, Make concluded the target was missing and continuously re-executed the script installation rule on every single incremental build. Prefix SCRIPTS with $(OUTPUT) and update the static pattern rule to ensure Kbuild correctly tracks generated script prerequisites during incremental builds. Reviewed-by: Namhyung Kim Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Albert Ou Cc: Alexandre Chartre Cc: Alexandre Ghiti Cc: Andrii Nakryiko Cc: Ankur Arora Cc: Collin Funk Cc: Costa Shulyupin Cc: Daniel Borkmann Cc: Dapeng Mi Cc: David Sterba Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Eduard Zingerman Cc: Howard Chu Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kumar Kartikeya Dwivedi Cc: Leo Yan Cc: Markus Mayer Cc: Martin KaFai Lau Cc: Nathan Chancellor Cc: Nick Terrell Cc: Palmer Dabbelt Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Quentin Monnet Cc: Ricky Ringler Cc: Song Liu Cc: Swapnil Sapkal Cc: Thomas Falcon Cc: Tomas Glozar Cc: Yonghong Song Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index b8a81c9749a8..fc92d6ceac5b 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -405,7 +405,7 @@ python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT # Use the detected configuration -include $(OUTPUT).config-detected -SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) +SCRIPTS = $(addprefix $(OUTPUT),$(patsubst %.sh,%,$(SCRIPT_SH))) PROGRAMS += $(OUTPUT)perf @@ -592,8 +592,8 @@ $(GTK_IN): FORCE prepare $(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS) $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS) -$(SCRIPTS) : % : %.sh - $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@' +$(SCRIPTS) : $(OUTPUT)% : %.sh + $(QUIET_GEN)$(INSTALL) '$<' '$@' $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE $(Q)$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) From f8d0db39bcc536ef652968c45ca23f8f27f58997 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 21 May 2026 08:35:58 -0700 Subject: [PATCH 091/343] perf build: Fix fsmount.o build A merge conflict between: commit 552636b9317c8a84 ("perf trace: Add beautifier script for fsmount flags") commit 32969ef6e3e1979a ("perf build: Pre-generate BPF skeleton tooling during umbrella prepare phase") Resulted in a missed build dependency in the linux-next merge: commit 61da860eee0798d3 ("Merge branch 'perf-tools-next' of https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git") Fix the build by adding the necessary build dependencies. Signed-off-by: Ian Rogers Cc: Mark Brown Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/trace/beauty/Build | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build index 93cde93461a3..996e63cdf765 100644 --- a/tools/perf/trace/beauty/Build +++ b/tools/perf/trace/beauty/Build @@ -111,6 +111,13 @@ $(fsmount_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsmount_tbls) $(call rule_mkdir) $(Q)$(call echo-cmd,gen)$(SHELL) '$(fsmount_tbls)' $(beauty_uapi_linux_dir) > $@ +fsmount_attr_arrays := $(beauty_outdir)/fsmount_attr_arrays.c +fsmount_attr_tbls := $(srctree)/tools/perf/trace/beauty/fsmount_attr.sh + +$(fsmount_attr_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsmount_attr_tbls) + $(call rule_mkdir) + $(Q)$(call echo-cmd,gen)$(SHELL) '$(fsmount_attr_tbls)' $(beauty_uapi_linux_dir) > $@ + fspick_arrays := $(beauty_outdir)/fspick_arrays.c fspick_tbls := $(srctree)/tools/perf/trace/beauty/fspick.sh @@ -285,7 +292,7 @@ $(OUTPUT)trace/beauty/syscalltbl.o: $(syscall_array) $(OUTPUT)trace/beauty/fsconfig.o: $(fsconfig_arrays) $(OUTPUT)trace/beauty/clone.o: $(clone_flags_array) $(OUTPUT)trace/beauty/fs_at_flags.o: $(fs_at_flags_array) -$(OUTPUT)trace/beauty/fsmount.o: $(fsmount_arrays) +$(OUTPUT)trace/beauty/fsmount.o: $(fsmount_arrays) $(fsmount_attr_arrays) $(OUTPUT)trace/beauty/fspick.o: $(fspick_arrays) $(OUTPUT)trace/beauty/ioctl.o: $(drm_ioctl_array) $(sndrv_pcm_ioctl_array) $(sndrv_ctl_ioctl_array) $(kvm_ioctl_array) $(vhost_virtio_ioctl_array) $(perf_ioctl_array) $(usbdevfs_ioctl_array) $(OUTPUT)trace/beauty/kcmp.o: $(kcmp_type_array) From 7a978c2ac722d527852c0239ecc71108547c7a23 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 13 May 2026 07:49:06 -0700 Subject: [PATCH 092/343] perf stat: Make metric only column line up with header Since some time the metric-only output columns are messed up and do not line up with the header, which makes it hard to read. I haven't bisected it, but presumably it was broken for some time. There were multiple problems: - The dummy pm invocation at the beginning did print a bogus field - The column computation in pm did not agree with the header length - The color escape strings from highlighting confuse printf's field length computation Fix all those. I simplified the column width computation significantly, ignoring EVNAME_LEN, MGROUP_LEN, config->unit_width which don't seem to be useful in the metric only context. It now only uses the actual unit width as well as config->metric_only_len. The result is more code removed than added. Before: % perf stat --topdown -a -I 1000 + time % tma_backend_bound % tma_frontend_bound % tma_bad_speculation % tma_retiring 1.000190386 45.5 40.0 5.3 9.2 2.005185654 45.3 40.1 5.6 9.0 3.009193207 45.4 39.9 5.6 9.1 After: % perf stat --topdown -a -I 1000 + time % tma_backend_bound % tma_frontend_bound % tma_bad_speculation % tma_retiring 1.000810024 46.3 39.7 5.3 8.7 2.004800656 45.8 39.8 5.4 8.9 3.008804783 46.0 39.6 5.4 9.0 Reviewed-by: Ian Rogers Signed-off-by: Andi Kleen Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-display.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 993f4c4b8f44..2b69d238858c 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -580,16 +580,13 @@ static void print_metricgroup_header_std(struct perf_stat_config *config, const char *metricgroup_name) { struct outstate *os = ctx; - int n; if (!metricgroup_name) { __new_line_std(config, os); return; } - n = fprintf(config->output, " %*s", EVNAME_LEN, metricgroup_name); - - fprintf(config->output, "%*s", MGROUP_LEN + config->unit_width + 2 - n, ""); + fprintf(config->output, " %*s", config->metric_only_len, metricgroup_name); } static void print_metric_only(struct perf_stat_config *config, @@ -599,19 +596,20 @@ static void print_metric_only(struct perf_stat_config *config, struct outstate *os = ctx; FILE *out = os->fh; char str[1024]; - unsigned mlen = config->metric_only_len; + unsigned mlen; const char *color = metric_threshold_classify__color(thresh); + int olen; - if (!unit) - unit = ""; - if (mlen < strlen(unit)) - mlen = strlen(unit) + 1; + if (!unit) { + os->first = false; + return; + } - if (color) - mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1; + mlen = max_t(unsigned, strlen(unit), config->metric_only_len); + olen = snprintf(str, sizeof(str), fmt ?: "", val); color_snprintf(str, sizeof(str), color ?: "", fmt ?: "", val); - fprintf(out, "%*s ", mlen, str); + fprintf(out, "%*s%s", max_t(int, mlen - olen, 1), "", str); os->first = false; } From fdec0a81cad5f14a7d3451a49acfa5adc898aa59 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 21 May 2026 00:24:27 -0700 Subject: [PATCH 093/343] perf build: Unconditionally set up libunwind feature build flags A "make feature-dump" build does not specify LIBUNWIND=1 because it is run with the default configuration to detect system-wide capabilities. This sets NO_LIBUNWIND := 1, causing Makefile.config to skip setting LIBUNWIND_LIBS and FEATURE_CHECK_LDFLAGS-libunwind. Consequently, when Makefile.feature is included and attempts to run all feature checks (via FEATURE_TESTS := all), the local feature test test-libunwind.bin compiles without the required architecture-specific library flags (-lunwind-x86_64) and fails to link on x86_64. This results in a corrupted cached BUILD_TEST_FEATURE_DUMP showing feature-libunwind=0 even when the host supports it. Subsequent test builds (like make_libunwind_O in the build-test suite) which reuse the feature dump and specify LIBUNWIND=1 will fail to compile due to a mismatch where CONFIG_LIBUNWIND is set (via remote architecture checks which are self-contained) but HAVE_LIBUNWIND_SUPPORT is disabled, causing compiler errors due to missing maps__e_machine definitions in maps.h. Fix this by unconditionally setting up the libunwind library lists and feature check LDFLAGS in Makefile.config so they are always populated and available to the feature detection engine regardless of whether LIBUNWIND=1 is opted-in for the current run. Fixes: 444508cd7c7b4f05 ("perf build: Be more programmatic when setting up libunwind variables") Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 99 +++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index b56fa8419f7d..c531b9315609 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -79,42 +79,43 @@ ifeq ($(ARCH),s390) CFLAGS += -fPIC endif +# Unconditionally set up the libunwind feature build flags as a +# feature-dump build doesn't specify LIBUNWIND=1. This means that +# dumping the libunwind features will be broken that can impact later +# builds that use the feature dump. +ifeq ($(SRCARCH),arm) + LIBUNWIND_LIBS = -lunwind -lunwind-arm +endif +ifeq ($(SRCARCH),arm64) + LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 +endif +ifeq ($(SRCARCH),loongarch) + LIBUNWIND_LIBS = -lunwind -lunwind-loongarch64 +endif +ifeq ($(ARCH),mips) + LIBUNWIND_LIBS = -lunwind -lunwind-mips +endif +ifeq ($(SRCARCH),powerpc) + LIBUNWIND_LIBS := -lunwind -lunwind-ppc64 +endif +ifeq ($(SRCARCH),riscv) + LIBUNWIND_LIBS := -lunwind -lunwind-riscv +endif +ifeq ($(SRCARCH),s390) + LIBUNWIND_LIBS := -lunwind -lunwind-s390x +endif +ifeq ($(SRCARCH),x86) + ifeq (${IS_64_BIT}, 1) + LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma + else + LIBUNWIND_LIBS = -lunwind-x86 -lunwind -llzma + endif +endif ifneq ($(LIBUNWIND),1) NO_LIBUNWIND := 1 endif - -ifndef NO_LIBUNWIND - ifeq ($(SRCARCH),arm) - LIBUNWIND_LIBS = -lunwind -lunwind-arm - endif - ifeq ($(SRCARCH),arm64) - LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 - endif - ifeq ($(SRCARCH),loongarch) - LIBUNWIND_LIBS = -lunwind -lunwind-loongarch64 - endif - ifeq ($(ARCH),mips) - LIBUNWIND_LIBS = -lunwind -lunwind-mips - endif - ifeq ($(SRCARCH),powerpc) - LIBUNWIND_LIBS := -lunwind -lunwind-ppc64 - endif - ifeq ($(SRCARCH),riscv) - LIBUNWIND_LIBS := -lunwind -lunwind-riscv - endif - ifeq ($(SRCARCH),s390) - LIBUNWIND_LIBS := -lunwind -lunwind-s390x - endif - ifeq ($(SRCARCH),x86) - ifeq (${IS_64_BIT}, 1) - LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma - else - LIBUNWIND_LIBS = -lunwind-x86 -lunwind -llzma - endif - endif - ifeq ($(LIBUNWIND_LIBS),) - NO_LIBUNWIND := 1 - endif +ifeq ($(LIBUNWIND_LIBS),) + NO_LIBUNWIND := 1 endif # @@ -124,24 +125,24 @@ endif # LIBUNWIND_ARCHS:=aarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x86 x86_64 -ifndef NO_LIBUNWIND - FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) - FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) - FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) - FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) +# "Local" (no arch specified) feature test flags. +FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) +FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) +FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) +FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) - ifdef LIBUNWIND_DIR - LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include - LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib +# Add directory into the "remote" (build for a a specific arch) feature tests. +ifdef LIBUNWIND_DIR + LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include + LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib - define libunwind_arch_set_flags - FEATURE_CHECK_CFLAGS-libunwind-$(1) = -I$(LIBUNWIND_DIR)/include - FEATURE_CHECK_LDFLAGS-libunwind-$(1) = -L$(LIBUNWIND_DIR)/lib -lunwind -lunwind-$(1) - endef - $(foreach arch,$(LIBUNWIND_ARCHS), \ - $(eval $(call libunwind_arch_set_flags,$(arch))) \ - ) - endif + define libunwind_arch_set_flags + FEATURE_CHECK_CFLAGS-libunwind-$(1) = -I$(LIBUNWIND_DIR)/include + FEATURE_CHECK_LDFLAGS-libunwind-$(1) = -L$(LIBUNWIND_DIR)/lib -lunwind -lunwind-$(1) + endef + $(foreach arch,$(LIBUNWIND_ARCHS), \ + $(eval $(call libunwind_arch_set_flags,$(arch))) \ + ) endif ifdef CSINCLUDES From ca426c0f6e9cce1db51348cfc8048a42e39cfa9a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 21 May 2026 00:24:28 -0700 Subject: [PATCH 094/343] perf kwork: Fix address sanitizer issues There is a double free in the record array due to how parse_options will mutate the array. Fix by keeping an array that isn't mutated. Ensure kwork_usage is freed on all paths. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kwork.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index 59a54d11f7fa..a4604e152002 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -2258,7 +2258,7 @@ static void setup_event_list(struct perf_kwork *kwork, static int perf_kwork__record(struct perf_kwork *kwork, int argc, const char **argv) { - const char **rec_argv; + const char **rec_argv, **to_free = NULL; unsigned int rec_argc, i, j; struct kwork_class *class; int ret; @@ -2295,16 +2295,27 @@ static int perf_kwork__record(struct perf_kwork *kwork, BUG_ON(i != rec_argc); + /* Save the pointers as the array will be mutated by cmd_record. */ + to_free = calloc(rec_argc + 1, sizeof(char *)); + if (to_free == NULL) { + ret = -ENOMEM; + goto EXIT; + } + pr_debug("record comm: "); - for (j = 0; j < rec_argc; j++) + for (j = 0; j < rec_argc; j++) { pr_debug("%s ", rec_argv[j]); + to_free[j] = rec_argv[j]; + } pr_debug("\n"); ret = cmd_record(i, rec_argv); EXIT: for (i = 0; i < rec_argc; i++) - free((void *)rec_argv[i]); + free((void *)(to_free ? to_free[i] : rec_argv[i])); + + free(to_free); free(rec_argv); return ret; } @@ -2447,6 +2458,7 @@ int cmd_kwork(int argc, const char **argv) const char *const kwork_subcommands[] = { "record", "report", "latency", "timehist", "top", NULL }; + int ret = 0; perf_tool__init(&kwork.tool, /*ordered_events=*/true); kwork.tool.mmap = perf_event__process_mmap; @@ -2463,7 +2475,7 @@ int cmd_kwork(int argc, const char **argv) if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) { setup_event_list(&kwork, kwork_options, kwork_usage); - return perf_kwork__record(&kwork, argc, argv); + ret = perf_kwork__record(&kwork, argc, argv); } else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) { kwork.sort_order = default_report_sort_order; if (argc > 1) { @@ -2474,7 +2486,7 @@ int cmd_kwork(int argc, const char **argv) kwork.report = KWORK_REPORT_RUNTIME; setup_sorting(&kwork, report_options, report_usage); setup_event_list(&kwork, kwork_options, kwork_usage); - return perf_kwork__report(&kwork); + ret = perf_kwork__report(&kwork); } else if (strlen(argv[0]) > 2 && strstarts("latency", argv[0])) { kwork.sort_order = default_latency_sort_order; if (argc > 1) { @@ -2485,7 +2497,7 @@ int cmd_kwork(int argc, const char **argv) kwork.report = KWORK_REPORT_LATENCY; setup_sorting(&kwork, latency_options, latency_usage); setup_event_list(&kwork, kwork_options, kwork_usage); - return perf_kwork__report(&kwork); + ret = perf_kwork__report(&kwork); } else if (strlen(argv[0]) > 2 && strstarts("timehist", argv[0])) { if (argc > 1) { argc = parse_options(argc, argv, timehist_options, timehist_usage, 0); @@ -2494,7 +2506,7 @@ int cmd_kwork(int argc, const char **argv) } kwork.report = KWORK_REPORT_TIMEHIST; setup_event_list(&kwork, kwork_options, kwork_usage); - return perf_kwork__timehist(&kwork); + ret = perf_kwork__timehist(&kwork); } else if (strlen(argv[0]) > 2 && strstarts("top", argv[0])) { kwork.sort_order = default_top_sort_order; if (argc > 1) { @@ -2507,12 +2519,12 @@ int cmd_kwork(int argc, const char **argv) kwork.event_list_str = "sched, irq, softirq"; setup_event_list(&kwork, kwork_options, kwork_usage); setup_sorting(&kwork, top_options, top_usage); - return perf_kwork__top(&kwork); + ret = perf_kwork__top(&kwork); } else usage_with_options(kwork_usage, kwork_options); /* free usage string allocated by parse_options_subcommand */ free((void *)kwork_usage[0]); - return 0; + return ret; } From e898c505b0ee4efb5b2dad9f494c94f74b478ab0 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 21 May 2026 00:24:29 -0700 Subject: [PATCH 095/343] perf kwork: Fix memory management of kwork_work This commit addresses several memory management issues in builtin-kwork.c: 1. Implements a global cleanup function perf_kwork__exit to free all kwork_work and kwork_atom_page objects at the end of the command. 2. Ensures all 'name' fields in struct kwork_work are malloc-ed (or NULL) and properly freed by using strdup and zfree. 3. Fixes memory leaks in top_merge_tasks where kwork_work objects were dropped without being freed. 4. Adds robustness with NULL checks for name fields. 5. Fixes workqueue_work_init to correctly resolve and strdup kernel function names, preventing bad-free errors. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kwork.c | 121 ++++++++++++++++++++++++++++-------- tools/perf/util/bpf_kwork.c | 14 +++-- tools/perf/util/kwork.h | 9 +++ 3 files changed, 115 insertions(+), 29 deletions(-) diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index a4604e152002..f793ea578515 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -323,8 +323,8 @@ static struct kwork_work *work_search(struct rb_root_cached *root, else if (cmp < 0) node = node->rb_right; else { - if (work->name == NULL) - work->name = key->name; + if (work->name == NULL && key->name != NULL) + work->name = strdup(key->name); return work; } } @@ -371,11 +371,54 @@ static struct kwork_work *work_new(struct kwork_work *key) work->id = key->id; work->cpu = key->cpu; - work->name = key->name; + work->name = key->name ? strdup(key->name) : NULL; work->class = key->class; return work; } + +static void work_delete(struct kwork_work *work) +{ + if (work) { + work_exit(work); + free(work); + } +} + +static void kwork_work__free_root(struct rb_root_cached *root) +{ + struct rb_node *next; + struct kwork_work *work; + + while ((next = rb_first_cached(root))) { + work = rb_entry(next, struct kwork_work, node); + rb_erase_cached(next, root); + work_delete(work); + } +} + +static void perf_kwork__exit(struct perf_kwork *kwork) +{ + struct kwork_class *class; + struct kwork_atom_page *page, *tmp_page; + + list_for_each_entry(class, &kwork->class_list, list) { + kwork_work__free_root(&class->work_root); + } + + kwork_work__free_root(&kwork->sorted_work_root); + + list_for_each_entry_safe(page, tmp_page, &kwork->atom_page_list, list) { + list_del_init(&page->list); + free(page); + } + + INIT_LIST_HEAD(&kwork->class_list); + INIT_LIST_HEAD(&kwork->atom_page_list); + INIT_LIST_HEAD(&kwork->sort_list); + INIT_LIST_HEAD(&kwork->cmp_id); +} + static struct kwork_work *work_findnew(struct rb_root_cached *root, struct kwork_work *key, struct list_head *sort_list) @@ -453,25 +496,29 @@ static int work_push_atom(struct perf_kwork *kwork, struct kwork_work **ret_work, bool overwrite) { - struct kwork_atom *atom, *dst_atom, *last_atom; + struct kwork_atom *atom = NULL, *dst_atom, *last_atom; struct kwork_work *work, key; + int ret = 0; BUG_ON(class->work_init == NULL); class->work_init(kwork, class, &key, src_type, sample, machine); atom = atom_new(kwork, sample); - if (atom == NULL) - return -1; + if (atom == NULL) { + ret = -1; + goto out; + } work = work_findnew(&class->work_root, &key, &kwork->cmp_id); if (work == NULL) { atom_free(atom); - return -1; + ret = -1; + goto out; } if (!profile_event_match(kwork, work, sample)) { atom_free(atom); - return 0; + goto out; } if (dst_type < KWORK_TRACE_MAX) { @@ -498,8 +545,9 @@ static int work_push_atom(struct perf_kwork *kwork, } list_add_tail(&atom->list, &work->atom_list[src_type]); - - return 0; +out: + work_exit(&key); + return ret; } static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork, @@ -510,7 +558,7 @@ static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork, struct machine *machine, struct kwork_work **ret_work) { - struct kwork_atom *atom, *src_atom; + struct kwork_atom *atom = NULL, *src_atom; struct kwork_work *work, key; BUG_ON(class->work_init == NULL); @@ -521,15 +569,15 @@ static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork, *ret_work = work; if (work == NULL) - return NULL; + goto out; if (!profile_event_match(kwork, work, sample)) - return NULL; + goto out; atom = list_last_entry_or_null(&work->atom_list[dst_type], struct kwork_atom, list); if (atom != NULL) - return atom; + goto out; src_atom = atom_new(kwork, sample); if (src_atom != NULL) @@ -538,8 +586,9 @@ static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork, if (ret_work != NULL) *ret_work = NULL; } - - return NULL; +out: + work_exit(&key); + return atom; } static struct kwork_work *find_work_by_id(struct rb_root_cached *root, @@ -1002,13 +1051,16 @@ static void irq_work_init(struct perf_kwork *kwork, work->name = NULL; } else { work->id = perf_sample__intval(sample, "irq"); - work->name = perf_sample__strval(sample, "name"); + work->name = strdup(perf_sample__strval(sample, "name") ?: ""); } } static void irq_work_name(struct kwork_work *work, char *buf, int len) { - snprintf(buf, len, "%s:%" PRIu64 "", work->name, work->id); + if (work->name != NULL) + snprintf(buf, len, "%s:%" PRIu64 "", work->name, work->id); + else + snprintf(buf, len, "%" PRIu64 "", work->id); } static struct kwork_class kwork_irq = { @@ -1135,7 +1187,10 @@ static void softirq_work_init(struct perf_kwork *kwork, static void softirq_work_name(struct kwork_work *work, char *buf, int len) { - snprintf(buf, len, "(s)%s:%" PRIu64 "", work->name, work->id); + if (work->name != NULL) + snprintf(buf, len, "(s)%s:%" PRIu64 "", work->name, work->id); + else + snprintf(buf, len, "(s)%" PRIu64 "", work->id); } static struct kwork_class kwork_softirq = { @@ -1220,8 +1275,14 @@ static void workqueue_work_init(struct perf_kwork *kwork __maybe_unused, work->class = class; work->cpu = sample->cpu; work->id = perf_sample__intval(sample, "work"); - work->name = function_addr == 0 ? NULL : - machine__resolve_kernel_addr(machine, &function_addr, &modp); + work->name = NULL; + + if (function_addr != 0) { + const char *name = machine__resolve_kernel_addr(machine, &function_addr, &modp); + + if (name) + work->name = strdup(name); + } } static void workqueue_work_name(struct kwork_work *work, char *buf, int len) @@ -1284,16 +1345,16 @@ static void sched_work_init(struct perf_kwork *kwork __maybe_unused, if (src_type == KWORK_TRACE_EXIT) { work->id = perf_sample__intval(sample, "prev_pid"); - work->name = strdup(perf_sample__strval(sample, "prev_comm")); + work->name = strdup(perf_sample__strval(sample, "prev_comm") ?: ""); } else if (src_type == KWORK_TRACE_ENTRY) { work->id = perf_sample__intval(sample, "next_pid"); - work->name = strdup(perf_sample__strval(sample, "next_comm")); + work->name = strdup(perf_sample__strval(sample, "next_comm") ?: ""); } } static void sched_work_name(struct kwork_work *work, char *buf, int len) { - snprintf(buf, len, "%s", work->name); + snprintf(buf, len, "%s", work->name ?: ""); } static struct kwork_class kwork_sched = { @@ -2100,8 +2161,10 @@ static void top_merge_tasks(struct perf_kwork *kwork) rb_erase_cached(node, &class->work_root); data = rb_entry(node, struct kwork_work, node); - if (!profile_name_match(kwork, data)) + if (!profile_name_match(kwork, data)) { + work_delete(data); continue; + } cpu = data->cpu; merged_work = find_work_by_id(&merged_root, data->id, @@ -2109,11 +2172,17 @@ static void top_merge_tasks(struct perf_kwork *kwork) if (!merged_work) { work_insert(&merged_root, data, &kwork->cmp_id); } else { + if (merged_work->name == NULL && data->name != NULL) + merged_work->name = strdup(data->name); + merged_work->total_runtime += data->total_runtime; merged_work->cpu_usage += data->cpu_usage; } top_calc_load_runtime(kwork, data); + + if (merged_work) + work_delete(data); } work_sort(kwork, class, &merged_root); @@ -2523,6 +2592,8 @@ int cmd_kwork(int argc, const char **argv) } else usage_with_options(kwork_usage, kwork_options); + perf_kwork__exit(&kwork); + /* free usage string allocated by parse_options_subcommand */ free((void *)kwork_usage[0]); diff --git a/tools/perf/util/bpf_kwork.c b/tools/perf/util/bpf_kwork.c index d3a2e548f2b6..2248f462a847 100644 --- a/tools/perf/util/bpf_kwork.c +++ b/tools/perf/util/bpf_kwork.c @@ -273,6 +273,7 @@ static int add_work(struct perf_kwork *kwork, .cpu = key->cpu, }; enum kwork_class_type type = key->type; + int ret = 0; if (!valid_kwork_class_type(type)) { pr_debug("Invalid class type %d to add work\n", type); @@ -287,8 +288,10 @@ static int add_work(struct perf_kwork *kwork, return -1; work = kwork->add_work(kwork, tmp.class, &tmp); - if (work == NULL) - return -1; + if (work == NULL) { + ret = -1; + goto out; + } if (kwork->report == KWORK_REPORT_RUNTIME) { work->nr_atoms = data->nr; @@ -304,13 +307,16 @@ static int add_work(struct perf_kwork *kwork, work->max_latency_end = data->max_time_end; } else { pr_debug("Invalid bpf report type %d\n", kwork->report); - return -1; + ret = -1; + goto out; } kwork->timestart = (u64)ts_start.tv_sec * NSEC_PER_SEC + ts_start.tv_nsec; kwork->timeend = (u64)ts_end.tv_sec * NSEC_PER_SEC + ts_end.tv_nsec; - return 0; +out: + work_exit(&tmp); + return ret; } int perf_kwork__report_read_bpf(struct perf_kwork *kwork) diff --git a/tools/perf/util/kwork.h b/tools/perf/util/kwork.h index abf637d44794..81d39a7f78c8 100644 --- a/tools/perf/util/kwork.h +++ b/tools/perf/util/kwork.h @@ -5,6 +5,7 @@ #include "util/tool.h" #include "util/time-utils.h" +#include #include #include #include @@ -164,6 +165,14 @@ struct kwork_class { char *buf, int len); }; +static inline void work_exit(struct kwork_work *work) +{ + if (work) { + free(work->name); + work->name = NULL; + } +} + struct trace_kwork_handler { int (*raise_event)(struct perf_kwork *kwork, struct kwork_class *class, From 0b97e92393a178765ee1ea01fe5087efece2c425 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 8 May 2026 05:59:57 +0000 Subject: [PATCH 096/343] perf test amd ibs: Fix incorrect kernel version check "AMD IBS sample period" unit test is getting skipped on kernel v7.x. Fix the kernel version >= v6.15 check. Fixes: 21fb366b2f457611 ("perf test amd: Skip amd-ibs-period test on kernel < v6.15") Signed-off-by: Ravi Bangoria Acked-by: Namhyung Kim Cc: Ananth Narayan Cc: Dapeng Mi Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Manali Shukla Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Sandipan Das Cc: Santosh Shukla Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/amd-ibs-period.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/arch/x86/tests/amd-ibs-period.c b/tools/perf/arch/x86/tests/amd-ibs-period.c index cee9e11c05e0..6a92b3a23ed7 100644 --- a/tools/perf/arch/x86/tests/amd-ibs-period.c +++ b/tools/perf/arch/x86/tests/amd-ibs-period.c @@ -932,7 +932,7 @@ static bool kernel_v6_15_or_newer(void) endptr++; minor = strtol(endptr, NULL, 10); - return major >= 6 && minor >= 15; + return major > 6 || (major == 6 && minor >= 15); } int test__amd_ibs_period(struct test_suite *test __maybe_unused, From 45bd2d77fbedec862204bb5c0fcaba2b7fa5fb56 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 8 May 2026 05:59:58 +0000 Subject: [PATCH 097/343] perf tool ibs: Sync AMD IBS header file IBS_OP_DATA2 register will have two more fields: strm_st and rmt_socket in Zen6 and future AMD platforms. Kernel header file is already updated. Add those fields in tools copy as well. Signed-off-by: Ravi Bangoria Acked-by: Namhyung Kim Cc: Ananth Narayan Cc: Dapeng Mi Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Manali Shukla Cc: Peter Zijlstra Cc: Sandipan Das Cc: Santosh Shukla Signed-off-by: Arnaldo Carvalho de Melo --- tools/arch/x86/include/asm/amd/ibs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/arch/x86/include/asm/amd/ibs.h b/tools/arch/x86/include/asm/amd/ibs.h index d0777b597322..6f25074e669f 100644 --- a/tools/arch/x86/include/asm/amd/ibs.h +++ b/tools/arch/x86/include/asm/amd/ibs.h @@ -99,7 +99,9 @@ union ibs_op_data2 { rmt_node:1, /* 4: destination node */ cache_hit_st:1, /* 5: cache hit state */ data_src_hi:2, /* 6-7: data source high */ - reserved1:56; /* 8-63: reserved */ + strm_st:1, /* 8: streaming store */ + rmt_socket:1, /* 9: remote socket */ + reserved1:54; /* 10-63: reserved */ }; }; From 540dc628ab5dc2cf176053c9794ed9891269484b Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 8 May 2026 05:59:59 +0000 Subject: [PATCH 098/343] perf test ibs: Skip privilege test on Zen6 and newer platforms IBS on pre-Zen6 platforms lacked a hardware privilege filter, so the kernel enabled swfilt=1. Zen6 and newer platforms provides privilege filtering via the RIP[63] bit, making swfilt redundant. Skip the perf unit test that assumes IBS has no hardware-assisted privilege filter on Zen6 and newer platforms. swfilt is ignored by kernel on platforms that support RIP[63] bit filter i.e. all amd-ibs-swfilt.sh tests will test hardware assisted privilege filter. Without the patch on Zen6: # sudo ./perf test -vv 77 77: AMD IBS software filtering: --- start --- test child forked, pid 30813 check availability of IBS swfilt run perf record with modifier and swfilt [FAIL] IBS PMU should not accept exclude_kernel ---- end(-1) ---- 77: AMD IBS software filtering : FAILED! With the patch: # ./perf test -vv 77 77: AMD IBS software filtering: --- start --- test child forked, pid 30903 check availability of IBS swfilt run perf record with modifier and swfilt [ perf record: Woken up 2 times to write data ] [ perf record: Captured and wrote 0.000 MB /dev/null ] [ perf record: Woken up 3 times to write data ] [ perf record: Captured and wrote 0.000 MB /dev/null ] [ perf record: Woken up 3 times to write data ] [ perf record: Captured and wrote 0.000 MB /dev/null ] [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.000 MB /dev/null ] check number of samples with swfilt [ perf record: Woken up 4 times to write data ] [ perf record: Captured and wrote 0.051 MB - ] [ perf record: Woken up 4 times to write data ] [ perf record: Captured and wrote 0.063 MB - ] ---- end(0) ---- 77: AMD IBS software filtering : Ok Signed-off-by: Ravi Bangoria Acked-by: Namhyung Kim Cc: Ananth Narayan Cc: Dapeng Mi Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Manali Shukla Cc: Peter Zijlstra Cc: Sandipan Das Cc: Santosh Shukla Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/amd-ibs-swfilt.sh | 37 +++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/tools/perf/tests/shell/amd-ibs-swfilt.sh b/tools/perf/tests/shell/amd-ibs-swfilt.sh index e7f66df05c4b..5d17dc624cbe 100755 --- a/tools/perf/tests/shell/amd-ibs-swfilt.sh +++ b/tools/perf/tests/shell/amd-ibs-swfilt.sh @@ -1,6 +1,33 @@ #!/bin/bash # AMD IBS software filtering +cpu_family() { + grep -m1 '^cpu family[[:space:]]*:' /proc/cpuinfo \ + | awk -F: '{gsub(/^[ \t]+/, "", $2); print $2}' +} + +cpu_model() { + grep -m1 '^model[[:space:]]*:' /proc/cpuinfo \ + | awk -F: '{gsub(/^[ \t]+/, "", $2); print $2}' +} + +# IBS PMUs does not advertize privilege filtering capability. Rely +# on Family / Model check. +hw_priv_filter_supported() { + family=$(cpu_family) + model=$(cpu_model) + + if (( family > 0x1a )) || + { (( family == 0x1a )) && + { { (( model >= 0x50 && model <= 0x5f )) || + (( model >= 0x80 && model <= 0xaf )) || + (( model >= 0xc0 && model <= 0xcf )); }; }; }; then + return 0 # True + else + return 1 # False + fi +} + ParanoidAndNotRoot() { [ "$(id -u)" != 0 ] && [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt $1 ] } @@ -23,10 +50,12 @@ echo "run perf record with modifier and swfilt" err=0 # setting any modifiers should fail -perf record -B -e ibs_op//u -o /dev/null true 2> /dev/null -if [ $? -eq 0 ]; then - echo "[FAIL] IBS PMU should not accept exclude_kernel" - exit 1 +if ! hw_priv_filter_supported; then + perf record -B -e ibs_op//u -o /dev/null true 2> /dev/null + if [ $? -eq 0 ]; then + echo "[FAIL] IBS PMU should not accept exclude_kernel" + exit 1 + fi fi # setting it with swfilt should be fine From f04a8a7649f9b248f89971b7a440f5d158d57d46 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 8 May 2026 06:00:00 +0000 Subject: [PATCH 099/343] perf amd ibs: Suppress bogus TlbRefillLat and DCPhysAd on Zen4+ On Zen4 (and future) CPUs, IBS_OP_DATA3[TlbRefillLat] is valid only if IBS_OP_DATA3[DcPhyAddrValid] is set. Similarly, IBS_DC_PHYSADDR is valid if IBS_OP_DATA3[DcLinAddrValid] is _also_ set. Add these checks while decoding IBS MSRs. When IBS is triggered by an unprivileged user, the kernel now zeroes PhysAddr before storing raw IBS register values in the perf sample. The perf tool, however, still outputs these zero physical addresses, which serves no purpose. So avoid printing zero physical addresses. Instead of explicit family/model checks use the !zen4_ibs_extensions as a proxy flag to cover Zen 3 and earlier revisions. Signed-off-by: Ravi Bangoria Acked-by: Namhyung Kim Cc: Ananth Narayan Cc: Dapeng Mi Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Manali Shukla Cc: Peter Zijlstra Cc: Sandipan Das Cc: Santosh Shukla Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/amd-sample-raw.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/amd-sample-raw.c b/tools/perf/util/amd-sample-raw.c index b084dee76b1a..385308c55f34 100644 --- a/tools/perf/util/amd-sample-raw.c +++ b/tools/perf/util/amd-sample-raw.c @@ -172,6 +172,7 @@ static void pr_ibs_op_data3(union ibs_op_data3 reg) char dc_l1_l2tlb_miss_str[sizeof(" DcL1TlbMiss _ DcL2TlbMiss _")] = ""; char dc_l1tlb_hit_str[sizeof(" DcL1TlbHit2M _ DcL1TlbHit1G _")] = ""; char op_mem_width_str[sizeof(" OpMemWidth _____ bytes")] = ""; + char tlb_refill_lat_str[sizeof(" TlbRefillLat _____")] = ""; char dc_l2tlb_hit_2m_str[sizeof(" DcL2TlbHit2M _")] = ""; char dc_l2tlb_hit_1g_str[sizeof(" DcL2TlbHit1G _")] = ""; char dc_page_size_str[sizeof(" DcPageSize ____")] = ""; @@ -214,17 +215,23 @@ static void pr_ibs_op_data3(union ibs_op_data3 reg) " DcL2TlbHit1G %d", reg.dc_l2_tlb_hit_1g); } + /* Use !zen4_ibs_extensions as a proxy for Zen3 and earlier */ + if (!zen4_ibs_extensions || reg.dc_phy_addr_valid) { + snprintf(tlb_refill_lat_str, sizeof(tlb_refill_lat_str), + " TlbRefillLat %5d", reg.tlb_refill_lat); + } + printf("ibs_op_data3:\t%016llx LdOp %d StOp %d%s%s%s DcMiss %d DcMisAcc %d " "DcWcMemAcc %d DcUcMemAcc %d DcLockedOp %d DcMissNoMabAlloc %d " "DcLinAddrValid %d DcPhyAddrValid %d%s%s SwPf %d%s%s " - "DcMissLat %5d TlbRefillLat %5d\n", + "DcMissLat %5d%s\n", reg.val, reg.ld_op, reg.st_op, dc_l1_l2tlb_miss_str, dtlb_pgsize_cap ? dc_page_size_str : dc_l1tlb_hit_str, dc_l2tlb_hit_2m_str, reg.dc_miss, reg.dc_mis_acc, reg.dc_wc_mem_acc, reg.dc_uc_mem_acc, reg.dc_locked_op, reg.dc_miss_no_mab_alloc, reg.dc_lin_addr_valid, reg.dc_phy_addr_valid, dc_l2tlb_hit_1g_str, l2_miss_str, reg.sw_pf, op_mem_width_str, op_dc_miss_open_mem_reqs_str, - reg.dc_miss_lat, reg.tlb_refill_lat); + reg.dc_miss_lat, tlb_refill_lat_str); } /* @@ -253,8 +260,12 @@ static void amd_dump_ibs_op(struct perf_sample *sample) pr_ibs_op_data3(*op_data3); if (op_data3->dc_lin_addr_valid) printf("IbsDCLinAd:\t%016llx\n", *(rip + 4)); - if (op_data3->dc_phy_addr_valid) + + /* Use !zen4_ibs_extensions as a proxy for Zen3 and earlier */ + if (op_data3->dc_phy_addr_valid && *(rip + 5) && + (!zen4_ibs_extensions || op_data3->dc_lin_addr_valid)) { printf("IbsDCPhysAd:\t%016llx\n", *(rip + 5)); + } if (op_data->op_brn_ret && *(rip + 6)) printf("IbsBrTarget:\t%016llx\n", *(rip + 6)); } From ea0ce2e12ed5347ecefc7b7c2a01623b855d9ddb Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 8 May 2026 06:00:01 +0000 Subject: [PATCH 100/343] perf amd ibs: Make Fetch status bits dependent on PhyAddrValid for newer platforms On Zen6 and future platforms, IBS_FETCH_CTL status fields are valid only if IBS_FETCH_CTL[IbsPhyAddrValid] is set. Same for IBS_FETCH_CTL_EXT. Add these checks while decoding IBS MSRs. Unfortunately, there is no CPUID bit to indicate the change. Fallback to Family/Model check. Signed-off-by: Ravi Bangoria Acked-by: Namhyung Kim Cc: Ananth Narayan Cc: Dapeng Mi Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Manali Shukla Cc: Peter Zijlstra Cc: Sandipan Das Cc: Santosh Shukla Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/amd-sample-raw.c | 42 ++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/amd-sample-raw.c b/tools/perf/util/amd-sample-raw.c index 385308c55f34..ae005eb0363d 100644 --- a/tools/perf/util/amd-sample-raw.c +++ b/tools/perf/util/amd-sample-raw.c @@ -22,6 +22,29 @@ static bool zen4_ibs_extensions; static bool ldlat_cap; static bool dtlb_pgsize_cap; +/* + * Status fields of IBS_FETCH_CTL and IBS_FETCH_CTL_EXT are valid only if + * IBS_FETCH_CTL[PhyAddrValid] is set. + */ +static int fetch_ctl_depends_on_phy_addr_valid(void) +{ + static int depends = -1; /* -1: Don't know, 1: Yes, 0: No */ + + if (depends != -1) + return depends; + + depends = 0; + if (cpu_family > 0x1a || + (cpu_family == 0x1a && ( + (cpu_model >= 0x50 && cpu_model <= 0x5f) || + (cpu_model >= 0x80 && cpu_model <= 0xaf) || + (cpu_model >= 0xc0 && cpu_model <= 0xcf)))) { + depends = 1; + } + + return depends; +} + static void pr_ibs_fetch_ctl(union ibs_fetch_ctl reg) { const char * const ic_miss_strs[] = { @@ -43,6 +66,18 @@ static void pr_ibs_fetch_ctl(union ibs_fetch_ctl reg) const char *ic_miss_str = NULL; const char *l1tlb_pgsz_str = NULL; char l3_miss_str[sizeof(" L3MissOnly _ FetchOcMiss _ FetchL3Miss _")] = ""; + char l3_miss_only_str[sizeof(" L3MissOnly _")] = ""; + + if (fetch_ctl_depends_on_phy_addr_valid() && !reg.phy_addr_valid) { + snprintf(l3_miss_only_str, sizeof(l3_miss_only_str), + " L3MissOnly %d", reg.l3_miss_only); + + printf("ibs_fetch_ctl:\t%016llx MaxCnt %7d Cnt %7d En %d Val %d Comp %d " + "PhyAddrValid 0 RandEn %d%s\n", reg.val, reg.fetch_maxcnt << 4, + reg.fetch_cnt << 4, reg.fetch_en, reg.fetch_val, reg.fetch_comp, + reg.rand_en, l3_miss_only_str); + return; + } if (cpu_family == 0x19 && cpu_model < 0x10) { /* @@ -72,8 +107,11 @@ static void pr_ibs_fetch_ctl(union ibs_fetch_ctl reg) l3_miss_str); } -static void pr_ic_ibs_extd_ctl(union ic_ibs_extd_ctl reg) +static void pr_ic_ibs_extd_ctl(union ibs_fetch_ctl fetch_ctl, union ic_ibs_extd_ctl reg) { + if (fetch_ctl_depends_on_phy_addr_valid() && !fetch_ctl.phy_addr_valid) + return; + printf("ic_ibs_ext_ctl:\t%016llx IbsItlbRefillLat %3d\n", reg.val, reg.itlb_refill_lat); } @@ -285,7 +323,7 @@ static void amd_dump_ibs_fetch(struct perf_sample *sample) printf("IbsFetchLinAd:\t%016llx\n", *addr++); if (fetch_ctl->phy_addr_valid) printf("IbsFetchPhysAd:\t%016llx\n", *addr); - pr_ic_ibs_extd_ctl(*extd_ctl); + pr_ic_ibs_extd_ctl(*fetch_ctl, *extd_ctl); } /* From 7c04195ccefcfc95d46abfd30a435679a28493b2 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 8 May 2026 06:00:02 +0000 Subject: [PATCH 101/343] perf amd ibs: Decode Remote-Socket flag in IBS OP raw dump IBS OP on Zen6 and future platform can mark a data source as coming from a remote socket. When the PMU advertises this feature, interpret IBS_OP_DATA2[9] bit as the Remote-Socket indicator and show it in the raw dump output. Signed-off-by: Ravi Bangoria Acked-by: Namhyung Kim Cc: Ananth Narayan Cc: Dapeng Mi Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Manali Shukla Cc: Peter Zijlstra Cc: Sandipan Das Cc: Santosh Shukla Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/amd-sample-raw.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/amd-sample-raw.c b/tools/perf/util/amd-sample-raw.c index ae005eb0363d..3e5530008b14 100644 --- a/tools/perf/util/amd-sample-raw.c +++ b/tools/perf/util/amd-sample-raw.c @@ -21,6 +21,7 @@ static u32 cpu_family, cpu_model, ibs_fetch_type, ibs_op_type; static bool zen4_ibs_extensions; static bool ldlat_cap; static bool dtlb_pgsize_cap; +static bool rmtsocket_cap; /* * Status fields of IBS_FETCH_CTL and IBS_FETCH_CTL_EXT are valid only if @@ -164,8 +165,13 @@ static void pr_ibs_op_data2_extended(union ibs_op_data2 reg) /* 13 to 31 are reserved. Avoid printing them. */ }; int data_src = (reg.data_src_hi << 3) | reg.data_src_lo; + char rmtsocket[sizeof("RmtSocket _ ")] = ""; - printf("ibs_op_data2:\t%016llx %sRmtNode %d%s\n", reg.val, + if (rmtsocket_cap) + snprintf(rmtsocket, sizeof(rmtsocket), "RmtSocket %d ", reg.rmt_socket); + + printf("ibs_op_data2:\t%016llx %s%sRmtNode %d%s\n", reg.val, + rmtsocket, (data_src == 1 || data_src == 2 || data_src == 5) ? (reg.cache_hit_st ? "CacheHitSt 1=O-State " : "CacheHitSt 0=M-state ") : "", reg.rmt_node, @@ -184,8 +190,13 @@ static void pr_ibs_op_data2_default(union ibs_op_data2 reg) " DataSrc 6=(reserved)", " DataSrc 7=Other" }; + char rmtsocket[sizeof("RmtSocket _ ")] = ""; - printf("ibs_op_data2:\t%016llx %sRmtNode %d%s\n", reg.val, + if (rmtsocket_cap) + snprintf(rmtsocket, sizeof(rmtsocket), "RmtSocket %d ", reg.rmt_socket); + + printf("ibs_op_data2:\t%016llx %s%sRmtNode %d%s\n", reg.val, + rmtsocket, reg.data_src_lo == 2 ? (reg.cache_hit_st ? "CacheHitSt 1=O-State " : "CacheHitSt 0=M-state ") : "", reg.rmt_node, data_src_str[reg.data_src_lo]); @@ -429,6 +440,9 @@ bool evlist__has_amd_ibs(struct evlist *evlist) if (perf_env__find_pmu_cap(env, "ibs_op", "dtlb_pgsize")) dtlb_pgsize_cap = 1; + if (perf_env__find_pmu_cap(env, "ibs_op", "rmtsocket")) + rmtsocket_cap = 1; + if (ibs_fetch_type || ibs_op_type) { if (!cpu_family) parse_cpuid(env); From 873f232d09622767c57557003d4bd98ed6c6f327 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 8 May 2026 06:00:03 +0000 Subject: [PATCH 102/343] perf amd ibs: Decode Streaming-store flag in IBS OP raw dump IBS OP on Zen6 and future platform can tag IBS samples that originate from streaming-store instruction. When the PMU advertises this feature, interpret IBS_OP_DATA2[8] bit as the streaming store indicator and show it in the raw dump output. Signed-off-by: Ravi Bangoria Acked-by: Namhyung Kim Cc: Ananth Narayan Cc: Dapeng Mi Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Manali Shukla Cc: Peter Zijlstra Cc: Sandipan Das Cc: Santosh Shukla Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/amd-sample-raw.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/amd-sample-raw.c b/tools/perf/util/amd-sample-raw.c index 3e5530008b14..394c061fbeb3 100644 --- a/tools/perf/util/amd-sample-raw.c +++ b/tools/perf/util/amd-sample-raw.c @@ -22,6 +22,7 @@ static bool zen4_ibs_extensions; static bool ldlat_cap; static bool dtlb_pgsize_cap; static bool rmtsocket_cap; +static bool strmst_cap; /* * Status fields of IBS_FETCH_CTL and IBS_FETCH_CTL_EXT are valid only if @@ -166,12 +167,15 @@ static void pr_ibs_op_data2_extended(union ibs_op_data2 reg) }; int data_src = (reg.data_src_hi << 3) | reg.data_src_lo; char rmtsocket[sizeof("RmtSocket _ ")] = ""; + char strmst[sizeof("StrmSt _ ")] = ""; if (rmtsocket_cap) snprintf(rmtsocket, sizeof(rmtsocket), "RmtSocket %d ", reg.rmt_socket); + if (strmst_cap) + snprintf(strmst, sizeof(strmst), "StrmSt %d ", reg.strm_st); - printf("ibs_op_data2:\t%016llx %s%sRmtNode %d%s\n", reg.val, - rmtsocket, + printf("ibs_op_data2:\t%016llx %s%s%sRmtNode %d%s\n", reg.val, + rmtsocket, strmst, (data_src == 1 || data_src == 2 || data_src == 5) ? (reg.cache_hit_st ? "CacheHitSt 1=O-State " : "CacheHitSt 0=M-state ") : "", reg.rmt_node, @@ -191,12 +195,15 @@ static void pr_ibs_op_data2_default(union ibs_op_data2 reg) " DataSrc 7=Other" }; char rmtsocket[sizeof("RmtSocket _ ")] = ""; + char strmst[sizeof("StrmSt _ ")] = ""; if (rmtsocket_cap) snprintf(rmtsocket, sizeof(rmtsocket), "RmtSocket %d ", reg.rmt_socket); + if (strmst_cap) + snprintf(strmst, sizeof(strmst), "StrmSt %d ", reg.strm_st); - printf("ibs_op_data2:\t%016llx %s%sRmtNode %d%s\n", reg.val, - rmtsocket, + printf("ibs_op_data2:\t%016llx %s%s%sRmtNode %d%s\n", reg.val, + rmtsocket, strmst, reg.data_src_lo == 2 ? (reg.cache_hit_st ? "CacheHitSt 1=O-State " : "CacheHitSt 0=M-state ") : "", reg.rmt_node, data_src_str[reg.data_src_lo]); @@ -443,6 +450,9 @@ bool evlist__has_amd_ibs(struct evlist *evlist) if (perf_env__find_pmu_cap(env, "ibs_op", "rmtsocket")) rmtsocket_cap = 1; + if (perf_env__find_pmu_cap(env, "ibs_op", "strmst")) + strmst_cap = 1; + if (ibs_fetch_type || ibs_op_type) { if (!cpu_family) parse_cpuid(env); From a31423e67c0e8c716c9ecdf0d4836dd7049ad78b Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Fri, 8 May 2026 06:00:04 +0000 Subject: [PATCH 103/343] perf doc: Document new IBS capabilities in man page Include examples of: o Privilege filter with Fetch and Op PMUs, including swfilt approach on Zen5 and older platforms and hardware assisted filter on Zen6 and newer platforms o Streaming store filter with Op PMU o Fetch latency filter with Fetch PMU Signed-off-by: Ravi Bangoria Acked-by: Namhyung Kim Cc: Ananth Narayan Cc: Dapeng Mi Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Manali Shukla Cc: Peter Zijlstra Cc: Sandipan Das Cc: Santosh Shukla Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-amd-ibs.txt | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tools/perf/Documentation/perf-amd-ibs.txt b/tools/perf/Documentation/perf-amd-ibs.txt index 548549935760..253a7375c88a 100644 --- a/tools/perf/Documentation/perf-amd-ibs.txt +++ b/tools/perf/Documentation/perf-amd-ibs.txt @@ -69,6 +69,14 @@ Per-cpu profile (cpu10), cycles event, sampling period: 100000 # perf record -e ibs_op// -c 100000 -C 10 +Userspace only, per-cpu profile (cpu10), cycles event, sampling period: 100000 + + Zen6 onward (See NOTES): + # perf record -e ibs_op//u -c 100000 -C 10 + + Until Zen5: + # perf record -e ibs_op/swfilt=1/u -c 100000 -C 10 + Per-cpu profile (cpu10), cycles event, sampling freq: 1000 # perf record -e ibs_op// -F 1000 -C 10 @@ -94,6 +102,11 @@ onward) Latency value which is a multiple of 128 incurs a little less profiling overhead compared to other values. +System-wide profile, cycles event, sampling period: 100000, streaming store +filter (Zen6 onward) + + # perf record -e ibs_op/strmst=1/ -c 100000 -a + Per process(upstream v6.2 onward), uOps event, sampling period: 100000 # perf record -e ibs_op/cnt_ctl=1/ -c 100000 -p 1234 @@ -150,6 +163,14 @@ System-wide profile, fetch ops event, sampling period: 100000 # perf record -e ibs_fetch// -c 100000 -a +Userspace only, system-wide profile, fetch ops event, sampling period: 100000 + + Zen6 onward (See NOTES): + # perf record -e ibs_fetch//u -c 100000 -a + + Until Zen5: + # perf record -e ibs_fetch/swfilt=1/u -c 100000 -a + System-wide profile, fetch ops event, sampling period: 100000, Random enable # perf record -e ibs_fetch/rand_en=1/ -c 100000 -a @@ -158,6 +179,15 @@ System-wide profile, fetch ops event, sampling period: 100000, Random enable helps in cases like long running loops where PMU is tagging the same instruction over and over because of fixed sample period. +System-wide profile, fetch ops event, sampling period: 10000, fetch latency +filter (Zen6 onward) + + # perf record -e ibs_fetch/fetchlat=128/ -c 10000 -a + + Supported fetch latency threshold values are 128 to 1920 (both inclusive). + Latency value which is a multiple of 128 incurs a little less profiling + overhead compared to other values. + etc. PERF MEM AND PERF C2C @@ -216,6 +246,15 @@ sort keys. For example: Please refer to their man page for more detail. +NOTES +----- +Hardware privilege filtering uses bit 63 to distinguish between kernel +and userspace addresses. Hardware privilege filtering is not supported +on 32-bit systems. Also, the bit 63 convention is not universal and can +fail in specific environments, such as, using 64-bit host IBS to profile +a 32-bit guest, using 64-bit host IBS to profile non-Linux 64-bit guests +that do not adhere to the bit 63 privilege standard etc. + SEE ALSO -------- From 0b18bced5444f4fc54ba4500c377f2e88d31ea09 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 18:41:05 -0700 Subject: [PATCH 104/343] perf tool_pmu: Make tool PMU events respect enable/disable Tool PMU events (duration_time, user_time, system_time) currently count from when the event is opened to when it is read. This causes issues with features like the delay option (-D) or control fd, where events are opened but should not start counting immediately. Make these events behave more like regular counters by implementing proper enable and disable support. Add accumulated_time to struct evsel to track time while enabled, and implement enable/disable CPU callbacks to start/stop counting. Also generalize userspace PMU mixed group handling. Userspace synthetic PMUs (type > PERF_PMU_TYPE_PE_END) do not have kernel implementations and cannot be grouped in the kernel (opened with group_fd = -1), and are skipped by kernel enable/disable calls. Iterate over group members in userspace and manually enable/disable any members if the leader or the member is a non-perf-event open PMU, and synchronize their disabled flags. Closes: https://lore.kernel.org/linux-perf-users/20260517093650.2540920-1-nigro.fra@gmail.com/ Fixes: b71f46a6a7086175 ("perf stat: Remove hard coded shadow metrics") Reported-by: Francesco Nigro Assisted-by: Antigravity:gemini-3-flash Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 10 +- tools/perf/util/evsel.c | 205 ++++++++++++++++++++++++------- tools/perf/util/evsel.h | 15 ++- tools/perf/util/tool_pmu.c | 246 +++++++++++++++++++++++++++++-------- tools/perf/util/tool_pmu.h | 4 + 5 files changed, 379 insertions(+), 101 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index ee971d15b3c6..1a238b245b3a 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -529,7 +529,7 @@ static int evlist__is_enabled(struct evlist *evlist) static void __evlist__disable(struct evlist *evlist, char *evsel_name, bool excl_dummy) { - struct evsel *pos; + struct evsel *pos, *member; struct evlist_cpu_iterator evlist_cpu_itr; bool has_imm = false; @@ -561,6 +561,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name, bool excl if (excl_dummy && evsel__is_dummy_event(pos)) continue; pos->disabled = true; + + for_each_group_member(member, pos) + member->disabled = true; } /* @@ -590,7 +593,7 @@ void evlist__disable_evsel(struct evlist *evlist, char *evsel_name) static void __evlist__enable(struct evlist *evlist, char *evsel_name, bool excl_dummy) { - struct evsel *pos; + struct evsel *pos, *member; struct evlist_cpu_iterator evlist_cpu_itr; evlist__for_each_cpu(evlist_cpu_itr, evlist) { @@ -611,6 +614,9 @@ static void __evlist__enable(struct evlist *evlist, char *evsel_name, bool excl_ if (excl_dummy && evsel__is_dummy_event(pos)) continue; pos->disabled = false; + + for_each_group_member(member, pos) + member->disabled = false; } /* diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 713a250c7374..ac92f9e0e5b4 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -11,68 +11,71 @@ */ #define __SANE_USERSPACE_TYPES__ -#include +#include "evsel.h" + #include #include +#include + +#include #include -#include -#include +#include +#include +#include #include #include -#include -#include #include #include #include #include #include -#include -#include + +#include +#include +#include +#include +#include +#include +#include #include + +#include "../perf-sys.h" #include "asm/bug.h" +#include "bpf-filter.h" #include "bpf_counter.h" #include "callchain.h" #include "cgroup.h" #include "counts.h" -#include "dwarf-regs.h" -#include "event.h" -#include "evsel.h" -#include "time-utils.h" -#include "util/env.h" -#include "util/evsel_config.h" -#include "util/evsel_fprintf.h" -#include "evlist.h" -#include -#include "thread_map.h" -#include "target.h" -#include "perf_regs.h" -#include "record.h" #include "debug.h" -#include "trace-event.h" +#include "drm_pmu.h" +#include "dwarf-regs.h" +#include "env.h" +#include "event.h" +#include "evlist.h" +#include "evsel_config.h" +#include "evsel_fprintf.h" +#include "hashmap.h" +#include "hist.h" +#include "hwmon_pmu.h" +#include "intel-tpebs.h" +#include "memswap.h" +#include "off_cpu.h" +#include "parse-branch-options.h" +#include "perf_regs.h" +#include "pmu.h" +#include "pmus.h" +#include "record.h" +#include "rlimit.h" #include "session.h" #include "stat.h" #include "string2.h" -#include "memswap.h" -#include "util.h" -#include "util/hashmap.h" -#include "off_cpu.h" -#include "pmu.h" -#include "pmus.h" -#include "drm_pmu.h" -#include "hwmon_pmu.h" +#include "target.h" +#include "thread_map.h" +#include "time-utils.h" #include "tool_pmu.h" #include "tp_pmu.h" -#include "rlimit.h" -#include "../perf-sys.h" -#include "util/parse-branch-options.h" -#include "util/bpf-filter.h" -#include "util/hist.h" -#include -#include -#include -#include "util/intel-tpebs.h" - -#include +#include "trace-event.h" +#include "util.h" #ifdef HAVE_LIBTRACEEVENT #include @@ -1795,27 +1798,114 @@ int evsel__append_addr_filter(struct evsel *evsel, const char *filter) /* Caller has to clear disabled after going through all CPUs. */ int evsel__enable_cpu(struct evsel *evsel, int cpu_map_idx) { - return perf_evsel__enable_cpu(&evsel->core, cpu_map_idx); + int err; + + if (evsel__is_tool(evsel)) + err = evsel__tool_pmu_enable_cpu(evsel, cpu_map_idx); + else + err = perf_evsel__enable_cpu(&evsel->core, cpu_map_idx); + + if (!err && evsel__is_group_leader(evsel)) { + struct evsel *member; + + for_each_group_member(member, evsel) { + if (evsel__is_non_perf_event_open_pmu(evsel) || + evsel__is_non_perf_event_open_pmu(member)) { + /* + * In a mixed PMU group, userspace PMUs are not + * grouped in the kernel (opened with group_fd = -1) + * and are skipped by the kernel when enabling the + * group leader. We must manually enable them in + * userspace. + */ + int mem_err = evsel__enable_cpu(member, cpu_map_idx); + + if (mem_err) + return mem_err; + } + } + } + return err; } int evsel__enable(struct evsel *evsel) { - int err = perf_evsel__enable(&evsel->core); + int err; + + if (evsel__is_tool(evsel)) + err = evsel__tool_pmu_enable(evsel); + else + err = perf_evsel__enable(&evsel->core); if (!err) evsel->disabled = false; + + if (!err && evsel__is_group_leader(evsel)) { + struct evsel *member; + + for_each_group_member(member, evsel) { + if (evsel__is_non_perf_event_open_pmu(evsel) || + evsel__is_non_perf_event_open_pmu(member)) { + /* + * In a mixed PMU group, userspace PMUs are not + * grouped in the kernel (opened with group_fd = -1) + * and are skipped by the kernel when enabling the + * group leader. We must manually enable them in + * userspace. + */ + int mem_err = evsel__enable(member); + + if (mem_err) + return mem_err; + } + member->disabled = false; + } + } + return err; } /* Caller has to set disabled after going through all CPUs. */ int evsel__disable_cpu(struct evsel *evsel, int cpu_map_idx) { - return perf_evsel__disable_cpu(&evsel->core, cpu_map_idx); + int err; + + if (evsel__is_tool(evsel)) + err = evsel__tool_pmu_disable_cpu(evsel, cpu_map_idx); + else + err = perf_evsel__disable_cpu(&evsel->core, cpu_map_idx); + + if (!err && evsel__is_group_leader(evsel)) { + struct evsel *member; + + for_each_group_member(member, evsel) { + if (evsel__is_non_perf_event_open_pmu(evsel) || + evsel__is_non_perf_event_open_pmu(member)) { + /* + * In a mixed PMU group, userspace PMUs are not + * grouped in the kernel and are skipped by the + * kernel when disabling the group leader. We must + * manually disable them in userspace. + */ + int mem_err = evsel__disable_cpu(member, cpu_map_idx); + + if (mem_err) + return mem_err; + } + } + } + return err; } int evsel__disable(struct evsel *evsel) { - int err = perf_evsel__disable(&evsel->core); + int err; + + if (evsel__is_tool(evsel)) + err = evsel__tool_pmu_disable(evsel); + else + err = perf_evsel__disable(&evsel->core); + /* * We mark it disabled here so that tools that disable a event can * ignore events after they disable it. I.e. the ring buffer may have @@ -1825,6 +1915,27 @@ int evsel__disable(struct evsel *evsel) if (!err) evsel->disabled = true; + if (!err && evsel__is_group_leader(evsel)) { + struct evsel *member; + + for_each_group_member(member, evsel) { + if (evsel__is_non_perf_event_open_pmu(evsel) || + evsel__is_non_perf_event_open_pmu(member)) { + /* + * In a mixed PMU group, userspace PMUs are not + * grouped in the kernel and are skipped by the + * kernel when disabling the group leader. We must + * manually disable them in userspace. + */ + int mem_err = evsel__disable(member); + + if (mem_err) + return mem_err; + } + member->disabled = true; + } + } + return err; } @@ -1885,8 +1996,10 @@ void evsel__exit(struct evsel *evsel) evsel__priv_destructor(evsel->priv); perf_evsel__object.fini(evsel); if (evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME || - evsel__tool_event(evsel) == TOOL_PMU__EVENT_USER_TIME) - xyarray__delete(evsel->start_times); + evsel__tool_event(evsel) == TOOL_PMU__EVENT_USER_TIME) { + xyarray__delete(evsel->process_time.start_times); + xyarray__delete(evsel->process_time.accumulated_times); + } } void evsel__delete(struct evsel *evsel) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 927e5b4756cc..3b12d99f0aa9 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -190,12 +190,18 @@ struct evsel { double max; } retirement_latency; /* duration_time is a single global time. */ - __u64 start_time; + struct { + __u64 start_time; + __u64 accumulated_time; + } duration_time; /* * user_time and system_time read an initial value potentially * per-CPU or per-pid. */ - struct xyarray *start_times; + struct { + struct xyarray *start_times; + struct xyarray *accumulated_times; + } process_time; }; /* Is the tool's fd for /proc/pid/stat or /proc/stat. */ bool pid_stat; @@ -350,6 +356,11 @@ void arch_evsel__apply_ratio_to_prev(struct evsel *evsel, struct perf_event_attr int evsel__set_filter(struct evsel *evsel, const char *filter); int evsel__append_tp_filter(struct evsel *evsel, const char *filter); int evsel__append_addr_filter(struct evsel *evsel, const char *filter); +static inline bool evsel__is_non_perf_event_open_pmu(const struct evsel *evsel) +{ + return evsel->pmu && evsel->pmu->type > PERF_PMU_TYPE_PE_END; +} + int evsel__enable_cpu(struct evsel *evsel, int cpu_map_idx); int evsel__enable(struct evsel *evsel); int evsel__disable(struct evsel *evsel); diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c index 6a9df3dc0e07..5c30854b4644 100644 --- a/tools/perf/util/tool_pmu.c +++ b/tools/perf/util/tool_pmu.c @@ -17,6 +17,8 @@ #include #include +#define INVALID_START_TIME ~0ULL + static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = { NULL, "duration_time", @@ -205,20 +207,57 @@ int evsel__tool_pmu_prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus, int nthreads) { - if ((evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME || - evsel__tool_event(evsel) == TOOL_PMU__EVENT_USER_TIME) && - !evsel->start_times) { - evsel->start_times = xyarray__new(perf_cpu_map__nr(cpus), - nthreads, - sizeof(__u64)); - if (!evsel->start_times) - return -ENOMEM; + enum tool_pmu_event ev = evsel__tool_event(evsel); + + if (ev == TOOL_PMU__EVENT_SYSTEM_TIME || ev == TOOL_PMU__EVENT_USER_TIME) { + if (!evsel->process_time.start_times) { + evsel->process_time.start_times = + xyarray__new(perf_cpu_map__nr(cpus), nthreads, sizeof(__u64)); + if (!evsel->process_time.start_times) + return -ENOMEM; + } + if (!evsel->process_time.accumulated_times) { + evsel->process_time.accumulated_times = + xyarray__new(perf_cpu_map__nr(cpus), nthreads, sizeof(__u64)); + if (!evsel->process_time.accumulated_times) + return -ENOMEM; + } } return 0; } #define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y)) +static int tool_pmu__read_stat(struct evsel *evsel, int cpu_map_idx, int thread, __u64 *val) +{ + enum tool_pmu_event ev = evsel__tool_event(evsel); + bool system = ev == TOOL_PMU__EVENT_SYSTEM_TIME; + int fd = FD(evsel, cpu_map_idx, thread); + int err = 0; + + if (fd < 0) { + *val = 0; + return 0; + } + + lseek(fd, 0, SEEK_SET); + if (evsel->pid_stat) { + if (cpu_map_idx == 0) + err = read_pid_stat_field(fd, system ? 15 : 14, val); + else + *val = 0; + } else { + if (thread == 0) { + struct perf_cpu cpu = perf_cpu_map__cpu(evsel->core.cpus, cpu_map_idx); + + err = read_stat_field(fd, cpu, system ? 3 : 1, val); + } else { + *val = 0; + } + } + return err; +} + int evsel__tool_pmu_open(struct evsel *evsel, struct perf_thread_map *threads, int start_cpu_map_idx, int end_cpu_map_idx) @@ -232,7 +271,14 @@ int evsel__tool_pmu_open(struct evsel *evsel, if (ev == TOOL_PMU__EVENT_DURATION_TIME) { if (evsel->core.attr.sample_period) /* no sampling */ return -EINVAL; - evsel->start_time = rdclock(); + evsel->duration_time.accumulated_time = 0; + if (evsel->core.attr.disabled) { + evsel->disabled = true; + evsel->duration_time.start_time = INVALID_START_TIME; + } else { + evsel->disabled = false; + evsel->duration_time.start_time = rdclock(); + } return 0; } @@ -246,8 +292,8 @@ int evsel__tool_pmu_open(struct evsel *evsel, pid = perf_thread_map__pid(threads, thread); if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) { - bool system = ev == TOOL_PMU__EVENT_SYSTEM_TIME; __u64 *start_time = NULL; + __u64 *accumulated_time = NULL; int fd; if (evsel->core.attr.sample_period) { @@ -269,21 +315,25 @@ int evsel__tool_pmu_open(struct evsel *evsel, err = -errno; goto out_close; } - start_time = xyarray__entry(evsel->start_times, idx, thread); - if (pid > -1) { - err = read_pid_stat_field(fd, system ? 15 : 14, - start_time); + start_time = xyarray__entry(evsel->process_time.start_times, idx, + thread); + accumulated_time = xyarray__entry( + evsel->process_time.accumulated_times, idx, thread); + *accumulated_time = 0; + + if (evsel->core.attr.disabled) { + evsel->disabled = true; + *start_time = INVALID_START_TIME; } else { - struct perf_cpu cpu; - - cpu = perf_cpu_map__cpu(evsel->core.cpus, idx); - err = read_stat_field(fd, cpu, system ? 3 : 1, - start_time); + evsel->disabled = false; + err = tool_pmu__read_stat(evsel, idx, thread, start_time); + if (err) { + close(fd); + FD(evsel, idx, thread) = -1; + goto out_close; + } } - if (err) - goto out_close; } - } } return 0; @@ -467,10 +517,111 @@ static void perf_counts__update(struct perf_counts_values *count, count->lost = 0; } } +int evsel__tool_pmu_enable_cpu(struct evsel *evsel, int cpu_map_idx) +{ + enum tool_pmu_event ev = evsel__tool_event(evsel); + int thread, nthreads; + + if (!evsel->disabled) + return 0; + + if (ev == TOOL_PMU__EVENT_DURATION_TIME) { + if (cpu_map_idx == 0) + evsel->duration_time.start_time = rdclock(); + return 0; + } + + if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) { + nthreads = xyarray__max_y(evsel->process_time.start_times); + for (thread = 0; thread < nthreads; thread++) { + __u64 *start_time = xyarray__entry(evsel->process_time.start_times, + cpu_map_idx, thread); + __u64 val; + int err; + + err = tool_pmu__read_stat(evsel, cpu_map_idx, thread, &val); + if (!err) + *start_time = val; + else + *start_time = INVALID_START_TIME; + } + } + return 0; +} + +int evsel__tool_pmu_enable(struct evsel *evsel) +{ + unsigned int idx; + int err = 0; + + if (!evsel->disabled) + return 0; + + for (idx = 0; idx < perf_cpu_map__nr(evsel->core.cpus); idx++) { + err = evsel__tool_pmu_enable_cpu(evsel, idx); + if (err) + break; + } + return err; +} + +int evsel__tool_pmu_disable_cpu(struct evsel *evsel, int cpu_map_idx) +{ + enum tool_pmu_event ev = evsel__tool_event(evsel); + int thread, nthreads; + + if (evsel->disabled) + return 0; + + if (ev == TOOL_PMU__EVENT_DURATION_TIME) { + if (cpu_map_idx == 0) { + __u64 delta = rdclock() - evsel->duration_time.start_time; + + evsel->duration_time.accumulated_time += delta; + } + return 0; + } + + if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) { + nthreads = xyarray__max_y(evsel->process_time.start_times); + for (thread = 0; thread < nthreads; thread++) { + __u64 *start_time = xyarray__entry(evsel->process_time.start_times, + cpu_map_idx, thread); + __u64 *accumulated_time = xyarray__entry( + evsel->process_time.accumulated_times, cpu_map_idx, thread); + __u64 val; + int err; + + err = tool_pmu__read_stat(evsel, cpu_map_idx, thread, &val); + if (!err) { + if (*start_time != INVALID_START_TIME && val >= *start_time) + *accumulated_time += (val - *start_time); + } + *start_time = INVALID_START_TIME; + } + } + return 0; +} + +int evsel__tool_pmu_disable(struct evsel *evsel) +{ + unsigned int idx; + int err = 0; + + if (evsel->disabled) + return 0; + + for (idx = 0; idx < perf_cpu_map__nr(evsel->core.cpus); idx++) { + err = evsel__tool_pmu_disable_cpu(evsel, idx); + if (err) + break; + } + return err; +} int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) { - __u64 *start_time, cur_time, delta_start; + __u64 delta_start = 0; int err = 0; struct perf_counts_values *count, *old_count = NULL; bool adjust = false; @@ -507,39 +658,33 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) return 0; } case TOOL_PMU__EVENT_DURATION_TIME: - /* - * Pretend duration_time is only on the first CPU and thread, or - * else aggregation will scale duration_time by the number of - * CPUs/threads. - */ - start_time = &evsel->start_time; - if (cpu_map_idx == 0 && thread == 0) - cur_time = rdclock(); - else - cur_time = *start_time; + if (cpu_map_idx == 0 && thread == 0) { + delta_start = evsel->duration_time.accumulated_time; + if (!evsel->disabled && + evsel->duration_time.start_time != INVALID_START_TIME) + delta_start += (rdclock() - evsel->duration_time.start_time); + } else { + delta_start = 0; + } break; case TOOL_PMU__EVENT_USER_TIME: case TOOL_PMU__EVENT_SYSTEM_TIME: { - bool system = evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME; - int fd = FD(evsel, cpu_map_idx, thread); + __u64 accumulated = *(__u64 *)xyarray__entry(evsel->process_time.accumulated_times, + cpu_map_idx, thread); - start_time = xyarray__entry(evsel->start_times, cpu_map_idx, thread); - lseek(fd, SEEK_SET, 0); - if (evsel->pid_stat) { - /* The event exists solely on 1 CPU. */ - if (cpu_map_idx == 0) - err = read_pid_stat_field(fd, system ? 15 : 14, &cur_time); - else - cur_time = 0; + if (evsel->disabled) { + delta_start = accumulated; } else { - /* The event is for all threads. */ - if (thread == 0) { - struct perf_cpu cpu = perf_cpu_map__cpu(evsel->core.cpus, - cpu_map_idx); + __u64 *start_time = xyarray__entry(evsel->process_time.start_times, + cpu_map_idx, thread); + __u64 cur_time; - err = read_stat_field(fd, cpu, system ? 3 : 1, &cur_time); - } else { - cur_time = 0; + err = tool_pmu__read_stat(evsel, cpu_map_idx, thread, &cur_time); + if (!err) { + if (*start_time != INVALID_START_TIME && cur_time >= *start_time) + delta_start = accumulated + (cur_time - *start_time); + else + delta_start = accumulated; } } adjust = true; @@ -553,7 +698,6 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) if (err) return err; - delta_start = cur_time - *start_time; if (adjust) { __u64 ticks_per_sec = sysconf(_SC_CLK_TCK); diff --git a/tools/perf/util/tool_pmu.h b/tools/perf/util/tool_pmu.h index f1714001bc1d..f66d24cf3502 100644 --- a/tools/perf/util/tool_pmu.h +++ b/tools/perf/util/tool_pmu.h @@ -56,6 +56,10 @@ int evsel__tool_pmu_prepare_open(struct evsel *evsel, int evsel__tool_pmu_open(struct evsel *evsel, struct perf_thread_map *threads, int start_cpu_map_idx, int end_cpu_map_idx); +int evsel__tool_pmu_enable_cpu(struct evsel *evsel, int cpu_map_idx); +int evsel__tool_pmu_enable(struct evsel *evsel); +int evsel__tool_pmu_disable_cpu(struct evsel *evsel, int cpu_map_idx); +int evsel__tool_pmu_disable(struct evsel *evsel); int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread); struct perf_pmu *tool_pmu__new(void); From f83deb058025d1b6eb0ff297422634a5a11ef87b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 May 2026 18:41:06 -0700 Subject: [PATCH 105/343] perf tests: Add test for stat delay option with duration_time Add a new test case `test_stat_delay` to `stat.sh` to verify that `duration_time` correctly excludes the delay period when using the delay option (-D). The test runs `perf stat -D 1000 -e duration_time sleep 2` and verifies that `duration_time` is ~1s (excluding the 1s delay), not ~2s. Assisted-by: Antigravity:gemini-3-flash Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Francesco Nigro Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/stat.sh | 53 ++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tools/perf/tests/shell/stat.sh b/tools/perf/tests/shell/stat.sh index 4edb04039036..1e17bee026bd 100755 --- a/tools/perf/tests/shell/stat.sh +++ b/tools/perf/tests/shell/stat.sh @@ -483,6 +483,58 @@ test_stat_pid() { wait $pid 2>/dev/null || true } +test_stat_delay() { + echo "stat -D test" + if ! env LC_ALL=C perf stat -D 1000 -e duration_time sleep 2 > "${stat_output}" 2>&1 + then + echo "stat -D test [Failed - command failed]" + cat "${stat_output}" + err=1 + return + fi + + duration=$(grep "duration_time" "${stat_output}" | awk '{print $1}' | tr -d ',') + elapsed=$(grep "seconds time elapsed" "${stat_output}" | awk '{print $1}') + + if [ -z "$duration" ] || [ -z "$elapsed" ] + then + echo "stat -D test [Failed - failed to find duration_time or time elapsed in output]" + cat "${stat_output}" + err=1 + return + fi + + # Compare duration (ns) and elapsed (s) using awk to handle float and allow tolerance. + if ! awk -v d="$duration" -v e="$elapsed" ' + BEGIN { + diff = d - (e * 1e9); + if (diff < 0) diff = -diff; + # Allow 200ms tolerance (200,000,000 ns) for loaded CI machines. + if (diff > 200000000) { + printf "Fail: duration (%d ns) and elapsed (%f s) mismatch (diff %d ns)\n", d, e, diff; + exit 1; + } + # Lower bound check: must be at least 0.5s. + if (d < 500000000) { + printf "Fail: duration (%d ns) is abnormally small\n", d; + exit 1; + } + # Upper bound check: must be strictly less than 1.7s (proving delay was excluded). + if (d > 1700000000) { + printf "Fail: duration (%d ns) is too large (delay might not be excluded)\n", d; + exit 1; + } + exit 0; + }' + then + echo "stat -D test [Failed - validation failed]" + cat "${stat_output}" + err=1 + return + fi + echo "stat -D test [Success]" +} + test_default_stat test_null_stat test_offline_cpu_stat @@ -498,6 +550,7 @@ test_stat_no_aggr test_stat_detailed test_stat_repeat test_stat_pid +test_stat_delay cleanup exit $err From 7378b6656aa46fda56f2743d5a7c1f619c2f6f9b Mon Sep 17 00:00:00 2001 From: Li Guan Date: Thu, 14 May 2026 02:07:21 +0800 Subject: [PATCH 106/343] perf riscv: Fix discarded const qualifier in _get_field() The assignment of strrchr() return values to non-const char * variables triggers a -Werror=discarded-qualifiers warning when building with GCC 14. This happens because in newer glibc versions, strrchr() returns a 'const char *' if the input string is const. Properly declare 'line2' and 'nl' as const char * to match the glibc function signature and ensure type safety. This avoids the need for explicit type casting and aligns with the design pattern of not modifying read-only memory in the perf tool. Reviewed-by: Ian Rogers Signed-off-by: Li Guan Cc: Adrian Hunter Cc: Namhyung Kim Cc: Palmer Dabbelt Cc: Paul Walmsley Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/riscv/util/header.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/arch/riscv/util/header.c b/tools/perf/arch/riscv/util/header.c index 4b839203d4a5..891984e909bd 100644 --- a/tools/perf/arch/riscv/util/header.c +++ b/tools/perf/arch/riscv/util/header.c @@ -19,7 +19,7 @@ static char *_get_field(const char *line) { - char *line2, *nl; + const char *line2, *nl; line2 = strrchr(line, ' '); if (!line2) From 65bd18199ad5358f7c879dc69b4de3671b33e62e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 19 May 2026 08:27:15 -0700 Subject: [PATCH 107/343] perf stat: Propagate supported flag to follower cgroup BPF events When using BPF counters with cgroups, follower events (for cgroups other than the first one) are not opened. Because they are not opened, their `supported` flag was left as `false`. During metric calculation, `prepare_metric` checks if the event is supported. If it is not supported (like the follower events), it explicitly sets the value to `NAN`, which eventually causes the metric to be reported as `nan %`. Fix this by propagating the `supported` flag from the "leader" events (the ones opened for the first cgroup) to the "follower" events. Also add a validation check to `bperf_load_program` to ensure `nr_cgroups` is not zero and the number of events is a multiple of `nr_cgroups`, preventing a potential division-by-zero (SIGFPE) exception when `num_events` evaluates to 0 (e.g., with a trailing comma in cgroups list). Reported-by: Svilen Kanev Assisted-by: Antigravity:gemini-3-flash Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf_counter_cgroup.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/perf/util/bpf_counter_cgroup.c b/tools/perf/util/bpf_counter_cgroup.c index 519fee3dc3d0..e1ce5aa3b957 100644 --- a/tools/perf/util/bpf_counter_cgroup.c +++ b/tools/perf/util/bpf_counter_cgroup.c @@ -104,6 +104,11 @@ static int bperf_load_program(struct evlist *evlist) set_max_rlimit(); + if (nr_cgroups == 0 || evlist->core.nr_entries % nr_cgroups != 0) { + pr_err("Invalid cgroup or event count\n"); + return -EINVAL; + } + test_max_events_program_load(); skel = bperf_cgroup_bpf__open(); @@ -186,6 +191,21 @@ static int bperf_load_program(struct evlist *evlist) i++; } + /* + * Propagate supported flag from leaders to followers. Follower events + * are not opened, so their supported flag remains false. + */ + { + struct evsel *leader; + int num_events = evlist->core.nr_entries / nr_cgroups; + + evlist__for_each_entry(evlist, evsel) { + leader = evlist__find_evsel(evlist, evsel->core.idx % num_events); + if (leader) + evsel->supported = leader->supported; + } + } + /* * bperf uses BPF_PROG_TEST_RUN to get accurate reading. Check * whether the kernel support it From bd2a5be1fe731bc7548205dd148db75f1d588da2 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 19 May 2026 08:27:16 -0700 Subject: [PATCH 108/343] perf test: Add stat metrics --for-each-cgroup test Add a new shell test `stat_metrics_cgrp.sh` to verify metric reporting with `--for-each-cgroup`, both with and without `--bpf-counters`. The test: - Checks if system-wide monitoring is supported (skips if not). - Finds cgroups to test. - Runs `perf stat` with `insn_per_cycle` metric and verifies that the metric is reported for each cgroup. - Dynamically pairs and verifies instructions and cycles counts to avoid false failures on idle cgroups. - Tests both standard mode and BPF counters mode (if supported). Assisted-by: Antigravity:gemini-3-flash Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Svilen Kanev Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/stat_metrics_cgrp.sh | 200 ++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100755 tools/perf/tests/shell/stat_metrics_cgrp.sh diff --git a/tools/perf/tests/shell/stat_metrics_cgrp.sh b/tools/perf/tests/shell/stat_metrics_cgrp.sh new file mode 100755 index 000000000000..d4226ee0ae98 --- /dev/null +++ b/tools/perf/tests/shell/stat_metrics_cgrp.sh @@ -0,0 +1,200 @@ +#!/bin/bash +# perf stat metrics --for-each-cgroup test +# SPDX-License-Identifier: GPL-2.0 + +set -e + +test_cgroups= + +log_verbose() { + echo "$1" +} + +is_numeric_and_non_zero() { + local val="$1" + if [[ "${val}" =~ ^[0-9]+$ ]] && [ "${val}" -gt 0 ] + then + return 0 # True + fi + return 1 # False +} + +# skip if system-wide is not supported +check_system_wide() +{ + log_verbose "Checking system-wide..." + if ! perf stat -a --metrics=insn_per_cycle sleep 0.01 > /dev/null 2>&1 + then + log_verbose "Skipping: system-wide monitoring not supported" + exit 2 + fi +} + +# find two cgroups to measure +find_cgroups() +{ + log_verbose "Finding cgroups..." + # try usual systemd slices first + if [ -d /sys/fs/cgroup/system.slice ] && [ -d /sys/fs/cgroup/user.slice ] + then + test_cgroups="system.slice,user.slice" + log_verbose "Found cgroups: ${test_cgroups}" + return + fi + + # try root and self cgroups + find_cgroups_self_cgrp=$(grep perf_event /proc/self/cgroup | cut -d: -f3) + if [ -z "${find_cgroups_self_cgrp}" ] + then + # cgroup v2 doesn't specify perf_event + find_cgroups_self_cgrp=$(grep ^0: /proc/self/cgroup | cut -d: -f3) + fi + + if [ -z "${find_cgroups_self_cgrp}" ] + then + test_cgroups="/" + else + test_cgroups="/,${find_cgroups_self_cgrp}" + fi + log_verbose "Found cgroups: ${test_cgroups}" +} + +# Check if metric is reported for each cgroup +# $1: extra options (e.g. --bpf-counters) +check_metric_reported() +{ + local opts="$1" + local output + + log_verbose "Running check_metric_reported with opts '${opts}'..." + # Run perf stat + if ! output=$(perf stat -a ${opts} \ + --metrics=insn_per_cycle \ + --for-each-cgroup "${test_cgroups}" \ + -x, sleep 0.1 2>&1) + then + echo "FAIL: perf stat failed with exit code $?" + echo "Output: ${output}" + exit 1 + fi + + log_verbose "perf stat output:" + log_verbose "${output}" + + # Split test_cgroups by comma + IFS=',' read -r -a cgrps <<< "${test_cgroups}" + + for cgrp in "${cgrps[@]}"; do + # Find metric lines for this cgroup + # We use exact cgroup match with surrounding commas + local cgrp_lines + cgrp_lines=$(echo "${output}" | grep -F ",${cgrp}," | grep "insn_per_cycle" || true) + + if [ -z "${cgrp_lines}" ] + then + echo "FAIL: No metric lines found for cgroup '${cgrp}'" + exit 1 + fi + + # Parse each metric line + while read -r line; do + [ -z "${line}" ] && continue + + local val1 + val1=$(echo "${line}" | cut -d, -f1) + + local event_name + event_name=$(echo "${line}" | cut -d, -f3) + + local cycles_val="" + local inst_val="" + + if echo "${event_name}" | grep -q -i "cycles" + then + cycles_val="${val1}" + # Find corresponding instructions event + local inst_event_name + inst_event_name="${event_name/cpu-cycles/instructions}" + inst_event_name="${inst_event_name/cycles/instructions}" + + local inst_line + inst_line=$(echo "${output}" | \ + grep -F ",${cgrp}," | \ + grep -F "${inst_event_name}" || true) + inst_val=$(echo "${inst_line}" | cut -d, -f1) + elif echo "${event_name}" | grep -q -i "instructions" + then + inst_val="${val1}" + # Find corresponding cycles event (try cpu-cycles + # first, then cycles) + local cycles_event_name + cycles_event_name="${event_name/instructions/cpu-cycles}" + local cycles_line + cycles_line=$(echo "${output}" | \ + grep -F ",${cgrp}," | \ + grep -F "${cycles_event_name}" || true) + + if [ -z "${cycles_line}" ] + then + # Try "cycles" instead of "cpu-cycles" + cycles_event_name="${event_name/instructions/cycles}" + cycles_line=$(echo "${output}" | \ + grep -F ",${cgrp}," | \ + grep -F "${cycles_event_name}" || true) + fi + cycles_val=$(echo "${cycles_line}" | cut -d, -f1) + fi + + log_verbose "Cgroup '${cgrp}': event '${event_name}' \ +val '${cycles_val}', inst val '${inst_val}'" + + # Only enforce metric check if both cycles and + # instructions have non-zero numeric counts + if is_numeric_and_non_zero "${cycles_val}" && \ + is_numeric_and_non_zero "${inst_val}" + then + log_verbose "Enforcing metric check for cgroup '${cgrp}' \ +event '${event_name}'" + # Check for nan or nested in the metric value (7th field) + # Actually we can just check the whole line for simplicity + if echo "${line}" | grep -q -i -E ",nan,|,nested," + then + echo "FAIL: Invalid metric value (nan/nested) \ +for cgroup '${cgrp}'" + echo "Line: ${line}" + exit 1 + fi + # Check for empty metric value (2 consecutive + # commas before the unit) + if echo "${line}" | grep -q -E ",,[[:space:]]*[^,]*insn_per_cycle" + then + echo "FAIL: Empty metric value for cgroup '${cgrp}'" + echo "Line: ${line}" + exit 1 + fi + else + log_verbose "Skipping metric check for cgroup '${cgrp}' \ +event '${event_name}' (idle or not counted)" + fi + done <<< "${cgrp_lines}" + done + log_verbose "check_metric_reported passed for opts '${opts}'" +} + +check_system_wide +find_cgroups + +# Test 1: Without BPF counters +check_metric_reported "" + +# Test 2: With BPF counters (if supported) +log_verbose "Checking BPF support..." +if perf stat -a --bpf-counters --for-each-cgroup / true > /dev/null 2>&1 +then + log_verbose "BPF supported, running Test 2..." + check_metric_reported "--bpf-counters" +else + log_verbose "BPF not supported, skipping Test 2" +fi + +exit 0 From 789d22d77879eabb042627f6627cdb62787bc142 Mon Sep 17 00:00:00 2001 From: Athira Rajeev Date: Mon, 4 May 2026 20:43:20 +0530 Subject: [PATCH 109/343] powerpc tools perf: Initialize error code in auxtrace_record_init function perf trace record fails some cases in powerpc # perf test "perf trace record and replay" 128: perf trace record and replay : FAILED! # perf trace record sleep 1 # echo $? 32 This is happening because of non-zero err value from auxtrace_record__init() function. static int record__auxtrace_init(struct record *rec) { int err; if ((rec->opts.auxtrace_snapshot_opts || rec->opts.auxtrace_sample_opts) && record__threads_enabled(rec)) { pr_err("AUX area tracing options are not available in parallel streaming mode.\n"); return -EINVAL; } if (!rec->itr) { rec->itr = auxtrace_record__init(rec->evlist, &err); if (err) return err; } Here "int err" is not initialised. The code expects "err" to be set from auxtrace_record__init() function. Update auxtrace_record__init() in arch/powerpc/util/auxtrace.c to clear err value in the beginning. - Clear err value in beginning of function. Any fail later will set appropriate return code to err. - Even if we haven't found any event for auxtrace, perf record should continue for other events. NULL return will indicate that there is no auxtrace record initialized. - Not having "err" set here will affect monitoring of other events also because perf record will fail seeing random value in err. Set err to -EINVAL before invoking auxtrace_record__init() in builtin-record.c With the fix, # perf trace record sleep 1 [ perf record: Woken up 2 times to write data ] [ perf record: Captured and wrote 0.033 MB perf.data (228 samples) ] Fixes: 1dbfaf94cf66ec4b ("perf powerpc: Add basic CONFIG_AUXTRACE support for VPA pmu on powerpc") Reviewed-by: Adrian Hunter Signed-off-by: Athira Rajeev Acked-by: Namhyung Kim Cc: Athira Rajeev Cc: Hari Bathini Cc: Ian Rogers Cc: Jiri Olsa Cc: linuxppc-dev@lists.ozlabs.org Cc: Madhavan Srinivasan Cc: Michael Petlan Cc: Shivani Nittor Cc: Tanushree Shah Cc: Tejas Manhas Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/powerpc/util/auxtrace.c | 6 ++++++ tools/perf/builtin-record.c | 1 + 2 files changed, 7 insertions(+) diff --git a/tools/perf/arch/powerpc/util/auxtrace.c b/tools/perf/arch/powerpc/util/auxtrace.c index e39deff6c857..4600a1661b4f 100644 --- a/tools/perf/arch/powerpc/util/auxtrace.c +++ b/tools/perf/arch/powerpc/util/auxtrace.c @@ -71,6 +71,12 @@ struct auxtrace_record *auxtrace_record__init(struct evlist *evlist, struct evsel *pos; int found = 0; + /* + * Set err value to zero here. Any fail later + * will set appropriate return code to err. + */ + *err = 0; + evlist__for_each_entry(evlist, pos) { if (strstarts(pos->name, "vpa_dtl")) { found = 1; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index cc601796b2c8..4a30688699d5 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -866,6 +866,7 @@ static int record__auxtrace_init(struct record *rec) } if (!rec->itr) { + err = -EINVAL; rec->itr = auxtrace_record__init(rec->evlist, &err); if (err) return err; From 3ca7f9ef8fa1d96793b855d331e9fe06d47d2a60 Mon Sep 17 00:00:00 2001 From: Athira Rajeev Date: Mon, 4 May 2026 20:43:21 +0530 Subject: [PATCH 110/343] perf auxtrace: Add kernel-doc comment to auxtrace_record__init() function Add documentation comment describing the parameters and return code for auxtrace_record__init() in util/auxtrace.c Reviewed-by: Adrian Hunter Signed-off-by: Athira Rajeev Cc: Hari Bathini Cc: Ian Rogers Cc: Jiri Olsa Cc: Madhavan Srinivasan Cc: Michael Petlan Cc: Namhyung Kim Cc: Shivani Nittor Cc: Tanushree.Shah@ibm.com Cc: Tejas.Manhas1@ibm.com Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/auxtrace.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index a224687ffbc1..a9f007d47c0b 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -896,6 +896,21 @@ int auxtrace_parse_aux_action(struct evlist *evlist) return 0; } +/** + * auxtrace_record__init - Initialize an AUX area tracing record. + * @evlist: The list of events to check for AUX area tracing event. + * @err: Pointer to an integer to store return code. + * + * This function looks through the @evlist to determine which AUX area + * tracing hardware is being used and initializes the auxtrace_record + * structure. + * + * Return: + * a) A pointer to the struct auxtrace_record with @err = 0 on success. + * b) NULL with @err = 0 if no AUX area tracing event is found/supported + * (not considered an error). + * c) NULL with non-zero @err on actual auxtrace_record__init failure. + */ struct auxtrace_record *__weak auxtrace_record__init(struct evlist *evlist __maybe_unused, int *err) { From e987110f09d2817d74a5d624c7bfb620d2bb0d40 Mon Sep 17 00:00:00 2001 From: Rui Qi Date: Fri, 22 May 2026 16:26:03 +0800 Subject: [PATCH 111/343] perf: Extract is_ignored_kernel_symbol() for kernel mapping symbol filtering Mapping symbol filtering is scattered across multiple files with inconsistent checks. The kernel's own is_mapping_symbol() covers x86 local symbols ('.L*' and 'L0*') on top of the '$' prefix used by ARM/AArch64/RISC-V, but the perf tool only checks '$'. Extract is_ignored_kernel_symbol() into symbol.h matching the kernel definition, and convert the kallsyms and ksymbol event paths to use it. Add ksymbol event name validation and early mapping symbol filtering before any state mutation. Signed-off-by: Rui Qi Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 18 +++++++++++++++++- tools/perf/util/symbol.c | 4 ++-- tools/perf/util/symbol.h | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index c2e0a99efe97..e5d1e8b882a9 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "callchain.h" #include "debug.h" #include "dso.h" @@ -729,9 +730,15 @@ static int machine__process_ksymbol_register(struct machine *machine, { struct symbol *sym; struct dso *dso = NULL; - struct map *map = maps__find(machine__kernel_maps(machine), event->ksymbol.addr); + struct map *map; int err = 0; + /* Ignore mapping symbols in ksymbol events - check early before any state mutation */ + if (is_ignored_kernel_symbol(event->ksymbol.name)) + return 0; + + map = maps__find(machine__kernel_maps(machine), event->ksymbol.addr); + if (!map) { dso = dso__new(event->ksymbol.name); @@ -790,6 +797,10 @@ static int machine__process_ksymbol_unregister(struct machine *machine, struct symbol *sym; struct map *map; + /* Ignore mapping symbols in ksymbol events */ + if (is_ignored_kernel_symbol(event->ksymbol.name)) + return 0; + map = maps__find(machine__kernel_maps(machine), event->ksymbol.addr); if (!map) return 0; @@ -814,6 +825,11 @@ int machine__process_ksymbol(struct machine *machine __maybe_unused, if (dump_trace) perf_event__fprintf_ksymbol(event, stdout); + if (event->header.size < offsetof(struct perf_record_ksymbol, name) + 2 || + !memchr(event->ksymbol.name, '\0', + event->header.size - offsetof(struct perf_record_ksymbol, name))) + return -EINVAL; + /* no need to process non-JIT BPF as it cannot get samples */ if (event->ksymbol.len == 0) return 0; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fcaeeddbbb6b..714b6e6048fa 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -770,8 +770,8 @@ static int map__process_kallsym_symbol(void *arg, const char *name, if (!symbol_type__filter(type)) return 0; - /* Ignore local symbols for ARM modules */ - if (name[0] == '$') + /* Ignore mapping symbols in kallsyms */ + if (is_ignored_kernel_symbol(name)) return 0; /* diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index bd6eb90c8668..95592779eb77 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -28,6 +28,21 @@ struct maps; struct option; struct build_id; +/* + * Ignore kernel mapping symbols, matching kernel is_mapping_symbol() logic. + * This checks for '$' prefix (used by ARM, AArch64, RISC-V) and + * x86 local symbol prefixes (.L* and L0*). + * Only use this for kernel symbols (kallsyms, ksymbol events, kernel ELF DSOs). + */ +static inline bool is_ignored_kernel_symbol(const char *str) +{ + if (str[0] == '.' && str[1] == 'L') + return true; + if (str[0] == 'L' && str[1] == '0') + return true; + return str[0] == '$'; +} + /* * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; * for newer versions we can use mmap to reduce memory usage: From 43b16bf3e7306b4c9ec1aa804872b32a969f5777 Mon Sep 17 00:00:00 2001 From: Rui Qi Date: Fri, 22 May 2026 16:26:04 +0800 Subject: [PATCH 112/343] perf: Apply is_ignored_kernel_symbol() filter in ELF loading path for kernel DSOs dso__load_sym_internal() had no filtering for .L* and L0* mapping symbols while the kallsyms path already filters them via is_ignored_kernel_symbol(). Add the same check gated by dso__kernel() so that kernel ELF objects (vmlinux, .ko) have mapping symbols filtered across all architectures, but userspace ELF objects are unaffected -- '$' is a valid prefix in languages like Java and Scala. The existing ARM/AArch64 and RISC-V architecture-specific mapping symbol checks are preserved; the new is_ignored_kernel_symbol() check adds x86 local symbol (.L*, L0*) filtering and provides unified cross-architecture coverage for kernel DSOs. Signed-off-by: Rui Qi Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 7afa8a117139..77e6dcba8fda 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1592,9 +1592,11 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss, if (!is_label && !elf_sym__filter(&sym)) continue; - /* Reject ARM ELF "mapping symbols": these aren't unique and + /* + * Reject ARM ELF "mapping symbols": these aren't unique and * don't identify functions, so will confuse the profile - * output: */ + * output: + */ if (ehdr.e_machine == EM_ARM || ehdr.e_machine == EM_AARCH64) { if (elf_name[0] == '$' && strchr("adtx", elf_name[1]) && (elf_name[2] == '\0' || elf_name[2] == '.')) @@ -1607,6 +1609,10 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss, continue; } + /* Reject kernel mapping symbols for kernel DSOs only */ + if (dso__kernel(dso) && is_ignored_kernel_symbol(elf_name)) + continue; + if (runtime_ss->opdsec && sym.st_shndx == runtime_ss->opdidx) { u32 offset = sym.st_value - syms_ss->opdshdr.sh_addr; u64 *opd = opddata->d_buf + offset; From 390d5ea26622f794c2d29cefd5a01ef116b4fe1d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 22 May 2026 15:04:12 -0700 Subject: [PATCH 113/343] perf arch arm: Sort includes and add missed explicit dependencies Fix missing #includes found while cleaning the evsel/evlist header files. Sort the remaining header files for consistency with the rest of the code. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alice Rogers Cc: Dapeng Mi Cc: Ingo Molnar Cc: James Clark Cc: Leo Yan Cc: Peter Zijlstra Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index b7a839de8707..cdf8e3e60606 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -3,10 +3,13 @@ * Copyright(C) 2015 Linaro Limited. All rights reserved. * Author: Mathieu Poirier */ +#include "../../../util/cs-etm.h" + +#include +#include -#include -#include #include +#include #include #include #include @@ -14,25 +17,24 @@ #include #include #include +#include + +#include +#include // page_size -#include "cs-etm.h" -#include "../../../util/debug.h" -#include "../../../util/record.h" #include "../../../util/auxtrace.h" #include "../../../util/cpumap.h" +#include "../../../util/debug.h" #include "../../../util/event.h" #include "../../../util/evlist.h" #include "../../../util/evsel.h" -#include "../../../util/perf_api_probe.h" #include "../../../util/evsel_config.h" +#include "../../../util/perf_api_probe.h" +#include "../../../util/pmu.h" #include "../../../util/pmus.h" -#include "../../../util/cs-etm.h" -#include // page_size +#include "../../../util/record.h" #include "../../../util/session.h" - -#include -#include -#include +#include "cs-etm.h" struct cs_etm_recording { struct auxtrace_record itr; From 03f5a800545eb483308988b578f8f8543aaf9c86 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 22 May 2026 15:04:13 -0700 Subject: [PATCH 114/343] perf arch x86: Sort includes and add missed explicit dependencies Fix missing #includes found while cleaning the evsel/evlist header files. Sort the remaining header files for consistency with the rest of the code. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alice Rogers Cc: Dapeng Mi Cc: Ingo Molnar Cc: James Clark Cc: Leo Yan Cc: Peter Zijlstra Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/intel-bts.c | 32 ++++++++++++++----------- tools/perf/arch/x86/util/intel-pt.c | 35 +++++++++++++++------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index 85c8186300c8..100a23d27998 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -4,27 +4,31 @@ * Copyright (c) 2013-2015, Intel Corporation. */ +#include "../../../util/intel-bts.h" + #include -#include -#include + #include +#include #include +#include #include -#include "../../../util/cpumap.h" -#include "../../../util/event.h" -#include "../../../util/evsel.h" -#include "../../../util/evlist.h" -#include "../../../util/mmap.h" -#include "../../../util/session.h" -#include "../../../util/pmus.h" -#include "../../../util/debug.h" -#include "../../../util/record.h" -#include "../../../util/tsc.h" -#include "../../../util/auxtrace.h" -#include "../../../util/intel-bts.h" #include // page_size +#include "../../../util/auxtrace.h" +#include "../../../util/cpumap.h" +#include "../../../util/debug.h" +#include "../../../util/event.h" +#include "../../../util/evlist.h" +#include "../../../util/evsel.h" +#include "../../../util/mmap.h" +#include "../../../util/pmu.h" +#include "../../../util/pmus.h" +#include "../../../util/record.h" +#include "../../../util/session.h" +#include "../../../util/tsc.h" + #define KiB(x) ((x) * 1024) #define MiB(x) ((x) * 1024 * 1024) #define KiB_MASK(x) (KiB(x) - 1) diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index c131a727774f..0307ff15d9fc 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -3,36 +3,39 @@ * intel_pt.c: Intel Processor Trace support * Copyright (c) 2013-2015, Intel Corporation. */ +#include "../../../util/intel-pt.h" #include #include -#include -#include -#include -#include -#include -#include -#include "../../../util/session.h" +#include +#include +#include +#include +#include +#include + +#include +#include // page_size +#include + +#include "../../../util/auxtrace.h" +#include "../../../util/config.h" +#include "../../../util/cpumap.h" +#include "../../../util/debug.h" #include "../../../util/event.h" #include "../../../util/evlist.h" #include "../../../util/evsel.h" #include "../../../util/evsel_config.h" -#include "../../../util/config.h" -#include "../../../util/cpumap.h" #include "../../../util/mmap.h" -#include #include "../../../util/parse-events.h" -#include "../../../util/pmus.h" -#include "../../../util/debug.h" -#include "../../../util/auxtrace.h" #include "../../../util/perf_api_probe.h" +#include "../../../util/pmu.h" +#include "../../../util/pmus.h" #include "../../../util/record.h" +#include "../../../util/session.h" #include "../../../util/target.h" #include "../../../util/tsc.h" -#include // page_size -#include "../../../util/intel-pt.h" -#include #include "cpuid.h" #define KiB(x) ((x) * 1024) From 7b1aa97e976953141486a943ed47acdc19209d1e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 22 May 2026 15:04:14 -0700 Subject: [PATCH 115/343] perf tests: Sort includes and add missed explicit dependencies Fix missing #includes found while cleaning the evsel/evlist header files. Sort the remaining header files for consistency with the rest of the code. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alice Rogers Cc: Dapeng Mi Cc: Ingo Molnar Cc: James Clark Cc: Leo Yan Cc: Peter Zijlstra Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/hwmon_pmu.c | 14 +++++++++----- tools/perf/tests/mmap-basic.c | 18 +++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/tools/perf/tests/hwmon_pmu.c b/tools/perf/tests/hwmon_pmu.c index 4aa4aac94f09..ada6e445c4c4 100644 --- a/tools/perf/tests/hwmon_pmu.c +++ b/tools/perf/tests/hwmon_pmu.c @@ -1,15 +1,19 @@ // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -#include "debug.h" -#include "evlist.h" #include "hwmon_pmu.h" -#include "parse-events.h" -#include "tests.h" + #include + #include -#include #include #include #include +#include + +#include "debug.h" +#include "evlist.h" +#include "parse-events.h" +#include "pmus.h" +#include "tests.h" static const struct test_event { const char *name; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index a18d84d858aa..a69cd1046e9a 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -1,25 +1,29 @@ // SPDX-License-Identifier: GPL-2.0 #include -#include #include #include + +#include +#include +#include +#include + #include +#include +#include #include "cpumap.h" #include "debug.h" #include "event.h" #include "evlist.h" #include "evsel.h" -#include "thread_map.h" +#include "pmu.h" +#include "pmus.h" #include "tests.h" +#include "thread_map.h" #include "util/affinity.h" #include "util/mmap.h" #include "util/sample.h" -#include -#include -#include -#include -#include /* * This test will generate random numbers of calls to some getpid syscalls, From 60d69f2c4e283bddcbb9b37778222b78ec4067f6 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 22 May 2026 15:04:15 -0700 Subject: [PATCH 116/343] perf script: Sort includes and add missed explicit dependencies Fix missing #include of pmu.h found while cleaning the evsel/evlist header files. Sort the remaining header files for consistency with the rest of the code. Doing this exposed a missing forward declaration of addr_location in print_insn.h, add this and sort the forward declarations. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alice Rogers Cc: Dapeng Mi Cc: Ingo Molnar Cc: James Clark Cc: Leo Yan Cc: Peter Zijlstra Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 123 ++++++++++++++++++----------------- tools/perf/util/print_insn.h | 5 +- 2 files changed, 66 insertions(+), 62 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index c0918006e0ab..e330ae7f725e 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1,75 +1,78 @@ // SPDX-License-Identifier: GPL-2.0 -#include "builtin.h" - -#include "util/counts.h" -#include "util/debug.h" -#include "util/dso.h" -#include -#include "util/header.h" -#include -#include "util/perf_regs.h" -#include "util/session.h" -#include "util/tool.h" -#include "util/map.h" -#include "util/srcline.h" -#include "util/symbol.h" -#include "util/thread.h" -#include "util/trace-event.h" -#include "util/env.h" -#include "util/evlist.h" -#include "util/evsel.h" -#include "util/evsel_fprintf.h" -#include "util/evswitch.h" -#include "util/sort.h" -#include "util/data.h" -#include "util/auxtrace.h" -#include "util/cpumap.h" -#include "util/thread_map.h" -#include "util/stat.h" -#include "util/color.h" -#include "util/string2.h" -#include "util/thread-stack.h" -#include "util/time-utils.h" -#include "util/path.h" -#include "util/event.h" -#include "util/mem-info.h" -#include "util/metricgroup.h" -#include "ui/ui.h" -#include "print_binary.h" -#include "print_insn.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "asm/bug.h" -#include "util/mem-events.h" -#include "util/dump-insn.h" -#include #include #include #include #include -#include -#include -#include + +#include #include -#include -#include -#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "asm/bug.h" +#include "builtin.h" +#include "perf.h" +#include "print_binary.h" +#include "print_insn.h" +#include "ui/ui.h" +#include "util/annotate.h" +#include "util/auxtrace.h" +#include "util/cgroup.h" +#include "util/color.h" +#include "util/counts.h" +#include "util/cpumap.h" +#include "util/data.h" +#include "util/debug.h" #include "util/dlfilter.h" +#include "util/dso.h" +#include "util/dump-insn.h" +#include "util/env.h" +#include "util/event.h" +#include "util/evlist.h" +#include "util/evsel.h" +#include "util/evsel_fprintf.h" +#include "util/evswitch.h" +#include "util/header.h" +#include "util/map.h" +#include "util/mem-events.h" +#include "util/mem-info.h" +#include "util/metricgroup.h" +#include "util/path.h" +#include "util/perf_regs.h" +#include "util/pmu.h" #include "util/record.h" +#include "util/session.h" +#include "util/sort.h" +#include "util/srcline.h" +#include "util/stat.h" +#include "util/string2.h" +#include "util/symbol.h" +#include "util/thread-stack.h" +#include "util/thread.h" +#include "util/thread_map.h" +#include "util/time-utils.h" +#include "util/tool.h" +#include "util/trace-event.h" #include "util/unwind.h" #include "util/util.h" -#include "util/cgroup.h" -#include "util/annotate.h" -#include "perf.h" -#include #ifdef HAVE_LIBTRACEEVENT #include #endif diff --git a/tools/perf/util/print_insn.h b/tools/perf/util/print_insn.h index 07d11af3fc1c..a54f7e858e49 100644 --- a/tools/perf/util/print_insn.h +++ b/tools/perf/util/print_insn.h @@ -5,10 +5,11 @@ #include #include -struct perf_sample; -struct thread; +struct addr_location; struct machine; struct perf_insn; +struct perf_sample; +struct thread; #define PRINT_INSN_IMM_HEX (1<<0) From 1f9d9b62cfd54fb06df9b5f2f2868324bee3aab4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 27 May 2026 13:19:33 -0300 Subject: [PATCH 117/343] perf tests hwmon_pmu: Use PRIu64 + (uint64_t) cast for a __u64 field to work more widely MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While testing perf with an updated Debian experimental cross compiler (gcc version 14.2.0 (Debian 14.2.0-13)) this started failing: In file included from tests/hwmon_pmu.c:12: tests/hwmon_pmu.c: In function 'do_test': tests/hwmon_pmu.c:199:34: error: format '%lld' expects argument of type 'long long int', but argument 7 has type '__u64' {aka 'long unsigned int'} [-Werror=format=] 199 | pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %ld\n", | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /git/perf-7.1.0-rc5/tools/perf/util/debug.h:20:21: note: in definition of macro 'pr_fmt' 20 | #define pr_fmt(fmt) fmt | ^~~ tests/hwmon_pmu.c:199:25: note: in expansion of macro 'pr_debug' 199 | pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %ld\n", | ^~~~~~~~ tests/hwmon_pmu.c:199:79: note: format string is defined here 199 | pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %ld\n", | ~~~^ | | | long long int | %ld LD /tmp/build/perf/util/intel-pt-decoder/perf-util-in.o The usual make that %lld a PRIu64 (since arg7 is evsel->core.attr.config, which is a __u64) but then on Fedora 44 (gcc version 16.1.1 20260515 (Red Hat 16.1.1-2)) it ends up with: In file included from tests/hwmon_pmu.c:13: tests/hwmon_pmu.c: In function ‘do_test’: tests/hwmon_pmu.c:200:34: error: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 7 has type ‘__u64’ {aka ‘long long unsigned int’} [-Werror=format=] 200 | pr_debug("FAILED %s:%d Unexpected config for '%s', %" PRIu64 " != %ld\n", | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/acme/git/perf-tools-next2/tools/perf/util/debug.h:20:21: note: in definition of macro ‘pr_fmt’ 20 | #define pr_fmt(fmt) fmt | ^~~ tests/hwmon_pmu.c:200:25: note: in expansion of macro ‘pr_debug’ 200 | pr_debug("FAILED %s:%d Unexpected config for '%s', %" PRIu64 " != %ld\n", | ^~~~~~~~ cc1: all warnings being treated as errors So the way to satisfy both compilers is to also add a (u64) cast to arg7. Cc: Adrian Hunter Cc: Ian Rogers Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/hwmon_pmu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/hwmon_pmu.c b/tools/perf/tests/hwmon_pmu.c index ada6e445c4c4..62e0841a6c31 100644 --- a/tools/perf/tests/hwmon_pmu.c +++ b/tools/perf/tests/hwmon_pmu.c @@ -2,6 +2,7 @@ #include "hwmon_pmu.h" #include +#include #include #include @@ -196,9 +197,9 @@ static int do_test(size_t i, bool with_pmu, bool with_alias) continue; if (evsel->core.attr.config != (u64)test_events[i].key.type_and_num) { - pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %ld\n", + pr_debug("FAILED %s:%d Unexpected config for '%s', %" PRIu64 " != %ld\n", __FILE__, __LINE__, str, - evsel->core.attr.config, + (uint64_t)evsel->core.attr.config, test_events[i].key.type_and_num); ret = TEST_FAIL; goto out; From da27c4379ce6b2b7d5d3359e9b10c829b9e5dbbe Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 5 May 2026 12:36:18 -0300 Subject: [PATCH 118/343] perf session: Add minimum event size and alignment validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a per-type minimum size table (perf_event__min_size[]) and enforce it before swap and processing, so that both cross-endian and native-endian paths are protected from accessing fields past the event boundary. The table uses offsetof() for types with trailing variable-length fields (filenames, strings, msg arrays) and sizeof() for fixed-size types. Zero entries mean no minimum beyond the 8-byte header already enforced by the reader. Undersized events are skipped with a warning in process_event and rejected in peek_event — both checked before the swap handler runs, preventing OOB access on crafted event fields. Also reject events whose header.size is not 8-byte aligned. The kernel aligns all event sizes to sizeof(u64) — see perf_event_comm_event() (ALIGN), perf_event_mmap_event(), perf_event_cgroup(), perf_event_ksymbol() (IS_ALIGNED loops), and perf_event_text_poke() (ALIGN) in kernel/events/core.c. An unaligned size means the file is corrupted or crafted; reject early so downstream code that divides by sizeof(u64) to compute array element counts gets exact results. Three legacy user events are exempted from the alignment check: TRACING_DATA (66) had a 12-byte struct before commit b39c915a4f36 ("libperf event: Ensure tracing data is multiple of 8 sized") added padding, COMPRESSED (81) carries raw ZSTD output (already superseded by COMPRESSED2 with PERF_ALIGN), and HEADER_FEATURE (80) uses do_write_string() with a 4-byte length prefix. Also guard event_swap() against crafted event types >= PERF_RECORD_HEADER_MAX to prevent OOB reads on the perf_event__swap_ops[] array. Changes in v2: - Fix double-skip for unsupported event types: return 0 instead of event->header.size in perf_session__process_event() for HEADER_MAX, since reader__read_event() already advances by event->header.size (Reported-by: sashiko-bot@kernel.org) - Exempt TRACING_DATA, COMPRESSED, and HEADER_FEATURE from the alignment check — these legacy user events predate the 8-byte alignment rule (Reported-by: sashiko-bot@kernel.org) - peek_event: return 0 (skip) for unknown event types instead of -1 (error), consistent with process_event which already skips unsupported types gracefully (Reported-by: sashiko-bot@kernel.org) Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 263 ++++++++++++++++++++++++++++++++------ 1 file changed, 225 insertions(+), 38 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1e25892963b7..0523fd243e02 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1759,15 +1759,121 @@ int perf_session__deliver_synth_attr_event(struct perf_session *session, return perf_session__deliver_synth_event(session, &ev.ev, NULL); } +/* + * Minimum event sizes indexed by type. Checked before swap and + * processing so that both cross-endian and native-endian paths + * are protected from accessing fields past the event boundary. + * Zero means no minimum beyond the 8-byte header (already + * enforced by the reader). + */ +static const u32 perf_event__min_size[PERF_RECORD_HEADER_MAX] = { + /* + * offsetof() + 1 for types with a trailing variable-length + * string (filename, comm, path, name, msg): the +1 ensures + * room for at least a null terminator. Full null-termination + * within the event boundary is checked separately. + * + * PERF_RECORD_SAMPLE is omitted: all64_swap is bounded by + * header.size, and the internal layout varies by sample_type + * so a fixed minimum is not meaningful. + */ + [PERF_RECORD_MMAP] = offsetof(struct perf_record_mmap, filename) + 1, + [PERF_RECORD_LOST] = sizeof(struct perf_record_lost), + [PERF_RECORD_COMM] = offsetof(struct perf_record_comm, comm) + 1, + [PERF_RECORD_EXIT] = sizeof(struct perf_record_fork), + [PERF_RECORD_THROTTLE] = sizeof(struct perf_record_throttle), + [PERF_RECORD_UNTHROTTLE] = sizeof(struct perf_record_throttle), + [PERF_RECORD_FORK] = sizeof(struct perf_record_fork), + /* + * The kernel dynamically sizes PERF_RECORD_READ based on + * attr.read_format — the minimum has just pid + tid + value. + */ + [PERF_RECORD_READ] = offsetof(struct perf_record_read, time_enabled), + [PERF_RECORD_MMAP2] = offsetof(struct perf_record_mmap2, filename) + 1, + [PERF_RECORD_LOST_SAMPLES] = sizeof(struct perf_record_lost_samples), + [PERF_RECORD_AUX] = sizeof(struct perf_record_aux), + [PERF_RECORD_ITRACE_START] = sizeof(struct perf_record_itrace_start), + [PERF_RECORD_SWITCH] = sizeof(struct perf_event_header), + [PERF_RECORD_SWITCH_CPU_WIDE] = sizeof(struct perf_record_switch), + [PERF_RECORD_NAMESPACES] = sizeof(struct perf_record_namespaces), + [PERF_RECORD_CGROUP] = offsetof(struct perf_record_cgroup, path) + 1, + [PERF_RECORD_TEXT_POKE] = sizeof(struct perf_record_text_poke_event), + [PERF_RECORD_KSYMBOL] = offsetof(struct perf_record_ksymbol, name) + 1, + [PERF_RECORD_BPF_EVENT] = sizeof(struct perf_record_bpf_event), + [PERF_RECORD_HEADER_ATTR] = sizeof(struct perf_event_header) + PERF_ATTR_SIZE_VER0, + [PERF_RECORD_HEADER_EVENT_TYPE] = sizeof(struct perf_record_header_event_type), + /* Legacy events predate the __u32 pad field, accept 12-byte records */ + [PERF_RECORD_HEADER_TRACING_DATA] = offsetof(struct perf_record_header_tracing_data, pad), + [PERF_RECORD_AUX_OUTPUT_HW_ID] = sizeof(struct perf_record_aux_output_hw_id), + [PERF_RECORD_AUXTRACE_INFO] = sizeof(struct perf_record_auxtrace_info), + [PERF_RECORD_AUXTRACE] = sizeof(struct perf_record_auxtrace), + [PERF_RECORD_AUXTRACE_ERROR] = offsetof(struct perf_record_auxtrace_error, msg) + 1, + [PERF_RECORD_THREAD_MAP] = sizeof(struct perf_record_thread_map), + /* Smallest valid variant is RANGE_CPUS: header(8) + type(2) + range(6) */ + [PERF_RECORD_CPU_MAP] = sizeof(struct perf_event_header) + + sizeof(__u16) + + sizeof(struct perf_record_range_cpu_map), + [PERF_RECORD_STAT_CONFIG] = sizeof(struct perf_record_stat_config), + [PERF_RECORD_STAT] = sizeof(struct perf_record_stat), + [PERF_RECORD_STAT_ROUND] = sizeof(struct perf_record_stat_round), + /* Union inflates sizeof; use fixed header fields as minimum */ + [PERF_RECORD_EVENT_UPDATE] = offsetof(struct perf_record_event_update, scale), + [PERF_RECORD_TIME_CONV] = offsetof(struct perf_record_time_conv, time_cycles), + [PERF_RECORD_ID_INDEX] = sizeof(struct perf_record_id_index), + [PERF_RECORD_HEADER_BUILD_ID] = sizeof(struct perf_record_header_build_id), + [PERF_RECORD_HEADER_FEATURE] = sizeof(struct perf_record_header_feature), + [PERF_RECORD_COMPRESSED2] = sizeof(struct perf_record_compressed2), + [PERF_RECORD_BPF_METADATA] = sizeof(struct perf_record_bpf_metadata), + [PERF_RECORD_CALLCHAIN_DEFERRED] = sizeof(struct perf_event_header) + sizeof(__u64), + /* + * SCHEDSTAT events have a version-dependent union after the + * fixed header fields; the minimum is the base (pre-union) + * portion so old and new versions both pass. + */ + [PERF_RECORD_SCHEDSTAT_CPU] = offsetof(struct perf_record_schedstat_cpu, v15), + [PERF_RECORD_SCHEDSTAT_DOMAIN] = offsetof(struct perf_record_schedstat_domain, v15), +}; + +/* + * Return true if the event is too small for its declared type. + * Caller must ensure event->header.type < PERF_RECORD_HEADER_MAX. + * If min is non-NULL, stores the required minimum on failure. + */ +static bool perf_event__too_small(const union perf_event *event, u32 *min) +{ + u32 min_sz = perf_event__min_size[event->header.type]; + + if (min_sz && event->header.size < min_sz) { + if (min) + *min = min_sz; + return true; + } + + return false; +} + +/* Caller must ensure event->header.type < PERF_RECORD_HEADER_MAX */ static void event_swap(union perf_event *event, bool sample_id_all) { - perf_event__swap_op swap; - - swap = perf_event__swap_ops[event->header.type]; + perf_event__swap_op swap = perf_event__swap_ops[event->header.type]; if (swap) swap(event, sample_id_all); } +/* + * Read and validate the event at @file_offset. + * + * Returns: + * 0 — success: *event_ptr is set and safe to access. + * -1 — error; check *event_ptr to decide whether to advance or abort: + * *event_ptr set — event header was read but the event is + * malformed (too small for its type, or byte-swap + * failed). header.size is still valid, so the + * caller can advance past the event. + * *event_ptr NULL — fatal: couldn't read the header at all + * (I/O error, offset out of range, pipe mode). + * Caller must abort. + */ int perf_session__peek_event(struct perf_session *session, off_t file_offset, void *buf, size_t buf_sz, union perf_event **event_ptr, @@ -1775,52 +1881,85 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, { union perf_event *event; size_t hdr_sz, rest; + u32 min_sz; int fd; + *event_ptr = NULL; + if (session->one_mmap && !session->header.needs_swap) { event = file_offset - session->one_mmap_offset + session->one_mmap_addr; - goto out_parse_sample; + + /* Every event must at least contain its own header */ + if (event->header.size < sizeof(struct perf_event_header)) + return -1; + } else { + if (perf_data__is_pipe(session->data)) + return -1; + + fd = perf_data__fd(session->data); + hdr_sz = sizeof(struct perf_event_header); + + if (buf_sz < hdr_sz) + return -1; + + if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 || + readn(fd, buf, hdr_sz) != (ssize_t)hdr_sz) + return -1; + + event = (union perf_event *)buf; + + if (session->header.needs_swap) + perf_event_header__bswap(&event->header); + + if (event->header.size < hdr_sz || event->header.size > buf_sz) + return -1; + + buf += hdr_sz; + rest = event->header.size - hdr_sz; + + if (readn(fd, buf, rest) != (ssize_t)rest) + return -1; } - if (perf_data__is_pipe(session->data)) + /* Event data is fully loaded — expose so callers can advance */ + *event_ptr = event; + + /* + * Check alignment before type: an unaligned size misaligns the + * stream for all subsequent reads regardless of event type. + * Three legacy user events predate the 8-byte rule — exempt them. + */ + if (event->header.size % sizeof(u64) && + event->header.type != PERF_RECORD_HEADER_TRACING_DATA && + event->header.type != PERF_RECORD_COMPRESSED && + event->header.type != PERF_RECORD_HEADER_FEATURE) { + pr_warning("WARNING: peek_event: event type %u size %u not aligned to %zu\n", + event->header.type, + event->header.size, sizeof(u64)); return -1; + } - fd = perf_data__fd(session->data); - hdr_sz = sizeof(struct perf_event_header); + if (event->header.type >= PERF_RECORD_HEADER_MAX) { + pr_warning("WARNING: peek_event: unsupported event type %u, skipping\n", + event->header.type); + return 0; + } - if (buf_sz < hdr_sz) - return -1; - - if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 || - readn(fd, buf, hdr_sz) != (ssize_t)hdr_sz) - return -1; - - event = (union perf_event *)buf; - - if (session->header.needs_swap) - perf_event_header__bswap(&event->header); - - if (event->header.size < hdr_sz || event->header.size > buf_sz) - return -1; - - buf += hdr_sz; - rest = event->header.size - hdr_sz; - - if (readn(fd, buf, rest) != (ssize_t)rest) + if (perf_event__too_small(event, &min_sz)) { + pr_warning("WARNING: peek_event: %s event size %u too small (min %u)\n", + perf_event__name(event->header.type), + event->header.size, min_sz); return -1; + } if (session->header.needs_swap) event_swap(event, evlist__sample_id_all(session->evlist)); -out_parse_sample: - if (sample && event->header.type < PERF_RECORD_USER_TYPE_START && evlist__parse_sample(session->evlist, event, sample)) return -1; - *event_ptr = event; - return 0; } @@ -1858,23 +1997,71 @@ static s64 perf_session__process_event(struct perf_session *session, { struct evlist *evlist = session->evlist; const struct perf_tool *tool = session->tool; + u32 min_sz; int ret; - if (session->header.needs_swap) - event_swap(event, evlist__sample_id_all(evlist)); + /* + * The kernel aligns all event sizes to sizeof(u64) — see + * perf_event_comm_event() (ALIGN), perf_event_mmap_event(), + * perf_event_cgroup(), perf_event_ksymbol() (IS_ALIGNED loops), + * and perf_event_text_poke() (ALIGN) in kernel/events/core.c. + * + * An unaligned size means the file is corrupted or crafted. + * Abort: there is no point continuing to read unaligned records + * because the caller advances rd->head by event->header.size, + * so every subsequent read would start at a misaligned offset, + * producing garbage headers for the rest of the file. + * + * Exempt three legacy user events that predate the alignment rule: + * + * TRACING_DATA (66): struct tracing_data_event was 12 bytes before + * b39c915a4f36 ("libperf event: Ensure tracing data is multiple + * of 8 sized") added __u32 pad; old perf.data files still contain + * 12-byte records. + * TODO: introduce HEADER_TRACING_DATA2 with guaranteed alignment. + * + * COMPRESSED (81): raw ZSTD output, arbitrary length. Already + * superseded by COMPRESSED2 (83) with PERF_ALIGN. + * + * HEADER_FEATURE (80): do_write_string() uses a 4-byte length + * prefix with no padding to 8-byte total. + * TODO: introduce HEADER_FEATURE2 with guaranteed alignment. + */ + if (event->header.size % sizeof(u64) && + event->header.type != PERF_RECORD_HEADER_TRACING_DATA && + event->header.type != PERF_RECORD_COMPRESSED && + event->header.type != PERF_RECORD_HEADER_FEATURE) { + pr_err("ERROR: %s event size %u is not 8-byte aligned, aborting\n", + perf_event__name(event->header.type), + event->header.size); + return -EINVAL; + } if (event->header.type >= PERF_RECORD_HEADER_MAX) { - /* perf should not support unaligned event, stop here. */ - if (event->header.size % sizeof(u64)) - return -EINVAL; - /* This perf is outdated and does not support the latest event type. */ ui__warning("Unsupported header type %u, please consider updating perf.\n", event->header.type); - /* Skip unsupported event by returning its size. */ - return event->header.size; + /* + * Return 0 to skip: the caller (reader__read_event) + * already advances by event->header.size. + */ + return 0; } + /* + * Skip rather than abort: a too-small-but-aligned event + * can be safely stepped over without misaligning the stream. + */ + if (perf_event__too_small(event, &min_sz)) { + pr_warning("WARNING: %s event size %u too small (min %u), skipping\n", + perf_event__name(event->header.type), + event->header.size, min_sz); + return 0; + } + + if (session->header.needs_swap) + event_swap(event, evlist__sample_id_all(evlist)); + events_stats__inc(&evlist->stats, event->header.type); if (event->header.type >= PERF_RECORD_USER_TYPE_START) From 1e389b7639f17e947ab9ed77bcba9f2ab7420f74 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 23 May 2026 08:06:35 -0300 Subject: [PATCH 119/343] perf session: Bounds-check one_mmap event pointer in peek_event perf_session__peek_event() computes an event pointer directly from file_offset when one_mmap is active, without verifying that file_offset and the subsequent event->header.size fall within the mapped region. A corrupted perf.data file could cause out-of-bounds memory reads. Add one_mmap_size to the session struct and validate both the header and full event fit within the mmap before dereferencing. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 29 ++++++++++++++++++++++++++--- tools/perf/util/session.h | 2 ++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0523fd243e02..c4cd8ad6d810 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1887,12 +1887,27 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, *event_ptr = NULL; if (session->one_mmap && !session->header.needs_swap) { - event = file_offset - session->one_mmap_offset + - session->one_mmap_addr; + u64 offset_in_mmap; + + /* Validate offset with integer arithmetic to avoid pointer UB */ + if ((u64)file_offset < session->one_mmap_offset) + return -1; + + offset_in_mmap = (u64)file_offset - session->one_mmap_offset; + + /* Use subtraction to avoid addition overflow */ + if (offset_in_mmap >= session->one_mmap_size || + session->one_mmap_size - offset_in_mmap < sizeof(struct perf_event_header)) + return -1; + + event = session->one_mmap_addr + offset_in_mmap; - /* Every event must at least contain its own header */ if (event->header.size < sizeof(struct perf_event_header)) return -1; + + /* Ensure full event is within the mmap region */ + if (session->one_mmap_size - offset_in_mmap < event->header.size) + return -1; } else { if (perf_data__is_pipe(session->data)) return -1; @@ -2560,6 +2575,14 @@ reader__mmap(struct reader *rd, struct perf_session *session) if (session->one_mmap) { session->one_mmap_addr = buf; session->one_mmap_offset = rd->file_offset; + /* + * mmap_size was set to the full file extent (data_offset + + * data_size) but file_offset was shifted forward by + * page_offset for page alignment. Reduce by page_offset + * so the bounds check reflects the file-backed portion + * of the mapping — pages beyond the file cause SIGBUS. + */ + session->one_mmap_size = rd->mmap_size - page_offset; } return 0; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index f05f0d4a6c23..d554e2a1a50e 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -71,6 +71,8 @@ struct perf_session { void *one_mmap_addr; /** @one_mmap_offset: File offset in perf.data file when mapped. */ u64 one_mmap_offset; + /** @one_mmap_size: Size of the single mmap in bytes. */ + u64 one_mmap_size; /** @ordered_events: Used to turn unordered events into ordered ones. */ struct ordered_events ordered_events; /** @data: Optional perf data file being read from. */ From 1a646a28a0063f1fb31589f7190f2b4fb613e413 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 May 2026 07:37:22 -0300 Subject: [PATCH 120/343] perf tools: Fix event_contains() macro to verify full field extent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit event_contains() checked whether a field's start offset was within the event (header.size > offsetof), but not whether the full field fit. A crafted event with header.size = offsetof(field) + 1 would pass the check, but an 8-byte access (bswap_64, direct read) would overrun the event boundary by up to 7 bytes. Fix the macro to verify the complete field: header.size >= offsetof(field) + sizeof(field) Also update all callers that check event_contains(time_cycles) but access later fields (time_mask, cap_user_time_zero, cap_user_time_short) to check for cap_user_time_short — the last field accessed — so the entire extended block is verified: tsc.c, arm-spe.c, cs-etm.c, jitdump.c. Note: session.c's perf_event__time_conv_swap() also guards on time_cycles but accesses time_mask — a pre-existing issue not introduced by this macro change. It is fixed by a later patch in this series ("perf session: Add validated swap infrastructure with null-termination checks"), which decouples time_cycles and time_mask into independent per-field event_contains() checks. The struct assignment overread (session->time_conv = event->time_conv copies sizeof on a potentially shorter event) is separately fixed by "perf session: Use bounded copy for PERF_RECORD_TIME_CONV". Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/include/perf/event.h | 9 ++++++++- tools/perf/util/arm-spe.c | 2 +- tools/perf/util/cs-etm.c | 2 +- tools/perf/util/jitdump.c | 2 +- tools/perf/util/tsc.c | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h index 9043dc72b5d6..fdced574c889 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -8,7 +8,14 @@ #include #include /* pid_t */ -#define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj), mem)) +/* + * Verify the full field fits within the event, not just its start offset. + * Only valid for fixed-size scalar fields — for trailing arrays like + * filename[PATH_MAX], sizeof() evaluates to the declared maximum, not + * the actual string length, so this would spuriously return false. + */ +#define event_contains(obj, mem) \ + ((obj).header.size >= offsetof(typeof(obj), mem) + sizeof((obj).mem)) struct perf_record_mmap { struct perf_event_header header; diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 31f05f467810..552f063f126e 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -2002,7 +2002,7 @@ int arm_spe_process_auxtrace_info(union perf_event *event, spe->tc.time_mult = tc->time_mult; spe->tc.time_zero = tc->time_zero; - if (event_contains(*tc, time_cycles)) { + if (event_contains(*tc, cap_user_time_short)) { spe->tc.time_cycles = tc->time_cycles; spe->tc.time_mask = tc->time_mask; spe->tc.cap_user_time_zero = tc->cap_user_time_zero; diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 6ec48de29441..40c6ddfa8c8d 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -3514,7 +3514,7 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event, etm->tc.time_shift = tc->time_shift; etm->tc.time_mult = tc->time_mult; etm->tc.time_zero = tc->time_zero; - if (event_contains(*tc, time_cycles)) { + if (event_contains(*tc, cap_user_time_short)) { etm->tc.time_cycles = tc->time_cycles; etm->tc.time_mask = tc->time_mask; etm->tc.cap_user_time_zero = tc->cap_user_time_zero; diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 52e6ffac2b3e..18fd84a82153 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -409,7 +409,7 @@ static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp) * checks the event size and assigns these extended fields if these * fields are contained in the event. */ - if (event_contains(*time_conv, time_cycles)) { + if (event_contains(*time_conv, cap_user_time_short)) { tc.time_cycles = time_conv->time_cycles; tc.time_mask = time_conv->time_mask; tc.cap_user_time_zero = time_conv->cap_user_time_zero; diff --git a/tools/perf/util/tsc.c b/tools/perf/util/tsc.c index 511a517ce613..ebf289bf6b9d 100644 --- a/tools/perf/util/tsc.c +++ b/tools/perf/util/tsc.c @@ -127,7 +127,7 @@ size_t perf_event__fprintf_time_conv(union perf_event *event, FILE *fp) * when supported cap_user_time_short, for backward compatibility, * prints the extended fields only if they are contained in the event. */ - if (event_contains(*tc, time_cycles)) { + if (event_contains(*tc, cap_user_time_short)) { ret += fprintf(fp, "... Time Cycles %" PRI_lu64 "\n", tc->time_cycles); ret += fprintf(fp, "... Time Mask %#" PRI_lx64 "\n", From a18908b5056b8fdb2c44505f0c57ff05865740a3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 May 2026 18:26:07 -0300 Subject: [PATCH 121/343] perf zstd: Fix compression error path in zstd_compress_stream_to_records() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The error fallback does memcpy(dst, src, src_size) intending to store uncompressed data when compression fails, but this has three bugs: 1. dst has been advanced past the record header (and potentially past earlier compressed records), so the copy writes to the wrong offset in the output buffer. 2. src still points to the start of the input, not to the remaining uncompressed data at src + input.pos. On a second or later iteration, previously compressed data would be duplicated. 3. No check that dst_size >= src_size — if the remaining output space is smaller, this is an out-of-bounds write. Replace with return -1 after resetting the ZSTD compression context via ZSTD_initCStream(). The -1 propagates through zstd_compress() -> record__pushfn() -> perf_mmap__push() to the recording loop, which breaks out and terminates recording. Add an out_child_no_flush label in __cmd_record() so the mmap-read failure path skips the final record__mmap_read_all() flush — retrying the same read that just failed would just fail again, and the flush is only useful when the mmap data is intact but the control path (auxtrace, switch_output) had an error. Consolidate all error paths through a single 'reset' label to ensure the compression context is always reset on failure — including the output-buffer-full path, where a bare return without resetting would leave stale stream state that corrupts output if the caller retries. Also guard against process_header() writing the event header before the buffer-full check: add a sizeof(perf_event_header) pre-check so the callback never writes past the output buffer. Guard against ZSTD making no progress: if output.pos is zero after ZSTD_compressStream(), calling process_header(record, 0) would re-trigger header initialization, double-subtracting the header size from dst_size and underflowing the unsigned counter. Also fix two pre-existing issues in the same function: - Add a dst_size guard before subtracting the record header size: if the output buffer is nearly full, the unsigned dst_size -= size underflows to a huge value, causing ZSTD_compressStream to write past the buffer boundary. - Check the ZSTD_initCStream() return value and log an error if the context reset itself fails. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 6 +++++- tools/perf/util/zstd.c | 27 +++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 4a30688699d5..a33c78f030d9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -2744,7 +2744,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) trigger_error(&auxtrace_snapshot_trigger); trigger_error(&switch_output_trigger); err = -1; - goto out_child; + goto out_child_no_flush; } if (auxtrace_record__snapshot_started) { @@ -2891,6 +2891,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) out_child: record__stop_threads(rec); record__mmap_read_all(rec, true); + goto out_free_threads; +out_child_no_flush: + /* mmap read already failed — retrying would just fail again */ + record__stop_threads(rec); out_free_threads: record__free_thread_data(rec); evlist__finalize_ctlfd(rec->evlist); diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c index 57027e0ac7b6..ecda9deb53b7 100644 --- a/tools/perf/util/zstd.c +++ b/tools/perf/util/zstd.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include "util/compress.h" #include "util/debug.h" @@ -54,7 +55,13 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_ while (input.pos < input.size) { record = dst; + /* process_header writes the event header into record */ + if (dst_size < sizeof(struct perf_event_header)) + goto reset; size = process_header(record, 0); + /* Output buffer full — cannot fit even the record header */ + if (size > dst_size) + goto reset; compressed += size; dst += size; dst_size -= size; @@ -65,10 +72,18 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_ if (ZSTD_isError(ret)) { pr_err("failed to compress %ld bytes: %s\n", (long)src_size, ZSTD_getErrorName(ret)); - memcpy(dst, src, src_size); - return src_size; + goto reset; } size = output.pos; + /* + * No progress: ZSTD couldn't emit any bytes into the + * remaining output buffer. Calling process_header + * with size=0 would re-trigger header initialization, + * double-subtracting the header size from dst_size and + * underflowing the unsigned counter. + */ + if (size == 0) + goto reset; size = process_header(record, size); compressed += size; dst += size; @@ -76,6 +91,14 @@ ssize_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_ } return compressed; + +reset: + /* Reset so the context is usable if the caller retries */ + ret = ZSTD_initCStream(data->cstream, data->comp_level); + if (ZSTD_isError(ret)) + pr_err("failed to reset compression context: %s\n", + ZSTD_getErrorName(ret)); + return -1; } size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size, From 3ec93875fda94e7f4c466855825c860a2e0ceac2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 19:46:21 -0300 Subject: [PATCH 122/343] perf zstd: Fix multi-iteration decompression and error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit zstd_decompress_stream() has two bugs in its multi-iteration loop: 1. After each ZSTD_decompressStream() call, the code advances output.dst by output.pos but doesn't reset output.pos to 0. ZSTD interprets output.pos relative to output.dst, so the next iteration writes at (dst + pos) + pos = dst + 2*pos, skipping a gap and potentially writing out of bounds. 2. On ZSTD_decompressStream() error, the loop executes break and returns output.pos (which is > 0 if some bytes were decompressed before the error). The caller checks !decomp_size and skips the error, silently accepting truncated or corrupted data. Fix both by removing the output buffer adjustment — ZSTD correctly accumulates output.pos across calls without it. Return 0 on decompression error so the caller detects it. Add a no-progress guard to prevent infinite loops if the output buffer fills before all input is consumed. Note: the compressed event data_size is validated against header.size by a subsequent patch in this series ("perf tools: Harden compressed event processing"). Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/zstd.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c index ecda9deb53b7..21a0eb58597c 100644 --- a/tools/perf/util/zstd.c +++ b/tools/perf/util/zstd.c @@ -123,14 +123,26 @@ size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size } } while (input.pos < input.size) { + size_t prev_in = input.pos; + size_t prev_out = output.pos; + ret = ZSTD_decompressStream(data->dstream, &output, &input); if (ZSTD_isError(ret)) { pr_err("failed to decompress (B): %zd -> %zd, dst_size %zd : %s\n", - src_size, output.size, dst_size, ZSTD_getErrorName(ret)); - break; + src_size, output.pos, dst_size, ZSTD_getErrorName(ret)); + return 0; } - output.dst = dst + output.pos; - output.size = dst_size - output.pos; + /* + * Neither stream advanced — decompression is stuck. + * Return 0 (error) rather than partial output: perf + * uses ZSTD_flushStream (not ZSTD_endStream), so the + * stream is continuous across compressed events. + * Discarding unconsumed input would desynchronize the + * decompressor, causing the next call to produce + * garbage that could be misinterpreted as valid events. + */ + if (input.pos == prev_in && output.pos == prev_out) + return 0; } return output.pos; From fe84caf425f9d404833dc165eb60efbd0fc54e43 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 12:57:48 -0300 Subject: [PATCH 123/343] perf session: Fix PERF_RECORD_READ swap and dump for variable-length events The kernel dynamically sizes PERF_RECORD_READ based on attr.read_format: only the fields enabled by PERF_FORMAT_TOTAL_TIME_ENABLED, PERF_FORMAT_TOTAL_TIME_RUNNING, PERF_FORMAT_ID, and PERF_FORMAT_LOST are emitted, packed with no gaps. perf_event__read_swap() unconditionally byte-swapped time_enabled, time_running, and id at their fixed struct offsets, causing out-of-bounds access on smaller events and swapping the wrong bytes when not all format fields are present. It also swapped sample_id_all at a fixed offset past the full struct, which is wrong for shorter events. Replace the individual field swaps with a single mem_bswap_64() over the entire tail from value onward. Since every field after pid/tid is u64 regardless of which combination is present, this correctly handles any read_format combination and any trailing sample_id_all fields. Similarly, dump_read() accessed optional fields via fixed struct offsets, displaying values from wrong positions when not all format bits are set. Walk the packed u64 array sequentially instead, with bounds checks against event->header.size. Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 61 ++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c4cd8ad6d810..24f2ba599b80 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -354,17 +354,24 @@ static void perf_event__task_swap(union perf_event *event, bool sample_id_all) swap_sample_id_all(event, &event->fork + 1); } -static void perf_event__read_swap(union perf_event *event, bool sample_id_all) +static void perf_event__read_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { + size_t tail; + event->read.pid = bswap_32(event->read.pid); event->read.tid = bswap_32(event->read.tid); - event->read.value = bswap_64(event->read.value); - event->read.time_enabled = bswap_64(event->read.time_enabled); - event->read.time_running = bswap_64(event->read.time_running); - event->read.id = bswap_64(event->read.id); - - if (sample_id_all) - swap_sample_id_all(event, &event->read + 1); + /* + * Everything after pid/tid is u64: the read values (variable + * set determined by attr.read_format, which we don't have + * here) optionally followed by sample_id_all fields. + * Since all are u64, swap the entire remaining tail at once. + */ + tail = event->header.size - offsetof(struct perf_record_read, value); + /* mem_bswap_64 rounds up to 8-byte chunks — unaligned tail overruns the buffer */ + if (tail % sizeof(u64)) + return; + mem_bswap_64(&event->read.value, tail); } static void perf_event__aux_swap(union perf_event *event, bool sample_id_all) @@ -1200,8 +1207,9 @@ static void dump_deferred_callchain(union perf_event *event, struct perf_sample static void dump_read(struct evsel *evsel, union perf_event *event) { - struct perf_record_read *read_event = &event->read; u64 read_format; + __u64 *array; + void *end; if (!dump_trace) return; @@ -1213,18 +1221,37 @@ static void dump_read(struct evsel *evsel, union perf_event *event) return; read_format = evsel->core.attr.read_format; + /* + * The kernel packs only the enabled read_format fields + * after value, with no gaps. Walk the packed array + * instead of using fixed struct offsets. + */ + array = &event->read.value + 1; + end = (void *)event + event->header.size; - if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) - printf("... time enabled : %" PRI_lu64 "\n", read_event->time_enabled); + if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { + if ((void *)(array + 1) > end) + return; + printf("... time enabled : %" PRI_lu64 "\n", *array++); + } - if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) - printf("... time running : %" PRI_lu64 "\n", read_event->time_running); + if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) { + if ((void *)(array + 1) > end) + return; + printf("... time running : %" PRI_lu64 "\n", *array++); + } - if (read_format & PERF_FORMAT_ID) - printf("... id : %" PRI_lu64 "\n", read_event->id); + if (read_format & PERF_FORMAT_ID) { + if ((void *)(array + 1) > end) + return; + printf("... id : %" PRI_lu64 "\n", *array++); + } - if (read_format & PERF_FORMAT_LOST) - printf("... lost : %" PRI_lu64 "\n", read_event->lost); + if (read_format & PERF_FORMAT_LOST) { + if ((void *)(array + 1) > end) + return; + printf("... lost : %" PRI_lu64 "\n", *array++); + } } static struct machine *machines__find_for_cpumode(struct machines *machines, From 315c81b4b971b6e92cb47c990fb4fbaa14f0386c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 13:01:34 -0300 Subject: [PATCH 124/343] perf session: Fix swap_sample_id_all() crash on crafted events swap_sample_id_all() calls BUG_ON(size % sizeof(u64)) which kills perf on any event where the sample_id_all tail is not 8-byte aligned. A crafted perf.data can trigger this trivially. Replace BUG_ON with a bounds check: skip the swap if the data pointer is past the end of the event, and only swap when there are bytes remaining. Note: the strlen calls in string-field swap handlers (comm, mmap, mmap2, cgroup) are replaced with bounded strnlen by the next patch in this series ("perf session: Add validated swap infrastructure with null-termination checks"). Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 24f2ba599b80..37544a357418 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -276,10 +276,18 @@ void perf_session__delete(struct perf_session *session) static void swap_sample_id_all(union perf_event *event, void *data) { void *end = (void *) event + event->header.size; - int size = end - data; + int size; - BUG_ON(size % sizeof(u64)); - mem_bswap_64(data, size); + if (data >= end) + return; + + size = end - data; + if (size % sizeof(u64)) { + pr_warning("swap_sample_id_all: unaligned sample_id_all remainder (%d), skipping swap\n", size); + return; + } + if (size > 0) + mem_bswap_64(data, size); } static void perf_event__all64_swap(union perf_event *event, From 981f13ae6255fe8e9e68ca6435cd8194446460ec Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 12:47:46 -0300 Subject: [PATCH 125/343] perf session: Add validated swap infrastructure with null-termination checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change swap callbacks from void to int return so handlers can propagate errors. All 28 existing handlers are converted to return 0 on success, -1 on error. Three new handlers (KSYMBOL, BPF_EVENT, HEADER_FEATURE) are added returning int from the start, with sample_id_all handling for the kernel event types. event_swap() propagates the return to its callers (process_event and peek_event), which skip events that fail to swap. Add perf_event__check_nul() for null-termination enforcement on the common event delivery path for MMAP, MMAP2, COMM, CGROUP, and KSYMBOL events. Events with unterminated strings are skipped — native-endian files are mapped read-only, so writing a NUL byte in place would segfault. Swap handler hardening: - Use strnlen bounded by event size (instead of strlen) in COMM/MMAP/MMAP2/CGROUP swap handlers, returning -1 on unterminated strings. - Bounds check text_poke old_len+new_len before computing the sample_id offset, returning -1 on overflow. Use offsetof() for the native-path check in machines__deliver_event() since sizeof() includes struct padding past the flexible array. - Fix PERF_RECORD_SWITCH sample_id_all: non-CPU_WIDE SWITCH events have sample_id immediately after the 8-byte header, not at sizeof(struct perf_record_switch) which is the CPU_WIDE variant size. - Fix perf_event__time_conv_swap(): decouple time_cycles and time_mask into independent per-field event_contains() checks, so each field is only swapped when the event is large enough to contain it. The original code guarded both fields under a single time_cycles check, which would swap time_mask on a short event that contains time_cycles but not time_mask. - Handle ABI0 (attr.size == 0) in perf_event__attr_swap() by substituting PERF_ATTR_SIZE_VER0, so bswap_safe() correctly swaps VER0 fields instead of skipping everything. - peek_events: on swap failure, advance past the malformed entry instead of aborting the loop. Note: the nr-field bounds checks for namespaces, thread_map, cpu_map, and stat_config arrays are added by a subsequent patch ("perf session: Validate nr fields against event size on both swap and common paths"). The HEADER_ATTR attr.size validation is added by ("perf session: Validate HEADER_ATTR attr.size before swapping"). By establishing the int-returning swap infrastructure first, all subsequent hardening patches can use direct error returns from day one — no poison values, no workarounds for void return. Changes in v2: - peek_events: abort instead of skip for AUXTRACE events on validation failure — skipping only header.size would land inside the raw trace payload, causing subsequent iterations to misparse data as events (Reported-by: sashiko-bot@kernel.org) Fixes: 9aa0bfa370b2 ("perf tools: Handle PERF_RECORD_KSYMBOL") Fixes: 45178a928a4b ("perf tools: Handle PERF_RECORD_BPF_EVENT") Fixes: e9def1b2e74e ("perf tools: Add feature header record to pipe-mode") Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: David Carrillo-Cisneros Cc: Jiri Olsa Cc: Namhyung Kim Cc: Song Liu Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 406 ++++++++++++++++++++++++++++++-------- 1 file changed, 325 insertions(+), 81 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 37544a357418..d5864e380c1b 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -290,28 +290,44 @@ static void swap_sample_id_all(union perf_event *event, void *data) mem_bswap_64(data, size); } -static void perf_event__all64_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__all64_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { struct perf_event_header *hdr = &event->header; - mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); + size_t size = event->header.size - sizeof(*hdr); + + /* mem_bswap_64 rounds up to 8-byte chunks — unaligned size overruns the buffer */ + if (size % sizeof(u64)) + return -1; + mem_bswap_64(hdr + 1, size); + return 0; } -static void perf_event__comm_swap(union perf_event *event, bool sample_id_all) +static int perf_event__comm_swap(union perf_event *event, bool sample_id_all) { event->comm.pid = bswap_32(event->comm.pid); event->comm.tid = bswap_32(event->comm.tid); if (sample_id_all) { void *data = &event->comm.comm; + void *end = (void *)event + event->header.size; + size_t len = strnlen(data, end - data); - data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); + /* + * No NUL within the event boundary — can't locate where + * sample_id_all starts. Reject so the event is skipped + * rather than swapping garbage. + */ + if (len == (size_t)(end - data)) + return -1; + data += PERF_ALIGN(len + 1, sizeof(u64)); swap_sample_id_all(event, data); } + return 0; } -static void perf_event__mmap_swap(union perf_event *event, - bool sample_id_all) +static int perf_event__mmap_swap(union perf_event *event, + bool sample_id_all) { event->mmap.pid = bswap_32(event->mmap.pid); event->mmap.tid = bswap_32(event->mmap.tid); @@ -321,13 +337,19 @@ static void perf_event__mmap_swap(union perf_event *event, if (sample_id_all) { void *data = &event->mmap.filename; + void *end = (void *)event + event->header.size; + size_t len = strnlen(data, end - data); - data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); + /* See comment in perf_event__comm_swap() */ + if (len == (size_t)(end - data)) + return -1; + data += PERF_ALIGN(len + 1, sizeof(u64)); swap_sample_id_all(event, data); } + return 0; } -static void perf_event__mmap2_swap(union perf_event *event, +static int perf_event__mmap2_swap(union perf_event *event, bool sample_id_all) { event->mmap2.pid = bswap_32(event->mmap2.pid); @@ -345,12 +367,19 @@ static void perf_event__mmap2_swap(union perf_event *event, if (sample_id_all) { void *data = &event->mmap2.filename; + void *end = (void *)event + event->header.size; + size_t len = strnlen(data, end - data); - data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); + /* See comment in perf_event__comm_swap() */ + if (len == (size_t)(end - data)) + return -1; + data += PERF_ALIGN(len + 1, sizeof(u64)); swap_sample_id_all(event, data); } + return 0; } -static void perf_event__task_swap(union perf_event *event, bool sample_id_all) + +static int perf_event__task_swap(union perf_event *event, bool sample_id_all) { event->fork.pid = bswap_32(event->fork.pid); event->fork.tid = bswap_32(event->fork.tid); @@ -360,10 +389,11 @@ static void perf_event__task_swap(union perf_event *event, bool sample_id_all) if (sample_id_all) swap_sample_id_all(event, &event->fork + 1); + return 0; } -static void perf_event__read_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__read_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { size_t tail; @@ -378,11 +408,12 @@ static void perf_event__read_swap(union perf_event *event, tail = event->header.size - offsetof(struct perf_record_read, value); /* mem_bswap_64 rounds up to 8-byte chunks — unaligned tail overruns the buffer */ if (tail % sizeof(u64)) - return; + return -1; mem_bswap_64(&event->read.value, tail); + return 0; } -static void perf_event__aux_swap(union perf_event *event, bool sample_id_all) +static int perf_event__aux_swap(union perf_event *event, bool sample_id_all) { event->aux.aux_offset = bswap_64(event->aux.aux_offset); event->aux.aux_size = bswap_64(event->aux.aux_size); @@ -390,19 +421,21 @@ static void perf_event__aux_swap(union perf_event *event, bool sample_id_all) if (sample_id_all) swap_sample_id_all(event, &event->aux + 1); + return 0; } -static void perf_event__itrace_start_swap(union perf_event *event, - bool sample_id_all) +static int perf_event__itrace_start_swap(union perf_event *event, + bool sample_id_all) { event->itrace_start.pid = bswap_32(event->itrace_start.pid); event->itrace_start.tid = bswap_32(event->itrace_start.tid); if (sample_id_all) swap_sample_id_all(event, &event->itrace_start + 1); + return 0; } -static void perf_event__switch_swap(union perf_event *event, bool sample_id_all) +static int perf_event__switch_swap(union perf_event *event, bool sample_id_all) { if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) { event->context_switch.next_prev_pid = @@ -411,30 +444,45 @@ static void perf_event__switch_swap(union perf_event *event, bool sample_id_all) bswap_32(event->context_switch.next_prev_tid); } - if (sample_id_all) - swap_sample_id_all(event, &event->context_switch + 1); + if (sample_id_all) { + /* + * PERF_RECORD_SWITCH has no fields beyond the header; + * SWITCH_CPU_WIDE adds pid/tid. Use the right offset + * so sample_id starts at the correct position. + */ + if (event->header.type == PERF_RECORD_SWITCH) + swap_sample_id_all(event, (void *)event + sizeof(event->header)); + else + swap_sample_id_all(event, &event->context_switch + 1); + } + return 0; } -static void perf_event__text_poke_swap(union perf_event *event, bool sample_id_all) +static int perf_event__text_poke_swap(union perf_event *event, bool sample_id_all) { event->text_poke.addr = bswap_64(event->text_poke.addr); event->text_poke.old_len = bswap_16(event->text_poke.old_len); event->text_poke.new_len = bswap_16(event->text_poke.new_len); if (sample_id_all) { + void *data = &event->text_poke.old_len; + void *end = (void *)event + event->header.size; size_t len = sizeof(event->text_poke.old_len) + sizeof(event->text_poke.new_len) + event->text_poke.old_len + event->text_poke.new_len; - void *data = &event->text_poke.old_len; + /* old_len + new_len exceeds event — can't find sample_id_all */ + if (data + len > end) + return -1; data += PERF_ALIGN(len, sizeof(u64)); swap_sample_id_all(event, data); } + return 0; } -static void perf_event__throttle_swap(union perf_event *event, - bool sample_id_all) +static int perf_event__throttle_swap(union perf_event *event, + bool sample_id_all) { event->throttle.time = bswap_64(event->throttle.time); event->throttle.id = bswap_64(event->throttle.id); @@ -442,10 +490,11 @@ static void perf_event__throttle_swap(union perf_event *event, if (sample_id_all) swap_sample_id_all(event, &event->throttle + 1); + return 0; } -static void perf_event__namespaces_swap(union perf_event *event, - bool sample_id_all) +static int perf_event__namespaces_swap(union perf_event *event, + bool sample_id_all) { u64 i; @@ -462,18 +511,25 @@ static void perf_event__namespaces_swap(union perf_event *event, if (sample_id_all) swap_sample_id_all(event, &event->namespaces.link_info[i]); + return 0; } -static void perf_event__cgroup_swap(union perf_event *event, bool sample_id_all) +static int perf_event__cgroup_swap(union perf_event *event, bool sample_id_all) { event->cgroup.id = bswap_64(event->cgroup.id); if (sample_id_all) { void *data = &event->cgroup.path; + void *end = (void *)event + event->header.size; + size_t len = strnlen(data, end - data); - data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); + /* See comment in perf_event__comm_swap() */ + if (len == (size_t)(end - data)) + return -1; + data += PERF_ALIGN(len + 1, sizeof(u64)); swap_sample_id_all(event, data); } + return 0; } static u8 revbyte(u8 b) @@ -514,9 +570,19 @@ void perf_event__attr_swap(struct perf_event_attr *attr) attr->type = bswap_32(attr->type); attr->size = bswap_32(attr->size); -#define bswap_safe(f, n) \ - (attr->size > (offsetof(struct perf_event_attr, f) + \ - sizeof(attr->f) * (n))) + /* + * ABI0: size == 0 means the producer didn't set it. + * Assume PERF_ATTR_SIZE_VER0 so bswap_safe() below + * correctly swaps the VER0 fields instead of skipping + * everything. Same convention as read_attr(). + */ + if (!attr->size) + attr->size = PERF_ATTR_SIZE_VER0; + +/* Verify the full field extent fits, not just its start offset */ +#define bswap_safe(f, n) \ + (attr->size >= (offsetof(struct perf_event_attr, f) + \ + sizeof(attr->f) * ((n) + 1))) #define bswap_field(f, sz) \ do { \ if (bswap_safe(f, 0)) \ @@ -554,8 +620,8 @@ do { \ #undef bswap_safe } -static void perf_event__hdr_attr_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__hdr_attr_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { size_t size; @@ -564,30 +630,34 @@ static void perf_event__hdr_attr_swap(union perf_event *event, size = event->header.size; size -= perf_record_header_attr_id(event) - (void *)event; mem_bswap_64(perf_record_header_attr_id(event), size); + return 0; } -static void perf_event__event_update_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__event_update_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { event->event_update.type = bswap_64(event->event_update.type); event->event_update.id = bswap_64(event->event_update.id); + return 0; } -static void perf_event__event_type_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__event_type_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { event->event_type.event_type.event_id = bswap_64(event->event_type.event_type.event_id); + return 0; } -static void perf_event__tracing_data_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__tracing_data_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { event->tracing_data.size = bswap_32(event->tracing_data.size); + return 0; } -static void perf_event__auxtrace_info_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__auxtrace_info_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { size_t size; @@ -596,10 +666,11 @@ static void perf_event__auxtrace_info_swap(union perf_event *event, size = event->header.size; size -= (void *)&event->auxtrace_info.priv - (void *)event; mem_bswap_64(event->auxtrace_info.priv, size); + return 0; } -static void perf_event__auxtrace_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__auxtrace_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { event->auxtrace.size = bswap_64(event->auxtrace.size); event->auxtrace.offset = bswap_64(event->auxtrace.offset); @@ -607,10 +678,11 @@ static void perf_event__auxtrace_swap(union perf_event *event, event->auxtrace.idx = bswap_32(event->auxtrace.idx); event->auxtrace.tid = bswap_32(event->auxtrace.tid); event->auxtrace.cpu = bswap_32(event->auxtrace.cpu); + return 0; } -static void perf_event__auxtrace_error_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__auxtrace_error_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { event->auxtrace_error.type = bswap_32(event->auxtrace_error.type); event->auxtrace_error.code = bswap_32(event->auxtrace_error.code); @@ -625,10 +697,11 @@ static void perf_event__auxtrace_error_swap(union perf_event *event, event->auxtrace_error.machine_pid = bswap_32(event->auxtrace_error.machine_pid); event->auxtrace_error.vcpu = bswap_32(event->auxtrace_error.vcpu); } + return 0; } -static void perf_event__thread_map_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__thread_map_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { unsigned i; @@ -636,10 +709,11 @@ static void perf_event__thread_map_swap(union perf_event *event, for (i = 0; i < event->thread_map.nr; i++) event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid); + return 0; } -static void perf_event__cpu_map_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__cpu_map_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { struct perf_record_cpu_map_data *data = &event->cpu_map.data; @@ -677,20 +751,22 @@ static void perf_event__cpu_map_swap(union perf_event *event, default: break; } + return 0; } -static void perf_event__stat_config_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__stat_config_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { u64 size; size = bswap_64(event->stat_config.nr) * sizeof(event->stat_config.data[0]); size += 1; /* nr item itself */ mem_bswap_64(&event->stat_config.nr, size); + return 0; } -static void perf_event__stat_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__stat_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { event->stat.id = bswap_64(event->stat.id); event->stat.thread = bswap_32(event->stat.thread); @@ -698,44 +774,90 @@ static void perf_event__stat_swap(union perf_event *event, event->stat.val = bswap_64(event->stat.val); event->stat.ena = bswap_64(event->stat.ena); event->stat.run = bswap_64(event->stat.run); + return 0; } -static void perf_event__stat_round_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__stat_round_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { event->stat_round.type = bswap_64(event->stat_round.type); event->stat_round.time = bswap_64(event->stat_round.time); + return 0; } -static void perf_event__time_conv_swap(union perf_event *event, - bool sample_id_all __maybe_unused) +static int perf_event__time_conv_swap(union perf_event *event, + bool sample_id_all __maybe_unused) { event->time_conv.time_shift = bswap_64(event->time_conv.time_shift); event->time_conv.time_mult = bswap_64(event->time_conv.time_mult); event->time_conv.time_zero = bswap_64(event->time_conv.time_zero); - if (event_contains(event->time_conv, time_cycles)) { + if (event_contains(event->time_conv, time_cycles)) event->time_conv.time_cycles = bswap_64(event->time_conv.time_cycles); + if (event_contains(event->time_conv, time_mask)) event->time_conv.time_mask = bswap_64(event->time_conv.time_mask); - } + return 0; } -static void +static int perf_event__schedstat_cpu_swap(union perf_event *event __maybe_unused, bool sample_id_all __maybe_unused) { /* FIXME */ + return 0; } -static void +static int perf_event__schedstat_domain_swap(union perf_event *event __maybe_unused, bool sample_id_all __maybe_unused) { /* FIXME */ + return 0; } -typedef void (*perf_event__swap_op)(union perf_event *event, - bool sample_id_all); +static int perf_event__ksymbol_swap(union perf_event *event, + bool sample_id_all) +{ + event->ksymbol.addr = bswap_64(event->ksymbol.addr); + event->ksymbol.len = bswap_32(event->ksymbol.len); + event->ksymbol.ksym_type = bswap_16(event->ksymbol.ksym_type); + event->ksymbol.flags = bswap_16(event->ksymbol.flags); + + if (sample_id_all) { + void *data = &event->ksymbol.name; + void *end = (void *)event + event->header.size; + size_t len = strnlen(data, end - data); + + /* See comment in perf_event__comm_swap() */ + if (len == (size_t)(end - data)) + return -1; + data += PERF_ALIGN(len + 1, sizeof(u64)); + swap_sample_id_all(event, data); + } + return 0; +} + +static int perf_event__bpf_event_swap(union perf_event *event, + bool sample_id_all) +{ + event->bpf.type = bswap_16(event->bpf.type); + event->bpf.flags = bswap_16(event->bpf.flags); + event->bpf.id = bswap_32(event->bpf.id); + + if (sample_id_all) + swap_sample_id_all(event, &event->bpf + 1); + return 0; +} + +static int perf_event__header_feature_swap(union perf_event *event, + bool sample_id_all __maybe_unused) +{ + event->feat.feat_id = bswap_64(event->feat.feat_id); + return 0; +} + +typedef int (*perf_event__swap_op)(union perf_event *event, + bool sample_id_all); static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_MMAP] = perf_event__mmap_swap, @@ -755,6 +877,8 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_SWITCH_CPU_WIDE] = perf_event__switch_swap, [PERF_RECORD_NAMESPACES] = perf_event__namespaces_swap, [PERF_RECORD_CGROUP] = perf_event__cgroup_swap, + [PERF_RECORD_KSYMBOL] = perf_event__ksymbol_swap, + [PERF_RECORD_BPF_EVENT] = perf_event__bpf_event_swap, [PERF_RECORD_TEXT_POKE] = perf_event__text_poke_swap, [PERF_RECORD_AUX_OUTPUT_HW_ID] = perf_event__all64_swap, [PERF_RECORD_CALLCHAIN_DEFERRED] = perf_event__all64_swap, @@ -762,6 +886,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, [PERF_RECORD_HEADER_BUILD_ID] = NULL, + [PERF_RECORD_HEADER_FEATURE] = perf_event__header_feature_swap, [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap, [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, @@ -1488,6 +1613,25 @@ static int session__flush_deferred_samples(struct perf_session *session, return ret; } +/* + * Return true if the string field is properly null-terminated + * within the event boundary. Native-endian files are mapped + * read-only (MAP_SHARED + PROT_READ) so we cannot write a + * null byte in place; skip the event instead. + */ +static bool perf_event__check_nul(const char *str, const void *end, const char *event_name) +{ + size_t max_len = (const char *)end - str; + + if (max_len == 0 || strnlen(str, max_len) == max_len) { + pr_warning("WARNING: PERF_RECORD_%s: string not null-terminated, skipping event\n", + event_name); + return false; + } + + return true; +} + static int machines__deliver_event(struct machines *machines, struct evlist *evlist, union perf_event *event, @@ -1536,16 +1680,32 @@ static int machines__deliver_event(struct machines *machines, } return evlist__deliver_sample(evlist, tool, event, sample, machine); case PERF_RECORD_MMAP: + if (!perf_event__check_nul(event->mmap.filename, + (void *)event + event->header.size, + "MMAP")) + return 0; return tool->mmap(tool, event, sample, machine); case PERF_RECORD_MMAP2: if (event->header.misc & PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT) ++evlist->stats.nr_proc_map_timeout; + if (!perf_event__check_nul(event->mmap2.filename, + (void *)event + event->header.size, + "MMAP2")) + return 0; return tool->mmap2(tool, event, sample, machine); case PERF_RECORD_COMM: + if (!perf_event__check_nul(event->comm.comm, + (void *)event + event->header.size, + "COMM")) + return 0; return tool->comm(tool, event, sample, machine); case PERF_RECORD_NAMESPACES: return tool->namespaces(tool, event, sample, machine); case PERF_RECORD_CGROUP: + if (!perf_event__check_nul(event->cgroup.path, + (void *)event + event->header.size, + "CGROUP")) + return 0; return tool->cgroup(tool, event, sample, machine); case PERF_RECORD_FORK: return tool->fork(tool, event, sample, machine); @@ -1584,11 +1744,25 @@ static int machines__deliver_event(struct machines *machines, case PERF_RECORD_SWITCH_CPU_WIDE: return tool->context_switch(tool, event, sample, machine); case PERF_RECORD_KSYMBOL: + if (!perf_event__check_nul(event->ksymbol.name, + (void *)event + event->header.size, + "KSYMBOL")) + return 0; return tool->ksymbol(tool, event, sample, machine); case PERF_RECORD_BPF_EVENT: return tool->bpf(tool, event, sample, machine); - case PERF_RECORD_TEXT_POKE: + case PERF_RECORD_TEXT_POKE: { + /* offsetof(bytes), not sizeof — sizeof includes padding past the flexible array */ + size_t text_poke_len = offsetof(struct perf_record_text_poke_event, bytes) + + event->text_poke.old_len + + event->text_poke.new_len; + + if (event->header.size < text_poke_len) { + pr_warning("WARNING: PERF_RECORD_TEXT_POKE: old_len+new_len exceeds event, skipping\n"); + return 0; + } return tool->text_poke(tool, event, sample, machine); + } case PERF_RECORD_AUX_OUTPUT_HW_ID: return tool->aux_output_hw_id(tool, event, sample, machine); case PERF_RECORD_CALLCHAIN_DEFERRED: @@ -1794,12 +1968,28 @@ int perf_session__deliver_synth_attr_event(struct perf_session *session, return perf_session__deliver_synth_event(session, &ev.ev, NULL); } +/* Caller must ensure event->header.type < PERF_RECORD_HEADER_MAX */ +static int event_swap(union perf_event *event, bool sample_id_all) +{ + perf_event__swap_op swap = perf_event__swap_ops[event->header.type]; + + if (swap) + return swap(event, sample_id_all); + return 0; +} + /* * Minimum event sizes indexed by type. Checked before swap and * processing so that both cross-endian and native-endian paths * are protected from accessing fields past the event boundary. * Zero means no minimum beyond the 8-byte header (already * enforced by the reader). + * + * These values represent the smallest event the kernel has ever + * emitted for each type, so they do not reject legitimate legacy + * perf.data files from older kernels. Variable-length events + * use offsetof() to the first variable field; the variable + * content is validated separately (e.g., perf_event__check_nul). */ static const u32 perf_event__min_size[PERF_RECORD_HEADER_MAX] = { /* @@ -1821,7 +2011,9 @@ static const u32 perf_event__min_size[PERF_RECORD_HEADER_MAX] = { [PERF_RECORD_FORK] = sizeof(struct perf_record_fork), /* * The kernel dynamically sizes PERF_RECORD_READ based on - * attr.read_format — the minimum has just pid + tid + value. + * attr.read_format — only the enabled fields are emitted, + * packed with no gaps. The minimum valid event has just + * pid + tid + one u64 value (no optional fields). */ [PERF_RECORD_READ] = offsetof(struct perf_record_read, time_enabled), [PERF_RECORD_MMAP2] = offsetof(struct perf_record_mmap2, filename) + 1, @@ -1844,14 +2036,25 @@ static const u32 perf_event__min_size[PERF_RECORD_HEADER_MAX] = { [PERF_RECORD_AUXTRACE] = sizeof(struct perf_record_auxtrace), [PERF_RECORD_AUXTRACE_ERROR] = offsetof(struct perf_record_auxtrace_error, msg) + 1, [PERF_RECORD_THREAD_MAP] = sizeof(struct perf_record_thread_map), - /* Smallest valid variant is RANGE_CPUS: header(8) + type(2) + range(6) */ + /* + * sizeof(perf_record_cpu_map) is 20 because the outer struct + * isn't packed and GCC adds 2 bytes of trailing padding. + * The smallest valid variant (RANGE_CPUS) is only 16 bytes: + * header(8) + type(2) + range_cpu_data(6). Per-variant + * bounds are checked in the swap handler via payload. + */ [PERF_RECORD_CPU_MAP] = sizeof(struct perf_event_header) + sizeof(__u16) + sizeof(struct perf_record_range_cpu_map), [PERF_RECORD_STAT_CONFIG] = sizeof(struct perf_record_stat_config), [PERF_RECORD_STAT] = sizeof(struct perf_record_stat), [PERF_RECORD_STAT_ROUND] = sizeof(struct perf_record_stat_round), - /* Union inflates sizeof; use fixed header fields as minimum */ + /* + * EVENT_UPDATE has a union whose largest member (cpus) + * inflates sizeof to 40, but SCALE events are only 32 + * and UNIT/NAME events can be even smaller. Use the + * fixed header fields (header + type + id) as minimum. + */ [PERF_RECORD_EVENT_UPDATE] = offsetof(struct perf_record_event_update, scale), [PERF_RECORD_TIME_CONV] = offsetof(struct perf_record_time_conv, time_cycles), [PERF_RECORD_ID_INDEX] = sizeof(struct perf_record_id_index), @@ -1887,14 +2090,6 @@ static bool perf_event__too_small(const union perf_event *event, u32 *min) return false; } -/* Caller must ensure event->header.type < PERF_RECORD_HEADER_MAX */ -static void event_swap(union perf_event *event, bool sample_id_all) -{ - perf_event__swap_op swap = perf_event__swap_ops[event->header.type]; - if (swap) - swap(event, sample_id_all); -} - /* * Read and validate the event at @file_offset. * @@ -2003,8 +2198,16 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, return -1; } - if (session->header.needs_swap) - event_swap(event, evlist__sample_id_all(session->evlist)); + if (session->header.needs_swap && + event_swap(event, evlist__sample_id_all(session->evlist))) { + /* + * The header was already swapped so header.size is + * valid — expose the event so callers can advance + * past this malformed entry instead of aborting. + */ + *event_ptr = event; + return -1; + } if (sample && event->header.type < PERF_RECORD_USER_TYPE_START && evlist__parse_sample(session->evlist, event, sample)) @@ -2022,11 +2225,37 @@ int perf_session__peek_events(struct perf_session *session, u64 offset, int err; do { + event = NULL; err = perf_session__peek_event(session, offset, buf, PERF_SAMPLE_MAX_SIZE, &event, NULL); - if (err) - return err; + if (err) { + /* + * Recoverable error: peek_event returns -1 but + * sets event_ptr when the header was read + * successfully but the event is malformed (too + * small or swap failed). Skip past it using + * header.size — don't invoke the callback since + * type-specific fields may be truncated. + * + * Must abort if: event_ptr is NULL (I/O error), + * size is 0 (can't advance), type is AUXTRACE + * (payload extends beyond header.size), or size + * is unaligned (would misalign all subsequent reads). + * + * Direct callers (auxtrace, cs-etm) treat any + * non-zero return as fatal — only this loop skips. + */ + if (event && event->header.size && + event->header.type != PERF_RECORD_AUXTRACE && + event->header.size % sizeof(u64) == 0) { + offset += event->header.size; + err = 0; + } else { + return err; + } + continue; + } err = cb(session, event, offset, data); if (err) @@ -2109,8 +2338,12 @@ static s64 perf_session__process_event(struct perf_session *session, return 0; } - if (session->header.needs_swap) - event_swap(event, evlist__sample_id_all(evlist)); + if (session->header.needs_swap && + event_swap(event, evlist__sample_id_all(evlist))) { + pr_warning("WARNING: swap failed for %s event, skipping\n", + perf_event__name(event->header.type)); + return 0; + } events_stats__inc(&evlist->stats, event->header.type); @@ -2579,6 +2812,17 @@ reader__mmap(struct reader *rd, struct perf_session *session) char *buf, **mmaps = rd->mmaps; u64 page_offset; + /* + * Native-endian: MAP_SHARED + PROT_READ — the kernel + * guarantees page-level coherence but a concurrent writer + * could modify the file between validation and use. This + * is a theoretical TOCTOU that affects the entire perf.data + * processing pipeline; fixing it would require copying each + * event to a private buffer before processing. + * + * Cross-endian: MAP_PRIVATE + PROT_WRITE — swap handlers + * get a copy-on-write snapshot immune to concurrent writes. + */ mmap_prot = PROT_READ; mmap_flags = MAP_SHARED; From 3ade633da7aa58e2a643c9eb0686c91d7dfa4f4e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 6 May 2026 17:00:50 -0300 Subject: [PATCH 126/343] perf session: Use bounded copy for PERF_RECORD_TIME_CONV session->time_conv = event->time_conv copies sizeof(struct perf_record_time_conv) bytes unconditionally, but older kernels emit shorter TIME_CONV events without the time_cycles, time_mask, cap_user_time_zero, and cap_user_time_short fields. For a 32-byte event (the original format), this reads 24 bytes past the event boundary into adjacent mmap'd data. The garbage values end up in session->time_conv and can cause incorrect TSC conversion if cap_user_time_zero happens to be non-zero. Replace the struct assignment with a bounded memcpy capped at event->header.size, zeroing the remainder so extended fields default to off when absent. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index d5864e380c1b..3f72b80aac56 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1897,7 +1897,14 @@ static s64 perf_session__process_user_event(struct perf_session *session, err = tool->stat_round(tool, session, event); break; case PERF_RECORD_TIME_CONV: - session->time_conv = event->time_conv; + /* + * Bounded copy: older kernels emit a shorter struct + * without time_cycles/time_mask/cap_user_time_*. + * Zero the rest so extended fields default to off. + */ + memset(&session->time_conv, 0, sizeof(session->time_conv)); + memcpy(&session->time_conv, &event->time_conv, + min((size_t)event->header.size, sizeof(session->time_conv))); err = tool->time_conv(tool, session, event); break; case PERF_RECORD_HEADER_FEATURE: From 6a38b515a5ea7101e8a9e14acf248d14083c632f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 13:07:27 -0300 Subject: [PATCH 127/343] perf session: Validate HEADER_ATTR attr.size before swapping Harden PERF_RECORD_HEADER_ATTR handling against crafted perf.data: - Validate attr.size: must be >= PERF_ATTR_SIZE_VER0, a multiple of sizeof(u64), and fit within the event payload. - Copy only min(attr.size, sizeof(struct perf_event_attr)) bytes into a local attr, zeroing the rest so legacy files don't leak adjacent event data into new fields. - Keep the original attr.size so perf_event__synthesize_attr() uses it for both allocation and ID-array placement. Fix perf_event__synthesize_attr() to use attr->size (not the compiled sizeof) for event allocation and layout, so perf inject correctly re-synthesizes attrs from files recorded by a different perf version. Without this, the ID array destination pointer (computed via perf_record_header_attr_id()) would be inconsistent with the allocation when attr->size differs from sizeof. Also fix the parse-no-sample-id-all test to set attr.size, which is now validated, and improve error handling in read_attr() for short reads and invalid attr sizes. Handle ABI0 pipe/inject events where attr.size is 0: use a local attr_size variable set to PERF_ATTR_SIZE_VER0 for both the bounded copy and ID array position, instead of writing back to the event. Native-endian files may be MAP_SHARED (read-only mmap), so writing to the event buffer would SIGSEGV. The swap path handles ABI0 in perf_event__attr_swap() which writes to the MAP_PRIVATE copy. header.size alignment is now validated centrally in perf_session__process_event() (see "Add minimum event size and alignment validation"). Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 23 ++++-- tools/perf/tests/parse-no-sample-id-all.c | 6 ++ tools/perf/util/header.c | 96 +++++++++++++++++++++-- tools/perf/util/session.c | 31 ++++++++ tools/perf/util/synthetic-events.c | 25 +++++- 5 files changed, 166 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 41a3721a194d..d8cb1f562f69 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -229,6 +229,7 @@ static int perf_event__repipe_attr(const struct perf_tool *tool, struct perf_inject *inject = container_of(tool, struct perf_inject, tool); struct perf_event_attr attr; + u32 raw_attr_size, attr_size; size_t n_ids; u64 *ids; int ret; @@ -244,24 +245,34 @@ static int perf_event__repipe_attr(const struct perf_tool *tool, if (!inject->itrace_synth_opts.set) return perf_event__repipe_synth(tool, event); - if (event->header.size < sizeof(struct perf_event_header) + sizeof(u64)) { + if (event->header.size < sizeof(struct perf_event_header) + PERF_ATTR_SIZE_VER0) { pr_err("Attribute event size %u is too small\n", event->header.size); return -EINVAL; } - if (event->header.size - sizeof(event->header) < event->attr.attr.size) { + /* + * ABI0 pipe/inject events have attr.size == 0; default to + * PERF_ATTR_SIZE_VER0 (the ABI0 footprint) for the bounded + * copy and ID array position. Same pattern as + * perf_event__process_attr() in header.c. + */ + raw_attr_size = event->attr.attr.size; + attr_size = raw_attr_size ?: PERF_ATTR_SIZE_VER0; + + if (raw_attr_size && (raw_attr_size < PERF_ATTR_SIZE_VER0 || + raw_attr_size > event->header.size - sizeof(event->header))) { pr_err("Attribute event size %u is too small for attr.size %u\n", - event->header.size, event->attr.attr.size); + event->header.size, raw_attr_size); return -EINVAL; } memset(&attr, 0, sizeof(attr)); memcpy(&attr, &event->attr.attr, - min_t(size_t, sizeof(attr), (size_t)event->attr.attr.size)); + min_t(size_t, sizeof(attr), attr_size)); - n_ids = event->header.size - sizeof(event->header) - event->attr.attr.size; + n_ids = event->header.size - sizeof(event->header) - attr_size; n_ids /= sizeof(u64); - ids = perf_record_header_attr_id(event); + ids = (void *)&event->attr.attr + attr_size; attr.size = sizeof(struct perf_event_attr); attr.sample_type &= ~PERF_SAMPLE_AUX; diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c index 50e68b7d43aa..8ac862c94879 100644 --- a/tools/perf/tests/parse-no-sample-id-all.c +++ b/tools/perf/tests/parse-no-sample-id-all.c @@ -82,6 +82,9 @@ static int test__parse_no_sample_id_all(struct test_suite *test __maybe_unused, .type = PERF_RECORD_HEADER_ATTR, .size = sizeof(struct test_attr_event), }, + .attr = { + .size = sizeof(struct perf_event_attr), + }, .id = 1, }; struct test_attr_event event2 = { @@ -89,6 +92,9 @@ static int test__parse_no_sample_id_all(struct test_suite *test __maybe_unused, .type = PERF_RECORD_HEADER_ATTR, .size = sizeof(struct test_attr_event), }, + .attr = { + .size = sizeof(struct perf_event_attr), + }, .id = 2, }; struct perf_record_mmap event3 = { diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index f30e48eb3fc3..967c3d8ff12c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -4770,9 +4770,15 @@ static int read_attr(int fd, struct perf_header *ph, if (sz == 0) { /* assume ABI0 */ sz = PERF_ATTR_SIZE_VER0; + } else if (sz < PERF_ATTR_SIZE_VER0) { + pr_debug("bad attr size %zu, expected at least %d\n", + sz, PERF_ATTR_SIZE_VER0); + errno = EINVAL; + return -1; } else if (sz > our_sz) { pr_debug("file uses a more recent and unsupported ABI" " (%zu bytes extra)\n", sz - our_sz); + errno = EINVAL; return -1; } /* what we have not yet read and that we know about */ @@ -4782,11 +4788,21 @@ static int read_attr(int fd, struct perf_header *ph, ptr += PERF_ATTR_SIZE_VER0; ret = readn(fd, ptr, left); + if (ret <= 0) { + if (ret == 0) + errno = EIO; + return -1; + } } /* read perf_file_section, ids are read in caller */ ret = readn(fd, &f_attr->ids, sizeof(f_attr->ids)); + if (ret <= 0) { + if (ret == 0) + errno = EIO; + return -1; + } - return ret <= 0 ? -1 : 0; + return 0; } #ifdef HAVE_LIBTRACEEVENT @@ -5094,11 +5110,42 @@ int perf_event__process_attr(const struct perf_tool *tool __maybe_unused, union perf_event *event, struct evlist **pevlist) { - u32 i, n_ids; + struct perf_event_attr attr; + u32 i, n_ids, raw_attr_size; u64 *ids; + size_t attr_size, copy_size; struct evsel *evsel; struct evlist *evlist = *pevlist; + /* + * HEADER_ATTR event layout (pipe/inject mode): + * + * [header (8 bytes)] [attr (attr_size bytes)] [id0 id1 ... idN] + * |<------------------ header.size --------------------------->| + * + * attr_size varies across perf versions: VER0 = 64 bytes, + * current sizeof(struct perf_event_attr) = larger. A newer + * producer may emit a larger attr than we understand. + * + * attr.size == 0 (ABI0) means the producer didn't set it + * (e.g., bench/inject-buildid, older perf). Treat as VER0. + * + * Require 8-byte alignment so the u64 ID array is aligned + * and attr.size fits cleanly within the payload. + * + * Read attr.size once — the event may be on a shared mmap + * and re-reading could yield a different value. + */ + raw_attr_size = event->attr.attr.size; + if (event->header.size < sizeof(event->header) + PERF_ATTR_SIZE_VER0 || + (raw_attr_size && (raw_attr_size < PERF_ATTR_SIZE_VER0 || + raw_attr_size % sizeof(u64) || + raw_attr_size > event->header.size - sizeof(event->header)))) { + pr_err("PERF_RECORD_HEADER_ATTR: invalid attr.size %u (event size %u, min %d)\n", + raw_attr_size, event->header.size, PERF_ATTR_SIZE_VER0); + return -EINVAL; + } + if (dump_trace) perf_event__fprintf_attr(event, stdout); @@ -5108,13 +5155,46 @@ int perf_event__process_attr(const struct perf_tool *tool __maybe_unused, return -ENOMEM; } - evsel = evsel__new(&event->attr.attr); + /* + * attr_size = footprint of the attr in the event — determines + * where the ID array starts. For ABI0, assume VER0 (64 bytes). + * + * copy_size = how much we copy into our local struct, capped at + * sizeof(attr) so a newer producer's larger attr doesn't + * overflow. Fields beyond copy_size are zeroed. + * + * Do NOT write attr_size back to the event — native-endian + * files use MAP_SHARED (read-only), writing would SIGSEGV. + * The swap path handles ABI0 in perf_event__attr_swap() + * which writes to the writable MAP_PRIVATE copy instead. + */ + attr_size = raw_attr_size ?: PERF_ATTR_SIZE_VER0; + copy_size = min(attr_size, sizeof(attr)); + memcpy(&attr, &event->attr.attr, copy_size); + if (copy_size < sizeof(attr)) + memset((void *)&attr + copy_size, 0, sizeof(attr) - copy_size); + + /* + * Normalize ABI0: the swap path sets attr.size = VER0 on the + * event, but the native path leaves it as 0. Set it on the + * local copy so perf inject re-synthesizes with consistent + * layout regardless of endianness. + */ + attr.size = attr_size; + + evsel = evsel__new(&attr); if (evsel == NULL) return -ENOMEM; evlist__add(evlist, evsel); - n_ids = event->header.size - sizeof(event->header) - event->attr.attr.size; + /* + * IDs occupy the remainder after header + attr. Use attr_size + * (not copy_size) — even if the producer's attr is larger than + * our struct, the IDs start after attr_size bytes in the event. + * Validation above guarantees attr_size <= payload size. + */ + n_ids = event->header.size - sizeof(event->header) - attr_size; n_ids = n_ids / sizeof(u64); /* * We don't have the cpu and thread maps on the header, so @@ -5124,7 +5204,13 @@ int perf_event__process_attr(const struct perf_tool *tool __maybe_unused, if (perf_evsel__alloc_id(&evsel->core, 1, n_ids)) return -ENOMEM; - ids = perf_record_header_attr_id(event); + /* + * Locate IDs at attr_size bytes past the attr start in the + * event. Cannot use perf_record_header_attr_id() — that + * macro reads event->attr.attr.size, which is 0 for ABI0 + * on the native-endian path (no swap handler to fix it up). + */ + ids = (void *)&event->attr.attr + attr_size; for (i = 0; i < n_ids; i++) { perf_evlist__id_add(&evlist->core, &evsel->core, 0, i, ids[i]); } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 3f72b80aac56..aef10d42be35 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -623,8 +623,39 @@ do { \ static int perf_event__hdr_attr_swap(union perf_event *event, bool sample_id_all __maybe_unused) { + u32 attr_size, payload_size; size_t size; + /* + * Validate attr.size (still foreign-endian) before calling + * perf_event__attr_swap(), which uses it via bswap_safe() + * to decide which fields to swap. A crafted attr.size + * larger than the event payload would swap past the event + * boundary and corrupt adjacent memory. + * + * header.size alignment is already validated by + * perf_session__process_event(). The min_size table + * guarantees header.size >= sizeof(header) + + * PERF_ATTR_SIZE_VER0, so attr.size is safe to access. + */ + attr_size = bswap_32(event->attr.attr.size); + /* + * ABI0: size field not set. This only happens in pipe/inject + * mode where HEADER_ATTR events carry their own attr. For + * regular perf.data files, read_attr() uses f_header.attr_size + * from the file header instead. Assume PERF_ATTR_SIZE_VER0. + */ + if (!attr_size) + attr_size = PERF_ATTR_SIZE_VER0; + payload_size = event->header.size - sizeof(event->header); + + if (attr_size < PERF_ATTR_SIZE_VER0 || attr_size % sizeof(u64) || + attr_size > payload_size) { + pr_err("PERF_RECORD_HEADER_ATTR: invalid attr.size %u (min: %d, max: %u, 8-byte aligned)\n", + attr_size, PERF_ATTR_SIZE_VER0, payload_size); + return -1; + } + perf_event__attr_swap(&event->attr.attr); size = event->header.size; diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index d665b0f94b32..5307d707711d 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -2181,11 +2181,21 @@ int perf_event__synthesize_attr(const struct perf_tool *tool, struct perf_event_ u32 ids, u64 *id, perf_event__handler_t process) { union perf_event *ev; - size_t size; + size_t attr_size, size; int err; - size = sizeof(struct perf_event_attr); - size = PERF_ALIGN(size, sizeof(u64)); + /* + * Use attr->size for the event layout, not the compiled + * sizeof(struct perf_event_attr), so that synthesized events + * match the source perf.data layout. This matters for perf + * inject, which re-synthesizes attrs from a file that may + * have been recorded by a different version of perf. + * perf_record_header_attr_id() locates the ID array at + * attr->size bytes past the attr. + */ + attr_size = attr->size ?: sizeof(struct perf_event_attr); + + size = PERF_ALIGN(attr_size, sizeof(u64)); size += sizeof(struct perf_event_header); size += ids * sizeof(u64); @@ -2194,7 +2204,14 @@ int perf_event__synthesize_attr(const struct perf_tool *tool, struct perf_event_ if (ev == NULL) return -ENOMEM; - ev->attr.attr = *attr; + /* + * Copy only the bytes we understand; zalloc ensures that any + * extra bytes between sizeof(struct perf_event_attr) and + * attr_size are zero when the source file uses a newer, larger + * struct. + */ + memcpy(&ev->attr.attr, attr, min(sizeof(struct perf_event_attr), attr_size)); + ev->attr.attr.size = attr_size; memcpy(perf_record_header_attr_id(ev), id, ids * sizeof(u64)); ev->attr.header.type = PERF_RECORD_HEADER_ATTR; From 5682175baf39cddefe6697ee3faed05928c26364 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 13:14:06 -0300 Subject: [PATCH 128/343] perf session: Validate nr fields against event size on both swap and common paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several event types use an nr field to control iteration over variable-length arrays. The swap handlers byte-swap and loop using these fields without bounds checks, and the native processing path trusts them as well. Add bounds checks on both paths for: - PERF_RECORD_THREAD_MAP: validate nr against payload, return -1 on the swap path. On the native path, reject with -EINVAL. - PERF_RECORD_NAMESPACES: clamp nr on the swap path (safe because each entry is indexed by type; missing entries just won't be resolved). Skip the event on the native path. - PERF_RECORD_CPU_MAP: clamp nr for CPUS and MASK sub-types on the swap path. Add bounds checks for mask64 which previously had no nr validation. Skip the event on the native path. - PERF_RECORD_STAT_CONFIG: clamp nr on the swap path (safe because each config entry is self-describing via its tag). Skip the event on the native path. The swap path (cross-endian, writable MAP_PRIVATE mapping) can safely clamp by writing back to the event. The native path (read-only MAP_SHARED mapping) must skip instead of clamping because writing to the mmap'd event would segfault. Also fix stat_config swap range: change size += 1 to size += sizeof(event->stat_config.nr) for clarity. The old +1 happened to work because mem_bswap_64 processes 8-byte chunks, but the intent is to include the 8-byte nr field in the swap range. Changes in v2: - Document that PERF_RECORD_NAMESPACES max_nr includes trailing sample_id space when sample_id_all is present — harmless on the swap path because both per-element bswap_64 and swap_sample_id_all() perform the same u64 byte swap (Reported-by: sashiko-bot@kernel.org) Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 253 +++++++++++++++++++++++++++++++++++--- 1 file changed, 234 insertions(+), 19 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index aef10d42be35..8588e12f110f 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -496,13 +496,35 @@ static int perf_event__throttle_swap(union perf_event *event, static int perf_event__namespaces_swap(union perf_event *event, bool sample_id_all) { - u64 i; + u64 i, nr, max_nr; event->namespaces.pid = bswap_32(event->namespaces.pid); event->namespaces.tid = bswap_32(event->namespaces.tid); event->namespaces.nr_namespaces = bswap_64(event->namespaces.nr_namespaces); - for (i = 0; i < event->namespaces.nr_namespaces; i++) { + nr = event->namespaces.nr_namespaces; + /* + * Cannot underflow: perf_event__min_size[] guarantees header.size >= sizeof. + * When sample_id_all is present max_nr slightly overestimates the + * array space because header.size includes the trailing sample_id. + * Harmless: both the per-element bswap_64 loop and swap_sample_id_all() + * perform the same u64 byte swap, so the result is correct regardless + * of where the boundary between array and sample_id falls. + */ + max_nr = (event->header.size - sizeof(event->namespaces)) / + sizeof(event->namespaces.link_info[0]); + /* + * Safe to clamp: each namespace entry is indexed by type; + * missing entries just won't be resolved. + */ + if (nr > max_nr) { + pr_warning("WARNING: PERF_RECORD_NAMESPACES: nr_namespaces %" PRIu64 " exceeds payload (max %" PRIu64 "), clamping\n", + nr, max_nr); + nr = max_nr; + event->namespaces.nr_namespaces = nr; + } + + for (i = 0; i < nr; i++) { struct perf_ns_link_info *ns = &event->namespaces.link_info[i]; ns->dev = bswap_64(ns->dev); @@ -734,11 +756,23 @@ static int perf_event__auxtrace_error_swap(union perf_event *event, static int perf_event__thread_map_swap(union perf_event *event, bool sample_id_all __maybe_unused) { - unsigned i; + unsigned int i; + u64 nr; event->thread_map.nr = bswap_64(event->thread_map.nr); - for (i = 0; i < event->thread_map.nr; i++) + /* + * Reject rather than clamp: unlike namespaces (indexed by type) + * or stat_config (self-describing tags), a truncated thread map + * is structurally broken — downstream would get a wrong map. + */ + /* Cannot underflow: perf_event__min_size[] guarantees header.size >= sizeof */ + nr = event->thread_map.nr; + if (nr > (event->header.size - sizeof(event->thread_map)) / + sizeof(event->thread_map.entries[0])) + return -1; + + for (i = 0; i < nr; i++) event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid); return 0; } @@ -747,32 +781,80 @@ static int perf_event__cpu_map_swap(union perf_event *event, bool sample_id_all __maybe_unused) { struct perf_record_cpu_map_data *data = &event->cpu_map.data; + u32 payload = event->header.size - sizeof(event->header); data->type = bswap_16(data->type); + /* + * Safe to clamp: a shorter CPU map just means some CPUs + * are absent; tools process the CPUs that are present. + */ switch (data->type) { - case PERF_CPU_MAP__CPUS: - data->cpus_data.nr = bswap_16(data->cpus_data.nr); + case PERF_CPU_MAP__CPUS: { + u16 nr, max_nr; - for (unsigned i = 0; i < data->cpus_data.nr; i++) + data->cpus_data.nr = bswap_16(data->cpus_data.nr); + nr = data->cpus_data.nr; + max_nr = (payload - offsetof(struct perf_record_cpu_map_data, + cpus_data.cpu)) / + sizeof(data->cpus_data.cpu[0]); + if (nr > max_nr) { + pr_warning("WARNING: PERF_RECORD_CPU_MAP: nr %u exceeds payload (max %u), clamping\n", + nr, max_nr); + nr = max_nr; + data->cpus_data.nr = nr; + } + for (unsigned int i = 0; i < nr; i++) data->cpus_data.cpu[i] = bswap_16(data->cpus_data.cpu[i]); break; + } case PERF_CPU_MAP__MASK: data->mask32_data.long_size = bswap_16(data->mask32_data.long_size); switch (data->mask32_data.long_size) { - case 4: + case 4: { + u16 nr, max_nr; + data->mask32_data.nr = bswap_16(data->mask32_data.nr); - for (unsigned i = 0; i < data->mask32_data.nr; i++) + nr = data->mask32_data.nr; + max_nr = (payload - offsetof(struct perf_record_cpu_map_data, + mask32_data.mask)) / + sizeof(data->mask32_data.mask[0]); + if (nr > max_nr) { + pr_warning("WARNING: PERF_RECORD_CPU_MAP mask32: nr %u exceeds payload (max %u), clamping\n", + nr, max_nr); + nr = max_nr; + data->mask32_data.nr = nr; + } + for (unsigned int i = 0; i < nr; i++) data->mask32_data.mask[i] = bswap_32(data->mask32_data.mask[i]); break; - case 8: + } + case 8: { + u16 nr, max_nr; + data->mask64_data.nr = bswap_16(data->mask64_data.nr); - for (unsigned i = 0; i < data->mask64_data.nr; i++) + nr = data->mask64_data.nr; + if (payload < offsetof(struct perf_record_cpu_map_data, mask64_data.mask)) { + data->mask64_data.nr = 0; + break; + } + max_nr = (payload - offsetof(struct perf_record_cpu_map_data, + mask64_data.mask)) / + sizeof(data->mask64_data.mask[0]); + if (nr > max_nr) { + pr_warning("WARNING: PERF_RECORD_CPU_MAP mask64: nr %u exceeds payload (max %u), clamping\n", + nr, max_nr); + nr = max_nr; + data->mask64_data.nr = nr; + } + for (unsigned int i = 0; i < nr; i++) data->mask64_data.mask[i] = bswap_64(data->mask64_data.mask[i]); break; + } default: - pr_err("cpu_map swap: unsupported long size\n"); + pr_err("cpu_map swap: unsupported long size %u\n", + data->mask32_data.long_size); } break; case PERF_CPU_MAP__RANGE_CPUS: @@ -788,11 +870,27 @@ static int perf_event__cpu_map_swap(union perf_event *event, static int perf_event__stat_config_swap(union perf_event *event, bool sample_id_all __maybe_unused) { - u64 size; + u64 nr, max_nr, size; - size = bswap_64(event->stat_config.nr) * sizeof(event->stat_config.data[0]); - size += 1; /* nr item itself */ + nr = bswap_64(event->stat_config.nr); + /* Cannot underflow: perf_event__min_size[] guarantees header.size >= sizeof */ + max_nr = (event->header.size - sizeof(event->stat_config)) / + sizeof(event->stat_config.data[0]); + /* + * Safe to clamp: each config entry is self-describing + * via its tag; missing entries keep their defaults. + */ + if (nr > max_nr) { + pr_warning("WARNING: PERF_RECORD_STAT_CONFIG: nr %" PRIu64 " exceeds payload (max %" PRIu64 "), clamping\n", + nr, max_nr); + nr = max_nr; + } + size = nr * sizeof(event->stat_config.data[0]); + /* The swap starts at &nr, so add its size to cover the full range */ + size += sizeof(event->stat_config.nr); mem_bswap_64(&event->stat_config.nr, size); + /* Persist the clamped value in native byte order */ + event->stat_config.nr = nr; return 0; } @@ -1730,8 +1828,27 @@ static int machines__deliver_event(struct machines *machines, "COMM")) return 0; return tool->comm(tool, event, sample, machine); - case PERF_RECORD_NAMESPACES: + case PERF_RECORD_NAMESPACES: { + /* + * Cannot underflow: perf_event__min_size[] guarantees header.size >= sizeof. + * Includes trailing sample_id space when present, but prevents OOB. + */ + u64 max_nr = (event->header.size - sizeof(event->namespaces)) / + sizeof(event->namespaces.link_info[0]); + + /* + * Native-endian events are mmap'd read-only, so we + * cannot clamp nr in place. Skip the event instead. + * The swap handler already clamps on the writable + * cross-endian path. + */ + if (event->namespaces.nr_namespaces > max_nr) { + pr_warning("WARNING: PERF_RECORD_NAMESPACES: nr_namespaces %" PRIu64 " exceeds payload (max %" PRIu64 "), skipping\n", + (u64)event->namespaces.nr_namespaces, max_nr); + return 0; + } return tool->namespaces(tool, event, sample, machine); + } case PERF_RECORD_CGROUP: if (!perf_event__check_nul(event->cgroup.path, (void *)event + event->header.size, @@ -1912,15 +2029,112 @@ static s64 perf_session__process_user_event(struct perf_session *session, perf_session__auxtrace_error_inc(session, event); err = tool->auxtrace_error(tool, session, event); break; - case PERF_RECORD_THREAD_MAP: + case PERF_RECORD_THREAD_MAP: { + u64 max_nr; + + if (event->header.size < sizeof(event->thread_map)) { + pr_err("PERF_RECORD_THREAD_MAP: header.size (%u) too small\n", + event->header.size); + err = -EINVAL; + break; + } + + max_nr = (event->header.size - sizeof(event->thread_map)) / + sizeof(event->thread_map.entries[0]); + if (event->thread_map.nr > max_nr) { + pr_err("PERF_RECORD_THREAD_MAP: nr %" PRIu64 " exceeds max %" PRIu64 "\n", + (u64)event->thread_map.nr, max_nr); + err = -EINVAL; + break; + } + err = tool->thread_map(tool, session, event); break; - case PERF_RECORD_CPU_MAP: + } + case PERF_RECORD_CPU_MAP: { + struct perf_record_cpu_map_data *data = &event->cpu_map.data; + u32 payload = event->header.size - sizeof(event->header); + + /* + * Native-endian events are mmap'd read-only, so we + * cannot clamp nr fields in place. Skip the event + * if any variant overflows. + */ + switch (data->type) { + case PERF_CPU_MAP__CPUS: { + u16 max_nr = (payload - offsetof(struct perf_record_cpu_map_data, + cpus_data.cpu)) / + sizeof(data->cpus_data.cpu[0]); + + if (data->cpus_data.nr > max_nr) { + pr_warning("WARNING: PERF_RECORD_CPU_MAP: nr %u exceeds payload (max %u), skipping\n", + data->cpus_data.nr, max_nr); + err = 0; + goto out; + } + break; + } + case PERF_CPU_MAP__MASK: + if (data->mask32_data.long_size == 4) { + u16 max_nr = (payload - offsetof(struct perf_record_cpu_map_data, + mask32_data.mask)) / + sizeof(data->mask32_data.mask[0]); + + if (data->mask32_data.nr > max_nr) { + pr_warning("WARNING: PERF_RECORD_CPU_MAP mask32: nr %u exceeds payload (max %u), skipping\n", + data->mask32_data.nr, max_nr); + err = 0; + goto out; + } + } else if (data->mask64_data.long_size == 8) { + u16 max_nr; + + if (payload < offsetof(struct perf_record_cpu_map_data, mask64_data.mask)) { + err = 0; + goto out; + } + max_nr = (payload - offsetof(struct perf_record_cpu_map_data, + mask64_data.mask)) / + sizeof(data->mask64_data.mask[0]); + if (data->mask64_data.nr > max_nr) { + pr_warning("WARNING: PERF_RECORD_CPU_MAP mask64: nr %u exceeds payload (max %u), skipping\n", + data->mask64_data.nr, max_nr); + err = 0; + goto out; + } + } else { + pr_warning("WARNING: PERF_RECORD_CPU_MAP: unsupported long_size %u, skipping\n", + data->mask32_data.long_size); + err = 0; + goto out; + } + break; + default: + break; + } + err = tool->cpu_map(tool, session, event); break; - case PERF_RECORD_STAT_CONFIG: + } + case PERF_RECORD_STAT_CONFIG: { + /* Cannot underflow: perf_event__min_size[] guarantees header.size >= sizeof */ + u64 max_nr = (event->header.size - sizeof(event->stat_config)) / + sizeof(event->stat_config.data[0]); + + /* + * Native-endian events are mmap'd read-only, so we + * cannot clamp nr in place. Skip the event instead. + */ + if (event->stat_config.nr > max_nr) { + pr_warning("WARNING: PERF_RECORD_STAT_CONFIG: nr %" PRIu64 " exceeds payload (max %" PRIu64 "), skipping\n", + (u64)event->stat_config.nr, max_nr); + err = 0; + goto out; + } + err = tool->stat_config(tool, session, event); break; + } case PERF_RECORD_STAT: err = tool->stat(tool, session, event); break; @@ -1963,6 +2177,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, err = -EINVAL; break; } +out: perf_sample__exit(&sample); return err; } From 23d6be944edd59f2e0a9a2a186388c0c58e85416 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 12:53:52 -0300 Subject: [PATCH 129/343] perf header: Byte-swap build ID event pid and bounds check section entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit perf_header__read_build_ids() swaps the event header fields for cross-endian perf.data files but not bev.pid. This causes perf_session__findnew_machine() to look up the wrong machine for guest VM build IDs, misattributing them. Swap bev.pid alongside the header fields. Also add a build_id_swap callback for stream-mode build ID events, and validate NUL-termination of build_id.filename on the native-endian delivery path (perf_session__process_user_event) — events with unterminated filenames are skipped. Harden perf_header__read_build_ids() against crafted perf.data files: - Add overflow check on offset + size to prevent wrap past ULLONG_MAX. - Reject bev.header.size == 0 which would loop forever. - Reject bev.header.size > remaining section to prevent reading past the section boundary. - Guard memcmp(filename, "nel.kallsyms]", 13) with len >= 13 to avoid reading uninitialized stack memory on short filenames. - Force NUL-termination of filename before passing it to functions like machine__findnew_dso() that use strlen/strcmp. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 50 +++++++++++++++++++++++++++++++++++---- tools/perf/util/session.c | 27 ++++++++++++++++++++- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 967c3d8ff12c..c0b5c99f462a 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include "string2.h" #include #include @@ -2578,7 +2579,13 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, } old_bev; struct perf_record_header_build_id bev; char filename[PATH_MAX]; - u64 limit = offset + size; + u64 limit; + + /* Prevent offset + size from wrapping past ULLONG_MAX */ + if (size > ULLONG_MAX - offset) + return -1; + + limit = offset + size; while (offset < limit) { ssize_t len; @@ -2589,6 +2596,10 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, if (header->needs_swap) perf_event_header__bswap(&old_bev.header); + /* size == 0 loops forever; size > remaining reads past section */ + if (old_bev.header.size == 0 || old_bev.header.size > limit - offset) + return -1; + len = old_bev.header.size - sizeof(old_bev); if (len < 0 || len >= PATH_MAX) { pr_warning("invalid build_id filename length %zd\n", len); @@ -2597,6 +2608,13 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, if (readn(input, filename, len) != len) return -1; + /* + * The file data may lack a null terminator, which could + * indicate a corrupt or crafted perf.data file. Ensure + * filename is always a valid C string before passing it + * to functions like machine__findnew_dso(). + */ + filename[len] = '\0'; bev.header = old_bev.header; @@ -2624,17 +2642,32 @@ static int perf_header__read_build_ids(struct perf_header *header, struct perf_session *session = container_of(header, struct perf_session, header); struct perf_record_header_build_id bev; char filename[PATH_MAX]; - u64 limit = offset + size, orig_offset = offset; + u64 limit, orig_offset = offset; int err = -1; + /* Prevent offset + size from wrapping past ULLONG_MAX */ + if (size > ULLONG_MAX - offset) + return -1; + + limit = offset + size; + while (offset < limit) { ssize_t len; if (readn(input, &bev, sizeof(bev)) != sizeof(bev)) goto out; - if (header->needs_swap) + if (header->needs_swap) { perf_event_header__bswap(&bev.header); + bev.pid = bswap_32(bev.pid); + } + + /* + * size == 0 would loop forever (offset never advances); + * size > remaining would read past the section boundary. + */ + if (bev.header.size == 0 || bev.header.size > limit - offset) + goto out; len = bev.header.size - sizeof(bev); if (len < 0 || len >= PATH_MAX) { @@ -2644,6 +2677,13 @@ static int perf_header__read_build_ids(struct perf_header *header, if (readn(input, filename, len) != len) goto out; + /* + * The file data may lack a null terminator, which could + * indicate a corrupt or crafted perf.data file. Ensure + * filename is always a valid C string before passing it + * to functions like machine__findnew_dso(). + */ + filename[len] = '\0'; /* * The a1645ce1 changeset: * @@ -2657,7 +2697,9 @@ static int perf_header__read_build_ids(struct perf_header *header, * '[kernel.kallsyms]' string for the kernel build-id has the * first 4 characters chopped off (where the pid_t sits). */ - if (memcmp(filename, "nel.kallsyms]", 13) == 0) { + /* Guard short filenames against memcmp reading past the buffer */ + if (len >= (ssize_t)sizeof("nel.kallsyms]") - 1 && + memcmp(filename, "nel.kallsyms]", sizeof("nel.kallsyms]") - 1) == 0) { if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1) return -1; return perf_header__read_build_ids_abi_quirk(header, input, offset, size); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 8588e12f110f..0fac8f4e0e22 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -686,6 +686,25 @@ static int perf_event__hdr_attr_swap(union perf_event *event, return 0; } +static int perf_event__build_id_swap(union perf_event *event, + bool sample_id_all) +{ + event->build_id.pid = bswap_32(event->build_id.pid); + + if (sample_id_all) { + void *data = &event->build_id.filename; + void *end = (void *)event + event->header.size; + size_t len = strnlen(data, end - data); + + /* See comment in perf_event__comm_swap() */ + if (len == (size_t)(end - data)) + return -1; + data += PERF_ALIGN(len + 1, sizeof(u64)); + swap_sample_id_all(event, data); + } + return 0; +} + static int perf_event__event_update_swap(union perf_event *event, bool sample_id_all __maybe_unused) { @@ -1014,7 +1033,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, - [PERF_RECORD_HEADER_BUILD_ID] = NULL, + [PERF_RECORD_HEADER_BUILD_ID] = perf_event__build_id_swap, [PERF_RECORD_HEADER_FEATURE] = perf_event__header_feature_swap, [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap, @@ -2004,6 +2023,12 @@ static s64 perf_session__process_user_event(struct perf_session *session, err = tool->tracing_data(tool, session, event); break; case PERF_RECORD_HEADER_BUILD_ID: + if (!perf_event__check_nul(event->build_id.filename, + (void *)event + event->header.size, + "HEADER_BUILD_ID")) { + err = 0; + break; + } err = tool->build_id(tool, session, event); break; case PERF_RECORD_FINISHED_ROUND: From f11a797cb6a8707be7e18603519406076c90efe3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 4 May 2026 11:17:19 -0300 Subject: [PATCH 130/343] perf cpumap: Reject RANGE_CPUS with start_cpu > end_cpu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cpu_map__from_range() computes nr_cpus as end_cpu - start_cpu + 1. When a crafted perf.data has start_cpu > end_cpu, this wraps to a huge value, causing perf_cpu_map__empty_new() to attempt a massive allocation. Return NULL when the range is inverted. Also clamp any_cpu to boolean (0 or 1) since it is added to the allocation count — a crafted value > 1 would inflate the map size. Harden cpu_map__from_mask() to reject unsupported long_size values (anything other than 4 or 8), preventing misinterpretation of the mask data layout. Snapshot mmap'd fields via READ_ONCE() into locals to prevent TOCTOU re-reads — the data pointer references MAP_SHARED mmap'd memory that could theoretically change between reads on a FUSE-backed file: - cpu_map__from_range(): snapshot start_cpu, end_cpu, any_cpu - cpu_map__from_entries(): snapshot nr and each cpu[i] element - cpu_map__from_mask(): snapshot long_size (before validation, closing the check-then-read gap), mask_nr - perf_record_cpu_map_data__read_one_mask(): add u16 long_size parameter so callers pass the validated copy instead of re-reading data->mask32_data.long_size from mmap'd memory Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cpumap.c | 62 +++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 11922e1ded84..b1e5c29c6e3e 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -10,6 +10,7 @@ #include #include "asm/bug.h" +#include #include #include #include @@ -40,15 +41,16 @@ bool perf_record_cpu_map_data__test_bit(int i, /* Read ith mask value from data into the given 64-bit sized bitmap */ static void perf_record_cpu_map_data__read_one_mask(const struct perf_record_cpu_map_data *data, - int i, unsigned long *bitmap) + int i, unsigned long *bitmap, + u16 long_size) { #if __SIZEOF_LONG__ == 8 - if (data->mask32_data.long_size == 4) + if (long_size == 4) bitmap[0] = data->mask32_data.mask[i]; else bitmap[0] = data->mask64_data.mask[i]; #else - if (data->mask32_data.long_size == 4) { + if (long_size == 4) { bitmap[0] = data->mask32_data.mask[i]; bitmap[1] = 0; } else { @@ -64,24 +66,27 @@ static void perf_record_cpu_map_data__read_one_mask(const struct perf_record_cpu } static struct perf_cpu_map *cpu_map__from_entries(const struct perf_record_cpu_map_data *data) { + /* Snapshot nr — data is mmap'd and could change between reads */ + u16 nr = READ_ONCE(data->cpus_data.nr); struct perf_cpu_map *map; - map = perf_cpu_map__empty_new(data->cpus_data.nr); + map = perf_cpu_map__empty_new(nr); if (!map) return NULL; - for (unsigned int i = 0; i < data->cpus_data.nr; i++) { + for (unsigned int i = 0; i < nr; i++) { + u16 cpu = READ_ONCE(data->cpus_data.cpu[i]); /* * Special treatment for -1, which is not real cpu number, * and we need to use (int) -1 to initialize map[i], * otherwise it would become 65535. */ - if (data->cpus_data.cpu[i] == (u16) -1) { + if (cpu == (u16) -1) { RC_CHK_ACCESS(map)->map[i].cpu = -1; - } else if (data->cpus_data.cpu[i] < INT16_MAX) { - RC_CHK_ACCESS(map)->map[i].cpu = (int16_t) data->cpus_data.cpu[i]; + } else if (cpu < INT16_MAX) { + RC_CHK_ACCESS(map)->map[i].cpu = (int16_t) cpu; } else { - pr_err("Invalid cpumap entry %u\n", data->cpus_data.cpu[i]); + pr_err("Invalid cpumap entry %u\n", cpu); perf_cpu_map__put(map); return NULL; } @@ -93,11 +98,21 @@ static struct perf_cpu_map *cpu_map__from_entries(const struct perf_record_cpu_m static struct perf_cpu_map *cpu_map__from_mask(const struct perf_record_cpu_map_data *data) { DECLARE_BITMAP(local_copy, 64); - int weight = 0, mask_nr = data->mask32_data.nr; + int weight = 0, mask_nr; + /* Snapshot before validation — data is mmap'd and could change */ + u16 long_size = READ_ONCE(data->mask32_data.long_size); struct perf_cpu_map *map; + /* long_size must be 4 or 8; other values overflow cpus_per_i below */ + if (long_size != 4 && long_size != 8) { + pr_warning("WARNING: cpu_map mask: unsupported long_size %u\n", long_size); + return NULL; + } + + mask_nr = READ_ONCE(data->mask32_data.nr); + for (int i = 0; i < mask_nr; i++) { - perf_record_cpu_map_data__read_one_mask(data, i, local_copy); + perf_record_cpu_map_data__read_one_mask(data, i, local_copy, long_size); weight += bitmap_weight(local_copy, 64); } @@ -106,11 +121,14 @@ static struct perf_cpu_map *cpu_map__from_mask(const struct perf_record_cpu_map_ return NULL; for (int i = 0, j = 0; i < mask_nr; i++) { - int cpus_per_i = (i * data->mask32_data.long_size * BITS_PER_BYTE); + int cpus_per_i = (i * long_size * BITS_PER_BYTE); int cpu; - perf_record_cpu_map_data__read_one_mask(data, i, local_copy); + perf_record_cpu_map_data__read_one_mask(data, i, local_copy, long_size); for_each_set_bit(cpu, local_copy, 64) { + /* Guard against more set bits than the first pass counted */ + if (j >= weight) + break; if (cpu + cpus_per_i < INT16_MAX) { RC_CHK_ACCESS(map)->map[j++].cpu = cpu + cpus_per_i; } else { @@ -126,18 +144,28 @@ static struct perf_cpu_map *cpu_map__from_mask(const struct perf_record_cpu_map_ static struct perf_cpu_map *cpu_map__from_range(const struct perf_record_cpu_map_data *data) { + /* Snapshot fields — data is mmap'd and could change between reads */ + u16 start_cpu = READ_ONCE(data->range_cpu_data.start_cpu); + u16 end_cpu = READ_ONCE(data->range_cpu_data.end_cpu); + u16 any_cpu = READ_ONCE(data->range_cpu_data.any_cpu); struct perf_cpu_map *map; unsigned int i = 0; - map = perf_cpu_map__empty_new(data->range_cpu_data.end_cpu - - data->range_cpu_data.start_cpu + 1 + data->range_cpu_data.any_cpu); + if (end_cpu < start_cpu) { + pr_warning("WARNING: cpu_map range: end_cpu %u < start_cpu %u\n", + end_cpu, start_cpu); + return NULL; + } + + /* any_cpu is boolean (0 or 1), not a count — clamp to avoid inflated nr */ + map = perf_cpu_map__empty_new(end_cpu - start_cpu + 1 + !!any_cpu); if (!map) return NULL; - if (data->range_cpu_data.any_cpu) + if (any_cpu) RC_CHK_ACCESS(map)->map[i++].cpu = -1; - for (int cpu = data->range_cpu_data.start_cpu; cpu <= data->range_cpu_data.end_cpu; + for (int cpu = start_cpu; cpu <= end_cpu; i++, cpu++) { if (cpu < INT16_MAX) { RC_CHK_ACCESS(map)->map[i].cpu = cpu; From 97cd22555c6dd3c5124ff16417fa66dd7bb844be Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 13:18:45 -0300 Subject: [PATCH 131/343] perf auxtrace: Harden auxtrace_error event handling Fix four issues in PERF_RECORD_AUXTRACE_ERROR handling: 1. auxtrace_error_name() takes a signed int parameter, but e->type is __u32. A crafted value like 0xFFFFFFFF converts to -1, passes the bounds check, and causes a negative array index. Fix by changing the parameter to unsigned int. 2. The msg field is printed via %s without a length bound. The min_size table only guarantees fields up to msg (offset 48), so a truncated event has zero msg bytes within the event boundary. Compute the available msg length from header.size, cap at sizeof(e->msg), and use %.*s. 3. fmt >= 2 adds machine_pid and vcpu fields after msg[64]. Older files may have fmt >= 2 but an event size that doesn't include these fields. Add a size check in the swap handler to downgrade fmt before the conditional field access, and a matching size guard in the fprintf path for native-endian events (which are mmap'd read-only and can't be modified in place). 4. python_process_auxtrace_error() had the same issues: msg was passed to tuple_set_string() unbounded, and machine_pid/vcpu were accessed unconditionally without checking fmt or event size. Apply the same bounds checks. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/auxtrace.c | 24 +++++++++++++--- .../scripting-engines/trace-event-python.c | 28 +++++++++++++++++-- tools/perf/util/session.c | 18 ++++++++++-- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index a9f007d47c0b..fcf564e0d777 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -1774,7 +1774,7 @@ static const char * const auxtrace_error_type_name[] = { [PERF_AUXTRACE_ERROR_ITRACE] = "instruction trace", }; -static const char *auxtrace_error_name(int type) +static const char *auxtrace_error_name(unsigned int type) { const char *error_type_name = NULL; @@ -1790,6 +1790,7 @@ size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp) struct perf_record_auxtrace_error *e = &event->auxtrace_error; unsigned long long nsecs = e->time; const char *msg = e->msg; + int msg_max; int ret; ret = fprintf(fp, " %s error type %u", @@ -1807,11 +1808,26 @@ size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp) if (!e->fmt) msg = (const char *)&e->time; - if (e->fmt >= 2 && e->machine_pid) + /* Bound msg to the bytes actually within the event, capped at the array size */ + msg_max = (int)((void *)event + event->header.size - (void *)msg); + if (msg_max < 0) + msg_max = 0; + if (msg_max > (int)sizeof(e->msg)) + msg_max = sizeof(e->msg); + + /* + * Unlike the swap path which downgrades fmt in place, + * native-endian events are mmap'd read-only — check size + * instead to avoid accessing machine_pid/vcpu OOB. + */ + if (e->fmt >= 2 && + event->header.size >= offsetof(typeof(event->auxtrace_error), vcpu) + + sizeof(event->auxtrace_error.vcpu) && + e->machine_pid) ret += fprintf(fp, " machine_pid %d vcpu %d", e->machine_pid, e->vcpu); - ret += fprintf(fp, " cpu %d pid %d tid %d ip %#"PRI_lx64" code %u: %s\n", - e->cpu, e->pid, e->tid, e->ip, e->code, msg); + ret += fprintf(fp, " cpu %d pid %d tid %d ip %#"PRI_lx64" code %u: %.*s\n", + e->cpu, e->pid, e->tid, e->ip, e->code, msg_max, msg); return ret; } diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 8edd2f36e5a9..cee1f32d7022 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -1607,6 +1607,9 @@ static void python_process_auxtrace_error(struct perf_session *session __maybe_u const char *handler_name = "auxtrace_error"; unsigned long long tm = e->time; const char *msg = e->msg; + s32 machine_pid = 0, vcpu = 0; + char msg_buf[MAX_AUXTRACE_ERROR_MSG + 1]; + int msg_max; PyObject *handler, *t; handler = get_handler(handler_name); @@ -1618,6 +1621,25 @@ static void python_process_auxtrace_error(struct perf_session *session __maybe_u msg = (const char *)&e->time; } + /* Bound msg to the bytes within the event, ensure NUL-termination */ + msg_max = (int)((void *)event + event->header.size - (void *)msg); + if (msg_max <= 0) { + msg_buf[0] = '\0'; + } else { + if (msg_max > (int)sizeof(msg_buf) - 1) + msg_max = sizeof(msg_buf) - 1; + memcpy(msg_buf, msg, msg_max); + msg_buf[msg_max] = '\0'; + } + + /* Only access fmt >= 2 fields if the event is large enough */ + if (e->fmt >= 2 && + event->header.size >= offsetof(typeof(event->auxtrace_error), vcpu) + + sizeof(event->auxtrace_error.vcpu)) { + machine_pid = e->machine_pid; + vcpu = e->vcpu; + } + t = tuple_new(11); tuple_set_u32(t, 0, e->type); @@ -1627,10 +1649,10 @@ static void python_process_auxtrace_error(struct perf_session *session __maybe_u tuple_set_s32(t, 4, e->tid); tuple_set_u64(t, 5, e->ip); tuple_set_u64(t, 6, tm); - tuple_set_string(t, 7, msg); + tuple_set_string(t, 7, msg_buf); tuple_set_u32(t, 8, cpumode); - tuple_set_s32(t, 9, e->machine_pid); - tuple_set_s32(t, 10, e->vcpu); + tuple_set_s32(t, 9, machine_pid); + tuple_set_s32(t, 10, vcpu); call_object(handler, t, handler_name); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0fac8f4e0e22..092fccbea8f8 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -766,8 +766,22 @@ static int perf_event__auxtrace_error_swap(union perf_event *event, if (event->auxtrace_error.fmt) event->auxtrace_error.time = bswap_64(event->auxtrace_error.time); if (event->auxtrace_error.fmt >= 2) { - event->auxtrace_error.machine_pid = bswap_32(event->auxtrace_error.machine_pid); - event->auxtrace_error.vcpu = bswap_32(event->auxtrace_error.vcpu); + /* + * fmt >= 2 adds machine_pid and vcpu after msg[64]. + * Older files may have fmt >= 2 but an event size + * that doesn't include these fields — downgrade to + * avoid swapping out of bounds. + */ + if (event->header.size < offsetof(typeof(event->auxtrace_error), vcpu) + + sizeof(event->auxtrace_error.vcpu)) { + pr_warning("WARNING: PERF_RECORD_AUXTRACE_ERROR: fmt %u but event too small for machine_pid/vcpu (%u bytes), downgrading fmt\n", + event->auxtrace_error.fmt, + event->header.size); + event->auxtrace_error.fmt = 1; + } else { + event->auxtrace_error.machine_pid = bswap_32(event->auxtrace_error.machine_pid); + event->auxtrace_error.vcpu = bswap_32(event->auxtrace_error.vcpu); + } } return 0; } From 355ca55e3e96ea272b330f3fb80401472f60d18c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 13:26:51 -0300 Subject: [PATCH 132/343] perf session: Add byte-swap and bounds check for PERF_RECORD_BPF_METADATA events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PERF_RECORD_BPF_METADATA has no entry in perf_event__swap_ops[], so its nr_entries field is never byte-swapped when reading a cross-endian perf.data file. Downstream processing in perf_event__fprintf_bpf_metadata() loops over nr_entries, so a foreign-endian value causes out-of-bounds reads. Add a swap handler that byte-swaps nr_entries after validating that header.size is large enough. The entries[] array contains only char arrays (key/value strings), so no per-entry swap is needed — but ensure NUL-termination on the writable cross-endian path. Validate header.size, nr_entries, and string NUL-termination in the common event delivery path so that native-endian files with malicious values are also rejected. Snapshot nr_entries via READ_ONCE() before validation — the event is on a MAP_SHARED mmap that could theoretically change between the bounds check and the loop. Changes in v2: - Snapshot event->header.size via READ_ONCE() into a local variable to prevent a double-fetch underflow in the max_entries calculation (Reported-by: sashiko-bot@kernel.org) - Write back clamped nr_entries to the event on the swap path, consistent with NAMESPACES and STAT_CONFIG handlers — without writeback the native path sees the inflated nr and skips the event entirely (Reported-by: sashiko-bot@kernel.org) Fixes: ab38e84ba9a8 ("perf record: collect BPF metadata from existing BPF programs") Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Blake Jones Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 89 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 092fccbea8f8..95eb793026de 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -961,6 +961,48 @@ static int perf_event__time_conv_swap(union perf_event *event, return 0; } +static int perf_event__bpf_metadata_swap(union perf_event *event, + bool sample_id_all __maybe_unused) +{ + u64 i, nr, max_nr; + + /* Fixed header must fit before accessing nr_entries or prog_name */ + if (event->header.size < sizeof(event->bpf_metadata)) + return -1; + + event->bpf_metadata.nr_entries = bswap_64(event->bpf_metadata.nr_entries); + + /* + * Ensure NUL-termination on the cross-endian path where the + * mapping is writable (MAP_PRIVATE + PROT_WRITE). Fixing + * the string in place is preferred over rejecting because it + * preserves the event for downstream processing — only the + * last byte is lost. + * + * The native-endian path (MAP_SHARED + PROT_READ) cannot + * write, so it validates and skips unterminated events in + * perf_session__process_user_event() instead. The two + * strategies produce different outcomes for the same + * malformed input (fix vs skip), which is inherent in the + * writable-vs-read-only mapping model. + */ + event->bpf_metadata.prog_name[BPF_PROG_NAME_LEN - 1] = '\0'; + + nr = event->bpf_metadata.nr_entries; + max_nr = (event->header.size - sizeof(event->bpf_metadata)) / + sizeof(event->bpf_metadata.entries[0]); + if (nr > max_nr) { + /* Persist clamped value so the native path processes entries, not skips */ + nr = max_nr; + event->bpf_metadata.nr_entries = nr; + } + + for (i = 0; i < nr; i++) { + event->bpf_metadata.entries[i].key[BPF_METADATA_KEY_LEN - 1] = '\0'; + event->bpf_metadata.entries[i].value[BPF_METADATA_VALUE_LEN - 1] = '\0'; + } + return 0; +} static int perf_event__schedstat_cpu_swap(union perf_event *event __maybe_unused, bool sample_id_all __maybe_unused) @@ -1060,6 +1102,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, [PERF_RECORD_TIME_CONV] = perf_event__time_conv_swap, + [PERF_RECORD_BPF_METADATA] = perf_event__bpf_metadata_swap, [PERF_RECORD_SCHEDSTAT_CPU] = perf_event__schedstat_cpu_swap, [PERF_RECORD_SCHEDSTAT_DOMAIN] = perf_event__schedstat_domain_swap, [PERF_RECORD_HEADER_MAX] = NULL, @@ -2203,9 +2246,53 @@ static s64 perf_session__process_user_event(struct perf_session *session, case PERF_RECORD_FINISHED_INIT: err = tool->finished_init(tool, session, event); break; - case PERF_RECORD_BPF_METADATA: + case PERF_RECORD_BPF_METADATA: { + u64 nr_entries, max_entries; + u32 hdr_size = READ_ONCE(event->header.size); + + if (hdr_size < sizeof(event->bpf_metadata)) { + pr_warning("WARNING: PERF_RECORD_BPF_METADATA: header.size (%u) too small, skipping\n", + hdr_size); + err = 0; + break; + } + + /* + * Native-endian files are mmap'd read-only — validate + * NUL-termination instead of writing. + */ + if (strnlen(event->bpf_metadata.prog_name, + BPF_PROG_NAME_LEN) == BPF_PROG_NAME_LEN) { + pr_warning("WARNING: PERF_RECORD_BPF_METADATA: prog_name not null-terminated, skipping\n"); + err = 0; + break; + } + + /* Snapshot — event is mmap'd and could change between reads */ + nr_entries = READ_ONCE(event->bpf_metadata.nr_entries); + max_entries = (hdr_size - sizeof(event->bpf_metadata)) / + sizeof(event->bpf_metadata.entries[0]); + if (nr_entries > max_entries) { + pr_warning("WARNING: PERF_RECORD_BPF_METADATA: nr_entries %" PRIu64 " exceeds max %" PRIu64 ", skipping\n", + nr_entries, max_entries); + err = 0; + break; + } + + for (u64 i = 0; i < nr_entries; i++) { + if (strnlen(event->bpf_metadata.entries[i].key, + BPF_METADATA_KEY_LEN) == BPF_METADATA_KEY_LEN || + strnlen(event->bpf_metadata.entries[i].value, + BPF_METADATA_VALUE_LEN) == BPF_METADATA_VALUE_LEN) { + pr_warning("WARNING: PERF_RECORD_BPF_METADATA: entry %" PRIu64 " key/value not null-terminated, skipping\n", i); + err = 0; + goto out; + } + } + err = tool->bpf_metadata(tool, session, event); break; + } case PERF_RECORD_SCHEDSTAT_CPU: err = tool->schedstat_cpu(tool, session, event); break; From 3c18544fb18b18fa824d072fc6a22e8d9f6dc070 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 13:31:40 -0300 Subject: [PATCH 133/343] perf header: Validate null-termination in PERF_RECORD_EVENT_UPDATE string fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit strdup(ev->unit) and strdup(ev->name) read until '\0' with no guarantee the string is null-terminated within event->header.size. The dump_trace fprintf path has the same problem with %s. Validate before either path runs — same class of bug fixed for MMAP/MMAP2/COMM/CGROUP by perf_event__check_nul(). Also harden the event_update swap handler to: - Validate SCALE event size before swapping the double at offset 24, which exceeds the 24-byte min_size. - Validate CPUS event size before accessing the cpu_map type/nr/long_size fields, which also start at the min_size boundary. - Swap CPUS variant fields (type, nr, long_size) so the processing path sees native byte order. Add validation in perf_event__process_event_update() for all event update variants (UNIT, NAME, SCALE, CPUS) before dump_trace or processing. Validate CPUS nr against payload size for both PERF_CPU_MAP__CPUS and PERF_CPU_MAP__MASK types on the fprintf (dump_trace) path: - CPUS: check nr does not exceed available cpu entries - MASK: check nr does not exceed available mask entries for both mask32 (long_size == 4) and mask64 (long_size == 8) layouts, with underflow guards on the offsetof subtraction Fix a missing break before the default case in the CPUS switch path. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 150 ++++++++++++++++++++++++++++++++++++-- tools/perf/util/session.c | 99 ++++++++++++++++++++++++- 2 files changed, 242 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index c0b5c99f462a..9e3a08b1f8ae 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -5117,15 +5117,76 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp) switch (ev->type) { case PERF_EVENT_UPDATE__SCALE: + if (event->header.size < offsetof(struct perf_record_event_update, scale) + + sizeof(ev->scale)) { + ret += fprintf(fp, "... scale: (truncated)\n"); + break; + } ret += fprintf(fp, "... scale: %f\n", ev->scale.scale); break; case PERF_EVENT_UPDATE__UNIT: - ret += fprintf(fp, "... unit: %s\n", ev->unit); + case PERF_EVENT_UPDATE__NAME: { + size_t str_off = offsetof(struct perf_record_event_update, unit); + size_t max_len = event->header.size > str_off ? + event->header.size - str_off : 0; + + if (max_len == 0 || strnlen(ev->unit, max_len) == max_len) { + ret += fprintf(fp, "... %s: (unterminated)\n", + ev->type == PERF_EVENT_UPDATE__UNIT ? "unit" : "name"); + break; + } + ret += fprintf(fp, "... %s: %s\n", + ev->type == PERF_EVENT_UPDATE__UNIT ? "unit" : "name", + ev->unit); break; - case PERF_EVENT_UPDATE__NAME: - ret += fprintf(fp, "... name: %s\n", ev->name); - break; - case PERF_EVENT_UPDATE__CPUS: + } + case PERF_EVENT_UPDATE__CPUS: { + size_t cpus_off = offsetof(struct perf_record_event_update, cpus); + u32 cpus_payload; + + if (event->header.size < cpus_off + sizeof(__u16) + + sizeof(struct perf_record_range_cpu_map)) { + ret += fprintf(fp, "... cpus: (truncated)\n"); + break; + } + + /* + * Validate nr against payload — this function may be + * called from the stub handler (dump_trace path) which + * bypasses perf_event__process_event_update() validation. + */ + cpus_payload = event->header.size - cpus_off; + if (ev->cpus.cpus.type == PERF_CPU_MAP__CPUS) { + if (cpus_payload < offsetof(struct perf_record_cpu_map_data, cpus_data.cpu) || + ev->cpus.cpus.cpus_data.nr > + (cpus_payload - offsetof(struct perf_record_cpu_map_data, cpus_data.cpu)) / + sizeof(ev->cpus.cpus.cpus_data.cpu[0])) { + ret += fprintf(fp, "... cpus: nr %u exceeds payload\n", + ev->cpus.cpus.cpus_data.nr); + break; + } + } else if (ev->cpus.cpus.type == PERF_CPU_MAP__MASK) { + if (ev->cpus.cpus.mask32_data.long_size == 4) { + if (cpus_payload < offsetof(struct perf_record_cpu_map_data, mask32_data.mask) || + ev->cpus.cpus.mask32_data.nr > + (cpus_payload - offsetof(struct perf_record_cpu_map_data, mask32_data.mask)) / + sizeof(ev->cpus.cpus.mask32_data.mask[0])) { + ret += fprintf(fp, "... cpus: mask nr %u exceeds payload\n", + ev->cpus.cpus.mask32_data.nr); + break; + } + } else if (ev->cpus.cpus.mask64_data.long_size == 8) { + if (cpus_payload < offsetof(struct perf_record_cpu_map_data, mask64_data.mask) || + ev->cpus.cpus.mask64_data.nr > + (cpus_payload - offsetof(struct perf_record_cpu_map_data, mask64_data.mask)) / + sizeof(ev->cpus.cpus.mask64_data.mask[0])) { + ret += fprintf(fp, "... cpus: mask nr %u exceeds payload\n", + ev->cpus.cpus.mask64_data.nr); + break; + } + } + } + ret += fprintf(fp, "... "); map = cpu_map__new_data(&ev->cpus.cpus); @@ -5135,6 +5196,7 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp) } else ret += fprintf(fp, "failed to get cpus\n"); break; + } default: ret += fprintf(fp, "... unknown type\n"); break; @@ -5269,6 +5331,83 @@ int perf_event__process_event_update(const struct perf_tool *tool __maybe_unused struct evsel *evsel; struct perf_cpu_map *map; + /* + * Validate payload before dump_trace or processing — both + * paths access variant-specific fields without further checks. + */ + if (ev->type == PERF_EVENT_UPDATE__UNIT || + ev->type == PERF_EVENT_UPDATE__NAME) { + size_t str_off = offsetof(struct perf_record_event_update, unit); + size_t max_len = event->header.size > str_off ? + event->header.size - str_off : 0; + + if (max_len == 0 || strnlen(ev->unit, max_len) == max_len) { + pr_warning("WARNING: PERF_RECORD_EVENT_UPDATE: %s not null-terminated, skipping\n", + ev->type == PERF_EVENT_UPDATE__UNIT ? "unit" : "name"); + return 0; + } + } else if (ev->type == PERF_EVENT_UPDATE__SCALE) { + if (event->header.size < offsetof(struct perf_record_event_update, scale) + + sizeof(ev->scale)) { + pr_warning("WARNING: PERF_RECORD_EVENT_UPDATE: SCALE payload too small, skipping\n"); + return 0; + } + } else if (ev->type == PERF_EVENT_UPDATE__CPUS) { + size_t cpus_off = offsetof(struct perf_record_event_update, cpus); + size_t min_cpus = sizeof(__u16) + + sizeof(struct perf_record_range_cpu_map); + u32 cpus_payload; + + if (event->header.size < cpus_off + min_cpus) { + pr_warning("WARNING: PERF_RECORD_EVENT_UPDATE: CPUS payload too small, skipping\n"); + return 0; + } + + /* + * Validate per-variant nr against the remaining + * payload on the native path — the swap path clamps + * nr in perf_event__event_update_swap(), but native + * events are read-only and cannot be clamped in place. + * cpu_map__new_data() trusts nr for allocation and + * iteration, so unchecked values cause OOB reads. + */ + cpus_payload = event->header.size - cpus_off; + switch (ev->cpus.cpus.type) { + case PERF_CPU_MAP__CPUS: + if (ev->cpus.cpus.cpus_data.nr > + (cpus_payload - offsetof(struct perf_record_cpu_map_data, cpus_data.cpu)) / + sizeof(ev->cpus.cpus.cpus_data.cpu[0])) { + pr_warning("WARNING: EVENT_UPDATE CPUS: nr %u exceeds payload, skipping\n", + ev->cpus.cpus.cpus_data.nr); + return 0; + } + break; + case PERF_CPU_MAP__MASK: + if (ev->cpus.cpus.mask32_data.long_size == 4) { + if (cpus_payload < offsetof(struct perf_record_cpu_map_data, mask32_data.mask) || + ev->cpus.cpus.mask32_data.nr > + (cpus_payload - offsetof(struct perf_record_cpu_map_data, mask32_data.mask)) / + sizeof(ev->cpus.cpus.mask32_data.mask[0])) { + pr_warning("WARNING: EVENT_UPDATE MASK: nr %u exceeds payload, skipping\n", + ev->cpus.cpus.mask32_data.nr); + return 0; + } + } else if (ev->cpus.cpus.mask64_data.long_size == 8) { + if (cpus_payload < offsetof(struct perf_record_cpu_map_data, mask64_data.mask) || + ev->cpus.cpus.mask64_data.nr > + (cpus_payload - offsetof(struct perf_record_cpu_map_data, mask64_data.mask)) / + sizeof(ev->cpus.cpus.mask64_data.mask[0])) { + pr_warning("WARNING: EVENT_UPDATE MASK: nr %u exceeds payload, skipping\n", + ev->cpus.cpus.mask64_data.nr); + return 0; + } + } + break; + default: + break; + } + } + if (dump_trace) perf_event__fprintf_event_update(event, stdout); @@ -5300,6 +5439,7 @@ int perf_event__process_event_update(const struct perf_tool *tool __maybe_unused evsel->core.pmu_cpus = map; } else pr_err("failed to get event_update cpus\n"); + break; default: break; } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 95eb793026de..8280413f4528 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -708,8 +708,103 @@ static int perf_event__build_id_swap(union perf_event *event, static int perf_event__event_update_swap(union perf_event *event, bool sample_id_all __maybe_unused) { - event->event_update.type = bswap_64(event->event_update.type); - event->event_update.id = bswap_64(event->event_update.id); + struct perf_record_event_update *ev = &event->event_update; + + ev->type = bswap_64(ev->type); + ev->id = bswap_64(ev->id); + + /* + * Swap variant-specific fields so the processing path + * sees native byte order. + */ + if (ev->type == PERF_EVENT_UPDATE__SCALE) { + if (event->header.size < offsetof(struct perf_record_event_update, scale) + + sizeof(ev->scale)) + return -1; + mem_bswap_64(&ev->scale.scale, sizeof(ev->scale.scale)); + } else if (ev->type == PERF_EVENT_UPDATE__CPUS) { + u32 cpus_payload; + struct perf_record_cpu_map_data *data = &ev->cpus.cpus; + + /* CPUS fields start at the same offset as scale (union) */ + if (event->header.size < offsetof(struct perf_record_event_update, cpus) + + sizeof(__u16) + sizeof(struct perf_record_range_cpu_map)) + return -1; + cpus_payload = event->header.size - offsetof(struct perf_record_event_update, cpus); + data->type = bswap_16(data->type); + /* + * Full swap including array elements — same logic as + * perf_event__cpu_map_swap() but scoped to the + * embedded cpu_map_data within EVENT_UPDATE. + */ + switch (data->type) { + case PERF_CPU_MAP__CPUS: { + u16 nr, max_nr; + + data->cpus_data.nr = bswap_16(data->cpus_data.nr); + nr = data->cpus_data.nr; + max_nr = (cpus_payload - offsetof(struct perf_record_cpu_map_data, + cpus_data.cpu)) / + sizeof(data->cpus_data.cpu[0]); + if (nr > max_nr) { + nr = max_nr; + data->cpus_data.nr = nr; + } + for (unsigned int i = 0; i < nr; i++) + data->cpus_data.cpu[i] = bswap_16(data->cpus_data.cpu[i]); + break; + } + case PERF_CPU_MAP__MASK: + data->mask32_data.long_size = bswap_16(data->mask32_data.long_size); + switch (data->mask32_data.long_size) { + case 4: { + u16 nr, max_nr; + + data->mask32_data.nr = bswap_16(data->mask32_data.nr); + nr = data->mask32_data.nr; + max_nr = (cpus_payload - offsetof(struct perf_record_cpu_map_data, + mask32_data.mask)) / + sizeof(data->mask32_data.mask[0]); + if (nr > max_nr) { + nr = max_nr; + data->mask32_data.nr = nr; + } + for (unsigned int i = 0; i < nr; i++) + data->mask32_data.mask[i] = bswap_32(data->mask32_data.mask[i]); + break; + } + case 8: { + u16 nr, max_nr; + + data->mask64_data.nr = bswap_16(data->mask64_data.nr); + nr = data->mask64_data.nr; + if (cpus_payload < offsetof(struct perf_record_cpu_map_data, mask64_data.mask)) { + data->mask64_data.nr = 0; + break; + } + max_nr = (cpus_payload - offsetof(struct perf_record_cpu_map_data, + mask64_data.mask)) / + sizeof(data->mask64_data.mask[0]); + if (nr > max_nr) { + nr = max_nr; + data->mask64_data.nr = nr; + } + for (unsigned int i = 0; i < nr; i++) + data->mask64_data.mask[i] = bswap_64(data->mask64_data.mask[i]); + break; + } + default: + break; + } + break; + case PERF_CPU_MAP__RANGE_CPUS: + data->range_cpu_data.start_cpu = bswap_16(data->range_cpu_data.start_cpu); + data->range_cpu_data.end_cpu = bswap_16(data->range_cpu_data.end_cpu); + break; + default: + break; + } + } return 0; } From 2bd03e3054a4e21895e6aa20dd8a14c08e37edee Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 14:20:14 -0300 Subject: [PATCH 134/343] perf tools: Bounds check perf_event_attr fields against attr.size before printing perf_event_attr__fprintf() accessed all struct fields unconditionally, but attrs from older perf.data files or BPF-captured syscall payloads may have a smaller size than the current struct. Fields beyond the recorded size contain uninitialized or zero-filled data. Add size-guarded macros (PRINT_ATTRn, PRINT_ATTRn_bf) that compare each field's offset against attr->size before accessing it. Guard the bitfield block (disabled, inherit, ... defer_output) with attr_size >= 48. These bitfields share a single __u64 at offset 40, which is within PERF_ATTR_SIZE_VER0 for validated perf.data attrs, but BPF-captured attrs from perf trace can have a smaller size when the tracee passes a minimal struct to sys_perf_event_open. Also fix the BPF trace path: when perf trace intercepts sys_perf_event_open via BPF, the program copies PERF_ATTR_SIZE_VER0 bytes when the tracee passes size=0, but leaves the size field as 0. Set attr->size to PERF_ATTR_SIZE_VER0 in the augmented syscall handler so the bounds checks match the actual copied size. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/trace/beauty/perf_event_open.c | 23 +++- tools/perf/util/perf_event_attr_fprintf.c | 141 ++++++++++++++-------- 2 files changed, 114 insertions(+), 50 deletions(-) diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c index c1c7445dcff9..6315b46bcdf0 100644 --- a/tools/perf/trace/beauty/perf_event_open.c +++ b/tools/perf/trace/beauty/perf_event_open.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: LGPL-2.1 +#include #include "trace/beauty/beauty.h" #include "util/evsel_fprintf.h" #include @@ -80,7 +81,27 @@ static size_t perf_event_attr___scnprintf(struct perf_event_attr *attr, char *bf static size_t syscall_arg__scnprintf_augmented_perf_event_attr(struct syscall_arg *arg, char *bf, size_t size) { - return perf_event_attr___scnprintf((void *)arg->augmented.args->value, bf, size, + struct perf_event_attr *attr = (void *)arg->augmented.args->value; + struct perf_event_attr local_attr; + + /* + * augmented_raw_syscalls.bpf.c (shipped with perf) copies + * PERF_ATTR_SIZE_VER0 bytes when the tracee passes size=0, + * but leaves the size field as 0. The payload size is + * guaranteed by perf's own BPF program, not externally + * controllable. Copy to a local so we can fix up size + * without writing to the potentially read-only augmented + * args buffer. + */ + if (!attr->size) { + memcpy(&local_attr, attr, PERF_ATTR_SIZE_VER0); + memset((void *)&local_attr + PERF_ATTR_SIZE_VER0, 0, + sizeof(local_attr) - PERF_ATTR_SIZE_VER0); + local_attr.size = PERF_ATTR_SIZE_VER0; + attr = &local_attr; + } + + return perf_event_attr___scnprintf(attr, bf, size, trace__show_zeros(arg->trace)); } diff --git a/tools/perf/util/perf_event_attr_fprintf.c b/tools/perf/util/perf_event_attr_fprintf.c index 741c3d657a8b..3933639d76c5 100644 --- a/tools/perf/util/perf_event_attr_fprintf.c +++ b/tools/perf/util/perf_event_attr_fprintf.c @@ -275,24 +275,56 @@ static void __p_config_id(struct perf_pmu *pmu, char *buf, size_t size, u32 type #define p_type_id(val) __p_type_id(buf, BUF_SIZE, pmu, val) #define p_config_id(val) __p_config_id(pmu, buf, BUF_SIZE, attr->type, val) -#define PRINT_ATTRn(_n, _f, _p, _a) \ -do { \ - if (_a || attr->_f) { \ - _p(attr->_f); \ - ret += attr__fprintf(fp, _n, buf, priv);\ - } \ +#define PRINT_ATTRn(_n, _f, _p, _a) \ +do { \ + if (attr_size >= offsetof(struct perf_event_attr, _f) + \ + sizeof(attr->_f) && \ + (_a || attr->_f)) { \ + _p(attr->_f); \ + ret += attr__fprintf(fp, _n, buf, priv); \ + } \ +} while (0) + +/* bitfield members share an offset; most are within PERF_ATTR_SIZE_VER0 */ +#define PRINT_ATTRn_bf(_n, _f, _p, _a) \ +do { \ + if (_a || attr->_f) { \ + _p(attr->_f); \ + ret += attr__fprintf(fp, _n, buf, priv); \ + } \ } while (0) #define PRINT_ATTRf(_f, _p) PRINT_ATTRn(#_f, _f, _p, false) +#define PRINT_ATTRf_bf(_f, _p) PRINT_ATTRn_bf(#_f, _f, _p, false) int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, attr__fprintf_f attr__fprintf, void *priv) { struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); + /* + * size == 0 means ABI0 — the producer didn't set attr.size. + * perf_event__fprintf_attr() may pass the raw mmap'd event + * before the local copy, so default to PERF_ATTR_SIZE_VER0 + * (the ABI0 footprint) to avoid reading past the attr into + * the ID array that follows it in HEADER_ATTR events. + */ + u32 attr_size = attr->size ?: PERF_ATTR_SIZE_VER0; char buf[BUF_SIZE]; int ret = 0; - if (!pmu && (attr->type == PERF_TYPE_HARDWARE || attr->type == PERF_TYPE_HW_CACHE)) { + /* + * Cap to what we understand: all callers store the attr in a + * buffer of sizeof(*attr) bytes (perf.data read path copies + * min(attr.size, sizeof), BPF augmented path copies into a + * fixed-size value[] array). A spoofed attr->size larger + * than sizeof would cause PRINT_ATTRn to read past the + * actual buffer. + */ + if (attr_size > sizeof(*attr)) + attr_size = sizeof(*attr); + + if (!pmu && attr_size >= offsetof(struct perf_event_attr, config) + sizeof(attr->config) && + (attr->type == PERF_TYPE_HARDWARE || attr->type == PERF_TYPE_HW_CACHE)) { u32 extended_type = attr->config >> PERF_PMU_TYPE_SHIFT; if (extended_type) @@ -306,45 +338,53 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, PRINT_ATTRf(sample_type, p_sample_type); PRINT_ATTRf(read_format, p_read_format); - PRINT_ATTRf(disabled, p_unsigned); - PRINT_ATTRf(inherit, p_unsigned); - PRINT_ATTRf(pinned, p_unsigned); - PRINT_ATTRf(exclusive, p_unsigned); - PRINT_ATTRf(exclude_user, p_unsigned); - PRINT_ATTRf(exclude_kernel, p_unsigned); - PRINT_ATTRf(exclude_hv, p_unsigned); - PRINT_ATTRf(exclude_idle, p_unsigned); - PRINT_ATTRf(mmap, p_unsigned); - PRINT_ATTRf(comm, p_unsigned); - PRINT_ATTRf(freq, p_unsigned); - PRINT_ATTRf(inherit_stat, p_unsigned); - PRINT_ATTRf(enable_on_exec, p_unsigned); - PRINT_ATTRf(task, p_unsigned); - PRINT_ATTRf(watermark, p_unsigned); - PRINT_ATTRf(precise_ip, p_unsigned); - PRINT_ATTRf(mmap_data, p_unsigned); - PRINT_ATTRf(sample_id_all, p_unsigned); - PRINT_ATTRf(exclude_host, p_unsigned); - PRINT_ATTRf(exclude_guest, p_unsigned); - PRINT_ATTRf(exclude_callchain_kernel, p_unsigned); - PRINT_ATTRf(exclude_callchain_user, p_unsigned); - PRINT_ATTRf(mmap2, p_unsigned); - PRINT_ATTRf(comm_exec, p_unsigned); - PRINT_ATTRf(use_clockid, p_unsigned); - PRINT_ATTRf(context_switch, p_unsigned); - PRINT_ATTRf(write_backward, p_unsigned); - PRINT_ATTRf(namespaces, p_unsigned); - PRINT_ATTRf(ksymbol, p_unsigned); - PRINT_ATTRf(bpf_event, p_unsigned); - PRINT_ATTRf(aux_output, p_unsigned); - PRINT_ATTRf(cgroup, p_unsigned); - PRINT_ATTRf(text_poke, p_unsigned); - PRINT_ATTRf(build_id, p_unsigned); - PRINT_ATTRf(inherit_thread, p_unsigned); - PRINT_ATTRf(remove_on_exec, p_unsigned); - PRINT_ATTRf(sigtrap, p_unsigned); - PRINT_ATTRf(defer_callchain, p_unsigned); - PRINT_ATTRf(defer_output, p_unsigned); + /* + * All bitfields share a single __u64 right after read_format. + * BPF-captured attrs from perf trace may have a small size + * when the tracee passes a minimal struct, so skip the + * entire block when it's not covered. + */ + if (attr_size >= offsetof(struct perf_event_attr, wakeup_events)) { + PRINT_ATTRf_bf(disabled, p_unsigned); + PRINT_ATTRf_bf(inherit, p_unsigned); + PRINT_ATTRf_bf(pinned, p_unsigned); + PRINT_ATTRf_bf(exclusive, p_unsigned); + PRINT_ATTRf_bf(exclude_user, p_unsigned); + PRINT_ATTRf_bf(exclude_kernel, p_unsigned); + PRINT_ATTRf_bf(exclude_hv, p_unsigned); + PRINT_ATTRf_bf(exclude_idle, p_unsigned); + PRINT_ATTRf_bf(mmap, p_unsigned); + PRINT_ATTRf_bf(comm, p_unsigned); + PRINT_ATTRf_bf(freq, p_unsigned); + PRINT_ATTRf_bf(inherit_stat, p_unsigned); + PRINT_ATTRf_bf(enable_on_exec, p_unsigned); + PRINT_ATTRf_bf(task, p_unsigned); + PRINT_ATTRf_bf(watermark, p_unsigned); + PRINT_ATTRf_bf(precise_ip, p_unsigned); + PRINT_ATTRf_bf(mmap_data, p_unsigned); + PRINT_ATTRf_bf(sample_id_all, p_unsigned); + PRINT_ATTRf_bf(exclude_host, p_unsigned); + PRINT_ATTRf_bf(exclude_guest, p_unsigned); + PRINT_ATTRf_bf(exclude_callchain_kernel, p_unsigned); + PRINT_ATTRf_bf(exclude_callchain_user, p_unsigned); + PRINT_ATTRf_bf(mmap2, p_unsigned); + PRINT_ATTRf_bf(comm_exec, p_unsigned); + PRINT_ATTRf_bf(use_clockid, p_unsigned); + PRINT_ATTRf_bf(context_switch, p_unsigned); + PRINT_ATTRf_bf(write_backward, p_unsigned); + PRINT_ATTRf_bf(namespaces, p_unsigned); + PRINT_ATTRf_bf(ksymbol, p_unsigned); + PRINT_ATTRf_bf(bpf_event, p_unsigned); + PRINT_ATTRf_bf(aux_output, p_unsigned); + PRINT_ATTRf_bf(cgroup, p_unsigned); + PRINT_ATTRf_bf(text_poke, p_unsigned); + PRINT_ATTRf_bf(build_id, p_unsigned); + PRINT_ATTRf_bf(inherit_thread, p_unsigned); + PRINT_ATTRf_bf(remove_on_exec, p_unsigned); + PRINT_ATTRf_bf(sigtrap, p_unsigned); + PRINT_ATTRf_bf(defer_callchain, p_unsigned); + PRINT_ATTRf_bf(defer_output, p_unsigned); + } PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned, false); PRINT_ATTRf(bp_type, p_unsigned); @@ -359,9 +399,12 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, PRINT_ATTRf(sample_max_stack, p_unsigned); PRINT_ATTRf(aux_sample_size, p_unsigned); PRINT_ATTRf(sig_data, p_unsigned); - PRINT_ATTRf(aux_start_paused, p_unsigned); - PRINT_ATTRf(aux_pause, p_unsigned); - PRINT_ATTRf(aux_resume, p_unsigned); + /* aux_{start_paused,pause,resume} are at byte 116, past VER0 */ + if (attr_size >= offsetof(struct perf_event_attr, sig_data)) { + PRINT_ATTRf_bf(aux_start_paused, p_unsigned); + PRINT_ATTRf_bf(aux_pause, p_unsigned); + PRINT_ATTRf_bf(aux_resume, p_unsigned); + } return ret; } From 7d19f2008abf4b5440bfd9962f46f605beab69df Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 14:24:02 -0300 Subject: [PATCH 135/343] perf header: Propagate feature section processing errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit perf_session__read_header() discards the return value from perf_header__process_sections(), so any error from a feature section processor (process_nrcpus, process_compressed, etc.) is silently ignored and the session opens as if nothing went wrong. This defeats the validation added by subsequent commits in this series: a crafted perf.data that fails a feature section check would still be processed with partially-initialized state. Check the return value and fail the session if any feature section processor returns an error. For truncated files (data.size == 0, i.e. recording was interrupted before the header was finalized), skip feature section processing entirely and clear the feature bitmap so tools use their "feature not present" fallbacks instead of accessing uninitialized env fields. Change the feature processor stubs for optional libraries (libtraceevent, libbpf) from returning -1 to returning 0, so that perf.data files containing these features can still be opened on builds without the optional library — the feature is simply skipped rather than causing a fatal error. Also propagate evlist__prepare_tracepoint_events() failure as -ENOMEM, since the function can fail due to strdup() allocation failure inside evsel__prepare_tracepoint_event(). Fixes: 1c0b04d12ae9 ("perf tools: Add perf_session__read_header function") Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 51 ++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 9e3a08b1f8ae..f4e0e257ff72 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2748,8 +2748,9 @@ static int process_tracing_data(struct feat_fd *ff __maybe_unused, void *data __ return ret < 0 ? -1 : 0; #else - pr_err("ERROR: Trying to read tracing data without libtraceevent support.\n"); - return -1; + /* Not an error — the feature is simply unsupported in this build */ + pr_debug("Tracing data present but libtraceevent not available, skipping.\n"); + return 0; #endif } @@ -3643,8 +3644,9 @@ static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data _ up_write(&env->bpf_progs.lock); return err; #else - pr_err("ERROR: Trying to read bpf_prog_info without libbpf support.\n"); - return -1; + /* Not an error — the feature is simply unsupported in this build */ + pr_debug("BPF prog info present but libbpf not available, skipping.\n"); + return 0; #endif // HAVE_LIBBPF_SUPPORT } @@ -3712,8 +3714,9 @@ static int process_bpf_btf(struct feat_fd *ff __maybe_unused, void *data __mayb free(node); return err; #else - pr_err("ERROR: Trying to read btf data without libbpf support.\n"); - return -1; + /* Not an error — the feature is simply unsupported in this build */ + pr_debug("BTF data present but libbpf not available, skipping.\n"); + return 0; #endif // HAVE_LIBBPF_SUPPORT } @@ -4900,7 +4903,7 @@ int perf_session__read_header(struct perf_session *session) struct perf_file_header f_header; struct perf_file_attr f_attr; u64 f_id; - int nr_attrs, nr_ids, i, j, err; + int nr_attrs, nr_ids, i, j, err = -ENOMEM; int fd = perf_data__fd(data); session->evlist = evlist__new(); @@ -4920,6 +4923,7 @@ int perf_session__read_header(struct perf_session *session) return err; } + err = -ENOMEM; if (perf_file_header__read(&f_header, header, fd) < 0) return -EINVAL; @@ -4997,15 +5001,36 @@ int perf_session__read_header(struct perf_session *session) lseek(fd, tmp, SEEK_SET); } + /* + * Skip feature section processing for truncated files + * (data.size == 0 means recording was interrupted). The + * section table is unreliable in that case, and the event + * data can still be processed without the feature headers. + * Clear the bitmap so has_feat() returns false and tools + * use their "feature not present" fallbacks instead of + * accessing uninitialized env fields. + */ + if (f_header.data.size == 0) { + bitmap_zero(header->adds_features, HEADER_FEAT_BITS); + } else { #ifdef HAVE_LIBTRACEEVENT - perf_header__process_sections(header, fd, &session->tevent, - perf_file_section__process); + err = perf_header__process_sections(header, fd, &session->tevent, + perf_file_section__process); + if (err < 0) + goto out_delete_evlist; - if (evlist__prepare_tracepoint_events(session->evlist, session->tevent.pevent)) - goto out_delete_evlist; + if (evlist__prepare_tracepoint_events(session->evlist, + session->tevent.pevent)) { + err = -ENOMEM; + goto out_delete_evlist; + } #else - perf_header__process_sections(header, fd, NULL, perf_file_section__process); + err = perf_header__process_sections(header, fd, NULL, + perf_file_section__process); + if (err < 0) + goto out_delete_evlist; #endif + } return 0; out_errno: @@ -5014,7 +5039,7 @@ int perf_session__read_header(struct perf_session *session) out_delete_evlist: evlist__delete(session->evlist); session->evlist = NULL; - return -ENOMEM; + return err; } int perf_event__process_feature(const struct perf_tool *tool __maybe_unused, From 7685cc0f2ea34b341524453badf1933142a0961d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 14:28:06 -0300 Subject: [PATCH 136/343] perf header: Validate f_attr.ids section before use in perf_session__read_header() perf_session__read_header() reads f_attr.ids.size from the perf.data file and divides it by sizeof(u64) to compute nr_ids, which is declared as int. No validation is performed on the value before it is used to allocate arrays and drive a read loop. On 32-bit architectures, a crafted f_attr.ids.size of 0x100000000 (4 GB) produces nr_ids = 0x20000000, but the allocation size 1 * 0x20000000 * 8 overflows size_t to 0, so zalloc(0) returns a valid pointer. The subsequent loop writes 0x20000000 IDs into that zero-length buffer, corrupting the heap. On 64-bit, the u64-to-int truncation silently drops high bits, processing fewer IDs than the file claims. While not exploitable, this is a data integrity issue. Add validation before using f_attr.ids: - Cap nr_attrs (attrs.size / attr_size) to MAX_NR_ATTRS (1 << 16) with overflow-safe u64 comparison before assigning to int - Reject ids.size not aligned to sizeof(u64) - Cap ids.size / sizeof(u64) to MAX_IDS_PER_ATTR (1 << 24) to prevent int truncation and size_t overflow on 32-bit - Reject ids sections that extend past the end of the file, guarded by S_ISREG() so non-regular files (block devices, pipes) are not falsely rejected Also fix perf_header__getbuffer64() to set errno = EIO when readn() returns 0 (EOF). Without this, the out_errno path in perf_session__read_header() returns -errno which is 0 (success) on truncated files, causing downstream NULL dereferences. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 77 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index f4e0e257ff72..fe23bbd8370c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -64,6 +64,25 @@ #include #endif +/* + * nr_ids * sizeof(struct perf_sample_id) must not overflow + * size_t on 32-bit; the struct is ~104 bytes (32-bit) or + * ~184 bytes (64-bit), so 1<<24 (16M) keeps the product + * under 2 GB on 32-bit. + * + * This is a per-attribute cap only — the total across all + * attributes is not capped because legitimate high-core-count + * workloads (e.g. 5000 tracepoints × 4096 CPUs) can exceed + * a single-attribute limit. + */ +#define MAX_IDS_PER_ATTR (1 << 24) +/* + * Cap nr_attrs to prevent resource exhaustion from crafted + * files. 65536 is well beyond any real workload (perf stat + * typically uses < 100 events) but prevents u64-to-int + * truncation on the attr count. + */ +#define MAX_NR_ATTRS (1 << 16) #define MAX_BPF_DATA_LEN (256 * 1024 * 1024) #define MAX_BPF_PROGS 131072 #define MAX_CACHE_ENTRIES 32768 @@ -4468,8 +4487,13 @@ int perf_session__inject_header(struct perf_session *session, static int perf_header__getbuffer64(struct perf_header *header, int fd, void *buf, size_t size) { - if (readn(fd, buf, size) <= 0) + ssize_t n = readn(fd, buf, size); + + if (n <= 0) { + if (n == 0) + errno = EIO; return -1; + } if (header->needs_swap) mem_bswap_64(buf, size); @@ -4803,6 +4827,8 @@ static int read_attr(int fd, struct perf_header *ph, if (ret <= 0) { pr_debug("cannot read %d bytes of header attr\n", PERF_ATTR_SIZE_VER0); + if (ret == 0) + errno = EIO; return -1; } @@ -4903,6 +4929,7 @@ int perf_session__read_header(struct perf_session *session) struct perf_file_header f_header; struct perf_file_attr f_attr; u64 f_id; + struct stat input_stat; int nr_attrs, nr_ids, i, j, err = -ENOMEM; int fd = perf_data__fd(data); @@ -4951,6 +4978,15 @@ int perf_session__read_header(struct perf_session *session) return -EINVAL; } + if (fstat(fd, &input_stat) < 0) + return -errno; + + /* Check before assigning to int to avoid u64-to-int truncation */ + if (f_header.attrs.size / f_header.attr_size > MAX_NR_ATTRS) { + pr_err("Too many attributes: %" PRIu64 " (max %d)\n", + f_header.attrs.size / f_header.attr_size, MAX_NR_ATTRS); + return -EINVAL; + } nr_attrs = f_header.attrs.size / f_header.attr_size; lseek(fd, f_header.attrs.offset, SEEK_SET); @@ -4967,6 +5003,45 @@ int perf_session__read_header(struct perf_session *session) perf_event__attr_swap(&f_attr.attr); } + /* + * Validate ids section: must be aligned to u64, and + * the count must fit in an int to avoid truncation in + * nr_ids and size_t overflow in perf_evsel__alloc_id() + * on 32-bit architectures. + */ + if (f_attr.ids.size % sizeof(u64)) { + pr_err("Invalid ids section size %" PRIu64 " for attr %d, not aligned to u64\n", + f_attr.ids.size, i); + err = -EINVAL; + goto out_delete_evlist; + } + + /* + * Cap the ID count to avoid int truncation of nr_ids + * on 64-bit and size_t overflow in the allocation + * paths (nr_ids * sizeof(u64), nr_ids * + * sizeof(struct perf_sample_id)) on 32-bit. + */ + if (f_attr.ids.size / sizeof(u64) > MAX_IDS_PER_ATTR) { + pr_err("Invalid ids section size %" PRIu64 " for attr %d, too many IDs\n", + f_attr.ids.size, i); + err = -EINVAL; + goto out_delete_evlist; + } + + /* + * FIXME: see perf_header__process_sections() — block + * devices bypass this check because st_size is 0. + */ + if (S_ISREG(input_stat.st_mode) && + (f_attr.ids.offset > (u64)input_stat.st_size || + f_attr.ids.size > (u64)input_stat.st_size - f_attr.ids.offset)) { + pr_err("Invalid ids section for attr %d: offset=%" PRIu64 " size=%" PRIu64 " exceeds file size %" PRIu64 "\n", + i, f_attr.ids.offset, f_attr.ids.size, (u64)input_stat.st_size); + err = -EINVAL; + goto out_delete_evlist; + } + tmp = lseek(fd, 0, SEEK_CUR); evsel = evsel__new(&f_attr.attr); From b8deecd753441eea76e67f08989189ce6ddf8011 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 14:32:58 -0300 Subject: [PATCH 137/343] perf header: Validate feature section size and add read path bounds checking Harden feature section parsing against crafted perf.data files: 1. perf_header__process_sections() reads the feature section table and passes each section's offset and size directly to the processing callbacks without validating them against the actual file size. A crafted section size would make all downstream bounds checks against ff->size ineffective since they compare against the untrusted, inflated bound. Add an fstat() check with S_ISREG() guard and verify that each section's offset + size does not extend past EOF. 2. __do_read_buf() validates reads against ff->size (section size), but __do_read_fd() had no such check, so a malformed perf.data with an understated section size could cause reads past the end of the current section into the next section's data. Add the bounds check in __do_read(), the common caller of both helpers, so it is enforced uniformly for both the fd and buf paths. Track the section-relative offset in __do_read_fd() so the check works for the fd path. Reject negative sizes which on 32-bit can occur when a u32 >= 0x80000000 is passed as ssize_t. 3. do_read_string() relied on file data being null-padded. Add explicit null-termination (buf[len-1] = '\0') after reading and validate length (>= 1, fits within section) before allocating, so callers like process_cpu_topology() never receive an unterminated string. 4. Initialize feat_fd.offset to 0 (section-relative) instead of section->offset (file-absolute) so the bounds tracking is consistent with __do_read()'s section-relative comparison. Adjust process_build_id() to use lseek() for its file-absolute offset needs since it cannot rely on ff->offset for that. 5. Propagate ff->size to perf_file_section__fprintf_info() so its reads are also bounded. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: David Carrillo-Cisneros Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 66 ++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index fe23bbd8370c..90417a478c8d 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -233,23 +233,32 @@ static int __do_read_fd(struct feat_fd *ff, void *addr, ssize_t size) if (ret != size) return ret < 0 ? (int)ret : -1; + ff->offset += size; return 0; } static int __do_read_buf(struct feat_fd *ff, void *addr, ssize_t size) { - if (size > (ssize_t)ff->size - ff->offset) - return -1; - memcpy(addr, ff->buf + ff->offset, size); ff->offset += size; return 0; - } static int __do_read(struct feat_fd *ff, void *addr, ssize_t size) { + /* + * Reject negative sizes, which on 32-bit can occur when a + * u32 >= 0x80000000 is passed as ssize_t. The cast to + * ssize_t is safe because perf_header__process_sections() + * validates that each section fits within the file size + * before any feature callback reaches here, and only + * feature sections (metadata like build IDs, topology, etc.) + * use this path — these cannot legitimately approach 2GB. + */ + if (size < 0 || size > (ssize_t)ff->size - ff->offset) + return -1; + if (!ff->buf) return __do_read_fd(ff, addr, size); return __do_read_buf(ff, addr, size); @@ -289,16 +298,25 @@ static char *do_read_string(struct feat_fd *ff) if (do_read_u32(ff, &len)) return NULL; + /* At least the null terminator. */ + if (len < 1 || len > ff->size - ff->offset) { + pr_debug("do_read_string: invalid length %u (remaining %zu)\n", + len, (size_t)(ff->size - ff->offset)); + return NULL; + } + buf = malloc(len); if (!buf) return NULL; if (!__do_read(ff, buf, len)) { /* - * strings are padded by zeroes - * thus the actual strlen of buf - * may be less than len + * do_write_string() writes len including the null + * terminator, padded to NAME_ALIGN. Ensure the + * string is always null-terminated even if the file + * data has been tampered with. */ + buf[len - 1] = '\0'; return buf; } @@ -2775,7 +2793,13 @@ static int process_tracing_data(struct feat_fd *ff __maybe_unused, void *data __ static int process_build_id(struct feat_fd *ff, void *data __maybe_unused) { - if (perf_header__read_build_ids(ff->ph, ff->fd, ff->offset, ff->size)) + /* lseek fails in pipe mode — fall back to ff->offset */ + off_t offset = lseek(ff->fd, 0, SEEK_CUR); + + if (offset == (off_t)-1) + offset = ff->offset; + + if (perf_header__read_build_ids(ff->ph, ff->fd, offset, ff->size)) pr_debug("Failed to read buildids, continuing...\n"); return 0; } @@ -4152,6 +4176,7 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section, ff = (struct feat_fd) { .fd = fd, .ph = ph, + .size = section->size, }; if (!feat_ops[feat].full_only || hd->full) @@ -4512,6 +4537,7 @@ int perf_header__process_sections(struct perf_header *header, int fd, int sec_size; int feat; int err; + struct stat st; nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); if (!nr_sections) @@ -4529,7 +4555,29 @@ int perf_header__process_sections(struct perf_header *header, int fd, if (err < 0) goto out_free; + if (fstat(fd, &st) < 0) { + pr_err("Failed to stat the perf data file\n"); + err = -1; + goto out_free; + } + for_each_set_bit(feat, header->adds_features, header->last_feat) { + /* + * FIXME: block devices have st_size == 0, so we skip + * bounds checking entirely. Historically perf never + * prevented using a block device as input, but it + * probably should — there's no valid use case for it + * and it bypasses all file-size validation. + */ + if (S_ISREG(st.st_mode) && + (sec->offset > (u64)st.st_size || + sec->size > (u64)st.st_size - sec->offset)) { + pr_err("Feature %s (%d) section extends past EOF (offset=%" PRIu64 ", size=%" PRIu64 ", file=%" PRIu64 ")\n", + header_feat__name(feat), feat, + sec->offset, sec->size, (u64)st.st_size); + err = -1; + goto out_free; + } err = process(sec++, header, feat, fd, data); if (err < 0) goto out_free; @@ -4756,7 +4804,7 @@ static int perf_file_section__process(struct perf_file_section *section, .fd = fd, .ph = ph, .size = section->size, - .offset = section->offset, + .offset = 0, }; if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { From 944f65c8b8231d26d4db6be67bcb641142603cb4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 14:37:39 -0300 Subject: [PATCH 138/343] perf header: Sanity check HEADER_EVENT_DESC attr.size before swap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit read_event_desc() reads nre (event count), sz (attr size), and nr (IDs per event) from the file and uses them to control allocations and loops without validating them against the section size. A crafted perf.data could trigger large allocations or many loop iterations before __do_read() eventually rejects the reads. Add bounds checks in read_event_desc(): - Reject sz smaller than PERF_ATTR_SIZE_VER0. - Require at least one event (nre > 0). - Check that nre events fit in the remaining section, using the minimum per-event footprint of sz + sizeof(u32). - Pre-swap attr->size to native byte order, then reject values below PERF_ATTR_SIZE_VER0 or above sz before calling perf_event__attr_swap() to prevent heap out-of-bounds access. - Handle ABI0 (attr.size == 0): substitute PERF_ATTR_SIZE_VER0, and on native-endian files write the value back so free_event_desc() does not treat the zero as its end-of-array sentinel (it iterates while attr.size != 0). The swap path skips the write-back — perf_event__attr_swap() has its own ABI0 fallback that sets VER0 after swapping. - Check that nr IDs fit in the remaining section before allocating. Fixes: b30b61729246 ("perf tools: Fix a problem when opening old perf.data with different byte order") Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 90417a478c8d..37d7c9849e0e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2173,9 +2173,28 @@ static struct evsel *read_event_desc(struct feat_fd *ff) if (do_read_u32(ff, &nre)) goto error; + /* Size of each of the nre attributes. */ if (do_read_u32(ff, &sz)) goto error; + /* + * Require at least one event with an attr no smaller than the + * first published struct, and reject sz values where + * sz + sizeof(u32) would overflow size_t (possible on 32-bit) + * or nre == UINT32_MAX where nre + 1 wraps to 0 in the calloc. + * + * The minimum section footprint per event is sz bytes for the + * attr plus a u32 for the id count, check that nre events fit. + */ + if (!nre || sz < PERF_ATTR_SIZE_VER0 || + sz > ff->size || (size_t)sz > SIZE_MAX - sizeof(u32) || + nre == UINT32_MAX || + nre > (ff->size - ff->offset) / (sz + sizeof(u32))) { + pr_err("Invalid HEADER_EVENT_DESC: nre=%u sz=%u (min %d)\n", + nre, sz, PERF_ATTR_SIZE_VER0); + goto error; + } + /* buffer to hold on file attr struct */ buf = malloc(sz); if (!buf) @@ -2191,6 +2210,9 @@ static struct evsel *read_event_desc(struct feat_fd *ff) msz = sz; for (i = 0, evsel = events; i < nre; evsel++, i++) { + struct perf_event_attr *attr = buf; + u32 attr_size; + evsel->core.idx = i; /* @@ -2200,6 +2222,32 @@ static struct evsel *read_event_desc(struct feat_fd *ff) if (__do_read(ff, buf, sz)) goto error; + /* Reject before attr_swap to prevent OOB via bswap_safe() */ + attr_size = ff->ph->needs_swap ? bswap_32(attr->size) : attr->size; + /* ABI0: size == 0 means the producer didn't set it */ + if (!attr_size) { + attr_size = PERF_ATTR_SIZE_VER0; + /* + * Write back so free_event_desc() doesn't + * treat this event as the end-of-array sentinel + * (it iterates while attr.size != 0). + * + * Only for native — the swap path must NOT + * write native-endian VER0 here because + * perf_event__attr_swap() would re-swap it + * to 0x40000000, defeating bswap_safe() bounds. + * perf_event__attr_swap() has its own ABI0 + * fallback that sets VER0 after swapping. + */ + if (!ff->ph->needs_swap) + attr->size = attr_size; + } + if (attr_size < PERF_ATTR_SIZE_VER0 || attr_size > sz) { + pr_err("Event %d attr.size (%u) invalid (min: %d, max: %u)\n", + i, attr_size, PERF_ATTR_SIZE_VER0, sz); + goto error; + } + if (ff->ph->needs_swap) perf_event__attr_swap(buf); @@ -2221,6 +2269,12 @@ static struct evsel *read_event_desc(struct feat_fd *ff) if (!nr) continue; + /* Prevent oversized allocation from crafted nr */ + if (nr > (ff->size - ff->offset) / sizeof(*id)) { + pr_err("Event %d: id count %u exceeds remaining section\n", i, nr); + goto error; + } + id = calloc(nr, sizeof(*id)); if (!id) goto error; From 3669697bda41c562d90eb38f54881cc02ef3d51c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 14:41:46 -0300 Subject: [PATCH 139/343] perf header: Validate bitmap size before allocating in do_read_bitmap() do_read_bitmap() reads a u64 bit count from the file and passes it to bitmap_zalloc() without checking it against the remaining section size. A crafted perf.data could trigger a large allocation that would only fail later when the per-element reads exceed section bounds. Additionally, bitmap_zalloc() takes an int parameter, so a crafted size with bits set above bit 31 (e.g. 0x100000040) would pass the section bounds check but truncate when passed to bitmap_zalloc(), allocating a much smaller buffer than the subsequent read loop expects. Reject size values that exceed INT_MAX, and check that the data needed (BITS_TO_U64(size) u64 values) fits in the remaining section before allocating. Switch from bitmap_zalloc() to calloc() of u64 units so the allocation size matches the u64 read/write granularity and avoids unsigned long vs u64 mismatch on 32-bit architectures. Fix do_write_bitmap() to use memcpy to read u64-sized chunks from the unsigned long bitmap, preventing out-of-bounds reads on 32-bit systems where sizeof(unsigned long) is 4 but the bitmap is stored in u64 units. Fix process_mem_topology() minimum section size: the check used nr * 2 * sizeof(u64) per node, but do_read_bitmap() reads an additional u64 for the bitmap size, so the minimum is 3 * sizeof(u64). Fix memory leak in process_mem_topology() error paths: replace free(nodes) with memory_node__delete_nodes() to free per-node bitmaps allocated by do_read_bitmap(). Currently used by process_mem_topology() for HEADER_MEM_TOPOLOGY. Fixes: a881fc56038a ("perf header: Sanity check HEADER_MEM_TOPOLOGY") Closes: https://lore.kernel.org/linux-perf-users/20260414224622.2AE69C19425@smtp.kernel.org/ Closes: https://lore.kernel.org/linux-perf-users/20260410223242.DD76FC19421@smtp.kernel.org/ Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 37d7c9849e0e..2fea0172140e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -178,15 +178,25 @@ int do_write(struct feat_fd *ff, const void *buf, size_t size) /* Return: 0 if succeeded, -ERR if failed. */ static int do_write_bitmap(struct feat_fd *ff, unsigned long *set, u64 size) { - u64 *p = (u64 *) set; + size_t byte_size = BITS_TO_LONGS(size) * sizeof(unsigned long); int i, ret; ret = do_write(ff, &size, sizeof(size)); if (ret < 0) return ret; + /* + * The on-disk format uses u64 elements, but the in-memory bitmap + * uses unsigned long, which is only 4 bytes on 32-bit architectures. + * Copy with bounded size so the last element doesn't read past the + * bitmap allocation when BITS_TO_LONGS(size) is odd. + */ for (i = 0; (u64) i < BITS_TO_U64(size); i++) { - ret = do_write(ff, p + i, sizeof(*p)); + u64 val = 0; + size_t off = i * sizeof(val); + + memcpy(&val, (char *)set + off, min(sizeof(val), byte_size - off)); + ret = do_write(ff, &val, sizeof(val)); if (ret < 0) return ret; } @@ -335,7 +345,20 @@ static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize) if (ret) return ret; - set = bitmap_zalloc(size); + /* Bitmap APIs use int for nbits; reject u64 values that truncate. */ + if (size > INT_MAX || + BITS_TO_U64(size) > (ff->size - ff->offset) / sizeof(u64)) { + pr_debug("do_read_bitmap: size %" PRIu64 " exceeds section bounds\n", size); + return -1; + } + + /* + * bitmap_zalloc() allocates in unsigned long units, which are only + * 4 bytes on 32-bit architectures. The read loop below casts the + * buffer to u64 * and writes 8-byte elements, so allocate in u64 + * units to ensure the buffer is large enough. + */ + set = calloc(BITS_TO_U64(size), sizeof(u64)); if (!set) return -ENOMEM; @@ -3497,7 +3520,8 @@ static int process_mem_topology(struct feat_fd *ff, return -1; } - if (ff->size < 3 * sizeof(u64) + nr * 2 * sizeof(u64)) { + /* Per node: node_id(u64) + mem_size(u64) + bitmap_nr_bits(u64) */ + if (ff->size < 3 * sizeof(u64) + nr * 3 * sizeof(u64)) { pr_err("Invalid HEADER_MEM_TOPOLOGY: section too small (%zu) for %llu nodes\n", ff->size, (unsigned long long)nr); return -1; @@ -3532,7 +3556,7 @@ static int process_mem_topology(struct feat_fd *ff, out: if (ret) - free(nodes); + memory_node__delete_nodes(nodes, nr); return ret; } From 1c9d2ac2ead70d4d7c70e7f1276d68ca86e15fa4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 13:22:33 -0300 Subject: [PATCH 140/343] perf session: Add byte-swap handler for PERF_RECORD_COMPRESSED2 PERF_RECORD_COMPRESSED2 events carry a data_size field that must be byte-swapped when reading cross-endian perf.data files. Without a swap handler, reading COMPRESSED2 events on a different-endian machine would misinterpret data_size as a garbage value, causing the decompression path to read the wrong number of bytes. The compressed payload itself is a raw byte stream and needs no swapping. Fixes: 208c0e16834472bb ("perf record: Add 8-byte aligned event type PERF_RECORD_COMPRESSED2") Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: Chun-Tse Shao Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 8280413f4528..9271885e3920 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1056,6 +1056,14 @@ static int perf_event__time_conv_swap(union perf_event *event, return 0; } +static int perf_event__compressed2_swap(union perf_event *event, + bool sample_id_all __maybe_unused) +{ + /* Only data_size needs swapping — compressed payload is a raw byte stream */ + event->pack2.data_size = bswap_64(event->pack2.data_size); + return 0; +} + static int perf_event__bpf_metadata_swap(union perf_event *event, bool sample_id_all __maybe_unused) { @@ -1197,6 +1205,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, [PERF_RECORD_TIME_CONV] = perf_event__time_conv_swap, + [PERF_RECORD_COMPRESSED2] = perf_event__compressed2_swap, [PERF_RECORD_BPF_METADATA] = perf_event__bpf_metadata_swap, [PERF_RECORD_SCHEDSTAT_CPU] = perf_event__schedstat_cpu_swap, [PERF_RECORD_SCHEDSTAT_DOMAIN] = perf_event__schedstat_domain_swap, From 6e803f1e0198f436d512f9b0eebd89ec2a85ac85 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 14:47:38 -0300 Subject: [PATCH 141/343] perf tools: Harden compressed event processing Add several hardening checks to the compressed event decompression pipeline: 1. Guard against decomp_last_rem underflow: check that decomp_last->head does not exceed decomp_last->size before subtracting. A u64 underflow here would produce a huge decomp_len, causing an oversized mmap allocation. 2. Validate comp_mmap_len from the HEADER_COMPRESSED feature section: reject values that are not 4K-aligned or smaller than 4096. The downstream decompression path checks allocation sizes against SIZE_MAX, which handles 32-bit safety. 3. Validate COMPRESSED event header size: reject events where header.size is too small to contain the fixed struct fields, preventing underflow in the payload size calculation. 4. Validate COMPRESSED2 event data_size: check that data_size does not exceed the available payload (header.size minus the fixed struct fields) for the newer compressed format. 5. Reject compressed events when the HEADER_COMPRESSED feature is missing from the file header, which means no decompression context was initialized. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 17 +++++++++++++++++ tools/perf/util/tool.c | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 2fea0172140e..f771a76321c1 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3861,6 +3861,23 @@ static int process_compressed(struct feat_fd *ff, if (do_read_u32(ff, &(env->comp_mmap_len))) return -1; + /* + * FIXME: perf.data should record the recording system's page + * size — it affects mmap buffer alignment, sample addresses, + * and data_page_size/code_page_size interpretation. Without + * it we assume 4K (the smallest Linux page size) as a safe + * minimum alignment for comp_mmap_len validation. + * + * No upper-bound cap: perf_session__process_compressed_event() + * checks decomp_len + sizeof(struct decomp) against SIZE_MAX + * before allocating, which handles 32-bit safety. + */ + if (env->comp_mmap_len < 4096 || env->comp_mmap_len % 4096) { + pr_err("Invalid HEADER_COMPRESSED: comp_mmap_len (%u) must be a 4K-aligned value >= 4096\n", + env->comp_mmap_len); + return -1; + } + return 0; } diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c index 225a77d530ce..18641919473a 100644 --- a/tools/perf/util/tool.c +++ b/tools/perf/util/tool.c @@ -24,7 +24,15 @@ static int perf_session__process_compressed_event(const struct perf_tool *tool _ size_t mmap_len, decomp_len = perf_session__env(session)->comp_mmap_len; struct decomp *decomp, *decomp_last = session->active_decomp->decomp_last; + if (!decomp_len) { + pr_err("Compressed events found but HEADER_COMPRESSED not set\n"); + return -1; + } + if (decomp_last) { + /* Prevent u64 underflow in decomp_last_rem */ + if (decomp_last->head > decomp_last->size) + return -1; decomp_last_rem = decomp_last->size - decomp_last->head; decomp_len += decomp_last_rem; } @@ -47,14 +55,37 @@ static int perf_session__process_compressed_event(const struct perf_tool *tool _ decomp->size = decomp_last_rem; } + /* + * Events are read directly from the mmap'd file; fields could + * theoretically change via a FUSE-backed file, but that applies + * to the entire event processing pipeline, not just here. + */ if (event->header.type == PERF_RECORD_COMPRESSED) { + if (event->header.size < sizeof(struct perf_record_compressed)) + goto err_decomp; src = (void *)event + sizeof(struct perf_record_compressed); src_size = event->pack.header.size - sizeof(struct perf_record_compressed); } else if (event->header.type == PERF_RECORD_COMPRESSED2) { + /* + * prefetch_event() only guarantees that the 8-byte + * event header fits; validate that header.size covers + * the data_size field before accessing it, otherwise a + * crafted event reads data_size from adjacent memory. + */ + if (event->header.size < sizeof(struct perf_record_compressed2)) + goto err_decomp; src = (void *)event + sizeof(struct perf_record_compressed2); src_size = event->pack2.data_size; + /* + * data_size is independent of header.size (which + * includes padding); verify it doesn't exceed the + * actual payload to prevent out-of-bounds reads in + * zstd_decompress_stream(). + */ + if (src_size > event->header.size - sizeof(struct perf_record_compressed2)) + goto err_decomp; } else { - return -1; + goto err_decomp; } decomp_size = zstd_decompress_stream(session->active_decomp->zstd_decomp, src, src_size, @@ -77,6 +108,11 @@ static int perf_session__process_compressed_event(const struct perf_tool *tool _ pr_debug("decomp (B): %zd to %zd\n", src_size, decomp_size); return 0; + +err_decomp: + munmap(decomp, mmap_len); + pr_err("Couldn't decompress data\n"); + return -1; } #endif From d88e954c8271c9c47d6d50dcfdd864e6b031d166 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 14:51:05 -0300 Subject: [PATCH 142/343] perf session: Check for decompression buffer size overflow On 32-bit systems, sizeof(struct decomp) + decomp_len can wrap size_t when comp_mmap_len is large. The preceding patch validates comp_mmap_len alignment but does not cap the upper bound, so two additions can still overflow: 1. decomp_len += decomp_last_rem: on 32-bit, adding a u64 to size_t silently truncates, producing a corrupted decomp_len that would bypass the subsequent overflow check and result in an undersized buffer allocation. 2. sizeof(struct decomp) + decomp_len: the final addition could overflow on systems with small size_t. Add explicit overflow checks before each addition as defense-in-depth. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/tool.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c index 18641919473a..25c9b378aa16 100644 --- a/tools/perf/util/tool.c +++ b/tools/perf/util/tool.c @@ -34,9 +34,22 @@ static int perf_session__process_compressed_event(const struct perf_tool *tool _ if (decomp_last->head > decomp_last->size) return -1; decomp_last_rem = decomp_last->size - decomp_last->head; + /* + * Check before adding: on 32-bit, size_t += u64 + * silently truncates, bypassing the overflow check + * below and producing an undersized buffer. + */ + if (decomp_last_rem > SIZE_MAX - decomp_len - sizeof(struct decomp)) { + pr_err("Decompression buffer size overflow\n"); + return -1; + } decomp_len += decomp_last_rem; } + if (decomp_len > SIZE_MAX - sizeof(struct decomp)) { + pr_err("Decompression buffer size overflow\n"); + return -1; + } mmap_len = sizeof(struct decomp) + decomp_len; decomp = mmap(NULL, mmap_len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); From a2e59fb79f449fb43ca277a413f1e1de3c3a6326 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 2 May 2026 14:55:43 -0300 Subject: [PATCH 143/343] perf session: Bound nr_cpus_avail and validate sample CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several downstream consumers (timechart, kwork, sched) use fixed-size arrays indexed by CPU. A crafted perf.data can supply arbitrary CPU values that index past these arrays, causing out-of-bounds access. Validate sample.cpu against min(nr_cpus_avail, MAX_NR_CPUS) in perf_session__deliver_event() before any tool callback runs. The cap at MAX_NR_CPUS protects fixed-size downstream arrays; the true nr_cpus_avail is preserved in env for header parsing (e.g. process_cpu_topology) which needs the real count. Fall back to MAX_NR_CPUS when HEADER_NRCPUS is missing (truncated files, pipe mode, pre-2017 perf). Only validate when PERF_SAMPLE_CPU is set in sample_type — when absent, evsel__parse_sample() leaves sample.cpu as (u32)-1, a sentinel that downstream tools (script, inject) check to identify events without CPU info. Clamping it to 0 would break those checks. Inline evlist__parse_sample() into perf_session__deliver_event() so the evsel lookup needed for sample_type checking reuses the same evsel that parsed the sample, avoiding a second evlist__event2evsel() call on every event. For pipe-mode streams where HEADER_NRCPUS may arrive late or not at all, the MAX_NR_CPUS fallback ensures the bounds check is still effective against the fixed-size downstream arrays. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 30 +++++++++++++ tools/perf/util/session.c | 88 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index f771a76321c1..5b1fa1653d2a 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -48,6 +48,7 @@ #include #include "asm/bug.h" #include "tool.h" +#include "../perf.h" #include "time-utils.h" #include "units.h" #include "util/util.h" // perf_exe() @@ -2895,6 +2896,17 @@ static int process_nrcpus(struct feat_fd *ff, void *data __maybe_unused) if (ret) return ret; + /* + * Cap at 1M CPUs — generous for any real system but prevents + * stack overflow from VLA allocations sized by nr_cpus_avail + * (e.g. DECLARE_BITMAP in builtin-c2c.c node_entry()). + */ + if (nr_cpus_avail > (1U << 20)) { + pr_err("Invalid HEADER_NRCPUS: nr_cpus_avail (%u) exceeds maximum (%u)\n", + nr_cpus_avail, 1U << 20); + return -1; + } + if (nr_cpus_online > nr_cpus_avail) { pr_err("Invalid HEADER_NRCPUS: nr_cpus_online (%u) > nr_cpus_avail (%u)\n", nr_cpus_online, nr_cpus_avail); @@ -5250,6 +5262,24 @@ int perf_session__read_header(struct perf_session *session) #endif } + /* + * Without nr_cpus_avail the sample CPU bounds check in + * perf_session__deliver_event() is bypassed, allowing crafted + * CPU IDs to reach downstream consumers that index fixed-size + * arrays (timechart, kwork, sched — all sized MAX_NR_CPUS). + * + * This can happen with truncated files (interrupted recording + * loses all feature sections), very old files that predate + * HEADER_NRCPUS, or crafted files that omit it. Fall back to + * MAX_NR_CPUS so the bounds check is still effective — any + * CPU ID below that limit is safe for all downstream arrays. + */ + if (header->env.nr_cpus_avail == 0) { + header->env.nr_cpus_avail = MAX_NR_CPUS; + pr_warning("WARNING: perf.data is missing HEADER_NRCPUS, using MAX_NR_CPUS (%d) as CPU bound\n", + MAX_NR_CPUS); + } + return 0; out_errno: return -errno; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 9271885e3920..6de665d3c905 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -2110,14 +2110,100 @@ static int perf_session__deliver_event(struct perf_session *session, const char *file_path) { struct perf_sample sample; + struct evsel *evsel; int ret; perf_sample__init(&sample, /*all=*/false); - ret = evlist__parse_sample(session->evlist, event, &sample); + evsel = evlist__event2evsel(session->evlist, event); + if (!evsel) { + pr_err("No evsel found for event type %u\n", + event->header.type); + ret = -EFAULT; + goto out; + } + ret = evsel__parse_sample(evsel, event, &sample); if (ret) { pr_err("Can't parse sample, err = %d\n", ret); goto out; } + /* + * evsel__parse_sample() doesn't populate machine_pid/vcpu, + * which are needed by machines__find_for_cpumode() to + * attribute samples to guest VMs. The SID table maps + * sample IDs to the guest that owns the event. + */ + if (perf_guest && sample.id) { + struct perf_sample_id *sid = evlist__id2sid(session->evlist, sample.id); + + if (sid) { + sample.machine_pid = sid->machine_pid; + sample.vcpu = sid->vcpu.cpu; + } + } + + /* + * Validate sample.cpu before any callback can use it as an + * array index (kwork cpus_runtime, timechart cpus_cstate_*, + * sched cpu_last_switched). + * + * When PERF_SAMPLE_CPU is absent, evsel__parse_sample() leaves + * sample.cpu as (u32)-1 — a sentinel that downstream tools + * (script, inject) check to identify events without CPU info. + * Only check when sample.cpu was actually populated from event + * data: PERF_RECORD_SAMPLE always has it when PERF_SAMPLE_CPU + * is set; non-sample events only have it when sample_id_all is + * enabled. Otherwise sample.cpu is the (u32)-1 sentinel from + * evsel__parse_sample() and must not be validated or clamped. + */ + if ((evsel->core.attr.sample_type & PERF_SAMPLE_CPU) && + (event->header.type == PERF_RECORD_SAMPLE || + evsel->core.attr.sample_id_all)) { + int nr_cpus_avail = perf_session__env(session)->nr_cpus_avail; + + /* + * For perf.data files the MAX_NR_CPUS fallback in + * perf_session__read_header() guarantees this is set. + * For pipe mode, HEADER_NRCPUS may arrive late or not + * at all (pre-2017 perf, third-party tools). Fall + * back to MAX_NR_CPUS so the bounds check still works + * against fixed-size downstream arrays. + * + * Do NOT write back to env: this function runs during + * recording (synthesized events) when nr_cpus_avail is + * legitimately 0. Writing MAX_NR_CPUS would cause + * write_cpu_topology() to emit 4096 core_id/socket_id + * pairs instead of the real CPU count, corrupting the + * topology section in the generated perf.data. + */ + if (nr_cpus_avail <= 0) + nr_cpus_avail = MAX_NR_CPUS; + /* + * Cap at MAX_NR_CPUS for the bounds check — downstream + * consumers use fixed-size arrays of that size. Keep + * the true nr_cpus_avail in env for header parsing + * (e.g. process_cpu_topology) which needs the real count. + */ + if (nr_cpus_avail > MAX_NR_CPUS) + nr_cpus_avail = MAX_NR_CPUS; + if (sample.cpu >= (u32)nr_cpus_avail && + sample.cpu != (u32)-1) { + /* + * Warn rather than abort: synthesized events + * (MMAP, COMM) lack sample_id_all data, so + * parse_id_sample reads garbage from the event + * payload. Clamping to 0 protects downstream + * array indexing while keeping the session alive. + * + * Preserve (u32)-1: perf script and perf inject + * use it as a sentinel for "CPU not applicable." + * Downstream array users (timechart, kwork) have + * their own per-callback bounds checks. + */ + pr_warning_once("WARNING: sample CPU %u >= nr_cpus_avail %u, clamping to 0\n", + sample.cpu, nr_cpus_avail); + sample.cpu = 0; + } + } ret = auxtrace__process_event(session, event, &sample, tool); if (ret < 0) From 48d004c0742dcbc940ffb3b7390540c5a200729e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 3 May 2026 13:05:51 -0300 Subject: [PATCH 144/343] perf kwork: Bounds check work->cpu before indexing cpus_runtime[] work->cpu comes from sample->cpu which is (u32)-1 when PERF_SAMPLE_CPU is absent. Stored as int, this becomes -1 which passes the signed BUG_ON(work->cpu >= MAX_NR_CPUS) but causes an out-of-bounds access on cpus_runtime[-1]. Replace the BUG_ON in top_calc_total_runtime() with an unsigned bounds check that skips entries with invalid CPU values, counting them for a summary warning. Guard the same index in profile_event_match() (bitmap OOB), top_calc_idle_time(), top_calc_irq_runtime(), top_calc_cpu_usage(), and top_calc_load_runtime(). Also guard against division by zero in top_calc_cpu_usage() when no runtime was accumulated. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Cc: Yang Jihong Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kwork.c | 45 +++++++++++++++++++++++++++++++++----- tools/perf/util/kwork.h | 1 + 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index f793ea578515..99dc293a0744 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -467,7 +467,9 @@ static bool profile_event_match(struct perf_kwork *kwork, u64 time = sample->time; struct perf_time_interval *ptime = &kwork->ptime; - if ((kwork->cpu_list != NULL) && !test_bit(cpu, kwork->cpu_bitmap)) + /* Guard test_bit: cpu == -1 (absent PERF_SAMPLE_CPU) would index past the bitmap */ + if ((kwork->cpu_list != NULL) && + ((unsigned int)cpu >= MAX_NR_CPUS || !test_bit(cpu, kwork->cpu_bitmap))) return false; if (((ptime->start != 0) && (ptime->start > time)) || @@ -2041,7 +2043,18 @@ static void top_calc_total_runtime(struct perf_kwork *kwork) next = rb_first_cached(&class->work_root); while (next) { work = rb_entry(next, struct kwork_work, node); - BUG_ON(work->cpu >= MAX_NR_CPUS); + /* + * work->cpu comes from sample->cpu which is -1 when + * PERF_SAMPLE_CPU is absent. As int that's -1, but as + * unsigned it exceeds MAX_NR_CPUS — skip to avoid OOB + * on cpus_runtime[]. + */ + /* Counted and reported in perf_kwork__top_report() */ + if ((unsigned int)work->cpu >= MAX_NR_CPUS) { + stat->nr_skipped_cpu++; + next = rb_next(next); + continue; + } stat->cpus_runtime[work->cpu].total += work->total_runtime; stat->cpus_runtime[MAX_NR_CPUS].total += work->total_runtime; next = rb_next(next); @@ -2053,7 +2066,8 @@ static void top_calc_idle_time(struct perf_kwork *kwork, { struct kwork_top_stat *stat = &kwork->top_stat; - if (work->id == 0) { + /* See comment in top_calc_total_runtime() */ + if (work->id == 0 && (unsigned int)work->cpu < MAX_NR_CPUS) { stat->cpus_runtime[work->cpu].idle += work->total_runtime; stat->cpus_runtime[MAX_NR_CPUS].idle += work->total_runtime; } @@ -2065,6 +2079,10 @@ static void top_calc_irq_runtime(struct perf_kwork *kwork, { struct kwork_top_stat *stat = &kwork->top_stat; + /* See comment in top_calc_total_runtime() */ + if ((unsigned int)work->cpu >= MAX_NR_CPUS) + return; + if (type == KWORK_CLASS_IRQ) { stat->cpus_runtime[work->cpu].irq += work->total_runtime; stat->cpus_runtime[MAX_NR_CPUS].irq += work->total_runtime; @@ -2117,12 +2135,19 @@ static void top_calc_cpu_usage(struct perf_kwork *kwork) if (work->total_runtime == 0) goto next; + /* See comment in top_calc_total_runtime() */ + if ((unsigned int)work->cpu >= MAX_NR_CPUS) + goto next; + __set_bit(work->cpu, stat->all_cpus_bitmap); top_subtract_irq_runtime(kwork, work); - work->cpu_usage = work->total_runtime * 10000 / - stat->cpus_runtime[work->cpu].total; + /* Guard against division by zero if no runtime was accumulated */ + if (stat->cpus_runtime[work->cpu].total) { + work->cpu_usage = work->total_runtime * 10000 / + stat->cpus_runtime[work->cpu].total; + } top_calc_idle_time(kwork, work); next: @@ -2135,7 +2160,8 @@ static void top_calc_load_runtime(struct perf_kwork *kwork, { struct kwork_top_stat *stat = &kwork->top_stat; - if (work->id != 0) { + /* See comment in top_calc_total_runtime() */ + if (work->id != 0 && (unsigned int)work->cpu < MAX_NR_CPUS) { stat->cpus_runtime[work->cpu].load += work->total_runtime; stat->cpus_runtime[MAX_NR_CPUS].load += work->total_runtime; } @@ -2211,6 +2237,13 @@ static void perf_kwork__top_report(struct perf_kwork *kwork) next = rb_next(next); } + if (kwork->top_stat.nr_skipped_cpu) { + printf(" Warning: %u work entries with invalid CPU were excluded from totals.\n" + " Task runtimes may appear inflated (IRQ time not subtracted).\n" + " Consider re-recording with PERF_SAMPLE_CPU enabled.\n", + kwork->top_stat.nr_skipped_cpu); + } + printf("\n"); } diff --git a/tools/perf/util/kwork.h b/tools/perf/util/kwork.h index 81d39a7f78c8..6ec70dcc4157 100644 --- a/tools/perf/util/kwork.h +++ b/tools/perf/util/kwork.h @@ -202,6 +202,7 @@ struct __top_cpus_runtime { struct kwork_top_stat { DECLARE_BITMAP(all_cpus_bitmap, MAX_NR_CPUS); struct __top_cpus_runtime *cpus_runtime; + unsigned int nr_skipped_cpu; }; struct perf_kwork { From f6ded4d1e8b5e29278605e89c893197fb484c2a6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 23 May 2026 15:30:15 -0300 Subject: [PATCH 145/343] perf session: Snapshot event->header.size in process_user_event() On native-endian files, events are read from MAP_SHARED memory. Multiple reads of event->header.size can return different values if the file is concurrently modified, allowing an attacker to bypass bounds checks performed on an earlier read. Snapshot header.size into a local variable at function entry using READ_ONCE() to prevent compiler rematerialization, and use it for all size-dependent arithmetic within the function. This ensures every bounds calculation uses the same value that was validated by the reader. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 6de665d3c905..e2e821b77766 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -2230,6 +2230,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, { struct ordered_events *oe = &session->ordered_events; const struct perf_tool *tool = session->tool; + const u32 event_size = READ_ONCE(event->header.size); struct perf_sample sample; int fd = perf_data__fd(session->data); s64 err; @@ -2271,7 +2272,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, break; case PERF_RECORD_HEADER_BUILD_ID: if (!perf_event__check_nul(event->build_id.filename, - (void *)event + event->header.size, + (void *)event + event_size, "HEADER_BUILD_ID")) { err = 0; break; @@ -2294,7 +2295,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, * place already. */ if (!perf_data__is_pipe(session->data)) - lseek(fd, file_offset + event->header.size, SEEK_SET); + lseek(fd, file_offset + event_size, SEEK_SET); err = tool->auxtrace(tool, session, event); break; case PERF_RECORD_AUXTRACE_ERROR: @@ -2304,14 +2305,14 @@ static s64 perf_session__process_user_event(struct perf_session *session, case PERF_RECORD_THREAD_MAP: { u64 max_nr; - if (event->header.size < sizeof(event->thread_map)) { + if (event_size < sizeof(event->thread_map)) { pr_err("PERF_RECORD_THREAD_MAP: header.size (%u) too small\n", - event->header.size); + event_size); err = -EINVAL; break; } - max_nr = (event->header.size - sizeof(event->thread_map)) / + max_nr = (event_size - sizeof(event->thread_map)) / sizeof(event->thread_map.entries[0]); if (event->thread_map.nr > max_nr) { pr_err("PERF_RECORD_THREAD_MAP: nr %" PRIu64 " exceeds max %" PRIu64 "\n", @@ -2325,7 +2326,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, } case PERF_RECORD_CPU_MAP: { struct perf_record_cpu_map_data *data = &event->cpu_map.data; - u32 payload = event->header.size - sizeof(event->header); + u32 payload = event_size - sizeof(event->header); /* * Native-endian events are mmap'd read-only, so we @@ -2389,8 +2390,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, break; } case PERF_RECORD_STAT_CONFIG: { - /* Cannot underflow: perf_event__min_size[] guarantees header.size >= sizeof */ - u64 max_nr = (event->header.size - sizeof(event->stat_config)) / + /* Cannot underflow: perf_event__min_size[] guarantees event_size >= sizeof */ + u64 max_nr = (event_size - sizeof(event->stat_config)) / sizeof(event->stat_config.data[0]); /* @@ -2421,7 +2422,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, */ memset(&session->time_conv, 0, sizeof(session->time_conv)); memcpy(&session->time_conv, &event->time_conv, - min((size_t)event->header.size, sizeof(session->time_conv))); + min((size_t)event_size, sizeof(session->time_conv))); err = tool->time_conv(tool, session, event); break; case PERF_RECORD_HEADER_FEATURE: @@ -2438,11 +2439,10 @@ static s64 perf_session__process_user_event(struct perf_session *session, break; case PERF_RECORD_BPF_METADATA: { u64 nr_entries, max_entries; - u32 hdr_size = READ_ONCE(event->header.size); - if (hdr_size < sizeof(event->bpf_metadata)) { + if (event_size < sizeof(event->bpf_metadata)) { pr_warning("WARNING: PERF_RECORD_BPF_METADATA: header.size (%u) too small, skipping\n", - hdr_size); + event_size); err = 0; break; } @@ -2458,9 +2458,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, break; } - /* Snapshot — event is mmap'd and could change between reads */ nr_entries = READ_ONCE(event->bpf_metadata.nr_entries); - max_entries = (hdr_size - sizeof(event->bpf_metadata)) / + max_entries = (event_size - sizeof(event->bpf_metadata)) / sizeof(event->bpf_metadata.entries[0]); if (nr_entries > max_entries) { pr_warning("WARNING: PERF_RECORD_BPF_METADATA: nr_entries %" PRIu64 " exceeds max %" PRIu64 ", skipping\n", From f86446669053125485a4721a722b446e1c3e5efa Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 9 May 2026 23:55:07 -0300 Subject: [PATCH 146/343] perf test: Add truncated perf.data robustness test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a shell test that verifies perf report handles truncated perf.data files gracefully — exiting with an error code rather than crashing with SIGSEGV or SIGABRT. The test records a simple workload, then truncates the resulting perf.data at four offsets that exercise different parsing stages: 8 bytes — file header magic only 64 bytes — partial file header (attr section incomplete) 256 bytes — into the first events (partial event headers) 75% size — mid-stream truncation (partial event data) For each truncation, perf report is run and the exit code is checked: - Exit code 0 (success) fails the test — a truncated file should never parse without error. - Crash signals are detected portably via kill -l, which maps the signal number to a name on the running system. This handles architectures where signal numbers differ (e.g. SIGBUS is 7 on x86/ARM but 10 on MIPS/SPARC). Core-dump and fatal signals (KILL, ILL, ABRT, BUS, FPE, SEGV, TRAP, SYS) fail the test. - Higher exit codes (200+) are perf's own negative-errno returns (e.g. -EINVAL = 234) and are expected. This exercises the bounds checking, minimum-size validation, and error propagation added by the preceding patches in this series. Testing it: root@number:~# perf test truncat 84: Test that perf report handles truncated perf.data gracefully (no crash, no segfault — clean error exit).: Ok root@number:~# perf test -vv truncat 84: Test that perf report handles truncated perf.data gracefully (no crash, no segfault — clean error exit).: --- start --- test child forked, pid 62890 ---- end(0) ---- 84: Test that perf report handles truncated perf.data gracefully (no crash, no segfault — clean error exit).: Ok root@number:~# Changes in v2: - Add SIGKILL to the list of fatal signals so OOM kills from resource exhaustion bugs are detected (Reported-by: sashiko-bot@kernel.org) Reviewed-by: Ian Rogers Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6-1m [ Fixed the SPDX on the line where 'perf test' expects the test description, reviewed by Ian Rogers ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/data_validation.sh | 86 +++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100755 tools/perf/tests/shell/data_validation.sh diff --git a/tools/perf/tests/shell/data_validation.sh b/tools/perf/tests/shell/data_validation.sh new file mode 100755 index 000000000000..bf16b2f2b911 --- /dev/null +++ b/tools/perf/tests/shell/data_validation.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# Test that perf report handles truncated perf.data gracefully (no crash, no segfault — clean error exit). +# SPDX-License-Identifier: GPL-2.0 +# +# Exercises the bounds checking and minimum-size validation added +# by the perf-data-validation hardening series. + +err=0 + +cleanup() { + [ -n "${perfdata}" ] && rm -f "${perfdata}" "${perfdata}.old" + rm -f "${truncated}" "${stderrfile}" + trap - EXIT TERM INT +} +trap 'cleanup; exit 1' TERM INT +trap cleanup EXIT + +perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2 +truncated=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2 +stderrfile=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2 + +# Record a simple workload +if ! perf record -o "${perfdata}" -- perf test -w noploop 2>/dev/null; then + echo "Skip: perf record failed" + cleanup + exit 2 +fi + +file_size=$(wc -c < "${perfdata}") +if [ "${file_size}" -lt 512 ]; then + echo "Skip: perf.data too small (${file_size} bytes)" + cleanup + exit 2 +fi + +# Test truncation at various offsets that exercise different +# parsing stages: +# 8 — file header magic only, no attrs or data +# 64 — partial file header (attr section incomplete) +# 256 — into the first events (partial event headers) +# 75% — mid-stream truncation (partial event data) +for cut_at in 8 64 256 $((file_size * 3 / 4)); do + if [ "${cut_at}" -ge "${file_size}" ]; then + continue + fi + dd if="${perfdata}" of="${truncated}" bs="${cut_at}" count=1 2>/dev/null + + # perf report should exit with an error, not crash. + # Capture stderr to detect sanitizer violations. + perf report -i "${truncated}" --stdio > /dev/null 2> "${stderrfile}" + exit_code=$? + + # A truncated file should never parse successfully + if [ ${exit_code} -eq 0 ]; then + echo "FAIL: perf report exited 0 (success) on ${cut_at}-byte truncated file — expected an error" + err=1 + continue + fi + + # Detect sanitizer violations — ASAN/MSAN/TSAN/UBSAN exit + # with code 1 by default, which would otherwise look like a + # clean error exit. Check stderr for their markers. + if grep -qE "^(==[0-9]+==ERROR:|SUMMARY: [A-Za-z]*Sanitizer)" "${stderrfile}" 2>/dev/null; then + sanitizer=$(grep -oE "(Address|Memory|Thread|UndefinedBehavior)Sanitizer" "${stderrfile}" | head -1) + echo "FAIL: perf report triggered ${sanitizer:-sanitizer} on ${cut_at}-byte truncated file" + err=1 + continue + fi + + # Detect crash signals portably — signal numbers differ + # across architectures (e.g. SIGBUS is 7 on x86/ARM but + # 10 on MIPS/SPARC). Use kill -l to map the number to a + # name on the running system. + if [ ${exit_code} -gt 128 ] && [ ${exit_code} -lt 200 ]; then + sig_name=$(kill -l $((exit_code - 128)) 2>/dev/null) + case ${sig_name} in + KILL|ILL|ABRT|BUS|FPE|SEGV|TRAP|SYS) + echo "FAIL: perf report crashed (SIG${sig_name}) on ${cut_at}-byte truncated file" + err=1 + ;; + esac + fi +done + +cleanup +exit ${err} From 6f31bb737ef8c519e0d58d39d93a5352b920b9b7 Mon Sep 17 00:00:00 2001 From: James Clark Date: Mon, 11 May 2026 10:19:35 +0100 Subject: [PATCH 147/343] perf test: Make leafloop workload immune to compiler options Since the leafloop test program was moved into the main Perf binary as a workload, it inherited the same compiler options as Perf. In this case the -fstack-protector option broke the assumption that simple leaf frames don't have a stack frame on Arm. This causes test_arm_callgraph_fp.sh to pass even if the stack isn't augmented with the link register, making the test useless. Fix it by rewriting the leaf function in assembly seeing as it's so simple. Adding -fno-stack-protector would also work, but wouldn't be robust against other future compiler option additions. The local variables and 'a' variable were never needed so remove them to simplify. Reviewed-by: Ian Rogers Assisted-by: GitHub-Copilot:GPT-5.5 Signed-off-by: James Clark Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/workloads/leafloop.c | 40 +++++++++++++++++++++------ 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/tools/perf/tests/workloads/leafloop.c b/tools/perf/tests/workloads/leafloop.c index f7561767e32c..c20c75f7ba49 100644 --- a/tools/perf/tests/workloads/leafloop.c +++ b/tools/perf/tests/workloads/leafloop.c @@ -6,26 +6,48 @@ #include "../tests.h" /* We want to check these symbols in perf script */ -noinline void leaf(volatile int b); -noinline void parent(volatile int b); +noinline void leaf(void); +noinline void parent(void); -static volatile int a; -static volatile sig_atomic_t done; +static volatile sig_atomic_t done asm("leafloop_done"); static void sighandler(int sig __maybe_unused) { done = 1; } -noinline void leaf(volatile int b) +#if defined(__aarch64__) +/* + * Write leaf() in assembly so it stays as a minimal leaf function with no + * stack frame and won't get silently broken in the future by any Perf wide + * compilation options like -fstack-protector-all. + */ +asm( + ".pushsection .text,\"ax\",%progbits\n" + ".global leaf\n" + ".type leaf, %function\n" + "leaf:\n" + " adrp x1, leafloop_done\n" + " ldr w2, [x1, #:lo12:leafloop_done]\n" + " cbz w2, leaf\n" + " ret\n" + ".size leaf, .-leaf\n" + ".popsection\n" +); + +#else + +noinline void leaf(void) { while (!done) - a += b; + ; } -noinline void parent(volatile int b) +#endif + +noinline void parent(void) { - leaf(b); + leaf(); } static int leafloop(int argc, const char **argv) @@ -39,7 +61,7 @@ static int leafloop(int argc, const char **argv) signal(SIGALRM, sighandler); alarm(sec); - parent(sec); + parent(); return 0; } From e1620c2add523868f3655feb5e4727ddeee83c59 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:43 -0700 Subject: [PATCH 148/343] perf vendor events intel: Update alderlake events from 1.37 to 1.39 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events were published in: https://github.com/intel/perfmon/commit/e55693d19f4dfe6b09c0ee9eb2b4e93781e16dd9 https://github.com/intel/perfmon/commit/25a1cd4847c1ed9159b5c79d1f7afe24ec965269 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- .../pmu-events/arch/x86/alderlake/cache.json | 85 +++++++++++++++++++ .../pmu-events/arch/x86/alderlake/memory.json | 64 ++++++++++++++ .../arch/x86/alderlake/pipeline.json | 54 ++++++++++++ .../arch/x86/alderlake/virtual-memory.json | 9 ++ tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 5 files changed, 213 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/arch/x86/alderlake/cache.json b/tools/perf/pmu-events/arch/x86/alderlake/cache.json index 5d0d824f3e7e..e44e6b651d55 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/cache.json @@ -150,6 +150,16 @@ "UMask": "0x2", "Unit": "cpu_atom" }, + { + "BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "SampleAfterValue": "200003", + "UMask": "0xdf", + "Unit": "cpu_core" + }, { "BriefDescription": "Counts the number of L2 Cache accesses that resulted in a miss. Counts on a per core basis.", "Counter": "0,1,2,3,4,5", @@ -259,6 +269,16 @@ "UMask": "0x21", "Unit": "cpu_core" }, + { + "BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "L2_RQSTS.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "SampleAfterValue": "200003", + "UMask": "0xdf", + "Unit": "cpu_core" + }, { "BriefDescription": "L2_RQSTS.HWPF_MISS", "Counter": "0,1,2,3", @@ -338,6 +358,16 @@ "UMask": "0x40", "Unit": "cpu_core" }, + { + "BriefDescription": "Cycles when L1D is locked", + "Counter": "0,1,2,3", + "EventCode": "0x42", + "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION", + "PublicDescription": "This event counts the number of cycles when the L1D is locked. It is a superset of the 0x1 mask (BUS_LOCK_CLOCKS.BUS_LOCK_DURATION).", + "SampleAfterValue": "2000003", + "UMask": "0x2", + "Unit": "cpu_core" + }, { "BriefDescription": "Counts the number of cacheable memory requests that miss in the LLC. Counts on a per core basis.", "Counter": "0,1,2,3,4,5", @@ -853,6 +883,17 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of memory uops retired.", + "Counter": "0,1,2,3,4,5", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.ALL", + "PublicDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST)", + "SampleAfterValue": "200003", + "UMask": "0x83", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of load uops retired.", "Counter": "0,1,2,3,4,5", @@ -875,6 +916,18 @@ "UMask": "0x82", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024. Only counts with PEBS enabled.", + "Counter": "0,1", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024", + "MSRIndex": "0x3F6", + "MSRValue": "0x400", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128. Only counts with PEBS enabled.", "Counter": "0,1", @@ -899,6 +952,18 @@ "UMask": "0x5", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048. Only counts with PEBS enabled.", + "Counter": "0,1", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048", + "MSRIndex": "0x3F6", + "MSRValue": "0x800", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256. Only counts with PEBS enabled.", "Counter": "0,1", @@ -981,6 +1046,16 @@ "UMask": "0x21", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of memory uops retired that were splits.", + "Counter": "0,1,2,3,4,5", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.SPLIT", + "SampleAfterValue": "200003", + "UMask": "0x43", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of retired split load uops.", "Counter": "0,1,2,3,4,5", @@ -991,6 +1066,16 @@ "UMask": "0x41", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of retired split store uops.", + "Counter": "0,1,2,3,4,5", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES", + "SampleAfterValue": "200003", + "UMask": "0x42", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the total number of load and store uops retired that missed in the second level TLB.", "Counter": "0,1,2,3,4,5", diff --git a/tools/perf/pmu-events/arch/x86/alderlake/memory.json b/tools/perf/pmu-events/arch/x86/alderlake/memory.json index a0260d5b8619..f482c06ac728 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/memory.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/memory.json @@ -9,6 +9,15 @@ "UMask": "0x6", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.ANY", + "SampleAfterValue": "1000003", + "UMask": "0x7f", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block, on a load that retires.", "Counter": "0,1,2,3,4,5", @@ -27,6 +36,15 @@ "UMask": "0xf4", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DL1 miss.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.L1_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DL1 miss.", "Counter": "0,1,2,3,4,5", @@ -36,6 +54,16 @@ "UMask": "0x81", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.OTHER", + "PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases such as pipeline conflicts, fences, etc.", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases.", "Counter": "0,1,2,3,4,5", @@ -46,6 +74,15 @@ "UMask": "0xc0", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a pagewalk.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.PGWALK", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a pagewalk.", "Counter": "0,1,2,3,4,5", @@ -55,6 +92,15 @@ "UMask": "0xa0", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a store data forward block.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.ST_ADDR", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a store address match.", "Counter": "0,1,2,3,4,5", @@ -64,6 +110,24 @@ "UMask": "0x84", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL_AT_RET", + "SampleAfterValue": "1000003", + "UMask": "0x82", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of machine clears due to memory ordering caused by a snoop from an external agent. Does not count internally generated machine clears such as those due to memory disambiguation.", "Counter": "0,1,2,3,4,5", diff --git a/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json b/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json index 80cad3c49d20..1c292f29b0aa 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json @@ -349,6 +349,15 @@ "UMask": "0xfd", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of near relative JMP branch instructions retired.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.REL_JMP", + "SampleAfterValue": "200003", + "UMask": "0xdf", + "Unit": "cpu_atom" + }, { "BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.NEAR_RETURN", "Counter": "0,1,2,3,4,5", @@ -359,6 +368,15 @@ "UMask": "0xf7", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of taken branch instructions retired.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.TAKEN", + "SampleAfterValue": "200003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.COND_TAKEN", "Counter": "0,1,2,3,4,5", @@ -560,6 +578,15 @@ "UMask": "0xfe", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the total number of BTCLEARS.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xe8", + "EventName": "BTCLEAR.ANY", + "PublicDescription": "Counts the total number of BTCLEARS which occurs when the Branch Target Buffer (BTB) predicts a taken branch.", + "SampleAfterValue": "200003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Core clocks when the thread is in the C0.1 light-weight slower wakeup time but more power saving optimized state.", "Counter": "0,1,2,3,4,5,6,7", @@ -1214,6 +1241,24 @@ "UMask": "0x8", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FAST", + "SampleAfterValue": "20003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of virtual traps taken.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP", + "SampleAfterValue": "20003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of machines clears due to memory renaming.", "Counter": "0,1,2,3,4,5", @@ -1410,6 +1455,15 @@ "UMask": "0x4", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number issue slots not consumed due to a color request for an FCW or MXCSR control register when all 4 colors (copies) are already in use.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x75", + "EventName": "SERIALIZATION.COLOR_STALLS", + "SampleAfterValue": "200003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires.", "Counter": "0,1,2,3,4,5", diff --git a/tools/perf/pmu-events/arch/x86/alderlake/virtual-memory.json b/tools/perf/pmu-events/arch/x86/alderlake/virtual-memory.json index 132ce48af6d9..115bbc000a45 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/virtual-memory.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/virtual-memory.json @@ -250,6 +250,15 @@ "UMask": "0x10", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DTLB miss.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.DTLB_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DTLB miss.", "Counter": "0,1,2,3,4,5", diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 8a9e1735e21e..2f542283202a 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -1,5 +1,5 @@ Family-model,Version,Filename,EventType -GenuineIntel-6-(97|9A|B7|BA|BF),v1.37,alderlake,core +GenuineIntel-6-(97|9A|B7|BA|BF),v1.39,alderlake,core GenuineIntel-6-BE,v1.37,alderlaken,core GenuineIntel-6-C[56],v1.16,arrowlake,core GenuineIntel-6-(1C|26|27|35|36),v5,bonnell,core From 9996a23d319dd5db39bb8f89debeead52658b70c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:44 -0700 Subject: [PATCH 149/343] perf vendor events intel: Update alderlaken events from 1.37 to 1.39 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events were published in: https://github.com/intel/perfmon/commit/e55693d19f4dfe6b09c0ee9eb2b4e93781e16dd9 https://github.com/intel/perfmon/commit/25a1cd4847c1ed9159b5c79d1f7afe24ec965269 Signed-off-by: Ian Rogers Reviewed-by: Dapeng Mi Link: https://lore.kernel.org/r/20260529045155.311805-3-irogers@google.com Cc: Peter Zijlstra Cc: Adrian Hunter Cc: Thomas Falcon Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: James Clark Cc: Alexander Shishkin Cc: Ingo Molnar Cc: Andreas Färber Cc: linux-kernel@vger.kernel.org Cc: linux-perf-users@vger.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../pmu-events/arch/x86/alderlaken/cache.json | 50 ++++++++++++++++ .../arch/x86/alderlaken/memory.json | 57 +++++++++++++++++++ .../arch/x86/alderlaken/pipeline.json | 48 ++++++++++++++++ .../arch/x86/alderlaken/virtual-memory.json | 8 +++ tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 5 files changed, 164 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/cache.json b/tools/perf/pmu-events/arch/x86/alderlaken/cache.json index 1f97a4dc6fb1..0ffad953e752 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/cache.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/cache.json @@ -225,6 +225,16 @@ "SampleAfterValue": "20003", "UMask": "0x1" }, + { + "BriefDescription": "Counts the number of memory uops retired.", + "Counter": "0,1,2,3,4,5", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.ALL", + "PublicDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST)", + "SampleAfterValue": "200003", + "UMask": "0x83" + }, { "BriefDescription": "Counts the number of load uops retired.", "Counter": "0,1,2,3,4,5", @@ -245,6 +255,17 @@ "SampleAfterValue": "200003", "UMask": "0x82" }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024. Only counts with PEBS enabled.", + "Counter": "0,1", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024", + "MSRIndex": "0x3F6", + "MSRValue": "0x400", + "SampleAfterValue": "1000003", + "UMask": "0x5" + }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128. Only counts with PEBS enabled.", "Counter": "0,1", @@ -267,6 +288,17 @@ "SampleAfterValue": "1000003", "UMask": "0x5" }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048. Only counts with PEBS enabled.", + "Counter": "0,1", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048", + "MSRIndex": "0x3F6", + "MSRValue": "0x800", + "SampleAfterValue": "1000003", + "UMask": "0x5" + }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256. Only counts with PEBS enabled.", "Counter": "0,1", @@ -342,6 +374,15 @@ "SampleAfterValue": "200003", "UMask": "0x21" }, + { + "BriefDescription": "Counts the number of memory uops retired that were splits.", + "Counter": "0,1,2,3,4,5", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.SPLIT", + "SampleAfterValue": "200003", + "UMask": "0x43" + }, { "BriefDescription": "Counts the number of retired split load uops.", "Counter": "0,1,2,3,4,5", @@ -351,6 +392,15 @@ "SampleAfterValue": "200003", "UMask": "0x41" }, + { + "BriefDescription": "Counts the number of retired split store uops.", + "Counter": "0,1,2,3,4,5", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES", + "SampleAfterValue": "200003", + "UMask": "0x42" + }, { "BriefDescription": "Counts the total number of load and store uops retired that missed in the second level TLB.", "Counter": "0,1,2,3,4,5", diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/memory.json b/tools/perf/pmu-events/arch/x86/alderlaken/memory.json index 049c5e2630d7..a0dd82ddd58a 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/memory.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/memory.json @@ -1,4 +1,12 @@ [ + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.ANY", + "SampleAfterValue": "1000003", + "UMask": "0x7f" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block, on a load that retires.", "Counter": "0,1,2,3,4,5", @@ -15,6 +23,14 @@ "SampleAfterValue": "1000003", "UMask": "0xf4" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DL1 miss.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.L1_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DL1 miss.", "Counter": "0,1,2,3,4,5", @@ -23,6 +39,15 @@ "SampleAfterValue": "1000003", "UMask": "0x81" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.OTHER", + "PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases such as pipeline conflicts, fences, etc.", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases.", "Counter": "0,1,2,3,4,5", @@ -32,6 +57,14 @@ "SampleAfterValue": "1000003", "UMask": "0xc0" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a pagewalk.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.PGWALK", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a pagewalk.", "Counter": "0,1,2,3,4,5", @@ -40,6 +73,14 @@ "SampleAfterValue": "1000003", "UMask": "0xa0" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a store data forward block.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.ST_ADDR", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a store address match.", "Counter": "0,1,2,3,4,5", @@ -48,6 +89,22 @@ "SampleAfterValue": "1000003", "UMask": "0x84" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL_AT_RET", + "SampleAfterValue": "1000003", + "UMask": "0x82" + }, { "BriefDescription": "Counts the number of machine clears due to memory ordering caused by a snoop from an external agent. Does not count internally generated machine clears such as those due to memory disambiguation.", "Counter": "0,1,2,3,4,5", diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json b/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json index a13851071624..ad3acb109bd8 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json @@ -175,6 +175,14 @@ "SampleAfterValue": "200003", "UMask": "0xfd" }, + { + "BriefDescription": "Counts the number of near relative JMP branch instructions retired.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.REL_JMP", + "SampleAfterValue": "200003", + "UMask": "0xdf" + }, { "BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.NEAR_RETURN", "Counter": "0,1,2,3,4,5", @@ -184,6 +192,14 @@ "SampleAfterValue": "200003", "UMask": "0xf7" }, + { + "BriefDescription": "Counts the number of taken branch instructions retired.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.TAKEN", + "SampleAfterValue": "200003", + "UMask": "0x80" + }, { "BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.COND_TAKEN", "Counter": "0,1,2,3,4,5", @@ -293,6 +309,14 @@ "SampleAfterValue": "200003", "UMask": "0xfe" }, + { + "BriefDescription": "Counts the total number of BTCLEARS.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xe8", + "EventName": "BTCLEAR.ANY", + "PublicDescription": "Counts the total number of BTCLEARS which occurs when the Branch Target Buffer (BTB) predicts a taken branch.", + "SampleAfterValue": "200003" + }, { "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles. [This event is alias to CPU_CLK_UNHALTED.THREAD]", "Counter": "Fixed counter 1", @@ -400,6 +424,22 @@ "SampleAfterValue": "20003", "UMask": "0x8" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FAST", + "SampleAfterValue": "20003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of virtual traps taken.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP", + "SampleAfterValue": "20003", + "UMask": "0x40" + }, { "BriefDescription": "Counts the number of machines clears due to memory renaming.", "Counter": "0,1,2,3,4,5", @@ -482,6 +522,14 @@ "SampleAfterValue": "200003", "UMask": "0x4" }, + { + "BriefDescription": "Counts the number issue slots not consumed due to a color request for an FCW or MXCSR control register when all 4 colors (copies) are already in use.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x75", + "EventName": "SERIALIZATION.COLOR_STALLS", + "SampleAfterValue": "200003", + "UMask": "0x8" + }, { "BriefDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires.", "Counter": "0,1,2,3,4,5", diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/virtual-memory.json b/tools/perf/pmu-events/arch/x86/alderlaken/virtual-memory.json index d9c737a17df0..56c1bfc38024 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/virtual-memory.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/virtual-memory.json @@ -42,6 +42,14 @@ "SampleAfterValue": "200003", "UMask": "0xe" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DTLB miss.", + "Counter": "0,1,2,3,4,5", + "EventCode": "0x05", + "EventName": "LD_HEAD.DTLB_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DTLB miss.", "Counter": "0,1,2,3,4,5", diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 2f542283202a..c076dbed1611 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -1,6 +1,6 @@ Family-model,Version,Filename,EventType GenuineIntel-6-(97|9A|B7|BA|BF),v1.39,alderlake,core -GenuineIntel-6-BE,v1.37,alderlaken,core +GenuineIntel-6-BE,v1.39,alderlaken,core GenuineIntel-6-C[56],v1.16,arrowlake,core GenuineIntel-6-(1C|26|27|35|36),v5,bonnell,core GenuineIntel-6-(3D|47),v30,broadwell,core From 8a990b123bf524205484516339e469fbe887a000 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:45 -0700 Subject: [PATCH 150/343] perf vendor events intel: Update arrowlake events from 1.16 to 1.17 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events were published in: https://github.com/intel/perfmon/commit/90c505bcd9b10fd9ce692a670c23074ab743aa87 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- .../pmu-events/arch/x86/arrowlake/cache.json | 53 +++++++++++++++++++ .../arch/x86/arrowlake/floating-point.json | 9 ++++ .../arch/x86/arrowlake/pipeline.json | 48 ++++++++++++++++- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 4 files changed, 110 insertions(+), 2 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/cache.json b/tools/perf/pmu-events/arch/x86/arrowlake/cache.json index 4c3aa1fab5a8..fe6b9ad68f87 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/cache.json @@ -339,6 +339,16 @@ "UMask": "0x2", "Unit": "cpu_atom" }, + { + "BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "Counter": "0,1,2,3,4,5,6,7,8,9", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "SampleAfterValue": "200003", + "UMask": "0x5f", + "Unit": "cpu_core" + }, { "BriefDescription": "Counts the number of L2 Cache Accesses that resulted in a Hit from a front door request only (does not include rejects or recycles), per core event", "Counter": "0,1,2,3,4,5,6,7", @@ -464,6 +474,16 @@ "UMask": "0x21", "Unit": "cpu_core" }, + { + "BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "Counter": "0,1,2,3,4,5,6,7,8,9", + "EventCode": "0x24", + "EventName": "L2_RQSTS.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "SampleAfterValue": "200003", + "UMask": "0x5f", + "Unit": "cpu_core" + }, { "BriefDescription": "Read requests with true-miss in L2 cache [This event is alias to L2_REQUEST.MISS]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1126,6 +1146,15 @@ "UMask": "0x20", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of retired load ops that hit in the L3 cache in which a snoop was required and modified data was forwarded", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_HITM", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of retired load ops with an unknown source", "Counter": "0,1,2,3,4,5,6,7", @@ -1393,6 +1422,18 @@ "UMask": "0x82", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024.", + "Counter": "0,1", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024", + "MSRIndex": "0x3F6", + "MSRValue": "0x400", + "SampleAfterValue": "200003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024. Only counts with PEBS enabled.", "Counter": "0,1", @@ -1453,6 +1494,18 @@ "UMask": "0x5", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048.", + "Counter": "0,1", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048", + "MSRIndex": "0x3F6", + "MSRValue": "0x800", + "SampleAfterValue": "200003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048. Only counts with PEBS enabled.", "Counter": "0,1", diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/floating-point.json b/tools/perf/pmu-events/arch/x86/arrowlake/floating-point.json index 3e68c2468f11..c54fc201a6ca 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/floating-point.json @@ -564,6 +564,15 @@ "UMask": "0x1", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer store data port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.STD", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_lowpower" + }, { "BriefDescription": "Counts the number of floating point operations retired that required microcode assist.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/arrowlake/pipeline.json b/tools/perf/pmu-events/arch/x86/arrowlake/pipeline.json index fb973c75be57..a0fd63cace22 100644 --- a/tools/perf/pmu-events/arch/x86/arrowlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/arrowlake/pipeline.json @@ -376,7 +376,7 @@ "Unit": "cpu_lowpower" }, { - "BriefDescription": "Counts the number of taken branch instructions retired", + "BriefDescription": "Counts the number of near taken branch instructions retired", "Counter": "0,1,2,3,4,5,6,7", "EventCode": "0xc4", "EventName": "BR_INST_RETIRED.NEAR_TAKEN", @@ -422,6 +422,15 @@ "UMask": "0xfd", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of relative JMP branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.REL_JMP", + "SampleAfterValue": "200003", + "UMask": "0xdf", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of near relative JMP branch instructions retired.", "Counter": "0,1,2,3,4,5,6,7", @@ -431,6 +440,25 @@ "UMask": "0xdf", "Unit": "cpu_lowpower" }, + { + "BriefDescription": "Counts the number of taken branch instructions retired", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.TAKEN", + "SampleAfterValue": "200003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of taken branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "Errata": "ARL011", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.TAKEN", + "SampleAfterValue": "200003", + "UMask": "0x80", + "Unit": "cpu_lowpower" + }, { "BriefDescription": "Counts the total number of mispredicted branch instructions retired for all branch types.", "Counter": "0,1,2,3,4,5,6,7", @@ -1663,6 +1691,15 @@ "UMask": "0x88", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts number of virtual trap actually taken (e.g. highest priority event during retirement). It can count virtual trap from FPC port 0 or port 1 (x87/SSE) equally in a single counter.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP", + "SampleAfterValue": "20003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of nukes due to memory renaming", "Counter": "0,1,2,3,4,5,6,7", @@ -1672,6 +1709,15 @@ "UMask": "0x10", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of machines clears due to memory renaming.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MRN_NUKE", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_lowpower" + }, { "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index c076dbed1611..85f41cab56c7 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -1,7 +1,7 @@ Family-model,Version,Filename,EventType GenuineIntel-6-(97|9A|B7|BA|BF),v1.39,alderlake,core GenuineIntel-6-BE,v1.39,alderlaken,core -GenuineIntel-6-C[56],v1.16,arrowlake,core +GenuineIntel-6-C[56],v1.17,arrowlake,core GenuineIntel-6-(1C|26|27|35|36),v5,bonnell,core GenuineIntel-6-(3D|47),v30,broadwell,core GenuineIntel-6-56,v12,broadwellde,core From 1a5c515eae7c2234b86b35b3b0f2ab94887f43d7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:46 -0700 Subject: [PATCH 151/343] perf vendor events intel: Update clearwaterforest events and metrics from 1.00 to 1.02 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events and metrics were published in: https://github.com/intel/perfmon/commit/6de6be144b5ea747690a74106f180269c3d647b0 https://github.com/intel/perfmon/commit/e7f5e6092c3e4c11f350c0468ddecb0e1e818b76 https://github.com/intel/perfmon/commit/9c1a1baa5156efbe9325392194d2bf5d1c8bcb92 https://github.com/intel/perfmon/commit/6055edb3c30634fc913250b562c0fc42ac4eb523 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- .../arch/x86/clearwaterforest/cache.json | 525 ++- .../arch/x86/clearwaterforest/counter.json | 79 +- .../x86/clearwaterforest/cwf-metrics.json | 310 ++ .../x86/clearwaterforest/floating-point.json | 191 + .../arch/x86/clearwaterforest/frontend.json | 226 ++ .../arch/x86/clearwaterforest/memory.json | 92 + .../arch/x86/clearwaterforest/other.json | 20 + .../arch/x86/clearwaterforest/pipeline.json | 829 +++- .../x86/clearwaterforest/uncore-cache.json | 3413 +++++++++++++++++ .../arch/x86/clearwaterforest/uncore-cxl.json | 31 + .../clearwaterforest/uncore-interconnect.json | 1625 ++++++++ .../arch/x86/clearwaterforest/uncore-io.json | 1925 ++++++++++ .../x86/clearwaterforest/uncore-memory.json | 883 +++++ .../x86/clearwaterforest/uncore-power.json | 109 + .../x86/clearwaterforest/virtual-memory.json | 94 + tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 16 files changed, 10307 insertions(+), 47 deletions(-) create mode 100644 tools/perf/pmu-events/arch/x86/clearwaterforest/cwf-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/clearwaterforest/floating-point.json create mode 100644 tools/perf/pmu-events/arch/x86/clearwaterforest/other.json create mode 100644 tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-cache.json create mode 100644 tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-cxl.json create mode 100644 tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-interconnect.json create mode 100644 tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-io.json create mode 100644 tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-memory.json create mode 100644 tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-power.json diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/cache.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/cache.json index ecb7dc252208..480874ccbd09 100644 --- a/tools/perf/pmu-events/arch/x86/clearwaterforest/cache.json +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/cache.json @@ -1,4 +1,140 @@ [ + { + "BriefDescription": "Counts the number of requests that were not accepted into the L2Q because the L2Q is FULL.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x31", + "EventName": "CORE_REJECT_L2Q.ANY", + "PublicDescription": "Counts the number of (demand and L1 prefetchers) core requests rejected by the L2Q due to a full or nearly full condition which likely indicates back pressure from L2Q. It also counts requests that would have gone directly to the XQ, but are rejected due to a full or nearly full condition, indicating back pressure from the IDI link. The L2Q may also reject transactions from a core to ensure fairness between cores, or to delay a core's dirty eviction when the address conflicts with incoming external snoops. Note that L2 prefetcher requests that are dropped are not counted by this event. Counts on a per core basis.", + "SampleAfterValue": "1000003" + }, + { + "BriefDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x30", + "EventName": "L2_REJECT_XQ.ANY", + "PublicDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition which likely indicates back pressure from the IDI link. The IDI link is a central on-die protocol for memory and coherence traffic between the core and the uncore. It is highly optimized for efficiency, bandwidth, and coherency, using multiple channels and flow control mechanisms to manage high-throughput, low-latency data and protocol communication within the chip. The XQ may reject transactions from the L2Q (non-cacheable requests), BBL (L2 misses) and WOB (L2 write-back victims).", + "SampleAfterValue": "1000003" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door requests for Code Read, Data Read, RFO, ITOM, and L2 Prefetches. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.ALL", + "SampleAfterValue": "1000003", + "UMask": "0x1ff" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Code Read requests. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_CODE_RD", + "SampleAfterValue": "1000003", + "UMask": "0xc4" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Code Read requests that resulted in a hit. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_CODE_RD_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x84" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Code Read requests that resulted in a Miss. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_CODE_RD_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x44" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Data Read requests. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_DATA_RD", + "SampleAfterValue": "1000003", + "UMask": "0xc1" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Data Read requests that resulted in a hit. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_DATA_RD_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x81" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Data Read requests that resulted in a Miss. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_DATA_RD_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x41" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand RFO requests. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_RFO", + "SampleAfterValue": "1000003", + "UMask": "0xc2" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand RFO requests that resulted in a hit. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_RFO_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x82" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand RFO requests that resulted in a Miss. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_RFO_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x42" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door requests that resulted in a Hit. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HIT", + "SampleAfterValue": "1000003", + "UMask": "0x1bf" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Hardware Prefetch requests, including hits and misses. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HWPF", + "SampleAfterValue": "1000003", + "UMask": "0xc8" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Hardware Prefetch requests that result in a hit. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HWPF_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x88" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Hardware Prefetch requests that result in a miss. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HWPF_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x48" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door requests that resulted in a Miss. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.MISS", + "SampleAfterValue": "1000003", + "UMask": "0x17f" + }, { "BriefDescription": "Counts the number of cacheable memory requests that miss in the LLC. Counts on a per core basis.", "Counter": "0,1,2,3,4,5,6,7", @@ -17,6 +153,231 @@ "SampleAfterValue": "1000003", "UMask": "0x4f" }, + { + "BriefDescription": "Counts the number of cycles the core is stalled due to a demand load which hit in the L2 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.L2_HIT", + "PublicDescription": "Counts the number of cycles a core is stalled due to a demand load which hit in the L2 cache.", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which hit in the LLC.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.LLC_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x6" + }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which hit in the LLC, no snoop was required. LLC provided data.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.LLC_HIT_NOSNOOP", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which hit in the LLC, a snoop was required, the snoop misses or the snoop hits but no fwd. LLC provides the data.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.LLC_HIT_SNOOP", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which missed all the caches. DRAM, MMIO or other LOCAL memory type provides the data.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.LLC_MISS_LOCALMEM", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which missed all the caches, a snoop was required, and hits in other core or module on same die. Another core provides the data with a fwd, no fwd, or hitM.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.LLC_MISS_OTHERMOD", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the total number of load ops retired that miss the L3 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.ALL", + "PublicDescription": "Counts the total number of load ops retired that miss the L3 cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0xff" + }, + { + "BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in DRAM", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.LOCAL_DRAM", + "PublicDescription": "Counts the number of load ops retired that miss the L3 cache and hit in DRAM Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote DRAM", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_DRAM_OR_NOFWD", + "PublicDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote DRAM, OR had a Remote snoop miss/no fwd and hit in the Local DRAM. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote Cache and modified data was forwarded", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_FWD_HITM", + "PublicDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote Cache and modified data was forwarded Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote Cache and non-modified data was forwarded", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_FWD_NONM", + "PublicDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote Cache and non-modified data was forwarded Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and modified data was forwarded.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_HITM", + "PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and modified data was forwarded. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and no data was forwarded.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_NO_FWD", + "PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and no data was forwarded. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and non-modified data was forwarded.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_WITH_FWD", + "PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and non-modified data was forwarded. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit the L1 data cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT", + "PublicDescription": "Counts the number of load ops retired that hit the L1 data cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of load ops retired that miss in the L1 data cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS", + "PublicDescription": "Counts the number of load ops retired that miss in the L1 data cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L2 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT", + "PublicDescription": "Counts the number of load ops retired that hit in the L2 cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of load ops retired that miss in the L2 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS", + "PublicDescription": "Counts the number of load ops retired that miss in the L2 cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT", + "PublicDescription": "Counts the number of load ops retired that hit in the L3 cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1c" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which no snoop was required.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT_NO_SNOOP", + "PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which no snoop was required. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and it hit and forwarded data, it hit and did not forward data, or it hit and the forwarded data was modified.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT_SNOOP_HIT", + "PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and it hit and forwarded data, it hit and did not forward data, or it hit and the forwarded data was modified. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of cycles that uops are blocked for any of the following reasons: load buffer, store buffer or RSV full.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x04", + "EventName": "MEM_SCHEDULER_BLOCK.ALL", + "SampleAfterValue": "1000003", + "UMask": "0x7" + }, + { + "BriefDescription": "Counts the number of cycles that uops are blocked due to a load buffer full condition.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x04", + "EventName": "MEM_SCHEDULER_BLOCK.LD_BUF", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of cycles that uops are blocked due to an RSV full condition.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x04", + "EventName": "MEM_SCHEDULER_BLOCK.RSV", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of cycles that uops are blocked due to a store buffer full condition.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x04", + "EventName": "MEM_SCHEDULER_BLOCK.ST_BUF", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.ALL", + "PublicDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST). Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x83" + }, { "BriefDescription": "Counts the number of load ops retired.", "Counter": "0,1,2,3,4,5,6,7", @@ -36,121 +397,213 @@ "UMask": "0x82" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024", "MSRIndex": "0x3F6", "MSRValue": "0x400", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", "MSRIndex": "0x3F6", "MSRValue": "0x80", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 16.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", "MSRIndex": "0x3F6", "MSRValue": "0x10", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 16. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048", "MSRIndex": "0x3F6", "MSRValue": "0x800", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", "MSRIndex": "0x3F6", "MSRValue": "0x100", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 32.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", "MSRIndex": "0x3F6", "MSRValue": "0x20", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 32. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 4.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", "MSRIndex": "0x3F6", "MSRValue": "0x4", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 4. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 512.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", "MSRIndex": "0x3F6", "MSRValue": "0x200", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 512. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 64.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", "MSRIndex": "0x3F6", "MSRValue": "0x40", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 64. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", - "Counter": "0,1", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 8.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", "MSRIndex": "0x3F6", "MSRValue": "0x8", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 8. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5" }, { - "BriefDescription": "Counts the number of stores uops retired same as MEM_UOPS_RETIRED.ALL_STORES", + "BriefDescription": "Counts the number of load uops retired that performed one or more locks", "Counter": "0,1,2,3,4,5,6,7", "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOCK_LOADS", + "PublicDescription": "Counts the number of load uops retired that performed one or more locks Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x21" + }, + { + "BriefDescription": "Counts the number of load uops retired that were correctly predicated by the memory renaming (MRN) feature.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.MRN_LOADS", + "PublicDescription": "Counts the number of load uops retired that were correctly predicated by the memory renaming (MRN) feature. MRN loads are a part of the memory renaming process that optimizes data forwarding between stores and loads, reducing latency and improving performance. This involves tagging stores that forward to loads and copying the physical source (the actual data) directly from the store to the load. The MRN'd load can complete without accessing the memory, thus reducing load-to-use latency. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x9" + }, + { + "BriefDescription": "Counts the number of store uops retired that were correctly tagged by the memory renaming (MRN) feature.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.MRN_STORES", + "PublicDescription": "Counts the number of store uops retired that were correctly tagged by the memory renaming (MRN) feature. MRN stores are a part of the memory renaming process that optimizes data forwarding between stores and loads, reducing latency and improving performance. This involves tagging stores that forward to loads and copying the physical source (the actual data) directly from the store to the load. The MRN store ensures that it's data is accurately forwarded to matching subsequent loads. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0xa" + }, + { + "BriefDescription": "Counts the number of memory uops retired that were splits.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.SPLIT", + "PublicDescription": "Counts the number of memory uops retired that were splits. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x43" + }, + { + "BriefDescription": "Counts the number of retired split load uops.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS", + "PublicDescription": "Counts the number of retired split load uops. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x41" + }, + { + "BriefDescription": "Counts the number of retired split store uops.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.SPLIT_STORES", + "PublicDescription": "Counts the number of retired split store uops. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x42" + }, + { + "BriefDescription": "Counts the number of memory uops retired that missed in the second level TLB.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.STLB_MISS", + "PublicDescription": "Counts the number of memory uops retired that missed in the second level TLB. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x13" + }, + { + "BriefDescription": "Counts the number of load uops retired that miss in the second Level TLB.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS", + "PublicDescription": "Counts the number of load uops retired that miss in the second Level TLB. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x11" + }, + { + "BriefDescription": "Counts the number of store uops retired that miss in the second level TLB.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES", + "PublicDescription": "Counts the number of store uops retired that miss in the second level TLB. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x12" + }, + { + "BriefDescription": "Counts the number of stores uops retired.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.STORE_LATENCY", - "PublicDescription": "Counts the number of stores uops retired same as MEM_UOPS_RETIRED.ALL_STORES Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of stores uops retired. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x6" }, @@ -175,5 +628,13 @@ "PublicDescription": "Counts demand read for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that have any type of response. Available PDIST counters: 0", "SampleAfterValue": "100003", "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to an icache miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.ICACHE", + "SampleAfterValue": "1000003", + "UMask": "0x20" } ] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/counter.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/counter.json index a0eaf5b6f2bc..03c2e5f77204 100644 --- a/tools/perf/pmu-events/arch/x86/clearwaterforest/counter.json +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/counter.json @@ -1,7 +1,82 @@ [ { "Unit": "core", - "CountersNumFixed": "3", - "CountersNumGeneric": "39" + "CountersNumFixed": "7", + "CountersNumGeneric": "8" + }, + { + "Unit": "B2CMI", + "CountersNumFixed": "0", + "CountersNumGeneric": "4" + }, + { + "Unit": "CHA", + "CountersNumFixed": "0", + "CountersNumGeneric": "4" + }, + { + "Unit": "IMC", + "CountersNumFixed": "0", + "CountersNumGeneric": "4" + }, + { + "Unit": "B2HOT", + "CountersNumFixed": "0", + "CountersNumGeneric": 4 + }, + { + "Unit": "IIO", + "CountersNumFixed": "0", + "CountersNumGeneric": "4" + }, + { + "Unit": "IRP", + "CountersNumFixed": "0", + "CountersNumGeneric": "4" + }, + { + "Unit": "UPI", + "CountersNumFixed": "0", + "CountersNumGeneric": "4" + }, + { + "Unit": "B2UPI", + "CountersNumFixed": "0", + "CountersNumGeneric": 4 + }, + { + "Unit": "B2CXL", + "CountersNumFixed": "0", + "CountersNumGeneric": 4 + }, + { + "Unit": "UBOX", + "CountersNumFixed": "0", + "CountersNumGeneric": "2" + }, + { + "Unit": "PCU", + "CountersNumFixed": "0", + "CountersNumGeneric": "4" + }, + { + "Unit": "CHACMS", + "CountersNumFixed": "0", + "CountersNumGeneric": "4" + }, + { + "Unit": "MDF", + "CountersNumFixed": "0", + "CountersNumGeneric": 4 + }, + { + "Unit": "CXLCM", + "CountersNumFixed": "0", + "CountersNumGeneric": 8 + }, + { + "Unit": "CXLDP", + "CountersNumFixed": "0", + "CountersNumGeneric": 4 } ] \ No newline at end of file diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/cwf-metrics.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/cwf-metrics.json new file mode 100644 index 000000000000..bff8841096cd --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/cwf-metrics.json @@ -0,0 +1,310 @@ +[ + { + "BriefDescription": "C1 residency percent per core", + "MetricExpr": "cstate_core@c1\\-residency@ / msr@tsc@", + "MetricGroup": "Power", + "MetricName": "C1_Core_Residency", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "C2 residency percent per package", + "MetricExpr": "cstate_pkg@c2\\-residency@ / msr@tsc@", + "MetricGroup": "Power", + "MetricName": "C2_Pkg_Residency", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "C6 residency percent per core", + "MetricExpr": "cstate_core@c6\\-residency@ / msr@tsc@", + "MetricGroup": "Power", + "MetricName": "C6_Core_Residency", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "C6 residency percent per package", + "MetricExpr": "cstate_pkg@c6\\-residency@ / msr@tsc@", + "MetricGroup": "Power", + "MetricName": "C6_Pkg_Residency", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "Cycles per instruction retired; indicating how much time each executed instruction took; in units of cycles", + "MetricExpr": "CPU_CLK_UNHALTED.THREAD / INST_RETIRED.ANY", + "MetricName": "cpi", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "The average number of cores that are in cstate C0 as observed by the power control unit (PCU)", + "MetricExpr": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C0 / pcu_0@UNC_P_CLOCKTICKS@ * #num_packages", + "MetricName": "cpu_cstate_c0" + }, + { + "BriefDescription": "The average number of cores are in cstate C6 as observed by the power control unit (PCU)", + "MetricExpr": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C6 / pcu_0@UNC_P_CLOCKTICKS@ * #num_packages", + "MetricName": "cpu_cstate_c6" + }, + { + "BriefDescription": "CPU operating frequency (in GHz)", + "MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC * #SYSTEM_TSC_FREQ / 1e9", + "MetricName": "cpu_operating_frequency", + "ScaleUnit": "1GHz" + }, + { + "BriefDescription": "Percentage of time spent in the active CPU power state C0", + "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@", + "MetricName": "cpu_utilization", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "Ratio of number of completed page walks (for all page sizes) caused by demand data loads to the total number of completed instructions", + "MetricExpr": "DTLB_LOAD_MISSES.WALK_COMPLETED / INST_RETIRED.ANY", + "MetricName": "dtlb_2nd_level_load_mpi", + "PublicDescription": "Ratio of number of completed page walks (for all page sizes) caused by demand data loads to the total number of completed instructions. This implies it missed in the DTLB and further levels of TLB", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Ratio of number of completed page walks (for all page sizes) caused by demand data stores to the total number of completed instructions", + "MetricExpr": "DTLB_STORE_MISSES.WALK_COMPLETED / INST_RETIRED.ANY", + "MetricName": "dtlb_2nd_level_store_mpi", + "PublicDescription": "Ratio of number of completed page walks (for all page sizes) caused by demand data stores to the total number of completed instructions. This implies it missed in the DTLB and further levels of TLB", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Bandwidth observed by the integrated I/O traffic controller (IIO) of IO reads that are initiated by end device controllers that are requesting memory from the CPU", + "MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.ALL_PARTS * 4 / 1e6 / duration_time", + "MetricName": "iio_bandwidth_read", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth observed by the integrated I/O traffic controller (IIO) of IO writes that are initiated by end device controllers that are writing memory to the CPU", + "MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.ALL_PARTS * 4 / 1e6 / duration_time", + "MetricName": "iio_bandwidth_write", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth of IO reads that are initiated by end device controllers that are requesting memory from the CPU", + "MetricExpr": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR * 64 / 1e6 / duration_time", + "MetricName": "io_bandwidth_read", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth of inbound IO reads that are initiated by end device controllers that are requesting memory from the CPU and miss the L3 cache", + "MetricExpr": "UNC_CHA_TOR_INSERTS.IO_MISS_PCIRDCUR * 64 / 1e6 / duration_time", + "MetricName": "io_bandwidth_read_l3_miss", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth of IO reads that are initiated by end device controllers that are requesting memory from the local CPU socket", + "MetricExpr": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR_LOCAL * 64 / 1e6 / duration_time", + "MetricName": "io_bandwidth_read_local", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth of IO reads that are initiated by end device controllers that are requesting memory from a remote CPU socket", + "MetricExpr": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR_REMOTE * 64 / 1e6 / duration_time", + "MetricName": "io_bandwidth_read_remote", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth of IO writes that are initiated by end device controllers that are writing memory to the CPU", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_ITOM + UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR) * 64 / 1e6 / duration_time", + "MetricName": "io_bandwidth_write", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth of inbound IO writes that are initiated by end device controllers that are writing memory to the CPU", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_MISS_ITOM + UNC_CHA_TOR_INSERTS.IO_MISS_ITOMCACHENEAR) * 64 / 1e6 / duration_time", + "MetricName": "io_bandwidth_write_l3_miss", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth of IO writes that are initiated by end device controllers that are writing memory to the local CPU socket", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_ITOM_LOCAL + UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR_LOCAL) * 64 / 1e6 / duration_time", + "MetricName": "io_bandwidth_write_local", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth of IO writes that are initiated by end device controllers that are writing memory to a remote CPU socket", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_ITOM_REMOTE + UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR_REMOTE) * 64 / 1e6 / duration_time", + "MetricName": "io_bandwidth_write_remote", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "The percent of inbound full cache line writes initiated by IO that miss the L3 cache", + "MetricExpr": "UNC_CHA_TOR_INSERTS.IO_MISS_ITOM / UNC_CHA_TOR_INSERTS.IO_ITOM", + "MetricName": "io_full_write_l3_miss", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "The number of times per second that ownership of a cacheline was stolen from the integrated IO controller before it was able to write back the modified line", + "MetricExpr": "(UNC_I_MISC1.LOST_FWD + UNC_I_MISC1.SEC_RCVD_INVLD) / duration_time", + "MetricName": "io_lost_fwd", + "ScaleUnit": "1per_sec" + }, + { + "BriefDescription": "Message Signaled Interrupts (MSI) per second sent by the integrated I/O traffic controller (IIO) to System Configuration Controller (Ubox)", + "MetricExpr": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.UBOX_POSTED / duration_time", + "MetricName": "io_msi", + "ScaleUnit": "1per_sec" + }, + { + "BriefDescription": "", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR + UNC_CHA_TOR_INSERTS.IO_RFO) / duration_time", + "MetricName": "io_number_of_partial_pci_writes", + "ScaleUnit": "1per_sec" + }, + { + "BriefDescription": "The percent of inbound partial writes initiated by IO that miss the L3 cache", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_MISS_ITOMCACHENEAR + UNC_CHA_TOR_INSERTS.IO_MISS_RFO) / (UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR + UNC_CHA_TOR_INSERTS.IO_RFO)", + "MetricName": "io_partial_write_l3_miss", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "The percent of inbound reads initiated by IO that miss the L3 cache", + "MetricExpr": "UNC_CHA_TOR_INSERTS.IO_MISS_PCIRDCUR / UNC_CHA_TOR_INSERTS.IO_PCIRDCUR", + "MetricName": "io_read_l3_miss", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "Ratio of number of completed page walks (for all page sizes) caused by a code fetch to the total number of completed instructions", + "MetricExpr": "ITLB_MISSES.WALK_COMPLETED / INST_RETIRED.ANY", + "MetricName": "itlb_2nd_level_mpi", + "PublicDescription": "Ratio of number of completed page walks (for all page sizes) caused by a code fetch to the total number of completed instructions. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Ratio of number of code read requests missing in L1 instruction cache (includes prefetches) to the total number of completed instructions", + "MetricExpr": "ICACHE.MISSES / INST_RETIRED.ANY", + "MetricName": "l1_i_code_read_misses_with_prefetches_per_instr", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Ratio of number of demand load requests hitting in L1 data cache to the total number of completed instructions", + "MetricExpr": "MEM_LOAD_UOPS_RETIRED.L1_HIT / INST_RETIRED.ANY", + "MetricName": "l1d_demand_data_read_hits_per_instr", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Ratio of number of completed demand load requests hitting in L2 cache to the total number of completed instructions", + "MetricExpr": "MEM_LOAD_UOPS_RETIRED.L2_HIT / INST_RETIRED.ANY", + "MetricName": "l2_demand_data_read_hits_per_instr", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Ratio of number of completed data read request missing L2 cache to the total number of completed instructions", + "MetricExpr": "MEM_LOAD_UOPS_RETIRED.L2_MISS / INST_RETIRED.ANY", + "MetricName": "l2_demand_data_read_mpi", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Ratio of number of code read requests missing last level core cache (includes demand w/ prefetches) to the total number of completed instructions", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IA_MISS_CRD + UNC_CHA_TOR_INSERTS.IA_MISS_CRD_PREF) / INST_RETIRED.ANY", + "MetricName": "llc_code_read_mpi_demand_plus_prefetch", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Ratio of number of data read requests missing last level core cache (includes demand w/ prefetches) to the total number of completed instructions", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF + UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFDATA) / INST_RETIRED.ANY", + "MetricName": "llc_data_read_mpi_demand_plus_prefetch", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Average latency of a last level cache (LLC) demand data read miss (read memory access) in nano seconds", + "MetricExpr": "1e9 * (UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT / UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT) / (UNC_CHA_CLOCKTICKS / (source_count(UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT) * #num_packages)) * duration_time", + "MetricName": "llc_demand_data_read_miss_latency", + "ScaleUnit": "1ns" + }, + { + "BriefDescription": "Bandwidth (MB/sec) of read requests that miss the last level cache (LLC) and go to local memory", + "MetricExpr": "UNC_CHA_REQUESTS.READS_LOCAL * 64 / 1e6 / duration_time", + "MetricName": "llc_miss_local_memory_bandwidth_read", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth (MB/sec) of write requests that miss the last level cache (LLC) and go to local memory", + "MetricExpr": "UNC_CHA_REQUESTS.WRITES_LOCAL * 64 / 1e6 / duration_time", + "MetricName": "llc_miss_local_memory_bandwidth_write", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth (MB/sec) of read requests that miss the last level cache (LLC) and go to remote memory", + "MetricExpr": "UNC_CHA_REQUESTS.READS_REMOTE * 64 / 1e6 / duration_time", + "MetricName": "llc_miss_remote_memory_bandwidth_read", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Bandwidth (MB/sec) of write requests that miss the last level cache (LLC) and go to remote memory", + "MetricExpr": "UNC_CHA_REQUESTS.WRITES_REMOTE * 64 / 1e6 / duration_time", + "MetricName": "llc_miss_remote_memory_bandwidth_write", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "", + "MetricExpr": "MEM_UOPS_RETIRED.ALL_LOADS / INST_RETIRED.ANY", + "MetricName": "loads_retired_per_instr", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "DDR memory read bandwidth (MB/sec)", + "MetricExpr": "(UNC_M_CAS_COUNT_SCH0.RD + UNC_M_CAS_COUNT_SCH1.RD) * 64 / 1e6 / duration_time", + "MetricName": "memory_bandwidth_read", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "DDR memory bandwidth (MB/sec)", + "MetricExpr": "(UNC_M_CAS_COUNT_SCH0.RD + UNC_M_CAS_COUNT_SCH1.RD + UNC_M_CAS_COUNT_SCH0.WR + UNC_M_CAS_COUNT_SCH1.WR) * 64 / 1e6 / duration_time", + "MetricName": "memory_bandwidth_total", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "DDR memory write bandwidth (MB/sec)", + "MetricExpr": "(UNC_M_CAS_COUNT_SCH0.WR + UNC_M_CAS_COUNT_SCH1.WR) * 64 / 1e6 / duration_time", + "MetricName": "memory_bandwidth_write", + "ScaleUnit": "1MB/s" + }, + { + "BriefDescription": "Memory read that miss the last level cache (LLC) addressed to local DRAM as a percentage of total memory read accesses, does not include LLC prefetches", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_LOCAL) / (UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_REMOTE + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_REMOTE)", + "MetricName": "numa_reads_addressed_to_local_dram", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "Memory reads that miss the last level cache (LLC) addressed to remote DRAM as a percentage of total memory read accesses, does not include LLC prefetches", + "MetricExpr": "(UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_REMOTE + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_REMOTE) / (UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_REMOTE + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_REMOTE)", + "MetricName": "numa_reads_addressed_to_remote_dram", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "Percentage of cycles spent in System Management Interrupts.", + "MetricExpr": "((msr@aperf@ - cycles) / msr@aperf@ if msr@smi@ > 0 else 0)", + "MetricGroup": "smi", + "MetricName": "smi_cycles", + "MetricThreshold": "smi_cycles > 0.1", + "ScaleUnit": "100%" + }, + { + "BriefDescription": "Number of SMI interrupts.", + "MetricExpr": "msr@smi@", + "MetricGroup": "smi", + "MetricName": "smi_num", + "ScaleUnit": "1SMI#" + }, + { + "BriefDescription": "", + "MetricExpr": "MEM_UOPS_RETIRED.ALL_STORES / INST_RETIRED.ANY", + "MetricName": "stores_retired_per_instr", + "ScaleUnit": "1per_instr" + }, + { + "BriefDescription": "Uncore operating frequency in GHz", + "MetricExpr": "UNC_CHA_CLOCKTICKS / (source_count(UNC_CHA_CLOCKTICKS) * #num_packages) / 1e9 / duration_time", + "MetricName": "uncore_frequency", + "ScaleUnit": "1GHz" + }, + { + "BriefDescription": "Intel(R) Ultra Path Interconnect (UPI) data transmit bandwidth (MB/sec)", + "MetricExpr": "UNC_UPI_TxL_FLITS.ALL_DATA * 7.111111111111111 / 1e6 / duration_time", + "MetricName": "upi_data_transmit_bw", + "ScaleUnit": "1MB/s" + } +] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/floating-point.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/floating-point.json new file mode 100644 index 000000000000..34d7a50d2fd8 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/floating-point.json @@ -0,0 +1,191 @@ +[ + { + "BriefDescription": "Counts the number of cycles when any of the floating point dividers are active.", + "Counter": "0,1,2,3,4,5,6,7", + "CounterMask": "1", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of floating point dividers per cycle in the loop stage.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_OCCUPANCY", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of floating point divider uops executed per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_UOPS", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of all types of floating point operations per uop with all default weighting", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc8", + "EventName": "FP_FLOPS_RETIRED.ALL", + "PublicDescription": "Counts the number of all types of floating point operations per uop with all default weighting Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x3" + }, + { + "BriefDescription": "Counts the number of floating point operations that produce 32 bit single precision results", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc8", + "EventName": "FP_FLOPS_RETIRED.FP32", + "PublicDescription": "Counts the number of floating point operations that produce 32 bit single precision results Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of floating point operations that produce 64 bit double precision results", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc8", + "EventName": "FP_FLOPS_RETIRED.FP64", + "PublicDescription": "Counts the number of floating point operations that produce 64 bit double precision results Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of retired instructions whose sources are a packed 128 bit double precision floating point. This may be SSE or AVX.128 operations.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc7", + "EventName": "FP_INST_RETIRED.128B_DP", + "PublicDescription": "Counts the number of retired instructions whose sources are a packed 128 bit double precision floating point. This may be SSE or AVX.128 operations. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of retired instructions whose sources are a packed 128 bit single precision floating point. This may be SSE or AVX.128 operations.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc7", + "EventName": "FP_INST_RETIRED.128B_SP", + "PublicDescription": "Counts the number of retired instructions whose sources are a packed 128 bit single precision floating point. This may be SSE or AVX.128 operations. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of retired instructions whose sources are a packed 256 bit double precision floating point.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc7", + "EventName": "FP_INST_RETIRED.256B_DP", + "PublicDescription": "Counts the number of retired instructions whose sources are a packed 256 bit double precision floating point. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of retired instructions whose sources are a packed 256 bit single precision floating point.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc7", + "EventName": "FP_INST_RETIRED.256B_SP", + "PublicDescription": "Counts the number of retired instructions whose sources are a packed 256 bit single precision floating point. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of retired instructions whose sources are a scalar 32bit single precision floating point.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc7", + "EventName": "FP_INST_RETIRED.32B_SP", + "PublicDescription": "Counts the number of retired instructions whose sources are a scalar 32bit single precision floating point. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of retired instructions whose sources are a scalar 64 bit double precision floating point.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc7", + "EventName": "FP_INST_RETIRED.64B_DP", + "PublicDescription": "Counts the number of retired instructions whose sources are a scalar 64 bit double precision floating point. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the total number of floating point retired instructions.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc7", + "EventName": "FP_INST_RETIRED.ALL", + "PublicDescription": "Counts the total number of floating point retired instructions. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x3f" + }, + { + "BriefDescription": "Counts the number of uops executed on all floating point ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0x1f" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P3", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0, 1, 2, 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.PRIMARY", + "SampleAfterValue": "1000003", + "UMask": "0x1e" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer store data port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.STD", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of floating point operations retired that required microcode assist.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FP_ASSIST", + "PublicDescription": "Counts the number of floating point operations retired that required microcode assist, which is not a reflection of the number of FP operations, instructions or uops.", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of floating point divide uops retired (x87 and sse, including x87 sqrt).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.FPDIV", + "PublicDescription": "Counts the number of floating point divide uops retired (x87 and sse, including x87 sqrt). Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x40" + } +] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/frontend.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/frontend.json index 7a9250e5c8f2..b71d6ae1abe8 100644 --- a/tools/perf/pmu-events/arch/x86/clearwaterforest/frontend.json +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/frontend.json @@ -1,4 +1,206 @@ [ + { + "BriefDescription": "Counts the total number of BACLEARS due to all branch types including conditional and unconditional jumps, returns, and indirect branches.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe6", + "EventName": "BACLEARS.ANY", + "PublicDescription": "Counts the total number of BACLEARS, which occur when the Branch Target Buffer (BTB) prediction or lack thereof, was corrected by a later branch predictor in the frontend. Includes BACLEARS due to all branch types including conditional and unconditional jumps, returns, and indirect branches.", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of BACLEARS due to a conditional jump.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe6", + "EventName": "BACLEARS.COND", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of BACLEARS due to an indirect branch.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe6", + "EventName": "BACLEARS.INDIRECT", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of BACLEARS due to a return branch.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe6", + "EventName": "BACLEARS.RETURN", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of BACLEARS due to a direct, unconditional jump.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe6", + "EventName": "BACLEARS.UNCOND", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged with having preceded with frontend bound behavior", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.ALL", + "PublicDescription": "Counts the number of instructions retired that were tagged with having preceded with frontend bound behavior Available PDIST counters: 0,1", + "SampleAfterValue": "1000003" + }, + { + "BriefDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a baclear", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.BRANCH_DETECT", + "PublicDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a baclear Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles /empty issue slots due to a btclear", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.BRANCH_RESTEER", + "PublicDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles /empty issue slots due to a btclear Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged following an ms flow due to the bubble/wasted issue slot from exiting long ms flow", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.CISC", + "PublicDescription": "Counts the number of instructions retired that were tagged following an ms flow due to the bubble/wasted issue slot from exiting long ms flow Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged every cycle the decoder is unable to send 3 uops per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.DECODE", + "PublicDescription": "Counts the number of instructions retired that were tagged every cycle the decoder is unable to send 3 uops per cycle. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to icache miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.ICACHE", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to icache miss Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.ITLB_MISS", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of instruction retired tagged after a wasted issue slot if none of the previous events occurred", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.OTHER", + "PublicDescription": "Counts the number of instruction retired tagged after a wasted issue slot if none of the previous events occurred Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a predecode wrong.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.PREDECODE", + "PublicDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a predecode wrong. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L2 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L2_HIT", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L2 cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L2_MISS", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0xe" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_HIT", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x6" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and did not have to snoop another core.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_HIT_NO_SNOOP", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and did not have to snoop another core. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and required a snoop (that resulted in a snoop miss, snoop hitm, snoop hit with fwd, or snoop hit with no fwd).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_HIT_WITH_SNOOP", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and required a snoop (that resulted in a snoop miss, snoop hitm, snoop hit with fwd, or snoop hit with no fwd). Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 and L3 caches.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_MISS", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 and L3 caches. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss that hit in the second level TLB.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ITLB_STLB_HIT", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss that hit in the second level TLB. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss that also missed the second level TLB.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ITLB_STLB_MISS", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss that also missed the second level TLB. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of instructions retired that were preceded by empty issue slots at allocation due to an Instruction L1 cache miss, that matched a current outstanding prefetch request initiated by a Code SWPF stream.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.LATE_SWPF", + "PublicDescription": "Counts the number of instructions retired that were preceded by empty issue slots at allocation due to an Instruction L1 cache miss, that matched a current outstanding prefetch request initiated by a Code SWPF stream. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, { "BriefDescription": "Counts every time the code stream enters into a new cache line by walking sequential from the previous line or being redirected by a jump.", "Counter": "0,1,2,3,4,5,6,7", @@ -7,6 +209,14 @@ "SampleAfterValue": "1000003", "UMask": "0x3" }, + { + "BriefDescription": "Counts every time the code stream enters into a new cache line by walking sequential from the previous line or being redirected by a jump and the instruction cache registers bytes are present.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x80", + "EventName": "ICACHE.HIT", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, { "BriefDescription": "Counts every time the code stream enters into a new cache line by walking sequential from the previous line or being redirected by a jump and the instruction cache registers bytes are not present. -", "Counter": "0,1,2,3,4,5,6,7", @@ -14,5 +224,21 @@ "EventName": "ICACHE.MISSES", "SampleAfterValue": "1000003", "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of cycles that the micro-sequencer is busy.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe7", + "EventName": "MS_DECODED.MS_BUSY", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of times entered into a ucode flow in the FEC. Includes inserted flows due to front-end detected faults or assists.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe7", + "EventName": "MS_DECODED.MS_ENTRY", + "SampleAfterValue": "1000003", + "UMask": "0x1" } ] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/memory.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/memory.json index 58e543550279..ae9095a090e5 100644 --- a/tools/perf/pmu-events/arch/x86/clearwaterforest/memory.json +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/memory.json @@ -1,4 +1,96 @@ [ + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a core bound stall including a store address match, a DTLB miss or a page walk that detains the load from retiring.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.L1_BOUND_AT_RET", + "SampleAfterValue": "1000003", + "UMask": "0xf4" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DL1 miss.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.L1_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DL1 miss.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.L1_MISS_AT_RET", + "SampleAfterValue": "1000003", + "UMask": "0x81" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.OTHER", + "PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases such as pipeline conflicts, fences, etc.", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.OTHER_AT_RET", + "PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases such as pipeline conflicts, fences, etc.", + "SampleAfterValue": "1000003", + "UMask": "0xc0" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL_AT_RET", + "SampleAfterValue": "1000003", + "UMask": "0x82" + }, + { + "BriefDescription": "Counts the number of machine clears due to memory ordering caused by a snoop from an external agent. Does not count internally generated machine clears such as those due to memory disambiguation.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MEMORY_ORDERING", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MEMORY_ORDERING_FAST", + "SampleAfterValue": "1000003", + "UMask": "0x8002" + }, + { + "BriefDescription": "Counts misaligned loads that are 4K page splits.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x13", + "EventName": "MISALIGN_MEM_REF.LOAD_PAGE_SPLIT", + "PublicDescription": "Counts misaligned loads that are 4K page splits. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts misaligned stores that are 4K page splits.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x13", + "EventName": "MISALIGN_MEM_REF.STORE_PAGE_SPLIT", + "PublicDescription": "Counts misaligned stores that are 4K page splits. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, { "BriefDescription": "Counts demand data reads that were not supplied by the L3 cache.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/other.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/other.json new file mode 100644 index 000000000000..2c8721903610 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/other.json @@ -0,0 +1,20 @@ +[ + { + "BriefDescription": "Counts the number of LBR entries recorded. Requires LBRs to be enabled in IA32_LBR_CTL. [This event is alias to MISC_RETIRED.LBR_INSERTS]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe4", + "EventName": "LBR_INSERTS.ANY", + "PublicDescription": "Counts the number of LBR entries recorded. Requires LBRs to be enabled in IA32_LBR_CTL. [This event is alias to MISC_RETIRED.LBR_INSERTS] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the total number of BTCLEARS.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe8", + "EventName": "PREDICTION.BTCLEAR", + "PublicDescription": "Counts the total number of BTCLEARS which occurs when the Branch Target Buffer (BTB) predicts a taken branch.", + "SampleAfterValue": "1000003", + "UMask": "0x1" + } +] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/pipeline.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/pipeline.json index 26bd12fefa3d..3d10dcffb8fc 100644 --- a/tools/perf/pmu-events/arch/x86/clearwaterforest/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/pipeline.json @@ -1,4 +1,38 @@ [ + { + "BriefDescription": "Counts the number of cycles when any of the floating point or integer dividers are active.", + "Counter": "0,1,2,3,4,5,6,7", + "CounterMask": "1", + "EventCode": "0xcd", + "EventName": "ARITH.DIV_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x3" + }, + { + "BriefDescription": "Counts the number of cycles when any of the integer dividers are active.", + "Counter": "0,1,2,3,4,5,6,7", + "CounterMask": "1", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts number of active integer dividers per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_OCCUPANCY", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of integer divider uops executed per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_UOPS", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, { "BriefDescription": "Counts the total number of branch instructions retired for all branch types.", "Counter": "0,1,2,3,4,5,6,7", @@ -7,6 +41,211 @@ "PublicDescription": "Counts the total number of instructions in which the instruction pointer (IP) of the processor is resteered due to a branch instruction and the branch instruction successfully retires. All branch type instructions are accounted for. Available PDIST counters: 0,1", "SampleAfterValue": "1000003" }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.ALL_NEAR_IND", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x50" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_OR_RETURN]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.ALL_NEAR_IND_OR_RET", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_OR_RETURN] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x58" + }, + { + "BriefDescription": "Counts the number of conditional branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.COND", + "PublicDescription": "Counts the number of conditional branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x7" + }, + { + "BriefDescription": "Counts the number of not taken conditional branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.COND_NTAKEN", + "PublicDescription": "Counts the number of not taken conditional branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of taken conditional branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.COND_TAKEN", + "PublicDescription": "Counts the number of taken conditional branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x3" + }, + { + "BriefDescription": "Counts the number of taken backward conditional branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.COND_TAKEN_BWD", + "PublicDescription": "Counts the number of taken backward conditional branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of taken forward conditional branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.COND_TAKEN_FWD", + "PublicDescription": "Counts the number of taken forward conditional branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of near CALL branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_CALL", + "PublicDescription": "Counts the number of near CALL branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x30" + }, + { + "BriefDescription": "Counts the number of near direct CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_DIR_CALL]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_DIRECT_CALL", + "PublicDescription": "Counts the number of near direct CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_DIR_CALL] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of near direct JMP branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_DIR_JMP]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_DIRECT_JMP", + "PublicDescription": "Counts the number of near direct JMP branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_DIR_JMP] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_DIRECT_CALL]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_DIR_CALL", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_DIRECT_CALL] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_DIRECT_JMP]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_DIR_JMP", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_DIRECT_JMP] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Counts the number of near indirect JMP and near indirect CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.ALL_NEAR_IND]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_INDIRECT", + "PublicDescription": "Counts the number of near indirect JMP and near indirect CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.ALL_NEAR_IND] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x50" + }, + { + "BriefDescription": "Counts the number of near indirect CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_CALL]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_INDIRECT_CALL", + "PublicDescription": "Counts the number of near indirect CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_CALL] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of near indirect JMP branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_JMP]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_INDIRECT_JMP", + "PublicDescription": "Counts the number of near indirect JMP branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_JMP] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of near indirect JMP, near indirect CALL, and RET branch instructions retired. [This event is alias to BR_INST_RETIRED.ALL_NEAR_IND_OR_RET]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_INDIRECT_OR_RETURN", + "PublicDescription": "Counts the number of near indirect JMP, near indirect CALL, and RET branch instructions retired. [This event is alias to BR_INST_RETIRED.ALL_NEAR_IND_OR_RET] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x58" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_CALL]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_IND_CALL", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_CALL] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_JMP]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_IND_JMP", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_JMP] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of near JMP branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_JMP", + "PublicDescription": "Counts the number of near JMP branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0xc0" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_RETURN]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_RET", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_RETURN] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of near RET branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_RET]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_RETURN", + "PublicDescription": "Counts the number of near RET branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_RET] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of near taken branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_TAKEN", + "PublicDescription": "Counts the number of near taken branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0xfb" + }, { "BriefDescription": "Counts the total number of mispredicted branch instructions retired for all branch types.", "Counter": "0,1,2,3,4,5,6,7", @@ -16,10 +255,47 @@ "SampleAfterValue": "1000003" }, { - "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles.", + "BriefDescription": "This event is deprecated. [This event is alias to BR_MISP_RETIRED.NEAR_INDIRECT]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.ALL_NEAR_IND", + "PublicDescription": "This event is deprecated. [This event is alias to BR_MISP_RETIRED.NEAR_INDIRECT] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x50" + }, + { + "BriefDescription": "Counts the number of mispredicted not taken conditional branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.COND_NTAKEN", + "PublicDescription": "Counts the number of mispredicted not taken conditional branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of mispredicted taken conditional branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.COND_TAKEN", + "PublicDescription": "Counts the number of mispredicted taken conditional branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x3" + }, + { + "BriefDescription": "Counts the number of mispredicted near indirect JMP and near indirect CALL branch instructions retired. [This event is alias to BR_MISP_RETIRED.ALL_NEAR_IND]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.NEAR_INDIRECT", + "PublicDescription": "Counts the number of mispredicted near indirect JMP and near indirect CALL branch instructions retired. [This event is alias to BR_MISP_RETIRED.ALL_NEAR_IND] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x50" + }, + { + "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles. [This event is alias to CPU_CLK_UNHALTED.THREAD]", "Counter": "Fixed counter 1", "EventName": "CPU_CLK_UNHALTED.CORE", - "SampleAfterValue": "1000003", + "SampleAfterValue": "2000003", "UMask": "0x2" }, { @@ -27,13 +303,13 @@ "Counter": "0,1,2,3,4,5,6,7", "EventCode": "0x3c", "EventName": "CPU_CLK_UNHALTED.CORE_P", - "SampleAfterValue": "1000003" + "SampleAfterValue": "2000003" }, { "BriefDescription": "Fixed Counter: Counts the number of unhalted reference clock cycles.", "Counter": "Fixed counter 2", "EventName": "CPU_CLK_UNHALTED.REF_TSC", - "SampleAfterValue": "1000003", + "SampleAfterValue": "2000003", "UMask": "0x3" }, { @@ -42,14 +318,14 @@ "EventCode": "0x3c", "EventName": "CPU_CLK_UNHALTED.REF_TSC_P", "PublicDescription": "Counts the number of reference cycles that the core is not in a halt state. The core enters the halt state when it is running the HLT instruction. This event is not affected by core frequency changes and increments at a fixed frequency that is also used for the Time Stamp Counter (TSC). This event uses a programmable general purpose performance counter.", - "SampleAfterValue": "1000003", + "SampleAfterValue": "2000003", "UMask": "0x1" }, { - "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles.", + "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles. [This event is alias to CPU_CLK_UNHALTED.CORE]", "Counter": "Fixed counter 1", "EventName": "CPU_CLK_UNHALTED.THREAD", - "SampleAfterValue": "1000003", + "SampleAfterValue": "2000003", "UMask": "0x2" }, { @@ -57,14 +333,14 @@ "Counter": "0,1,2,3,4,5,6,7", "EventCode": "0x3c", "EventName": "CPU_CLK_UNHALTED.THREAD_P", - "SampleAfterValue": "1000003" + "SampleAfterValue": "2000003" }, { "BriefDescription": "Fixed Counter: Counts the number of instructions retired.", "Counter": "Fixed counter 0", "EventName": "INST_RETIRED.ANY", "PublicDescription": "Fixed Counter: Counts the number of instructions retired. Available PDIST counters: 32", - "SampleAfterValue": "1000003", + "SampleAfterValue": "2000003", "UMask": "0x1" }, { @@ -73,15 +349,339 @@ "EventCode": "0xc0", "EventName": "INST_RETIRED.ANY_P", "PublicDescription": "Counts the number of instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "2000003" + }, + { + "BriefDescription": "Counts the number of uops executed on secondary integer ports 0,1,2,3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.2ND", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Counts the number of uops executed on all Integer ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0xff" + }, + { + "BriefDescription": "Counts the number of uops executed on a load port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.LD", + "PublicDescription": "Counts the number of uops executed on a load port. This event counts for integer uops even if the destination is FP/vector", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P3", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 0,1, 2, 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.PRIMARY", + "SampleAfterValue": "1000003", + "UMask": "0x78" + }, + { + "BriefDescription": "Counts the number of uops executed on a Store address port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.STA", + "PublicDescription": "Counts the number of uops executed on a Store address port. This event counts integer uops even if the data source is FP/vector", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of uops executed on an integer store data and jump port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.STD_JMP", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of retired loads that are blocked because it initially appears to be store forward blocked, but subsequently is shown not to be blocked based on 4K alias check.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.ADDRESS_ALIAS", + "PublicDescription": "Counts the number of retired loads that are blocked because it initially appears to be store forward blocked, but subsequently is shown not to be blocked based on 4K alias check. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of retired loads that are blocked for any of the following reasons: DTLB miss, address alias, store forward or data unknown (includes memory disambiguation blocks and ESP consuming load blocks) and others.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.ALL", + "PublicDescription": "Counts the number of retired loads that are blocked for any of the following reasons: DTLB miss, address alias, store forward or data unknown (includes memory disambiguation blocks and ESP consuming load blocks) and others. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1f" + }, + { + "BriefDescription": "Counts the number of retired loads that are blocked because its address exactly matches an older store whose data is not ready.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.DATA_UNKNOWN", + "PublicDescription": "Counts the number of retired loads that are blocked because its address exactly matches an older store whose data is not ready. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of retired loads that are blocked because its address partially overlapped with an older store.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.STORE_FORWARD", + "PublicDescription": "Counts the number of retired loads that are blocked because its address partially overlapped with an older store. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the total number of machine clears for any reason including, but not limited to, memory ordering, memory disambiguation, SMC, and FP assist.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.ANY", "SampleAfterValue": "1000003" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.ANY_FAST", + "SampleAfterValue": "1000003", + "UMask": "0x80ff" + }, + { + "BriefDescription": "Counts the number of machine clears due to memory ordering in which an internal load passes an older store within the same CPU.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.DISAMBIGUATION", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.DISAMBIGUATION_FAST", + "SampleAfterValue": "1000003", + "UMask": "0x8008" + }, + { + "BriefDescription": "Counts the number of virtual traps taken.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of machine clears due to memory renaming.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MRN_NUKE", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MRN_NUKE_FAST", + "SampleAfterValue": "1000003", + "UMask": "0x8010" + }, + { + "BriefDescription": "Counts the number of machine clears due to a page fault. Counts both I-Side and D-Side (Loads/Stores) page faults. A page fault occurs when either the page is not present, or an access violation occurs.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.PAGE_FAULT", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of machine clears due to program modifying data (self modifying code) within 1K of a recently fetched code page.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.SMC", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of machine clears due to program modifying data (cross-core modifying code) within 1K of a recently fetched code page.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.XMC", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to LBR_INSERTS.ANY]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xe4", + "EventName": "MISC_RETIRED.LBR_INSERTS", + "PublicDescription": "This event is deprecated. [This event is alias to LBR_INSERTS.ANY] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of CLFLUSH, CLWB, and CLDEMOTE instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe0", + "EventName": "MISC_RETIRED1.CL_INST", + "PublicDescription": "Counts the number of CLFLUSH, CLWB, and CLDEMOTE instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0xff" + }, + { + "BriefDescription": "Counts the number of LFENCE instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe0", + "EventName": "MISC_RETIRED1.LFENCE", + "PublicDescription": "Counts the number of LFENCE instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of accesses to KeyLocker cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe1", + "EventName": "MISC_RETIRED2.KEYLOCKER_ACCESS", + "PublicDescription": "Counts the number of accesses to KeyLocker cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of misses to KeyLocker cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe1", + "EventName": "MISC_RETIRED2.KEYLOCKER_MISS", + "PublicDescription": "Counts the number of misses to KeyLocker cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x11" + }, + { + "BriefDescription": "Counts the number of issue slots in a UMWAIT or TPAUSE instruction where no uop issues due to the instruction putting the CPU into the C0.1 activity state. For Tremont, UMWAIT and TPAUSE will only put the CPU into C0.1 activity state (not C0.2 activity state).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.C01_MS_SCB", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of issue slots not consumed due to a color request for an FCW or MXCSR control register when all 4 colors (copies) are already in use.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.COLOR_STALLS", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of issue slots where no uop could issue due to an IQ scoreboard that stalls allocation until a specified older uop retires or (in the case of jump scoreboard) executes. Commonly executed instructions with IQ scoreboards include LFENCE and MFENCE.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.IQ_JEU_SCB", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.NON_C01_MS_SCB", + "PublicDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires. The most commonly executed instruction with an MS scoreboard is PAUSE.", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, { "BriefDescription": "Fixed Counter: Counts the number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear.", - "Counter": "36", + "Counter": "Fixed counter 4", "EventName": "TOPDOWN_BAD_SPECULATION.ALL", "SampleAfterValue": "1000003", "UMask": "0x5" }, + { + "BriefDescription": "Counts the number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.ALL_P", + "PublicDescription": "Counts the total number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear. Only issue slots wasted due to fast nukes such as memory ordering nukes are counted. Other nukes are not accounted for. Counts all issue slots blocked during this recovery window, including relevant microcode flows, and while uops are not yet available in the instruction queue (IQ) or until an FE_BOUND event occurs besides OTHER and CISC. Also includes the issue slots that were consumed by the backend but were thrown away because they were younger than the mispredict or machine clear.", + "SampleAfterValue": "1000003" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to Fast Nukes such as Memory Ordering Machine clears and MRN nukes", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.FASTNUKE", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to a branch mispredict that resulted in LSD exit.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.LSD_MISPREDICT", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the total number of issue slots that were not consumed by the backend because allocation is stalled due to a machine clear (nuke) of any kind including memory ordering and memory disambiguation.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.MACHINE_CLEARS", + "SampleAfterValue": "1000003", + "UMask": "0x3" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to Branch Mispredict", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.MISPREDICT", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to a machine clear (nuke).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.NUKE", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, { "BriefDescription": "Counts the number of retirement slots not consumed due to backend stalls. [This event is alias to TOPDOWN_BE_BOUND.ALL_P]", "Counter": "0,1,2,3,4,5,6,7", @@ -90,6 +690,14 @@ "SampleAfterValue": "1000003", "UMask": "0x2" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to due to certain allocation restrictions.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.ALLOC_RESTRICTIONS", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, { "BriefDescription": "Counts the number of retirement slots not consumed due to backend stalls. [This event is alias to TOPDOWN_BE_BOUND.ALL]", "Counter": "0,1,2,3,4,5,6,7", @@ -98,18 +706,215 @@ "SampleAfterValue": "1000003", "UMask": "0x2" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to LSD entry.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.LSD", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to memory reservation stall (scheduler not being able to accept another uop). This could be caused by RSV full or load/store buffer block.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.MEM_SCHEDULER", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to IEC and FPC RAT stalls - which can be due to the FIQ and IEC reservation station stall (integer, FP and SIMD scheduler not being able to accept another uop).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.NON_MEM_SCHEDULER", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to mrbl stall. A marble refers to a physical register file entry, also known as the physical destination (PDST).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.REGISTER", + "PublicDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to mrbl stall. A 'marble' refers to a physical register file entry, also known as the physical destination (PDST).", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to ROB full", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.REORDER_BUFFER", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to iq/jeu scoreboards or ms scb", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.SERIALIZATION", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, { "BriefDescription": "Fixed Counter: Counts the number of retirement slots not consumed due to front end stalls.", - "Counter": "37", + "Counter": "Fixed counter 5", "EventName": "TOPDOWN_FE_BOUND.ALL", "SampleAfterValue": "1000003", "UMask": "0x6" }, + { + "BriefDescription": "Counts the number of retirement slots not consumed due to front end stalls.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x9c", + "EventName": "TOPDOWN_FE_BOUND.ALL_P", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to BAClear", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.BRANCH_DETECT", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to BTClear", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.BRANCH_RESTEER", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to ms", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.CISC", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to decode stall", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.DECODE", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to frontend bandwidth restrictions due to decode, predecode, cisc, and other limitations.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.FRONTEND_BANDWIDTH", + "SampleAfterValue": "1000003", + "UMask": "0x8d" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to latency related stalls including BACLEARs, BTCLEARs, ITLB misses, and ICache misses.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.FRONTEND_LATENCY", + "SampleAfterValue": "1000003", + "UMask": "0x72" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to itlb miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.ITLB_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend that do not categorize into any other common frontend stall", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.OTHER", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to predecode wrong", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.PREDECODE", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, { "BriefDescription": "Fixed Counter: Counts the number of consumed retirement slots.", - "Counter": "38", + "Counter": "Fixed counter 6", "EventName": "TOPDOWN_RETIRING.ALL", "SampleAfterValue": "1000003", "UMask": "0x7" + }, + { + "BriefDescription": "Counts the number of consumed retirement slots.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "TOPDOWN_RETIRING.ALL_P", + "PublicDescription": "Counts the number of consumed retirement slots. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of uops issued by the front end every cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x0e", + "EventName": "UOPS_ISSUED.ANY", + "PublicDescription": "Counts the number of uops issued by the front end every cycle. When 4-uops are requested and only 2-uops are delivered, the event counts 2. Uops_issued correlates to the number of ROB entries. If uop takes 2 ROB slots it counts as 2 uops_issued.", + "SampleAfterValue": "1000003" + }, + { + "BriefDescription": "Counts the number of uops retired that were dual destination.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.DUAL_DEST", + "PublicDescription": "Counts the number of uops retired that were dual destination. Dual destination (dual dest) micro-operations require writing to two separate destination registers or memory addresses upon execution. These uops consume two entries in the ROB and tracked separately because they involve more complex operations that necessitate multiple results. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of uops retired that are the last uop of a macro-instruction.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.EOM", + "PublicDescription": "Counts the number of uops retired that are the last uop of a macro-instruction. EOM uops indicate the 'end of a macro-instruction' and play a crucial role in the processor's control flow and recovery mechanisms.", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of integer divide uops retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.IDIV", + "PublicDescription": "Counts the number of integer divide uops retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Counts the number of uops retired that originated from a loop stream detector.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.LSD", + "PublicDescription": "Counts the number of uops retired that originated from a loop stream detector. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of uops that are from the complex flows issued by the micro-sequencer (MS). This includes uops from flows due to complex instructions, faults, assists, and inserted flows.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.MS", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of x87 uops retired, includes those in ms flows.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.X87", + "SampleAfterValue": "1000003" } ] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-cache.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-cache.json new file mode 100644 index 000000000000..278837f2068a --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-cache.json @@ -0,0 +1,3413 @@ +[ + { + "BriefDescription": "Clockticks for CMS units attached to CHA", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_CHACMS_CLOCKTICKS", + "PerPkg": "1", + "PortMask": "0x000", + "Unit": "CHACMS" + }, + { + "BriefDescription": "UNC_CHACMS_DISTRESS_ASSERTED", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHACMS_DISTRESS_ASSERTED", + "PerPkg": "1", + "PortMask": "0x000", + "Unit": "CHACMS" + }, + { + "BriefDescription": "Counts the number of cycles FAST trigger is received from the global FAST distress wire.", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHACMS_RING_SRC_THRTL", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "Unit": "CHACMS" + }, + { + "BriefDescription": "Number of CHA clock cycles while the event is enabled", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_CHA_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Clockticks of the uncore caching and home agent (CHA)", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts transactions that looked into the multi-socket cacheline Directory state, and therefore did not send a snoop because the Directory indicated it was not needed.", + "Counter": "0,1,2,3", + "EventCode": "0x53", + "EventName": "UNC_CHA_DIR_LOOKUP.NO_SNP", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts transactions that looked into the multi-socket cacheline Directory state, and sent one or more snoops, because the Directory indicated it was needed.", + "Counter": "0,1,2,3", + "EventCode": "0x53", + "EventName": "UNC_CHA_DIR_LOOKUP.SNP", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts only multi-socket cacheline Directory state updates memory writes issued from the HA pipe. This does not include memory write requests which are for I (Invalid) or E (Exclusive) cachelines.", + "Counter": "0,1,2,3", + "EventCode": "0x54", + "EventName": "UNC_CHA_DIR_UPDATE.HA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts only multi-socket cacheline Directory state updates due to memory writes issued from the TOR pipe which are the result of remote transaction hitting the SF/LLC and returning data Core2Core. This does not include memory write requests which are for I (Invalid) or E (Exclusive) cachelines.", + "Counter": "0,1,2,3", + "EventCode": "0x54", + "EventName": "UNC_CHA_DIR_UPDATE.TOR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Distress signal assertion for dynamic prefetch throttle (DPT). Threshold for distress signal assertion reached in TOR or IRQ (immediate cause for triggering).", + "Counter": "0,1,2,3", + "EventCode": "0x59", + "EventName": "UNC_CHA_DISTRESS_ASSERTED.DPT_ANY", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x3", + "Unit": "CHA" + }, + { + "BriefDescription": "Distress signal assertion for dynamic prefetch throttle (DPT). Threshold for distress signal assertion reached in IRQ (immediate cause for triggering).", + "Counter": "0,1,2,3", + "EventCode": "0x59", + "EventName": "UNC_CHA_DISTRESS_ASSERTED.DPT_IRQ", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Distress signal assertion for dynamic prefetch throttle (DPT). Threshold for distress signal assertion reached in TOR (immediate cause for triggering).", + "Counter": "0,1,2,3", + "EventCode": "0x59", + "EventName": "UNC_CHA_DISTRESS_ASSERTED.DPT_TOR", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts when a normal (Non-Isochronous) full line write is issued from the CHA to the any of the memory controller channels.", + "Counter": "0,1,2,3", + "EventCode": "0x5b", + "EventName": "UNC_CHA_IMC_WRITES_COUNT.FULL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA to iMC Full Line Writes Issued : ISOCH Full Line : Counts the total number of full line writes issued from the HA into the memory controller.", + "Counter": "0,1,2,3", + "EventCode": "0x5b", + "EventName": "UNC_CHA_IMC_WRITES_COUNT.FULL_PRIORITY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA to iMC Full Line Writes Issued : Partial Non-ISOCH : Counts the total number of full line writes issued from the HA into the memory controller.", + "Counter": "0,1,2,3", + "EventCode": "0x5b", + "EventName": "UNC_CHA_IMC_WRITES_COUNT.PARTIAL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA to iMC Full Line Writes Issued : ISOCH Partial : Counts the total number of full line writes issued from the HA into the memory controller.", + "Counter": "0,1,2,3", + "EventCode": "0x5b", + "EventName": "UNC_CHA_IMC_WRITES_COUNT.PARTIAL_PRIORITY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: All Requests to Remotely Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.ALL_REMOTE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : All transactions from Remote Agents", + "UMask": "0x17e0ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: CRd Requests", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.CODE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests", + "UMask": "0x1bd0ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Read Requests and Read Prefetches", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.DATA_RD", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x1bc1ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Read Requests, Read Prefetches, and Snoops", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.DATA_READ_ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Data Reads", + "UMask": "0x1fc1ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Read Requests to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.DATA_READ_LOCAL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Demand Data Reads, Core and LLC prefetches", + "UMask": "0x841ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Read Requests, Read Prefetches, and Snoops which miss the Cache", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.DATA_READ_MISS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Data Read Misses", + "UMask": "0x1fc101", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: All Requests to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCALLY_HOMED_ADDRESS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Transactions homed locally", + "UMask": "0xbdfff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Code Read Requests and Code Read Prefetches to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_CODE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests", + "UMask": "0x19d0ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Read Requests and Read Prefetches to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_DATA_RD", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x19c1ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Code Read Requests to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_DMND_CODE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests", + "UMask": "0x1850ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Read Requests to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_DMND_DATA_RD", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x1841ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: RFO Requests to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_DMND_RFO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : RFO Requests", + "UMask": "0x1848ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: LLC Prefetch Requests to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_LLC_PF", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x189dff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: All Prefetches to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_PF", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x199dff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Code Prefetches to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_PF_CODE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests", + "UMask": "0x1910ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Read Prefetches to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_PF_DATA_RD", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x1981ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: RFO Prefetches to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_PF_RFO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : RFO Requests", + "UMask": "0x1908ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: RFO Requests and RFO Prefetches to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_RFO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : RFO Requests", + "UMask": "0x19c8ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: All Requests to Remotely Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTELY_HOMED_ADDRESS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Transactions homed remotely : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Transaction whose address resides in a remote MC", + "UMask": "0x15dfff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Code Read/Prefetch Requests from a Remote Socket", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_CODE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests", + "UMask": "0x1a10ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Data Read/Prefetch Requests from a Remote Socket", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_DATA_RD", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x1a01ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: RFO Requests/Prefetches from a Remote Socket", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_RFO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : RFO Requests", + "UMask": "0x1a08ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Snoop Requests from a Remote Socket", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_SNP", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed", + "UMask": "0x1c19ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: All RFO and RFO Prefetches", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.RFO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : All RFOs - Demand and Prefetches", + "UMask": "0x1bc8ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: RFO Requests and RFO Prefetches to Locally Homed Memory", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.RFO_LOCAL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Locally HOMed RFOs - Demand and Prefetches", + "UMask": "0x9c8ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Writes to Locally Homed Memory (includes writebacks from L1/L2)", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.WRITE_LOCAL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Writes", + "UMask": "0x842ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups: Writes to Remotely Homed Memory (includes writebacks from L1/L2)", + "Counter": "0,1,2,3", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.WRITE_REMOTE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Remote Writes", + "UMask": "0x17c2ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : All Lines Victimized", + "UMask": "0xf", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : IA traffic : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.IA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : IO traffic : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.IO", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Local - All Lines", + "UMask": "0x200f", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_E", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Local - Lines in E State", + "UMask": "0x2002", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_F", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Local - Lines in F State", + "UMask": "0x2008", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_M", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Local - Lines in M State", + "UMask": "0x2001", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_S", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Local - Lines in S State", + "UMask": "0x2004", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.REMOTE_ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Remote - All Lines", + "UMask": "0x800f", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.REMOTE_E", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Remote - Lines in E State", + "UMask": "0x8002", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.REMOTE_M", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Remote - Lines in M State", + "UMask": "0x8001", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.REMOTE_S", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Remote - Lines in S State", + "UMask": "0x8004", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.TOTAL_E", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Lines in E state", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.TOTAL_M", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Lines in M state", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.TOTAL_S", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Lines in S State", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts when a RFO (the Read for Ownership issued before a write) request hit a cacheline in the S (Shared) state.", + "Counter": "0,1,2,3", + "EventCode": "0x39", + "EventName": "UNC_CHA_MISC.RFO_HIT_S", + "PerPkg": "1", + "PublicDescription": "Cbo Misc : RFO HitS", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : Local InvItoE : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "Counter": "0,1,2,3", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.LOCAL_INVITOE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : Local Rd : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "Counter": "0,1,2,3", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.LOCAL_READ", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : Off : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "Counter": "0,1,2,3", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.OFF_PWRHEURISTIC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : Remote Rd : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "Counter": "0,1,2,3", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.REMOTE_READ", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : RFO HitS Snoop Broadcast : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "Counter": "0,1,2,3", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.RFO_HITS_SNP_BCAST", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.ALLOC_EXCLUSIVE", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.ALLOC_EXCLUSIVE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.ALLOC_SHARED", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.ALLOC_SHARED", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.DEALLOC_EVCTCLN", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.DEALLOC_EVCTCLN", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.DIRBACKED_ONLY", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.DIRBACKED_ONLY", + "Experimental": "1", + "PerPkg": "1", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.HIT_EXCLUSIVE", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.HIT_EXCLUSIVE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.HIT_SHARED", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.HIT_SHARED", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.INCLUSIVE_ONLY", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.INCLUSIVE_ONLY", + "Experimental": "1", + "PerPkg": "1", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.MISS", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.MISS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.UPDATE_EXCLUSIVE", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.UPDATE_EXCLUSIVE", + "Experimental": "1", + "PerPkg": "1", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.UPDATE_SHARED", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.UPDATE_SHARED", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.VICTIM_EXCLUSIVE", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.VICTIM_EXCLUSIVE", + "Experimental": "1", + "PerPkg": "1", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_REMOTE_SF.VICTIM_SHARED", + "Counter": "0,1,2,3", + "EventCode": "0x69", + "EventName": "UNC_CHA_REMOTE_SF.VICTIM_SHARED", + "Experimental": "1", + "PerPkg": "1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the total number of requests coming from a unit on this socket for exclusive ownership of a cache line without receiving data (INVITOE) to the CHA.", + "Counter": "0,1,2,3", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.INVITOE", + "PerPkg": "1", + "PublicDescription": "HA Read and Write Requests : InvalItoE", + "UMask": "0x30", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the total number of requests coming from a unit on this socket for exclusive ownership of a cache line without receiving data (INVITOE) to the CHA.", + "Counter": "0,1,2,3", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.INVITOE_LOCAL", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the total number of requests coming from a remote socket for exclusive ownership of a cache line without receiving data (INVITOE) to the CHA.", + "Counter": "0,1,2,3", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.INVITOE_REMOTE", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts read requests made into this CHA. Reads include all read opcodes (including RFO: the Read for Ownership issued before a write) .", + "Counter": "0,1,2,3", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.READS", + "PerPkg": "1", + "PublicDescription": "HA Read and Write Requests : Reads", + "UMask": "0x3", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts read requests coming from a unit on this socket made into this CHA. Reads include all read opcodes (including RFO: the Read for Ownership issued before a write).", + "Counter": "0,1,2,3", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.READS_LOCAL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts read requests coming from a remote socket made into the CHA. Reads include all read opcodes (including RFO: the Read for Ownership issued before a write).", + "Counter": "0,1,2,3", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.READS_REMOTE", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts write requests made into the CHA, including streaming, evictions, HitM (Reads from another core to a Modified cacheline), etc.", + "Counter": "0,1,2,3", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.WRITES", + "PerPkg": "1", + "PublicDescription": "HA Read and Write Requests : Writes", + "UMask": "0xc", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts write requests coming from a unit on this socket made into this CHA, including streaming, evictions, HitM (Reads from another core to a Modified cacheline), etc.", + "Counter": "0,1,2,3", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.WRITES_LOCAL", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the total number of read requests made into the Home Agent. Reads include all read opcodes (including RFO). Writes include all writes (streaming, evictions, HitM, etc).", + "Counter": "0,1,2,3", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.WRITES_REMOTE", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Allocations : IRQ : Counts number of allocations per cycle into the specified Ingress queue.", + "Counter": "0,1,2,3", + "EventCode": "0x13", + "EventName": "UNC_CHA_RxC_INSERTS.IRQ", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Occupancy : IRQ : Counts number of entries in the specified Ingress queue in each cycle.", + "Counter": "0", + "EventCode": "0x11", + "EventName": "UNC_CHA_RxC_OCCUPANCY.IRQ", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts snoop filter capacity evictions for entries tracking exclusive lines in the core's cache. Snoop filter capacity evictions occur when the snoop filter is full and evicts an existing entry to track a new entry. Does not count clean evictions such as when a core's cache replaces a tracked cacheline with a new cacheline.", + "Counter": "0,1,2,3", + "EventCode": "0x3d", + "EventName": "UNC_CHA_SF_EVICTION.E_STATE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Snoop Filter Capacity Evictions : E state", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts snoop filter capacity evictions for entries tracking modified lines in the core's cache. Snoop filter capacity evictions occur when the snoop filter is full and evicts an existing entry to track a new entry. Does not count clean evictions such as when a core's cache replaces a tracked cacheline with a new cacheline.", + "Counter": "0,1,2,3", + "EventCode": "0x3d", + "EventName": "UNC_CHA_SF_EVICTION.M_STATE", + "PerPkg": "1", + "PublicDescription": "Snoop Filter Capacity Evictions : M state", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts snoop filter capacity evictions for entries tracking shared lines in the core's cache. Snoop filter capacity evictions occur when the snoop filter is full and evicts an existing entry to track a new entry. Does not count clean evictions such as when a core's cache replaces a tracked cacheline with a new cacheline.", + "Counter": "0,1,2,3", + "EventCode": "0x3d", + "EventName": "UNC_CHA_SF_EVICTION.S_STATE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Snoop Filter Capacity Evictions : S state", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "All TOR Inserts", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All", + "UMask": "0xc001ffff", + "Unit": "CHA" + }, + { + "BriefDescription": "CLFlush transactions from a CXL device which hit in the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_HIT_CLFLUSH", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c8c7fd20", + "Unit": "CHA" + }, + { + "BriefDescription": "FsRdCur transactions from a CXL device which hit in the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_HIT_FSRDCUR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c8effd20", + "Unit": "CHA" + }, + { + "BriefDescription": "FsRdCurPtl transactions from a CXL device which hit in the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_HIT_FSRDCURPTL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c9effd20", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoM transactions from a CXL device which hit in the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_HIT_ITOM", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc47fd20", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoMWr transactions from a CXL device which hit in the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_HIT_ITOMWR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc4ffd20", + "Unit": "CHA" + }, + { + "BriefDescription": "MemPushWr transactions from a CXL device which hit in the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_HIT_MEMPUSHWR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc6ffd20", + "Unit": "CHA" + }, + { + "BriefDescription": "WCiL transactions from a CXL device which hit in the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_HIT_WCIL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c86ffd20", + "Unit": "CHA" + }, + { + "BriefDescription": "WcilF transactions from a CXL device which hit in the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_HIT_WCILF", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c867fd20", + "Unit": "CHA" + }, + { + "BriefDescription": "WiL transactions from a CXL device which hit in the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_HIT_WIL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c87ffd20", + "Unit": "CHA" + }, + { + "BriefDescription": "CLFlush transactions from a CXL device which miss the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_MISS_CLFLUSH", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c8c7fe20", + "Unit": "CHA" + }, + { + "BriefDescription": "FsRdCur transactions from a CXL device which miss the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_MISS_FSRDCUR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c8effe20", + "Unit": "CHA" + }, + { + "BriefDescription": "FsRdCurPtl transactions from a CXL device which miss the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_MISS_FSRDCURPTL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c9effe20", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoM transactions from a CXL device which miss the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_MISS_ITOM", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc47fe20", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoMWr transactions from a CXL device which miss the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_MISS_ITOMWR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc4ffe20", + "Unit": "CHA" + }, + { + "BriefDescription": "MemPushWr transactions from a CXL device which miss the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_MISS_MEMPUSHWR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc6ffe20", + "Unit": "CHA" + }, + { + "BriefDescription": "WCiL transactions from a CXL device which miss the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_MISS_WCIL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c86ffe20", + "Unit": "CHA" + }, + { + "BriefDescription": "WcilF transactions from a CXL device which miss the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_MISS_WCILF", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c867fe20", + "Unit": "CHA" + }, + { + "BriefDescription": "WiL transactions from a CXL device which miss the L3.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.CXL_MISS_WIL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c87ffe20", + "Unit": "CHA" + }, + { + "BriefDescription": "All locally initiated requests from IA Cores", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All requests from iA Cores", + "UMask": "0xc001ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "CLFlush events that are initiated from the Core", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_CLFLUSH", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CLFlushes issued by iA Cores", + "UMask": "0xc8c7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "CLFlushOpt events that are initiated from the Core", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_CLFLUSHOPT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CLFlushOpts issued by iA Cores", + "UMask": "0xc8d7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "Code read from local IA", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CRDs issued by iA Cores", + "UMask": "0xc80fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "Code read prefetch from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Code read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc88fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "Data read opt from local IA", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd_Opts issued by iA Cores", + "UMask": "0xc827ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "Data read opt prefetch from local IA", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd_Opt_Prefs issued by iA Cores", + "UMask": "0xc8a7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "All locally initiated requests from IA Cores which hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All requests from iA Cores that Hit the LLC", + "UMask": "0xc001fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "Code read from local IA that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CRds issued by iA Cores that Hit the LLC", + "UMask": "0xc80ffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "Code read prefetch from local IA that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CRd_Prefs issued by iA Cores that hit the LLC", + "UMask": "0xc88ffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "All requests issued from IA cores to CXL accelerator memory regions that hit the LLC.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c0018101", + "Unit": "CHA" + }, + { + "BriefDescription": "Data read opt from local IA that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd_Opts issued by iA Cores that hit the LLC", + "UMask": "0xc827fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "Data read opt prefetch from local IA that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd_Opt_Prefs issued by iA Cores that hit the LLC", + "UMask": "0xc8a7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoM requests from local IA cores that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by iA Cores that Hit LLC", + "UMask": "0xcc47fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "Last level cache prefetch code read from local IA that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : LLCPrefCode issued by iA Cores that hit the LLC", + "UMask": "0xcccffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "Last level cache prefetch data read from local IA that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : LLCPrefData issued by iA Cores that hit the LLC", + "UMask": "0xccd7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "Last level cache prefetch read for ownership from local IA that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : LLCPrefRFO issued by iA Cores that hit the LLC", + "UMask": "0xccc7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership from local IA that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by iA Cores that Hit the LLC", + "UMask": "0xc807fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership prefetch from local IA that hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFO_Prefs issued by iA Cores that Hit the LLC", + "UMask": "0xc887fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoM events that are initiated from the Core", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by iA Cores", + "UMask": "0xcc47ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoMCacheNear requests from local IA cores", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMCacheNears issued by iA Cores", + "UMask": "0xcd47ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "Last level cache prefetch code read from local IA.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : LLCPrefCode issued by iA Cores", + "UMask": "0xcccfff01", + "Unit": "CHA" + }, + { + "BriefDescription": "Last level cache prefetch data read from local IA.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : LLCPrefData issued by iA Cores", + "UMask": "0xccd7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "Last level cache prefetch read for ownership from local IA", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : LLCPrefRFO issued by iA Cores", + "UMask": "0xccc7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "All locally initiated requests from IA Cores which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All requests from iA Cores that Missed the LLC", + "UMask": "0xc001fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Code read from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CRds issued by iA Cores that Missed the LLC", + "UMask": "0xc80ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "CRDs from local IA cores to locally homed memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CRd issued by iA Cores that Missed the LLC - HOMed locally", + "UMask": "0xc80efe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Code read prefetch from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CRd_Prefs issued by iA Cores that Missed the LLC", + "UMask": "0xc88ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "CRD Prefetches from local IA cores to locally homed memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed locally", + "UMask": "0xc88efe01", + "Unit": "CHA" + }, + { + "BriefDescription": "CRD Prefetches from local IA cores to remotely homed memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed remotely", + "UMask": "0xc88f7e01", + "Unit": "CHA" + }, + { + "BriefDescription": "CRDs from local IA cores to remotely homed memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CRd issued by iA Cores that Missed the LLC - HOMed remotely", + "UMask": "0xc80f7e01", + "Unit": "CHA" + }, + { + "BriefDescription": "All requests issued from IA cores to CXL accelerator memory regions that miss the LLC.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c0018201", + "Unit": "CHA" + }, + { + "BriefDescription": "DRds and equivalent opcodes issued from an IA core which miss the L3 and target memory in a CXL type 2 memory expander card.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_CXL_ACC", + "PerPkg": "1", + "PublicDescription": "DRds issued from an IA core which miss the L3 and target memory in a CXL type 2 memory expander card.", + "UMask": "0x10c8178201", + "Unit": "CHA" + }, + { + "BriefDescription": "Data read opt from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd_Opt issued by iA Cores that missed the LLC", + "UMask": "0xc827fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd_Opt, and which target local memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd_Opt issued by iA Cores that Missed the LLC - HOMed locally", + "UMask": "0xc826fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Data read opt prefetch from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd_Opt_Prefs issued by iA Cores that missed the LLC", + "UMask": "0xc8a7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRD_PREF_OPT, and target local memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Data read opt prefetch from local iA that missed the LLC targeting local memory", + "UMask": "0xc8a6fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRD_PREF_OPT, and target remote memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Data read opt prefetch from local iA that missed the LLC targeting remote memory", + "UMask": "0xc8a77e01", + "Unit": "CHA" + }, + { + "BriefDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd_Opt, and target remote memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Data read opt from local iA that missed the LLC targeting remote memory", + "UMask": "0xc8277e01", + "Unit": "CHA" + }, + { + "BriefDescription": "L2 data prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8978201", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoM requests from local IA cores that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by iA Cores that Missed LLC", + "UMask": "0xcc47fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Last level cache prefetch code read from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : LLCPrefCode issued by iA Cores that missed the LLC", + "UMask": "0xcccffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Last level cache prefetch data read from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : LLCPrefData issued by iA Cores that missed the LLC", + "UMask": "0xccd7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "LLC data prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFDATA_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10ccd78201", + "Unit": "CHA" + }, + { + "BriefDescription": "Last level cache prefetch read for ownership from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : LLCPrefRFO issued by iA Cores that missed the LLC", + "UMask": "0xccc7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "L2 RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFRFO_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8878201", + "Unit": "CHA" + }, + { + "BriefDescription": "WCILF requests from local IA cores to locally homed DDR addresses that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LOCAL_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed locally", + "UMask": "0xc8668601", + "Unit": "CHA" + }, + { + "BriefDescription": "WCILF requests from local IA cores to locally homed PMM addresses which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LOCAL_WCILF_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed locally", + "UMask": "0xc8668a01", + "Unit": "CHA" + }, + { + "BriefDescription": "WCIL requests from local IA cores to locally homed DDR addresses that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LOCAL_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed locally", + "UMask": "0xc86e8601", + "Unit": "CHA" + }, + { + "BriefDescription": "WCIL requests from local IA cores to locally homed PMM addresses which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LOCAL_WCIL_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed locally", + "UMask": "0xc86e8a01", + "Unit": "CHA" + }, + { + "BriefDescription": "WCILF requests from local IA cores to remotely homed DDR addresses that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_REMOTE_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely", + "UMask": "0xc8670601", + "Unit": "CHA" + }, + { + "BriefDescription": "WCILF requests from local IA cores to remotely homed PMM addresses which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_REMOTE_WCILF_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely", + "UMask": "0xc8670a01", + "Unit": "CHA" + }, + { + "BriefDescription": "WCIL requests from local IA cores to remotely homed DDR addresses that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_REMOTE_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely", + "UMask": "0xc86f0601", + "Unit": "CHA" + }, + { + "BriefDescription": "WCIL requests from local IA cores to remotely homed PMM addresses which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_REMOTE_WCIL_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely", + "UMask": "0xc86f0a01", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by iA Cores that Missed the LLC", + "UMask": "0xc807fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "RFOs issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8078201", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership from local IA that miss the LLC targeting local memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by iA Cores that Missed the LLC - HOMed locally", + "UMask": "0xc806fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership prefetch from local IA that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFO_Prefs issued by iA Cores that Missed the LLC", + "UMask": "0xc887fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "LLC RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10ccc78201", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership prefetch from local IA that miss the LLC targeting local memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFO_Prefs issued by iA Cores that Missed the LLC - HOMed locally", + "UMask": "0xc886fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership prefetch from local IA that miss the LLC targeting remote memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFO_Prefs issued by iA Cores that Missed the LLC - HOMed remotely", + "UMask": "0xc8877e01", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership from local IA that miss the LLC targeting remote memory", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by iA Cores that Missed the LLC - HOMed remotely", + "UMask": "0xc8077e01", + "Unit": "CHA" + }, + { + "BriefDescription": "UCRDF requests from local IA cores that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_UCRDF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : UCRdFs issued by iA Cores that Missed LLC", + "UMask": "0xc877de01", + "Unit": "CHA" + }, + { + "BriefDescription": "WCIL requests from a local IA core that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCIL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLs issued by iA Cores that Missed the LLC", + "UMask": "0xc86ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "WCILF requests from local IA core that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCILF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLF issued by iA Cores that Missed the LLC", + "UMask": "0xc867fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "WCILF requests from local IA cores to DDR homed addresses which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting DDR that missed the LLC", + "UMask": "0xc8678601", + "Unit": "CHA" + }, + { + "BriefDescription": "WCILF requests from local IA cores to PMM homed addresses which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCILF_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting PMM that missed the LLC", + "UMask": "0xc8678a01", + "Unit": "CHA" + }, + { + "BriefDescription": "WCIL requests from local IA cores to DDR homed addresses which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLs issued by iA Cores targeting DDR that missed the LLC", + "UMask": "0xc86f8601", + "Unit": "CHA" + }, + { + "BriefDescription": "WCIL requests from a local IA core to PMM homed addresses that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCIL_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLs issued by iA Cores targeting PMM that missed the LLC", + "UMask": "0xc86f8a01", + "Unit": "CHA" + }, + { + "BriefDescription": "WIL requests from local IA cores that miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WIL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WiLs issued by iA Cores that Missed LLC", + "UMask": "0xc87fde01", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership from local IA", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by iA Cores", + "UMask": "0xc807ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "Read for ownership prefetch from local IA", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFO_Prefs issued by iA Cores", + "UMask": "0xc887ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "SpecItoM events that are initiated from the Core", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_SPECITOM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : SpecItoMs issued by iA Cores", + "UMask": "0xcc57ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "WbEFtoEs issued by iA Cores. (Non Modified Write Backs)", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBEFTOE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by IO Devices that Hit the LLC", + "UMask": "0xcc3fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "WbEFtoIs issued by iA Cores . (Non Modified Write Backs)", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBEFTOI", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by IO Devices that Hit the LLC", + "UMask": "0xcc37ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "WbMtoEs issued by iA Cores . (Modified Write Backs)", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBMTOE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by IO Devices that Hit the LLC", + "UMask": "0xcc2fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "WbMtoI requests from local IA cores", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBMTOI", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WbMtoIs issued by iA Cores", + "UMask": "0xcc27ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "WbStoIs issued by iA Cores . (Non Modified Write Backs)", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBSTOI", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by IO Devices that Hit the LLC", + "UMask": "0xcc67ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "WCIL requests from a local IA core", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WCIL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLs issued by iA Cores", + "UMask": "0xc86fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "WCILF requests from local IA core", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WCILF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WCiLF issued by iA Cores", + "UMask": "0xc867ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "All TOR inserts from local IO devices", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All requests from IO Devices", + "UMask": "0xc001ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "CLFlush requests from IO devices", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_CLFLUSH", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : CLFlushes issued by IO Devices", + "UMask": "0xc8c3ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "All TOR inserts from local IO devices which hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All requests from IO Devices that hit the LLC", + "UMask": "0xc001fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoMs from local IO devices which hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by IO Devices that Hit the LLC", + "UMask": "0xcc43fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoMCacheNears, indicating a partial write request, from IO Devices that hit the LLC", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMCacheNears, indicating a partial write request, from IO Devices that hit the LLC", + "UMask": "0xcd43fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "PCIRDCURs issued by IO devices which hit the LLC", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PCIRdCurs issued by IO Devices that hit the LLC", + "UMask": "0xc8f3fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "RFOs from local IO devices which hit the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by IO Devices that hit the LLC", + "UMask": "0xc803fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "All TOR ItoM inserts from local IO devices", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by IO Devices", + "UMask": "0xcc43ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoMCacheNears, indicating a partial write request, from IO Devices", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMCacheNears, indicating a partial write request, from IO Devices", + "UMask": "0xcd43ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoMCacheNear (partial write) transactions from an IO device that addresses memory on the local socket", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMCacheNears, indicating a partial write request, from IO Devices that address memory on the local socket", + "UMask": "0xcd42ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoMCacheNear (partial write) transactions from an IO device that addresses memory on a remote socket", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMCacheNears, indicating a partial write request, from IO Devices that address memory on a remote socket", + "UMask": "0xcd437f04", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoM (write) transactions from an IO device that addresses memory on the local socket", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_ITOM_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoM, indicating a write request, from IO Devices that address memory on the local socket", + "UMask": "0xcc42ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoM (write) transactions from an IO device that addresses memory on a remote socket", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_ITOM_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoM, indicating a write request, from IO Devices that address memory on a remote socket", + "UMask": "0xcc437f04", + "Unit": "CHA" + }, + { + "BriefDescription": "All TOR inserts from local IO devices which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All requests from IO Devices that missed the LLC", + "UMask": "0xc001fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "All TOR ItoM inserts from local IO devices which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMs issued by IO Devices that missed the LLC", + "UMask": "0xcc43fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC", + "UMask": "0xcd43fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "PCIRDCURs issued by IO devices which miss the LLC", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PCIRdCurs issued by IO Devices that missed the LLC", + "UMask": "0xc8f3fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "All TOR RFO inserts from local IO devices which miss the cache", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by IO Devices that missed the LLC", + "UMask": "0xc803fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "PCIRDCURs issued by IO devices", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PCIRdCurs issued by IO Devices", + "UMask": "0xc8f3ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "PCIRDCUR (read) transactions from an IO device that addresses memory on the local socket", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PCIRdCurs issued by IO Devices that addresses memory on the local socket", + "UMask": "0xc8f2ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "PCIRDCUR (read) transactions from an IO device that addresses memory on a remote socket", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PCIRdCurs issued by IO Devices that addresses memory on a remote socket", + "UMask": "0xc8f37f04", + "Unit": "CHA" + }, + { + "BriefDescription": "RFOs from local IO devices", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by IO Devices", + "UMask": "0xc803ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "WBMtoI requests from IO devices", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_WBMTOI", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WbMtoIs issued by IO Devices", + "UMask": "0xcc23ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for SF or LLC Evictions", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.LLC_OR_SF_EVICTIONS", + "PerPkg": "1", + "PublicDescription": "TOR allocation occurred as a result of SF/LLC evictions (came from the ISMQ)", + "UMask": "0xc001ff02", + "Unit": "CHA" + }, + { + "BriefDescription": "All locally initiated requests", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.LOC_ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All from Local iA and IO", + "UMask": "0xc000ff05", + "Unit": "CHA" + }, + { + "BriefDescription": "All from Local iA", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.LOC_IA", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All from Local iA", + "UMask": "0xc000ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "All from Local IO", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.LOC_IO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All from Local IO", + "UMask": "0xc000ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "All remote requests (e.g. snoops, writebacks) that came from remote sockets", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.REM_ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All Remote Requests", + "UMask": "0xc001ffc8", + "Unit": "CHA" + }, + { + "BriefDescription": "All snoops to this LLC that came from remote sockets", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.REM_SNPS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All Snoops from Remote", + "UMask": "0xc001ff08", + "Unit": "CHA" + }, + { + "BriefDescription": "Occupancy for all TOR entries", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All", + "UMask": "0xc001ffff", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CLFlush transactions from a CXL device which hit in the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_HIT_CLFLUSH", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c8c7fd20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for FsRdCur transactions from a CXL device which hit in the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_HIT_FSRDCUR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c8effd20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for FsRdCurPtl transactions from a CXL device which hit in the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_HIT_FSRDCURPTL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c9effd20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoM transactions from a CXL device which hit in the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_HIT_ITOM", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc47fd20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoMWr transactions from a CXL device which hit in the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_HIT_ITOMWR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc4ffd20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for MemPushWr transactions from a CXL device which hit in the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_HIT_MEMPUSHWR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc6ffd20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCiL transactions from a CXL device which hit in the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_HIT_WCIL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c86ffd20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WcilF transactions from a CXL device which hit in the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_HIT_WCILF", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c867fd20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WiL transactions from a CXL device which hit in the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_HIT_WIL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c87ffd20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CLFlush transactions from a CXL device which miss the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_MISS_CLFLUSH", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c8c7fe20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for FsRdCur transactions from a CXL device which miss the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_MISS_FSRDCUR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c8effe20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for FsRdCurPtl transactions from a CXL device which miss the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_MISS_FSRDCURPTL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c9effe20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoM transactions from a CXL device which miss the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_MISS_ITOM", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc47fe20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoMWr transactions from a CXL device which miss the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_MISS_ITOMWR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc4ffe20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for MemPushWr transactions from a CXL device which miss the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_MISS_MEMPUSHWR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78cc6ffe20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCiL transactions from a CXL device which miss the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_MISS_WCIL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c86ffe20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WcilF transactions from a CXL device which miss the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_MISS_WCILF", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c867fe20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WiL transactions from a CXL device which miss the L3.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.CXL_MISS_WIL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78c87ffe20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All locally initiated requests from IA Cores", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from iA Cores", + "UMask": "0xc001ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CLFlush events that are initiated from the Core", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_CLFLUSH", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CLFlushes issued by iA Cores", + "UMask": "0xc8c7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CLFlushOpt events that are initiated from the Core", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_CLFLUSHOPT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CLFlushOpts issued by iA Cores", + "UMask": "0xc8d7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Code read from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRDs issued by iA Cores", + "UMask": "0xc80fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Code read prefetch from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Code read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc88fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Data read opt from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Opts issued by iA Cores", + "UMask": "0xc827ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Data read opt prefetch from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_DRD_OPT_PREF", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Opt_Prefs issued by iA Cores", + "UMask": "0xc8a7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All locally initiated requests from IA Cores which hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from iA Cores that Hit the LLC", + "UMask": "0xc001fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Code read from local IA that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRds issued by iA Cores that Hit the LLC", + "UMask": "0xc80ffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Code read prefetch from local IA that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd_Prefs issued by iA Cores that hit the LLC", + "UMask": "0xc88ffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All requests issued from IA cores to CXL accelerator memory regions that hit the LLC.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c0018101", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Data read opt from local IA that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Opts issued by iA Cores that hit the LLC", + "UMask": "0xc827fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Data read opt prefetch from local IA that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Opt_Prefs issued by iA Cores that hit the LLC", + "UMask": "0xc8a7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoM requests from local IA cores that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by iA Cores that Hit LLC", + "UMask": "0xcc47fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Last level cache prefetch code read from local IA that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : LLCPrefCode issued by iA Cores that hit the LLC", + "UMask": "0xcccffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Last level cache prefetch data read from local IA that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : LLCPrefData issued by iA Cores that hit the LLC", + "UMask": "0xccd7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Last level cache prefetch read for ownership from local IA that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : LLCPrefRFO issued by iA Cores that hit the LLC", + "UMask": "0xccc7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership from local IA that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by iA Cores that Hit the LLC", + "UMask": "0xc807fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership prefetch from local IA that hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFO_Prefs issued by iA Cores that Hit the LLC", + "UMask": "0xc887fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoM events that are initiated from the Core", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by iA Cores", + "UMask": "0xcc47ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoMCacheNear requests from local IA cores", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMCacheNears issued by iA Cores", + "UMask": "0xcd47ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Last level cache prefetch code read from local IA.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : LLCPrefCode issued by iA Cores", + "UMask": "0xcccfff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Last level cache prefetch data read from local IA.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : LLCPrefData issued by iA Cores", + "UMask": "0xccd7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Last level cache prefetch read for ownership from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : LLCPrefRFO issued by iA Cores", + "UMask": "0xccc7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All locally initiated requests from IA Cores which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from iA Cores that Missed the LLC", + "UMask": "0xc001fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Code read from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRds issued by iA Cores that Missed the LLC", + "UMask": "0xc80ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CRDs from local IA cores to locally homed memory", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd issued by iA Cores that Missed the LLC - HOMed locally", + "UMask": "0xc80efe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Code read prefetch from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd_Prefs issued by iA Cores that Missed the LLC", + "UMask": "0xc88ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CRD Prefetches from local IA cores to locally homed memory", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed locally", + "UMask": "0xc88efe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CRD Prefetches from local IA cores to remotely homed memory", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed remotely", + "UMask": "0xc88f7e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CRDs from local IA cores to remotely homed memory", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd issued by iA Cores that Missed the LLC - HOMed remotely", + "UMask": "0xc80f7e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All requests issued from IA cores to CXL accelerator memory regions that miss the LLC.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c0018201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for DRds and equivalent opcodes issued from an IA core which miss the L3 and target memory in a CXL type 2 memory expander card.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8178201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Data read opt from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Opt issued by iA Cores that missed the LLC", + "UMask": "0xc827fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Data read opt prefetch from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Opt_Prefs issued by iA Cores that missed the LLC", + "UMask": "0xc8a7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for L2 data prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8978201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoM requests from local IA cores that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by iA Cores that Missed LLC", + "UMask": "0xcc47fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Last level cache prefetch code read from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : LLCPrefCode issued by iA Cores that missed the LLC", + "UMask": "0xcccffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Last level cache prefetch data read from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : LLCPrefData issued by iA Cores that missed the LLC", + "UMask": "0xccd7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for LLC data prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFDATA_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10ccd78201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Last level cache prefetch read for ownership from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : LLCPrefRFO issued by iA Cores that missed the LLC", + "UMask": "0xccc7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for L2 RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFRFO_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8878201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCILF requests from local IA cores to locally homed DDR addresses that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LOCAL_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed locally", + "UMask": "0xc8668601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCILF requests from local IA cores to locally homed PMM addresses which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LOCAL_WCILF_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed locally", + "UMask": "0xc8668a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCIL requests from local IA cores to locally homed DDR addresses that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LOCAL_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed locally", + "UMask": "0xc86e8601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCIL requests from local IA cores to locally homed PMM addresses which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LOCAL_WCIL_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed locally", + "UMask": "0xc86e8a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCILF requests from local IA cores to remotely homed DDR addresses that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_REMOTE_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely", + "UMask": "0xc8670601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCILF requests from local IA cores to remotely homed PMM addresses which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_REMOTE_WCILF_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely", + "UMask": "0xc8670a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCIL requests from local IA cores to remotely homed DDR addresses that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_REMOTE_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely", + "UMask": "0xc86f0601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCIL requests from local IA cores to remotely homed PMM addresses which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_REMOTE_WCIL_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely", + "UMask": "0xc86f0a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by iA Cores that Missed the LLC", + "UMask": "0xc807fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for RFOs issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8078201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by iA Cores that Missed the LLC - HOMed locally", + "UMask": "0xc806fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership prefetch from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFO_Prefs issued by iA Cores that Missed the LLC", + "UMask": "0xc887fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for LLC RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10ccc78201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership prefetch from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFO_Prefs issued by iA Cores that Missed the LLC - HOMed locally", + "UMask": "0xc886fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership prefetch from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFO_Prefs issued by iA Cores that Missed the LLC - HOMed remotely", + "UMask": "0xc8877e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by iA Cores that Missed the LLC - HOMed remotely", + "UMask": "0xc8077e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for UCRDF requests from local IA cores that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_UCRDF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : UCRdFs issued by iA Cores that Missed LLC", + "UMask": "0xc877de01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCIL requests from a local IA core that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCIL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores that Missed the LLC", + "UMask": "0xc86ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCILF requests from local IA core that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCILF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLF issued by iA Cores that Missed the LLC", + "UMask": "0xc867fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCILF requests from local IA cores to DDR homed addresses which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting DDR that missed the LLC", + "UMask": "0xc8678601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCILF requests from local IA cores to PMM homed addresses which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCILF_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting PMM that missed the LLC", + "UMask": "0xc8678a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCIL requests from local IA cores to DDR homed addresses which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting DDR that missed the LLC", + "UMask": "0xc86f8601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCIL requests from a local IA core to PMM homed addresses that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCIL_PMM", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting PMM that missed the LLC", + "UMask": "0xc86f8a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WIL requests from local IA cores that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WIL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WiLs issued by iA Cores that Missed LLC", + "UMask": "0xc87fde01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by iA Cores", + "UMask": "0xc807ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for Read for ownership prefetch from local IA that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFO_Prefs issued by iA Cores", + "UMask": "0xc887ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for SpecItoM events that are initiated from the Core", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_SPECITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : SpecItoMs issued by iA Cores", + "UMask": "0xcc57ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WbMtoI requests from local IA cores", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_WBMTOI", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WbMtoIs issued by iA Cores", + "UMask": "0xcc27ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCIL requests from a local IA core", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_WCIL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores", + "UMask": "0xc86fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WCILF requests from local IA core", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_WCILF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLF issued by iA Cores", + "UMask": "0xc867ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All TOR inserts from local IO devices", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from IO Devices", + "UMask": "0xc001ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CLFlush requests from IO devices", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_CLFLUSH", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CLFlushes issued by IO Devices", + "UMask": "0xc8c3ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All TOR inserts from local IO devices which hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from IO Devices that hit the LLC", + "UMask": "0xc001fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoMs from local IO devices which hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by IO Devices that Hit the LLC", + "UMask": "0xcc43fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoMCacheNears, indicating a partial write request, from IO Devices that hit the LLC", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices that hit the LLC", + "UMask": "0xcd43fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for PCIRDCURs issued by IO devices which hit the LLC", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PCIRdCurs issued by IO Devices that hit the LLC", + "UMask": "0xc8f3fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for RFOs from local IO devices which hit the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by IO Devices that hit the LLC", + "UMask": "0xc803fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All TOR ItoM inserts from local IO devices", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by IO Devices", + "UMask": "0xcc43ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoMCacheNears, indicating a partial write request, from IO Devices", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices", + "UMask": "0xcd43ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All TOR inserts from local IO devices which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from IO Devices that missed the LLC", + "UMask": "0xc001fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All TOR ItoM inserts from local IO devices which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by IO Devices that missed the LLC", + "UMask": "0xcc43fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC", + "UMask": "0xcd43fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoMCacheNear transactions from an IO device on the local socket that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_ITOMCACHENEAR_LOCAL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC", + "UMask": "0xcd42fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoMCacheNear transactions from an IO device on a remote socket that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_ITOMCACHENEAR_REMOTE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC", + "UMask": "0xcd437e04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoM transactions from an IO device on the local socket that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_ITOM_LOCAL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by IO Devices that missed the LLC", + "UMask": "0xcc42fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for ItoM transactions from an IO device on a remote socket that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_ITOM_REMOTE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by IO Devices that missed the LLC", + "UMask": "0xcc437e04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for PCIRDCURs issued by IO devices which miss the LLC", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PCIRdCurs issued by IO Devices that missed the LLC", + "UMask": "0xc8f3fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for PCIRDCUR transactions from an IO device on the local socket that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_PCIRDCUR_LOCAL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PCIRdCurs issued by IO Devices that missed the LLC", + "UMask": "0xc8f2fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for PCIRDCUR transactions from an IO device on a remote socket that miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_PCIRDCUR_REMOTE", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PCIRdCurs issued by IO Devices that missed the LLC", + "UMask": "0xc8f37e04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All TOR RFO inserts from local IO devices which miss the cache", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by IO Devices that missed the LLC", + "UMask": "0xc803fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for PCIRDCURs issued by IO devices", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PCIRdCurs issued by IO Devices", + "UMask": "0xc8f3ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for RFOs from local IO devices", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by IO Devices", + "UMask": "0xc803ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for WBMtoI requests from IO devices", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_WBMTOI", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WbMtoIs issued by IO Devices", + "UMask": "0xcc23ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All locally initiated requests", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.LOC_ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All from Local iA and IO", + "UMask": "0xc000ff05", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All from Local iA", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.LOC_IA", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All from Local iA", + "UMask": "0xc000ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All from Local IO", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.LOC_IO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All from Local IO", + "UMask": "0xc000ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All remote requests (e.g. snoops, writebacks) that came from remote sockets", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.REM_ALL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All Remote Requests", + "UMask": "0xc001ffc8", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All snoops to this LLC that came from remote sockets", + "Counter": "0", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.REM_SNPS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All Snoops from Remote", + "UMask": "0xc001ff08", + "Unit": "CHA" + } +] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-cxl.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-cxl.json new file mode 100644 index 000000000000..383a5ba5a697 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-cxl.json @@ -0,0 +1,31 @@ +[ + { + "BriefDescription": "B2CXL Clockticks", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_B2CXL_CLOCKTICKS", + "PerPkg": "1", + "PortMask": "0x000", + "Unit": "B2CXL" + }, + { + "BriefDescription": "Number of Allocation to Mem Data Packing buffer", + "Counter": "4,5,6,7", + "EventCode": "0x41", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_INSERTS.MEM_DATA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to M2S Data AGF", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_CXLDP_TxC_AGF_INSERTS.M2S_DATA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CXLDP" + } +] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-interconnect.json new file mode 100644 index 000000000000..251e5d20fefe --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-interconnect.json @@ -0,0 +1,1625 @@ +[ + { + "BriefDescription": "Clockticks of the mesh to memory (B2CMI)", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_B2CMI_CLOCKTICKS", + "PerPkg": "1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of time D2C was not honoured by egress due to directory state constraints", + "Counter": "0,1,2,3", + "EventCode": "0x17", + "EventName": "UNC_B2CMI_DIRECT2CORE_NOT_TAKEN_DIRSTATE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of times B2CMI egress did D2C (direct to core)", + "Counter": "0,1,2,3", + "EventCode": "0x16", + "EventName": "UNC_B2CMI_DIRECT2CORE_TAKEN", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of times D2C wasn't honoured even though the incoming request had d2c set for non cisgress txn", + "Counter": "0,1,2,3", + "EventCode": "0x18", + "EventName": "UNC_B2CMI_DIRECT2CORE_TXN_OVERRIDE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of d2k wasn't done due to credit constraints", + "Counter": "0,1,2,3", + "EventCode": "0x1B", + "EventName": "UNC_B2CMI_DIRECT2UPI_NOT_TAKEN_CREDITS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Direct to UPI Transactions - Ignored due to lack of credits : All : Counts the number of d2k wasn't done due to credit constraints", + "Counter": "0,1,2,3", + "EventCode": "0x1B", + "EventName": "UNC_B2CMI_DIRECT2UPI_NOT_TAKEN_CREDITS.EGRESS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of time D2K was not honoured by egress due to directory state constraints", + "Counter": "0,1,2,3", + "EventCode": "0x1A", + "EventName": "UNC_B2CMI_DIRECT2UPI_NOT_TAKEN_DIRSTATE", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Cycles when Direct2UPI was Disabled : Egress Ignored D2U : Counts the number of time D2K was not honoured by egress due to directory state constraints", + "Counter": "0,1,2,3", + "EventCode": "0x1A", + "EventName": "UNC_B2CMI_DIRECT2UPI_NOT_TAKEN_DIRSTATE.EGRESS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of times egress did D2K (Direct to KTI)", + "Counter": "0,1,2,3", + "EventCode": "0x19", + "EventName": "UNC_B2CMI_DIRECT2UPI_TAKEN", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of times D2K wasn't honoured even though the incoming request had d2k set for non cisgress txn", + "Counter": "0,1,2,3", + "EventCode": "0x1C", + "EventName": "UNC_B2CMI_DIRECT2UPI_TXN_OVERRIDE", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Hit Clean", + "Counter": "0,1,2,3", + "EventCode": "0x1D", + "EventName": "UNC_B2CMI_DIRECTORY_HIT.CLEAN", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x38", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in A State", + "Counter": "0,1,2,3", + "EventCode": "0x1D", + "EventName": "UNC_B2CMI_DIRECTORY_HIT.CLEAN_A", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in I State", + "Counter": "0,1,2,3", + "EventCode": "0x1D", + "EventName": "UNC_B2CMI_DIRECTORY_HIT.CLEAN_I", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in S State", + "Counter": "0,1,2,3", + "EventCode": "0x1D", + "EventName": "UNC_B2CMI_DIRECTORY_HIT.CLEAN_S", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Hit Dirty (modified)", + "Counter": "0,1,2,3", + "EventCode": "0x1D", + "EventName": "UNC_B2CMI_DIRECTORY_HIT.DIRTY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x7", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in A State", + "Counter": "0,1,2,3", + "EventCode": "0x1D", + "EventName": "UNC_B2CMI_DIRECTORY_HIT.DIRTY_A", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in I State", + "Counter": "0,1,2,3", + "EventCode": "0x1D", + "EventName": "UNC_B2CMI_DIRECTORY_HIT.DIRTY_I", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in S State", + "Counter": "0,1,2,3", + "EventCode": "0x1D", + "EventName": "UNC_B2CMI_DIRECTORY_HIT.DIRTY_S", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of 1lm or 2lm hit read data returns to egress with any directory to non persistent memory", + "Counter": "0,1,2,3", + "EventCode": "0x20", + "EventName": "UNC_B2CMI_DIRECTORY_LOOKUP.ANY", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of 1lm or 2lm hit read data returns to egress with directory A to non persistent memory", + "Counter": "0,1,2,3", + "EventCode": "0x20", + "EventName": "UNC_B2CMI_DIRECTORY_LOOKUP.STATE_A", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of 1lm or 2lm hit read data returns to egress with directory I to non persistent memory", + "Counter": "0,1,2,3", + "EventCode": "0x20", + "EventName": "UNC_B2CMI_DIRECTORY_LOOKUP.STATE_I", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the number of 1lm or 2lm hit read data returns to egress with directory S to non persistent memory", + "Counter": "0,1,2,3", + "EventCode": "0x20", + "EventName": "UNC_B2CMI_DIRECTORY_LOOKUP.STATE_S", + "PerPkg": "1", + "PublicDescription": "Counts the number of 1lm or 2lm hit read data returns to egress with directory S to non persistent memory", + "UMask": "0x4", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Miss Clean", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_B2CMI_DIRECTORY_MISS.CLEAN", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x38", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in A State", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_B2CMI_DIRECTORY_MISS.CLEAN_A", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in I State", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_B2CMI_DIRECTORY_MISS.CLEAN_I", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in S State", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_B2CMI_DIRECTORY_MISS.CLEAN_S", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Miss Dirty (modified)", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_B2CMI_DIRECTORY_MISS.DIRTY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x7", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in A State", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_B2CMI_DIRECTORY_MISS.DIRTY_A", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in I State", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_B2CMI_DIRECTORY_MISS.DIRTY_I", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in S State", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_B2CMI_DIRECTORY_MISS.DIRTY_S", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Any A2I Transition", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.A2I", + "PerPkg": "1", + "UMask": "0x320", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Any A2S Transition", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.A2S", + "PerPkg": "1", + "UMask": "0x340", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts cisgress directory updates", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.ANY", + "PerPkg": "1", + "UMask": "0x301", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts any 1lm or 2lm hit data return that would result in directory update to non persistent memory (DRAM)", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.HIT_ANY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x101", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory update in near memory to the A state", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.HIT_X2A", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x114", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory update in near memory to the I state", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.HIT_X2I", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x128", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory update in near memory to the S state", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.HIT_X2S", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x142", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Any I2A Transition", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.I2A", + "PerPkg": "1", + "UMask": "0x304", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Any I2S Transition", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.I2S", + "PerPkg": "1", + "UMask": "0x302", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory update in far memory to the A state", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.MISS_X2A", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x214", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory update in far memory to the I state", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.MISS_X2I", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x228", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory update in far memory to the S state", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.MISS_X2S", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x242", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Any S2A Transition", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.S2A", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x310", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Any S2I Transition", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.S2I", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x308", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory update to the A state", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.X2A", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x314", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory update to the I state", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.X2I", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x328", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Directory update to the S state", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_B2CMI_DIRECTORY_UPDATE.X2S", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x342", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts any read", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "UNC_B2CMI_IMC_READS.ALL", + "PerPkg": "1", + "UMask": "0x104", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts normal reads issue to CMI", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "UNC_B2CMI_IMC_READS.NORMAL", + "PerPkg": "1", + "UMask": "0x101", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Count reads to NM region", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "UNC_B2CMI_IMC_READS.TO_DDR_AS_CACHE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x110", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts reads to 1lm non persistent memory regions", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "UNC_B2CMI_IMC_READS.TO_DDR_AS_MEM", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x108", + "Unit": "B2CMI" + }, + { + "BriefDescription": "All Writes - All Channels", + "Counter": "0,1,2,3", + "EventCode": "0x25", + "EventName": "UNC_B2CMI_IMC_WRITES.ALL", + "PerPkg": "1", + "UMask": "0x110", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Full Non-ISOCH - All Channels", + "Counter": "0,1,2,3", + "EventCode": "0x25", + "EventName": "UNC_B2CMI_IMC_WRITES.FULL", + "PerPkg": "1", + "UMask": "0x101", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Non-Inclusive - All Channels", + "Counter": "0,1,2,3", + "EventCode": "0x25", + "EventName": "UNC_B2CMI_IMC_WRITES.NI", + "Experimental": "1", + "PerPkg": "1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Non-Inclusive Miss - All Channels", + "Counter": "0,1,2,3", + "EventCode": "0x25", + "EventName": "UNC_B2CMI_IMC_WRITES.NI_MISS", + "Experimental": "1", + "PerPkg": "1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Partial Non-ISOCH - All Channels", + "Counter": "0,1,2,3", + "EventCode": "0x25", + "EventName": "UNC_B2CMI_IMC_WRITES.PARTIAL", + "PerPkg": "1", + "UMask": "0x102", + "Unit": "B2CMI" + }, + { + "BriefDescription": "DDR, acting as Cache - All Channels", + "Counter": "0,1,2,3", + "EventCode": "0x25", + "EventName": "UNC_B2CMI_IMC_WRITES.TO_DDR_AS_CACHE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x140", + "Unit": "B2CMI" + }, + { + "BriefDescription": "DDR - All Channels", + "Counter": "0,1,2,3", + "EventCode": "0x25", + "EventName": "UNC_B2CMI_IMC_WRITES.TO_DDR_AS_MEM", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x120", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Prefetch CAM Inserts : UPI - Ch 0", + "Counter": "0,1,2,3", + "EventCode": "0x56", + "EventName": "UNC_B2CMI_PREFCAM_INSERTS.CH0_UPI", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Prefetch CAM Inserts : XPT - Ch 0", + "Counter": "0,1,2,3", + "EventCode": "0x56", + "EventName": "UNC_B2CMI_PREFCAM_INSERTS.CH0_XPT", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Prefetch CAM Inserts : UPI - All Channels", + "Counter": "0,1,2,3", + "EventCode": "0x56", + "EventName": "UNC_B2CMI_PREFCAM_INSERTS.UPI_ALLCH", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Prefetch CAM Inserts : XPT -All Channels", + "Counter": "0,1,2,3", + "EventCode": "0x56", + "EventName": "UNC_B2CMI_PREFCAM_INSERTS.XPT_ALLCH", + "PerPkg": "1", + "PublicDescription": "Prefetch CAM Inserts : XPT - All Channels", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Prefetch CAM Occupancy : Channel 0", + "Counter": "0,1,2,3", + "EventCode": "0x54", + "EventName": "UNC_B2CMI_PREFCAM_OCCUPANCY.CH0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm reads and WRNI which were a hit", + "Counter": "0,1,2,3", + "EventCode": "0x1F", + "EventName": "UNC_B2CMI_TAG_HIT.ALL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xf", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm reads which were a hit clean", + "Counter": "0,1,2,3", + "EventCode": "0x1F", + "EventName": "UNC_B2CMI_TAG_HIT.RD_CLEAN", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm reads which were a hit dirty", + "Counter": "0,1,2,3", + "EventCode": "0x1F", + "EventName": "UNC_B2CMI_TAG_HIT.RD_DIRTY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm WRNI which were a hit clean", + "Counter": "0,1,2,3", + "EventCode": "0x1F", + "EventName": "UNC_B2CMI_TAG_HIT.WR_CLEAN", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm WRNI which were a hit dirty", + "Counter": "0,1,2,3", + "EventCode": "0x1F", + "EventName": "UNC_B2CMI_TAG_HIT.WR_DIRTY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm second way read miss for a WrNI", + "Counter": "0,1,2,3", + "EventCode": "0x4B", + "EventName": "UNC_B2CMI_TAG_MISS.CLEAN", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x5", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm second way read miss for a WrNI", + "Counter": "0,1,2,3", + "EventCode": "0x4B", + "EventName": "UNC_B2CMI_TAG_MISS.DIRTY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm second way read miss for a Rd", + "Counter": "0,1,2,3", + "EventCode": "0x4B", + "EventName": "UNC_B2CMI_TAG_MISS.RD_2WAY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm reads which were a miss and the cache line is unmodified", + "Counter": "0,1,2,3", + "EventCode": "0x4B", + "EventName": "UNC_B2CMI_TAG_MISS.RD_CLEAN", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm reads which were a miss and the cache line is modified", + "Counter": "0,1,2,3", + "EventCode": "0x4B", + "EventName": "UNC_B2CMI_TAG_MISS.RD_DIRTY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm second way read miss for a WrNI", + "Counter": "0,1,2,3", + "EventCode": "0x4B", + "EventName": "UNC_B2CMI_TAG_MISS.WR_2WAY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm WRNI which were a miss and the cache line is unmodified", + "Counter": "0,1,2,3", + "EventCode": "0x4B", + "EventName": "UNC_B2CMI_TAG_MISS.WR_CLEAN", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Counts the 2lm WRNI which were a miss and the cache line is modified", + "Counter": "0,1,2,3", + "EventCode": "0x4B", + "EventName": "UNC_B2CMI_TAG_MISS.WR_DIRTY", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Tracker Inserts : Channel 0", + "Counter": "0,1,2,3", + "EventCode": "0x32", + "EventName": "UNC_B2CMI_TRACKER_INSERTS.CH0", + "PerPkg": "1", + "UMask": "0x104", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Tracker Occupancy : Channel 0", + "Counter": "0,1,2,3", + "EventCode": "0x33", + "EventName": "UNC_B2CMI_TRACKER_OCCUPANCY.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "Write Tracker Inserts : Channel 0", + "Counter": "0,1,2,3", + "EventCode": "0x40", + "EventName": "UNC_B2CMI_WR_TRACKER_INSERTS.CH0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2CMI" + }, + { + "BriefDescription": "UNC_B2HOT_CLOCKTICKS", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_B2HOT_CLOCKTICKS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "B2HOT" + }, + { + "BriefDescription": "Number of uclks in domain", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_B2UPI_CLOCKTICKS", + "PerPkg": "1", + "Unit": "B2UPI" + }, + { + "BriefDescription": "Total Write Cache Occupancy : Mem", + "Counter": "0,1,2,3", + "EventCode": "0x0F", + "EventName": "UNC_I_CACHE_TOTAL_OCCUPANCY.MEM", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "IRP" + }, + { + "BriefDescription": "IRP Clockticks", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_I_CLOCKTICKS", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "Inbound read requests received by the IRP and inserted into the FAF queue", + "Counter": "0,1,2,3", + "EventCode": "0x18", + "EventName": "UNC_I_FAF_INSERTS", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "FAF occupancy", + "Counter": "0,1,2,3", + "EventCode": "0x19", + "EventName": "UNC_I_FAF_OCCUPANCY", + "Experimental": "1", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Fastpath Rejects", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_I_MISC0.FAST_REJ", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Fastpath Requests", + "Counter": "0,1,2,3", + "EventCode": "0x1E", + "EventName": "UNC_I_MISC0.FAST_REQ", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "IRP" + }, + { + "BriefDescription": "Misc Events - Set 1 : Lost Forward : Snoop pulled away ownership before a write was committed", + "Counter": "0,1,2,3", + "EventCode": "0x1F", + "EventName": "UNC_I_MISC1.LOST_FWD", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "IRP" + }, + { + "BriefDescription": "Misc Events - Set 1 : Received Invalid : Secondary received a transfer that did not have sufficient MESI state", + "Counter": "0,1,2,3", + "EventCode": "0x1F", + "EventName": "UNC_I_MISC1.SEC_RCVD_INVLD", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Hit E/S responses", + "Counter": "0,1,2,3", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.ALL_HIT_ES", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x74", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Hit I responses", + "Counter": "0,1,2,3", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.ALL_HIT_I", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x72", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Hit M responses", + "Counter": "0,1,2,3", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.ALL_HIT_M", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x78", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop miss responses", + "Counter": "0,1,2,3", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.ALL_MISS", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x71", + "Unit": "IRP" + }, + { + "BriefDescription": "Inbound write (fast path) requests to coherent memory, received by the IRP resulting in write ownership requests issued by IRP to the mesh.", + "Counter": "0,1,2,3", + "EventCode": "0x11", + "EventName": "UNC_I_TRANSACTIONS.WR_PREF", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "IRP" + }, + { + "BriefDescription": "MDF Clockticks", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_MDF_CLOCKTICKS", + "PerPkg": "1", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of UPI LL clock cycles while the event is enabled", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_UPI_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Number of kfclks", + "Unit": "UPI" + }, + { + "BriefDescription": "Cycles in L1 : Number of UPI qfclk cycles spent in L1 power mode. L1 is a mode that totally shuts down a UPI link. Use edge detect to count the number of instances when the UPI link entered L1. Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another. Because L1 totally shuts down the link, it takes a good amount of time to exit this mode.", + "Counter": "0,1,2,3", + "EventCode": "0x21", + "EventName": "UNC_UPI_L1_POWER_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Non-Coherent Bypass", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.NCB", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xe", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Non-Coherent Bypass, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.NCB_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10e", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Non-Coherent Standard", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.NCS", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xf", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Non-Coherent Standard, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.NCS_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10f", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Request", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.REQ", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Request, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.REQ_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x108", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Response - Conflict", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.RSPCNFLT", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1aa", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Response - Invalid", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.RSPI", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x12a", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Response - Data", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.RSP_DATA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xc", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Response - Data, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.RSP_DATA_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10c", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Response - No Data", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.RSP_NODATA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Response - No Data, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.RSP_NODATA_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10a", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Snoop", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.SNP", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x9", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Snoop, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.SNP_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x109", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Writeback", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.WB", + "PerPkg": "1", + "UMask": "0xd", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Writeback, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.WB_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10d", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : All Data : Shows legal flit time (hides impact of L0p and L0c).", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.ALL_DATA", + "PerPkg": "1", + "UMask": "0xf", + "Unit": "UPI" + }, + { + "BriefDescription": "Null FLITs received from any slot", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.ALL_NULL", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : Null FLITs received from any slot", + "UMask": "0x27", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Data : Shows legal flit time (hides impact of L0p and L0c). : Count Data Flits (which consume all slots), but how much to count is based on Slot0-2 mask, so count can be 0-3 depending on which slots are enabled for counting..", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.DATA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Idle : Shows legal flit time (hides impact of L0p and L0c).", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.IDLE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x47", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : LLCRD Not Empty : Shows legal flit time (hides impact of L0p and L0c). : Enables counting of LLCRD (with non-zero payload). This only applies to slot 2 since LLCRD is only allowed in slot 2", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.LLCRD", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : LLCTRL : Shows legal flit time (hides impact of L0p and L0c). : Equivalent to an idle packet. Enables counting of slot 0 LLCTRL messages.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.LLCTRL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : All Non Data : Shows legal flit time (hides impact of L0p and L0c).", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.NON_DATA", + "PerPkg": "1", + "UMask": "0x97", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Slot NULL or LLCRD Empty : Shows legal flit time (hides impact of L0p and L0c). : LLCRD with all zeros is treated as NULL. Slot 1 is not treated as NULL if slot 0 is a dual slot. This can apply to slot 0,1, or 2.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.NULL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Protocol Header : Shows legal flit time (hides impact of L0p and L0c). : Enables count of protocol headers in slot 0,1,2 (depending on slot uMask bits)", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.PROTHDR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Slot 0 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 0 - Other mask bits determine types of headers to count.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.SLOT0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Slot 1 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 1 - Other mask bits determine types of headers to count.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.SLOT1", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Slot 2 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 2 - Other mask bits determine types of headers to count.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.SLOT2", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Flit Buffer Allocations : Slot 0 : Number of allocations into the UPI Rx Flit Buffer. Generally, when data is transmitted across UPI, it will bypass the RxQ and pass directly to the ring interface. If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency. This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.", + "Counter": "0,1,2,3", + "EventCode": "0x30", + "EventName": "UNC_UPI_RxL_INSERTS.SLOT0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Flit Buffer Allocations : Slot 1 : Number of allocations into the UPI Rx Flit Buffer. Generally, when data is transmitted across UPI, it will bypass the RxQ and pass directly to the ring interface. If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency. This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.", + "Counter": "0,1,2,3", + "EventCode": "0x30", + "EventName": "UNC_UPI_RxL_INSERTS.SLOT1", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Flit Buffer Allocations : Slot 2 : Number of allocations into the UPI Rx Flit Buffer. Generally, when data is transmitted across UPI, it will bypass the RxQ and pass directly to the ring interface. If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency. This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.", + "Counter": "0,1,2,3", + "EventCode": "0x30", + "EventName": "UNC_UPI_RxL_INSERTS.SLOT2", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Occupancy - All Packets : Slot 0", + "Counter": "0,1,2,3", + "EventCode": "0x32", + "EventName": "UNC_UPI_RxL_OCCUPANCY.SLOT0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Occupancy - All Packets : Slot 1", + "Counter": "0,1,2,3", + "EventCode": "0x32", + "EventName": "UNC_UPI_RxL_OCCUPANCY.SLOT1", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Occupancy - All Packets : Slot 2", + "Counter": "0,1,2,3", + "EventCode": "0x32", + "EventName": "UNC_UPI_RxL_OCCUPANCY.SLOT2", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "Cycles in L0p", + "Counter": "0,1,2,3", + "EventCode": "0x27", + "EventName": "UNC_UPI_TxL0P_POWER_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_POWER_CYCLES_LL_ENTER", + "Counter": "0,1,2,3", + "EventCode": "0x28", + "EventName": "UNC_UPI_TxL0P_POWER_CYCLES_LL_ENTER", + "Experimental": "1", + "PerPkg": "1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_POWER_CYCLES_M3_EXIT", + "Counter": "0,1,2,3", + "EventCode": "0x29", + "EventName": "UNC_UPI_TxL0P_POWER_CYCLES_M3_EXIT", + "Experimental": "1", + "PerPkg": "1", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Bypass", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.NCB", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xe", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Bypass, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.NCB_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10e", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Standard", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.NCS", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xf", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Standard, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.NCS_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10f", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Request", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.REQ", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Request, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.REQ_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x108", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Response - Conflict", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.RSPCNFLT", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1aa", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Response - Invalid", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.RSPI", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x12a", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Response - Data", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.RSP_DATA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xc", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Response - Data, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.RSP_DATA_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10c", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Response - No Data", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.RSP_NODATA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Response - No Data, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.RSP_NODATA_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10a", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Snoop", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.SNP", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x9", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Snoop, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.SNP_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x109", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Writeback", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.WB", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xd", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Writeback, Match Opcode", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.WB_OPC", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10d", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : All Data : Counts number of data flits across this UPI link.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.ALL_DATA", + "PerPkg": "1", + "UMask": "0xf", + "Unit": "UPI" + }, + { + "BriefDescription": "All Null Flits", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.ALL_NULL", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : Idle", + "UMask": "0x27", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Data : Shows legal flit time (hides impact of L0p and L0c). : Count Data Flits (which consume all slots), but how much to count is based on Slot0-2 mask, so count can be 0-3 depending on which slots are enabled for counting..", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.DATA", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Idle : Shows legal flit time (hides impact of L0p and L0c).", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.IDLE", + "PerPkg": "1", + "UMask": "0x47", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : LLCRD Not Empty : Shows legal flit time (hides impact of L0p and L0c). : Enables counting of LLCRD (with non-zero payload). This only applies to slot 2 since LLCRD is only allowed in slot 2", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.LLCRD", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : LLCTRL : Shows legal flit time (hides impact of L0p and L0c). : Equivalent to an idle packet. Enables counting of slot 0 LLCTRL messages.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.LLCTRL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : All Non Data : Shows legal flit time (hides impact of L0p and L0c).", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.NON_DATA", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : Null FLITs transmitted to any slot", + "UMask": "0x97", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Slot NULL or LLCRD Empty : Shows legal flit time (hides impact of L0p and L0c). : LLCRD with all zeros is treated as NULL. Slot 1 is not treated as NULL if slot 0 is a dual slot. This can apply to slot 0,1, or 2.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.NULL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Protocol Header : Shows legal flit time (hides impact of L0p and L0c). : Enables count of protocol headers in slot 0,1,2 (depending on slot uMask bits)", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.PROTHDR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Slot 0 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 0 - Other mask bits determine types of headers to count.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.SLOT0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Slot 1 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 1 - Other mask bits determine types of headers to count.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.SLOT1", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Slot 2 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 2 - Other mask bits determine types of headers to count.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.SLOT2", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "Message Received : Doorbell", + "Counter": "0,1", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.DOORBELL_RCVD", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UBOX" + }, + { + "BriefDescription": "Message Received : Interrupt", + "Counter": "0,1", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.INT_PRIO", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Message Received : Interrupt : Interrupts", + "UMask": "0x10", + "Unit": "UBOX" + }, + { + "BriefDescription": "Message Received : IPI", + "Counter": "0,1", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.IPI_RCVD", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Message Received : IPI : Inter Processor Interrupts", + "UMask": "0x4", + "Unit": "UBOX" + }, + { + "BriefDescription": "Message Received : MSI", + "Counter": "0,1", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.MSI_RCVD", + "PerPkg": "1", + "PublicDescription": "Message Received : MSI : Message Signaled Interrupts - interrupts sent by devices (including PCIe via IOxAPIC) (Socket Mode only)", + "UMask": "0x2", + "Unit": "UBOX" + }, + { + "BriefDescription": "Message Received : VLW", + "Counter": "0,1", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.VLW_RCVD", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Message Received : VLW : Virtual Logical Wire (legacy) message were received from Uncore.", + "UMask": "0x1", + "Unit": "UBOX" + } +] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-io.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-io.json new file mode 100644 index 000000000000..77f9c4cee952 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-io.json @@ -0,0 +1,1925 @@ +[ + { + "BriefDescription": "IIO Clockticks", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_IIO_CLOCKTICKS", + "PerPkg": "1", + "PortMask": "0x000", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIE Completion Buffer Inserts. Counts once per 64 byte read issued from this PCIE device.", + "Counter": "0,1,2,3", + "EventCode": "0xC2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.ALL_PARTS", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIE Completion Buffer Inserts. Counts once per 64 byte read issued from this PCIE device.", + "Counter": "0,1,2,3", + "EventCode": "0xC2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART0", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIE Completion Buffer Inserts. Counts once per 64 byte read issued from this PCIE device.", + "Counter": "0,1,2,3", + "EventCode": "0xC2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART1", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIE Completion Buffer Inserts. Counts once per 64 byte read issued from this PCIE device.", + "Counter": "0,1,2,3", + "EventCode": "0xC2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART2", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIE Completion Buffer Inserts. Counts once per 64 byte read issued from this PCIE device.", + "Counter": "0,1,2,3", + "EventCode": "0xC2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART3", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIE Completion Buffer Inserts. Counts once per 64 byte read issued from this PCIE device.", + "Counter": "0,1,2,3", + "EventCode": "0xC2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART4", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIE Completion Buffer Inserts. Counts once per 64 byte read issued from this PCIE device.", + "Counter": "0,1,2,3", + "EventCode": "0xC2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART5", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIE Completion Buffer Inserts. Counts once per 64 byte read issued from this PCIE device.", + "Counter": "0,1,2,3", + "EventCode": "0xC2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART6", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIE Completion Buffer Inserts. Counts once per 64 byte read issued from this PCIE device.", + "Counter": "0,1,2,3", + "EventCode": "0xC2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART7", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Count of allocations in the completion buffer", + "Counter": "2,3", + "EventCode": "0xD5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.ALL_PARTS", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0xff", + "Unit": "IIO" + }, + { + "BriefDescription": "Count of allocations in the completion buffer", + "Counter": "2,3", + "EventCode": "0xD5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART0", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Count of allocations in the completion buffer", + "Counter": "2,3", + "EventCode": "0xD5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART1", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Count of allocations in the completion buffer", + "Counter": "2,3", + "EventCode": "0xD5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART2", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Count of allocations in the completion buffer", + "Counter": "2,3", + "EventCode": "0xD5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART3", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Count of allocations in the completion buffer", + "Counter": "2,3", + "EventCode": "0xD5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART4", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": "Count of allocations in the completion buffer", + "Counter": "2,3", + "EventCode": "0xD5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART5", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": "Count of allocations in the completion buffer", + "Counter": "2,3", + "EventCode": "0xD5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART6", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x40", + "Unit": "IIO" + }, + { + "BriefDescription": "Count of allocations in the completion buffer", + "Counter": "2,3", + "EventCode": "0xD5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART7", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reporting completion of Card read from Core DRAM", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.ALL_PARTS", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reporting completion of Card read from Core DRAM", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART0", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reporting completion of Card read from Core DRAM", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART1", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reporting completion of Card read from Core DRAM", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART2", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reporting completion of Card read from Core DRAM", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART3", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reporting completion of Card read from Core DRAM", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART4", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reporting completion of Card read from Core DRAM", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART5", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reporting completion of Card read from Core DRAM", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART6", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reporting completion of Card read from Core DRAM", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART7", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.ALL_PARTS", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card.", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_READ.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card.", + "Counter": "2,3", + "EventCode": "0xC0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_WRITE.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Counts once for every 4 bytes read from this card to memory. This event does include reads to IO.", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x02", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x04", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x08", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x10", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x20", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x40", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x80", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Counts once for every 4 bytes written from this card to memory. This event does include writes to IO.", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x02", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x04", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x08", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x10", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x20", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x40", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Four byte data request of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x80", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_READ.PART0", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_READ.PART1", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_READ.PART2", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_READ.PART3", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_READ.PART4", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_READ.PART5", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_READ.PART6", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_READ.PART7", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Counts once for every 4 bytes written from this card to a peer device's IO space.", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.ALL_PARTS", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART0", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART1", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART2", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART3", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART4", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART5", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART6", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART7", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "IOTLB Hits to a 1G Page", + "Counter": "0,1,2,3", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.1G_HITS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": "IOTLB Hits to a 2M Page", + "Counter": "0,1,2,3", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.2M_HITS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "IOTLB Hits to a 4K Page", + "Counter": "0,1,2,3", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.4K_HITS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "IOTLB lookups all", + "Counter": "0,1,2,3", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.ALL_LOOKUPS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Context cache hits", + "Counter": "0,1,2,3", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.CTXT_CACHE_HITS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Context cache lookups", + "Counter": "0,1,2,3", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.CTXT_CACHE_LOOKUPS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x40", + "Unit": "IIO" + }, + { + "BriefDescription": "IOTLB lookups first", + "Counter": "0,1,2,3", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.FIRST_LOOKUPS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "IOTLB Fills (same as IOTLB miss)", + "Counter": "0,1,2,3", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.MISSES", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": "IOMMU memory access (both low and high priority)", + "Counter": "0,1,2,3", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.NUM_MEM_ACCESSES", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0xc0", + "Unit": "IIO" + }, + { + "BriefDescription": "IOMMU high priority memory access", + "Counter": "0,1,2,3", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.NUM_MEM_ACCESSES_HIGH", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "IOMMU low priority memory access", + "Counter": "0,1,2,3", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.NUM_MEM_ACCESSES_LOW", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x40", + "Unit": "IIO" + }, + { + "BriefDescription": "Second Level Page Walk Cache Hit to a 1G page", + "Counter": "0,1,2,3", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.SLPWC_1G_HITS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Second Level Page Walk Cache Hit to a 256T page", + "Counter": "0,1,2,3", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.SLPWC_256T_HITS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": "Second Level Page Walk Cache Hit to a 2M page", + "Counter": "0,1,2,3", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.SLPWC_2M_HITS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Second Level Page Walk Cache Hit to a 512G page", + "Counter": "0,1,2,3", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.SLPWC_512G_HITS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Second Level Page Walk Cache fill", + "Counter": "0,1,2,3", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.SLPWC_CACHE_FILLS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": "Second Level Page Walk Cache lookup", + "Counter": "0,1,2,3", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.SLPWC_CACHE_LOOKUPS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Cycles PWT full", + "Counter": "0,1,2,3", + "EventCode": "0x43", + "EventName": "UNC_IIO_IOMMU3.CYC_PWT_FULL", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Interrupt Entry cache hit", + "Counter": "0,1,2,3", + "EventCode": "0x43", + "EventName": "UNC_IIO_IOMMU3.INT_CACHE_HITS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Interrupt Entry cache lookup", + "Counter": "0,1,2,3", + "EventCode": "0x43", + "EventName": "UNC_IIO_IOMMU3.INT_CACHE_LOOKUPS", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x40", + "Unit": "IIO" + }, + { + "BriefDescription": "Context Cache invalidation events", + "Counter": "0,1,2,3", + "EventCode": "0x43", + "EventName": "UNC_IIO_IOMMU3.NUM_INVAL_CTXT_CACHE", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Interrupt Entry Cache invalidation events", + "Counter": "0,1,2,3", + "EventCode": "0x43", + "EventName": "UNC_IIO_IOMMU3.NUM_INVAL_INT_CACHE", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": "IOTLB invalidation events", + "Counter": "0,1,2,3", + "EventCode": "0x43", + "EventName": "UNC_IIO_IOMMU3.NUM_INVAL_IOTLB", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PASID Cache invalidation events", + "Counter": "0,1,2,3", + "EventCode": "0x43", + "EventName": "UNC_IIO_IOMMU3.NUM_INVAL_PASID_CACHE", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to UNC_IIO_NUM_OUTSTANDING_REQ_FROM_CPU.TO_IO]", + "Counter": "2,3", + "Deprecated": "1", + "EventCode": "0xc5", + "EventName": "UNC_IIO_NUM_OUSTANDING_REQ_FROM_CPU.TO_IO", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Occupancy of outbound request queue : To device : Counts number of outbound requests/completions IIO is currently processing [This event is alias to UNC_IIO_NUM_OUSTANDING_REQ_FROM_CPU.TO_IO]", + "Counter": "2,3", + "EventCode": "0xc5", + "EventName": "UNC_IIO_NUM_OUTSTANDING_REQ_FROM_CPU.TO_IO", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Passing data to be written", + "Counter": "0,1,2,3", + "EventCode": "0x88", + "EventName": "UNC_IIO_NUM_OUTSTANDING_REQ_OF_CPU.DATA", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": "Issuing final read or write of line", + "Counter": "0,1,2,3", + "EventCode": "0x88", + "EventName": "UNC_IIO_NUM_OUTSTANDING_REQ_OF_CPU.FINAL_RD_WR", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Processing response from IOMMU", + "Counter": "0,1,2,3", + "EventCode": "0x88", + "EventName": "UNC_IIO_NUM_OUTSTANDING_REQ_OF_CPU.IOMMU_HIT", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Issuing to IOMMU", + "Counter": "0,1,2,3", + "EventCode": "0x88", + "EventName": "UNC_IIO_NUM_OUTSTANDING_REQ_OF_CPU.IOMMU_REQ", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Request Ownership", + "Counter": "0,1,2,3", + "EventCode": "0x88", + "EventName": "UNC_IIO_NUM_OUTSTANDING_REQ_OF_CPU.REQ_OWN", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Writing line", + "Counter": "0,1,2,3", + "EventCode": "0x88", + "EventName": "UNC_IIO_NUM_OUTSTANDING_REQ_OF_CPU.WR", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.ABORT", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.ABORT", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.CONFINED_P2P", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.CONFINED_P2P", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x40", + "Unit": "IIO" + }, + { + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.LOC_P2P", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.LOC_P2P", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MCAST", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MCAST", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MEM", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MEM", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MSGB", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MSGB", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.REM_P2P", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.REM_P2P", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.UBOX", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.UBOX", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Posted requests sent by the integrated IO (IIO) controller to the Ubox, useful for counting message signaled interrupts (MSI).", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.UBOX_POSTED", + "FCMask": "0x01", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "All 9 bits of Page Walk Tracker Occupancy", + "Counter": "0,1,2,3", + "EventCode": "0x42", + "EventName": "UNC_IIO_PWT_OCCUPANCY", + "Experimental": "1", + "PerPkg": "1", + "PortMask": "0x000", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) reading from this card.", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_READ.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card.", + "Counter": "2,3", + "EventCode": "0xC1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_WRITE.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FF", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_READ.PART0", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_READ.PART1", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_READ.PART2", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_READ.PART3", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_READ.PART4", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_READ.PART5", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_READ.PART6", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_READ.PART7", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART0", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x001", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART1", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x002", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART2", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x004", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART3", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x008", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART4", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x010", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART5", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x020", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART6", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x040", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "Counter": "0,1", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART7", + "Experimental": "1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x080", + "UMask": "0x2", + "Unit": "IIO" + } +] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-memory.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-memory.json new file mode 100644 index 000000000000..8184c2b6b861 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-memory.json @@ -0,0 +1,883 @@ +[ + { + "BriefDescription": "DRAM Activate Count : Counts the number of DRAM Activate commands sent on this channel. Activate commands are issued to open up a page on the DRAM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_M_ACT_COUNT.ALL", + "PerPkg": "1", + "UMask": "0xf7", + "Unit": "IMC" + }, + { + "BriefDescription": "DRAM Activate Count : Read transaction on Page Empty or Page Miss : Counts the number of DRAM Activate commands sent on this channel. Activate commands are issued to open up a page on the DRAM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_M_ACT_COUNT.RD", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xf1", + "Unit": "IMC" + }, + { + "BriefDescription": "DRAM Activate Count : Underfill Read transaction on Page Empty or Page Miss : Counts the number of DRAM Activate commands sent on this channel. Activate commands are issued to open up a page on the DRAM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_M_ACT_COUNT.UFILL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xf4", + "Unit": "IMC" + }, + { + "BriefDescription": "DRAM Activate Count : Write transaction on Page Empty or Page Miss : Counts the number of DRAM Activate commands sent on this channel. Activate commands are issued to open up a page on the DRAM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "Counter": "0,1,2,3", + "EventCode": "0x02", + "EventName": "UNC_M_ACT_COUNT.WR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xf2", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0, all CAS operations", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.ALL", + "PerPkg": "1", + "UMask": "0xff", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0, all reads", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.RD", + "PerPkg": "1", + "UMask": "0xcf", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0 regular reads", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.RD_NON_UNDERFILL", + "PerPkg": "1", + "UMask": "0xc3", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0 auto-precharge reads", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.RD_PRE_REG", + "PerPkg": "1", + "UMask": "0xc2", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0 auto-precharge underfill reads", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.RD_PRE_UNDERFILL", + "PerPkg": "1", + "UMask": "0xc8", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0 regular reads", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.RD_REG", + "PerPkg": "1", + "UMask": "0xc1", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0 underfill reads", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.RD_UNDERFILL", + "PerPkg": "1", + "UMask": "0xc4", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0 underfill reads", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.RD_UNDERFILL_ALL", + "PerPkg": "1", + "UMask": "0xcc", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0, all writes", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.WR", + "PerPkg": "1", + "UMask": "0xf0", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0 regular writes", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.WR_NONPRE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xd0", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 0 auto-precharge writes", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT_SCH0.WR_PRE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xe0", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1, all CAS operations", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.ALL", + "PerPkg": "1", + "UMask": "0xff", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1, all reads", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.RD", + "PerPkg": "1", + "UMask": "0xcf", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1 regular reads", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.RD_NON_UNDERFILL", + "PerPkg": "1", + "UMask": "0xc3", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1 auto-precharge reads", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.RD_PRE_REG", + "PerPkg": "1", + "UMask": "0xc2", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1 auto-precharge underfill reads", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.RD_PRE_UNDERFILL", + "PerPkg": "1", + "UMask": "0xc8", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1 regular reads", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.RD_REG", + "PerPkg": "1", + "UMask": "0xc1", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1 underfill reads", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.RD_UNDERFILL", + "PerPkg": "1", + "UMask": "0xc4", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1 underfill reads", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.RD_UNDERFILL_ALL", + "PerPkg": "1", + "UMask": "0xcc", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1, all writes", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.WR", + "PerPkg": "1", + "UMask": "0xf0", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1 regular writes", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.WR_NONPRE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xd0", + "Unit": "IMC" + }, + { + "BriefDescription": "CAS count for SubChannel 1 auto-precharge writes", + "Counter": "0,1,2,3", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_COUNT_SCH1.WR_PRE", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xe0", + "Unit": "IMC" + }, + { + "BriefDescription": "Number of DRAM DCLK clock cycles while the event is enabled. DCLK is 1/4 of DRAM data rate.", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_M_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "DRAM Clockticks", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "Number of DRAM HCLK clock cycles while the event is enabled", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_M_HCLOCKTICKS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "DRAM Clockticks", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles MR4 temp readings forced 2x refresh", + "Counter": "0,1,2,3", + "EventCode": "0xA7", + "EventName": "UNC_M_MR4_2XREF_CYCLES.SCH0_DIMM0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_MR4_2XREF_CYCLES.SCH0_DIMM0", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles MR4 temp readings forced 2x refresh", + "Counter": "0,1,2,3", + "EventCode": "0xA7", + "EventName": "UNC_M_MR4_2XREF_CYCLES.SCH0_DIMM1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_MR4_2XREF_CYCLES.SCH0_DIMM1", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles MR4 temp readings forced 2x refresh", + "Counter": "0,1,2,3", + "EventCode": "0xA7", + "EventName": "UNC_M_MR4_2XREF_CYCLES.SCH1_DIMM0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_MR4_2XREF_CYCLES.SCH1_DIMM0", + "UMask": "0x4", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles MR4 temp readings forced 2x refresh", + "Counter": "0,1,2,3", + "EventCode": "0xA7", + "EventName": "UNC_M_MR4_2XREF_CYCLES.SCH1_DIMM1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_MR4_2XREF_CYCLES.SCH1_DIMM1", + "UMask": "0x8", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles MR4 MRRs was triggered/running", + "Counter": "0,1,2,3", + "EventCode": "0xA6", + "EventName": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH0_DIMM0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH0_DIMM0", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles MR4 MRRs was triggered/running", + "Counter": "0,1,2,3", + "EventCode": "0xA6", + "EventName": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH0_DIMM1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH0_DIMM1", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles MR4 MRRs was triggered/running", + "Counter": "0,1,2,3", + "EventCode": "0xA6", + "EventName": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH1_DIMM0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH1_DIMM0", + "UMask": "0x4", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles MR4 MRRs was triggered/running", + "Counter": "0,1,2,3", + "EventCode": "0xA6", + "EventName": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH1_DIMM1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH1_DIMM1", + "UMask": "0x8", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles a given rank is in Power Down Mode", + "Counter": "0,1,2,3", + "EventCode": "0x47", + "EventName": "UNC_M_POWERDOWN_CYCLES.SCH0_RANK0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles a given rank is in Power Down Mode", + "Counter": "0,1,2,3", + "EventCode": "0x47", + "EventName": "UNC_M_POWERDOWN_CYCLES.SCH0_RANK1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles a given rank is in Power Down Mode", + "Counter": "0,1,2,3", + "EventCode": "0x47", + "EventName": "UNC_M_POWERDOWN_CYCLES.SCH0_RANK2", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x4", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles a given rank is in Power Down Mode", + "Counter": "0,1,2,3", + "EventCode": "0x47", + "EventName": "UNC_M_POWERDOWN_CYCLES.SCH0_RANK3", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x8", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles a given rank is in Power Down Mode", + "Counter": "0,1,2,3", + "EventCode": "0x47", + "EventName": "UNC_M_POWERDOWN_CYCLES.SCH1_RANK0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x10", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles a given rank is in Power Down Mode", + "Counter": "0,1,2,3", + "EventCode": "0x47", + "EventName": "UNC_M_POWERDOWN_CYCLES.SCH1_RANK1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x20", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles a given rank is in Power Down Mode", + "Counter": "0,1,2,3", + "EventCode": "0x47", + "EventName": "UNC_M_POWERDOWN_CYCLES.SCH1_RANK2", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x40", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles a given rank is in Power Down Mode", + "Counter": "0,1,2,3", + "EventCode": "0x47", + "EventName": "UNC_M_POWERDOWN_CYCLES.SCH1_RANK3", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x80", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles a given rank is in Power Down Mode and all pages are closed", + "Counter": "0,1,2,3", + "EventCode": "0x88", + "EventName": "UNC_M_POWER_CHANNEL_PPD_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at Critical level on specified DIMM and throttle level is zero.", + "Counter": "0,1,2,3", + "EventCode": "0x89", + "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES.SLOT0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at Critical level on specified DIMM and throttle level is zero.", + "Counter": "0,1,2,3", + "EventCode": "0x89", + "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES.SLOT1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "UNC_M_POWER_THROTTLE_CYCLES.BW_SLOT0", + "Counter": "0,1,2,3", + "EventCode": "0x46", + "EventName": "UNC_M_POWER_THROTTLE_CYCLES.BW_SLOT0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "UNC_M_POWER_THROTTLE_CYCLES.BW_SLOT1", + "Counter": "0,1,2,3", + "EventCode": "0x46", + "EventName": "UNC_M_POWER_THROTTLE_CYCLES.BW_SLOT1", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "MR4 temp reading is throttling", + "Counter": "0,1,2,3", + "EventCode": "0x46", + "EventName": "UNC_M_POWER_THROTTLE_CYCLES.MR4BLKEN", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x8", + "Unit": "IMC" + }, + { + "BriefDescription": "RAPL is throttling", + "Counter": "0,1,2,3", + "EventCode": "0x46", + "EventName": "UNC_M_POWER_THROTTLE_CYCLES.RAPLBLK", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x4", + "Unit": "IMC" + }, + { + "BriefDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.ALL", + "PerPkg": "1", + "UMask": "0xff", + "Unit": "IMC" + }, + { + "BriefDescription": "DRAM Precharge commands. : Precharge due to (?) : Counts the number of DRAM Precharge commands sent on this channel.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.PGT", + "PerPkg": "1", + "UMask": "0xf8", + "Unit": "IMC" + }, + { + "BriefDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.RD", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xf1", + "Unit": "IMC" + }, + { + "BriefDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.UFILL", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xf4", + "Unit": "IMC" + }, + { + "BriefDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "Counter": "0,1,2,3", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.WR", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xf2", + "Unit": "IMC" + }, + { + "BriefDescription": "Read buffer inserts on subchannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x17", + "EventName": "UNC_M_RDB_INSERTS.SCH0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "IMC" + }, + { + "BriefDescription": "Read buffer inserts on subchannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x17", + "EventName": "UNC_M_RDB_INSERTS.SCH1", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "IMC" + }, + { + "BriefDescription": "Read buffer occupancy on subchannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x1a", + "EventName": "UNC_M_RDB_OCCUPANCY_SCH0", + "PerPkg": "1", + "Unit": "IMC" + }, + { + "BriefDescription": "Read buffer occupancy on subchannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x1b", + "EventName": "UNC_M_RDB_OCCUPANCY_SCH1", + "PerPkg": "1", + "Unit": "IMC" + }, + { + "BriefDescription": "Read Pending Queue Allocations : Counts the number of allocations into the Read Pending Queue. This queue is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory. This includes both ISOCH and non-ISOCH requests.", + "Counter": "0,1,2,3", + "EventCode": "0x10", + "EventName": "UNC_M_RPQ_INSERTS.PCH0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x50", + "Unit": "IMC" + }, + { + "BriefDescription": "Read Pending Queue Allocations : Counts the number of allocations into the Read Pending Queue. This queue is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory. This includes both ISOCH and non-ISOCH requests.", + "Counter": "0,1,2,3", + "EventCode": "0x10", + "EventName": "UNC_M_RPQ_INSERTS.PCH1", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xa0", + "Unit": "IMC" + }, + { + "BriefDescription": "Read Pending Queue inserts for subchannel 0, pseudochannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x10", + "EventName": "UNC_M_RPQ_INSERTS.SCH0_PCH0", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "IMC" + }, + { + "BriefDescription": "Read Pending Queue inserts for subchannel 0, pseudochannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x10", + "EventName": "UNC_M_RPQ_INSERTS.SCH0_PCH1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "IMC" + }, + { + "BriefDescription": "Read Pending Queue inserts for subchannel 1, pseudochannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x10", + "EventName": "UNC_M_RPQ_INSERTS.SCH1_PCH0", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "IMC" + }, + { + "BriefDescription": "Read Pending Queue inserts for subchannel 1, pseudochannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x10", + "EventName": "UNC_M_RPQ_INSERTS.SCH1_PCH1", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "IMC" + }, + { + "BriefDescription": "Read pending queue occupancy for subchannel 0, pseudochannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x80", + "EventName": "UNC_M_RPQ_OCCUPANCY_SCH0_PCH0", + "PerPkg": "1", + "Unit": "IMC" + }, + { + "BriefDescription": "Read pending queue occupancy for subchannel 0, pseudochannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x81", + "EventName": "UNC_M_RPQ_OCCUPANCY_SCH0_PCH1", + "PerPkg": "1", + "Unit": "IMC" + }, + { + "BriefDescription": "Read pending queue occupancy for subchannel 1, pseudochannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x82", + "EventName": "UNC_M_RPQ_OCCUPANCY_SCH1_PCH0", + "PerPkg": "1", + "Unit": "IMC" + }, + { + "BriefDescription": "Read pending queue occupancy for subchannel 1, pseudochannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x83", + "EventName": "UNC_M_RPQ_OCCUPANCY_SCH1_PCH1", + "PerPkg": "1", + "Unit": "IMC" + }, + { + "BriefDescription": "subevent0 - # of cycles all ranks were in SR subevent1 - # of times all ranks went into SR subevent2 -# of times ps_sr_active asserted (SRE) subevent3 - # of times ps_sr_active deasserted (SRX) subevent4 - # of times PS-&>Refresh ps_sr_req asserted (SRE) subevent5 - # of times PS-&>Refresh ps_sr_req deasserted (SRX) subevent6 - # of cycles PSCtrlr FSM was in FATAL", + "Counter": "0,1,2,3", + "EventCode": "0x43", + "EventName": "UNC_M_SELF_REFRESH.ENTER_SUCCESS", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_SELF_REFRESH.ENTER_SUCCESS", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles all ranks were in SR", + "Counter": "0,1,2,3", + "EventCode": "0x43", + "EventName": "UNC_M_SELF_REFRESH.ENTER_SUCCESS_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "-", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at Critical level on specified DIMM", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_M_THROTTLE_CRIT_CYCLES.SLOT0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_THROTTLE_CRIT_CYCLES.SLOT0", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at Critical level on specified DIMM", + "Counter": "0,1,2,3", + "EventCode": "0x8e", + "EventName": "UNC_M_THROTTLE_CRIT_CYCLES.SLOT1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_THROTTLE_CRIT_CYCLES.SLOT1", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at High level on specified DIMM", + "Counter": "0,1,2,3", + "EventCode": "0x8d", + "EventName": "UNC_M_THROTTLE_HIGH_CYCLES.SLOT0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_THROTTLE_HIGH_CYCLES.SLOT0", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at High level on specified DIMM", + "Counter": "0,1,2,3", + "EventCode": "0x8d", + "EventName": "UNC_M_THROTTLE_HIGH_CYCLES.SLOT1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_THROTTLE_HIGH_CYCLES.SLOT1", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at Normal level on specified DIMM", + "Counter": "0,1,2,3", + "EventCode": "0x8b", + "EventName": "UNC_M_THROTTLE_LOW_CYCLES.SLOT0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_THROTTLE_LOW_CYCLES.SLOT0", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at Normal level on specified DIMM", + "Counter": "0,1,2,3", + "EventCode": "0x8b", + "EventName": "UNC_M_THROTTLE_LOW_CYCLES.SLOT1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_THROTTLE_LOW_CYCLES.SLOT1", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at Mid level on specified DIMM", + "Counter": "0,1,2,3", + "EventCode": "0x8c", + "EventName": "UNC_M_THROTTLE_MID_CYCLES.SLOT0", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_THROTTLE_MID_CYCLES.SLOT0", + "UMask": "0x1", + "Unit": "IMC" + }, + { + "BriefDescription": "# of cycles Throttling at Mid level on specified DIMM", + "Counter": "0,1,2,3", + "EventCode": "0x8c", + "EventName": "UNC_M_THROTTLE_MID_CYCLES.SLOT1", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "UNC_M_THROTTLE_MID_CYCLES.SLOT1", + "UMask": "0x2", + "Unit": "IMC" + }, + { + "BriefDescription": "Write Pending Queue Allocations", + "Counter": "0,1,2,3", + "EventCode": "0x22", + "EventName": "UNC_M_WPQ_INSERTS.PCH0", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0x50", + "Unit": "IMC" + }, + { + "BriefDescription": "Write Pending Queue Allocations", + "Counter": "0,1,2,3", + "EventCode": "0x22", + "EventName": "UNC_M_WPQ_INSERTS.PCH1", + "Experimental": "1", + "PerPkg": "1", + "UMask": "0xa0", + "Unit": "IMC" + }, + { + "BriefDescription": "Write Pending Queue inserts for subchannel 0, pseudochannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x22", + "EventName": "UNC_M_WPQ_INSERTS.SCH0_PCH0", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "IMC" + }, + { + "BriefDescription": "Write Pending Queue inserts for subchannel 0, pseudochannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x22", + "EventName": "UNC_M_WPQ_INSERTS.SCH0_PCH1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "IMC" + }, + { + "BriefDescription": "Write Pending Queue inserts for subchannel 1, pseudochannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x22", + "EventName": "UNC_M_WPQ_INSERTS.SCH1_PCH0", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "IMC" + }, + { + "BriefDescription": "Write Pending Queue inserts for subchannel 1, pseudochannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x22", + "EventName": "UNC_M_WPQ_INSERTS.SCH1_PCH1", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "IMC" + }, + { + "BriefDescription": "Write pending queue occupancy for subchannel 0, pseudochannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x84", + "EventName": "UNC_M_WPQ_OCCUPANCY_SCH0_PCH0", + "PerPkg": "1", + "Unit": "IMC" + }, + { + "BriefDescription": "Write pending queue occupancy for subchannel 0, pseudochannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x85", + "EventName": "UNC_M_WPQ_OCCUPANCY_SCH0_PCH1", + "PerPkg": "1", + "Unit": "IMC" + }, + { + "BriefDescription": "Write pending queue occupancy for subchannel 1, pseudochannel 0", + "Counter": "0,1,2,3", + "EventCode": "0x86", + "EventName": "UNC_M_WPQ_OCCUPANCY_SCH1_PCH0", + "PerPkg": "1", + "Unit": "IMC" + }, + { + "BriefDescription": "Write pending queue occupancy for subchannel 1, pseudochannel 1", + "Counter": "0,1,2,3", + "EventCode": "0x87", + "EventName": "UNC_M_WPQ_OCCUPANCY_SCH1_PCH1", + "PerPkg": "1", + "Unit": "IMC" + } +] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-power.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-power.json new file mode 100644 index 000000000000..9ea852ef190e --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/uncore-power.json @@ -0,0 +1,109 @@ +[ + { + "BriefDescription": "PCU Clockticks", + "Counter": "0,1,2,3", + "EventCode": "0x01", + "EventName": "UNC_P_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "PCU Clockticks: The PCU runs off a fixed 1 GHz clock. This event counts the number of pclk cycles measured while the counter was enabled. The pclk, like the Memory Controller's dclk, counts at a constant rate making it a good measure of actual wall time.", + "Unit": "PCU" + }, + { + "BriefDescription": "Thermal Strongest Upper Limit Cycles", + "Counter": "0,1,2,3", + "EventCode": "0x04", + "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Thermal Strongest Upper Limit Cycles : Number of cycles any frequency is reduced due to a thermal limit. Count only if throttling is occurring.", + "Unit": "PCU" + }, + { + "BriefDescription": "Power Strongest Upper Limit Cycles", + "Counter": "0,1,2,3", + "EventCode": "0x05", + "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Power Strongest Upper Limit Cycles : Counts the number of cycles when power is the upper limit on frequency.", + "Unit": "PCU" + }, + { + "BriefDescription": "Cycles spent changing Frequency", + "Counter": "0,1,2,3", + "EventCode": "0x74", + "EventName": "UNC_P_FREQ_TRANS_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Cycles spent changing Frequency : Counts the number of cycles when the system is changing frequency. This can not be filtered by thread ID. One can also use it with the occupancy counter that monitors number of threads in C0 to estimate the performance impact that frequency transitions had on the system.", + "Unit": "PCU" + }, + { + "BriefDescription": "Package C State Residency - C2E", + "Counter": "0,1,2,3", + "EventCode": "0x2b", + "EventName": "UNC_P_PKG_RESIDENCY_C2E_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Package C State Residency - C2E : Counts the number of cycles when the package was in C2E. This event can be used in conjunction with edge detect to count C2E entrances (or exits using invert). Residency events do not include transition times.", + "Unit": "PCU" + }, + { + "BriefDescription": "Package C State Residency - C6", + "Counter": "0,1,2,3", + "EventCode": "0x2d", + "EventName": "UNC_P_PKG_RESIDENCY_C6_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Package C State Residency - C6 : Counts the number of cycles when the package was in C6. This event can be used in conjunction with edge detect to count C6 entrances (or exits using invert). Residency events do not include transition times.", + "Unit": "PCU" + }, + { + "BriefDescription": "Number of cores in C0", + "Counter": "0,1,2,3", + "EventCode": "0x35", + "EventName": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C0", + "PerPkg": "1", + "PublicDescription": "Number of cores in C0 : This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with thresholding to generate histograms, or with other PCU events and occupancy triggering to capture other details.", + "Unit": "PCU" + }, + { + "BriefDescription": "Number of cores in C3", + "Counter": "0,1,2,3", + "EventCode": "0x36", + "EventName": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C3", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Number of cores in C3 : This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with thresholding to generate histograms, or with other PCU events and occupancy triggering to capture other details.", + "Unit": "PCU" + }, + { + "BriefDescription": "Number of cores in C6", + "Counter": "0,1,2,3", + "EventCode": "0x37", + "EventName": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C6", + "PerPkg": "1", + "PublicDescription": "Number of cores in C6 : This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with thresholding to generate histograms, or with other PCU events and occupancy triggering to capture other details.", + "Unit": "PCU" + }, + { + "BriefDescription": "External Prochot", + "Counter": "0,1,2,3", + "EventCode": "0x0a", + "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "External Prochot : Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip.", + "Unit": "PCU" + }, + { + "BriefDescription": "Internal Prochot", + "Counter": "0,1,2,3", + "EventCode": "0x09", + "EventName": "UNC_P_PROCHOT_INTERNAL_CYCLES", + "Experimental": "1", + "PerPkg": "1", + "PublicDescription": "Internal Prochot : Counts the number of cycles that we are in Internal PROCHOT mode. This mode is triggered when a sensor on the die determines that we are too hot and must throttle to avoid damaging the chip.", + "Unit": "PCU" + } +] diff --git a/tools/perf/pmu-events/arch/x86/clearwaterforest/virtual-memory.json b/tools/perf/pmu-events/arch/x86/clearwaterforest/virtual-memory.json index 78f2b835c1fa..a6a8733de235 100644 --- a/tools/perf/pmu-events/arch/x86/clearwaterforest/virtual-memory.json +++ b/tools/perf/pmu-events/arch/x86/clearwaterforest/virtual-memory.json @@ -1,4 +1,20 @@ [ + { + "BriefDescription": "Counts the number of page walks initiated by a demand load that missed the first and second level TLBs.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x08", + "EventName": "DTLB_LOAD_MISSES.MISS_CAUSED_WALK", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of first level TLB misses but second level hits due to a demand load that did not start a page walk. Accounts for all page sizes. Will result in a DTLB write from STLB.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x08", + "EventName": "DTLB_LOAD_MISSES.STLB_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, { "BriefDescription": "Counts the number of page walks completed due to load DTLB misses to any page size.", "Counter": "0,1,2,3,4,5,6,7", @@ -8,6 +24,32 @@ "SampleAfterValue": "1000003", "UMask": "0xe" }, + { + "BriefDescription": "Counts the number of page walks completed due to load DTLB misses to a 4K page.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x08", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K", + "PublicDescription": "Counts the number of page walks completed due to loads (including SW prefetches) whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 4K pages. Includes page walks that page fault.", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of page walks initiated by a store that missed the first and second level TLBs.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x49", + "EventName": "DTLB_STORE_MISSES.MISS_CAUSED_WALK", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of first level TLB misses but second level hits due to stores that did not start a page walk. Accounts for all page sizes. Will result in a DTLB write from STLB.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x49", + "EventName": "DTLB_STORE_MISSES.STLB_HIT", + "PublicDescription": "Counts the number of first level TLB misses but second level hits due to a demand load that did not start a page walk. Accounts for all page sizes. Will result in a DTLB write from STLB.", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, { "BriefDescription": "Counts the number of page walks completed due to store DTLB misses to any page size.", "Counter": "0,1,2,3,4,5,6,7", @@ -17,6 +59,31 @@ "SampleAfterValue": "1000003", "UMask": "0xe" }, + { + "BriefDescription": "Counts the number of page walks completed due to store DTLB misses to a 4K page.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x49", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K", + "PublicDescription": "Counts the number of page walks completed due to stores whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 4K pages. Includes page walks that page fault.", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of page walks initiated by a instruction fetch that missed the first and second level TLBs.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x85", + "EventName": "ITLB_MISSES.MISS_CAUSED_WALK", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of first level TLB misses but second level hits due to an instruction fetch that did not start a page walk. Account for all pages sizes. Will result in an ITLB write from STLB.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x85", + "EventName": "ITLB_MISSES.STLB_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, { "BriefDescription": "Counts the number of page walks completed due to instruction fetch misses to any page size.", "Counter": "0,1,2,3,4,5,6,7", @@ -25,5 +92,32 @@ "PublicDescription": "Counts the number of page walks completed due to instruction fetches whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to any page size. Includes page walks that page fault.", "SampleAfterValue": "1000003", "UMask": "0xe" + }, + { + "BriefDescription": "Counts the number of page walks completed due to instruction fetch misses to a 4K page.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x85", + "EventName": "ITLB_MISSES.WALK_COMPLETED_4K", + "PublicDescription": "Counts the number of page walks completed due to instruction fetches whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to 4K pages. Includes page walks that page fault.", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of page walks outstanding for iside in PMH every cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x85", + "EventName": "ITLB_MISSES.WALK_PENDING", + "PublicDescription": "Counts the number of page walks outstanding for iside in PMH every cycle. A PMH page walk is outstanding from page walk start till PMH becomes idle again (ready to serve next walk). Includes EPT-walk intervals. Walks could be counted by edge detecting on this event, but would count restarted suspended walks.", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of retired loads that are blocked due to a first level TLB miss.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.DTLB_MISS", + "PublicDescription": "Counts the number of retired loads that are blocked due to a first level TLB miss. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8" } ] diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 85f41cab56c7..a52909e212b4 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -7,7 +7,7 @@ GenuineIntel-6-(3D|47),v30,broadwell,core GenuineIntel-6-56,v12,broadwellde,core GenuineIntel-6-4F,v23,broadwellx,core GenuineIntel-6-55-[56789ABCDEF],v1.25,cascadelakex,core -GenuineIntel-6-DD,v1.00,clearwaterforest,core +GenuineIntel-6-DD,v1.02,clearwaterforest,core GenuineIntel-6-9[6C],v1.05,elkhartlake,core GenuineIntel-6-CF,v1.21,emeraldrapids,core GenuineIntel-6-5[CF],v13,goldmont,core From 91a914e8b9bf937d7a700005dc9c0b83b7dfbc2f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:47 -0700 Subject: [PATCH 152/343] perf vendor events intel: Update emeraldrapids events from 1.21 to 1.23 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events and metrics were published in: https://github.com/intel/perfmon/commit/526f1bf0ad6a42d275d1bb115cd337b71c561f92 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- .../arch/x86/emeraldrapids/cache.json | 18 ++++++++++++++++++ tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/cache.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/cache.json index b2f8947f6741..ff6071d7728e 100644 --- a/tools/perf/pmu-events/arch/x86/emeraldrapids/cache.json +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/cache.json @@ -181,6 +181,15 @@ "SampleAfterValue": "200003", "UMask": "0xff" }, + { + "BriefDescription": "All requests that hit L2 cache [This event is alias to L2_RQSTS.HIT]", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "SampleAfterValue": "200003", + "UMask": "0xdf" + }, { "BriefDescription": "Read requests with true-miss in L2 cache. [This event is alias to L2_RQSTS.MISS]", "Counter": "0,1,2,3", @@ -279,6 +288,15 @@ "SampleAfterValue": "200003", "UMask": "0x21" }, + { + "BriefDescription": "All requests that hit L2 cache [This event is alias to L2_REQUEST.HIT]", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "L2_RQSTS.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "SampleAfterValue": "200003", + "UMask": "0xdf" + }, { "BriefDescription": "L2_RQSTS.HWPF_MISS", "Counter": "0,1,2,3", diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index a52909e212b4..b6d4d37bcf99 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -9,7 +9,7 @@ GenuineIntel-6-4F,v23,broadwellx,core GenuineIntel-6-55-[56789ABCDEF],v1.25,cascadelakex,core GenuineIntel-6-DD,v1.02,clearwaterforest,core GenuineIntel-6-9[6C],v1.05,elkhartlake,core -GenuineIntel-6-CF,v1.21,emeraldrapids,core +GenuineIntel-6-CF,v1.23,emeraldrapids,core GenuineIntel-6-5[CF],v13,goldmont,core GenuineIntel-6-7A,v1.01,goldmontplus,core GenuineIntel-6-B6,v1.11,grandridge,core From 409c04ab6b94ce0380034f416c515b19dee54b19 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:48 -0700 Subject: [PATCH 153/343] perf vendor events intel: Update grandridge events from 1.11 to 1.12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events and metrics were published in: https://github.com/intel/perfmon/commit/50159a77124571c633adc2625fa7b566010d5001 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- .../pmu-events/arch/x86/grandridge/cache.json | 56 ++++++++++++++++ .../arch/x86/grandridge/floating-point.json | 8 +++ .../arch/x86/grandridge/frontend.json | 64 +++++++++++++++++++ .../arch/x86/grandridge/pipeline.json | 15 +++++ .../arch/x86/grandridge/uncore-io.json | 15 ++--- .../arch/x86/grandridge/uncore-memory.json | 32 +++++----- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 7 files changed, 167 insertions(+), 25 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/grandridge/cache.json b/tools/perf/pmu-events/arch/x86/grandridge/cache.json index 0aa921ba89b4..393ce9421c12 100644 --- a/tools/perf/pmu-events/arch/x86/grandridge/cache.json +++ b/tools/perf/pmu-events/arch/x86/grandridge/cache.json @@ -121,6 +121,14 @@ "SampleAfterValue": "1000003", "UMask": "0x1" }, + { + "BriefDescription": "Counts the number of cycles the core is stalled due to an instruction cache or TLB miss which missed in the L2 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x35", + "EventName": "MEM_BOUND_STALLS_IFETCH.L2_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x7e" + }, { "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to an ICACHE or ITLB miss which hit in the LLC. If the core has access to an L3 cache, an LLC hit refers to an L3 cache hit, otherwise it counts zeros.", "Counter": "0,1,2,3,4,5,6,7", @@ -129,6 +137,14 @@ "SampleAfterValue": "1000003", "UMask": "0x6" }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to an ICACHE or ITLB miss which hit in the LLC, no snoop was required. LLC provides the data. If the core has access to an L3 cache, an LLC hit refers to an L3 cache hit, otherwise it counts zeros.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x35", + "EventName": "MEM_BOUND_STALLS_IFETCH.LLC_HIT_NOSNOOP", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, { "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to an ICACHE or ITLB miss which missed all the caches. If the core has access to an L3 cache, an LLC miss refers to an L3 cache miss, otherwise it is an L2 cache miss.", "Counter": "0,1,2,3,4,5,6,7", @@ -137,6 +153,14 @@ "SampleAfterValue": "1000003", "UMask": "0x78" }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to an ICACHE or ITLB miss which missed all the caches. DRAM, MMIO or other LOCAL memory type provides the data. If the core has access to an L3 cache, an LLC miss refers to an L3 cache miss, otherwise it is an L2 cache miss.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x35", + "EventName": "MEM_BOUND_STALLS_IFETCH.LLC_MISS_LOCALMEM", + "SampleAfterValue": "1000003", + "UMask": "0x50" + }, { "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to an L1 demand load miss.", "Counter": "0,1,2,3,4,5,6,7", @@ -154,6 +178,14 @@ "SampleAfterValue": "1000003", "UMask": "0x1" }, + { + "BriefDescription": "Counts the number of cycles the core is stalled due to a demand load which missed in the L2 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.L2_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x7e" + }, { "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which hit in the LLC. If the core has access to an L3 cache, an LLC hit refers to an L3 cache hit, otherwise it counts zeros.", "Counter": "0,1,2,3,4,5,6,7", @@ -162,6 +194,14 @@ "SampleAfterValue": "1000003", "UMask": "0x6" }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which hit in the LLC, a snoop was required, the snoop misses or the snoop hits but NO_FWD. LLC provides the data. If the core has access to an L3 cache, an LLC hit refers to an L3 cache hit, otherwise it counts zeros.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.LLC_HIT_SNOOP", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, { "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which missed all the local caches. If the core has access to an L3 cache, an LLC miss refers to an L3 cache miss, otherwise it is an L2 cache miss.", "Counter": "0,1,2,3,4,5,6,7", @@ -170,6 +210,14 @@ "SampleAfterValue": "1000003", "UMask": "0x78" }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled to a demand load miss and the data was provided from an unknown source. If the core has access to an L3 cache, an LLC miss refers to an L3 cache miss, otherwise it is an L2 cache miss.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.LLC_MISS_LOCALMEM", + "SampleAfterValue": "1000003", + "UMask": "0x50" + }, { "BriefDescription": "Counts the number of unhalted cycles when the core is stalled to a store buffer full condition", "Counter": "0,1,2,3,4,5,6,7", @@ -178,6 +226,14 @@ "SampleAfterValue": "1000003", "UMask": "0x80" }, + { + "BriefDescription": "Counts the total number of load ops retired that miss the L3 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0xff" + }, { "BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in DRAM", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/grandridge/floating-point.json b/tools/perf/pmu-events/arch/x86/grandridge/floating-point.json index 5266eed969be..c567f073713c 100644 --- a/tools/perf/pmu-events/arch/x86/grandridge/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/grandridge/floating-point.json @@ -90,6 +90,14 @@ "SampleAfterValue": "1000003", "UMask": "0x2" }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer store data port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.STD", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, { "BriefDescription": "Counts the number of floating point operations retired that required microcode assist.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/grandridge/frontend.json b/tools/perf/pmu-events/arch/x86/grandridge/frontend.json index fef5cba533bb..8a591e31d331 100644 --- a/tools/perf/pmu-events/arch/x86/grandridge/frontend.json +++ b/tools/perf/pmu-events/arch/x86/grandridge/frontend.json @@ -8,6 +8,54 @@ "SampleAfterValue": "200003", "UMask": "0x1" }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged with having preceded with frontend bound behavior", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.ALL", + "SampleAfterValue": "1000003" + }, + { + "BriefDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a baclear", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.BRANCH_DETECT", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles /empty issue slots due to a btclear", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.BRANCH_RESTEER", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged following an ms flow due to the bubble/wasted issue slot from exiting long ms flow", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.CISC", + "PublicDescription": "Counts the number of instructions retired that were tagged following an ms flow due to the bubble/wasted issue slot from exiting long ms flow", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged every cycle the decoder is unable to send 3 uops per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.DECODE", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to icache miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.ICACHE", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, { "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss", "Counter": "0,1,2,3,4,5,6,7", @@ -16,6 +64,22 @@ "SampleAfterValue": "1000003", "UMask": "0x10" }, + { + "BriefDescription": "Counts the number of instruction retired tagged after a wasted issue slot if none of the previous events occurred", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.OTHER", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a predecode wrong.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.PREDECODE", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, { "BriefDescription": "Counts every time the code stream enters into a new cache line by walking sequential from the previous line or being redirected by a jump.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/grandridge/pipeline.json b/tools/perf/pmu-events/arch/x86/grandridge/pipeline.json index 20986b987e18..0a8f7d327150 100644 --- a/tools/perf/pmu-events/arch/x86/grandridge/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/grandridge/pipeline.json @@ -260,6 +260,13 @@ "SampleAfterValue": "1000003", "UMask": "0x2" }, + { + "BriefDescription": "Counts the total number of machine clears for any reason including, but not limited to, memory ordering, memory disambiguation, SMC, and FP assist.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.ANY", + "SampleAfterValue": "20003" + }, { "BriefDescription": "Counts the number of machine clears due to memory ordering in which an internal load passes an older store within the same CPU.", "Counter": "0,1,2,3,4,5,6,7", @@ -268,6 +275,14 @@ "SampleAfterValue": "20003", "UMask": "0x8" }, + { + "BriefDescription": "Counts the number of machines clears due to memory renaming.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MRN_NUKE", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, { "BriefDescription": "Counts the number of machine clears due to a page fault. Counts both I-Side and D-Side (Loads/Stores) page faults. A page fault occurs when either the page is not present, or an access violation occurs.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/grandridge/uncore-io.json b/tools/perf/pmu-events/arch/x86/grandridge/uncore-io.json index 764cf2f0b4a8..1a495a89ed57 100644 --- a/tools/perf/pmu-events/arch/x86/grandridge/uncore-io.json +++ b/tools/perf/pmu-events/arch/x86/grandridge/uncore-io.json @@ -824,7 +824,7 @@ "Unit": "IIO" }, { - "BriefDescription": "-", + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.ABORT", "Counter": "0,1,2,3", "EventCode": "0x8e", "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.ABORT", @@ -836,7 +836,7 @@ "Unit": "IIO" }, { - "BriefDescription": "-", + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.CONFINED_P2P", "Counter": "0,1,2,3", "EventCode": "0x8e", "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.CONFINED_P2P", @@ -848,7 +848,7 @@ "Unit": "IIO" }, { - "BriefDescription": "-", + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.LOC_P2P", "Counter": "0,1,2,3", "EventCode": "0x8e", "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.LOC_P2P", @@ -860,7 +860,7 @@ "Unit": "IIO" }, { - "BriefDescription": "-", + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MCAST", "Counter": "0,1,2,3", "EventCode": "0x8e", "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MCAST", @@ -872,7 +872,7 @@ "Unit": "IIO" }, { - "BriefDescription": "-", + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MEM", "Counter": "0,1,2,3", "EventCode": "0x8e", "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MEM", @@ -884,7 +884,7 @@ "Unit": "IIO" }, { - "BriefDescription": "-", + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MSGB", "Counter": "0,1,2,3", "EventCode": "0x8e", "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MSGB", @@ -896,7 +896,7 @@ "Unit": "IIO" }, { - "BriefDescription": "-", + "BriefDescription": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.UBOX", "Counter": "0,1,2,3", "EventCode": "0x8e", "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.UBOX", @@ -915,7 +915,6 @@ "FCMask": "0x01", "PerPkg": "1", "PortMask": "0x0FF", - "PublicDescription": "-", "UMask": "0x4", "Unit": "IIO" }, diff --git a/tools/perf/pmu-events/arch/x86/grandridge/uncore-memory.json b/tools/perf/pmu-events/arch/x86/grandridge/uncore-memory.json index 6a11e5505957..8413391d752c 100644 --- a/tools/perf/pmu-events/arch/x86/grandridge/uncore-memory.json +++ b/tools/perf/pmu-events/arch/x86/grandridge/uncore-memory.json @@ -195,7 +195,7 @@ "EventName": "UNC_M_MR4_2XREF_CYCLES.SCH0_DIMM0", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_MR4_2XREF_CYCLES.SCH0_DIMM0", "UMask": "0x1", "Unit": "IMC" }, @@ -206,7 +206,7 @@ "EventName": "UNC_M_MR4_2XREF_CYCLES.SCH0_DIMM1", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_MR4_2XREF_CYCLES.SCH0_DIMM1", "UMask": "0x2", "Unit": "IMC" }, @@ -217,7 +217,7 @@ "EventName": "UNC_M_MR4_2XREF_CYCLES.SCH1_DIMM0", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_MR4_2XREF_CYCLES.SCH1_DIMM0", "UMask": "0x4", "Unit": "IMC" }, @@ -228,7 +228,7 @@ "EventName": "UNC_M_MR4_2XREF_CYCLES.SCH1_DIMM1", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_MR4_2XREF_CYCLES.SCH1_DIMM1", "UMask": "0x8", "Unit": "IMC" }, @@ -239,7 +239,7 @@ "EventName": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH0_DIMM0", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH0_DIMM0", "UMask": "0x1", "Unit": "IMC" }, @@ -250,7 +250,7 @@ "EventName": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH0_DIMM1", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH0_DIMM1", "UMask": "0x2", "Unit": "IMC" }, @@ -261,7 +261,7 @@ "EventName": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH1_DIMM0", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH1_DIMM0", "UMask": "0x4", "Unit": "IMC" }, @@ -272,7 +272,7 @@ "EventName": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH1_DIMM1", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_PDC_MR4ACTIVE_CYCLES.SCH1_DIMM1", "UMask": "0x8", "Unit": "IMC" }, @@ -617,7 +617,7 @@ "EventName": "UNC_M_THROTTLE_CRIT_CYCLES.SLOT0", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_THROTTLE_CRIT_CYCLES.SLOT0", "UMask": "0x1", "Unit": "IMC" }, @@ -628,7 +628,7 @@ "EventName": "UNC_M_THROTTLE_CRIT_CYCLES.SLOT1", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_THROTTLE_CRIT_CYCLES.SLOT1", "UMask": "0x2", "Unit": "IMC" }, @@ -639,7 +639,7 @@ "EventName": "UNC_M_THROTTLE_HIGH_CYCLES.SLOT0", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_THROTTLE_HIGH_CYCLES.SLOT0", "UMask": "0x1", "Unit": "IMC" }, @@ -650,7 +650,7 @@ "EventName": "UNC_M_THROTTLE_HIGH_CYCLES.SLOT1", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_THROTTLE_HIGH_CYCLES.SLOT1", "UMask": "0x2", "Unit": "IMC" }, @@ -661,7 +661,7 @@ "EventName": "UNC_M_THROTTLE_LOW_CYCLES.SLOT0", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_THROTTLE_LOW_CYCLES.SLOT0", "UMask": "0x1", "Unit": "IMC" }, @@ -672,7 +672,7 @@ "EventName": "UNC_M_THROTTLE_LOW_CYCLES.SLOT1", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_THROTTLE_LOW_CYCLES.SLOT1", "UMask": "0x2", "Unit": "IMC" }, @@ -683,7 +683,7 @@ "EventName": "UNC_M_THROTTLE_MID_CYCLES.SLOT0", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_THROTTLE_MID_CYCLES.SLOT0", "UMask": "0x1", "Unit": "IMC" }, @@ -694,7 +694,7 @@ "EventName": "UNC_M_THROTTLE_MID_CYCLES.SLOT1", "Experimental": "1", "PerPkg": "1", - "PublicDescription": "-", + "PublicDescription": "UNC_M_THROTTLE_MID_CYCLES.SLOT1", "UMask": "0x2", "Unit": "IMC" }, diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index b6d4d37bcf99..a1548f1306a6 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -12,7 +12,7 @@ GenuineIntel-6-9[6C],v1.05,elkhartlake,core GenuineIntel-6-CF,v1.23,emeraldrapids,core GenuineIntel-6-5[CF],v13,goldmont,core GenuineIntel-6-7A,v1.01,goldmontplus,core -GenuineIntel-6-B6,v1.11,grandridge,core +GenuineIntel-6-B6,v1.12,grandridge,core GenuineIntel-6-A[DE],v1.17,graniterapids,core GenuineIntel-6-(3C|45|46),v36,haswell,core GenuineIntel-6-3F,v29,haswellx,core From 8036f156851c4f35e180ecd27d56bdb8144bc1e8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:49 -0700 Subject: [PATCH 154/343] perf vendor events intel: Update graniterapids events from 1.17 to 1.18 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events and metrics were published in: https://github.com/intel/perfmon/commit/5b93c8c750300a15b29a9a718511869b280c91f4 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/arch/x86/graniterapids/cache.json | 9 +++++++++ tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/arch/x86/graniterapids/cache.json b/tools/perf/pmu-events/arch/x86/graniterapids/cache.json index db28866444b6..95d6b46f3445 100644 --- a/tools/perf/pmu-events/arch/x86/graniterapids/cache.json +++ b/tools/perf/pmu-events/arch/x86/graniterapids/cache.json @@ -296,6 +296,15 @@ "SampleAfterValue": "200003", "UMask": "0x40" }, + { + "BriefDescription": "Cycles when L1D is locked", + "Counter": "0,1,2,3", + "EventCode": "0x42", + "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION", + "PublicDescription": "This event counts the number of cycles when the L1D is locked. It is a superset of the 0x1 mask (BUS_LOCK_CLOCKS.BUS_LOCK_DURATION).", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, { "BriefDescription": "Core-originated cacheable requests that missed L3 (Except hardware prefetches to the L3)", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index a1548f1306a6..b97d19ae4264 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -13,7 +13,7 @@ GenuineIntel-6-CF,v1.23,emeraldrapids,core GenuineIntel-6-5[CF],v13,goldmont,core GenuineIntel-6-7A,v1.01,goldmontplus,core GenuineIntel-6-B6,v1.12,grandridge,core -GenuineIntel-6-A[DE],v1.17,graniterapids,core +GenuineIntel-6-A[DE],v1.18,graniterapids,core GenuineIntel-6-(3C|45|46),v36,haswell,core GenuineIntel-6-3F,v29,haswellx,core GenuineIntel-6-7[DE],v1.24,icelake,core From 988e264ae93f3e1a6059c13e6036c1fd73a585e2 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:50 -0700 Subject: [PATCH 155/343] perf vendor events intel: Update lunarlake events from 1.21 to 1.22 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events and metrics were published in: https://github.com/intel/perfmon/commit/fae822a0f9318e602902eeb2166b966a28c715f8 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- .../pmu-events/arch/x86/lunarlake/cache.json | 20 +++++++++++++++++++ .../arch/x86/lunarlake/pipeline.json | 9 +++++++++ tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/cache.json b/tools/perf/pmu-events/arch/x86/lunarlake/cache.json index 2db3e8a51fbd..92a3667b4520 100644 --- a/tools/perf/pmu-events/arch/x86/lunarlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/lunarlake/cache.json @@ -289,6 +289,16 @@ "UMask": "0x2", "Unit": "cpu_atom" }, + { + "BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "Counter": "0,1,2,3,4,5,6,7,8,9", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "SampleAfterValue": "200003", + "UMask": "0x5f", + "Unit": "cpu_core" + }, { "BriefDescription": "Counts the number of total L2 Cache Accesses that resulted in a Miss from a front door request only (does not include rejects or recycles), per core event", "Counter": "0,1,2,3,4,5,6,7", @@ -387,6 +397,16 @@ "UMask": "0x21", "Unit": "cpu_core" }, + { + "BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "Counter": "0,1,2,3,4,5,6,7,8,9", + "EventCode": "0x24", + "EventName": "L2_RQSTS.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "SampleAfterValue": "200003", + "UMask": "0x5f", + "Unit": "cpu_core" + }, { "BriefDescription": "Read requests with true-miss in L2 cache [This event is alias to L2_REQUEST.MISS]", "Counter": "0,1,2,3,4,5,6,7,8,9", diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json b/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json index d98723b3cd78..d66eafccebbb 100644 --- a/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json @@ -315,6 +315,15 @@ "UMask": "0xfd", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of relative JMP branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.REL_JMP", + "SampleAfterValue": "200003", + "UMask": "0xdf", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the total number of mispredicted branch instructions retired for all branch types.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index b97d19ae4264..4176d22da1a7 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -22,7 +22,7 @@ GenuineIntel-6-3A,v24,ivybridge,core GenuineIntel-6-3E,v24,ivytown,core GenuineIntel-6-2D,v24,jaketown,core GenuineIntel-6-(57|85),v16,knightslanding,core -GenuineIntel-6-BD,v1.21,lunarlake,core +GenuineIntel-6-BD,v1.22,lunarlake,core GenuineIntel-6-(AA|AC|B5),v1.20,meteorlake,core GenuineIntel-6-1[AEF],v4,nehalemep,core GenuineIntel-6-2E,v4,nehalemex,core From 8dee02f7397e7725f7a6e3f0f74349333af8a832 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:51 -0700 Subject: [PATCH 156/343] perf vendor events intel: Update meteorlake events from 1.20 to 1.21 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events and metrics were published in: https://github.com/intel/perfmon/commit/419a6600ad2019d4acbf0f79cc54cde85164afc1 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- .../pmu-events/arch/x86/meteorlake/cache.json | 55 ++++++ .../arch/x86/meteorlake/floating-point.json | 63 +++++++ .../arch/x86/meteorlake/memory.json | 64 +++++++ .../arch/x86/meteorlake/pipeline.json | 158 ++++++++++++++++++ .../arch/x86/meteorlake/virtual-memory.json | 9 + 6 files changed, 350 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 4176d22da1a7..1a6bb8597cbe 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -23,7 +23,7 @@ GenuineIntel-6-3E,v24,ivytown,core GenuineIntel-6-2D,v24,jaketown,core GenuineIntel-6-(57|85),v16,knightslanding,core GenuineIntel-6-BD,v1.22,lunarlake,core -GenuineIntel-6-(AA|AC|B5),v1.20,meteorlake,core +GenuineIntel-6-(AA|AC|B5),v1.21,meteorlake,core GenuineIntel-6-1[AEF],v4,nehalemep,core GenuineIntel-6-2E,v4,nehalemex,core GenuineIntel-6-CC,v1.04,pantherlake,core diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/cache.json b/tools/perf/pmu-events/arch/x86/meteorlake/cache.json index 4c1220c19456..6419bc36f249 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/cache.json @@ -1,4 +1,13 @@ [ + { + "BriefDescription": "Counts the number of request that were not accepted into the L2Q because the L2Q is FULL.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x31", + "EventName": "CORE_REJECT_L2Q.ANY", + "PublicDescription": "Counts the number of (demand and L1 prefetchers) core requests rejected by the L2Q due to a full or nearly full w condition which likely indicates back pressure from L2Q. It also counts requests that would have gone directly to the XQ, but are rejected due to a full or nearly full condition, indicating back pressure from the IDI link. The L2Q may also reject transactions from a core to insure fairness between cores, or to delay a cores dirty eviction when the address conflicts incoming external snoops. (Note that L2 prefetcher requests that are dropped are not counted by this event.) Counts on a per core basis.", + "SampleAfterValue": "200003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of L1D cacheline (dirty) evictions caused by load misses, stores, and prefetches.", "Counter": "0,1,2,3,4,5,6,7", @@ -181,6 +190,15 @@ "UMask": "0x4", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x30", + "EventName": "L2_REJECT_XQ.ANY", + "PublicDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition which likely indicates back pressure from the IDI link. The XQ may reject transactions from the L2Q (non-cacheable requests), BBL (L2 misses) and WOB (L2 write-back victims).", + "SampleAfterValue": "200003", + "Unit": "cpu_atom" + }, { "BriefDescription": "All accesses to L2 cache [This event is alias to L2_RQSTS.REFERENCES]", "Counter": "0,1,2,3", @@ -885,6 +903,33 @@ "UMask": "0x20", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and modified data was forwarded.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_HITM", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and no data was forwarded.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_NO_FWD", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and non-modified data was forwarded.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_WITH_FWD", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in DRAM", "Counter": "0,1,2,3,4,5,6,7", @@ -993,6 +1038,16 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST)", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.ALL", + "SampleAfterValue": "200003", + "UMask": "0x83", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of load ops retired.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/floating-point.json b/tools/perf/pmu-events/arch/x86/meteorlake/floating-point.json index 28dc5e06ee31..1ccbd54904c5 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/floating-point.json @@ -19,6 +19,24 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of active floating point dividers per cycle in the loop stage.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_OCCUPANCY", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of floating point divider uops executed per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_UOPS", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts all microcode FP assists.", "Counter": "0,1,2,3,4,5,6,7", @@ -274,6 +292,51 @@ "UMask": "0x2", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of uops executed on all floating point ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0xf", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0, 1, 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.PRIMARY", + "SampleAfterValue": "1000003", + "UMask": "0xe", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of uops executed on floating point and vector integer store data port.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/memory.json b/tools/perf/pmu-events/arch/x86/meteorlake/memory.json index f0cbeda4d5ca..7cdd5cb39009 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/memory.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/memory.json @@ -19,6 +19,15 @@ "UMask": "0x6", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.ANY", + "SampleAfterValue": "1000003", + "UMask": "0x7f", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block, on a load that retires.", "Counter": "0,1,2,3,4,5,6,7", @@ -37,6 +46,15 @@ "UMask": "0xf4", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DL1 miss.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.L1_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DL1 miss.", "Counter": "0,1,2,3,4,5,6,7", @@ -46,6 +64,16 @@ "UMask": "0x81", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.OTHER", + "PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases such as pipeline conflicts, fences, etc.", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases.", "Counter": "0,1,2,3,4,5,6,7", @@ -56,6 +84,15 @@ "UMask": "0xc0", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a pagewalk.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.PGWALK", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a pagewalk.", "Counter": "0,1,2,3,4,5,6,7", @@ -65,6 +102,15 @@ "UMask": "0xa0", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a store address match.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.ST_ADDR", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a store address match.", "Counter": "0,1,2,3,4,5,6,7", @@ -74,6 +120,24 @@ "UMask": "0x84", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL_AT_RET", + "SampleAfterValue": "1000003", + "UMask": "0x82", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of machine clears due to memory ordering caused by a snoop from an external agent. Does not count internally generated machine clears such as those due to memory disambiguation.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/pipeline.json b/tools/perf/pmu-events/arch/x86/meteorlake/pipeline.json index 7662846745bd..09e1147c4733 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/pipeline.json @@ -20,6 +20,16 @@ "UMask": "0x9", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of cycles when any of the integer dividers are active.", + "Counter": "0,1,2,3,4,5,6,7", + "CounterMask": "1", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "This event counts the cycles the integer divider is busy.", "Counter": "0,1,2,3,4,5,6,7", @@ -30,6 +40,24 @@ "UMask": "0x8", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of active integer dividers per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_OCCUPANCY", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of integer divider uops executed per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_UOPS", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Number of occurrences where a microcode assist is invoked by hardware.", "Counter": "0,1,2,3,4,5,6,7", @@ -255,6 +283,16 @@ "UMask": "0xdf", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of taken branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "Errata": "MTL013", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.TAKEN", + "SampleAfterValue": "200003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the total number of mispredicted branch instructions retired for all branch types.", "Counter": "0,1,2,3,4,5,6,7", @@ -929,6 +967,89 @@ "UMask": "0x10", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of uops executed on all Integer ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0xff", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on a load port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.LD", + "PublicDescription": "Counts the number of uops executed on a load port. This event counts for integer uops even if the destination is FP/vector", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P3", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 0,1, 2, 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.PRIMARY", + "SampleAfterValue": "1000003", + "UMask": "0x78", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on a Store address port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.STA", + "PublicDescription": "Counts the number of uops executed on a Store address port. This event counts integer uops even if the data source is FP/vector", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of uops executed on an integer store data and jump port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.STD_JMP", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "INT_VEC_RETIRED.128BIT", "Counter": "0,1,2,3,4,5,6,7", @@ -1131,6 +1252,24 @@ "UMask": "0x8", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FAST", + "SampleAfterValue": "20003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of virtual traps taken.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP", + "SampleAfterValue": "20003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of machines clears due to memory renaming.", "Counter": "0,1,2,3,4,5,6,7", @@ -1303,6 +1442,25 @@ "UMask": "0x4", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number issue slots not consumed due to a color request for an FCW or MXCSR control register when all 4 colors (copies) are already in use.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.COLOR_STALLS", + "SampleAfterValue": "200003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.NON_C01_MS_SCB", + "PublicDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires. The most commonly executed instruction with an MS scoreboard is PAUSE.", + "SampleAfterValue": "200003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, { "BriefDescription": "This event counts a subset of the Topdown Slots event that were not consumed by the back-end pipeline due to lack of back-end resources, as a result of memory subsystem delays, execution units limitations, or other conditions.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/virtual-memory.json b/tools/perf/pmu-events/arch/x86/meteorlake/virtual-memory.json index 305b96b26a4e..04396c7b3e08 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/virtual-memory.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/virtual-memory.json @@ -356,6 +356,15 @@ "UMask": "0x10", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DTLB miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.DTLB_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DTLB miss.", "Counter": "0,1,2,3,4,5,6,7", From 4aa006c38dca636519241667175f9125ff630838 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:52 -0700 Subject: [PATCH 157/343] perf vendor events intel: Update pantherlake events from 1.04 to 1.05 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events and metrics were published in: https://github.com/intel/perfmon/commit/f5593317a6dee0d11bb2db9a5895db1f231267a9 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- .../arch/x86/pantherlake/cache.json | 152 ++++++++++-- .../arch/x86/pantherlake/frontend.json | 60 +++++ .../arch/x86/pantherlake/memory.json | 29 +++ .../arch/x86/pantherlake/other.json | 10 + .../arch/x86/pantherlake/pipeline.json | 231 +++++++++++++++++- 6 files changed, 462 insertions(+), 22 deletions(-) diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 1a6bb8597cbe..70ba1af93822 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -26,7 +26,7 @@ GenuineIntel-6-BD,v1.22,lunarlake,core GenuineIntel-6-(AA|AC|B5),v1.21,meteorlake,core GenuineIntel-6-1[AEF],v4,nehalemep,core GenuineIntel-6-2E,v4,nehalemex,core -GenuineIntel-6-CC,v1.04,pantherlake,core +GenuineIntel-6-(CC|D5),v1.05,pantherlake,core GenuineIntel-6-A7,v1.04,rocketlake,core GenuineIntel-6-2A,v19,sandybridge,core GenuineIntel-6-8F,v1.36,sapphirerapids,core diff --git a/tools/perf/pmu-events/arch/x86/pantherlake/cache.json b/tools/perf/pmu-events/arch/x86/pantherlake/cache.json index e5323093eec0..165e955b870c 100644 --- a/tools/perf/pmu-events/arch/x86/pantherlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/pantherlake/cache.json @@ -1,4 +1,13 @@ [ + { + "BriefDescription": "Counts the number of requests that were not accepted into the L2Q because the L2Q is FULL.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x31", + "EventName": "CORE_REJECT_L2Q.ANY", + "PublicDescription": "Counts the number of (demand and L1 prefetchers) core requests rejected by the L2Q due to a full or nearly full condition which likely indicates back pressure from L2Q. It also counts requests that would have gone directly to the XQ, but are rejected due to a full or nearly full condition, indicating back pressure from the IDI link. The L2Q may also reject transactions from a core to ensure fairness between cores, or to delay a core's dirty eviction when the address conflicts with incoming external snoops. Note that L2 prefetcher requests that are dropped are not counted by this event. Counts on a per core basis.", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cache lines replaced in L0 data cache.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -130,6 +139,15 @@ "UMask": "0x4", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x30", + "EventName": "L2_REJECT_XQ.ANY", + "PublicDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition which likely indicates back pressure from the IDI link. The IDI link is a central on-die protocol for memory and coherence traffic between the core and the uncore. It is highly optimized for efficiency, bandwidth, and coherency, using multiple channels and flow control mechanisms to manage high-throughput, low-latency data and protocol communication within the chip. The XQ may reject transactions from the L2Q (non-cacheable requests), BBL (L2 misses) and WOB (L2 write-back victims).", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of L2 cache accesses from front door requests for Code Read, Data Read, RFO, ITOM, and L2 Prefetches. Does not include rejects or recycles, per core event.", "Counter": "0,1,2,3,4,5,6,7", @@ -158,6 +176,15 @@ "UMask": "0xc4", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Code Read requests that resulted in a hit. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_CODE_RD_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x84", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Code Read requests that resulted in a Miss. Does not include rejects or recycles, per core event.", "Counter": "0,1,2,3,4,5,6,7", @@ -176,6 +203,15 @@ "UMask": "0xc1", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Data Read requests that resulted in a hit. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_DATA_RD_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x81", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of L2 cache accesses from front door Demand Data Read requests that resulted in a Miss. Does not include rejects or recycles, per core event.", "Counter": "0,1,2,3,4,5,6,7", @@ -194,6 +230,15 @@ "UMask": "0xc2", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Demand RFO requests that resulted in a hit. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.DEMAND_RFO_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x82", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of L2 cache accesses from front door Demand RFO requests that resulted in a Miss. Does not include rejects or recycles, per core event.", "Counter": "0,1,2,3,4,5,6,7", @@ -212,6 +257,16 @@ "UMask": "0x1bf", "Unit": "cpu_atom" }, + { + "BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "Counter": "0,1,2,3,4,5,6,7,8,9", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "SampleAfterValue": "200003", + "UMask": "0x5f", + "Unit": "cpu_core" + }, { "BriefDescription": "Counts the number of L2 cache accesses from front door Hardware Prefetch requests. Does not include rejects or recycles, per core event.", "Counter": "0,1,2,3,4,5,6,7", @@ -221,6 +276,24 @@ "UMask": "0xc8", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Hardware Prefetch requests that result in a hit. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HWPF_HIT", + "SampleAfterValue": "1000003", + "UMask": "0x88", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of L2 cache accesses from front door Hardware Prefetch requests that result in a miss. Does not include rejects or recycles, per core event.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HWPF_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x48", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of L2 cache accesses from front door requests that resulted in a Miss. Does not include rejects or recycles, per core event.", "Counter": "0,1,2,3,4,5,6,7", @@ -310,6 +383,16 @@ "UMask": "0x21", "Unit": "cpu_core" }, + { + "BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "Counter": "0,1,2,3,4,5,6,7,8,9", + "EventCode": "0x24", + "EventName": "L2_RQSTS.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "SampleAfterValue": "200003", + "UMask": "0x5f", + "Unit": "cpu_core" + }, { "BriefDescription": "Read requests with true-miss in L2 cache [This event is alias to L2_REQUEST.MISS]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1019,6 +1102,19 @@ "UMask": "0x82", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of tagged load uops retired.", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY", + "MSRIndex": "0x3F6", + "MSRValue": "0x1", + "PublicDescription": "Counts the number of tagged load uops retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024.", "Counter": "0,1,2,3,4,5,6,7", @@ -1033,27 +1129,27 @@ "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128.", "Counter": "0,1,2,3,4,5,6,7", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", "MSRIndex": "0x3F6", "MSRValue": "0x80", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5", "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 16.", "Counter": "0,1,2,3,4,5,6,7", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", "MSRIndex": "0x3F6", "MSRValue": "0x10", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 16. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5", "Unit": "cpu_atom" @@ -1072,79 +1168,79 @@ "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256.", "Counter": "0,1,2,3,4,5,6,7", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", "MSRIndex": "0x3F6", "MSRValue": "0x100", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5", "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 32.", "Counter": "0,1,2,3,4,5,6,7", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", "MSRIndex": "0x3F6", "MSRValue": "0x20", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 32. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5", "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 4.", "Counter": "0,1,2,3,4,5,6,7", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", "MSRIndex": "0x3F6", "MSRValue": "0x4", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 4. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5", "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 512.", "Counter": "0,1,2,3,4,5,6,7", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", "MSRIndex": "0x3F6", "MSRValue": "0x200", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 512. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5", "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 64.", "Counter": "0,1,2,3,4,5,6,7", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", "MSRIndex": "0x3F6", "MSRValue": "0x40", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 64. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5", "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.", + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 8.", "Counter": "0,1,2,3,4,5,6,7", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", "MSRIndex": "0x3F6", "MSRValue": "0x8", - "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 8. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x5", "Unit": "cpu_atom" @@ -1159,6 +1255,26 @@ "UMask": "0x21", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of load uops retired that were correctly predicated by the memory renaming (MRN) feature.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.MRN_LOADS", + "PublicDescription": "Counts the number of load uops retired that were correctly predicated by the memory renaming (MRN) feature. MRN loads are a part of the memory renaming process that optimizes data forwarding between stores and loads, reducing latency and improving performance. This involves tagging stores that forward to loads and copying the physical source (the actual data) directly from the store to the load. The MRN'd load can complete without accessing the memory, thus reducing load-to-use latency. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x9", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of store uops retired that were correctly tagged by the memory renaming (MRN) feature.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.MRN_STORES", + "PublicDescription": "Counts the number of store uops retired that were correctly tagged by the memory renaming (MRN) feature. MRN stores are a part of the memory renaming process that optimizes data forwarding between stores and loads, reducing latency and improving performance. This involves tagging stores that forward to loads and copying the physical source (the actual data) directly from the store to the load. The MRN store ensures that it's data is accurately forwarded to matching subsequent loads. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0xa", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of memory uops retired that were splits.", "Counter": "0,1,2,3,4,5,6,7", @@ -1220,12 +1336,12 @@ "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the number of stores uops retired same as MEM_UOPS_RETIRED.ALL_STORES", + "BriefDescription": "Counts the number of stores uops retired.", "Counter": "0,1,2,3,4,5,6,7", "Data_LA": "1", "EventCode": "0xd0", "EventName": "MEM_UOPS_RETIRED.STORE_LATENCY", - "PublicDescription": "Counts the number of stores uops retired same as MEM_UOPS_RETIRED.ALL_STORES Available PDIST counters: 0,1", + "PublicDescription": "Counts the number of stores uops retired. Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x6", "Unit": "cpu_atom" diff --git a/tools/perf/pmu-events/arch/x86/pantherlake/frontend.json b/tools/perf/pmu-events/arch/x86/pantherlake/frontend.json index 5e69b81742f5..ef490c38569d 100644 --- a/tools/perf/pmu-events/arch/x86/pantherlake/frontend.json +++ b/tools/perf/pmu-events/arch/x86/pantherlake/frontend.json @@ -120,6 +120,16 @@ "UMask": "0x3", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to icache miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.ICACHE", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to icache miss Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss", "Counter": "0,1,2,3,4,5,6,7", @@ -344,6 +354,56 @@ "UMask": "0x1", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L2_MISS", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0xe", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_HIT", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x6", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and did not have to snoop another core.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_HIT_NO_SNOOP", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and did not have to snoop another core. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and required a snoop (that resulted in a snoop miss, snoop hitm, snoop hit with fwd, or snoop hit with no fwd).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_HIT_WITH_SNOOP", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and required a snoop (that resulted in a snoop miss, snoop hitm, snoop hit with fwd, or snoop hit with no fwd). Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 and L3 caches.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc9", + "EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_MISS", + "PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 and L3 caches. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss that hit in the second level TLB.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/pantherlake/memory.json b/tools/perf/pmu-events/arch/x86/pantherlake/memory.json index 4248cc101391..ac0446359de3 100644 --- a/tools/perf/pmu-events/arch/x86/pantherlake/memory.json +++ b/tools/perf/pmu-events/arch/x86/pantherlake/memory.json @@ -26,6 +26,26 @@ "UMask": "0x81", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.OTHER", + "PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases such as pipeline conflicts, fences, etc.", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.OTHER_AT_RET", + "PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases such as pipeline conflicts, fences, etc.", + "SampleAfterValue": "1000003", + "UMask": "0xc0", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.", "Counter": "0,1,2,3,4,5,6,7", @@ -63,6 +83,15 @@ "UMask": "0x2", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MEMORY_ORDERING_FAST", + "SampleAfterValue": "1000003", + "UMask": "0x8002", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 1024 cycles.", "Counter": "2,3,4,5,6,7,8,9", diff --git a/tools/perf/pmu-events/arch/x86/pantherlake/other.json b/tools/perf/pmu-events/arch/x86/pantherlake/other.json index 915c52f5abd1..91dd2d25ebaf 100644 --- a/tools/perf/pmu-events/arch/x86/pantherlake/other.json +++ b/tools/perf/pmu-events/arch/x86/pantherlake/other.json @@ -18,6 +18,16 @@ "UMask": "0x8", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of LBR entries recorded. Requires LBRs to be enabled in IA32_LBR_CTL. [This event is alias to MISC_RETIRED.LBR_INSERTS]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xe4", + "EventName": "LBR_INSERTS.ANY", + "PublicDescription": "Counts the number of LBR entries recorded. Requires LBRs to be enabled in IA32_LBR_CTL. [This event is alias to MISC_RETIRED.LBR_INSERTS] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts streaming stores that have any type of response.", "Counter": "0,1,2,3,4,5,6,7,8,9", diff --git a/tools/perf/pmu-events/arch/x86/pantherlake/pipeline.json b/tools/perf/pmu-events/arch/x86/pantherlake/pipeline.json index 86009237df2f..d476bad5e2a7 100644 --- a/tools/perf/pmu-events/arch/x86/pantherlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/pantherlake/pipeline.json @@ -258,6 +258,16 @@ "UMask": "0x30", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of near direct CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_DIR_CALL]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_DIRECT_CALL", + "PublicDescription": "Counts the number of near direct CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_DIR_CALL] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, { "BriefDescription": "near relative call instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_REL_CALL]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -268,6 +278,16 @@ "UMask": "0x20", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of near direct JMP branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_DIR_JMP]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_DIRECT_JMP", + "PublicDescription": "Counts the number of near direct JMP branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_DIR_JMP] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "near relative jump instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_REL_JMP]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -278,6 +298,28 @@ "UMask": "0x80", "Unit": "cpu_core" }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_DIRECT_CALL]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_DIR_CALL", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_DIRECT_CALL] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_DIRECT_JMP]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_DIR_JMP", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_DIRECT_JMP] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of near indirect JMP and near indirect CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.ALL_NEAR_IND]", "Counter": "0,1,2,3,4,5,6,7", @@ -298,6 +340,16 @@ "UMask": "0x50", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of near indirect CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_CALL]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_INDIRECT_CALL", + "PublicDescription": "Counts the number of near indirect CALL branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_CALL] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "Indirect near call instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_CALL]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -308,6 +360,16 @@ "UMask": "0x10", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of near indirect JMP branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_JMP]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_INDIRECT_JMP", + "PublicDescription": "Counts the number of near indirect JMP branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_JMP] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Indirect near jump instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_IND_JMP]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -328,6 +390,17 @@ "UMask": "0x58", "Unit": "cpu_atom" }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_CALL]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_IND_CALL", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_CALL] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_CALL]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -339,6 +412,17 @@ "UMask": "0x10", "Unit": "cpu_core" }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_JMP]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_IND_JMP", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_JMP] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_INDIRECT_JMP]", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -350,6 +434,16 @@ "UMask": "0x40", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of near JMP branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_JMP", + "PublicDescription": "Counts the number of near JMP branch instructions retired. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0xc0", + "Unit": "cpu_atom" + }, { "BriefDescription": "Indirect and Direct Relative near jump instructions retired.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -382,6 +476,27 @@ "UMask": "0x80", "Unit": "cpu_core" }, + { + "BriefDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_RETURN]", + "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_RET", + "PublicDescription": "This event is deprecated. [This event is alias to BR_INST_RETIRED.NEAR_RETURN] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of near RET branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_RET]", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_RETURN", + "PublicDescription": "Counts the number of near RET branch instructions retired. [This event is alias to BR_INST_RETIRED.NEAR_RET] Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Return instructions retired.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -966,7 +1081,7 @@ "Unit": "cpu_core" }, { - "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles.", + "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles. [This event is alias to CPU_CLK_UNHALTED.CORE]", "Counter": "Fixed counter 1", "EventName": "CPU_CLK_UNHALTED.THREAD", "SampleAfterValue": "2000003", @@ -1554,6 +1669,23 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the total number of machine clears for any reason including, but not limited to, memory ordering, memory disambiguation, SMC, and FP assist.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.ANY", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.ANY_FAST", + "SampleAfterValue": "1000003", + "UMask": "0x80ff", + "Unit": "cpu_atom" + }, { "BriefDescription": "Number of machine clears (nukes) of any type.", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1575,6 +1707,42 @@ "UMask": "0x8", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.DISAMBIGUATION_FAST", + "SampleAfterValue": "1000003", + "UMask": "0x8008", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of virtual traps taken.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of machines clears due to memory renaming.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MRN_NUKE", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MRN_NUKE_FAST", + "SampleAfterValue": "1000003", + "UMask": "0x8010", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of machine clears due to a page fault. Counts both I-Side and D-Side (Loads/Stores) page faults. A page fault occurs when either the page is not present, or an access violation occurs.", "Counter": "0,1,2,3,4,5,6,7", @@ -1603,6 +1771,16 @@ "UMask": "0x4", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of machine clears due to program modifying data (cross-core modifying code) within 1K of a recently fetched code page.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.XMC", + "PublicDescription": "Counts the number of machine clears due to program modifying data (self modifying code) within 1K of a recently fetched code page.", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts cycles where no execution is happening due to loads waiting for L1 cache (that is: no execution & load in flight & no load missed L1 cache)", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -1650,11 +1828,12 @@ "Unit": "cpu_core" }, { - "BriefDescription": "Counts the number of LBR entries recorded. Requires LBRs to be enabled in IA32_LBR_CTL.", + "BriefDescription": "This event is deprecated. [This event is alias to LBR_INSERTS.ANY]", "Counter": "0,1,2,3,4,5,6,7", + "Deprecated": "1", "EventCode": "0xe4", "EventName": "MISC_RETIRED.LBR_INSERTS", - "PublicDescription": "Counts the number of LBR entries recorded. Requires LBRs to be enabled in IA32_LBR_CTL. Available PDIST counters: 0,1", + "PublicDescription": "This event is deprecated. [This event is alias to LBR_INSERTS.ANY] Available PDIST counters: 0,1", "SampleAfterValue": "1000003", "UMask": "0x1", "Unit": "cpu_atom" @@ -1943,6 +2122,25 @@ "UMask": "0x2", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to IEC and FPC RAT stalls - which can be due to the FIQ and IEC reservation station stall (integer, FP and SIMD scheduler not being able to accept another uop).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.NON_MEM_SCHEDULER", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to mrbl stall. A marble refers to a physical register file entry, also known as the physical destination (PDST).", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.REGISTER", + "PublicDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to mrbl stall. A 'marble' refers to a physical register file entry, also known as the physical destination (PDST).", + "SampleAfterValue": "1000003", + "UMask": "0x20", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to ROB full", "Counter": "0,1,2,3,4,5,6,7", @@ -2014,6 +2212,15 @@ "UMask": "0x8", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to frontend bandwidth restrictions due to decode, predecode, cisc, and other limitations.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.FRONTEND_BANDWIDTH", + "SampleAfterValue": "1000003", + "UMask": "0x8d", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to latency related stalls including BACLEARs, BTCLEARs, ITLB misses, and ICache misses.", "Counter": "0,1,2,3,4,5,6,7", @@ -2262,6 +2469,14 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the total number of uops retired.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.ALL", + "SampleAfterValue": "1000003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Cycles with retired uop(s).", "Counter": "0,1,2,3,4,5,6,7,8,9", @@ -2273,6 +2488,16 @@ "UMask": "0x2", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of uops retired that were dual destination.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.DUAL_DEST", + "PublicDescription": "Counts the number of uops retired that were dual destination. Dual destination (dual dest) micro-operations require writing to two separate destination registers or memory addresses upon execution. These uops consume two entries in the ROB and tracked separately because they involve more complex operations that necessitate multiple results. Available PDIST counters: 0,1", + "SampleAfterValue": "1000003", + "UMask": "0x10", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of uops retired that are the last uop of a macro-instruction.", "Counter": "0,1,2,3,4,5,6,7", From ab85585e388caf9556f70bf9361b7cbe15af85ac Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:53 -0700 Subject: [PATCH 158/343] perf vendor events intel: Update sapphirerapids events from 1.36 to 1.39 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events and metrics were published in: https://github.com/intel/perfmon/commit/0718b785554ba9bb7f87ad2b838cf25bab5bfa9c https://github.com/intel/perfmon/commit/42fe96774f8bda1d67c6ad7ef7f45b27fae7c696 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- .../arch/x86/sapphirerapids/cache.json | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 70ba1af93822..dbe1fe5a68f6 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -29,7 +29,7 @@ GenuineIntel-6-2E,v4,nehalemex,core GenuineIntel-6-(CC|D5),v1.05,pantherlake,core GenuineIntel-6-A7,v1.04,rocketlake,core GenuineIntel-6-2A,v19,sandybridge,core -GenuineIntel-6-8F,v1.36,sapphirerapids,core +GenuineIntel-6-8F,v1.39,sapphirerapids,core GenuineIntel-6-AF,v1.15,sierraforest,core GenuineIntel-6-(37|4A|4C|4D|5A),v15,silvermont,core GenuineIntel-6-(4E|5E|8E|9E|A5|A6),v59,skylake,core diff --git a/tools/perf/pmu-events/arch/x86/sapphirerapids/cache.json b/tools/perf/pmu-events/arch/x86/sapphirerapids/cache.json index 373b26c84448..4c096b5e6766 100644 --- a/tools/perf/pmu-events/arch/x86/sapphirerapids/cache.json +++ b/tools/perf/pmu-events/arch/x86/sapphirerapids/cache.json @@ -181,6 +181,15 @@ "SampleAfterValue": "200003", "UMask": "0xff" }, + { + "BriefDescription": "All requests that hit L2 cache [This event is alias to L2_RQSTS.HIT]", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "L2_REQUEST.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]", + "SampleAfterValue": "200003", + "UMask": "0xdf" + }, { "BriefDescription": "Read requests with true-miss in L2 cache. [This event is alias to L2_RQSTS.MISS]", "Counter": "0,1,2,3", @@ -279,6 +288,15 @@ "SampleAfterValue": "200003", "UMask": "0x21" }, + { + "BriefDescription": "All requests that hit L2 cache [This event is alias to L2_REQUEST.HIT]", + "Counter": "0,1,2,3", + "EventCode": "0x24", + "EventName": "L2_RQSTS.HIT", + "PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]", + "SampleAfterValue": "200003", + "UMask": "0xdf" + }, { "BriefDescription": "L2_RQSTS.HWPF_MISS", "Counter": "0,1,2,3", @@ -350,6 +368,15 @@ "SampleAfterValue": "200003", "UMask": "0x40" }, + { + "BriefDescription": "Cycles when L1D is locked", + "Counter": "0,1,2,3", + "EventCode": "0x42", + "EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION", + "PublicDescription": "This event counts the number of cycles when the L1D is locked. It is a superset of the 0x1 mask (BUS_LOCK_CLOCKS.BUS_LOCK_DURATION).", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, { "BriefDescription": "Core-originated cacheable requests that missed L3 (Except hardware prefetches to the L3)", "Counter": "0,1,2,3,4,5,6,7", From 33518bdc96c49c7d213f081feefbcb62bc956035 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 28 May 2026 21:51:54 -0700 Subject: [PATCH 159/343] perf vendor events intel: Update sierraforest events from 1.15 to 1.17 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The updated events and metrics were published in: https://github.com/intel/perfmon/commit/efa15280e0577982744642a77af18208aab3635b https://github.com/intel/perfmon/commit/5cdba6c2ccfde2ec13e0e701bc2a374849ce9a44 Reviewed-by: Dapeng Mi Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andreas Färber Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Manivannan Sadhasivam Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Falcon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/arch/x86/mapfile.csv | 2 +- .../arch/x86/sierraforest/cache.json | 49 ++++++ .../arch/x86/sierraforest/floating-point.json | 64 +++++++ .../arch/x86/sierraforest/memory.json | 57 +++++++ .../arch/x86/sierraforest/pipeline.json | 156 ++++++++++++++++++ .../arch/x86/sierraforest/virtual-memory.json | 8 + 6 files changed, 335 insertions(+), 1 deletion(-) diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index dbe1fe5a68f6..50a403b429b1 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -30,7 +30,7 @@ GenuineIntel-6-(CC|D5),v1.05,pantherlake,core GenuineIntel-6-A7,v1.04,rocketlake,core GenuineIntel-6-2A,v19,sandybridge,core GenuineIntel-6-8F,v1.39,sapphirerapids,core -GenuineIntel-6-AF,v1.15,sierraforest,core +GenuineIntel-6-AF,v1.17,sierraforest,core GenuineIntel-6-(37|4A|4C|4D|5A),v15,silvermont,core GenuineIntel-6-(4E|5E|8E|9E|A5|A6),v59,skylake,core GenuineIntel-6-55-[01234],v1.37,skylakex,core diff --git a/tools/perf/pmu-events/arch/x86/sierraforest/cache.json b/tools/perf/pmu-events/arch/x86/sierraforest/cache.json index 168f43557a0e..71acb49b2ab9 100644 --- a/tools/perf/pmu-events/arch/x86/sierraforest/cache.json +++ b/tools/perf/pmu-events/arch/x86/sierraforest/cache.json @@ -1,4 +1,12 @@ [ + { + "BriefDescription": "Counts the number of requests that were not accepted into the L2Q because the L2Q is FULL.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x31", + "EventName": "CORE_REJECT_L2Q.ANY", + "PublicDescription": "Counts the number of (demand and L1 prefetchers) core requests rejected by the L2Q due to a full or nearly full w condition which likely indicates back pressure from L2Q. It also counts requests that would have gone directly to the XQ, but are rejected due to a full or nearly full condition, indicating back pressure from the IDI link. The L2Q may also reject transactions from a core to insure fairness between cores, or to delay a cores dirty eviction when the address conflicts incoming external snoops. (Note that L2 prefetcher requests that are dropped are not counted by this event.) Counts on a per core basis.", + "SampleAfterValue": "200003" + }, { "BriefDescription": "Counts the number of L1D cacheline (dirty) evictions caused by load misses, stores, and prefetches.", "Counter": "0,1,2,3,4,5,6,7", @@ -62,6 +70,14 @@ "SampleAfterValue": "1000003", "UMask": "0x1" }, + { + "BriefDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x30", + "EventName": "L2_REJECT_XQ.ANY", + "PublicDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition which likely indicates back pressure from the IDI link. The XQ may reject transactions from the L2Q (non-cacheable requests), BBL (L2 misses) and WOB (L2 write-back victims).", + "SampleAfterValue": "200003" + }, { "BriefDescription": "Counts the number of L2 Cache Accesses that resulted in a Hit from a front door request only (does not include rejects or recycles), per core event", "Counter": "0,1,2,3,4,5,6,7", @@ -154,6 +170,14 @@ "SampleAfterValue": "1000003", "UMask": "0x1" }, + { + "BriefDescription": "Counts the number of cycles the core is stalled due to a demand load which missed in the L2 cache.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.L2_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x7e" + }, { "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which hit in the LLC. If the core has access to an L3 cache, an LLC hit refers to an L3 cache hit, otherwise it counts zeros.", "Counter": "0,1,2,3,4,5,6,7", @@ -178,6 +202,14 @@ "SampleAfterValue": "1000003", "UMask": "0x78" }, + { + "BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which missed all the caches, a snoop was required, and hits in other core or module on the same die. Another core provides the data with a FWD, NO_FWD, or HITM. If the core has access to an L3 cache, an LLC miss refers to an L3 cache miss, otherwise it is an L2 cache miss.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x34", + "EventName": "MEM_BOUND_STALLS_LOAD.LLC_MISS_OTHERMOD", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, { "BriefDescription": "Counts the number of unhalted cycles when the core is stalled to a store buffer full condition", "Counter": "0,1,2,3,4,5,6,7", @@ -227,6 +259,14 @@ "SampleAfterValue": "1000003", "UMask": "0x4" }, + { + "BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and modified data was forwarded.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_HITM", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, { "BriefDescription": "Counts the number of load ops retired that hit the L1 data cache.", "Counter": "0,1,2,3,4,5,6,7", @@ -307,6 +347,15 @@ "SampleAfterValue": "20003", "UMask": "0x1" }, + { + "BriefDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST)", + "Counter": "0,1,2,3,4,5,6,7", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.ALL", + "SampleAfterValue": "200003", + "UMask": "0x83" + }, { "BriefDescription": "Counts the number of load ops retired.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/sierraforest/floating-point.json b/tools/perf/pmu-events/arch/x86/sierraforest/floating-point.json index 5266eed969be..67d52477aad6 100644 --- a/tools/perf/pmu-events/arch/x86/sierraforest/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/sierraforest/floating-point.json @@ -8,6 +8,22 @@ "SampleAfterValue": "1000003", "UMask": "0x2" }, + { + "BriefDescription": "Counts the number of active floating point dividers per cycle in the loop stage.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_OCCUPANCY", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of floating point divider uops executed per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.FPDIV_UOPS", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, { "BriefDescription": "Counts the number of all types of floating point operations per uop with all default weighting", "Counter": "0,1,2,3,4,5,6,7", @@ -90,6 +106,54 @@ "SampleAfterValue": "1000003", "UMask": "0x2" }, + { + "BriefDescription": "Counts the number of uops executed on all floating point ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0xf" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0, 1, 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.PRIMARY", + "SampleAfterValue": "1000003", + "UMask": "0xe" + }, + { + "BriefDescription": "Counts the number of uops executed on floating point and vector integer store data port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb2", + "EventName": "FP_VINT_UOPS_EXECUTED.STD", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, { "BriefDescription": "Counts the number of floating point operations retired that required microcode assist.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/sierraforest/memory.json b/tools/perf/pmu-events/arch/x86/sierraforest/memory.json index dc850a179517..01e07f90e76b 100644 --- a/tools/perf/pmu-events/arch/x86/sierraforest/memory.json +++ b/tools/perf/pmu-events/arch/x86/sierraforest/memory.json @@ -1,4 +1,12 @@ [ + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.ANY", + "SampleAfterValue": "1000003", + "UMask": "0x7f" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block, on a load that retires.", "Counter": "0,1,2,3,4,5,6,7", @@ -15,6 +23,14 @@ "SampleAfterValue": "1000003", "UMask": "0xf4" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DL1 miss.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.L1_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DL1 miss.", "Counter": "0,1,2,3,4,5,6,7", @@ -23,6 +39,15 @@ "SampleAfterValue": "1000003", "UMask": "0x81" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.OTHER", + "PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases such as pipeline conflicts, fences, etc.", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases.", "Counter": "0,1,2,3,4,5,6,7", @@ -32,6 +57,14 @@ "SampleAfterValue": "1000003", "UMask": "0xc0" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a pagewalk.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.PGWALK", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a pagewalk.", "Counter": "0,1,2,3,4,5,6,7", @@ -40,6 +73,14 @@ "SampleAfterValue": "1000003", "UMask": "0xa0" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a store address match.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.ST_ADDR", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a store address match.", "Counter": "0,1,2,3,4,5,6,7", @@ -48,6 +89,22 @@ "SampleAfterValue": "1000003", "UMask": "0x84" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to request buffers full or lock in progress.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.WCB_FULL_AT_RET", + "SampleAfterValue": "1000003", + "UMask": "0x82" + }, { "BriefDescription": "Counts the number of machine clears due to memory ordering caused by a snoop from an external agent. Does not count internally generated machine clears such as those due to memory disambiguation.", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/sierraforest/pipeline.json b/tools/perf/pmu-events/arch/x86/sierraforest/pipeline.json index cf67ff6135e0..e7ffb0042477 100644 --- a/tools/perf/pmu-events/arch/x86/sierraforest/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/sierraforest/pipeline.json @@ -8,6 +8,31 @@ "SampleAfterValue": "1000003", "UMask": "0x3" }, + { + "BriefDescription": "Counts the number of cycles when any of the integer dividers are active.", + "Counter": "0,1,2,3,4,5,6,7", + "CounterMask": "1", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of active integer dividers per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_OCCUPANCY", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of integer divider uops executed per cycle.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xcd", + "EventName": "ARITH.IDIV_UOPS", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, { "BriefDescription": "Counts the total number of branch instructions retired for all branch types.", "Counter": "0,1,2,3,4,5,6,7", @@ -121,6 +146,15 @@ "SampleAfterValue": "200003", "UMask": "0xdf" }, + { + "BriefDescription": "Counts the number of taken branch instructions retired.", + "Counter": "0,1,2,3,4,5,6,7", + "Errata": "SRF7", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.TAKEN", + "SampleAfterValue": "200003", + "UMask": "0x80" + }, { "BriefDescription": "Counts the total number of mispredicted branch instructions retired for all branch types.", "Counter": "0,1,2,3,4,5,6,7", @@ -244,6 +278,80 @@ "EventName": "INST_RETIRED.ANY_P", "SampleAfterValue": "2000003" }, + { + "BriefDescription": "Counts the number of uops executed on all Integer ports.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.ALL", + "SampleAfterValue": "1000003", + "UMask": "0xff" + }, + { + "BriefDescription": "Counts the number of uops executed on a load port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.LD", + "PublicDescription": "Counts the number of uops executed on a load port. This event counts for integer uops even if the destination is FP/vector", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 0.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P0", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 1.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P1", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 2.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P2", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.P3", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of uops executed on integer port 0,1, 2, 3.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.PRIMARY", + "SampleAfterValue": "1000003", + "UMask": "0x78" + }, + { + "BriefDescription": "Counts the number of uops executed on a Store address port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.STA", + "PublicDescription": "Counts the number of uops executed on a Store address port. This event counts integer uops even if the data source is FP/vector", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts the number of uops executed on an integer store data and jump port.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xb3", + "EventName": "INT_UOPS_EXECUTED.STD_JMP", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, { "BriefDescription": "Counts the number of retired loads that are blocked because it initially appears to be store forward blocked, but subsequently is shown not to be blocked based on 4K alias check.", "Counter": "0,1,2,3,4,5,6,7", @@ -268,6 +376,13 @@ "SampleAfterValue": "1000003", "UMask": "0x2" }, + { + "BriefDescription": "Counts the total number of machine clears for any reason including, but not limited to, memory ordering, memory disambiguation, SMC, and FP assist.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.ANY", + "SampleAfterValue": "20003" + }, { "BriefDescription": "Counts the number of machine clears due to memory ordering in which an internal load passes an older store within the same CPU.", "Counter": "0,1,2,3,4,5,6,7", @@ -276,6 +391,30 @@ "SampleAfterValue": "20003", "UMask": "0x8" }, + { + "BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FAST", + "SampleAfterValue": "20003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts the number of virtual traps taken.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP", + "SampleAfterValue": "20003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts the number of machines clears due to memory renaming.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MRN_NUKE", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, { "BriefDescription": "Counts the number of machine clears due to a page fault. Counts both I-Side and D-Side (Loads/Stores) page faults. A page fault occurs when either the page is not present, or an access violation occurs.", "Counter": "0,1,2,3,4,5,6,7", @@ -349,6 +488,23 @@ "SampleAfterValue": "200003", "UMask": "0x4" }, + { + "BriefDescription": "Counts the number of issue slots not consumed due to a color request for an FCW or MXCSR control register when all 4 colors (copies) are already in use.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.COLOR_STALLS", + "SampleAfterValue": "200003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires.", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x75", + "EventName": "SERIALIZATION.NON_C01_MS_SCB", + "PublicDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires. The most commonly executed instruction with an MS scoreboard is PAUSE.", + "SampleAfterValue": "200003", + "UMask": "0x2" + }, { "BriefDescription": "Counts the number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear. [This event is alias to TOPDOWN_BAD_SPECULATION.ALL_P]", "Counter": "0,1,2,3,4,5,6,7", diff --git a/tools/perf/pmu-events/arch/x86/sierraforest/virtual-memory.json b/tools/perf/pmu-events/arch/x86/sierraforest/virtual-memory.json index 35cc5b6d41f2..88996fdac15f 100644 --- a/tools/perf/pmu-events/arch/x86/sierraforest/virtual-memory.json +++ b/tools/perf/pmu-events/arch/x86/sierraforest/virtual-memory.json @@ -137,6 +137,14 @@ "SampleAfterValue": "200003", "UMask": "0x10" }, + { + "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DTLB miss", + "Counter": "0,1,2,3,4,5,6,7", + "EventCode": "0x05", + "EventName": "LD_HEAD.DTLB_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, { "BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DTLB miss.", "Counter": "0,1,2,3,4,5,6,7", From a43581b5dd1f05dd42f9a7b43e3bdfa09daed440 Mon Sep 17 00:00:00 2001 From: Chun-Tse Shao Date: Thu, 28 May 2026 16:44:54 -0700 Subject: [PATCH 160/343] perf jevents: Add IOMMU metrics for AMD Add IOMMU Translation Lookaside Buffer (TLB) and interrupt cache metrics to perf jevents for AMD platforms. This enhances I/O performance observability, allowing fleet-wide monitoring of IOMMU overhead. These metrics are supported on Zen 2 and newer processors (Rome, Milan, Genoa, Turin) and are implemented using the standard `amd_iommu` PMU events. The implementation uses the existing `_zen_model` helper to ensure these are only generated for Zen 2+. Note that the pde events on AMD cover both 2M and 1G pages, so 1G pages are implicitly included in the total hits/misses metrics (sum of pte and pde events). The following metrics are added: - iotlb_total_hit: Total IOTLB hits (4K, 2M, 1G pages). - iotlb_total_miss: Total IOTLB misses. - iotlb_miss_rate: IOTLB miss rate. - iotlb_interrupt_cache_hit: Interrupt cache hits. - iotlb_interrupt_cache_miss: Interrupt cache misses. - iotlb_interrupt_cache_lookup: Interrupt cache lookups. - iotlb_interrupt_cache_miss_rate: Interrupt cache miss rate. Tested: # perf stat -M \ iotlb_total_hit,iotlb_total_miss,iotlb_miss_rate \ --per-socket --metric-only -a -j -- sleep 10 {"socket" : "S0", "counters" : 10, "hits iotlb_total_hit" : "3579249.0", "% iotlb_miss_rate" : "0.0", "misses iotlb_total_miss" : "3.0"} {"socket" : "S1", "counters" : 10, "hits iotlb_total_hit" : "0.0", "% iotlb_miss_rate" : "0.0", "misses iotlb_total_miss" : "0.0"} Reviewed-by: Ian Rogers Reviewed-by: Sandipan Das Signed-off-by: Chun-Tse Shao Assisted-by: Gemini:gemini-3.1-pro-preview Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Dapeng Mi Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Perry Taylor Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/amd_metrics.py | 57 ++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tools/perf/pmu-events/amd_metrics.py b/tools/perf/pmu-events/amd_metrics.py index 971f6e7af1f8..dccfcacaf148 100755 --- a/tools/perf/pmu-events/amd_metrics.py +++ b/tools/perf/pmu-events/amd_metrics.py @@ -265,6 +265,62 @@ def AmdDtlb() -> Optional[MetricGroup]: ], description="Data TLB metrics") +def AmdIotlb() -> Optional[MetricGroup]: + global _zen_model + if _zen_model < 2: + return None + + # On AMD, the pde events cover both 2M and 1G pages. + total_hit = Event("amd_iommu/mem_iommu_tlb_pte_hit/") + Event( + "amd_iommu/mem_iommu_tlb_pde_hit/" + ) + total_miss = Event("amd_iommu/mem_iommu_tlb_pte_mis/") + Event( + "amd_iommu/mem_iommu_tlb_pde_mis/" + ) + miss_rate = d_ratio(total_miss, total_miss + total_hit) + + interrupt_cache_hit = Event("amd_iommu/int_dte_hit/") + interrupt_cache_miss = Event("amd_iommu/int_dte_mis/") + interrupt_cache_lookup = interrupt_cache_hit + interrupt_cache_miss + interrupt_cache_miss_rate = d_ratio( + interrupt_cache_miss, interrupt_cache_miss + interrupt_cache_hit + ) + + return MetricGroup( + "iotlb", + [ + Metric("iotlb_total_hit", "IOTLB total hit", total_hit, "hits"), + Metric("iotlb_total_miss", "IOTLB total miss", total_miss, "misses"), + Metric("iotlb_miss_rate", "IOTLB miss rate", miss_rate, "100%"), + Metric( + "iotlb_interrupt_cache_hit", + "IOTLB interrupt cache hit", + interrupt_cache_hit, + "hits", + ), + Metric( + "iotlb_interrupt_cache_miss", + "IOTLB interrupt cache miss", + interrupt_cache_miss, + "misses", + ), + Metric( + "iotlb_interrupt_cache_lookup", + "IOTLB interrupt cache lookup", + interrupt_cache_lookup, + "lookups", + ), + Metric( + "iotlb_interrupt_cache_miss_rate", + "IOTLB interrupt cache miss rate", + interrupt_cache_miss_rate, + "100%", + ), + ], + description="IOMMU TLB metrics", + ) + + def AmdItlb(): global _zen_model l2h = Event("bp_l1_tlb_miss_l2_tlb_hit", "bp_l1_tlb_miss_l2_hit") @@ -473,6 +529,7 @@ def main() -> None: AmdBr(), AmdCtxSw(), AmdDtlb(), + AmdIotlb(), AmdItlb(), AmdLdSt(), AmdUpc(), From 3dfaf02e554f63f9b4e68b69deda9617a1948993 Mon Sep 17 00:00:00 2001 From: Chun-Tse Shao Date: Thu, 28 May 2026 16:44:55 -0700 Subject: [PATCH 161/343] perf jevents: Add IOMMU metrics for Intel Add IOMMU Translation Lookaside Buffer (TLB) and interrupt cache metrics to perf jevents for Intel platforms. This enhances I/O performance observability, allowing fleet-wide monitoring of IOMMU overhead. These metrics are supported on platforms that expose the required uncore IIO IOMMU events (such as Emerald Rapids and Granite Rapids). The Intel implementation dynamically detects event availability at generation time. It requires at least the TLB events to expose the metric group, while the interrupt cache events are optional. This allows platforms like Emerald Rapids, which lack IOMMU interrupt cache events, to still expose the IOMMU TLB metrics. The following metrics are added: - iotlb_total_hit: Total IOTLB hits (4K, 2M, 1G pages). - iotlb_total_miss: Total IOTLB misses. - iotlb_miss_rate: IOTLB miss rate. - iotlb_interrupt_cache_hit: Interrupt cache hits. - iotlb_interrupt_cache_miss: Interrupt cache misses (calculated as lookup - hit, clamped to zero). - iotlb_interrupt_cache_lookup: Interrupt cache lookups. - iotlb_interrupt_cache_miss_rate: Interrupt cache miss rate. Tested: # perf stat -M \ iotlb_total_hit,iotlb_total_miss,iotlb_miss_rate \ --per-socket --metric-only -a -j -- sleep 10 {"socket" : "S0", "counters" : 10, "hits iotlb_total_hit" : "3579249.0", "% iotlb_miss_rate" : "0.0", "misses iotlb_total_miss" : "3.0"} {"socket" : "S1", "counters" : 10, "hits iotlb_total_hit" : "0.0", "% iotlb_miss_rate" : "0.0", "misses iotlb_total_miss" : "0.0"} Reviewed-by: Ian Rogers Signed-off-by: Chun-Tse Shao Assisted-by: Gemini:gemini-3.1-pro-preview Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Dapeng Mi Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Perry Taylor Cc: Peter Zijlstra Cc: Sandipan Das Link: https://lore.kernel.org/r/20260528234455.434027-3-ctshao@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/intel_metrics.py | 62 ++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tools/perf/pmu-events/intel_metrics.py b/tools/perf/pmu-events/intel_metrics.py index 52035433b505..c3a5c2965f74 100755 --- a/tools/perf/pmu-events/intel_metrics.py +++ b/tools/perf/pmu-events/intel_metrics.py @@ -457,6 +457,67 @@ def IntelIlp() -> MetricGroup: ]) +def IntelIotlb() -> Optional[MetricGroup]: + try: + total_hit = ( + Event("UNC_IIO_IOMMU0.4K_HITS") + + Event("UNC_IIO_IOMMU0.2M_HITS") + + Event("UNC_IIO_IOMMU0.1G_HITS") + ) + total_miss = Event("UNC_IIO_IOMMU0.MISSES") + except: + return None + + miss_rate = d_ratio(total_miss, total_miss + total_hit) + metrics = [ + Metric("iotlb_total_hit", "IOTLB total hit", total_hit, "hits"), + Metric("iotlb_total_miss", "IOTLB total miss", total_miss, "misses"), + Metric("iotlb_miss_rate", "IOTLB miss rate", miss_rate, "100%"), + ] + + try: + interrupt_cache_hit = Event("UNC_IIO_IOMMU3.INT_CACHE_HITS") + interrupt_cache_lookup = Event("UNC_IIO_IOMMU3.INT_CACHE_LOOKUPS") + interrupt_cache_miss = max(interrupt_cache_lookup - interrupt_cache_hit, 0) + interrupt_cache_miss_rate = d_ratio( + interrupt_cache_miss, interrupt_cache_miss + interrupt_cache_hit + ) + metrics += [ + Metric( + "iotlb_interrupt_cache_hit", + "IOTLB interrupt cache hit", + interrupt_cache_hit, + "hits", + ), + Metric( + "iotlb_interrupt_cache_miss", + "IOTLB interrupt cache miss", + interrupt_cache_miss, + "misses", + ), + Metric( + "iotlb_interrupt_cache_lookup", + "IOTLB interrupt cache lookup", + interrupt_cache_lookup, + "lookups", + ), + Metric( + "iotlb_interrupt_cache_miss_rate", + "IOTLB interrupt cache miss rate", + interrupt_cache_miss_rate, + "100%", + ), + ] + except: + pass + + return MetricGroup( + "iotlb", + metrics, + description="IOMMU TLB metrics", + ) + + def IntelL2() -> Optional[MetricGroup]: try: DC_HIT = Event("L2_RQSTS.DEMAND_DATA_RD_HIT") @@ -1105,6 +1166,7 @@ def main() -> None: IntelCtxSw(), IntelFpu(), IntelIlp(), + IntelIotlb(), IntelL2(), IntelLdSt(), IntelMissLat(), From 167bef4df68635f8bfa2af9108351ee78536d7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Mart=C3=ADn=20Gil?= Date: Tue, 26 May 2026 13:08:52 +0200 Subject: [PATCH 162/343] perf util: Fix perf_exe() buffer write past end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit perf_exe() passes len to readlink() and then unconditionally writes a trailing NUL at buf[n]. If readlink() returns len, the write lands one byte past the buffer. Read at most len - 1 bytes and keep the existing NUL termination. Also guard the fallback path for tiny buffers so copying "perf" cannot overflow. Reviewed-by: Ian Rogers Signed-off-by: Miguel Martín Gil Cc: Ingo Molnar Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/util.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 25849434f0a4..2c2a5c449ffd 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -419,11 +419,21 @@ int perf_tip(char **strp, const char *dirpath) char *perf_exe(char *buf, int len) { - int n = readlink("/proc/self/exe", buf, len); + int n; + + if (len <= 0) + return buf; + + n = readlink("/proc/self/exe", buf, len - 1); if (n > 0) { buf[n] = 0; return buf; } + if (len < (int)sizeof("perf")) { + buf[0] = '\0'; + return buf; + } + return strcpy(buf, "perf"); } From 83eff458a690e650b68cd6467aae8959755c5388 Mon Sep 17 00:00:00 2001 From: James Clark Date: Fri, 10 Apr 2026 12:05:12 +0100 Subject: [PATCH 163/343] perf arm-spe: Don't warn about the discard bit if it doesn't exist Opening an SPE event shows a warning that doesn't concern the user: $ perf record -e arm_spe Unknown/empty format name: discard Perf only wants to know if the discard bit is set for configuring the event, not in response to anything the user has done. Fix it by adding another helper that returns if a config bit exists without warning. We should probably keep the warning in evsel__get_config_val() to avoid having every caller having to do it, and most format bits should never be missing. Add a test for the new helper. Rename the parent test function to be more generic rather than adding a new one as it requires a lot of boilerplate. Reviewed-by: Ian Rogers Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: Jiri Olsa Cc: John Garry Cc: Leo Yan Cc: Mark Rutland Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm64/util/arm-spe.c | 3 ++- tools/perf/tests/pmu.c | 11 +++++++++-- tools/perf/util/evsel.c | 6 ++++++ tools/perf/util/evsel.h | 1 + 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index f00d72d087fc..91bb28cad79a 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -428,7 +428,8 @@ static int arm_spe_recording_options(struct auxtrace_record *itr, evlist__for_each_entry_safe(evlist, tmp, evsel) { if (evsel__is_aux_event(evsel)) { arm_spe_setup_evsel(evsel, cpus); - if (!evsel__get_config_val(evsel, "discard", &discard_bit)) + if (evsel__config_exists(evsel, "discard") && + !evsel__get_config_val(evsel, "discard", &discard_bit)) discard = !!discard_bit; } } diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c index 0ebf2d7b2cb4..d7be9d1c6f52 100644 --- a/tools/perf/tests/pmu.c +++ b/tools/perf/tests/pmu.c @@ -201,7 +201,8 @@ static int test__pmu_format(struct test_suite *test __maybe_unused, int subtest return ret; } -static int test__pmu_usr_chgs(struct test_suite *test __maybe_unused, int subtest __maybe_unused) +static int test__pmu_config_helpers(struct test_suite *test __maybe_unused, + int subtest __maybe_unused) { const char *event = "perf-pmu-test/config=15,config1=4,krava02=170," "krava03=1,krava11=27,krava12=1/"; @@ -236,6 +237,12 @@ static int test__pmu_usr_chgs(struct test_suite *test __maybe_unused, int subtes } evsel = evlist__first(evlist); + /* Test evsel__config_exists() */ + TEST_ASSERT_EQUAL("krava01 should exist", + evsel__config_exists(evsel, "krava01"), true); + TEST_ASSERT_EQUAL("krava99 should not exist", + evsel__config_exists(evsel, "krava99"), false); + /* * Set via config=15, krava01 bits 0-1 * Set via config1=4, krava11 bit 1 @@ -629,7 +636,7 @@ static struct test_case tests__pmu[] = { TEST_CASE("PMU name combining", name_len), TEST_CASE("PMU name comparison", name_cmp), TEST_CASE("PMU cmdline match", pmu_match), - TEST_CASE("PMU user config changes", pmu_usr_chgs), + TEST_CASE("PMU config helpers", pmu_config_helpers), { .name = NULL, } }; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index ac92f9e0e5b4..34c03f47a913 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1399,6 +1399,12 @@ void evsel__set_config_if_unset(struct evsel *evsel, const char *config_name, perf_pmu__format_pack(format->bits, val, vp, /*zero=*/true); } +bool evsel__config_exists(const struct evsel *evsel, const char *config_name) +{ + struct perf_pmu_format *format = pmu_find_format(&evsel->pmu->format, config_name); + + return format && !bitmap_empty(format->bits, PERF_PMU_FORMAT_BITS); +} int evsel__get_config_val(const struct evsel *evsel, const char *config_name, u64 *val) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 3b12d99f0aa9..8178858d168a 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -589,6 +589,7 @@ void evsel__uniquify_counter(struct evsel *counter); ((((src) >> (pos)) & ((1ull << (size)) - 1)) << (63 - ((pos) + (size) - 1))) u64 evsel__bitfield_swap_branch_flags(u64 value); +bool evsel__config_exists(const struct evsel *evsel, const char *config_name); int evsel__get_config_val(const struct evsel *evsel, const char *config_name, u64 *val); void evsel__set_config_if_unset(struct evsel *evsel, const char *config_name, From 6539aef6347ee57301c7e47a518bbc9403dba6fa Mon Sep 17 00:00:00 2001 From: Dapeng Mi Date: Thu, 28 May 2026 10:36:36 -0500 Subject: [PATCH 164/343] perf script: Fix missing '+' indicator when branch counter reaches upper limit When displaying branch counter (br_cntr) information, a "+" suffix represents that event occurrences may have been lost due to branch counter saturation. However, this indicator was missing in perf script. Add it back. Before: # Branch counter abbr list: # cpu_core/event=0xc4,umask=0x20/ppp = A # cpu_core/instructions/ = B # cpu_core/MEM_INST_RETIRED.ALL_LOADS/ = C # cpu_core/MEM_LOAD_RETIRED.L2_MISS/ = D # '-' No event occurs # '+' Event occurrences may be lost due to branch counter saturated ... datasym+190: 00005567f9951676 jz 0x5567f995162dr_cntr: BBBC # PRED 1 cycles [1] ... After: ... datasym+190: 00005567f9951676 jz 0x5567f995162dr_cntr: BBB+C # PRED 1 cycles [1] ... Reviewed-by: Dapeng Mi Signed-off-by: Dapeng Mi Signed-off-by: Thomas Falcon Acked-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index e330ae7f725e..5124edf2b7a6 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1291,8 +1291,12 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, if (!verbose) { for (j = 0; j < num; j++) printed += fprintf(fp, "%s", pos->abbr_name); - } else - printed += fprintf(fp, "%s %d ", pos->name, num); + if (mask && (num == mask)) + printed += fprintf(fp, "+"); + } else { + printed += fprintf(fp, "%s %d%s", pos->name, + num, mask && (num == mask) ? "+ " : " "); + } } if (numprinted == 0 && !verbose) printed += fprintf(fp, "-"); From bb4832101b0969d7d3faf7dd6095274db288cd0f Mon Sep 17 00:00:00 2001 From: Thomas Falcon Date: Thu, 28 May 2026 10:36:37 -0500 Subject: [PATCH 165/343] perf annotate: Fix missing branch counter column in TUI mode 'perf annotate' checks that evlist->nr_br_cntr has been incremented to determine whether to show branch counter information. However, this data is not populated until after the check when events are processed. Therefore, this counter will always be less than zero and the Branch Count column is never shown. Do this check after events have been processed and branch counter data is updated. Reviewed-by: Dapeng Mi Signed-off-by: Thomas Falcon Acked-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 719b36d4eed5..5f450c8093c0 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -559,6 +559,10 @@ static int __cmd_annotate(struct perf_annotate *ann) if (ret) goto out; + if ((use_browser == 1 || ann->use_stdio2) && ann->has_br_stack) + if (session->evlist->nr_br_cntr > 0) + annotate_opts.show_br_cntr = true; + if (dump_trace) { perf_session__fprintf_nr_events(session, stdout); evlist__fprintf_nr_events(session->evlist, stdout); @@ -922,11 +926,8 @@ int cmd_annotate(int argc, const char **argv) * branch counters, if the corresponding branch info is available * in the perf data in the TUI mode. */ - if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) { + if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) sort__mode = SORT_MODE__BRANCH; - if (annotate.session->evlist->nr_br_cntr > 0) - annotate_opts.show_br_cntr = true; - } if (setup_sorting(/*evlist=*/NULL, perf_session__env(annotate.session)) < 0) usage_with_options(annotate_usage, options); From 7a490187f22b4bfae7ef752edbe3fb13017ca11c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 1 Jun 2026 13:07:52 -0300 Subject: [PATCH 166/343] perf sample: Add file_offset field to struct perf_sample Add a file_offset field to struct perf_sample so that event processing callbacks can report the byte offset of the problematic event in perf.data, letting users cross-reference with 'perf report -D' output. Set sample.file_offset in perf_session__deliver_event(), which is the common entry point for both file mode (mmap'd offset) and pipe mode (running byte counter from __perf_session__process_pipe_events). The assignment is placed after evsel__parse_sample(), which zeroes the struct via memset. Preserve file_offset through the deferred callchain delivery path by storing it in struct deferred_event and restoring it after evlist__parse_sample() in both evlist__deliver_deferred_callchain() and session__flush_deferred_samples(). Subsequent patches will use this field in skip/stop warning messages. Reviewed-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sample.h | 2 ++ tools/perf/util/session.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/tools/perf/util/sample.h b/tools/perf/util/sample.h index e556c9b656ea..c4eae8b2fd06 100644 --- a/tools/perf/util/sample.h +++ b/tools/perf/util/sample.h @@ -158,6 +158,8 @@ struct perf_sample { u64 code_page_size; /** @cgroup: The sample event PERF_SAMPLE_CGROUP value. */ u64 cgroup; + /** @file_offset: Byte offset of this event in the perf.data file. */ + u64 file_offset; /** @flags: Extra flag data from auxiliary events like intel-pt. */ u32 flags; /** @machine_pid: The guest machine pid derived from the sample id. */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index e2e821b77766..7996787d742e 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1824,6 +1824,7 @@ static int evlist__deliver_sample(struct evlist *evlist, const struct perf_tool struct deferred_event { struct list_head list; union perf_event *event; + u64 file_offset; }; /* @@ -1858,6 +1859,7 @@ static int evlist__deliver_deferred_callchain(struct evlist *evlist, perf_sample__exit(&orig_sample); break; } + orig_sample.file_offset = de->file_offset; if (sample->tid != orig_sample.tid) { perf_sample__exit(&orig_sample); @@ -1906,6 +1908,7 @@ static int session__flush_deferred_samples(struct perf_session *session, perf_sample__exit(&sample); break; } + sample.file_offset = de->file_offset; sample.evsel = evlist__id2evsel(evlist, sample.id); ret = evlist__deliver_sample(evlist, tool, de->event, @@ -1984,6 +1987,7 @@ static int machines__deliver_event(struct machines *machines, return -ENOMEM; } memcpy(de->event, event, sz); + de->file_offset = sample->file_offset; list_add_tail(&de->list, &evlist->deferred_samples); return 0; } @@ -2126,6 +2130,7 @@ static int perf_session__deliver_event(struct perf_session *session, pr_err("Can't parse sample, err = %d\n", ret); goto out; } + sample.file_offset = file_offset; /* * evsel__parse_sample() doesn't populate machine_pid/vcpu, * which are needed by machines__find_for_cpumode() to From 43f827251af596072834fd6eb2b562468d1990d5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 1 Jun 2026 14:19:30 -0300 Subject: [PATCH 167/343] perf session: Include file offset in event skip/stop messages Add 'at offset %#' to all warning and error messages in session.c that fire when events are skipped or processing stops due to validation failures. This lets users cross-reference with 'perf report -D' output to inspect the surrounding records and understand the corruption context. Covers messages in perf_session__process_event() (alignment, min size, swap failure), perf_session__deliver_event() (no evsel, parse failure, CPU clamping), machines__deliver_event() (NAMESPACES, TEXT_POKE, null-terminated string checks for MMAP/MMAP2/COMM/CGROUP/KSYMBOL), and perf_session__process_user_event() (THREAD_MAP, CPU_MAP, STAT_CONFIG, BPF_METADATA, HEADER_BUILD_ID). Reviewed-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 112 ++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 52 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 7996787d742e..e4efb7550927 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1931,13 +1931,14 @@ static int session__flush_deferred_samples(struct perf_session *session, * read-only (MAP_SHARED + PROT_READ) so we cannot write a * null byte in place; skip the event instead. */ -static bool perf_event__check_nul(const char *str, const void *end, const char *event_name) +static bool perf_event__check_nul(const char *str, const void *end, + const char *event_name, u64 file_offset) { size_t max_len = (const char *)end - str; if (max_len == 0 || strnlen(str, max_len) == max_len) { - pr_warning("WARNING: PERF_RECORD_%s: string not null-terminated, skipping event\n", - event_name); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_%s: string not null-terminated, skipping event\n", + file_offset, event_name); return false; } @@ -1995,7 +1996,7 @@ static int machines__deliver_event(struct machines *machines, case PERF_RECORD_MMAP: if (!perf_event__check_nul(event->mmap.filename, (void *)event + event->header.size, - "MMAP")) + "MMAP", file_offset)) return 0; return tool->mmap(tool, event, sample, machine); case PERF_RECORD_MMAP2: @@ -2003,13 +2004,13 @@ static int machines__deliver_event(struct machines *machines, ++evlist->stats.nr_proc_map_timeout; if (!perf_event__check_nul(event->mmap2.filename, (void *)event + event->header.size, - "MMAP2")) + "MMAP2", file_offset)) return 0; return tool->mmap2(tool, event, sample, machine); case PERF_RECORD_COMM: if (!perf_event__check_nul(event->comm.comm, (void *)event + event->header.size, - "COMM")) + "COMM", file_offset)) return 0; return tool->comm(tool, event, sample, machine); case PERF_RECORD_NAMESPACES: { @@ -2027,8 +2028,8 @@ static int machines__deliver_event(struct machines *machines, * cross-endian path. */ if (event->namespaces.nr_namespaces > max_nr) { - pr_warning("WARNING: PERF_RECORD_NAMESPACES: nr_namespaces %" PRIu64 " exceeds payload (max %" PRIu64 "), skipping\n", - (u64)event->namespaces.nr_namespaces, max_nr); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_NAMESPACES: nr_namespaces %" PRIu64 " exceeds payload (max %" PRIu64 "), skipping\n", + file_offset, (u64)event->namespaces.nr_namespaces, max_nr); return 0; } return tool->namespaces(tool, event, sample, machine); @@ -2036,7 +2037,7 @@ static int machines__deliver_event(struct machines *machines, case PERF_RECORD_CGROUP: if (!perf_event__check_nul(event->cgroup.path, (void *)event + event->header.size, - "CGROUP")) + "CGROUP", file_offset)) return 0; return tool->cgroup(tool, event, sample, machine); case PERF_RECORD_FORK: @@ -2078,7 +2079,7 @@ static int machines__deliver_event(struct machines *machines, case PERF_RECORD_KSYMBOL: if (!perf_event__check_nul(event->ksymbol.name, (void *)event + event->header.size, - "KSYMBOL")) + "KSYMBOL", file_offset)) return 0; return tool->ksymbol(tool, event, sample, machine); case PERF_RECORD_BPF_EVENT: @@ -2090,7 +2091,8 @@ static int machines__deliver_event(struct machines *machines, event->text_poke.new_len; if (event->header.size < text_poke_len) { - pr_warning("WARNING: PERF_RECORD_TEXT_POKE: old_len+new_len exceeds event, skipping\n"); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_TEXT_POKE: old_len+new_len exceeds event, skipping\n", + file_offset); return 0; } return tool->text_poke(tool, event, sample, machine); @@ -2120,14 +2122,17 @@ static int perf_session__deliver_event(struct perf_session *session, perf_sample__init(&sample, /*all=*/false); evsel = evlist__event2evsel(session->evlist, event); if (!evsel) { - pr_err("No evsel found for event type %u\n", + pr_err("ERROR: at offset %#" PRIx64 ": no evsel found for %s (%u) event\n", + file_offset, perf_event__name(event->header.type), event->header.type); ret = -EFAULT; goto out; } ret = evsel__parse_sample(evsel, event, &sample); if (ret) { - pr_err("Can't parse sample, err = %d\n", ret); + pr_err("ERROR: at offset %#" PRIx64 ": can't parse %s (%u) sample, err = %d\n", + file_offset, perf_event__name(event->header.type), + event->header.type, ret); goto out; } sample.file_offset = file_offset; @@ -2204,8 +2209,8 @@ static int perf_session__deliver_event(struct perf_session *session, * Downstream array users (timechart, kwork) have * their own per-callback bounds checks. */ - pr_warning_once("WARNING: sample CPU %u >= nr_cpus_avail %u, clamping to 0\n", - sample.cpu, nr_cpus_avail); + pr_warning_once("WARNING: at offset %#" PRIx64 ": sample CPU %u >= nr_cpus_avail %u, clamping to 0\n", + file_offset, sample.cpu, nr_cpus_avail); sample.cpu = 0; } } @@ -2278,7 +2283,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, case PERF_RECORD_HEADER_BUILD_ID: if (!perf_event__check_nul(event->build_id.filename, (void *)event + event_size, - "HEADER_BUILD_ID")) { + "HEADER_BUILD_ID", file_offset)) { err = 0; break; } @@ -2311,8 +2316,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, u64 max_nr; if (event_size < sizeof(event->thread_map)) { - pr_err("PERF_RECORD_THREAD_MAP: header.size (%u) too small\n", - event_size); + pr_err("ERROR: at offset %#" PRIx64 ": PERF_RECORD_THREAD_MAP: header.size (%u) too small\n", + file_offset, event_size); err = -EINVAL; break; } @@ -2320,8 +2325,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, max_nr = (event_size - sizeof(event->thread_map)) / sizeof(event->thread_map.entries[0]); if (event->thread_map.nr > max_nr) { - pr_err("PERF_RECORD_THREAD_MAP: nr %" PRIu64 " exceeds max %" PRIu64 "\n", - (u64)event->thread_map.nr, max_nr); + pr_err("ERROR: at offset %#" PRIx64 ": PERF_RECORD_THREAD_MAP: nr %" PRIu64 " exceeds max %" PRIu64 "\n", + file_offset, (u64)event->thread_map.nr, max_nr); err = -EINVAL; break; } @@ -2345,8 +2350,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, sizeof(data->cpus_data.cpu[0]); if (data->cpus_data.nr > max_nr) { - pr_warning("WARNING: PERF_RECORD_CPU_MAP: nr %u exceeds payload (max %u), skipping\n", - data->cpus_data.nr, max_nr); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_CPU_MAP: nr %u exceeds payload (max %u), skipping\n", + file_offset, data->cpus_data.nr, max_nr); err = 0; goto out; } @@ -2359,8 +2364,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, sizeof(data->mask32_data.mask[0]); if (data->mask32_data.nr > max_nr) { - pr_warning("WARNING: PERF_RECORD_CPU_MAP mask32: nr %u exceeds payload (max %u), skipping\n", - data->mask32_data.nr, max_nr); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_CPU_MAP mask32: nr %u exceeds payload (max %u), skipping\n", + file_offset, data->mask32_data.nr, max_nr); err = 0; goto out; } @@ -2375,14 +2380,14 @@ static s64 perf_session__process_user_event(struct perf_session *session, mask64_data.mask)) / sizeof(data->mask64_data.mask[0]); if (data->mask64_data.nr > max_nr) { - pr_warning("WARNING: PERF_RECORD_CPU_MAP mask64: nr %u exceeds payload (max %u), skipping\n", - data->mask64_data.nr, max_nr); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_CPU_MAP mask64: nr %u exceeds payload (max %u), skipping\n", + file_offset, data->mask64_data.nr, max_nr); err = 0; goto out; } } else { - pr_warning("WARNING: PERF_RECORD_CPU_MAP: unsupported long_size %u, skipping\n", - data->mask32_data.long_size); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_CPU_MAP: unsupported long_size %u, skipping\n", + file_offset, data->mask32_data.long_size); err = 0; goto out; } @@ -2404,8 +2409,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, * cannot clamp nr in place. Skip the event instead. */ if (event->stat_config.nr > max_nr) { - pr_warning("WARNING: PERF_RECORD_STAT_CONFIG: nr %" PRIu64 " exceeds payload (max %" PRIu64 "), skipping\n", - (u64)event->stat_config.nr, max_nr); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_STAT_CONFIG: nr %" PRIu64 " exceeds payload (max %" PRIu64 "), skipping\n", + file_offset, (u64)event->stat_config.nr, max_nr); err = 0; goto out; } @@ -2446,8 +2451,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, u64 nr_entries, max_entries; if (event_size < sizeof(event->bpf_metadata)) { - pr_warning("WARNING: PERF_RECORD_BPF_METADATA: header.size (%u) too small, skipping\n", - event_size); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_BPF_METADATA: header.size (%u) too small, skipping\n", + file_offset, event_size); err = 0; break; } @@ -2458,7 +2463,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, */ if (strnlen(event->bpf_metadata.prog_name, BPF_PROG_NAME_LEN) == BPF_PROG_NAME_LEN) { - pr_warning("WARNING: PERF_RECORD_BPF_METADATA: prog_name not null-terminated, skipping\n"); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_BPF_METADATA: prog_name not null-terminated, skipping\n", + file_offset); err = 0; break; } @@ -2467,8 +2473,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, max_entries = (event_size - sizeof(event->bpf_metadata)) / sizeof(event->bpf_metadata.entries[0]); if (nr_entries > max_entries) { - pr_warning("WARNING: PERF_RECORD_BPF_METADATA: nr_entries %" PRIu64 " exceeds max %" PRIu64 ", skipping\n", - nr_entries, max_entries); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_BPF_METADATA: nr_entries %" PRIu64 " exceeds max %" PRIu64 ", skipping\n", + file_offset, nr_entries, max_entries); err = 0; break; } @@ -2478,7 +2484,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, BPF_METADATA_KEY_LEN) == BPF_METADATA_KEY_LEN || strnlen(event->bpf_metadata.entries[i].value, BPF_METADATA_VALUE_LEN) == BPF_METADATA_VALUE_LEN) { - pr_warning("WARNING: PERF_RECORD_BPF_METADATA: entry %" PRIu64 " key/value not null-terminated, skipping\n", i); + pr_warning("WARNING: at offset %#" PRIx64 ": PERF_RECORD_BPF_METADATA: entry %" PRIu64 " key/value not null-terminated, skipping\n", + file_offset, i); err = 0; goto out; } @@ -2752,22 +2759,22 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, event->header.type != PERF_RECORD_HEADER_TRACING_DATA && event->header.type != PERF_RECORD_COMPRESSED && event->header.type != PERF_RECORD_HEADER_FEATURE) { - pr_warning("WARNING: peek_event: event type %u size %u not aligned to %zu\n", - event->header.type, - event->header.size, sizeof(u64)); + pr_warning("WARNING: at offset %#" PRIx64 ": %s (%u) event size %u not aligned to %zu\n", + (u64)file_offset, perf_event__name(event->header.type), + event->header.type, event->header.size, sizeof(u64)); return -1; } if (event->header.type >= PERF_RECORD_HEADER_MAX) { - pr_warning("WARNING: peek_event: unsupported event type %u, skipping\n", - event->header.type); + pr_warning("WARNING: at offset %#" PRIx64 ": unsupported event type %u, skipping\n", + (u64)file_offset, event->header.type); return 0; } if (perf_event__too_small(event, &min_sz)) { - pr_warning("WARNING: peek_event: %s event size %u too small (min %u)\n", - perf_event__name(event->header.type), - event->header.size, min_sz); + pr_warning("WARNING: at offset %#" PRIx64 ": %s (%u) event size %u too small (min %u)\n", + (u64)file_offset, perf_event__name(event->header.type), + event->header.type, event->header.size, min_sz); return -1; } @@ -2883,9 +2890,9 @@ static s64 perf_session__process_event(struct perf_session *session, event->header.type != PERF_RECORD_HEADER_TRACING_DATA && event->header.type != PERF_RECORD_COMPRESSED && event->header.type != PERF_RECORD_HEADER_FEATURE) { - pr_err("ERROR: %s event size %u is not 8-byte aligned, aborting\n", - perf_event__name(event->header.type), - event->header.size); + pr_err("ERROR: at offset %#" PRIx64 ": %s (%u) event size %u is not 8-byte aligned, aborting\n", + file_offset, perf_event__name(event->header.type), + event->header.type, event->header.size); return -EINVAL; } @@ -2905,16 +2912,17 @@ static s64 perf_session__process_event(struct perf_session *session, * can be safely stepped over without misaligning the stream. */ if (perf_event__too_small(event, &min_sz)) { - pr_warning("WARNING: %s event size %u too small (min %u), skipping\n", - perf_event__name(event->header.type), - event->header.size, min_sz); + pr_warning("WARNING: at offset %#" PRIx64 ": %s (%u) event size %u too small (min %u), skipping\n", + file_offset, perf_event__name(event->header.type), + event->header.type, event->header.size, min_sz); return 0; } if (session->header.needs_swap && event_swap(event, evlist__sample_id_all(evlist))) { - pr_warning("WARNING: swap failed for %s event, skipping\n", - perf_event__name(event->header.type)); + pr_warning("WARNING: at offset %#" PRIx64 ": swap failed for %s (%u) event, skipping\n", + file_offset, perf_event__name(event->header.type), + event->header.type); return 0; } From d38bee6d8082c23635faa5473162291d228ca96e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 1 Jun 2026 14:21:44 -0300 Subject: [PATCH 168/343] perf sched: Include file offset in event skip messages Add the perf.data file offset to the CPU out-of-bounds and machine__resolve failure messages emitted when samples are skipped in process_sched_switch_event(), process_sched_runtime_event(), and timehist_sched_change_event(). Also switch event type from raw integer to perf_event__name() string for readability. Reviewed-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 812a1b0d56d6..9ec8e049e19b 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1792,8 +1792,10 @@ static int process_sched_switch_event(const struct perf_tool *tool, u32 prev_pid = perf_sample__intval(sample, "prev_pid"), next_pid = perf_sample__intval(sample, "next_pid"); + /* perf.data is untrusted input — CPU may be absent or corrupted */ if (this_cpu < 0 || this_cpu >= MAX_CPUS) { - pr_warning("Out-of-bound sample CPU %d. Skipping sample\n", this_cpu); + pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n", + sample->file_offset, this_cpu); return 0; } @@ -1819,8 +1821,10 @@ static int process_sched_runtime_event(const struct perf_tool *tool, { struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + /* perf.data is untrusted input — CPU may be absent or corrupted */ if (sample->cpu >= MAX_CPUS) { - pr_warning("Out-of-bound sample CPU %u. Skipping sample\n", sample->cpu); + pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %u, skipping sample\n", + sample->file_offset, sample->cpu); return 0; } @@ -2786,15 +2790,18 @@ static int timehist_sched_change_event(const struct perf_tool *tool, int rc = 0; const char state = perf_sample__taskstate(sample, "prev_state"); + /* perf.data is untrusted input — CPU may be absent or corrupted */ if (sample->cpu >= MAX_CPUS) { - pr_warning("Out-of-bound sample CPU %d. Skipping sample\n", sample->cpu); + pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n", + sample->file_offset, sample->cpu); return 0; } addr_location__init(&al); if (machine__resolve(machine, &al, sample) < 0) { - pr_err("problem processing %d event. skipping it\n", - event->header.type); + pr_err("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); rc = -1; goto out; } From 4cd74dee09d4b06f0e80826bf9d472d5aa42caaf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 1 Jun 2026 14:25:40 -0300 Subject: [PATCH 169/343] perf timechart: Include file offset in CPU bounds check messages Add the perf.data file offset to the out-of-bounds CPU debug messages in process_sample_cpu_idle(), process_sample_cpu_frequency(), process_sample_sched_wakeup(), and process_sample_sched_switch(). Reviewed-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-timechart.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 630756bebe32..071987241a52 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -605,8 +605,10 @@ process_sample_cpu_idle(struct timechart *tchart __maybe_unused, u32 state = perf_sample__intval(sample, "state"); u32 cpu_id = perf_sample__intval(sample, "cpu_id"); + /* perf.data is untrusted input — cpu_id may be corrupted */ if (cpu_id >= MAX_CPUS) { - pr_debug("Out-of-bounds cpu_id %u\n", cpu_id); + pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu_id %u\n", + sample->file_offset, cpu_id); return -1; } if (state == (u32)PWR_EVENT_EXIT) @@ -624,8 +626,10 @@ process_sample_cpu_frequency(struct timechart *tchart, u32 state = perf_sample__intval(sample, "state"); u32 cpu_id = perf_sample__intval(sample, "cpu_id"); + /* perf.data is untrusted input — cpu_id may be corrupted */ if (cpu_id >= MAX_CPUS) { - pr_debug("Out-of-bounds cpu_id %u\n", cpu_id); + pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu_id %u\n", + sample->file_offset, cpu_id); return -1; } p_state_change(tchart, cpu_id, sample->time, state); @@ -641,8 +645,10 @@ process_sample_sched_wakeup(struct timechart *tchart, int waker = perf_sample__intval(sample, "common_pid"); int wakee = perf_sample__intval(sample, "pid"); + /* perf.data is untrusted input — CPU may be absent or corrupted */ if (sample->cpu >= MAX_CPUS) { - pr_debug("Out-of-bounds cpu %u\n", sample->cpu); + pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu %u\n", + sample->file_offset, sample->cpu); return -1; } sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace); @@ -658,8 +664,10 @@ process_sample_sched_switch(struct timechart *tchart, int next_pid = perf_sample__intval(sample, "next_pid"); u64 prev_state = perf_sample__intval(sample, "prev_state"); + /* perf.data is untrusted input — CPU may be absent or corrupted */ if (sample->cpu >= MAX_CPUS) { - pr_debug("Out-of-bounds cpu %u\n", sample->cpu); + pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu %u\n", + sample->file_offset, sample->cpu); return -1; } sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid, @@ -676,6 +684,7 @@ process_sample_power_start(struct timechart *tchart __maybe_unused, u64 cpu_id = perf_sample__intval(sample, "cpu_id"); u64 value = perf_sample__intval(sample, "value"); + /* perf.data is untrusted input — cpu_id may be corrupted */ if (cpu_id >= MAX_CPUS) { pr_debug("Out-of-bounds cpu_id %llu\n", (unsigned long long)cpu_id); return -1; @@ -689,6 +698,7 @@ process_sample_power_end(struct timechart *tchart, struct perf_sample *sample, const char *backtrace __maybe_unused) { + /* perf.data is untrusted input — CPU may be absent or corrupted */ if (sample->cpu >= MAX_CPUS) { pr_debug("Out-of-bounds cpu %u\n", sample->cpu); return -1; @@ -705,6 +715,7 @@ process_sample_power_frequency(struct timechart *tchart, u64 cpu_id = perf_sample__intval(sample, "cpu_id"); u64 value = perf_sample__intval(sample, "value"); + /* perf.data is untrusted input — cpu_id may be corrupted */ if (cpu_id >= MAX_CPUS) { pr_debug("Out-of-bounds cpu_id %llu\n", (unsigned long long)cpu_id); return -1; From 865224bfde78b31be8883302db496ecb3b7919ab Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 1 Jun 2026 15:21:20 -0300 Subject: [PATCH 170/343] perf tools: Include file offset and event type name in skip messages Add the perf.data file offset and use perf_event__name() instead of raw event type integers in the 'problem processing event, skipping it' messages emitted by process_sample_event() callbacks across annotate, c2c, diff, kmem, kvm, kwork, lock, report, script, and build-id. This lets users cross-reference skipped events with 'perf report -D' output. Also add explicit #include "util/event.h" and where needed to avoid depending on transitive includes. Reviewed-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 5 +++-- tools/perf/builtin-c2c.c | 5 +++-- tools/perf/builtin-diff.c | 8 +++++--- tools/perf/builtin-kmem.c | 6 ++++-- tools/perf/builtin-kvm.c | 9 ++++++--- tools/perf/builtin-kwork.c | 4 +++- tools/perf/builtin-lock.c | 6 ++++-- tools/perf/builtin-report.c | 9 ++++++--- tools/perf/builtin-script.c | 10 ++++++---- tools/perf/util/build-id.c | 5 +++-- 10 files changed, 43 insertions(+), 24 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 5f450c8093c0..b918f9eed5fd 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -288,8 +288,9 @@ static int process_sample_event(const struct perf_tool *tool, addr_location__init(&al); if (machine__resolve(machine, &al, sample) < 0) { - pr_warning("problem processing %d event, skipping it.\n", - event->header.type); + pr_warning("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); ret = -1; goto out_put; } diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 36f386949923..d3503be9350c 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -328,8 +328,9 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, addr_location__init(&al); if (machine__resolve(machine, &al, sample) < 0) { - pr_debug("problem processing %d event, skipping it.\n", - event->header.type); + pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); ret = -1; goto out; } diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index b4ff863b304c..9592f44b6545 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -409,8 +409,9 @@ static int diff__process_sample_event(const struct perf_tool *tool, addr_location__init(&al); if (machine__resolve(machine, &al, sample) < 0) { - pr_warning("problem processing %d event, skipping it.\n", - event->header.type); + pr_warning("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); ret = -1; goto out; } @@ -436,7 +437,8 @@ static int diff__process_sample_event(const struct perf_tool *tool, case COMPUTE_STREAM: if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, NULL)) { - pr_debug("problem adding hist entry, skipping event\n"); + pr_debug("problem adding hist entry at offset %#" PRIx64 ", skipping event\n", + sample->file_offset); goto out; } break; diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 33585e353efe..e1b2f5bc1ba8 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -22,6 +22,7 @@ #include "util/cpumap.h" #include "util/debug.h" +#include "util/event.h" #include "util/string2.h" #include "util/util.h" @@ -987,8 +988,9 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, sample->tid); if (thread == NULL) { - pr_debug("problem processing %d event, skipping it.\n", - event->header.type); + pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); return -1; } diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index dd2ed21596aa..394302ebdb16 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -22,6 +22,7 @@ #include "util/synthetic-events.h" #include "util/top.h" #include "util/data.h" +#include "util/event.h" #include "util/ordered-events.h" #include "util/kvm-stat.h" #include "util/util.h" @@ -1141,14 +1142,16 @@ static int process_sample_event(const struct perf_tool *tool, return 0; if (machine__resolve(machine, &kvm->al, sample) < 0) { - pr_warning("Fail to resolve address location, skip sample.\n"); + pr_warning("WARNING: at offset %#" PRIx64 ": fail to resolve address location, skipping sample\n", + sample->file_offset); return 0; } thread = machine__findnew_thread(machine, sample->pid, sample->tid); if (thread == NULL) { - pr_debug("problem processing %d event, skipping it.\n", - event->header.type); + pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); return -1; } diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index 99dc293a0744..110de3507d48 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -9,6 +9,7 @@ #include "perf.h" #include "util/data.h" +#include "util/event.h" #include "util/evlist.h" #include "util/evsel.h" #include "util/header.h" @@ -897,7 +898,8 @@ static int timehist_exit_event(struct perf_kwork *kwork, addr_location__init(&al); if (machine__resolve(machine, &al, sample) < 0) { - pr_debug("Problem processing event, skipping it\n"); + pr_debug("problem processing event at offset %#" PRIx64 ", skipping it\n", + sample->file_offset); ret = -1; goto out; } diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 94a8c35abb0b..5841d43be971 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -21,6 +21,7 @@ #include "util/tracepoint.h" #include "util/debug.h" +#include "util/event.h" #include "util/session.h" #include "util/tool.h" #include "util/data.h" @@ -1433,8 +1434,9 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, sample->tid); if (thread == NULL) { - pr_debug("problem processing %d event, skipping it.\n", - event->header.type); + pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); return -1; } diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 973d97af8501..cd052aa78132 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -27,6 +27,7 @@ #include "perf.h" #include "util/debug.h" +#include "util/event.h" #include "util/evlist.h" #include "util/evsel.h" #include "util/evswitch.h" @@ -284,8 +285,9 @@ static int process_sample_event(const struct perf_tool *tool, addr_location__init(&al); if (machine__resolve(machine, &al, sample) < 0) { - pr_debug("problem processing %d event, skipping it.\n", - event->header.type); + pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); ret = -1; goto out_put; } @@ -332,7 +334,8 @@ static int process_sample_event(const struct perf_tool *tool, ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep); if (ret < 0) - pr_debug("problem adding hist entry, skipping event\n"); + pr_debug("problem adding hist entry at offset %#" PRIx64 ", skipping event\n", + sample->file_offset); out_put: addr_location__exit(&al); return ret; diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 5124edf2b7a6..f4aa255fc329 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2693,8 +2693,9 @@ static int process_sample_event(const struct perf_tool *tool, goto out_put; if (!al.thread && machine__resolve(machine, &al, sample) < 0) { - pr_err("problem processing %d event, skipping it.\n", - event->header.type); + pr_err("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); ret = -1; goto out_put; } @@ -2775,8 +2776,9 @@ static int process_deferred_sample_event(const struct perf_tool *tool, goto out_put; if (machine__resolve(machine, &al, sample) < 0) { - pr_err("problem processing %d event, skipping it.\n", - event->header.type); + pr_err("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); ret = -1; goto out_put; } diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index af4d874f1381..8c0a9ae932aa 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -10,6 +10,7 @@ #include "util.h" // lsdir(), mkdir_p(), rm_rf() #include #include +#include #include #include #include @@ -62,8 +63,8 @@ int build_id__mark_dso_hit(const struct perf_tool *tool __maybe_unused, sample->tid); if (thread == NULL) { - pr_err("problem processing %d event, skipping it.\n", - event->header.type); + pr_err("problem processing %s event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), sample->file_offset); return -1; } From fa06520fa0aae5a8e7386c1d6b622c4d8b6a400d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 1 Jun 2026 19:24:42 -0300 Subject: [PATCH 171/343] perf timechart: Fix cat_backtrace() use-after-free on corrupted callchain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cat_backtrace() uses open_memstream() to build a backtrace string. When an invalid callchain context is encountered, zfree(&p) frees the memstream buffer, then the exit path calls fclose(f), which flushes to the already-freed buffer — a use-after-free. The function then returns a dangling pointer that the caller passes to a handler and subsequently double-frees. Fix by replacing the zfree(&p) with a 'corrupted' flag. At the exit label, always fclose(f) first (which finalizes the buffer), then conditionally free it when corrupted. This ensures the memstream contract is honored: the buffer remains valid until fclose(). While here, update the machine__resolve failure message to include file_offset and the event type name, matching the pattern from the preceding series. Also update the three legacy power event handlers under SUPPORT_OLD_POWER_EVENTS to include file_offset in their out-of-bounds CPU messages for consistency. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-timechart.c | 36 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 071987241a52..85a9ad0455ae 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -489,6 +489,10 @@ static void sched_switch(struct timechart *tchart, int cpu, u64 timestamp, } } +/* + * Returns a malloc'd backtrace string built via open_memstream, or NULL + * on error. Caller must free() the returned pointer. + */ static char *cat_backtrace(union perf_event *event, struct perf_sample *sample, struct machine *machine) @@ -500,6 +504,7 @@ static char *cat_backtrace(union perf_event *event, u8 cpumode = PERF_RECORD_MISC_USER; struct ip_callchain *chain = sample->callchain; FILE *f = open_memstream(&p, &p_len); + bool corrupted = false; if (!f) { perror("open_memstream error"); @@ -511,8 +516,9 @@ static char *cat_backtrace(union perf_event *event, goto exit; if (machine__resolve(machine, &al, sample) < 0) { - fprintf(stderr, "problem processing %d event, skipping it.\n", - event->header.type); + pr_err("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); goto exit; } @@ -537,14 +543,8 @@ static char *cat_backtrace(union perf_event *event, cpumode = PERF_RECORD_MISC_USER; break; default: - pr_debug("invalid callchain context: " - "%"PRId64"\n", (s64) ip); - - /* - * It seems the callchain is corrupted. - * Discard all. - */ - zfree(&p); + pr_debug("invalid callchain context: %" PRId64 "\n", (s64) ip); + corrupted = true; goto exit; } continue; @@ -561,7 +561,14 @@ static char *cat_backtrace(union perf_event *event, } exit: addr_location__exit(&al); + /* + * fclose() on an open_memstream always sets p to a valid buffer, + * even if nothing was written — see open_memstream(3). So p is + * never NULL after fclose and we need the flag to discard it. + */ fclose(f); + if (corrupted) + zfree(&p); return p; } @@ -686,7 +693,8 @@ process_sample_power_start(struct timechart *tchart __maybe_unused, /* perf.data is untrusted input — cpu_id may be corrupted */ if (cpu_id >= MAX_CPUS) { - pr_debug("Out-of-bounds cpu_id %llu\n", (unsigned long long)cpu_id); + pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu_id %llu\n", + sample->file_offset, (unsigned long long)cpu_id); return -1; } c_state_start(cpu_id, sample->time, value); @@ -700,7 +708,8 @@ process_sample_power_end(struct timechart *tchart, { /* perf.data is untrusted input — CPU may be absent or corrupted */ if (sample->cpu >= MAX_CPUS) { - pr_debug("Out-of-bounds cpu %u\n", sample->cpu); + pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu %u\n", + sample->file_offset, sample->cpu); return -1; } c_state_end(tchart, sample->cpu, sample->time); @@ -717,7 +726,8 @@ process_sample_power_frequency(struct timechart *tchart, /* perf.data is untrusted input — cpu_id may be corrupted */ if (cpu_id >= MAX_CPUS) { - pr_debug("Out-of-bounds cpu_id %llu\n", (unsigned long long)cpu_id); + pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu_id %llu\n", + sample->file_offset, (unsigned long long)cpu_id); return -1; } p_state_change(tchart, cpu_id, sample->time, value); From 1e2c83f732deb329ebce23e26cbc482f4c4bf194 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 1 Jun 2026 19:53:41 -0300 Subject: [PATCH 172/343] perf sched: Replace BUG_ON on invalid CPU with graceful skip latency_switch_event(), latency_runtime_event(), and map_switch_event() use BUG_ON(cpu >= MAX_CPUS || cpu < 0) to validate the sample CPU. When PERF_SAMPLE_CPU is absent from the sample type, evsel__parse_sample() initializes sample->cpu to (u32)-1. Casting this to int yields -1, which triggers the BUG_ON and aborts perf sched. The central CPU validation in perf_session__deliver_event() intentionally preserves the (u32)-1 sentinel for downstream tools like perf script and perf inject, so leaf callbacks must handle it themselves. Replace the three BUG_ON calls with graceful skips using pr_warning(), matching the existing pattern in process_sched_switch_event() and process_sched_runtime_event() earlier in the same file. Include the file offset for cross-referencing with perf report -D. Reported-by: sashiko-bot@kernel.org # Running on a local machine Reviewed-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 9ec8e049e19b..81833d169470 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1145,7 +1145,12 @@ static int latency_switch_event(struct perf_sched *sched, int cpu = sample->cpu, err = -1; s64 delta; - BUG_ON(cpu >= MAX_CPUS || cpu < 0); + /* perf.data is untrusted input — CPU may be absent or corrupted */ + if (cpu >= MAX_CPUS || cpu < 0) { + pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n", + sample->file_offset, cpu); + return 0; + } timestamp0 = sched->cpu_last_switched[cpu]; sched->cpu_last_switched[cpu] = timestamp; @@ -1215,7 +1220,13 @@ static int latency_runtime_event(struct perf_sched *sched, if (thread == NULL) return -1; - BUG_ON(cpu >= MAX_CPUS || cpu < 0); + /* perf.data is untrusted input — CPU may be absent or corrupted */ + if (cpu >= MAX_CPUS || cpu < 0) { + pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n", + sample->file_offset, cpu); + err = 0; + goto out_put; + } if (!atoms) { if (thread_atoms_insert(sched, thread)) goto out_put; @@ -1640,7 +1651,12 @@ static int map_switch_event(struct perf_sched *sched, struct perf_sample *sampl const char *str; int ret = -1; - BUG_ON(this_cpu.cpu >= MAX_CPUS || this_cpu.cpu < 0); + /* perf.data is untrusted input — CPU may be absent or corrupted */ + if (this_cpu.cpu >= MAX_CPUS || this_cpu.cpu < 0) { + pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n", + sample->file_offset, this_cpu.cpu); + return 0; + } if (this_cpu.cpu > sched->max_cpu.cpu) sched->max_cpu = this_cpu; From 078fc0430bf17e2a571e36877c1942f6c0860524 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 2 Jun 2026 20:45:14 -0300 Subject: [PATCH 173/343] perf test: Add file offset diagnostic test for corrupted perf.data Add a shell test that verifies the file_offset diagnostic messages work correctly when perf encounters corrupted events. The test corrupts a MMAP2 event's size field in a recorded perf.data file, then checks that perf report produces warning messages that include both the file offset (e.g. "at offset 0x2738:") and the event type name with numeric id (e.g. "MMAP2 (10)"). This exercises the diagnostic improvements from the file_offset series, which retrofitted all skip/stop/error messages to include the position and type of the problematic event. Reviewed-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- .../shell/data_file_offset_diagnostics.sh | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100755 tools/perf/tests/shell/data_file_offset_diagnostics.sh diff --git a/tools/perf/tests/shell/data_file_offset_diagnostics.sh b/tools/perf/tests/shell/data_file_offset_diagnostics.sh new file mode 100755 index 000000000000..389b0b84752d --- /dev/null +++ b/tools/perf/tests/shell/data_file_offset_diagnostics.sh @@ -0,0 +1,91 @@ +#!/bin/bash +# Test that perf report includes file offsets and event type names in diagnostic messages. +# SPDX-License-Identifier: GPL-2.0 +# +# The file_offset diagnostic series adds "at offset 0x...: TYPE (N)" +# to all skip/stop/error messages. This test corrupts an event's size +# field in a perf.data file, then verifies the resulting warning +# includes the file offset and event type. + +err=0 + +cleanup() { + [ -n "${perfdata}" ] && rm -f "${perfdata}" "${perfdata}.old" + rm -f "${corrupted}" "${stderrfile}" + trap - EXIT TERM INT +} +trap 'cleanup; exit 1' TERM INT +trap cleanup EXIT + +perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2 +corrupted=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2 +stderrfile=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2 + +if ! perf record -o "${perfdata}" -- perf test -w noploop 2>/dev/null; then + echo "Skip: perf record failed" + cleanup + exit 2 +fi + +# Find the file offset of the first MMAP2 event via perf report -D. +# Format: "timestamp 0xOFFSET [0xSIZE]: PERF_RECORD_MMAP2 ..." +mmap2_line=$(perf report -D -i "${perfdata}" 2>/dev/null | grep "PERF_RECORD_MMAP2" | head -1) +if [ -z "${mmap2_line}" ]; then + echo "Skip: no MMAP2 events found in perf.data" + cleanup + exit 2 +fi + +mmap2_offset=$(echo "${mmap2_line}" | awk '{print $2}') +mmap2_offset_dec=$((mmap2_offset)) + +# Copy the file and corrupt the MMAP2 event's size field. +# perf_event_header layout: type(u32) misc(u16) size(u16) +# Set size to 16 — below the MMAP2 minimum, which triggers +# the "event size too small" warning. +# +# perf.data uses native byte order, so write the u16 in the +# host's endianness to work on both LE and BE architectures. +cp "${perfdata}" "${corrupted}" +if printf '\x01\x02' | od -A n -t x2 | grep -q "0201"; then + # Little-endian + printf '\x10\x00' +else + # Big-endian + printf '\x00\x10' +fi | dd of="${corrupted}" bs=1 seek=$((mmap2_offset_dec + 6)) conv=notrunc 2>/dev/null + +perf report -i "${corrupted}" --stdio > /dev/null 2> "${stderrfile}" + +# Check that warnings include "at offset 0x..." +if grep -q "at offset 0x" "${stderrfile}"; then + echo "File offset in diagnostics [Success]" +else + echo "File offset in diagnostics [Failed: no 'at offset 0x...' found]" + echo " stderr was:" + head -5 "${stderrfile}" + err=1 +fi + +# Check that the event type name and numeric id appear: "MMAP2 (10)" +if grep -q "MMAP2 (10)" "${stderrfile}"; then + echo "Event type name in diagnostics [Success]" +else + echo "Event type name in diagnostics [Failed: no 'MMAP2 (10)' found]" + echo " stderr was:" + head -5 "${stderrfile}" + err=1 +fi + +# Check that the reported offset matches the actual corruption point +if grep -q "at offset ${mmap2_offset}:" "${stderrfile}"; then + echo "Correct offset reported [Success]" +else + echo "Correct offset reported [Failed: expected offset ${mmap2_offset}]" + echo " stderr was:" + head -5 "${stderrfile}" + err=1 +fi + +cleanup +exit ${err} From ed52302f51ccb217a1d1b70bd7cec36d6f75693c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:24:58 -0700 Subject: [PATCH 174/343] perf env: Add perf_env__e_machine helper and use in perf_env__arch Add a helper that lazily computes the e_machine and falls back to EM_HOST. Use the perf_env's arch to compute the e_machine if available, using a binary search for efficiency while handling duplicate rules. Switch perf_env__arch to be derived from e_machine for consistency. To support 32-bit compat binaries on 64-bit hosts during dynamic local or live operations, unpopulated arch fallback paths query uname() at runtime to dynamically resolve the correct host e_machine, safely preventing bitness misclassification regressions. Update session and header to use the helper to safely record e_machine and flags without forcing premature thread scanning. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/env.c | 290 ++++++++++++++++++++++++++++++++------ tools/perf/util/env.h | 2 + tools/perf/util/header.c | 32 +++-- tools/perf/util/session.c | 26 ++-- 4 files changed, 284 insertions(+), 66 deletions(-) diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 20953ef7b9d8..0cd23b5fc651 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -1,10 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 #include "cpumap.h" +#include "dwarf-regs.h" #include "debug.h" #include "env.h" #include "util/header.h" #include "util/rwsem.h" #include +#include #include #include #include @@ -309,15 +311,27 @@ void perf_env__init(struct perf_env *env) static void perf_env__init_kernel_mode(struct perf_env *env) { - const char *arch = perf_env__raw_arch(env); + const char *arch = env->arch; - if (!strncmp(arch, "x86_64", 6) || !strncmp(arch, "aarch64", 7) || - !strncmp(arch, "arm64", 5) || !strncmp(arch, "mips64", 6) || - !strncmp(arch, "parisc64", 8) || !strncmp(arch, "riscv64", 7) || - !strncmp(arch, "s390x", 5) || !strncmp(arch, "sparc64", 7)) - env->kernel_is_64_bit = 1; - else - env->kernel_is_64_bit = 0; + if (!arch) { + static struct utsname uts = { .machine[0] = '\0', }; + + if (uts.machine[0] == '\0') + uname(&uts); + if (uts.machine[0] != '\0') + arch = uts.machine; + } + + if (arch) { + if (strstr(arch, "64") || strstr(arch, "s390x")) + env->kernel_is_64_bit = 1; + else + env->kernel_is_64_bit = 0; + return; + } + + /* Fallback if completely unresolvable (assume host-bitness) */ + env->kernel_is_64_bit = (sizeof(void *) == 8) ? 1 : 0; } int perf_env__kernel_is_64_bit(struct perf_env *env) @@ -588,51 +602,237 @@ void cpu_cache_level__free(struct cpu_cache_level *cache) zfree(&cache->size); } -/* - * Return architecture name in a normalized form. - * The conversion logic comes from the Makefile. - */ -static const char *normalize_arch(char *arch) -{ - if (!strcmp(arch, "x86_64")) - return "x86"; - if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6') - return "x86"; - if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5)) - return "sparc"; - if (!strncmp(arch, "aarch64", 7) || !strncmp(arch, "arm64", 5)) - return "arm64"; - if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110")) - return "arm"; - if (!strncmp(arch, "s390", 4)) - return "s390"; - if (!strncmp(arch, "parisc", 6)) - return "parisc"; - if (!strncmp(arch, "powerpc", 7) || !strncmp(arch, "ppc", 3)) - return "powerpc"; - if (!strncmp(arch, "mips", 4)) - return "mips"; - if (!strncmp(arch, "sh", 2) && isdigit(arch[2])) - return "sh"; - if (!strncmp(arch, "loongarch", 9)) - return "loongarch"; +struct arch_to_e_machine { + const char *prefix; + uint16_t e_machine; +}; - return arch; +/* + * A mapping from an arch prefix string to an ELF machine that can be used in a + * bsearch. Some arch prefixes are shared an need additional processing as + * marked next to the architecture. The prefixes handle both perf's architecture + * naming and those from uname. + */ +static const struct arch_to_e_machine prefix_to_e_machine[] = { + {"aarch64", EM_AARCH64}, + {"alpha", EM_ALPHA}, + {"arc", EM_ARC}, + {"arm", EM_ARM}, /* Check also for EM_AARCH64. */ + {"avr", EM_AVR}, /* Check also for EM_AVR32. */ + {"bfin", EM_BLACKFIN}, + {"blackfin", EM_BLACKFIN}, + {"cris", EM_CRIS}, + {"csky", EM_CSKY}, + {"hppa", EM_PARISC}, + {"i386", EM_386}, + {"i486", EM_386}, + {"i586", EM_386}, + {"i686", EM_386}, + {"loongarch", EM_LOONGARCH}, + {"m32r", EM_M32R}, + {"m68k", EM_68K}, + {"microblaze", EM_MICROBLAZE}, + {"mips", EM_MIPS}, + {"msp430", EM_MSP430}, + {"parisc", EM_PARISC}, + {"powerpc", EM_PPC}, /* Check also for EM_PPC64. */ + {"ppc", EM_PPC}, /* Check also for EM_PPC64. */ + {"riscv", EM_RISCV}, + {"s390", EM_S390}, + {"sa110", EM_ARM}, + {"sh", EM_SH}, + {"sparc", EM_SPARC}, /* Check also for EM_SPARCV9. */ + {"sun4u", EM_SPARC}, + {"x86", EM_X86_64}, /* Check also for EM_386. */ + {"xtensa", EM_XTENSA}, +}; + +static int compare_prefix(const void *key, const void *element) +{ + const char *search_key = key; + const struct arch_to_e_machine *map_element = element; + size_t prefix_len = strlen(map_element->prefix); + + return strncmp(search_key, map_element->prefix, prefix_len); +} + +static uint16_t perf_arch_to_e_machine(const char *perf_arch, int is_64_bit) +{ + /* Binary search for a matching prefix. */ + const struct arch_to_e_machine *result; + + if (!perf_arch) + return EM_HOST; + + result = bsearch(perf_arch, + prefix_to_e_machine, ARRAY_SIZE(prefix_to_e_machine), + sizeof(prefix_to_e_machine[0]), + compare_prefix); + + if (!result) { + pr_debug("Unknown perf arch for ELF machine mapping: %s\n", perf_arch); + return EM_NONE; + } + + /* + * Handle conflicting prefixes. If the is_64_bit is unknown (-1) then + * assume 64-bit. We can't use perf_env__kernel_is_64_bit as that + * depends on the arch string. + */ + switch (result->e_machine) { + case EM_ARM: + return !strcmp(perf_arch, "arm64") || !strcmp(perf_arch, "aarch64") + ? EM_AARCH64 : EM_ARM; + case EM_AVR: + return !strcmp(perf_arch, "avr32") ? EM_AVR32 : EM_AVR; + case EM_PPC: + if (is_64_bit == 1) + return EM_PPC64; + if (is_64_bit == 0) + return EM_PPC; + return strstarts(perf_arch, "ppc64") ? EM_PPC64 : EM_PPC; + case EM_SPARC: + if (is_64_bit == 1) + return EM_SPARCV9; + if (is_64_bit == 0) + return EM_SPARC; + return !strcmp(perf_arch, "sparc64") || !strcmp(perf_arch, "sun4u") + ? EM_SPARCV9 : EM_SPARC; + case EM_X86_64: + if (is_64_bit == 1) + return EM_X86_64; + if (is_64_bit == 0) + return EM_386; + return !strcmp(perf_arch, "x86_64") || !strcmp(perf_arch, "x86") + ? EM_X86_64 : EM_386; + default: + return result->e_machine; + } +} + +static const char *e_machine_to_perf_arch(uint16_t e_machine) +{ + /* + * Table for if either the perf arch string differs from uname or there + * are >1 ELF machine with the prefix. + */ + static const struct arch_to_e_machine extras[] = { + {"arm64", EM_AARCH64}, + {"avr32", EM_AVR32}, + {"powerpc", EM_PPC}, + {"powerpc", EM_PPC64}, + {"sparc", EM_SPARCV9}, + {"x86", EM_386}, + {"x86", EM_X86_64}, + {"none", EM_NONE}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(extras); i++) { + if (extras[i].e_machine == e_machine) + return extras[i].prefix; + } + + for (size_t i = 0; i < ARRAY_SIZE(prefix_to_e_machine); i++) { + if (prefix_to_e_machine[i].e_machine == e_machine) + return prefix_to_e_machine[i].prefix; + + } + return "unknown"; +} + +uint16_t perf_env__e_machine_nocache(struct perf_env *env, uint32_t *e_flags) +{ + uint16_t e_machine = EM_NONE; + const char *arch = NULL; + int is_64_bit = -1; + + if (e_flags) + *e_flags = 0; + + if (env) { + arch = env->arch; + is_64_bit = env->kernel_is_64_bit; + } + + if (!arch) { + static struct utsname uts = { .machine[0] = '\0', }; + + if (uts.machine[0] == '\0') + uname(&uts); + if (uts.machine[0] != '\0') + arch = uts.machine; + } + + e_machine = perf_arch_to_e_machine(arch, is_64_bit); + + if (e_flags) + *e_flags = (e_machine == EM_HOST) ? EF_HOST : 0; + + return e_machine; +} + +uint16_t perf_env__e_machine(struct perf_env *env, uint32_t *e_flags) +{ + uint16_t e_machine; + uint32_t local_e_flags = 0; + + if (env && env->e_machine != EM_NONE) { + if (e_flags) + *e_flags = env->e_flags; + + return env->e_machine; + } + e_machine = perf_env__e_machine_nocache(env, &local_e_flags); + /* + * Only cache the e_machine in perf_env if env->arch is not NULL. + * If env->arch is NULL, the e_machine is just a fallback to EM_HOST. + * Caching it permanently would prevent dynamic, more accurate + * thread-based session e_machine scanning later in + * perf_session__e_machine(). + */ + if (env && env->arch) { + env->e_machine = e_machine; + env->e_flags = local_e_flags; + } + if (e_flags) + *e_flags = local_e_flags; + + return e_machine; } const char *perf_env__arch(struct perf_env *env) { - char *arch_name; + uint16_t e_machine; + const char *arch; - if (!env || !env->arch) { /* Assume local operation */ + if (!env) { static struct utsname uts = { .machine[0] = '\0', }; - if (uts.machine[0] == '\0' && uname(&uts) < 0) - return NULL; - arch_name = uts.machine; - } else - arch_name = env->arch; + uint16_t host_e_machine; - return normalize_arch(arch_name); + if (uts.machine[0] == '\0') + uname(&uts); + if (uts.machine[0] != '\0') { + host_e_machine = perf_arch_to_e_machine(uts.machine, -1); + return e_machine_to_perf_arch(host_e_machine); + } + return e_machine_to_perf_arch(EM_HOST); + } + + /* + * Lazily compute/allocate arch. The e_machine may have been + * read from a data file and so may not be EM_HOST. + */ + e_machine = perf_env__e_machine(env, /*e_flags=*/NULL); + arch = e_machine_to_perf_arch(e_machine); + + if (e_machine == EM_RISCV && perf_env__kernel_is_64_bit(env) == 1) + arch = "riscv64"; + else if (e_machine == EM_MIPS && perf_env__kernel_is_64_bit(env) == 1) + arch = "mips64"; + else if (e_machine == EM_PARISC && perf_env__kernel_is_64_bit(env) == 1) + arch = "parisc64"; + + return arch; } const char *perf_env__arch_strerrno(struct perf_env *env __maybe_unused, int err __maybe_unused) diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index 739d884fc236..bde192fd5be5 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -187,6 +187,8 @@ int perf_env__read_cpu_topology_map(struct perf_env *env); void cpu_cache_level__free(struct cpu_cache_level *cache); +uint16_t perf_env__e_machine_nocache(struct perf_env *env, uint32_t *e_flags); +uint16_t perf_env__e_machine(struct perf_env *env, uint32_t *e_flags); const char *perf_env__arch(struct perf_env *env); const char *perf_env__arch_strerrno(struct perf_env *env, int err); arch_syscalls__strerrno_t *arch_syscalls__strerrno_function(const char *arch); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 5b1fa1653d2a..220e7720fbdb 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -441,21 +441,25 @@ static int write_osrelease(struct feat_fd *ff, return do_write_string(ff, uts.release); } -static int write_arch(struct feat_fd *ff, - struct evlist *evlist __maybe_unused) +static int write_arch(struct feat_fd *ff, struct evlist *evlist) { struct utsname uts; - int ret; + const char *arch = NULL; - ret = uname(&uts); - if (ret < 0) - return -1; + if (evlist->session) + arch = perf_env__arch(perf_session__env(evlist->session)); - return do_write_string(ff, uts.machine); + if (!arch) { + int ret = uname(&uts); + + if (ret < 0) + return -1; + arch = uts.machine; + } + return do_write_string(ff, arch); } -static int write_e_machine(struct feat_fd *ff, - struct evlist *evlist __maybe_unused) +static int write_e_machine(struct feat_fd *ff, struct evlist *evlist) { /* e_machine expanded from 16 to 32-bits for alignment. */ uint32_t e_flags; @@ -2841,10 +2845,18 @@ static int process_##__feat(struct feat_fd *ff, void *data __maybe_unused) \ FEAT_PROCESS_STR_FUN(hostname, hostname); FEAT_PROCESS_STR_FUN(osrelease, os_release); FEAT_PROCESS_STR_FUN(version, version); -FEAT_PROCESS_STR_FUN(arch, arch); FEAT_PROCESS_STR_FUN(cpudesc, cpu_desc); FEAT_PROCESS_STR_FUN(cpuid, cpuid); +static int process_arch(struct feat_fd *ff, void *data __maybe_unused) +{ + free(ff->ph->env.arch); + ff->ph->env.arch = do_read_string(ff); + if (!ff->ph->env.arch) + return -ENOMEM; + return 0; +} + static int process_e_machine(struct feat_fd *ff, void *data __maybe_unused) { int ret; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index e4efb7550927..1a9a008ddda3 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -4093,14 +4093,19 @@ uint16_t perf_session__e_machine(struct perf_session *session, uint32_t *e_flags return EM_HOST; } + /* + * Is the env caching an e_machine? If not we want to compute from the + * more accurate threads. + */ env = perf_session__env(session); - if (env && env->e_machine != EM_NONE) { - if (e_flags) - *e_flags = env->e_flags; - - return env->e_machine; - } + if (env && env->e_machine != EM_NONE) + return perf_env__e_machine(env, e_flags); + /* + * Compute from threads, note this is more accurate than + * perf_env__e_machine that falls back on EM_HOST and doesn't consider + * mixed 32-bit and 64-bit threads. + */ machines__for_each_thread(&session->machines, perf_session__e_machine_cb, &args); @@ -4118,10 +4123,9 @@ uint16_t perf_session__e_machine(struct perf_session *session, uint32_t *e_flags /* * Couldn't determine from the perf_env or current set of - * threads. Default to the host. + * threads. Potentially use logic that uses the arch string otherwise + * default to the host. Don't cache in the perf_env in case later + * threads indicate a better ELF machine type. */ - if (e_flags) - *e_flags = EF_HOST; - - return EM_HOST; + return perf_env__e_machine_nocache(env, e_flags); } From 4ccbc91df98a19eba2f40088e9bf5ab0888cf80a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:24:59 -0700 Subject: [PATCH 175/343] perf tests topology: Switch env->arch use to env->e_machine Some arch string comparisons weren't normalized. Avoid potential issues with normalized names vs uname values by swtiching to using the e_machine. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/topology.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c index f54502ebef4b..bd7b859dea66 100644 --- a/tools/perf/tests/topology.c +++ b/tools/perf/tests/topology.c @@ -11,6 +11,7 @@ #include "pmus.h" #include "target.h" #include +#include "dwarf-regs.h" #define TEMPL "/tmp/perf-test-XXXXXX" #define DATA_SIZE 10 @@ -74,6 +75,7 @@ static int check_cpu_topology(char *path, struct perf_cpu_map *map) struct aggr_cpu_id id; struct perf_cpu cpu; struct perf_env *env; + uint16_t e_machine; session = perf_session__new(&data, NULL); TEST_ASSERT_VAL("can't get session", !IS_ERR(session)); @@ -101,7 +103,9 @@ static int check_cpu_topology(char *path, struct perf_cpu_map *map) * condition is true (see do_core_id_test in header.c). So always * run this test on those platforms. */ - if (!env->cpu && strncmp(env->arch, "s390", 4) && strncmp(env->arch, "aarch64", 7)) + e_machine = perf_env__e_machine(env, NULL); + + if (!env->cpu && e_machine != EM_S390 && e_machine != EM_AARCH64) return TEST_SKIP; /* @@ -110,7 +114,7 @@ static int check_cpu_topology(char *path, struct perf_cpu_map *map) * physical_package_id will be set to -1. Hence skip this * test if physical_package_id returns -1 for cpu from perf_cpu_map. */ - if (!strncmp(env->arch, "ppc64le", 7)) { + if (e_machine == EM_PPC64) { if (cpu__get_socket_id(perf_cpu_map__cpu(map, 0)) == -1) return TEST_SKIP; } From f7c6e4b99ded250b3fdeaa5be4ccaac9ae05f8d9 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:00 -0700 Subject: [PATCH 176/343] perf env, dso, thread: Add _endian variants for e_machine helpers Add perf_arch_is_big_endian(), dso__read_e_machine_endian(), dso__e_machine_endian(), and thread__e_machine_endian() to support bi-endianness and cross-architecture analysis without breaking the existing API. These helpers allow querying the absolute endianness of a DSO or thread, which is required for tools like Capstone that need to set the correct disassembly mode. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 19 ++++++++----- tools/perf/util/dso.h | 14 ++++++++-- tools/perf/util/env.c | 16 +++++++++++ tools/perf/util/env.h | 1 + tools/perf/util/thread.c | 58 ++++++++++++++++++++++++++++++---------- tools/perf/util/thread.h | 23 +++++++++++++++- 6 files changed, 108 insertions(+), 23 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index b791e1b6b2cf..7dced896c64e 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1220,7 +1220,8 @@ static enum dso_swap_type dso_swap_type__from_elf_data(unsigned char eidata) } /* Reads e_machine from fd, optionally caching data in dso. */ -uint16_t dso__read_e_machine(struct dso *optional_dso, int fd, uint32_t *e_flags) +uint16_t dso__read_e_machine_endian(struct dso *optional_dso, int fd, uint32_t *e_flags, + bool *is_big_endian) { uint16_t e_machine = EM_NONE; unsigned char e_ident[EI_NIDENT]; @@ -1250,6 +1251,9 @@ uint16_t dso__read_e_machine(struct dso *optional_dso, int fd, uint32_t *e_flags if (swap_type == DSO_SWAP__UNSET) return EM_NONE; // Bad ELF data encoding. + if (is_big_endian) + *is_big_endian = (e_ident[EI_DATA] == ELFDATA2MSB); + /* Cache the need for swapping. */ if (optional_dso) { assert(dso__needs_swap(optional_dso) == DSO_SWAP__UNSET || @@ -1288,7 +1292,8 @@ uint16_t dso__read_e_machine(struct dso *optional_dso, int fd, uint32_t *e_flags return e_machine; } -uint16_t dso__e_machine(struct dso *dso, struct machine *machine, uint32_t *e_flags) +uint16_t dso__e_machine_endian(struct dso *dso, struct machine *machine, uint32_t *e_flags, + bool *is_big_endian) { uint16_t e_machine = EM_NONE; int fd; @@ -1308,9 +1313,11 @@ uint16_t dso__e_machine(struct dso *dso, struct machine *machine, uint32_t *e_fl case DSO_BINARY_TYPE__BPF_IMAGE: case DSO_BINARY_TYPE__OOL: case DSO_BINARY_TYPE__JAVA_JIT: - if (e_flags) - *e_flags = EF_HOST; - return EM_HOST; + if (is_big_endian) { + *is_big_endian = perf_arch_is_big_endian( + machine && machine->env ? perf_env__arch(machine->env) : NULL); + } + return perf_env__e_machine(machine ? machine->env : NULL, e_flags); case DSO_BINARY_TYPE__DEBUGLINK: case DSO_BINARY_TYPE__BUILD_ID_CACHE: case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: @@ -1338,7 +1345,7 @@ uint16_t dso__e_machine(struct dso *dso, struct machine *machine, uint32_t *e_fl try_to_open_dso(dso, machine); fd = dso__data(dso)->fd; if (fd >= 0) - e_machine = dso__read_e_machine(dso, fd, e_flags); + e_machine = dso__read_e_machine_endian(dso, fd, e_flags, is_big_endian); else if (e_flags) *e_flags = 0; diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index ede691e9a249..2916b954a804 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -866,8 +866,18 @@ int dso__data_file_size(struct dso *dso, struct machine *machine); off_t dso__data_size(struct dso *dso, struct machine *machine); ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, u64 offset, u8 *data, ssize_t size); -uint16_t dso__read_e_machine(struct dso *optional_dso, int fd, uint32_t *e_flags); -uint16_t dso__e_machine(struct dso *dso, struct machine *machine, uint32_t *e_flags); +uint16_t dso__read_e_machine_endian(struct dso *optional_dso, int fd, uint32_t *e_flags, + bool *is_big_endian); +static inline uint16_t dso__read_e_machine(struct dso *optional_dso, int fd, uint32_t *e_flags) +{ + return dso__read_e_machine_endian(optional_dso, fd, e_flags, NULL); +} +uint16_t dso__e_machine_endian(struct dso *dso, struct machine *machine, uint32_t *e_flags, + bool *is_big_endian); +static inline uint16_t dso__e_machine(struct dso *dso, struct machine *machine, uint32_t *e_flags) +{ + return dso__e_machine_endian(dso, machine, e_flags, NULL); +} ssize_t dso__data_read_addr(struct dso *dso, struct map *map, struct machine *machine, u64 addr, u8 *data, ssize_t size); diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 0cd23b5fc651..fae70b07ba8d 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -342,6 +342,22 @@ int perf_env__kernel_is_64_bit(struct perf_env *env) return env->kernel_is_64_bit; } +bool perf_arch_is_big_endian(const char *arch) +{ + if (!arch) + return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; + + if (str_ends_with(arch, "_be") || !strcmp(arch, "sparc") || !strcmp(arch, "sparc64") || + !strcmp(arch, "s390") || !strcmp(arch, "s390x") || !strcmp(arch, "powerpc") || + !strcmp(arch, "ppc") || !strcmp(arch, "ppc64") || + !strcmp(arch, "mips") || !strcmp(arch, "mips64") || !strcmp(arch, "parisc") || + !strcmp(arch, "parisc64") || !strcmp(arch, "m68k") || + !strcmp(arch, "armeb") || !strcmp(arch, "mipseb") || !strcmp(arch, "mips64eb")) + return true; + + return false; +} + int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) { int i; diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index bde192fd5be5..dd9907dbc345 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -175,6 +175,7 @@ void free_cpu_domain_info(struct cpu_domain_map **cd_map, u32 schedstat_version, void perf_env__exit(struct perf_env *env); int perf_env__kernel_is_64_bit(struct perf_env *env); +bool perf_arch_is_big_endian(const char *arch); int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index aac9cb75dcf4..ba33c0dfc18f 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -56,6 +56,7 @@ struct thread *thread__new(pid_t pid, pid_t tid) thread__set_cpu(thread, -1); thread__set_guest_cpu(thread, -1); thread__set_e_machine(thread, EM_NONE); + thread__set_e_is_big_endian(thread, false); thread__set_lbr_stitch_enable(thread, false); INIT_LIST_HEAD(thread__namespaces_list(thread)); INIT_LIST_HEAD(thread__comm_list(thread)); @@ -429,7 +430,7 @@ void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, } } -static uint16_t read_proc_e_machine_for_pid(pid_t pid, uint32_t *e_flags) +static uint16_t read_proc_e_machine_for_pid(pid_t pid, uint32_t *e_flags, bool *is_big_endian) { char path[6 /* "/proc/" */ + 11 /* max length of pid */ + 5 /* "/exe\0" */]; int fd; @@ -438,7 +439,8 @@ static uint16_t read_proc_e_machine_for_pid(pid_t pid, uint32_t *e_flags) snprintf(path, sizeof(path), "/proc/%d/exe", pid); fd = open(path, O_RDONLY); if (fd >= 0) { - e_machine = dso__read_e_machine(/*optional_dso=*/NULL, fd, e_flags); + e_machine = dso__read_e_machine_endian(/*optional_dso=*/NULL, fd, e_flags, + is_big_endian); close(fd); } return e_machine; @@ -448,6 +450,7 @@ struct thread__e_machine_callback_args { struct machine *machine; uint32_t e_flags; uint16_t e_machine; + bool is_big_endian; }; static int thread__e_machine_callback(struct map *map, void *_args) @@ -458,24 +461,38 @@ static int thread__e_machine_callback(struct map *map, void *_args) if (!dso) return 0; // No dso, continue search. - args->e_machine = dso__e_machine(dso, args->machine, &args->e_flags); + args->e_machine = + dso__e_machine_endian(dso, args->machine, &args->e_flags, &args->is_big_endian); return args->e_machine != EM_NONE ? 1 /* stop search */ : 0 /* continue search */; } -uint16_t thread__e_machine(struct thread *thread, struct machine *machine, uint32_t *e_flags) +uint16_t thread__e_machine_endian(struct thread *thread, struct machine *machine, uint32_t *e_flags, + bool *is_big_endian) { pid_t tid, pid; - uint16_t e_machine = RC_CHK_ACCESS(thread)->e_machine; + uint16_t e_machine; uint32_t local_e_flags = 0; - struct thread__e_machine_callback_args args = { - .machine = machine, - .e_flags = 0, - .e_machine = EM_NONE, - }; + struct thread__e_machine_callback_args args; + + if (!thread) { + if (is_big_endian) { + *is_big_endian = perf_arch_is_big_endian( + machine && machine->env ? perf_env__arch(machine->env) : NULL); + } + return perf_env__e_machine(machine ? machine->env : NULL, e_flags); + } + + e_machine = RC_CHK_ACCESS(thread)->e_machine; + args.machine = machine; + args.e_flags = 0; + args.e_machine = EM_NONE; + args.is_big_endian = false; if (e_machine != EM_NONE) { if (e_flags) *e_flags = thread__e_flags(thread); + if (is_big_endian) + *is_big_endian = thread__e_is_big_endian(thread); return e_machine; } @@ -483,6 +500,7 @@ uint16_t thread__e_machine(struct thread *thread, struct machine *machine, uint3 struct maps *maps = thread__maps(thread); machine = maps__machine(maps); + args.machine = machine; } tid = thread__tid(thread); pid = thread__pid(thread); @@ -490,7 +508,8 @@ uint16_t thread__e_machine(struct thread *thread, struct machine *machine, uint3 struct thread *parent = machine__findnew_thread(machine, pid, pid); if (parent) { - e_machine = thread__e_machine(parent, machine, &local_e_flags); + e_machine = thread__e_machine_endian(parent, machine, &local_e_flags, + &args.is_big_endian); thread__put(parent); goto out; } @@ -515,16 +534,27 @@ uint16_t thread__e_machine(struct thread *thread, struct machine *machine, uint3 is_live = !!session->data; } /* Read from /proc/pid/exe if live. */ - if (is_live) - e_machine = read_proc_e_machine_for_pid(pid, &local_e_flags); + if (is_live) { + e_machine = read_proc_e_machine_for_pid(pid, &local_e_flags, + &args.is_big_endian); + } else if (machine && machine->env) { + /* Offline analysis: fallback to environment metadata. */ + e_machine = perf_env__e_machine(machine->env, &local_e_flags); + args.is_big_endian = perf_arch_is_big_endian(perf_env__arch(machine->env)); + } } out: if (e_machine != EM_NONE) { - thread__set_e_machine(thread, e_machine); thread__set_e_flags(thread, local_e_flags); + thread__set_e_is_big_endian(thread, args.is_big_endian); + thread__set_e_machine(thread, e_machine); + if (is_big_endian) + *is_big_endian = args.is_big_endian; } else { e_machine = EM_HOST; local_e_flags = EF_HOST; + if (is_big_endian) + *is_big_endian = (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__); } if (e_flags) *e_flags = local_e_flags; diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index f5792d3e8a16..d82fce8173ae 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -69,6 +69,11 @@ DECLARE_RC_STRUCT(thread) { * computed. */ uint16_t e_machine; + /** + * @e_is_big_endian: True if the ELF architecture of the thread is big endian. + * Valid if e_machine != EM_NONE. + */ + bool e_is_big_endian; /* LBR call stack stitch */ bool lbr_stitch_enable; struct lbr_stitch *lbr_stitch; @@ -311,7 +316,13 @@ static inline void thread__set_filter_entry_depth(struct thread *thread, int dep RC_CHK_ACCESS(thread)->filter_entry_depth = depth; } -uint16_t thread__e_machine(struct thread *thread, struct machine *machine, uint32_t *e_flags); +uint16_t thread__e_machine_endian(struct thread *thread, struct machine *machine, uint32_t *e_flags, + bool *is_big_endian); +static inline uint16_t thread__e_machine(struct thread *thread, struct machine *machine, + uint32_t *e_flags) +{ + return thread__e_machine_endian(thread, machine, e_flags, NULL); +} static inline void thread__set_e_machine(struct thread *thread, uint16_t e_machine) { @@ -328,6 +339,16 @@ static inline void thread__set_e_flags(struct thread *thread, uint32_t e_flags) RC_CHK_ACCESS(thread)->e_flags = e_flags; } +static inline bool thread__e_is_big_endian(const struct thread *thread) +{ + return RC_CHK_ACCESS(thread)->e_is_big_endian; +} + +static inline void thread__set_e_is_big_endian(struct thread *thread, bool is_big_endian) +{ + RC_CHK_ACCESS(thread)->e_is_big_endian = is_big_endian; +} + static inline bool thread__lbr_stitch_enable(const struct thread *thread) { From 12c4737f55f2fb4a0062258336435c69847a426c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:01 -0700 Subject: [PATCH 177/343] perf capstone: Determine architecture from e_machine Avoid the use of arch string that is imprecise and use the e_machine. Do more e_machine to capstone machine translations adding MIPS and RISCV. Remove unnecessary maybe_unused annotations. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/capstone.c | 132 ++++++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 44 deletions(-) diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c index 25cf6e15ec27..5ad537fea436 100644 --- a/tools/perf/util/capstone.c +++ b/tools/perf/util/capstone.c @@ -1,7 +1,19 @@ // SPDX-License-Identifier: GPL-2.0 #include "capstone.h" -#include "annotate.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include + #include "addr_location.h" +#include "annotate.h" #include "debug.h" #include "disasm.h" #include "dso.h" @@ -11,13 +23,6 @@ #include "print_insn.h" #include "symbol.h" #include "thread.h" -#include -#include -#include -#include -#include - -#include #ifdef LIBCAPSTONE_DLOPEN static void *perf_cs_dll_handle(void) @@ -137,37 +142,70 @@ static enum cs_err perf_cs_close(csh *handle) #endif } -static int capstone_init(struct machine *machine, csh *cs_handle, bool is64, +static bool e_machine_to_capstone(uint16_t e_machine, bool is64, bool is_big_endian, + enum cs_arch *arch, enum cs_mode *mode) +{ + *mode = is_big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN; + + switch (e_machine) { + case EM_X86_64: + case EM_386: + *arch = CS_ARCH_X86; + *mode |= is64 ? CS_MODE_64 : CS_MODE_32; + return true; + case EM_AARCH64: + *arch = CS_ARCH_ARM64; + *mode |= CS_MODE_ARM; + return true; + case EM_ARM: + *arch = CS_ARCH_ARM; + *mode |= CS_MODE_ARM | CS_MODE_V8; + return true; + case EM_S390: + *arch = CS_ARCH_SYSZ; + return true; + case EM_MIPS: + *arch = CS_ARCH_MIPS; + *mode |= is64 ? CS_MODE_MIPS64 : CS_MODE_MIPS32; + return true; + case EM_PPC: + *arch = CS_ARCH_PPC; + return true; + case EM_PPC64: + *arch = CS_ARCH_PPC; + *mode |= CS_MODE_64; + return true; + case EM_SPARC: + *arch = CS_ARCH_SPARC; + return true; + case EM_SPARCV9: + *arch = CS_ARCH_SPARC; + *mode |= CS_MODE_V9; + return true; + case EM_RISCV: + *arch = CS_ARCH_RISCV; + *mode |= (is64 ? CS_MODE_RISCV64 : CS_MODE_RISCV32) | CS_MODE_RISCVC; + return true; + default: + return false; + } +} + +static int capstone_init(uint16_t e_machine, csh *cs_handle, bool is64, bool is_big_endian, bool disassembler_style) { enum cs_arch arch; enum cs_mode mode; - if (machine__is(machine, "x86_64") && is64) { - arch = CS_ARCH_X86; - mode = CS_MODE_64; - } else if (machine__normalized_is(machine, "x86")) { - arch = CS_ARCH_X86; - mode = CS_MODE_32; - } else if (machine__normalized_is(machine, "arm64")) { - arch = CS_ARCH_ARM64; - mode = CS_MODE_ARM; - } else if (machine__normalized_is(machine, "arm")) { - arch = CS_ARCH_ARM; - mode = CS_MODE_ARM + CS_MODE_V8; - } else if (machine__normalized_is(machine, "s390")) { - arch = CS_ARCH_SYSZ; - mode = CS_MODE_BIG_ENDIAN; - } else { + if (!e_machine_to_capstone(e_machine, is64, is_big_endian, &arch, &mode)) return -1; - } if (perf_cs_open(arch, mode, cs_handle) != CS_ERR_OK) { pr_warning_once("cs_open failed\n"); return -1; } - if (machine__normalized_is(machine, "x86")) { + if (arch == CS_ARCH_X86) { /* * In case of using capstone_init while symbol__disassemble * setting CS_OPT_SYNTAX_ATT depends if disassembler_style opts @@ -211,29 +249,28 @@ static size_t print_insn_x86(struct thread *thread, u8 cpumode, struct cs_insn * return printed; } - -ssize_t capstone__fprintf_insn_asm(struct machine *machine __maybe_unused, - struct thread *thread __maybe_unused, - u8 cpumode __maybe_unused, bool is64bit __maybe_unused, - const uint8_t *code __maybe_unused, - size_t code_size __maybe_unused, - uint64_t ip __maybe_unused, int *lenp __maybe_unused, - int print_opts __maybe_unused, FILE *fp __maybe_unused) +ssize_t capstone__fprintf_insn_asm(struct machine *machine, struct thread *thread, u8 cpumode, + bool is64bit, const uint8_t *code, size_t code_size, uint64_t ip, + int *lenp, int print_opts, FILE *fp) { size_t printed; struct cs_insn *insn; csh cs_handle; size_t count; + bool is_big_endian = false; + uint16_t e_machine = thread__e_machine_endian(thread, machine, + /*e_flags=*/NULL, &is_big_endian); int ret; /* TODO: Try to initiate capstone only once but need a proper place. */ - ret = capstone_init(machine, &cs_handle, is64bit, true); + ret = capstone_init(e_machine, &cs_handle, is64bit, is_big_endian, + /*disassembler_style=*/true); if (ret < 0) return ret; count = perf_cs_disasm(cs_handle, code, code_size, ip, 1, &insn); if (count > 0) { - if (machine__normalized_is(machine, "x86")) + if (e_machine == EM_X86_64 || e_machine == EM_386) printed = print_insn_x86(thread, cpumode, &insn[0], print_opts, fp); else printed = fprintf(fp, "%s %s", insn[0].mnemonic, insn[0].op_str); @@ -322,9 +359,8 @@ static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg) return 0; } -int symbol__disassemble_capstone(const char *filename __maybe_unused, - struct symbol *sym __maybe_unused, - struct annotate_args *args __maybe_unused) +int symbol__disassemble_capstone(const char *filename, struct symbol *sym, + struct annotate_args *args) { struct annotation *notes = symbol__annotation(sym); struct map *map = args->ms->map; @@ -344,6 +380,8 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused, char disasm_buf[512]; struct disasm_line *dl; bool disassembler_style = false; + uint16_t e_machine; + bool is_big_endian = false; if (args->options->objdump_path) return -1; @@ -373,8 +411,10 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused, !strcmp(args->options->disassembler_style, "att")) disassembler_style = true; - if (capstone_init(maps__machine(thread__maps(args->ms->thread)), &handle, is_64bit, - disassembler_style) < 0) + e_machine = thread__e_machine_endian(args->ms->thread, + /*machine=*/NULL, + /*e_flags=*/NULL, &is_big_endian); + if (capstone_init(e_machine, &handle, is_64bit, is_big_endian, disassembler_style) < 0) goto err; needs_cs_close = true; @@ -466,6 +506,8 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused, struct disasm_line *dl; u32 *line; bool disassembler_style = false; + uint16_t e_machine; + bool is_big_endian = false; if (args->options->objdump_path) return -1; @@ -484,8 +526,10 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused, !strcmp(args->options->disassembler_style, "att")) disassembler_style = true; - if (capstone_init(maps__machine(thread__maps(args->ms->thread)), &handle, is_64bit, - disassembler_style) < 0) + e_machine = thread__e_machine_endian(args->ms->thread, + /*machine=*/NULL, + /*e_flags=*/NULL, &is_big_endian); + if (capstone_init(e_machine, &handle, is_64bit, is_big_endian, disassembler_style) < 0) goto err; needs_cs_close = true; From c4e16f0543ff5df76e221141ab8e7430792bf841 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:02 -0700 Subject: [PATCH 178/343] perf print_insn: Use e_machine for fallback IP length check Avoid string comparisons with perf_env arch, switch to using the more precise ELF machine. Sort header files and fix missing definitions. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/print_insn.c | 23 ++++++++++++++--------- tools/perf/util/print_insn.h | 2 ++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/print_insn.c b/tools/perf/util/print_insn.c index 02e6fbb8ca04..4068436f26ea 100644 --- a/tools/perf/util/print_insn.c +++ b/tools/perf/util/print_insn.c @@ -4,19 +4,24 @@ * * Author(s): Changbin Du */ +#include "print_insn.h" + #include -#include #include +#include + +#include + #include "capstone.h" #include "debug.h" +#include "dso.h" +#include "dump-insn.h" +#include "env.h" +#include "machine.h" +#include "map.h" #include "sample.h" #include "symbol.h" -#include "machine.h" #include "thread.h" -#include "print_insn.h" -#include "dump-insn.h" -#include "map.h" -#include "dso.h" size_t sample__fprintf_insn_raw(struct perf_sample *sample, FILE *fp) { @@ -33,13 +38,13 @@ size_t sample__fprintf_insn_raw(struct perf_sample *sample, FILE *fp) static bool is64bitip(struct machine *machine, struct addr_location *al) { const struct dso *dso = al->map ? map__dso(al->map) : NULL; + uint16_t e_machine; if (dso) return dso__is_64_bit(dso); - return machine__is(machine, "x86_64") || - machine__normalized_is(machine, "arm64") || - machine__normalized_is(machine, "s390"); + e_machine = perf_env__e_machine(machine->env, /*e_flags=*/NULL); + return e_machine == EM_X86_64 || e_machine == EM_AARCH64 || e_machine == EM_S390; } ssize_t fprintf_insn_asm(struct machine *machine, struct thread *thread, u8 cpumode, diff --git a/tools/perf/util/print_insn.h b/tools/perf/util/print_insn.h index a54f7e858e49..cefa5c5f246e 100644 --- a/tools/perf/util/print_insn.h +++ b/tools/perf/util/print_insn.h @@ -5,6 +5,8 @@ #include #include +#include + struct addr_location; struct machine; struct perf_insn; From 0af46a17c86ec447404d1e1555973186d058b775 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:03 -0700 Subject: [PATCH 179/343] perf symbol: Avoid use of machine__is Switch to using the ELF machine from the dso or running machine rather than the machine perf_env arch that may fall back on EM_HOST. This also avoids potentially imprecise string comparisons. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 714b6e6048fa..2ce512f08a1d 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -851,6 +851,23 @@ static int maps__split_kallsyms_for_kcore(struct maps *kmaps, struct dso *dso) return count; } +static uint16_t machine_or_dso_e_machine(struct machine *machine, struct dso *dso) +{ + uint16_t e_machine = EM_NONE; + /* DSO should be most accurate */ + if (dso) + e_machine = dso__e_machine(dso, machine, /*e_flags=*/NULL); + + if (e_machine != EM_NONE) + return e_machine; + + /* Check the global environment next. */ + if (machine && machine->env && machine->env->e_machine != EM_NONE) + return machine->env->e_machine; + + return perf_env__e_machine(machine ? machine->env : NULL, /*e_flags=*/NULL); +} + /* * Split the symbols into maps, making sure there are no overlaps, i.e. the * kernel range is broken in several maps, named [kernel].N, as we don't have @@ -866,14 +883,13 @@ static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta, struct rb_root_cached *root = dso__symbols(dso); struct rb_node *next = rb_first_cached(root); int kernel_range = 0; - bool x86_64; + uint16_t e_machine = EM_NONE; if (!kmaps) return -1; machine = maps__machine(kmaps); - - x86_64 = machine__is(machine, "x86_64"); + e_machine = machine_or_dso_e_machine(machine, dso); while (next) { char *module; @@ -925,7 +941,7 @@ static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta, */ pos->start = map__map_ip(curr_map, pos->start); pos->end = map__map_ip(curr_map, pos->end); - } else if (x86_64 && is_entry_trampoline(pos->name)) { + } else if (e_machine == EM_X86_64 && is_entry_trampoline(pos->name)) { /* * These symbols are not needed anymore since the * trampoline maps refer to the text section and it's @@ -1428,7 +1444,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map, free(new_node); } - if (machine__is(machine, "x86_64")) { + if (machine_or_dso_e_machine(machine, dso) == EM_X86_64) { u64 addr; /* @@ -1716,7 +1732,7 @@ int dso__load(struct dso *dso, struct map *map) ret = dso__load_guest_kernel_sym(dso, map); machine = maps__machine(map__kmaps(map)); - if (machine__is(machine, "x86_64")) + if (machine && machine_or_dso_e_machine(machine, dso) == EM_X86_64) machine__map_x86_64_entry_trampolines(machine, dso); goto out; } From dfe48498e6ab1fff4a27600450d073e117b0bd5f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:04 -0700 Subject: [PATCH 180/343] perf machine: Use perf_env e_machine rather than arch The arch string is derived from uname and may be normalized causing potential differences meaning the ELF machine can be more precise. Reduce the scope of machine__is as often it is better to use a thread for the e_machine rather than the machine. Switch from string to ELF machine constant comparisons. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 35 ++++++++++++++++++----------------- tools/perf/util/machine.h | 2 -- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index e5d1e8b882a9..47be7a44a5f7 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -9,6 +9,7 @@ #include "debug.h" #include "dso.h" #include "env.h" +#include "dwarf-regs.h" #include "event.h" #include "evsel.h" #include "hist.h" @@ -1627,10 +1628,24 @@ static bool machine__uses_kcore(struct machine *machine) return dsos__for_each_dso(&machine->dsos, machine__uses_kcore_cb, NULL) != 0 ? true : false; } +static bool machine__is(struct machine *machine, uint16_t e_machine) +{ + if (!machine) + return false; + + if (!machine->env) { + if (machine__is_host(machine)) + return e_machine == EM_HOST; + return false; + } + + return perf_env__e_machine(machine->env, NULL) == e_machine; +} + static bool perf_event__is_extra_kernel_mmap(struct machine *machine, struct extra_kernel_map *xm) { - return machine__is(machine, "x86_64") && + return machine__is(machine, EM_X86_64) && is_entry_trampoline(xm->name); } @@ -2786,7 +2801,7 @@ static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread, static u64 get_leaf_frame_caller(struct perf_sample *sample, struct thread *thread, int usr_idx) { - if (machine__normalized_is(maps__machine(thread__maps(thread)), "arm64")) + if (thread__e_machine(thread, /*machine=*/NULL, /*e_flags=*/NULL) == EM_AARCH64) return get_leaf_frame_caller_aarch64(sample, thread, usr_idx); else return 0; @@ -3157,20 +3172,6 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid, return 0; } -/* - * Compares the raw arch string. N.B. see instead perf_env__arch() or - * machine__normalized_is() if a normalized arch is needed. - */ -bool machine__is(struct machine *machine, const char *arch) -{ - return machine && !strcmp(perf_env__raw_arch(machine->env), arch); -} - -bool machine__normalized_is(struct machine *machine, const char *arch) -{ - return machine && !strcmp(perf_env__arch(machine->env), arch); -} - int machine__nr_cpus_avail(struct machine *machine) { return machine ? perf_env__nr_cpus_avail(machine->env) : 0; @@ -3197,7 +3198,7 @@ int machine__get_kernel_start(struct machine *machine) * start of kernel text, but still above 2^63. So leave * kernel_start = 1ULL << 63 for x86_64. */ - if (!err && !machine__is(machine, "x86_64")) + if (!err && !machine__is(machine, EM_X86_64)) machine->kernel_start = map__start(map); } return err; diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 048b24e9bd38..aaddfb70ea66 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -224,8 +224,6 @@ static inline bool machine__is_host(struct machine *machine) } bool machine__is_lock_function(struct machine *machine, u64 addr); -bool machine__is(struct machine *machine, const char *arch); -bool machine__normalized_is(struct machine *machine, const char *arch); int machine__nr_cpus_avail(struct machine *machine); struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid); From d08cb3fb0fbbb759c2e10747fec099290f2108ad Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:05 -0700 Subject: [PATCH 181/343] perf sample-raw: Use perf_env e_machine rather than arch Use the e_machine rather than the arch to determine S390 and x86 types. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sample-raw.c | 27 ++++++++++++++------------- tools/perf/util/sample-raw.h | 6 +++++- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/sample-raw.c b/tools/perf/util/sample-raw.c index bcf442574d6e..e20b73c0c5bd 100644 --- a/tools/perf/util/sample-raw.c +++ b/tools/perf/util/sample-raw.c @@ -1,11 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0 */ - -#include -#include -#include "evlist.h" -#include "env.h" -#include "header.h" #include "sample-raw.h" + +#include +#include + +#include "env.h" +#include "evlist.h" +#include "header.h" #include "session.h" /* @@ -14,14 +15,14 @@ */ void evlist__init_trace_event_sample_raw(struct evlist *evlist, struct perf_env *env) { - const char *arch_pf = perf_env__arch(env); - const char *cpuid = perf_env__cpuid(env); + uint16_t e_machine = perf_env__e_machine(env, /*e_flags=*/NULL); - if (arch_pf && !strcmp("s390", arch_pf)) + if (e_machine == EM_S390) { evlist->trace_event_sample_raw = evlist__s390_sample_raw; - else if (arch_pf && !strcmp("x86", arch_pf) && - cpuid && strstarts(cpuid, "AuthenticAMD") && - evlist__has_amd_ibs(evlist)) { - evlist->trace_event_sample_raw = evlist__amd_sample_raw; + } else if (e_machine == EM_X86_64 || e_machine == EM_386) { + const char *cpuid = perf_env__cpuid(env); + + if (cpuid && strstarts(cpuid, "AuthenticAMD") && evlist__has_amd_ibs(evlist)) + evlist->trace_event_sample_raw = evlist__amd_sample_raw; } } diff --git a/tools/perf/util/sample-raw.h b/tools/perf/util/sample-raw.h index 896e9a87e373..c8d38c841c8c 100644 --- a/tools/perf/util/sample-raw.h +++ b/tools/perf/util/sample-raw.h @@ -2,7 +2,10 @@ #ifndef __SAMPLE_RAW_H #define __SAMPLE_RAW_H 1 +#include + struct evlist; +struct perf_env; union perf_event; struct perf_sample; @@ -12,4 +15,5 @@ bool evlist__has_amd_ibs(struct evlist *evlist); void evlist__amd_sample_raw(struct evlist *evlist, union perf_event *event, struct perf_sample *sample); void evlist__init_trace_event_sample_raw(struct evlist *evlist, struct perf_env *env); -#endif /* __PERF_EVLIST_H */ + +#endif /* __SAMPLE_RAW_H */ From 0158eb0d121c1a6c6972c01ae237784caca8a367 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:06 -0700 Subject: [PATCH 182/343] perf sort: Use perf_env e_machine rather than arch Use the e_machine rather than the arch to determine x86 or PPC types. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 62 +++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 0020089cb13c..90bc4a31bb55 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1,40 +1,45 @@ // SPDX-License-Identifier: GPL-2.0 +#include "sort.h" + #include #include #include -#include #include + +#include +#include #include +#include #include + +#include + +#include "annotate-data.h" +#include "annotate.h" +#include "branch.h" +#include "cacheline.h" +#include "cgroup.h" +#include "comm.h" #include "debug.h" #include "dso.h" -#include "sort.h" -#include "hist.h" -#include "cacheline.h" -#include "comm.h" -#include "map.h" -#include "maps.h" -#include "symbol.h" -#include "map_symbol.h" -#include "branch.h" -#include "thread.h" -#include "evsel.h" +#include "event.h" #include "evlist.h" -#include "srcline.h" -#include "strlist.h" -#include "strbuf.h" +#include "evsel.h" +#include "hist.h" +#include "machine.h" +#include "map.h" +#include "map_symbol.h" +#include "maps.h" #include "mem-events.h" #include "mem-info.h" -#include "annotate.h" -#include "annotate-data.h" -#include "event.h" -#include "time-utils.h" -#include "cgroup.h" -#include "machine.h" #include "session.h" +#include "srcline.h" +#include "strbuf.h" +#include "strlist.h" +#include "symbol.h" +#include "thread.h" +#include "time-utils.h" #include "trace-event.h" -#include -#include #ifdef HAVE_LIBTRACEEVENT #include @@ -2673,9 +2678,10 @@ struct sort_dimension { static int arch_support_sort_key(const char *sort_key, struct perf_env *env) { - const char *arch = perf_env__arch(env); + uint16_t e_machine = perf_env__e_machine(env, /*e_eflags=*/NULL); - if (!strcmp("x86", arch) || !strcmp("powerpc", arch)) { + if (e_machine == EM_X86_64 || e_machine == EM_386 || e_machine == EM_PPC64 || + e_machine == EM_PPC) { if (!strcmp(sort_key, "p_stage_cyc")) return 1; if (!strcmp(sort_key, "local_p_stage_cyc")) @@ -2686,14 +2692,14 @@ static int arch_support_sort_key(const char *sort_key, struct perf_env *env) static const char *arch_perf_header_entry(const char *se_header, struct perf_env *env) { - const char *arch = perf_env__arch(env); + uint16_t e_machine = perf_env__e_machine(env, /*e_eflags=*/NULL); - if (!strcmp("x86", arch)) { + if (e_machine == EM_X86_64 || e_machine == EM_386) { if (!strcmp(se_header, "Local Pipeline Stage Cycle")) return "Local Retire Latency"; else if (!strcmp(se_header, "Pipeline Stage Cycle")) return "Retire Latency"; - } else if (!strcmp("powerpc", arch)) { + } else if (e_machine == EM_PPC64 || e_machine == EM_PPC) { if (!strcmp(se_header, "Local INSTR Latency")) return "Finish Cyc"; else if (!strcmp(se_header, "INSTR Latency")) From 82ed70f00ccce18bd68cc82b62a80bb5a7f44856 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:07 -0700 Subject: [PATCH 183/343] perf arch common: Use perf_env e_machine rather than arch Use the e_machine rather than arch string matching. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/common.c | 94 ++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index ad0cab830a4d..5ad50e331c55 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c @@ -1,13 +1,18 @@ // SPDX-License-Identifier: GPL-2.0 +#include "common.h" + #include #include #include #include -#include -#include "common.h" -#include "../util/env.h" -#include "../util/debug.h" + #include +#include + +#include + +#include "../util/debug.h" +#include "../util/env.h" static const char *const arc_triplets[] = { "arc-linux-", @@ -141,11 +146,40 @@ static int lookup_triplets(const char *const *triplets, const char *name) return -1; } +static bool is_native_compatible(struct perf_env *env, uint16_t target, uint16_t host) +{ + if (target != host) { + /* A 64-bit host can natively disassemble its 32-bit compat architecture */ + if (host == EM_X86_64 && target == EM_386) + return true; + if (host == EM_AARCH64 && target == EM_ARM) + return true; + if (host == EM_PPC64 && target == EM_PPC) + return true; + if (host == EM_SPARCV9 && target == EM_SPARC) + return true; + return false; + } + + /* target == host case */ + if (target == EM_RISCV) { + bool target_is_64 = perf_env__kernel_is_64_bit(env); + bool host_is_64 = (sizeof(void *) == 8); + + /* 32-bit host cannot natively disassemble 64-bit target */ + if (!host_is_64 && target_is_64) + return false; + } + + return true; +} + static int perf_env__lookup_binutils_path(struct perf_env *env, const char *name, char **path) { int idx; - const char *arch = perf_env__arch(env), *cross_env; + uint16_t e_machine = perf_env__e_machine(env, /*e_flags=*/NULL); + const char *cross_env; const char *const *path_list; char *buf = NULL; @@ -153,7 +187,7 @@ static int perf_env__lookup_binutils_path(struct perf_env *env, * We don't need to try to find objdump path for native system. * Just use default binutils path (e.g.: "objdump"). */ - if (!strcmp(perf_env__arch(NULL), arch)) + if (is_native_compatible(env, e_machine, EM_HOST)) goto out; cross_env = getenv("CROSS_COMPILE"); @@ -170,30 +204,42 @@ static int perf_env__lookup_binutils_path(struct perf_env *env, zfree(&buf); } - if (!strcmp(arch, "arc")) + switch (e_machine) { + case EM_ARC: path_list = arc_triplets; - else if (!strcmp(arch, "arm")) + break; + case EM_ARM: path_list = arm_triplets; - else if (!strcmp(arch, "arm64")) + break; + case EM_AARCH64: path_list = arm64_triplets; - else if (!strcmp(arch, "powerpc")) + break; + case EM_PPC: + case EM_PPC64: path_list = powerpc_triplets; - else if (!strcmp(arch, "riscv32")) - path_list = riscv32_triplets; - else if (!strcmp(arch, "riscv64")) - path_list = riscv64_triplets; - else if (!strcmp(arch, "sh")) + break; + case EM_RISCV: + path_list = perf_env__kernel_is_64_bit(env) ? riscv64_triplets : riscv32_triplets; + break; + case EM_SH: path_list = sh_triplets; - else if (!strcmp(arch, "s390")) + break; + case EM_S390: path_list = s390_triplets; - else if (!strcmp(arch, "sparc")) + break; + case EM_SPARC: + case EM_SPARCV9: path_list = sparc_triplets; - else if (!strcmp(arch, "x86")) + break; + case EM_X86_64: + case EM_386: path_list = x86_triplets; - else if (!strcmp(arch, "mips")) + break; + case EM_MIPS: path_list = mips_triplets; - else { - ui__error("binutils for %s not supported.\n", arch); + break; + default: + ui__error("binutils for %s not supported.\n", perf_env__arch(env)); goto out_error; } @@ -202,7 +248,7 @@ static int perf_env__lookup_binutils_path(struct perf_env *env, ui__error("Please install %s for %s.\n" "You can add it to PATH, set CROSS_COMPILE or " "override the default using --%s.\n", - name, arch, name); + name, perf_env__arch(env), name); goto out_error; } @@ -237,7 +283,7 @@ int perf_env__lookup_objdump(struct perf_env *env, char **path) */ bool perf_env__single_address_space(struct perf_env *env) { - const char *arch = perf_env__arch(env); + uint16_t e_machine = perf_env__e_machine(env, /*e_flags=*/NULL); - return strcmp(arch, "s390") && strcmp(arch, "sparc"); + return e_machine != EM_SPARC && e_machine != EM_SPARCV9 && e_machine != EM_S390; } From 5d57371b9cd2a40e04df0104b62a4c302555d076 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:08 -0700 Subject: [PATCH 184/343] perf header: In print_pmu_caps use perf_env e_machine Switch from arch to e_machine in print_pmu_caps. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 220e7720fbdb..ecdac427d9c4 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2461,15 +2461,16 @@ static void print_cpu_pmu_caps(struct feat_fd *ff, FILE *fp) static void print_pmu_caps(struct feat_fd *ff, FILE *fp) { struct perf_env *env = &ff->ph->env; - struct pmu_caps *pmu_caps; + uint16_t e_machine = perf_env__e_machine(env, /*e_flags=*/NULL); for (int i = 0; i < env->nr_pmus_with_caps; i++) { - pmu_caps = &env->pmu_caps[i]; + struct pmu_caps *pmu_caps = &env->pmu_caps[i]; + __print_pmu_caps(fp, pmu_caps->nr_caps, pmu_caps->caps, pmu_caps->pmu_name); } - if (strcmp(perf_env__arch(env), "x86") == 0 && + if ((e_machine == EM_X86_64 || e_machine == EM_386) && perf_env__has_pmu_mapping(env, "ibs_op")) { char *max_precise = perf_env__find_pmu_cap(env, "cpu", "max_precise"); From 70b3c4f734bbfd5664cd6e4eb007c108bf2b1c43 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:09 -0700 Subject: [PATCH 185/343] perf c2c: Use perf_env e_machine rather than arch Use the e_machine rather than arch string matching for AARCH64. Add include of dwarf-regs.h in case the EM_AARCH64 isn't defined, sort the headers given this include. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index d3503be9350c..3dd45a550fdb 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -12,41 +12,45 @@ */ #include #include + +#include #include #include #include #include #include -#include #include -#include "debug.h" -#include "builtin.h" + +#include #include #include #include -#include "map_symbol.h" -#include "mem-events.h" -#include "session.h" -#include "hist.h" -#include "sort.h" -#include "tool.h" + +#include "builtin.h" #include "cacheline.h" #include "data.h" +#include "debug.h" #include "event.h" #include "evlist.h" #include "evsel.h" -#include "ui/browsers/hists.h" -#include "thread.h" -#include "mem2node.h" +#include "hist.h" +#include "map_symbol.h" +#include "mem-events.h" #include "mem-info.h" -#include "symbol.h" -#include "ui/ui.h" -#include "ui/progress.h" +#include "mem2node.h" #include "pmus.h" +#include "session.h" +#include "sort.h" #include "string2.h" -#include "util/util.h" -#include "util/symbol.h" +#include "symbol.h" +#include "thread.h" +#include "tool.h" +#include "ui/browsers/hists.h" +#include "ui/progress.h" +#include "ui/ui.h" #include "util/annotate.h" +#include "util/symbol.h" +#include "util/util.h" struct c2c_hists { struct hists hists; @@ -3203,7 +3207,7 @@ static int perf_c2c__report(int argc, const char **argv) * default display type. */ if (!display) { - if (!strcmp(perf_env__arch(env), "arm64")) + if (perf_env__e_machine(env, /*e_flags=*/NULL) == EM_AARCH64) display = "peer"; else display = "tot"; From 661b1d83ef9ee997019cbf6428d3029fb9e9b0af Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:10 -0700 Subject: [PATCH 186/343] perf lock-contention: Use perf_env e_machine rather than arch Use the e_machine rather than arch string matching for powerpc. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/lock-contention.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/lock-contention.c b/tools/perf/util/lock-contention.c index 92e7b7b572a2..119a7206f3cd 100644 --- a/tools/perf/util/lock-contention.c +++ b/tools/perf/util/lock-contention.c @@ -104,7 +104,8 @@ bool match_callstack_filter(struct machine *machine, u64 *callstack, int max_sta struct map *kmap; struct symbol *sym; u64 ip; - const char *arch = perf_env__arch(machine->env); + uint16_t e_machine = perf_env__e_machine(machine->env, /*e_flags=*/NULL); + bool is_powerpc = e_machine == EM_PPC64 || e_machine == EM_PPC; if (list_empty(&callstack_filters)) return true; @@ -125,8 +126,7 @@ bool match_callstack_filter(struct machine *machine, u64 *callstack, int max_sta * incase first or second callstack index entry has 0 * address for powerpc. */ - if (!callstack || (!callstack[i] && (strcmp(arch, "powerpc") || - (i != 1 && i != 2)))) + if (!callstack || (!callstack[i] && (!is_powerpc || (i != 1 && i != 2)))) break; ip = callstack[i]; From 13d5660026b5415caea341380d68bc75960ba502 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:11 -0700 Subject: [PATCH 187/343] perf env: Refactor perf_env__arch_strerrno The previous approach maps an architecture string to a function pointer to a function that takes an int errno value and returns a string. The new approach takes an e_machine and an errno value and returns a string. As the only call site is in builtin-trace.c, the e_machine is already present and potentially more specific than the perf_env arch string that is a single global value. Since the errno-to-name mapping is now generated statically and no longer depends on libtraceevent, we can remove the HAVE_LIBTRACEEVENT guards entirely, making perf_env__arch_strerrno unconditionally available. The major complication in this approach is having the shell script that generates the C code map a linux directory name to the matching ELF machine constants. To ensure compatibility with older hosts that have older glibc versions, output fallback definitions for newer ELF machine constants (EM_AARCH64, EM_CSKY, EM_LOONGARCH) if they are not defined in the system . Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 7 +-- tools/perf/trace/beauty/Build | 1 + tools/perf/trace/beauty/arch_errno_names.sh | 53 +++++++++++++++++++-- tools/perf/util/env.c | 13 ++--- tools/perf/util/env.h | 6 +-- 5 files changed, 58 insertions(+), 22 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 2530b4035e4f..377f0a18b00e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3032,9 +3032,8 @@ static int trace__sys_exit(struct trace *trace, } else if (ret < 0) { errno_print: { char bf[STRERR_BUFSIZE]; - struct perf_env *env = evsel__env(evsel) ?: &trace->host_env; const char *emsg = str_error_r(-ret, bf, sizeof(bf)); - const char *e = perf_env__arch_strerrno(env, err); + const char *e = perf_env__arch_strerrno(e_machine, err); fprintf(trace->output, "-1 %s (%s)", e, emsg); } @@ -4921,7 +4920,9 @@ static size_t syscall__dump_stats(struct trace *trace, int e_machine, FILE *fp, for (e = 0; e < stats->max_errno; ++e) { if (stats->errnos[e] != 0) - fprintf(fp, "\t\t\t\t%s: %d\n", perf_env__arch_strerrno(trace->host->env, e + 1), stats->errnos[e]); + fprintf(fp, "\t\t\t\t%s: %d\n", + perf_env__arch_strerrno(e_machine, e + 1), + stats->errnos[e]); } } lines++; diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build index 996e63cdf765..bf9553f683f8 100644 --- a/tools/perf/trace/beauty/Build +++ b/tools/perf/trace/beauty/Build @@ -36,6 +36,7 @@ perf-y += signum.o perf-y += socket_type.o perf-y += waitid_options.o perf-util-y += arch_errno_names.o + perf-y += tracepoints/ ifdef SHELLCHECK diff --git a/tools/perf/trace/beauty/arch_errno_names.sh b/tools/perf/trace/beauty/arch_errno_names.sh index d48d8561a7bb..8751bfa4a2b2 100755 --- a/tools/perf/trace/beauty/arch_errno_names.sh +++ b/tools/perf/trace/beauty/arch_errno_names.sh @@ -52,21 +52,50 @@ process_arch() |IFS=, create_errno_lookup_func "$arch" } +arch_to_e_machine() +{ + case "$1" in + alpha) printf '\tcase EM_ALPHA:\n' ;; + arc) printf '\tcase EM_ARC:\n' ;; + arm) printf '\tcase EM_ARM:\n' ;; + arm64) printf '\tcase EM_AARCH64:\n' ;; + csky) printf '\tcase EM_CSKY:\n' ;; + hexagon) printf '\tcase EM_HEXAGON:\n' ;; + loongarch) printf '\tcase EM_LOONGARCH:\n' ;; + microblaze) printf '\tcase EM_MICROBLAZE:\n' ;; + mips) printf '\tcase EM_MIPS:\n' ;; + parisc) printf '\tcase EM_PARISC:\n' ;; + powerpc) printf '\tcase EM_PPC:\n\tcase EM_PPC64:\n' ;; + riscv) printf '\tcase EM_RISCV:\n' ;; + s390) printf '\tcase EM_S390:\n' ;; + sh) printf '\tcase EM_SH:\n' ;; + sparc) printf '\tcase EM_SPARC:\n\tcase EM_SPARCV9:\n' ;; + x86) printf '\tcase EM_386:\n\tcase EM_X86_64:\n' ;; + xtensa) printf '\tcase EM_XTENSA:\n' ;; + esac +} + create_arch_errno_table_func() { archlist="$1" default="$2" - printf 'arch_syscalls__strerrno_t *\n' - printf 'arch_syscalls__strerrno_function(const char *arch)\n' + printf 'const char *arch_syscalls__strerrno(uint16_t e_machine, int err);\n\n' + printf '__attribute__((unused)) const char *\n' + printf 'arch_syscalls__strerrno(uint16_t e_machine, int err)\n' printf '{\n' + printf '\tswitch (e_machine) {\n' for arch in $archlist; do arch_str=$(arch_string "$arch") - printf '\tif (!strcmp(arch, "%s"))\n' "$arch_str" - printf '\t\treturn errno_to_name__%s;\n' "$arch_str" + ems=$(arch_to_e_machine "$arch_str") + if [ -n "$ems" ]; then + printf '%s\n' "$ems" + printf '\t\treturn errno_to_name__%s(err);\n' "$arch_str" + fi done arch_str=$(arch_string "$default") - printf '\treturn errno_to_name__%s;\n' "$arch_str" + printf '\tdefault:\n\t\treturn errno_to_name__%s(err);\n' "$arch_str" + printf '\t}\n' printf '}\n' } @@ -74,6 +103,20 @@ cat < +#include +#include + +#ifndef EM_AARCH64 +#define EM_AARCH64 183 +#endif + +#ifndef EM_CSKY +#define EM_CSKY 252 +#endif + +#ifndef EM_LOONGARCH +#define EM_LOONGARCH 258 +#endif EoHEADER diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index fae70b07ba8d..b41562fb06c6 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -851,16 +851,11 @@ const char *perf_env__arch(struct perf_env *env) return arch; } -const char *perf_env__arch_strerrno(struct perf_env *env __maybe_unused, int err __maybe_unused) -{ -#if defined(HAVE_LIBTRACEEVENT) - if (env->arch_strerrno == NULL) - env->arch_strerrno = arch_syscalls__strerrno_function(perf_env__arch(env)); +const char *arch_syscalls__strerrno(uint16_t e_machine, int err); - return env->arch_strerrno ? env->arch_strerrno(err) : "no arch specific strerrno function"; -#else - return "!HAVE_LIBTRACEEVENT"; -#endif +const char *perf_env__arch_strerrno(uint16_t e_machine, int err) +{ + return arch_syscalls__strerrno(e_machine, err); } const char *perf_env__cpuid(struct perf_env *env) diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index dd9907dbc345..5a917271ca0d 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -67,8 +67,6 @@ struct cpu_domain_map { struct domain_info **domains; }; -typedef const char *(arch_syscalls__strerrno_t)(int err); - struct perf_env { char *hostname; char *os_release; @@ -158,7 +156,6 @@ struct perf_env { */ bool enabled; } clock; - arch_syscalls__strerrno_t *arch_strerrno; }; enum perf_compress_type { @@ -191,8 +188,7 @@ void cpu_cache_level__free(struct cpu_cache_level *cache); uint16_t perf_env__e_machine_nocache(struct perf_env *env, uint32_t *e_flags); uint16_t perf_env__e_machine(struct perf_env *env, uint32_t *e_flags); const char *perf_env__arch(struct perf_env *env); -const char *perf_env__arch_strerrno(struct perf_env *env, int err); -arch_syscalls__strerrno_t *arch_syscalls__strerrno_function(const char *arch); +const char *perf_env__arch_strerrno(uint16_t e_machine, int err); const char *perf_env__cpuid(struct perf_env *env); const char *perf_env__raw_arch(struct perf_env *env); int perf_env__nr_cpus_avail(struct perf_env *env); From da976dd4842981fa9fe8bf736ec3d440fa9ce029 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:12 -0700 Subject: [PATCH 188/343] perf env: Remove unused perf_env__raw_arch The switch to using e_machine has made the perf_env__raw_arch function unused so remove it. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/env.c | 18 ------------------ tools/perf/util/env.h | 1 - 2 files changed, 19 deletions(-) diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index b41562fb06c6..28c54c58193e 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -470,19 +470,6 @@ int perf_env__read_cpuid(struct perf_env *env) return 0; } -static int perf_env__read_arch(struct perf_env *env) -{ - struct utsname uts; - - if (env->arch) - return 0; - - if (!uname(&uts)) - env->arch = strdup(uts.machine); - - return env->arch ? 0 : -ENOMEM; -} - static int perf_env__read_nr_cpus_avail(struct perf_env *env) { if (env->nr_cpus_avail == 0) @@ -601,11 +588,6 @@ int perf_env__read_core_pmu_caps(struct perf_env *env) return ret; } -const char *perf_env__raw_arch(struct perf_env *env) -{ - return env && !perf_env__read_arch(env) ? env->arch : "unknown"; -} - int perf_env__nr_cpus_avail(struct perf_env *env) { return env && !perf_env__read_nr_cpus_avail(env) ? env->nr_cpus_avail : 0; diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index 5a917271ca0d..83e74328798f 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -190,7 +190,6 @@ uint16_t perf_env__e_machine(struct perf_env *env, uint32_t *e_flags); const char *perf_env__arch(struct perf_env *env); const char *perf_env__arch_strerrno(uint16_t e_machine, int err); const char *perf_env__cpuid(struct perf_env *env); -const char *perf_env__raw_arch(struct perf_env *env); int perf_env__nr_cpus_avail(struct perf_env *env); void perf_env__init(struct perf_env *env); From 0ff9718c266f9eb334674377501ccf37d8d351a4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:13 -0700 Subject: [PATCH 189/343] perf env: Add mutex to protect lazy environment initialization Introduce a mutex to 'struct perf_env' to safely protect lazy metadata setup, such as os_release or e_machine resolution, preventing concurrent initialization data races and memory leaks during multi-threaded profiling or symbol loading. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/env.c | 5 +++++ tools/perf/util/env.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 28c54c58193e..03d90a45992c 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -250,6 +250,8 @@ void perf_env__exit(struct perf_env *env) { int i, j; + mutex_destroy(&env->lock); + perf_env__purge_bpf(env); perf_env__purge_cgroups(env); zfree(&env->hostname); @@ -307,6 +309,7 @@ void perf_env__init(struct perf_env *env) init_rwsem(&env->bpf_progs.lock); #endif env->kernel_is_64_bit = -1; + mutex_init(&env->lock); } static void perf_env__init_kernel_mode(struct perf_env *env) @@ -1014,6 +1017,7 @@ bool x86__is_amd_cpu(void) struct perf_env env = { .total_mem = 0, }; bool is_amd; + perf_env__init(&env); perf_env__cpuid(&env); is_amd = perf_env__is_x86_amd_cpu(&env); perf_env__exit(&env); @@ -1036,6 +1040,7 @@ bool x86__is_intel_cpu(void) struct perf_env env = { .total_mem = 0, }; bool is_intel; + perf_env__init(&env); perf_env__cpuid(&env); is_intel = perf_env__is_x86_intel_cpu(&env); perf_env__exit(&env); diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index 83e74328798f..6aaf80c640bd 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -6,6 +6,7 @@ #include #include "cpumap.h" #include "rwsem.h" +#include "mutex.h" struct perf_cpu_map; @@ -156,6 +157,8 @@ struct perf_env { */ bool enabled; } clock; + /* Protects lazy environment initialization (e.g. os_release, e_machine). */ + struct mutex lock; }; enum perf_compress_type { From b34c7c147bff19722f729d10370f00850d477eac Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:14 -0700 Subject: [PATCH 190/343] perf env: Add helper to lazily compute the os_release In live mode the os_release isn't being initialized, make a lazy initialization helper that assumes when the os_release isn't initialized this is live mode. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/data-convert-bt.c | 2 +- tools/perf/util/data-convert-json.c | 6 +++-- tools/perf/util/env.c | 38 +++++++++++++++++++++++++++++ tools/perf/util/env.h | 1 + tools/perf/util/header.c | 16 ++++++++---- tools/perf/util/symbol.c | 4 +-- 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index b3f745cff2a7..cc51b8677c8e 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -1414,7 +1414,7 @@ do { \ ADD("host", env->hostname); ADD("sysname", "Linux"); - ADD("release", env->os_release); + ADD("release", perf_env__os_release(env)); ADD("version", env->version); ADD("machine", env->arch); ADD("domain", "kernel"); diff --git a/tools/perf/util/data-convert-json.c b/tools/perf/util/data-convert-json.c index a7da93a7ff0e..c71dfb77c697 100644 --- a/tools/perf/util/data-convert-json.c +++ b/tools/perf/util/data-convert-json.c @@ -16,6 +16,7 @@ #include "linux/err.h" #include "util/auxtrace.h" #include "util/debug.h" +#include "util/env.h" #include "util/dso.h" #include "util/event.h" #include "util/evsel.h" @@ -272,7 +273,7 @@ static void output_headers(struct perf_session *session, struct convert_json *c) { struct stat st; const struct perf_header *header = &session->header; - const struct perf_env *env = perf_session__env(session); + struct perf_env *env = perf_session__env(session); int ret; int fd = perf_data__fd(session->data); int i; @@ -296,7 +297,8 @@ static void output_headers(struct perf_session *session, struct convert_json *c) output_json_key_format(out, true, 2, "feat-offset", "%" PRIu64, header->feat_offset); output_json_key_string(out, true, 2, "hostname", env->hostname); - output_json_key_string(out, true, 2, "os-release", env->os_release); + output_json_key_string(out, true, 2, "os-release", + perf_env__os_release(env)); output_json_key_string(out, true, 2, "arch", env->arch); if (env->cpu_desc) diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 03d90a45992c..c0e2b9d5f0b2 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -361,6 +361,44 @@ bool perf_arch_is_big_endian(const char *arch) return false; } +const char *perf_env__os_release(struct perf_env *env) +{ + struct utsname uts; + int ret; + const char *release; + + if (!env) + return perf_version_string; + + mutex_lock(&env->lock); + if (env->os_release) { + release = env->os_release; + goto out; + } + + /* + * If env->arch is set, this is an offline target environment. + * If the os_release is not populated in the file, we do not want + * to poison it with the host's release which would break guest checks. + */ + if (env->arch) { + release = NULL; + goto out; + } + + /* + * The os_release is being accessed but wasn't initialized from a data + * file, assume this is 'live' mode and use the release from uname. If + * uname or strdup fails then use the current perf tool version. + */ + ret = uname(&uts); + env->os_release = strdup(ret < 0 ? perf_version_string : uts.release); + release = env->os_release ?: perf_version_string; +out: + mutex_unlock(&env->lock); + return release; +} + int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) { int i; diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index 6aaf80c640bd..7621d1f73b83 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -176,6 +176,7 @@ void perf_env__exit(struct perf_env *env); int perf_env__kernel_is_64_bit(struct perf_env *env); bool perf_arch_is_big_endian(const char *arch); +const char *perf_env__os_release(struct perf_env *env); int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index ecdac427d9c4..d7f41db7322c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -432,13 +432,19 @@ static int write_osrelease(struct feat_fd *ff, struct evlist *evlist __maybe_unused) { struct utsname uts; - int ret; + const char *release = NULL; - ret = uname(&uts); - if (ret < 0) - return -1; + if (evlist->session) + release = perf_env__os_release(perf_session__env(evlist->session)); - return do_write_string(ff, uts.release); + if (!release) { + int ret = uname(&uts); + + if (ret < 0) + return -1; + release = uts.release; + } + return do_write_string(ff, release); } static int write_arch(struct feat_fd *ff, struct evlist *evlist) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 2ce512f08a1d..077d19af5240 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -2225,7 +2225,7 @@ static int vmlinux_path__init(struct perf_env *env) { struct utsname uts; char bf[PATH_MAX]; - char *kernel_version; + const char *kernel_version; unsigned int i; vmlinux_path = malloc(sizeof(char *) * (ARRAY_SIZE(vmlinux_paths) + @@ -2242,7 +2242,7 @@ static int vmlinux_path__init(struct perf_env *env) return 0; if (env) { - kernel_version = env->os_release; + kernel_version = perf_env__os_release(env); } else { if (uname(&uts) < 0) goto out_fail; From 979e87ab1f258036aab9ed874aecede0163586e5 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:15 -0700 Subject: [PATCH 191/343] perf symbol: Add setters for bitfields sharing a byte to avoid concurrent update issues A problem with putting bitfields into struct symbol is that other bits in the symbol could be updated concurrently and only one update to the underlying storage unit happen, leading to lost updates. To avoid this, use atomics to atomically read or set part of 16-bits of flags in the symbol. Add accessors to simplify this. The idle value has 3 values in preparation for a later change that will lazily update it. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 10 +-- tools/perf/builtin-kwork.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-sched.c | 4 +- tools/perf/builtin-top.c | 7 +- tools/perf/tests/symbols.c | 2 +- tools/perf/tests/vmlinux-kallsyms.c | 2 +- tools/perf/ui/browsers/annotate.c | 2 +- tools/perf/ui/browsers/map.c | 4 +- tools/perf/util/annotate.c | 5 +- tools/perf/util/auxtrace.c | 6 +- tools/perf/util/callchain.c | 4 +- tools/perf/util/dlfilter.c | 2 +- tools/perf/util/evsel_fprintf.c | 6 +- tools/perf/util/intel-pt.c | 2 +- tools/perf/util/libdw.c | 2 +- tools/perf/util/machine.c | 2 +- tools/perf/util/probe-event.c | 4 +- .../util/scripting-engines/trace-event-perl.c | 2 +- .../scripting-engines/trace-event-python.c | 4 +- tools/perf/util/sort.c | 8 +- tools/perf/util/srcline.c | 10 +-- tools/perf/util/symbol-elf.c | 3 +- tools/perf/util/symbol.c | 86 +++++++++++++++---- tools/perf/util/symbol.h | 78 +++++++++++++---- tools/perf/util/symbol_fprintf.c | 4 +- 26 files changed, 183 insertions(+), 80 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index d8cb1f562f69..75ffe31d03fe 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -549,13 +549,11 @@ static int perf_event__convert_sample_callchain(const struct perf_tool *tool, node = cursor->first; for (k = 0; k < cursor->nr && i < PERF_MAX_STACK_DEPTH; k++) { - if (machine->single_address_space && - machine__kernel_ip(machine, node->ip)) - /* kernel IPs were added already */; - else if (node->ms.sym && node->ms.sym->inlined) - /* we can't handle inlined callchains */; - else + if (!(machine->single_address_space && + machine__kernel_ip(machine, node->ip)) && + !(node->ms.sym && symbol__inlined(node->ms.sym))) { inject->raw_callchain->ips[i++] = node->ip; + } node = node->next; } diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index 110de3507d48..7b61168e01e9 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -770,7 +770,7 @@ static void timehist_save_callchain(struct perf_kwork *kwork, if (sym) { if (!strcmp(sym->name, "__softirqentry_text_start") || !strcmp(sym->name, "__do_softirq")) - sym->ignore = 1; + symbol__set_ignore(sym, true); } callchain_cursor_advance(cursor); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index cd052aa78132..6f044c3df893 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -752,7 +752,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg) struct report *rep = arg; struct symbol *sym = he->ms.sym; - if (rep->symbol_ipc && sym && !sym->annotate2) { + if (rep->symbol_ipc && sym && !symbol__is_annotate2(sym)) { struct evsel *evsel = hists_to_evsel(he->hists); symbol__annotate2(&he->ms, evsel, NULL); diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 81833d169470..4de2baf03c50 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2387,7 +2387,7 @@ static void save_task_callchain(struct perf_sched *sched, if (!strcmp(sym->name, "schedule") || !strcmp(sym->name, "__schedule") || !strcmp(sym->name, "preempt_schedule")) - sym->ignore = 1; + symbol__set_ignore(sym, true); } callchain_cursor_advance(cursor); @@ -3048,7 +3048,7 @@ static size_t callchain__fprintf_folded(FILE *fp, struct callchain_node *node) list_for_each_entry(chain, &node->val, list) { if (chain->ip >= PERF_CONTEXT_MAX) continue; - if (chain->ms.sym && chain->ms.sym->ignore) + if (chain->ms.sym && symbol__ignore(chain->ms.sym)) continue; ret += fprintf(fp, "%s%s", first ? "" : sep, callchain_list__sym_name(chain, bf, sizeof(bf), diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c8474f7ac658..1211401616ee 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -186,8 +186,8 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip) "Please report to linux-kernel@vger.kernel.org\n", ip, dso__long_name(dso), dso__symtab_origin(dso), map__start(map), map__end(map), sym->start, sym->end, - sym->binding == STB_GLOBAL ? 'g' : - sym->binding == STB_LOCAL ? 'l' : 'w', sym->name, + symbol__binding(sym) == STB_GLOBAL ? 'g' : + symbol__binding(sym) == STB_LOCAL ? 'l' : 'w', sym->name, err ? "[unknown]" : uts.machine, err ? "[unknown]" : uts.release, perf_version_string); if (use_browser <= 0) @@ -828,7 +828,8 @@ static void perf_event__process_sample(const struct perf_tool *tool, } } - if (al.sym == NULL || !al.sym->idle) { + if (al.sym == NULL || + !symbol__is_idle(al.sym, al.map ? map__dso(al.map) : NULL, machine->env)) { struct hists *hists = evsel__hists(sample->evsel); struct hist_entry_iter iter = { .sample = sample, diff --git a/tools/perf/tests/symbols.c b/tools/perf/tests/symbols.c index f4ffe5804f40..c09e04f36035 100644 --- a/tools/perf/tests/symbols.c +++ b/tools/perf/tests/symbols.c @@ -125,7 +125,7 @@ static int test_dso(struct dso *dso) for (nd = rb_first_cached(dso__symbols(dso)); nd; nd = rb_next(nd)) { struct symbol *sym = rb_entry(nd, struct symbol, rb_node); - if (sym->type != STT_FUNC && sym->type != STT_GNU_IFUNC) + if (symbol__type(sym) != STT_FUNC && symbol__type(sym) != STT_GNU_IFUNC) continue; /* Check for overlapping function symbols */ diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c index 524d46478364..7409abe4aa36 100644 --- a/tools/perf/tests/vmlinux-kallsyms.c +++ b/tools/perf/tests/vmlinux-kallsyms.c @@ -346,7 +346,7 @@ static int test__vmlinux_matches_kallsyms(struct test_suite *test __maybe_unused * such as __indirect_thunk_end. */ continue; - } else if (is_ignored_symbol(sym->name, sym->type)) { + } else if (is_ignored_symbol(sym->name, symbol__type(sym))) { /* * Ignore hidden symbols, see scripts/kallsyms.c for the details */ diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index ea17e6d29a7e..e220c4dfc881 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -1185,7 +1185,7 @@ int __hist_entry__tui_annotate(struct hist_entry *he, struct map_symbol *ms, if (dso__annotate_warned(dso)) return -1; - if (not_annotated || !sym->annotate2) { + if (not_annotated || !symbol__is_annotate2(sym)) { err = symbol__annotate2(ms, evsel, &browser.arch); if (err) { annotate_browser__symbol_annotate_error(&browser, err); diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c index c61ba3174a24..075a575cdc5d 100644 --- a/tools/perf/ui/browsers/map.c +++ b/tools/perf/ui/browsers/map.c @@ -32,8 +32,8 @@ static void map_browser__write(struct ui_browser *browser, void *nd, int row) ui_browser__set_percent_color(browser, 0, current_entry); ui_browser__printf(browser, "%*" PRIx64 " %*" PRIx64 " %c ", mb->addrlen, sym->start, mb->addrlen, sym->end, - sym->binding == STB_GLOBAL ? 'g' : - sym->binding == STB_LOCAL ? 'l' : 'w'); + symbol__binding(sym) == STB_GLOBAL ? 'g' : + symbol__binding(sym) == STB_LOCAL ? 'l' : 'w'); width = browser->width - ((mb->addrlen * 2) + 4); if (width > 0) ui_browser__write_nstring(browser, sym->name, width); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 470569745abe..02505222d8c2 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -236,7 +236,8 @@ static int __symbol__inc_addr_samples(struct map_symbol *ms, h = annotated_source__histogram(src, evsel); if (h == NULL) { pr_debug("%s(%d): ENOMEM! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 ", func: %d\n", - __func__, __LINE__, sym->name, sym->start, addr, sym->end, sym->type == STT_FUNC); + __func__, __LINE__, sym->name, sym->start, addr, sym->end, + symbol__type(sym) == STT_FUNC); return -ENOMEM; } @@ -2223,7 +2224,7 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel, annotation__init_column_widths(notes, sym); annotation__update_column_widths(notes); - sym->annotate2 = 1; + symbol__set_annotate2(sym, true); return 0; } diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index fcf564e0d777..5f4aa1701aef 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -2694,7 +2694,7 @@ static bool dso_sym_match(struct symbol *sym, const char *name, int *cnt, { /* Same name, and global or the n'th found or any */ return !arch__compare_symbol_names(name, sym->name) && - ((!idx && sym->binding == STB_GLOBAL) || + ((!idx && symbol__binding(sym) == STB_GLOBAL) || (idx > 0 && ++*cnt == idx) || idx < 0); } @@ -2712,8 +2712,8 @@ static void print_duplicate_syms(struct dso *dso, const char *sym_name) if (dso_sym_match(sym, sym_name, &cnt, -1)) { pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n", ++cnt, sym->start, - sym->binding == STB_GLOBAL ? 'g' : - sym->binding == STB_LOCAL ? 'l' : 'w', + symbol__binding(sym) == STB_GLOBAL ? 'g' : + symbol__binding(sym) == STB_LOCAL ? 'l' : 'w', sym->name); near = true; } else if (near) { diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 5c2282051e39..8981ae879ebb 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -801,7 +801,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node, * symbol start. Otherwise do a faster comparison based * on the symbol start address. */ - if (cnode->ms.sym->inlined || node->ms.sym->inlined) { + if (symbol__inlined(cnode->ms.sym) || symbol__inlined(node->ms.sym)) { match = match_chain_strings(cnode->ms.sym->name, node->ms.sym->name); if (match != MATCH_ERROR) @@ -1245,7 +1245,7 @@ char *callchain_list__sym_name(struct callchain_list *cl, int printed; if (cl->ms.sym) { - const char *inlined = cl->ms.sym->inlined ? " (inlined)" : ""; + const char *inlined = symbol__inlined(cl->ms.sym) ? " (inlined)" : ""; if (show_srcline && cl->srcline) printed = scnprintf(bf, bfsize, "%s %s%s", diff --git a/tools/perf/util/dlfilter.c b/tools/perf/util/dlfilter.c index dc31b5e7149e..e11e144af62b 100644 --- a/tools/perf/util/dlfilter.c +++ b/tools/perf/util/dlfilter.c @@ -56,7 +56,7 @@ static void al_to_d_al(struct addr_location *al, struct perf_dlfilter_al *d_al) d_al->symoff = al->addr - map__start(al->map) - sym->start; else d_al->symoff = 0; - d_al->sym_binding = sym->binding; + d_al->sym_binding = symbol__binding(sym); } else { d_al->sym = NULL; d_al->sym_start = 0; diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c index 5521d00bff2c..0f7a25500a44 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -146,7 +146,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, sym = node->ms.sym; map = node->ms.map; - if (sym && sym->ignore && print_skip_ignored) + if (sym && symbol__ignore(sym) && print_skip_ignored) goto next; printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); @@ -182,7 +182,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, addr_location__exit(&node_al); } - if (print_dso && (!sym || !sym->inlined)) + if (print_dso && (!sym || !symbol__inlined(sym))) printed += map__fprintf_dsoname_dsoff(map, print_dsoff, addr, fp); if (print_srcline) { @@ -192,7 +192,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, printed += map__fprintf_srcline(map, addr, "\n ", fp); } - if (sym && sym->inlined) + if (sym && symbol__inlined(sym)) printed += fprintf(fp, " (inlined)"); if (!print_oneline) diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index b8add2b20033..56a9e439f5f8 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -3000,7 +3000,7 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip) start = dso__first_symbol(map__dso(map)); for (sym = start; sym; sym = dso__next_symbol(sym)) { - if (sym->binding == STB_GLOBAL && + if (symbol__binding(sym) == STB_GLOBAL && !strcmp(sym->name, "__switch_to")) { ip = map__unmap_ip(map, sym->start); if (ip >= map__start(map) && ip < map__end(map)) { diff --git a/tools/perf/util/libdw.c b/tools/perf/util/libdw.c index 84713b2a7ad5..d5d2958902c0 100644 --- a/tools/perf/util/libdw.c +++ b/tools/perf/util/libdw.c @@ -130,7 +130,7 @@ static int libdw_a2l_cb(Dwarf_Die *die, void *_args) return 0; abort_delete_sym: - if (inline_sym->inlined) + if (symbol__inlined(inline_sym)) symbol__delete(inline_sym); abort_enomem: args->err = -ENOMEM; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 47be7a44a5f7..da1ad58758af 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1095,7 +1095,7 @@ static u64 find_entry_trampoline(struct dso *dso) unsigned int i; for (; sym; sym = dso__next_symbol(sym)) { - if (sym->binding != STB_GLOBAL) + if (symbol__binding(sym) != STB_GLOBAL) continue; for (i = 0; i < ARRAY_SIZE(syms); i++) { if (!strcmp(sym->name, syms[i])) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 34b4badd2c14..11ae4a09412c 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -416,7 +416,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo, map__for_each_symbol_by_name(map, pp->function, sym, idx) { if (uprobes) { address = sym->start; - if (sym->type == STT_GNU_IFUNC) + if (symbol__type(sym) == STT_GNU_IFUNC) pr_warning("Warning: The probe function (%s) is a GNU indirect function.\n" "Consider identifying the final function used at run time and set the probe directly on that.\n", pp->function); @@ -3189,7 +3189,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, for (j = 0; j < num_matched_functions; j++) { sym = syms[j]; - if (sym->type != STT_FUNC) + if (symbol__type(sym) != STT_FUNC) continue; /* There can be duplicated symbols in the map */ diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 7a18ea4b7d50..410dc4cd0600 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -303,7 +303,7 @@ static SV *perl_process_callchain(struct perf_sample *sample, } if (!hv_stores(sym, "start", newSVuv(node->ms.sym->start)) || !hv_stores(sym, "end", newSVuv(node->ms.sym->end)) || - !hv_stores(sym, "binding", newSVuv(node->ms.sym->binding)) || + !hv_stores(sym, "binding", newSVuv(symbol__binding(node->ms.sym))) || !hv_stores(sym, "name", newSVpvn(node->ms.sym->name, node->ms.sym->namelen)) || !hv_stores(elem, "sym", newRV_noinc((SV*)sym))) { diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index cee1f32d7022..8f832ae316ca 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -436,7 +436,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, pydict_set_item_string_decref(pysym, "end", PyLong_FromUnsignedLongLong(node->ms.sym->end)); pydict_set_item_string_decref(pysym, "binding", - _PyLong_FromLong(node->ms.sym->binding)); + _PyLong_FromLong(symbol__binding(node->ms.sym))); pydict_set_item_string_decref(pysym, "name", _PyUnicode_FromStringAndSize(node->ms.sym->name, node->ms.sym->namelen)); @@ -1270,7 +1270,7 @@ static int python_export_symbol(struct db_export *dbe, struct symbol *sym, tuple_set_d64(t, 1, dso__db_id(dso)); tuple_set_d64(t, 2, sym->start); tuple_set_d64(t, 3, sym->end); - tuple_set_s32(t, 4, sym->binding); + tuple_set_s32(t, 4, symbol__binding(sym)); tuple_set_string(t, 5, sym->name); call_object(tables->symbol_handler, t, "symbol_table"); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 90bc4a31bb55..005e7d85dc4a 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -469,7 +469,7 @@ int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) if (sym_l == sym_r) return 0; - if (sym_l->inlined || sym_r->inlined) { + if (symbol__inlined(sym_l) || symbol__inlined(sym_r)) { int ret = strcmp(sym_l->name, sym_r->name); if (ret) @@ -536,7 +536,7 @@ static int _hist_entry__sym_snprintf(struct map_symbol *ms, ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); if (sym && map) { - if (sym->type == STT_OBJECT) { + if (symbol__type(sym) == STT_OBJECT) { ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", ip - map__unmap_ip(map, sym->start)); @@ -544,7 +544,7 @@ static int _hist_entry__sym_snprintf(struct map_symbol *ms, ret += repsep_snprintf(bf + ret, size - ret, "%.*s", width - ret, sym->name); - if (sym->inlined) + if (symbol__inlined(sym)) ret += repsep_snprintf(bf + ret, size - ret, " (inlined)"); } @@ -1483,7 +1483,7 @@ static int _hist_entry__addr_snprintf(struct map_symbol *ms, ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); if (sym && map) { - if (sym->type == STT_OBJECT) { + if (symbol__type(sym) == STT_OBJECT) { ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", ip - map__unmap_ip(map, sym->start)); diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index 62884428fb5a..b082178c279b 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -113,16 +113,16 @@ struct symbol *new_inline_sym(struct dso *dso, /* ensure that we don't alias an inlined symbol, which could * lead to double frees in inline_node__delete */ - assert(!base_sym->inlined); + assert(!symbol__inlined(base_sym)); } else { /* create a fake symbol for the inline frame */ inline_sym = symbol__new(base_sym ? base_sym->start : 0, base_sym ? (base_sym->end - base_sym->start) : 0, - base_sym ? base_sym->binding : 0, - base_sym ? base_sym->type : 0, + base_sym ? symbol__binding(base_sym) : 0, + base_sym ? symbol__type(base_sym) : 0, funcname); if (inline_sym) - inline_sym->inlined = 1; + symbol__set_inlined(inline_sym, true); } free(demangled); @@ -440,7 +440,7 @@ void inline_node__clear_frames(struct inline_node *node) list_del_init(&ilist->list); zfree_srcline(&ilist->srcline); /* only the inlined symbols are owned by the list */ - if (ilist->symbol && ilist->symbol->inlined) + if (ilist->symbol && symbol__inlined(ilist->symbol)) symbol__delete(ilist->symbol); free(ilist); } diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 77e6dcba8fda..c5ed5e051976 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -350,7 +350,8 @@ static bool get_ifunc_name(Elf *elf, struct dso *dso, GElf_Ehdr *ehdr, sym = dso__find_symbol_nocache(dso, addr); /* Expecting the address to be an IFUNC or IFUNC alias */ - if (!sym || sym->start != addr || (sym->type != STT_GNU_IFUNC && !sym->ifunc_alias)) + if (!sym || sym->start != addr || + (symbol__type(sym) != STT_GNU_IFUNC && !symbol__ifunc_alias(sym))) return false; snprintf(buf, buf_sz, "%s@plt", sym->name); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 077d19af5240..ddd3106b03b1 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -50,7 +50,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map); static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map); -static bool symbol__is_idle(const char *name); +static bool symbol__compute_is_idle(const char *name); int vmlinux_path__nr_entries; char **vmlinux_path; @@ -163,24 +163,24 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb) else if ((a == 0) && (b > 0)) return SYMBOL_B; - if (syma->type != symb->type) { - if (syma->type == STT_NOTYPE) + if (symbol__type(syma) != symbol__type(symb)) { + if (symbol__type(syma) == STT_NOTYPE) return SYMBOL_B; - if (symb->type == STT_NOTYPE) + if (symbol__type(symb) == STT_NOTYPE) return SYMBOL_A; } /* Prefer a non weak symbol over a weak one */ - a = syma->binding == STB_WEAK; - b = symb->binding == STB_WEAK; + a = symbol__binding(syma) == STB_WEAK; + b = symbol__binding(symb) == STB_WEAK; if (b && !a) return SYMBOL_A; if (a && !b) return SYMBOL_B; /* Prefer a global symbol over a non global one */ - a = syma->binding == STB_GLOBAL; - b = symb->binding == STB_GLOBAL; + a = symbol__binding(syma) == STB_GLOBAL; + b = symbol__binding(symb) == STB_GLOBAL; if (a && !b) return SYMBOL_A; if (b && !a) @@ -227,14 +227,14 @@ void symbols__fixup_duplicate(struct rb_root_cached *symbols) continue; if (choose_best_symbol(curr, next) == SYMBOL_A) { - if (next->type == STT_GNU_IFUNC) - curr->ifunc_alias = true; + if (symbol__type(next) == STT_GNU_IFUNC) + symbol__set_ifunc_alias(curr, true); rb_erase_cached(&next->rb_node, symbols); symbol__delete(next); goto again; } else { - if (curr->type == STT_GNU_IFUNC) - next->ifunc_alias = true; + if (symbol__type(curr) == STT_GNU_IFUNC) + symbol__set_ifunc_alias(next, true); nd = rb_next(&curr->rb_node); rb_erase_cached(&curr->rb_node, symbols); symbol__delete(curr); @@ -322,8 +322,8 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, u8 type, const char * sym->start = start; sym->end = len ? start + len : start; - sym->type = type; - sym->binding = binding; + atomic_init(&sym->flags, (type << SYMBOL_FLAG_TYPE_SHIFT) | + (binding << SYMBOL_FLAG_BINDING_SHIFT)); sym->namelen = namelen - 1; pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", @@ -345,6 +345,49 @@ void symbol__delete(struct symbol *sym) free(((void *)sym) - symbol_conf.priv_size); } +void symbol__set_ignore(struct symbol *sym, bool ignore) +{ + if (ignore) + atomic_fetch_or(&sym->flags, SYMBOL_FLAG_IGNORE); + else + atomic_fetch_and(&sym->flags, ~SYMBOL_FLAG_IGNORE); +} + +void symbol__set_annotate2(struct symbol *sym, bool annotate2) +{ + if (annotate2) + atomic_fetch_or(&sym->flags, SYMBOL_FLAG_ANNOTATE2); + else + atomic_fetch_and(&sym->flags, ~SYMBOL_FLAG_ANNOTATE2); +} + +void symbol__set_inlined(struct symbol *sym, bool inlined) +{ + if (inlined) + atomic_fetch_or(&sym->flags, SYMBOL_FLAG_INLINED); + else + atomic_fetch_and(&sym->flags, ~SYMBOL_FLAG_INLINED); +} + +void symbol__set_ifunc_alias(struct symbol *sym, bool ifunc_alias) +{ + if (ifunc_alias) + atomic_fetch_or(&sym->flags, SYMBOL_FLAG_IFUNC_ALIAS); + else + atomic_fetch_and(&sym->flags, ~SYMBOL_FLAG_IFUNC_ALIAS); +} + +static void symbol__set_idle(struct symbol *sym, bool idle) +{ + uint16_t old_flags = atomic_load(&sym->flags); + uint16_t new_flags; + uint16_t idle_val = idle ? SYMBOL_IDLE__IDLE : SYMBOL_IDLE__NOT_IDLE; + + do { + new_flags = old_flags & ~SYMBOL_FLAG_IDLE_MASK; + new_flags |= (idle_val << SYMBOL_FLAG_IDLE_SHIFT); + } while (!atomic_compare_exchange_weak(&sym->flags, &old_flags, new_flags)); +} void symbols__delete(struct rb_root_cached *symbols) { struct symbol *pos; @@ -375,7 +418,7 @@ void __symbols__insert(struct rb_root_cached *symbols, */ if (name[0] == '.') name++; - sym->idle = symbol__is_idle(name); + symbol__set_idle(sym, symbol__compute_is_idle(name)); } while (*p != NULL) { @@ -717,11 +760,21 @@ int modules__parse(const char *filename, void *arg, return err; } +bool symbol__is_idle(struct symbol *sym, + const struct dso *dso __maybe_unused, + struct perf_env *env __maybe_unused) +{ + uint16_t flags = atomic_load_explicit(&sym->flags, memory_order_relaxed); + uint16_t idle_val = (flags & SYMBOL_FLAG_IDLE_MASK) >> SYMBOL_FLAG_IDLE_SHIFT; + + return idle_val == SYMBOL_IDLE__IDLE; +} + /* * These are symbols in the kernel image, so make sure that * sym is from a kernel DSO. */ -static bool symbol__is_idle(const char *name) +static bool symbol__compute_is_idle(const char *name) { const char * const idle_symbols[] = { "acpi_idle_do_entry", @@ -2492,6 +2545,7 @@ void symbol__exit(void) { if (!symbol_conf.initialized) return; + strlist__delete(symbol_conf.bt_stop_list); strlist__delete(symbol_conf.sym_list); strlist__delete(symbol_conf.dso_list); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 95592779eb77..16a27074a474 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ struct map; struct maps; struct option; struct build_id; +struct perf_env; /* * Ignore kernel mapping symbols, matching kernel is_mapping_symbol() logic. @@ -58,6 +60,23 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, GElf_Shdr *shp, const char *name, size_t *idx); #endif +enum symbol_idle_kind { + SYMBOL_IDLE__UNKNOWN = 0, + SYMBOL_IDLE__NOT_IDLE = 1, + SYMBOL_IDLE__IDLE = 2, +}; + +#define SYMBOL_FLAG_TYPE_SHIFT 0 +#define SYMBOL_FLAG_TYPE_MASK (0xF << SYMBOL_FLAG_TYPE_SHIFT) +#define SYMBOL_FLAG_BINDING_SHIFT 4 +#define SYMBOL_FLAG_BINDING_MASK (0xF << SYMBOL_FLAG_BINDING_SHIFT) +#define SYMBOL_FLAG_IDLE_SHIFT 8 +#define SYMBOL_FLAG_IDLE_MASK (0x3 << SYMBOL_FLAG_IDLE_SHIFT) +#define SYMBOL_FLAG_IGNORE (1 << 10) +#define SYMBOL_FLAG_INLINED (1 << 11) +#define SYMBOL_FLAG_ANNOTATE2 (1 << 12) +#define SYMBOL_FLAG_IFUNC_ALIAS (1 << 13) + /** * A symtab entry. When allocated this may be preceded by an annotation (see * symbol__annotation) and/or a browser_index (see symbol__browser_index). @@ -69,20 +88,7 @@ struct symbol { u64 end; /** Length of the string name. */ u16 namelen; - /** ELF symbol type as defined for st_info. E.g STT_OBJECT or STT_FUNC. */ - u8 type:4; - /** ELF binding type as defined for st_info. E.g. STB_WEAK or STB_GLOBAL. */ - u8 binding:4; - /** Set true for kernel symbols of idle routines. */ - u8 idle:1; - /** Resolvable but tools ignore it (e.g. idle routines). */ - u8 ignore:1; - /** Symbol for an inlined function. */ - u8 inlined:1; - /** Has symbol__annotate2 been performed. */ - u8 annotate2:1; - /** Symbol is an alias of an STT_GNU_IFUNC */ - u8 ifunc_alias:1; + _Atomic uint16_t flags; /** Architecture specific. Unused except on PPC where it holds st_other. */ u8 arch_sym; /** The name of length namelen associated with the symbol. */ @@ -92,6 +98,49 @@ struct symbol { void symbol__delete(struct symbol *sym); void symbols__delete(struct rb_root_cached *symbols); +static inline u8 symbol__type(const struct symbol *sym) +{ + return (atomic_load_explicit(&sym->flags, memory_order_relaxed) & + SYMBOL_FLAG_TYPE_MASK) >> SYMBOL_FLAG_TYPE_SHIFT; +} + +static inline u8 symbol__binding(const struct symbol *sym) +{ + return (atomic_load_explicit(&sym->flags, memory_order_relaxed) & + SYMBOL_FLAG_BINDING_MASK) >> SYMBOL_FLAG_BINDING_SHIFT; +} + +static inline bool symbol__ignore(const struct symbol *sym) +{ + return (atomic_load_explicit(&sym->flags, memory_order_relaxed) & + SYMBOL_FLAG_IGNORE) != 0; +} + +static inline bool symbol__inlined(const struct symbol *sym) +{ + return (atomic_load_explicit(&sym->flags, memory_order_relaxed) & + SYMBOL_FLAG_INLINED) != 0; +} + +static inline bool symbol__is_annotate2(const struct symbol *sym) +{ + return (atomic_load_explicit(&sym->flags, memory_order_relaxed) & + SYMBOL_FLAG_ANNOTATE2) != 0; +} + +static inline bool symbol__ifunc_alias(const struct symbol *sym) +{ + return (atomic_load_explicit(&sym->flags, memory_order_relaxed) & + SYMBOL_FLAG_IFUNC_ALIAS) != 0; +} + +bool symbol__is_idle(struct symbol *sym, const struct dso *dso, struct perf_env *env); + +void symbol__set_ignore(struct symbol *sym, bool ignore); +void symbol__set_annotate2(struct symbol *sym, bool annotate2); +void symbol__set_inlined(struct symbol *sym, bool inlined); +void symbol__set_ifunc_alias(struct symbol *sym, bool ifunc_alias); + /* symbols__for_each_entry - iterate over symbols (rb_root) * * @symbols: the rb_root of symbols @@ -169,7 +218,6 @@ int filename__read_debuglink(const char *filename, char *debuglink, size_t size); bool filename__has_section(const char *filename, const char *sec); -struct perf_env; int symbol__init(struct perf_env *env); void symbol__exit(void); void symbol__elf_init(void); diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c index 53e1af4ed9ac..4dc8d5761f52 100644 --- a/tools/perf/util/symbol_fprintf.c +++ b/tools/perf/util/symbol_fprintf.c @@ -11,8 +11,8 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp) { return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", sym->start, sym->end, - sym->binding == STB_GLOBAL ? 'g' : - sym->binding == STB_LOCAL ? 'l' : 'w', + symbol__binding(sym) == STB_GLOBAL ? 'g' : + symbol__binding(sym) == STB_LOCAL ? 'l' : 'w', sym->name); } From 044462f6f64d16e9f51a695719a3248e277c1d4e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 08:25:16 -0700 Subject: [PATCH 192/343] perf symbol: Lazily compute idle Switch from an idle boolean to a helper symbol__is_idle function. In the function lazily compute whether a symbol is an idle function taking into consideration the kernel version and architecture of the machine. As symbols__insert no longer needs to know if a symbol is for the kernel, remove the argument. To protect against drop-filtering of legitimate setup, online, or hotplug management functions (such as intel_idle_init), x86 matches are strictly constrained to exact known run-loops (intel_idle, intel_idle_irq, mwait_idle, mwait_idle_with_hints). If the target environment OS release is unresolvable (such as on guest traces), default to treating psw_idle as idle to prevent false negatives and match legacy trace behavior safely. This change is inspired by mailing list discussion, particularly from Thomas Richter and Heiko Carstens : https://lore.kernel.org/lkml/20260219113850.354271-1-tmricht@linux.ibm.com/ Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Honglei Wang Cc: Jan Polensky Cc: Sumanth Korikkar Cc: Thomas Richter Cc: Vasily Gorbik Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 2 +- tools/perf/util/symbol.c | 146 +++++++++++++++++++++++------------ tools/perf/util/symbol.h | 4 +- 3 files changed, 100 insertions(+), 52 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index c5ed5e051976..186e6d92ac3d 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1734,7 +1734,7 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss, arch__sym_update(f, &sym); - __symbols__insert(dso__symbols(curr_dso), f, dso__kernel(dso)); + __symbols__insert(dso__symbols(curr_dso), f); nr++; } dso__put(curr_dso); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index ddd3106b03b1..0c46b24ee098 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -50,7 +50,6 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map); static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map); -static bool symbol__compute_is_idle(const char *name); int vmlinux_path__nr_entries; char **vmlinux_path; @@ -379,7 +378,7 @@ void symbol__set_ifunc_alias(struct symbol *sym, bool ifunc_alias) static void symbol__set_idle(struct symbol *sym, bool idle) { - uint16_t old_flags = atomic_load(&sym->flags); + uint16_t old_flags = atomic_load_explicit(&sym->flags, memory_order_relaxed); uint16_t new_flags; uint16_t idle_val = idle ? SYMBOL_IDLE__IDLE : SYMBOL_IDLE__NOT_IDLE; @@ -401,8 +400,7 @@ void symbols__delete(struct rb_root_cached *symbols) } } -void __symbols__insert(struct rb_root_cached *symbols, - struct symbol *sym, bool kernel) +void __symbols__insert(struct rb_root_cached *symbols, struct symbol *sym) { struct rb_node **p = &symbols->rb_root.rb_node; struct rb_node *parent = NULL; @@ -410,17 +408,6 @@ void __symbols__insert(struct rb_root_cached *symbols, struct symbol *s; bool leftmost = true; - if (kernel) { - const char *name = sym->name; - /* - * ppc64 uses function descriptors and appends a '.' to the - * start of every instruction address. Remove it. - */ - if (name[0] == '.') - name++; - symbol__set_idle(sym, symbol__compute_is_idle(name)); - } - while (*p != NULL) { parent = *p; s = rb_entry(parent, struct symbol, rb_node); @@ -437,7 +424,7 @@ void __symbols__insert(struct rb_root_cached *symbols, void symbols__insert(struct rb_root_cached *symbols, struct symbol *sym) { - __symbols__insert(symbols, sym, false); + __symbols__insert(symbols, sym); } static struct symbol *symbols__find(struct rb_root_cached *symbols, u64 ip) @@ -598,7 +585,7 @@ void dso__reset_find_symbol_cache(struct dso *dso) void dso__insert_symbol(struct dso *dso, struct symbol *sym) { - __symbols__insert(dso__symbols(dso), sym, dso__kernel(dso)); + __symbols__insert(dso__symbols(dso), sym); /* update the symbol cache if necessary */ if (dso__last_find_result_addr(dso) >= sym->start && @@ -760,57 +747,120 @@ int modules__parse(const char *filename, void *arg, return err; } -bool symbol__is_idle(struct symbol *sym, - const struct dso *dso __maybe_unused, - struct perf_env *env __maybe_unused) -{ - uint16_t flags = atomic_load_explicit(&sym->flags, memory_order_relaxed); - uint16_t idle_val = (flags & SYMBOL_FLAG_IDLE_MASK) >> SYMBOL_FLAG_IDLE_SHIFT; - - return idle_val == SYMBOL_IDLE__IDLE; -} /* * These are symbols in the kernel image, so make sure that * sym is from a kernel DSO. */ -static bool symbol__compute_is_idle(const char *name) +static int sym_name_cmp(const void *a, const void *b) { - const char * const idle_symbols[] = { + const char *name = a; + const char *const *sym = b; + + return strcmp(name, *sym); +} + +static bool match_x86_idle_routine(const char *name, const char *base) +{ + if (strstarts(name, base)) { + size_t len = strlen(base); + + if (name[len] == '\0' || name[len] == '.') + return true; + } + return false; +} + +bool symbol__is_idle(struct symbol *sym, const struct dso *dso, struct perf_env *env) +{ + static const char * const idle_symbols[] = { "acpi_idle_do_entry", "acpi_processor_ffh_cstate_enter", "arch_cpu_idle", "cpu_idle", "cpu_startup_entry", - "idle_cpu", - "intel_idle", - "intel_idle_ibrs", "default_idle", - "native_safe_halt", "enter_idle", "exit_idle", - "mwait_idle", - "mwait_idle_with_hints", - "mwait_idle_with_hints.constprop.0", + "idle_cpu", + "native_safe_halt", "poll_idle", - "ppc64_runlatch_off", "pseries_dedicated_idle_sleep", - "psw_idle", - "psw_idle_exit", - NULL }; - int i; - static struct strlist *idle_symbols_list; + const char *name = sym->name; + uint16_t e_machine; - if (idle_symbols_list) - return strlist__has_entry(idle_symbols_list, name); + { + uint16_t flags = atomic_load_explicit(&sym->flags, memory_order_relaxed); + uint16_t idle_val = (flags & SYMBOL_FLAG_IDLE_MASK) >> SYMBOL_FLAG_IDLE_SHIFT; - idle_symbols_list = strlist__new(NULL, NULL); + if (idle_val != SYMBOL_IDLE__UNKNOWN) + return idle_val == SYMBOL_IDLE__IDLE; + } - for (i = 0; idle_symbols[i]; i++) - strlist__add(idle_symbols_list, idle_symbols[i]); + if (!dso || dso__kernel(dso) == DSO_SPACE__USER) { + symbol__set_idle(sym, /*idle=*/false); + return false; + } - return strlist__has_entry(idle_symbols_list, name); + /* + * ppc64 uses function descriptors and appends a '.' to the + * start of every instruction address. Remove it. + */ + if (name[0] == '.') + name++; + + if (bsearch(name, idle_symbols, ARRAY_SIZE(idle_symbols), + sizeof(idle_symbols[0]), sym_name_cmp)) { + symbol__set_idle(sym, /*idle=*/true); + return true; + } + + e_machine = (env && env->arch) ? perf_env__e_machine(env, NULL) : EM_NONE; + if (e_machine == EM_NONE && dso) + e_machine = dso__e_machine((struct dso *)dso, NULL, NULL); + if (e_machine == EM_NONE && env) + e_machine = perf_env__e_machine(env, NULL); + + if (e_machine == EM_386 || e_machine == EM_X86_64) { + if (match_x86_idle_routine(name, "intel_idle") || + match_x86_idle_routine(name, "intel_idle_irq") || + match_x86_idle_routine(name, "intel_idle_ibrs") || + match_x86_idle_routine(name, "mwait_idle") || + match_x86_idle_routine(name, "mwait_idle_with_hints")) { + symbol__set_idle(sym, /*idle=*/true); + return true; + } + } + + if (e_machine == EM_PPC64 && !strcmp(name, "ppc64_runlatch_off")) { + symbol__set_idle(sym, /*idle=*/true); + return true; + } + + if (e_machine == EM_S390 && strstarts(name, "psw_idle")) { + int major = 0, minor = 0; + const char *release = env ? perf_env__os_release(env) : NULL; + + /* + * If we can't determine the release (e.g. unpopulated guest traces), + * default to idle. + */ + if (!release) { + symbol__set_idle(sym, /*idle=*/true); + return true; + } + + /* Before v6.10, s390 used psw_idle. */ + if (sscanf(release, "%d.%d", &major, &minor) == 2 && + (major < 6 || (major == 6 && minor < 10))) { + symbol__set_idle(sym, /*idle=*/true); + return true; + } + } + + symbol__set_idle(sym, /*idle=*/false); + return false; } static int map__process_kallsym_symbol(void *arg, const char *name, @@ -839,7 +889,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name, * We will pass the symbols to the filter later, in * map__split_kallsyms, when we have split the maps per module */ - __symbols__insert(root, sym, !strchr(name, '[')); + __symbols__insert(root, sym); return 0; } diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 16a27074a474..a71525335703 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -76,7 +76,6 @@ enum symbol_idle_kind { #define SYMBOL_FLAG_INLINED (1 << 11) #define SYMBOL_FLAG_ANNOTATE2 (1 << 12) #define SYMBOL_FLAG_IFUNC_ALIAS (1 << 13) - /** * A symtab entry. When allocated this may be preceded by an annotation (see * symbol__annotation) and/or a browser_index (see symbol__browser_index). @@ -257,8 +256,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss); char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name); -void __symbols__insert(struct rb_root_cached *symbols, struct symbol *sym, - bool kernel); +void __symbols__insert(struct rb_root_cached *symbols, struct symbol *sym); void symbols__insert(struct rb_root_cached *symbols, struct symbol *sym); void symbols__fixup_duplicate(struct rb_root_cached *symbols); void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms); From b52ba22c7078e1987ce0cc0a8385654cb36296e3 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Wed, 3 Jun 2026 03:35:07 -0700 Subject: [PATCH 193/343] perf bench: Add --write-size option to sched pipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default ping-pong uses sizeof(int) (4 bytes) per iteration, which exercises only the pipe-buffer merge path and keeps allocation entirely out of the picture. That makes the bench a useful scheduler / context- switch latency probe but unable to surface anything from the pipe page-allocation hot path. Add a -s/--write-size option that sets the bytes written and read per ping-pong iteration. The buffer is allocated for each side via struct thread_data and replaces the on-stack int previously used. The default remains sizeof(int) so existing invocations are unchanged. With --write-size set above PAGE_SIZE the bench drives anon_pipe_write() through alloc_page() (or the bulk pre-alloc, if the relevant patch is applied), which is what we want when measuring pipe locking and page allocation work. The bench is a ping-pong: both sides call write() before read(), so a single write_size payload must fit entirely in the pipe buffer or both sides deadlock waiting for the other to drain. Resize the pipe via F_SETPIPE_SZ to match write_size (skipped at the sizeof(int) default), and error out cleanly when the request exceeds /proc/sys/fs/pipe-max-size. Committer testing: ⬢ [acme@toolbx perf-tools-next]$ perf bench sched pipe # Running 'sched/pipe' benchmark: # Executed 1000000 pipe operations between two processes Total time: 0.915 [sec] 0.915493 usecs/op 1092307 ops/sec ⬢ [acme@toolbx perf-tools-next]$ perf bench sched pipe --write-size 1024 # Running 'sched/pipe' benchmark: # Executed 1000000 pipe operations between two processes Total time: 0.891 [sec] 0.891915 usecs/op 1121183 ops/sec ⬢ [acme@toolbx perf-tools-next]$ perf bench sched pipe --write-size 4096 # Running 'sched/pipe' benchmark: # Executed 1000000 pipe operations between two processes Total time: 1.366 [sec] 1.366073 usecs/op 732025 ops/sec ⬢ [acme@toolbx perf-tools-next]$ strace -e fcntl perf bench sched pipe --write-size 4096 # Running 'sched/pipe' benchmark: fcntl(4, F_SETPIPE_SZ, 4096) = 4096 fcntl(6, F_SETPIPE_SZ, 4096) = 4096 ^Cstrace: Process 17840 detached ⬢ [acme@toolbx perf-tools-next]$ strace -e fcntl perf bench sched pipe --write-size 1024 # Running 'sched/pipe' benchmark: fcntl(4, F_SETPIPE_SZ, 1024) = 4096 fcntl(6, F_SETPIPE_SZ, 1024) = 4096 ^Cstrace: Process 17845 detached ⬢ [acme@toolbx perf-tools-next]$ strace -e fcntl perf bench sched pipe # Running 'sched/pipe' benchmark: ^Cstrace: Process 17851 detached ⬢ [acme@toolbx perf-tools-next]$ ⬢ [acme@toolbx perf-tools-next]$ perf bench sched pipe --write-size 1048577 # Running 'sched/pipe' benchmark: --write-size 1048577 exceeds /proc/sys/fs/pipe-max-size ⬢ [acme@toolbx perf-tools-next]$ cat /proc/sys/fs/pipe-max-size 1048576 ⬢ [acme@toolbx perf-tools-next]$ acme@number:~/git/perf-tools-next$ Signed-off-by: Breno Leitao Acked-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/sched-pipe.c | 129 ++++++++++++++++++++++++++++++---- 1 file changed, 116 insertions(+), 13 deletions(-) diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c index 70139036d68f..eb20c6d73d06 100644 --- a/tools/perf/bench/sched-pipe.c +++ b/tools/perf/bench/sched-pipe.c @@ -22,7 +22,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -39,6 +41,7 @@ struct thread_data { int epoll_fd; bool cgroup_failed; pthread_t pthread; + char *buf; }; #define LOOPS_DEFAULT 1000000 @@ -48,6 +51,7 @@ static int loops = LOOPS_DEFAULT; static bool threaded; static bool nonblocking; +static unsigned int write_size = sizeof(int); static char *cgrp_names[2]; static struct cgroup *cgrps[2]; @@ -88,6 +92,8 @@ static const struct option options[] = { OPT_BOOLEAN('n', "nonblocking", &nonblocking, "Use non-blocking operations"), OPT_INTEGER('l', "loop", &loops, "Specify number of loops"), OPT_BOOLEAN('T', "threaded", &threaded, "Specify threads/process based task setup"), + OPT_UINTEGER('s', "write-size", &write_size, + "Bytes per ping-pong write (default 4-bytes). Use larger values to exercise the pipe page-allocation path."), OPT_CALLBACK('G', "cgroups", NULL, "SEND,RECV", "Put sender and receivers in given cgroups", parse_two_cgroups), @@ -170,25 +176,77 @@ static void exit_cgroup(int nr) free(cgrp_names[nr]); } +/* Sleep until @fd is writable, so we don't busy-spin on EWOULDBLOCK. */ +static inline void wait_writable(int fd) +{ + struct pollfd pfd = { + .fd = fd, + .events = POLLOUT, + }; + + poll(&pfd, 1, -1); +} + +/* + * Loop on short read()/write(): the kernel may return fewer bytes than + * requested, retry on EINTR, and in non-blocking mode wait via poll() + * when the writer transiently hits EWOULDBLOCK while the peer is still + * draining a full pipe (capacity is sized to write_size). + */ +static inline int write_pipe(struct thread_data *td) +{ + unsigned int done = 0; + int ret; + + while (done < write_size) { + ret = write(td->pipe_write, td->buf + done, write_size - done); + if (ret < 0) { + if (errno == EINTR) + continue; + if (nonblocking && errno == EWOULDBLOCK) { + wait_writable(td->pipe_write); + continue; + } + return ret; + } + done += ret; + } + return done; +} + static inline int read_pipe(struct thread_data *td) { - int ret, m; -retry: - if (nonblocking) { - ret = epoll_wait(td->epoll_fd, &td->epoll_ev, 1, -1); - if (ret < 0) + unsigned int done = 0; + int ret; + + while (done < write_size) { + if (nonblocking) { + ret = epoll_wait(td->epoll_fd, &td->epoll_ev, 1, -1); + if (ret < 0) { + if (errno == EINTR) + continue; + return ret; + } + } + ret = read(td->pipe_read, td->buf + done, write_size - done); + if (ret < 0) { + if (errno == EINTR) + continue; + if (nonblocking && errno == EWOULDBLOCK) + continue; return ret; + } + if (ret == 0) + return done; + done += ret; } - ret = read(td->pipe_read, &m, sizeof(int)); - if (nonblocking && ret < 0 && errno == EWOULDBLOCK) - goto retry; - return ret; + return done; } static void *worker_thread(void *__tdata) { struct thread_data *td = __tdata; - int i, ret, m = 0; + int i, ret; ret = enter_cgroup(td->nr); if (ret < 0) { @@ -204,15 +262,38 @@ static void *worker_thread(void *__tdata) } for (i = 0; i < loops; i++) { - ret = write(td->pipe_write, &m, sizeof(int)); - BUG_ON(ret != sizeof(int)); + ret = write_pipe(td); + BUG_ON(ret != (int)write_size); ret = read_pipe(td); - BUG_ON(ret != sizeof(int)); + BUG_ON(ret != (int)write_size); } return NULL; } +/* + * On a custom write_size, resize the pipes so a single payload fits. + */ +static int resize_pipes(int wfd1, int wfd2) +{ + int r1, r2; + + if (write_size <= sizeof(int)) + return 0; + + r1 = fcntl(wfd1, F_SETPIPE_SZ, write_size); + r2 = fcntl(wfd2, F_SETPIPE_SZ, write_size); + if (r1 < 0 || r2 < 0 || + (unsigned int)r1 < write_size || + (unsigned int)r2 < write_size) { + fprintf(stderr, + "--write-size %u exceeds /proc/sys/fs/pipe-max-size\n", + write_size); + return -1; + } + return 0; +} + int bench_sched_pipe(int argc, const char **argv) { struct thread_data threads[2] = {}; @@ -233,12 +314,31 @@ int bench_sched_pipe(int argc, const char **argv) argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0); + /* + * The error paths below return early without closing the pipes or + * freeing the cgroup state. That is fine: bench_sched_pipe() runs + * once and the process exits right after it returns, so these are + * not real leaks. + */ + if (write_size == 0 || write_size > INT_MAX) { + fprintf(stderr, "--write-size must be in 1..%d\n", INT_MAX); + return -1; + } + if (nonblocking) flags |= O_NONBLOCK; BUG_ON(pipe2(pipe_1, flags)); BUG_ON(pipe2(pipe_2, flags)); + if (resize_pipes(pipe_1[1], pipe_2[1]) < 0) + return -1; + + for (t = 0; t < nr_threads; t++) { + threads[t].buf = calloc(1, write_size); + BUG_ON(!threads[t].buf); + } + gettimeofday(&start, NULL); for (t = 0; t < nr_threads; t++) { @@ -287,6 +387,9 @@ int bench_sched_pipe(int argc, const char **argv) gettimeofday(&stop, NULL); timersub(&stop, &start, &diff); + for (t = 0; t < nr_threads; t++) + free(threads[t].buf); + exit_cgroup(0); exit_cgroup(1); From 7a92b1e22dc267e1e21c66a6b64b147726050f30 Mon Sep 17 00:00:00 2001 From: Suchit Karunakaran Date: Sun, 31 May 2026 01:22:30 +0530 Subject: [PATCH 194/343] perf lock: Fix non-atomic max/time and min_time updates in contention_data The update_contention_data() had a FIXME noting that max_time and min_time updates lacked atomicity. Two CPUs could simultaneously read a stale value, pass the comparison check and race on the write-back, with the smaller value potentially overwriting the larger one and silently corrupting the statistics. Fix this by replacing the bare conditional assignments with a bpf_loop()-based CAS retry loop. Each field tracks its own convergence independently via max_done/min_done flags in cas_ctx, so a successful CAS on one field is never retried even if the other field needs more attempts. Signed-off-by: Suchit Karunakaran Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Signed-off-by: Arnaldo Carvalho de Melo --- .../perf/util/bpf_skel/lock_contention.bpf.c | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c index 96e7d853b9ed..5c8431be674a 100644 --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c @@ -175,6 +175,13 @@ struct mm_struct___new { struct rw_semaphore mmap_lock; } __attribute__((preserve_access_index)); +struct cas_ctx { + struct contention_data *data; + u64 duration; + int max_done; + int min_done; +}; + extern struct kmem_cache *bpf_get_kmem_cache(u64 addr) __ksym __weak; /* control flags */ @@ -486,16 +493,49 @@ static inline s32 get_owner_stack_id(u64 *stacktrace) return -1; } +static long cas_min_max_cb(u64 idx, void *arg) +{ + struct cas_ctx *ctx = arg; + + if (!ctx->max_done) { + u64 old_max = ctx->data->max_time; + if (old_max >= ctx->duration) { + ctx->max_done = 1; + } else { + u64 r = __sync_val_compare_and_swap( + &ctx->data->max_time, old_max, ctx->duration); + if (r == old_max) + ctx->max_done = 1; + } + } + + if (!ctx->min_done) { + u64 old_min = ctx->data->min_time; + if (old_min <= ctx->duration) { + ctx->min_done = 1; + } else { + u64 r = __sync_val_compare_and_swap( + &ctx->data->min_time, old_min, ctx->duration); + if (r == old_min) + ctx->min_done = 1; + } + } + + return (ctx->max_done && ctx->min_done) ? 1 : 0; +} + static inline void update_contention_data(struct contention_data *data, u64 duration, u32 count) { __sync_fetch_and_add(&data->total_time, duration); __sync_fetch_and_add(&data->count, count); - /* FIXME: need atomic operations */ - if (data->max_time < duration) - data->max_time = duration; - if (data->min_time > duration) - data->min_time = duration; + struct cas_ctx ctx = { + .data = data, + .duration = duration, + .max_done = 0, + .min_done = 0, + }; + bpf_loop(64, cas_min_max_cb, &ctx, 0); } static inline void update_owner_stat(u32 id, u64 duration, u32 flags) From 4caadd04f62104997cbf3c71364b0509e7b64108 Mon Sep 17 00:00:00 2001 From: Suchit Karunakaran Date: Sun, 31 May 2026 01:25:10 +0530 Subject: [PATCH 195/343] perf build: Compile BPF skeletons with -mcpu=v3 The lock_contention BPF program uses __sync_val_compare_and_swap() to atomically update the max_time and min_time fields in contention_data. This builtin lowers to the BPF_CMPXCHG instruction, which is only available in BPF ISA v3. Without an explicit -mcpu flag, Clang targets BPF v1/v2 by default on older toolchains (Clang < 18), causing build errors when v3 instructions are emitted. Add -mcpu=v3 to CLANG_OPTIONS, which is used exclusively in the BPF skeleton compilation rule. Reviewed-by: Namhyung Kim Signed-off-by: Suchit Karunakaran Acked-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Suchit Karunakaran Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bpf_skel.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/bpf_skel.mak b/tools/perf/bpf_skel.mak index 7704e7e635d8..f2559de39f96 100644 --- a/tools/perf/bpf_skel.mak +++ b/tools/perf/bpf_skel.mak @@ -29,7 +29,7 @@ ifneq ($(CROSS_COMPILE),) CLANG_TARGET_ARCH = --target=$(notdir $(CROSS_COMPILE:%-=%)) endif -CLANG_OPTIONS = -Wall +CLANG_OPTIONS = -Wall -mcpu=v3 CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH)) LIBBPF_INCLUDE := $(abspath $(or $(OUTPUT),.))/libbpf/include BPF_INCLUDE := -I$(SKEL_TMP_OUT)/.. -I$(SKEL_TOOL_OUT) -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES) From 7e1f74bbbed7d3bf2f0597f820eba15ec70f35fa Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 30 May 2026 18:09:24 -0700 Subject: [PATCH 196/343] tools build: Fix feature checks to touch target files on success In tools/build/feature/Makefile, test-clang-bpf-co-re.bin and test-bpftool-skeletons.bin redirected grep output but never touched or created the $@ target file upon success. Because the target file was never created on disk, Kbuild could never cache the result of the check. Consequently, Make treated the prerequisite as missing and continuously re-executed the Clang BPF backend and bpftool feature checks on every single sub-make evaluation during build startup, or on every incremental build. Refactor both feature check recipes to touch $@ on success. For test-clang-bpf-co-re.bin, group the shell pipeline within curly braces and redirect both stdout and stderr to .make.output to allow errors to be inspected and not appear in build output. List test-clang-bpf-co-re.bin's input C file as a dependency so modification triggers a rebuild. For test-bpftool-skeletons.bin, add it to the FILES list so that it will be cleaned. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Bill Wendling Cc: Costa Shulyupin Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Justin Stitt Cc: Leo Yan Cc: Namhyung Kim Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Yuzhuo Jing Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/feature/Makefile | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 4e4a92ef5e1e..9da5a4fd956a 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -72,7 +72,8 @@ FILES= \ test-file-handle.bin \ test-libpfm4.bin \ test-rust.bin \ - test-libopenssl.bin + test-libopenssl.bin \ + test-bpftool-skeletons.bin FILES := $(addprefix $(OUTPUT),$(FILES)) @@ -379,9 +380,9 @@ $(OUTPUT)test-libaio.bin: $(OUTPUT)test-libzstd.bin: $(BUILD) -lzstd -$(OUTPUT)test-clang-bpf-co-re.bin: - $(CLANG) -S -g --target=bpf -o - $(patsubst %.bin,%.c,$(@F)) | \ - grep BTF_KIND_VAR +$(OUTPUT)test-clang-bpf-co-re.bin: test-clang-bpf-co-re.c + { $(CLANG) -S -g --target=bpf -o - $< | \ + grep BTF_KIND_VAR; } > $(@:.bin=.make.output) 2>&1 && touch $@ $(OUTPUT)test-file-handle.bin: $(BUILD) @@ -393,8 +394,8 @@ $(OUTPUT)test-libopenssl.bin: $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags openssl 2>/dev/null) $(OUTPUT)test-bpftool-skeletons.bin: - $(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons' \ - > $(@:.bin=.make.output) 2>&1 + { $(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons'; } \ + > $(@:.bin=.make.output) 2>&1 && touch $@ # Testing Rust is special: we don't compile anything, it's enough to check the # compiler presence. Compiling a test code for this purposes is problematic, From e565ceb48bbf82cc4db4a42a33e378fe30d8d010 Mon Sep 17 00:00:00 2001 From: Chun-Tse Shao Date: Thu, 21 May 2026 13:15:04 -0700 Subject: [PATCH 197/343] perf stat: Add aggr_nr metric parser support Introduce the `aggr_nr` function to the metric expression parser. `aggr_nr` allows metric formulas to dynamically utilize the number of aggregated targets (`aggr->nr`) instead of relying on the static `source_count` (which represents the static socket or node count). This adds the `AGGR_NR` token to the lexer and parser, updates the expression parsing context helpers to store `aggr_nr`, and feeds `aggr->nr` from the aggregation structure in `prepare_metric`. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Chun-Tse Shao Tested-by: Zide Chen Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Leo Yan Cc: Mark Rutland Cc: Peter Zijlstra Cc: Sandipan Das Cc: Thomas Falcon Cc: Yang Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/expr.c | 26 ++++++++++++++++++++++---- tools/perf/util/expr.h | 6 +++++- tools/perf/util/expr.l | 1 + tools/perf/util/expr.y | 24 +++++++++++++++++------- tools/perf/util/stat-shadow.c | 6 +++++- 5 files changed, 50 insertions(+), 13 deletions(-) diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 644769e92708..232998fef72b 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -27,6 +27,7 @@ struct expr_id_data { struct { double val; int source_count; + int aggr_nr; } val; struct { double val; @@ -151,8 +152,8 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) } /* Caller must make sure id is allocated */ -int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id, - double val, int source_count) +int expr__add_id_val_source_count_aggr_nr(struct expr_parse_ctx *ctx, const char *id, + double val, int source_count, int aggr_nr) { struct expr_id_data *data_ptr = NULL, *old_data = NULL; char *old_key = NULL; @@ -163,6 +164,7 @@ int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id, return -ENOMEM; data_ptr->val.val = val; data_ptr->val.source_count = source_count; + data_ptr->val.aggr_nr = aggr_nr; data_ptr->kind = EXPR_ID_DATA__VALUE; ret = hashmap__set(ctx->ids, id, data_ptr, &old_key, &old_data); @@ -171,12 +173,20 @@ int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id, } else if (old_data) { data_ptr->val.val += old_data->val.val; data_ptr->val.source_count += old_data->val.source_count; + data_ptr->val.aggr_nr += old_data->val.aggr_nr; } free(old_key); free(old_data); return ret; } +/* Caller must make sure id is allocated */ +int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id, + double val, int source_count) +{ + return expr__add_id_val_source_count_aggr_nr(ctx, id, val, source_count, 1); +} + int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) { struct expr_id_data *data_ptr = NULL, *old_data = NULL; @@ -390,8 +400,16 @@ double expr_id_data__value(const struct expr_id_data *data) double expr_id_data__source_count(const struct expr_id_data *data) { - assert(data->kind == EXPR_ID_DATA__VALUE); - return data->val.source_count; + if (data->kind == EXPR_ID_DATA__VALUE) + return data->val.source_count; + return 1.0; +} + +double expr_id_data__aggr_nr(const struct expr_id_data *data) +{ + if (data->kind == EXPR_ID_DATA__VALUE) + return data->val.aggr_nr; + return 1.0; } double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx) diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h index c0cec29ddc29..ed12e4007d2d 100644 --- a/tools/perf/util/expr.h +++ b/tools/perf/util/expr.h @@ -36,7 +36,9 @@ void expr__del_id(struct expr_parse_ctx *ctx, const char *id); int expr__add_id(struct expr_parse_ctx *ctx, const char *id); int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id, - double val, int source_count); + double val, int source_count); +int expr__add_id_val_source_count_aggr_nr(struct expr_parse_ctx *ctx, const char *id, + double val, int source_count, int aggr_nr); int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); int expr__get_id(struct expr_parse_ctx *ctx, const char *id, struct expr_id_data **data); @@ -53,6 +55,8 @@ int expr__find_ids(const char *expr, const char *one, double expr_id_data__value(const struct expr_id_data *data); double expr_id_data__source_count(const struct expr_id_data *data); +double expr_id_data__aggr_nr(const struct expr_id_data *data); + double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx); double expr__has_event(const struct expr_parse_ctx *ctx, bool compute_ids, const char *id); double expr__strcmp_cpuid_str(const struct expr_parse_ctx *ctx, bool compute_ids, const char *id); diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index a2fc43159ee9..f16ccff278d0 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -121,6 +121,7 @@ min { return MIN; } if { return IF; } else { return ELSE; } source_count { return SOURCE_COUNT; } +aggr_nr { return AGGR_NR; } has_event { return HAS_EVENT; } strcmp_cpuid_str { return STRCMP_CPUID_STR; } NaN { return nan_value(yyscanner); } diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index e364790babb5..e20f649354cf 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -41,7 +41,7 @@ int expr_lex(YYSTYPE * yylval_param , void *yyscanner); } ids; } -%token ID NUMBER MIN MAX IF ELSE LITERAL D_RATIO SOURCE_COUNT HAS_EVENT STRCMP_CPUID_STR EXPR_ERROR +%token ID NUMBER MIN MAX IF ELSE LITERAL D_RATIO SOURCE_COUNT AGGR_NR HAS_EVENT STRCMP_CPUID_STR EXPR_ERROR %left MIN MAX IF %left '|' %left '^' @@ -87,8 +87,14 @@ static struct ids union_expr(struct ids ids1, struct ids ids2) return result; } +enum expr_id_kind { + EXPR_ID_KIND__VALUE, + EXPR_ID_KIND__SOURCE_COUNT, + EXPR_ID_KIND__AGGR_NR, +}; + static struct ids handle_id(struct expr_parse_ctx *ctx, char *id, - bool compute_ids, bool source_count) + bool compute_ids, enum expr_id_kind kind) { struct ids result; @@ -101,9 +107,12 @@ static struct ids handle_id(struct expr_parse_ctx *ctx, char *id, result.val = NAN; if (expr__resolve_id(ctx, id, &data) == 0) { - result.val = source_count - ? expr_id_data__source_count(data) - : expr_id_data__value(data); + if (kind == EXPR_ID_KIND__SOURCE_COUNT) + result.val = expr_id_data__source_count(data); + else if (kind == EXPR_ID_KIND__AGGR_NR) + result.val = expr_id_data__aggr_nr(data); + else + result.val = expr_id_data__value(data); } result.ids = NULL; free(id); @@ -201,8 +210,9 @@ expr: NUMBER $$.val = $1; $$.ids = NULL; } -| ID { $$ = handle_id(ctx, $1, compute_ids, /*source_count=*/false); } -| SOURCE_COUNT '(' ID ')' { $$ = handle_id(ctx, $3, compute_ids, /*source_count=*/true); } +| ID { $$ = handle_id(ctx, $1, compute_ids, EXPR_ID_KIND__VALUE); } +| SOURCE_COUNT '(' ID ')' { $$ = handle_id(ctx, $3, compute_ids, EXPR_ID_KIND__SOURCE_COUNT); } +| AGGR_NR '(' ID ')' { $$ = handle_id(ctx, $3, compute_ids, EXPR_ID_KIND__AGGR_NR); } | HAS_EVENT '(' ID ')' { $$.val = expr__has_event(ctx, compute_ids, $3); diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index bc2d44df7baf..c17373bb0e1e 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -53,6 +53,7 @@ static int prepare_metric(struct perf_stat_config *config, for (i = 0; metric_events[i]; i++) { int source_count = 0, tool_aggr_idx; + int aggr_nr = 1; bool is_tool_time = tool_pmu__is_time_event(config, metric_events[i], &tool_aggr_idx); struct perf_stat_evsel *ps = metric_events[i]->stats; @@ -89,6 +90,7 @@ static int prepare_metric(struct perf_stat_config *config, */ val = NAN; source_count = 0; + aggr_nr = 0; } else { struct perf_stat_aggr *aggr = &ps->aggr[is_tool_time ? tool_aggr_idx : aggr_idx]; @@ -96,6 +98,7 @@ static int prepare_metric(struct perf_stat_config *config, if (aggr->counts.run == 0) { val = NAN; source_count = 0; + aggr_nr = 0; } else { val = aggr->counts.val; if (is_tool_time) { @@ -104,13 +107,14 @@ static int prepare_metric(struct perf_stat_config *config, } if (!source_count) source_count = evsel__source_count(metric_events[i]); + aggr_nr = aggr->nr ?: 1; } } n = strdup(evsel__metric_id(metric_events[i])); if (!n) return -ENOMEM; - expr__add_id_val_source_count(pctx, n, val, source_count); + expr__add_id_val_source_count_aggr_nr(pctx, n, val, source_count, aggr_nr); } for (int j = 0; metric_refs && metric_refs[j].metric_name; j++) { From ca156ab12b2e2718b35dd6d30e0aea7be0edb11d Mon Sep 17 00:00:00 2001 From: Chun-Tse Shao Date: Thu, 21 May 2026 13:15:05 -0700 Subject: [PATCH 198/343] perf stat: Use aggr_nr scaling for Intel uncore miss latency metrics Update `metric.py` to support the new `aggr_nr` keyword in the python metric generator. Replace the usage of `source_count` with `aggr_nr` in `IntelMissLat` inside `intel_metrics.py` so that uncore latency metrics (like `lpm_miss_lat`) scale correctly on multi-socket and SNC systems when aggregated globally. Additionally, update the validation bypass logic in `CheckEveryEvent()` inside `metric.py` to whitelist 'cha' and 'uncore' events. This prevents validation failures when compiling metrics referencing these PMU-specific uncore events. Assisted-by: Gemini:gemini-3.1-pro-preview Signed-off-by: Chun-Tse Shao Tested-by: Zide Chen Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Leo Yan Cc: Mark Rutland Cc: Peter Zijlstra Cc: Sandipan Das Cc: Thomas Falcon Cc: Yang Li Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/intel_metrics.py | 6 +++--- tools/perf/pmu-events/metric.py | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/perf/pmu-events/intel_metrics.py b/tools/perf/pmu-events/intel_metrics.py index c3a5c2965f74..bc2b920d3a0d 100755 --- a/tools/perf/pmu-events/intel_metrics.py +++ b/tools/perf/pmu-events/intel_metrics.py @@ -7,7 +7,7 @@ import os import re from typing import Optional from common_metrics import Cycles -from metric import (d_ratio, has_event, max, source_count, CheckPmu, Event, +from metric import (d_ratio, has_event, max, aggr_nr, CheckPmu, Event, JsonEncodeMetric, JsonEncodeMetricGroupDescriptions, Literal, LoadEvents, Metric, MetricConstraint, MetricGroup, MetricRef, Select) @@ -735,10 +735,10 @@ def IntelMissLat() -> Optional[MetricGroup]: else: assert data_rd_loc_occ.name == "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_LOCAL", data_rd_loc_occ - ticks_per_cha = ticks / source_count(data_rd_loc_ins) + ticks_per_cha = ticks / aggr_nr(data_rd_loc_ins) loc_lat = interval_sec * 1e9 * data_rd_loc_occ / \ (ticks_per_cha * data_rd_loc_ins) - ticks_per_cha = ticks / source_count(data_rd_rem_ins) + ticks_per_cha = ticks / aggr_nr(data_rd_rem_ins) rem_lat = interval_sec * 1e9 * data_rd_rem_occ / \ (ticks_per_cha * data_rd_rem_ins) return MetricGroup("lpm_miss_lat", [ diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index ac582db785fc..a91ccb5977f0 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -93,7 +93,7 @@ def CheckEveryEvent(*names: str) -> None: name = name[:name.find(':')] elif '/' in name: name = name[:name.find('/')] - if any([name.startswith(x) for x in ['amd', 'arm', 'cpu', 'msr', 'power']]): + if any([name.startswith(x) for x in ['amd', 'arm', 'cpu', 'msr', 'power', 'cha', 'uncore']]): continue if name not in all_events_all_models: raise Exception(f"Is {name} a named json event?") @@ -576,6 +576,11 @@ def source_count(event: Event) -> Function: return Function('source_count', event) +def aggr_nr(event: Event) -> Function: + # pylint: disable=invalid-name + return Function('aggr_nr', event) + + def has_event(event: Event) -> Function: # pylint: disable=redefined-builtin # pylint: disable=invalid-name @@ -762,7 +767,7 @@ def ParsePerfJson(orig: str) -> Expression: # Convert accidentally converted scientific notation constants back py = re.sub(r'([0-9]+)Event\(r"(e[0-9]*)"\)', r'\1\2', py) # Convert all the known keywords back from events to just the keyword - keywords = ['if', 'else', 'min', 'max', 'd_ratio', 'source_count', 'has_event', 'strcmp_cpuid_str'] + keywords = ['if', 'else', 'min', 'max', 'd_ratio', 'source_count', 'aggr_nr', 'has_event', 'strcmp_cpuid_str'] for kw in keywords: py = re.sub(rf'Event\(r"{kw}"\)', kw, py) try: From 68018df3f55eba96a20dd703f5f276a6518f4963 Mon Sep 17 00:00:00 2001 From: Rui Qi Date: Thu, 28 May 2026 14:23:55 +0800 Subject: [PATCH 199/343] perf: Fix off-by-one stack buffer overflow in kallsyms__parse() In kallsyms__parse(), the loop reading symbol names iterates with i < sizeof(symbol_name), which allows i to reach sizeof(symbol_name) upon loop exit. The subsequent symbol_name[i] = '\0' then writes one byte past the end of the stack-allocated symbol_name[] array. Fix this by changing the loop bound to KSYM_NAME_LEN, so the null terminator always lands within the array. The overflow is triggerable by a kallsyms entry with a symbol name of KSYM_NAME_LEN+1 or more characters (e.g., long Rust mangled names or a malicious /proc/kallsyms). Fixes: 53df2b9344128984 ("libsymbols kallsyms: Parse using io api") Signed-off-by: Rui Qi Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/symbol/kallsyms.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c index e335ac2b9e19..d64bd9cc82a9 100644 --- a/tools/lib/symbol/kallsyms.c +++ b/tools/lib/symbol/kallsyms.c @@ -60,7 +60,7 @@ int kallsyms__parse(const char *filename, void *arg, read_to_eol(&io); continue; } - for (i = 0; i < sizeof(symbol_name); i++) { + for (i = 0; i < KSYM_NAME_LEN; i++) { ch = io__get_char(&io); if (ch < 0 || ch == '\n') break; @@ -68,6 +68,9 @@ int kallsyms__parse(const char *filename, void *arg, } symbol_name[i] = '\0'; + if (i == KSYM_NAME_LEN) + read_to_eol(&io); + err = process_symbol(arg, symbol_name, symbol_type, start); if (err) break; From 154b7c3ec4c1a85f5ff230678a1515c5f91bbc45 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 5 May 2026 14:19:00 -0700 Subject: [PATCH 200/343] perf tools: Ensure event leader stays at head of evlist after sorting For evlist of a certain event/metric, the HEAD should be the event leader. In some scenarios where uncore_xxx_0 does not exist, the event leader is not the first element after sorting. For example, on my test machine uncore_iio_0 does not exist, the event leader is uncore_iio_2. However, in `evlist__cmp`, it was reordered based on the PMU name, which makes uncore_iio_1 the HEAD of evlist, breaking the following merge logic in `evsel__merge_aliases`. The patch adds a loop at the end of `parse_events__sort_events_and_fix_groups` to make sure the first wildcard match is the earliest entry in the list, updating pointers accordingly without breaking reordering detection. Tested on device lacks uncore_iio_0, and `perf test` looks good. Signed-off-by: Chun-Tse Shao Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Cc: Thomas Falcon Cc: Thomas Richter Signed-off-by: Ian Rogers Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 1497e1f2a08c..943569e82b82 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2251,6 +2251,33 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list) } last_event_was_forced_leader = (force_grouped_leader == pos); } + + /* + * Make sure the first wildcard match is the earliest entry in the list. + * Since list_sort might have reordered the aliases, the original leader + * might not be at the head of the list anymore. We find the first + * alias in the sorted list and make it the new leader, and redirect + * all other aliases to it. + */ + list_for_each_entry(pos, list, core.node) { + struct evsel *orig_leader = pos->first_wildcard_match; + + if (!orig_leader) + continue; + + if (orig_leader->first_wildcard_match) { + /* Original leader was redirected to a new leader */ + pos->first_wildcard_match = orig_leader->first_wildcard_match; + } else if (pos->core.idx < orig_leader->core.idx) { + /* + * We are earlier than the original leader in sorted order, + * and no earlier alias has claimed leadership yet. + */ + orig_leader->first_wildcard_match = pos; + pos->first_wildcard_match = NULL; + } + } + list_for_each_entry(pos, list, core.node) { struct evsel *pos_leader = evsel__leader(pos); From 74802634e4a7e556429417963a8cbda27dd8b4b3 Mon Sep 17 00:00:00 2001 From: James Clark Date: Mon, 20 Apr 2026 12:52:17 +0100 Subject: [PATCH 201/343] perf annotate: Fix crashes on empty annotate windows Annotate can open with an empty window if the disassembly tool fails. After the linked change, the TUI started assuming there was a current annotation line and could assert or segfault in the seek, refresh, and source-toggle paths. Handle empty annotate windows explicitly: set the asm entry count before resetting the browser, return early when refreshing an empty list, and ignore source line toggle when there is no current annotation line. Fixes the following when opening an annotation: perf: ui/browser.c:125: ui_browser__list_head_seek: Assertion `pos != NULL' failed. Aborted Fixes: e201757f7a0a901e ("perf annotate: Fix source code annotate with objdump") Assisted-by: GitHub Copilot:GPT-5.4 Signed-off-by: James Clark Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browser.c | 3 +++ tools/perf/ui/browsers/annotate.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index dc88427b4ae5..321187b204d3 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -513,6 +513,9 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *browser) struct list_head *head = browser->entries; int row = 0; + if (browser->nr_entries == 0) + return 0; + if (browser->top == NULL || browser->top == browser->entries) browser->top = ui_browser__list_head_filter_entries(browser, head->next); diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index e220c4dfc881..97ae4c86bebb 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -449,6 +449,9 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser, struct annotation_line *al; off_t offset = browser->b.index - browser->b.top_idx; + if (browser->b.nr_entries == 0) + return false; + browser->b.seek(&browser->b, offset, SEEK_CUR); al = list_entry(browser->b.top, struct annotation_line, node); @@ -542,8 +545,8 @@ static void annotate_browser__show_full_location(struct ui_browser *browser) static void ui_browser__init_asm_mode(struct ui_browser *browser) { struct annotation *notes = browser__annotation(browser); - ui_browser__reset_index(browser); browser->nr_entries = notes->src->nr_asm_entries; + ui_browser__reset_index(browser); } static int sym_title(struct symbol *sym, struct map *map, char *title, From bded0398ac19bc808984f50023bb482ce41f7bdd Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:12 -0700 Subject: [PATCH 202/343] perf tpebs: Fix concurrent stop races and PID reuse hazards in tpebs_stop Parallel verbose test execution can trigger a race condition in tpebs_stop if called concurrently or when PID reuse occurs, causing finish_command() to block or reap the wrong process. Introduce a `tpebs_stopping` flag inside intel-tpebs.c to prevent redundant stop execution paths, and safely restore the `cmd.pid` temporarily only during `finish_command()` to ensure it is properly reaped, while preventing other threads from referencing it. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/intel-tpebs.c | 92 ++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/intel-tpebs.c b/tools/perf/util/intel-tpebs.c index ed8cfe2ba2fa..bc3b79bfa01a 100644 --- a/tools/perf/util/intel-tpebs.c +++ b/tools/perf/util/intel-tpebs.c @@ -37,6 +37,7 @@ static pthread_t tpebs_reader_thread; static struct child_process tpebs_cmd; static int control_fd[2], ack_fd[2]; static struct mutex tpebs_mtx; +static bool tpebs_stopping; struct tpebs_retire_lat { struct list_head nd; @@ -52,16 +53,18 @@ struct tpebs_retire_lat { bool started; }; -static void tpebs_mtx_init(void) +static void tpebs_init(void) { mutex_init(&tpebs_mtx); + control_fd[0] = control_fd[1] = -1; + ack_fd[0] = ack_fd[1] = -1; } static struct mutex *tpebs_mtx_get(void) { - static pthread_once_t tpebs_mtx_once = PTHREAD_ONCE_INIT; + static pthread_once_t tpebs_once = PTHREAD_ONCE_INIT; - pthread_once(&tpebs_mtx_once, tpebs_mtx_init); + pthread_once(&tpebs_once, tpebs_init); return &tpebs_mtx; } @@ -111,6 +114,7 @@ static int evsel__tpebs_start_perf_record(struct evsel *evsel) /* Note, no workload given so system wide is implied. */ assert(tpebs_cmd.pid == 0); + memset(&tpebs_cmd, 0, sizeof(tpebs_cmd)); tpebs_cmd.argv = record_argv; tpebs_cmd.out = -1; ret = start_command(&tpebs_cmd); @@ -320,20 +324,43 @@ static int tpebs_stop(void) EXCLUSIVE_LOCKS_REQUIRED(tpebs_mtx_get()) { int ret = 0; + if (tpebs_stopping) + return 0; + /* Like tpebs_start, we should only run tpebs_end once. */ if (tpebs_cmd.pid != 0) { + pid_t actual_pid = tpebs_cmd.pid; + + tpebs_stopping = true; tpebs_send_record_cmd(EVLIST_CTL_CMD_STOP_TAG); tpebs_cmd.pid = 0; mutex_unlock(tpebs_mtx_get()); pthread_join(tpebs_reader_thread, NULL); mutex_lock(tpebs_mtx_get()); - close(control_fd[0]); - close(control_fd[1]); - close(ack_fd[0]); - close(ack_fd[1]); - close(tpebs_cmd.out); + if (control_fd[0] >= 0) { + close(control_fd[0]); + control_fd[0] = -1; + } + if (control_fd[1] >= 0) { + close(control_fd[1]); + control_fd[1] = -1; + } + if (ack_fd[0] >= 0) { + close(ack_fd[0]); + ack_fd[0] = -1; + } + if (ack_fd[1] >= 0) { + close(ack_fd[1]); + ack_fd[1] = -1; + } + if (tpebs_cmd.out >= 0) { + close(tpebs_cmd.out); + tpebs_cmd.out = -1; + } + tpebs_cmd.pid = actual_pid; ret = finish_command(&tpebs_cmd); tpebs_cmd.pid = 0; + tpebs_stopping = false; if (ret == -ERR_RUN_COMMAND_WAITPID_SIGNAL) ret = 0; } @@ -486,30 +513,42 @@ int evsel__tpebs_open(struct evsel *evsel) { int ret; bool tpebs_empty; + bool started_process = false; /* We should only run tpebs_start when tpebs_recording is enabled. */ if (!tpebs_recording) return 0; + + mutex_lock(tpebs_mtx_get()); + if (tpebs_stopping) { + mutex_unlock(tpebs_mtx_get()); + return -EBUSY; + } /* Only start the events once. */ if (tpebs_cmd.pid != 0) { struct tpebs_retire_lat *t; bool valid; - mutex_lock(tpebs_mtx_get()); t = tpebs_retire_lat__find(evsel); valid = t && t->started; mutex_unlock(tpebs_mtx_get()); /* May fail as the event wasn't started. */ return valid ? 0 : -EBUSY; } + mutex_unlock(tpebs_mtx_get()); ret = evsel__tpebs_prepare(evsel); if (ret) return ret; mutex_lock(tpebs_mtx_get()); + if (tpebs_stopping || tpebs_cmd.pid != 0) { + ret = -EBUSY; + goto out; + } tpebs_empty = list_empty(&tpebs_results); if (!tpebs_empty) { + started_process = true; /*Create control and ack fd for --control*/ if (pipe(control_fd) < 0) { pr_err("tpebs: Failed to create control fifo"); @@ -529,7 +568,6 @@ int evsel__tpebs_open(struct evsel *evsel) if (pthread_create(&tpebs_reader_thread, /*attr=*/NULL, __sample_reader, /*arg=*/NULL)) { kill(tpebs_cmd.pid, SIGTERM); - close(tpebs_cmd.out); pr_err("Could not create thread to process sample data.\n"); ret = -1; goto out; @@ -540,8 +578,38 @@ int evsel__tpebs_open(struct evsel *evsel) if (ret) { struct tpebs_retire_lat *t = tpebs_retire_lat__find(evsel); - list_del_init(&t->nd); - tpebs_retire_lat__delete(t); + if (t) { + list_del_init(&t->nd); + tpebs_retire_lat__delete(t); + } + + if (started_process) { + if (tpebs_cmd.pid > 0) { + kill(tpebs_cmd.pid, SIGTERM); + finish_command(&tpebs_cmd); + tpebs_cmd.pid = 0; + } + if (tpebs_cmd.out >= 0) { + close(tpebs_cmd.out); + tpebs_cmd.out = -1; + } + if (control_fd[0] >= 0) { + close(control_fd[0]); + control_fd[0] = -1; + } + if (control_fd[1] >= 0) { + close(control_fd[1]); + control_fd[1] = -1; + } + if (ack_fd[0] >= 0) { + close(ack_fd[0]); + ack_fd[0] = -1; + } + if (ack_fd[1] >= 0) { + close(ack_fd[1]); + ack_fd[1] = -1; + } + } } mutex_unlock(tpebs_mtx_get()); return ret; From 2c43c0c78668a7026967ab8280f0f9ffc04e65f4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:13 -0700 Subject: [PATCH 203/343] perf jevents.py: Make generated C code more kernel style Make jevents.py generate C code that complies with formatting tools: - Add /* clang-format off */ before big_c_string and re-enable it after system mapping tables, bypassing large generated tables while checking functions and early structs. - Make comments more human readable and avoid going over 100 character line length. - Fix spaces indentation to tabs in struct/array initializers. - Fix other checkpatch detected related issues. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/empty-pmu-events.c | 8703 ++++++++++++++-------- tools/perf/pmu-events/jevents.py | 719 +- 2 files changed, 6022 insertions(+), 3400 deletions(-) diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index a92dd0424f79..ad5ade37adb0 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -1,6 +1,5 @@ - /* SPDX-License-Identifier: GPL-2.0 */ -/* THIS FILE WAS AUTOGENERATED BY jevents.py arch=none model=none ! */ +/* THIS FILE WAS AUTOGENERATED BY `jevents.py arch=none model=none` ! */ #include #include "util/header.h" @@ -9,2777 +8,5403 @@ #include struct compact_pmu_event { - int offset; + int offset; }; struct pmu_table_entry { - const struct compact_pmu_event *entries; - uint32_t num_entries; - struct compact_pmu_event pmu_name; + const struct compact_pmu_event *entries; + uint32_t num_entries; + struct compact_pmu_event pmu_name; }; +/* clang-format off */ static const char *const big_c_string = -/* offset=0 */ "default_core\000" -/* offset=13 */ "l1-dcache\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=99 */ "l1-dcache-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=190 */ "l1-dcache-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=286 */ "l1-dcache-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=387 */ "l1-dcache-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=482 */ "l1-dcache-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=580 */ "l1-dcache-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00000\000\000\000\000\000" -/* offset=682 */ "l1-dcache-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=782 */ "l1-dcache-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00000\000\000\000\000\000" -/* offset=874 */ "l1-dcache-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=971 */ "l1-dcache-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=1073 */ "l1-dcache-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=1169 */ "l1-dcache-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=1268 */ "l1-dcache-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=1371 */ "l1-dcache-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=1472 */ "l1-dcache-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=1563 */ "l1-dcache-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=1659 */ "l1-dcache-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=1760 */ "l1-dcache-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=1855 */ "l1-dcache-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=1953 */ "l1-dcache-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=2055 */ "l1-dcache-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=2155 */ "l1-dcache-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=2252 */ "l1-dcache-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=2354 */ "l1-dcache-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=2461 */ "l1-dcache-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=2562 */ "l1-dcache-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=2666 */ "l1-dcache-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00000\000\000\000\000\000" -/* offset=2770 */ "l1-dcache-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=2872 */ "l1-dcache-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00000\000\000\000\000\000" -/* offset=2970 */ "l1-dcache-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=3073 */ "l1-dcache-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=3181 */ "l1-dcache-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=3283 */ "l1-dcache-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=3388 */ "l1-dcache-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=3493 */ "l1-dcache-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=3596 */ "l1-dcache-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=3693 */ "l1-dcache-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=3795 */ "l1-dcache-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=3902 */ "l1-dcache-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=4003 */ "l1-dcache-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=4107 */ "l1-dcache-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=4211 */ "l1-dcache-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=4313 */ "l1-dcache-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=4416 */ "l1-dcache-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=4524 */ "l1-dcache-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=4637 */ "l1-dcache-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=4744 */ "l1-dcache-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=4854 */ "l1-dcache-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00000\000\000\000\000\000" -/* offset=4964 */ "l1-dcache-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=5072 */ "l1-dcache-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00000\000\000\000\000\000" -/* offset=5177 */ "l1-dcache-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=5287 */ "l1-dcache-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=5402 */ "l1-dcache-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=5511 */ "l1-dcache-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=5623 */ "l1-dcache-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=5735 */ "l1-dcache-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=5845 */ "l1-dcache-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=5956 */ "l1-dcache-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=6072 */ "l1-dcache-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=6193 */ "l1-dcache-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=6308 */ "l1-dcache-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=6426 */ "l1-dcache-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=6544 */ "l1-dcache-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=6660 */ "l1-dcache-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=6771 */ "l1-dcache-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=6887 */ "l1-dcache-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=7008 */ "l1-dcache-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=7123 */ "l1-dcache-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=7241 */ "l1-dcache-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=7359 */ "l1-dcache-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=7475 */ "l1-dcache-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=7566 */ "l1-dcache-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=7662 */ "l1-dcache-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=7752 */ "l1-dcache-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=7845 */ "l1-dcache-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=7942 */ "l1-dcache-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=8037 */ "l1-d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=8118 */ "l1-d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=8204 */ "l1-d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=8295 */ "l1-d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=8391 */ "l1-d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=8481 */ "l1-d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=8574 */ "l1-d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=8671 */ "l1-d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=8766 */ "l1-d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=8853 */ "l1-d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=8945 */ "l1-d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=9042 */ "l1-d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=9133 */ "l1-d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=9227 */ "l1-d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=9325 */ "l1-d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=9421 */ "l1-d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=9507 */ "l1-d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=9598 */ "l1-d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=9694 */ "l1-d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=9784 */ "l1-d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=9877 */ "l1-d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=9974 */ "l1-d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=10069 */ "l1-d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=10161 */ "l1-d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=10258 */ "l1-d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=10360 */ "l1-d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=10456 */ "l1-d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=10555 */ "l1-d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=10654 */ "l1-d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=10751 */ "l1-d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=10844 */ "l1-d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=10942 */ "l1-d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=11045 */ "l1-d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=11142 */ "l1-d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=11242 */ "l1-d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=11342 */ "l1-d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=11440 */ "l1-d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=11532 */ "l1-d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=11629 */ "l1-d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=11731 */ "l1-d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=11827 */ "l1-d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=11926 */ "l1-d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=12025 */ "l1-d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=12122 */ "l1-d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=12220 */ "l1-d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=12323 */ "l1-d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=12431 */ "l1-d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=12533 */ "l1-d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=12638 */ "l1-d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=12743 */ "l1-d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=12846 */ "l1-d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=12946 */ "l1-d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=13051 */ "l1-d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=13161 */ "l1-d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=13265 */ "l1-d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=13372 */ "l1-d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=13479 */ "l1-d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=13584 */ "l1-d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=13690 */ "l1-d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=13801 */ "l1-d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=13917 */ "l1-d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=14027 */ "l1-d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=14140 */ "l1-d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=14253 */ "l1-d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=14364 */ "l1-d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=14470 */ "l1-d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=14581 */ "l1-d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=14697 */ "l1-d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=14807 */ "l1-d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=14920 */ "l1-d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=15033 */ "l1-d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=15144 */ "l1-d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=15230 */ "l1-d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=15321 */ "l1-d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=15406 */ "l1-d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=15494 */ "l1-d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=15586 */ "l1-d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=15676 */ "l1d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=15756 */ "l1d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=15841 */ "l1d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=15931 */ "l1d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=16026 */ "l1d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=16115 */ "l1d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=16207 */ "l1d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=16303 */ "l1d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=16397 */ "l1d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=16483 */ "l1d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=16574 */ "l1d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=16670 */ "l1d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=16760 */ "l1d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=16853 */ "l1d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=16950 */ "l1d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=17045 */ "l1d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=17130 */ "l1d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=17220 */ "l1d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=17315 */ "l1d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=17404 */ "l1d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=17496 */ "l1d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=17592 */ "l1d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=17686 */ "l1d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=17777 */ "l1d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=17873 */ "l1d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=17974 */ "l1d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=18069 */ "l1d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=18167 */ "l1d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=18265 */ "l1d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=18361 */ "l1d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=18453 */ "l1d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=18550 */ "l1d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=18652 */ "l1d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=18748 */ "l1d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=18847 */ "l1d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=18946 */ "l1d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=19043 */ "l1d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=19134 */ "l1d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=19230 */ "l1d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=19331 */ "l1d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=19426 */ "l1d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=19524 */ "l1d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=19622 */ "l1d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=19718 */ "l1d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=19815 */ "l1d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=19917 */ "l1d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=20024 */ "l1d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=20125 */ "l1d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=20229 */ "l1d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=20333 */ "l1d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=20435 */ "l1d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=20534 */ "l1d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=20638 */ "l1d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=20747 */ "l1d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=20850 */ "l1d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=20956 */ "l1d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=21062 */ "l1d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=21166 */ "l1d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=21271 */ "l1d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=21381 */ "l1d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=21496 */ "l1d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=21605 */ "l1d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=21717 */ "l1d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=21829 */ "l1d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=21939 */ "l1d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=22044 */ "l1d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=22154 */ "l1d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=22269 */ "l1d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=22378 */ "l1d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=22490 */ "l1d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=22602 */ "l1d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=22712 */ "l1d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=22797 */ "l1d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=22887 */ "l1d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=22971 */ "l1d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=23058 */ "l1d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=23149 */ "l1d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=23238 */ "l1-data\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=23322 */ "l1-data-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=23411 */ "l1-data-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=23505 */ "l1-data-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=23604 */ "l1-data-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=23697 */ "l1-data-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=23793 */ "l1-data-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=23893 */ "l1-data-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=23991 */ "l1-data-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=24081 */ "l1-data-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=24176 */ "l1-data-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=24276 */ "l1-data-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=24370 */ "l1-data-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=24467 */ "l1-data-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=24568 */ "l1-data-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=24667 */ "l1-data-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=24756 */ "l1-data-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=24850 */ "l1-data-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=24949 */ "l1-data-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=25042 */ "l1-data-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=25138 */ "l1-data-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=25238 */ "l1-data-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=25336 */ "l1-data-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=25431 */ "l1-data-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=25531 */ "l1-data-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=25636 */ "l1-data-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=25735 */ "l1-data-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=25837 */ "l1-data-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=25939 */ "l1-data-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=26039 */ "l1-data-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=26135 */ "l1-data-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=26236 */ "l1-data-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=26342 */ "l1-data-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=26442 */ "l1-data-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=26545 */ "l1-data-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=26648 */ "l1-data-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=26749 */ "l1-data-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=26844 */ "l1-data-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=26944 */ "l1-data-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=27049 */ "l1-data-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=27148 */ "l1-data-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" -/* offset=27250 */ "l1-data-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=27352 */ "l1-data-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" -/* offset=27452 */ "l1-data-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=27553 */ "l1-data-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=27659 */ "l1-data-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=27770 */ "l1-data-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=27875 */ "l1-data-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=27983 */ "l1-data-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=28091 */ "l1-data-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=28197 */ "l1-data-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=28300 */ "l1-data-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=28408 */ "l1-data-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=28521 */ "l1-data-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=28628 */ "l1-data-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=28738 */ "l1-data-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=28848 */ "l1-data-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=28956 */ "l1-data-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=29065 */ "l1-data-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=29179 */ "l1-data-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=29298 */ "l1-data-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=29411 */ "l1-data-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=29527 */ "l1-data-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=29643 */ "l1-data-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=29757 */ "l1-data-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=29866 */ "l1-data-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=29980 */ "l1-data-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=30099 */ "l1-data-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=30212 */ "l1-data-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" -/* offset=30328 */ "l1-data-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=30444 */ "l1-data-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" -/* offset=30558 */ "l1-data-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=30647 */ "l1-data-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=30741 */ "l1-data-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=30829 */ "l1-data-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" -/* offset=30920 */ "l1-data-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=31015 */ "l1-data-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" -/* offset=31108 */ "l1-icache\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=31201 */ "l1-icache-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=31299 */ "l1-icache-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=31402 */ "l1-icache-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=31510 */ "l1-icache-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=31612 */ "l1-icache-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=31717 */ "l1-icache-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00000\000\000\000\000\000" -/* offset=31826 */ "l1-icache-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=31933 */ "l1-icache-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00000\000\000\000\000\000" -/* offset=32032 */ "l1-icache-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=32136 */ "l1-icache-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=32245 */ "l1-icache-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=32348 */ "l1-icache-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=32454 */ "l1-icache-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=32564 */ "l1-icache-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=32672 */ "l1-icache-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=32770 */ "l1-icache-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=32873 */ "l1-icache-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=32981 */ "l1-icache-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=33083 */ "l1-icache-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=33188 */ "l1-icache-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=33297 */ "l1-icache-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=33404 */ "l1-icache-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=33514 */ "l1-icache-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=33629 */ "l1-icache-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=33749 */ "l1-icache-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=33863 */ "l1-icache-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=33980 */ "l1-icache-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00000\000\000\000\000\000" -/* offset=34097 */ "l1-icache-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=34212 */ "l1-icache-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00000\000\000\000\000\000" -/* offset=34324 */ "l1-icache-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=34441 */ "l1-icache-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=34563 */ "l1-icache-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=34679 */ "l1-icache-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=34798 */ "l1-icache-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=34917 */ "l1-icache-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=35034 */ "l1-icache-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=35152 */ "l1-icache-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=35275 */ "l1-icache-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=35403 */ "l1-icache-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=35525 */ "l1-icache-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=35650 */ "l1-icache-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=35775 */ "l1-icache-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=35898 */ "l1-icache-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=36016 */ "l1-icache-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=36139 */ "l1-icache-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=36267 */ "l1-icache-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=36389 */ "l1-icache-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=36514 */ "l1-icache-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=36639 */ "l1-icache-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=36762 */ "l1-icache-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=36860 */ "l1-icache-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=36963 */ "l1-icache-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=37060 */ "l1-icache-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=37160 */ "l1-icache-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=37264 */ "l1-icache-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=37366 */ "l1-i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=37454 */ "l1-i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=37547 */ "l1-i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=37645 */ "l1-i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=37748 */ "l1-i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=37845 */ "l1-i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=37945 */ "l1-i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=38049 */ "l1-i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=38151 */ "l1-i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=38245 */ "l1-i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=38344 */ "l1-i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=38448 */ "l1-i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=38546 */ "l1-i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=38647 */ "l1-i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=38752 */ "l1-i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=38855 */ "l1-i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=38948 */ "l1-i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=39046 */ "l1-i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=39149 */ "l1-i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=39246 */ "l1-i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=39346 */ "l1-i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=39450 */ "l1-i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=39552 */ "l1-i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=39657 */ "l1-i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=39767 */ "l1-i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=39882 */ "l1-i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=39991 */ "l1-i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=40103 */ "l1-i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=40215 */ "l1-i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=40325 */ "l1-i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=40432 */ "l1-i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=40544 */ "l1-i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=40661 */ "l1-i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=40772 */ "l1-i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=40886 */ "l1-i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=41000 */ "l1-i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=41112 */ "l1-i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=41225 */ "l1-i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=41343 */ "l1-i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=41466 */ "l1-i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=41583 */ "l1-i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=41703 */ "l1-i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=41823 */ "l1-i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=41941 */ "l1-i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=42054 */ "l1-i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=42172 */ "l1-i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=42295 */ "l1-i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=42412 */ "l1-i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=42532 */ "l1-i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=42652 */ "l1-i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=42770 */ "l1-i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=42863 */ "l1-i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=42961 */ "l1-i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=43053 */ "l1-i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=43148 */ "l1-i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=43247 */ "l1-i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=43344 */ "l1i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=43431 */ "l1i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=43523 */ "l1i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=43620 */ "l1i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=43722 */ "l1i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=43818 */ "l1i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=43917 */ "l1i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=44020 */ "l1i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=44121 */ "l1i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=44214 */ "l1i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=44312 */ "l1i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=44415 */ "l1i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=44512 */ "l1i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=44612 */ "l1i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=44716 */ "l1i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=44818 */ "l1i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=44910 */ "l1i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=45007 */ "l1i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=45109 */ "l1i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=45205 */ "l1i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=45304 */ "l1i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=45407 */ "l1i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=45508 */ "l1i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=45612 */ "l1i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=45721 */ "l1i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=45835 */ "l1i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=45943 */ "l1i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=46054 */ "l1i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=46165 */ "l1i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=46274 */ "l1i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=46380 */ "l1i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=46491 */ "l1i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=46607 */ "l1i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=46717 */ "l1i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=46830 */ "l1i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=46943 */ "l1i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=47054 */ "l1i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=47166 */ "l1i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=47283 */ "l1i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=47405 */ "l1i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=47521 */ "l1i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=47640 */ "l1i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=47759 */ "l1i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=47876 */ "l1i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=47988 */ "l1i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=48105 */ "l1i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=48227 */ "l1i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=48343 */ "l1i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=48462 */ "l1i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=48581 */ "l1i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=48698 */ "l1i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=48790 */ "l1i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=48887 */ "l1i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=48978 */ "l1i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=49072 */ "l1i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=49170 */ "l1i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=49266 */ "l1-instruction\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=49364 */ "l1-instruction-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=49467 */ "l1-instruction-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=49575 */ "l1-instruction-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=49688 */ "l1-instruction-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=49795 */ "l1-instruction-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=49905 */ "l1-instruction-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=50019 */ "l1-instruction-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=50131 */ "l1-instruction-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=50235 */ "l1-instruction-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=50344 */ "l1-instruction-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=50458 */ "l1-instruction-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=50566 */ "l1-instruction-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=50677 */ "l1-instruction-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=50792 */ "l1-instruction-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=50905 */ "l1-instruction-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=51008 */ "l1-instruction-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=51116 */ "l1-instruction-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=51229 */ "l1-instruction-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=51336 */ "l1-instruction-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=51446 */ "l1-instruction-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=51560 */ "l1-instruction-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=51672 */ "l1-instruction-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=51787 */ "l1-instruction-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=51907 */ "l1-instruction-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=52032 */ "l1-instruction-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=52151 */ "l1-instruction-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=52273 */ "l1-instruction-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=52395 */ "l1-instruction-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=52515 */ "l1-instruction-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=52632 */ "l1-instruction-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=52754 */ "l1-instruction-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=52881 */ "l1-instruction-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=53002 */ "l1-instruction-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=53126 */ "l1-instruction-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=53250 */ "l1-instruction-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=53372 */ "l1-instruction-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=53495 */ "l1-instruction-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=53623 */ "l1-instruction-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=53756 */ "l1-instruction-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=53883 */ "l1-instruction-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=54013 */ "l1-instruction-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=54143 */ "l1-instruction-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=54271 */ "l1-instruction-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=54394 */ "l1-instruction-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=54522 */ "l1-instruction-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=54655 */ "l1-instruction-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=54782 */ "l1-instruction-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" -/* offset=54912 */ "l1-instruction-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=55042 */ "l1-instruction-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" -/* offset=55170 */ "l1-instruction-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=55273 */ "l1-instruction-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=55381 */ "l1-instruction-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=55483 */ "l1-instruction-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" -/* offset=55588 */ "l1-instruction-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=55697 */ "l1-instruction-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" -/* offset=55804 */ "llc\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=55882 */ "llc-load\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=55965 */ "llc-load-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=56053 */ "llc-load-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=56146 */ "llc-load-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=56233 */ "llc-load-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=56323 */ "llc-load-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00000\000\000\000\000\000" -/* offset=56417 */ "llc-load-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=56509 */ "llc-loads\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00000\000\000\000\000\000" -/* offset=56593 */ "llc-loads-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=56682 */ "llc-loads-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=56776 */ "llc-loads-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=56864 */ "llc-loads-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=56955 */ "llc-loads-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=57050 */ "llc-loads-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=57143 */ "llc-read\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=57226 */ "llc-read-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=57314 */ "llc-read-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=57407 */ "llc-read-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=57494 */ "llc-read-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=57584 */ "llc-read-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=57678 */ "llc-read-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=57770 */ "llc-store\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=57859 */ "llc-store-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=57953 */ "llc-store-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=58052 */ "llc-store-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=58145 */ "llc-store-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=58241 */ "llc-store-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00000\000\000\000\000\000" -/* offset=58337 */ "llc-store-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=58431 */ "llc-stores\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00000\000\000\000\000\000" -/* offset=58521 */ "llc-stores-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=58616 */ "llc-stores-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=58716 */ "llc-stores-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=58810 */ "llc-stores-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=58907 */ "llc-stores-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=59004 */ "llc-stores-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=59099 */ "llc-write\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=59188 */ "llc-write-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=59282 */ "llc-write-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=59381 */ "llc-write-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=59474 */ "llc-write-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=59570 */ "llc-write-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=59666 */ "llc-write-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=59760 */ "llc-prefetch\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=59855 */ "llc-prefetch-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=59955 */ "llc-prefetch-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=60060 */ "llc-prefetch-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=60159 */ "llc-prefetch-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=60261 */ "llc-prefetch-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00000\000\000\000\000\000" -/* offset=60363 */ "llc-prefetch-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=60463 */ "llc-prefetches\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00000\000\000\000\000\000" -/* offset=60560 */ "llc-prefetches-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=60662 */ "llc-prefetches-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=60769 */ "llc-prefetches-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=60870 */ "llc-prefetches-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=60974 */ "llc-prefetches-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=61078 */ "llc-prefetches-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=61180 */ "llc-speculative-read\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=61283 */ "llc-speculative-read-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=61391 */ "llc-speculative-read-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=61504 */ "llc-speculative-read-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=61611 */ "llc-speculative-read-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=61721 */ "llc-speculative-read-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=61831 */ "llc-speculative-read-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=61939 */ "llc-speculative-load\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=62042 */ "llc-speculative-load-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=62150 */ "llc-speculative-load-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=62263 */ "llc-speculative-load-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=62370 */ "llc-speculative-load-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=62480 */ "llc-speculative-load-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=62590 */ "llc-speculative-load-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=62698 */ "llc-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=62781 */ "llc-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=62869 */ "llc-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=62951 */ "llc-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=63036 */ "llc-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=63125 */ "llc-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=63212 */ "l2\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=63309 */ "l2-load\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=63411 */ "l2-load-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=63518 */ "l2-load-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=63630 */ "l2-load-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=63736 */ "l2-load-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=63845 */ "l2-load-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=63958 */ "l2-load-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=64069 */ "l2-loads\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=64172 */ "l2-loads-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=64280 */ "l2-loads-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=64393 */ "l2-loads-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=64500 */ "l2-loads-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=64610 */ "l2-loads-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=64724 */ "l2-loads-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=64836 */ "l2-read\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=64938 */ "l2-read-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=65045 */ "l2-read-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=65157 */ "l2-read-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=65263 */ "l2-read-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=65372 */ "l2-read-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=65485 */ "l2-read-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=65596 */ "l2-store\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=65704 */ "l2-store-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=65817 */ "l2-store-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=65935 */ "l2-store-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=66047 */ "l2-store-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=66162 */ "l2-store-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=66277 */ "l2-store-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=66390 */ "l2-stores\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=66499 */ "l2-stores-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=66613 */ "l2-stores-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=66732 */ "l2-stores-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=66845 */ "l2-stores-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=66961 */ "l2-stores-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=67077 */ "l2-stores-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=67191 */ "l2-write\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=67299 */ "l2-write-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=67412 */ "l2-write-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=67530 */ "l2-write-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=67642 */ "l2-write-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" -/* offset=67757 */ "l2-write-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=67872 */ "l2-write-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" -/* offset=67985 */ "l2-prefetch\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=68099 */ "l2-prefetch-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=68218 */ "l2-prefetch-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=68342 */ "l2-prefetch-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=68460 */ "l2-prefetch-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=68581 */ "l2-prefetch-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=68702 */ "l2-prefetch-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=68821 */ "l2-prefetches\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=68937 */ "l2-prefetches-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=69058 */ "l2-prefetches-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=69184 */ "l2-prefetches-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=69304 */ "l2-prefetches-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=69427 */ "l2-prefetches-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=69550 */ "l2-prefetches-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=69671 */ "l2-speculative-read\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=69793 */ "l2-speculative-read-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=69920 */ "l2-speculative-read-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=70052 */ "l2-speculative-read-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=70178 */ "l2-speculative-read-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=70307 */ "l2-speculative-read-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=70436 */ "l2-speculative-read-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=70563 */ "l2-speculative-load\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=70685 */ "l2-speculative-load-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=70812 */ "l2-speculative-load-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=70944 */ "l2-speculative-load-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=71070 */ "l2-speculative-load-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" -/* offset=71199 */ "l2-speculative-load-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=71328 */ "l2-speculative-load-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" -/* offset=71455 */ "l2-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=71557 */ "l2-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=71664 */ "l2-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=71765 */ "l2-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" -/* offset=71869 */ "l2-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=71977 */ "l2-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" -/* offset=72083 */ "dtlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=72154 */ "dtlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=72230 */ "dtlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=72311 */ "dtlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=72397 */ "dtlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=72477 */ "dtlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=72560 */ "dtlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00000\000\000\000\000\000" -/* offset=72647 */ "dtlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=72732 */ "dtlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00000\000\000\000\000\000" -/* offset=72809 */ "dtlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=72891 */ "dtlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=72978 */ "dtlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=73059 */ "dtlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=73143 */ "dtlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=73231 */ "dtlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=73317 */ "dtlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=73393 */ "dtlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=73474 */ "dtlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=73560 */ "dtlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=73640 */ "dtlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=73723 */ "dtlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=73810 */ "dtlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=73895 */ "dtlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=73977 */ "dtlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=74064 */ "dtlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=74156 */ "dtlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=74242 */ "dtlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=74331 */ "dtlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00000\000\000\000\000\000" -/* offset=74420 */ "dtlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=74507 */ "dtlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00000\000\000\000\000\000" -/* offset=74590 */ "dtlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=74678 */ "dtlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=74771 */ "dtlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=74858 */ "dtlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=74948 */ "dtlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=75038 */ "dtlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=75126 */ "dtlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=75208 */ "dtlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=75295 */ "dtlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=75387 */ "dtlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=75473 */ "dtlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=75562 */ "dtlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=75651 */ "dtlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=75738 */ "dtlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=75826 */ "dtlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=75919 */ "dtlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=76017 */ "dtlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=76109 */ "dtlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=76204 */ "dtlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00000\000\000\000\000\000" -/* offset=76299 */ "dtlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=76392 */ "dtlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00000\000\000\000\000\000" -/* offset=76482 */ "dtlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=76577 */ "dtlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=76677 */ "dtlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=76771 */ "dtlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=76868 */ "dtlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=76965 */ "dtlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=77060 */ "dtlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=77156 */ "dtlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=77257 */ "dtlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=77363 */ "dtlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=77463 */ "dtlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=77566 */ "dtlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=77669 */ "dtlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=77770 */ "dtlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=77866 */ "dtlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=77967 */ "dtlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=78073 */ "dtlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=78173 */ "dtlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=78276 */ "dtlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=78379 */ "dtlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=78480 */ "dtlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=78556 */ "dtlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=78637 */ "dtlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=78712 */ "dtlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=78790 */ "dtlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=78872 */ "dtlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=78952 */ "d-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79024 */ "d-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79101 */ "d-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79183 */ "d-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79270 */ "d-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79351 */ "d-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79435 */ "d-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=79523 */ "d-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=79609 */ "d-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79687 */ "d-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79770 */ "d-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79858 */ "d-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=79940 */ "d-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=80025 */ "d-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=80114 */ "d-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=80201 */ "d-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=80278 */ "d-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=80360 */ "d-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=80447 */ "d-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=80528 */ "d-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=80612 */ "d-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=80700 */ "d-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=80786 */ "d-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=80869 */ "d-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=80957 */ "d-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=81050 */ "d-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=81137 */ "d-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=81227 */ "d-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=81317 */ "d-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=81405 */ "d-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=81489 */ "d-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=81578 */ "d-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=81672 */ "d-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=81760 */ "d-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=81851 */ "d-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=81942 */ "d-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=82031 */ "d-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=82114 */ "d-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=82202 */ "d-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=82295 */ "d-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=82382 */ "d-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=82472 */ "d-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=82562 */ "d-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=82650 */ "d-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=82739 */ "d-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=82833 */ "d-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=82932 */ "d-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=83025 */ "d-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=83121 */ "d-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=83217 */ "d-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=83311 */ "d-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=83402 */ "d-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=83498 */ "d-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=83599 */ "d-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=83694 */ "d-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=83792 */ "d-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=83890 */ "d-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=83986 */ "d-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=84083 */ "d-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=84185 */ "d-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=84292 */ "d-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=84393 */ "d-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=84497 */ "d-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=84601 */ "d-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=84703 */ "d-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=84800 */ "d-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=84902 */ "d-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=85009 */ "d-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=85110 */ "d-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=85214 */ "d-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=85318 */ "d-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=85420 */ "d-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=85497 */ "d-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=85579 */ "d-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=85655 */ "d-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=85734 */ "d-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=85817 */ "d-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=85898 */ "data-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=85973 */ "data-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=86053 */ "data-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=86138 */ "data-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=86228 */ "data-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=86312 */ "data-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=86399 */ "data-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=86490 */ "data-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=86579 */ "data-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=86660 */ "data-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=86746 */ "data-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=86837 */ "data-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=86922 */ "data-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=87010 */ "data-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=87102 */ "data-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=87192 */ "data-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=87272 */ "data-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=87357 */ "data-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=87447 */ "data-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=87531 */ "data-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=87618 */ "data-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=87709 */ "data-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=87798 */ "data-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=87884 */ "data-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=87975 */ "data-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=88071 */ "data-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=88161 */ "data-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=88254 */ "data-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=88347 */ "data-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=88438 */ "data-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=88525 */ "data-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=88617 */ "data-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=88714 */ "data-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=88805 */ "data-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=88899 */ "data-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=88993 */ "data-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=89085 */ "data-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=89171 */ "data-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=89262 */ "data-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=89358 */ "data-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=89448 */ "data-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" -/* offset=89541 */ "data-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=89634 */ "data-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" -/* offset=89725 */ "data-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=89817 */ "data-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=89914 */ "data-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=90016 */ "data-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=90112 */ "data-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=90211 */ "data-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=90310 */ "data-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=90407 */ "data-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=90501 */ "data-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=90600 */ "data-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=90704 */ "data-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=90802 */ "data-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=90903 */ "data-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=91004 */ "data-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=91103 */ "data-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=91203 */ "data-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=91308 */ "data-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=91418 */ "data-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=91522 */ "data-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=91629 */ "data-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=91736 */ "data-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=91841 */ "data-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=91941 */ "data-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=92046 */ "data-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=92156 */ "data-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=92260 */ "data-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" -/* offset=92367 */ "data-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=92474 */ "data-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" -/* offset=92579 */ "data-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=92659 */ "data-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=92744 */ "data-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=92823 */ "data-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" -/* offset=92905 */ "data-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=92991 */ "data-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" -/* offset=93075 */ "itlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=93153 */ "itlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=93236 */ "itlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=93324 */ "itlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=93417 */ "itlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=93504 */ "itlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=93594 */ "itlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00000\000\000\000\000\000" -/* offset=93688 */ "itlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=93780 */ "itlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00000\000\000\000\000\000" -/* offset=93864 */ "itlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=93953 */ "itlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=94047 */ "itlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=94135 */ "itlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=94226 */ "itlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=94321 */ "itlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=94414 */ "itlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=94497 */ "itlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=94585 */ "itlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=94678 */ "itlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=94765 */ "itlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=94855 */ "itlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=94949 */ "itlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=95041 */ "itlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=95124 */ "itlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=95212 */ "itlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=95294 */ "itlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=95379 */ "itlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=95468 */ "itlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=95555 */ "i-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=95634 */ "i-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=95718 */ "i-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=95807 */ "i-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=95901 */ "i-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=95989 */ "i-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=96080 */ "i-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=96175 */ "i-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=96268 */ "i-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=96353 */ "i-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=96443 */ "i-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=96538 */ "i-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=96627 */ "i-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=96719 */ "i-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=96815 */ "i-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=96909 */ "i-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=96993 */ "i-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=97082 */ "i-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=97176 */ "i-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=97264 */ "i-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=97355 */ "i-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=97450 */ "i-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=97543 */ "i-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=97627 */ "i-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=97716 */ "i-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=97799 */ "i-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=97885 */ "i-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=97975 */ "i-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=98063 */ "instruction-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=98152 */ "instruction-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=98246 */ "instruction-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=98345 */ "instruction-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=98449 */ "instruction-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=98547 */ "instruction-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=98648 */ "instruction-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=98753 */ "instruction-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=98856 */ "instruction-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=98951 */ "instruction-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=99051 */ "instruction-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=99156 */ "instruction-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=99255 */ "instruction-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=99357 */ "instruction-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=99463 */ "instruction-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=99567 */ "instruction-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=99661 */ "instruction-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=99760 */ "instruction-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=99864 */ "instruction-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=99962 */ "instruction-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=100063 */ "instruction-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=100168 */ "instruction-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=100271 */ "instruction-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=100365 */ "instruction-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=100464 */ "instruction-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=100557 */ "instruction-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" -/* offset=100653 */ "instruction-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=100753 */ "instruction-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" -/* offset=100851 */ "branch\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=100938 */ "branch-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=101030 */ "branch-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=101127 */ "branch-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=101229 */ "branch-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=101325 */ "branch-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=101424 */ "branch-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00000\000\000\000\000\000" -/* offset=101527 */ "branch-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=101628 */ "branch-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00000\000\000\000\000\000" -/* offset=101721 */ "branch-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=101819 */ "branch-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=101922 */ "branch-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=102019 */ "branch-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=102119 */ "branch-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=102223 */ "branch-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=102325 */ "branch-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=102417 */ "branch-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=102514 */ "branch-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=102616 */ "branch-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=102712 */ "branch-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=102811 */ "branch-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=102914 */ "branch-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=103015 */ "branch-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=103107 */ "branch-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=103204 */ "branch-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=103295 */ "branch-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=103389 */ "branch-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=103485 */ "branches-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=103579 */ "branches-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=103678 */ "branches-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=103782 */ "branches-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=103880 */ "branches-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=103981 */ "branches-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=104086 */ "branches-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=104189 */ "branches-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=104284 */ "branches-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=104384 */ "branches-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=104489 */ "branches-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=104588 */ "branches-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=104690 */ "branches-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=104796 */ "branches-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=104900 */ "branches-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=104994 */ "branches-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=105093 */ "branches-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=105197 */ "branches-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=105295 */ "branches-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=105396 */ "branches-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=105501 */ "branches-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=105604 */ "branches-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=105698 */ "branches-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=105797 */ "branches-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=105890 */ "branches-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=105986 */ "branches-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=106086 */ "branches-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=106184 */ "bpu\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=106268 */ "bpu-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=106357 */ "bpu-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=106451 */ "bpu-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=106550 */ "bpu-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=106643 */ "bpu-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=106739 */ "bpu-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=106839 */ "bpu-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=106937 */ "bpu-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=107027 */ "bpu-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=107122 */ "bpu-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=107222 */ "bpu-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=107316 */ "bpu-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=107413 */ "bpu-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=107514 */ "bpu-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=107613 */ "bpu-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=107702 */ "bpu-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=107796 */ "bpu-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=107895 */ "bpu-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=107988 */ "bpu-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=108084 */ "bpu-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=108184 */ "bpu-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=108282 */ "bpu-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=108371 */ "bpu-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=108465 */ "bpu-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=108553 */ "bpu-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=108644 */ "bpu-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=108739 */ "bpu-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=108832 */ "btb\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=108916 */ "btb-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=109005 */ "btb-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=109099 */ "btb-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=109198 */ "btb-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=109291 */ "btb-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=109387 */ "btb-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=109487 */ "btb-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=109585 */ "btb-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=109675 */ "btb-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=109770 */ "btb-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=109870 */ "btb-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=109964 */ "btb-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=110061 */ "btb-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=110162 */ "btb-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=110261 */ "btb-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=110350 */ "btb-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=110444 */ "btb-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=110543 */ "btb-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=110636 */ "btb-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=110732 */ "btb-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=110832 */ "btb-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=110930 */ "btb-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=111019 */ "btb-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=111113 */ "btb-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=111201 */ "btb-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=111292 */ "btb-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=111387 */ "btb-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=111480 */ "bpc\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=111564 */ "bpc-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=111653 */ "bpc-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=111747 */ "bpc-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=111846 */ "bpc-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=111939 */ "bpc-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=112035 */ "bpc-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=112135 */ "bpc-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=112233 */ "bpc-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=112323 */ "bpc-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=112418 */ "bpc-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=112518 */ "bpc-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=112612 */ "bpc-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=112709 */ "bpc-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=112810 */ "bpc-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=112909 */ "bpc-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=112998 */ "bpc-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=113092 */ "bpc-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=113191 */ "bpc-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=113284 */ "bpc-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=113380 */ "bpc-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=113480 */ "bpc-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=113578 */ "bpc-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=113667 */ "bpc-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=113761 */ "bpc-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=113849 */ "bpc-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" -/* offset=113940 */ "bpc-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=114035 */ "bpc-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" -/* offset=114128 */ "node\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=114203 */ "node-load\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=114283 */ "node-load-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=114368 */ "node-load-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=114458 */ "node-load-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=114542 */ "node-load-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=114629 */ "node-load-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00000\000\000\000\000\000" -/* offset=114720 */ "node-load-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" -/* offset=114809 */ "node-loads\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00000\000\000\000\000\000" -/* offset=114890 */ "node-loads-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=114976 */ "node-loads-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=115067 */ "node-loads-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=115152 */ "node-loads-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=115240 */ "node-loads-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" -/* offset=115332 */ "node-loads-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" -/* offset=115422 */ "node-read\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=115502 */ "node-read-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=115587 */ "node-read-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=115677 */ "node-read-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=115761 */ "node-read-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=115848 */ "node-read-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" -/* offset=115939 */ "node-read-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" -/* offset=116028 */ "node-store\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=116114 */ "node-store-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=116205 */ "node-store-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=116301 */ "node-store-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=116391 */ "node-store-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=116484 */ "node-store-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00000\000\000\000\000\000" -/* offset=116577 */ "node-store-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" -/* offset=116668 */ "node-stores\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00000\000\000\000\000\000" -/* offset=116755 */ "node-stores-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=116847 */ "node-stores-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=116944 */ "node-stores-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=117035 */ "node-stores-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=117129 */ "node-stores-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" -/* offset=117223 */ "node-stores-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" -/* offset=117315 */ "node-write\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=117401 */ "node-write-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=117492 */ "node-write-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=117588 */ "node-write-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=117678 */ "node-write-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" -/* offset=117771 */ "node-write-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" -/* offset=117864 */ "node-write-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" -/* offset=117955 */ "node-prefetch\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=118047 */ "node-prefetch-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=118144 */ "node-prefetch-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=118246 */ "node-prefetch-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=118342 */ "node-prefetch-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=118441 */ "node-prefetch-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00000\000\000\000\000\000" -/* offset=118540 */ "node-prefetch-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" -/* offset=118637 */ "node-prefetches\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00000\000\000\000\000\000" -/* offset=118731 */ "node-prefetches-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=118830 */ "node-prefetches-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=118934 */ "node-prefetches-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=119032 */ "node-prefetches-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=119133 */ "node-prefetches-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" -/* offset=119234 */ "node-prefetches-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" -/* offset=119333 */ "node-speculative-read\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=119433 */ "node-speculative-read-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=119538 */ "node-speculative-read-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=119648 */ "node-speculative-read-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=119752 */ "node-speculative-read-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=119859 */ "node-speculative-read-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" -/* offset=119966 */ "node-speculative-read-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" -/* offset=120071 */ "node-speculative-load\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=120171 */ "node-speculative-load-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=120276 */ "node-speculative-load-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=120386 */ "node-speculative-load-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=120490 */ "node-speculative-load-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" -/* offset=120597 */ "node-speculative-load-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" -/* offset=120704 */ "node-speculative-load-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" -/* offset=120809 */ "node-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=120889 */ "node-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=120974 */ "node-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=121053 */ "node-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" -/* offset=121135 */ "node-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" -/* offset=121221 */ "node-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" -/* offset=121305 */ "cpu-cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000" -/* offset=121467 */ "cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cpu-cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000" -/* offset=121629 */ "instructions\000legacy hardware\000Retired instructions. Be careful, these can be affected by various issues, most notably hardware interrupt counts\000legacy-hardware-config=1\000\00000\000\000\000\000\000" -/* offset=121805 */ "cache-references\000legacy hardware\000Cache accesses. Usually this indicates Last Level Cache accesses but this may vary depending on your CPU. This may include prefetches and coherency messages; again this depends on the design of your CPU\000legacy-hardware-config=2\000\00000\000\000\000\000\000" -/* offset=122075 */ "cache-misses\000legacy hardware\000Cache misses. Usually this indicates Last Level Cache misses; this is intended to be used in conjunction with the PERF_COUNT_HW_CACHE_REFERENCES event to calculate cache miss rates\000legacy-hardware-config=3\000\00000\000\000\000\000\000" -/* offset=122318 */ "branches\000legacy hardware\000Retired branch instructions [This event is an alias of branch-instructions]\000legacy-hardware-config=4\000\00000\000\000\000\000\000" -/* offset=122452 */ "branch-instructions\000legacy hardware\000Retired branch instructions [This event is an alias of branches]\000legacy-hardware-config=4\000\00000\000\000\000\000\000" -/* offset=122586 */ "branch-misses\000legacy hardware\000Mispredicted branch instructions\000legacy-hardware-config=5\000\00000\000\000\000\000\000" -/* offset=122682 */ "bus-cycles\000legacy hardware\000Bus cycles, which can be different from total cycles\000legacy-hardware-config=6\000\00000\000\000\000\000\000" -/* offset=122795 */ "stalled-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of idle-cycles-frontend]\000legacy-hardware-config=7\000\00000\000\000\000\000\000" -/* offset=122945 */ "idle-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of stalled-cycles-fronted]\000legacy-hardware-config=7\000\00000\000\000\000\000\000" -/* offset=123094 */ "stalled-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of idle-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000" -/* offset=123247 */ "idle-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of stalled-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000" -/* offset=123400 */ "ref-cycles\000legacy hardware\000Total cycles; not affected by CPU frequency scaling\000legacy-hardware-config=9\000\00000\000\000\000\000\000" -/* offset=123512 */ "software\000" -/* offset=123521 */ "cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\000001e-6msec\000\000\000\000\000" -/* offset=123607 */ "task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\000001e-6msec\000\000\000\000\000" -/* offset=123695 */ "faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000" -/* offset=123790 */ "page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000" -/* offset=123885 */ "context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000" -/* offset=123986 */ "cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000" -/* offset=124087 */ "cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000" -/* offset=124219 */ "migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000" -/* offset=124351 */ "minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000" -/* offset=124460 */ "major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000" -/* offset=124563 */ "alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000" -/* offset=124655 */ "emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000" -/* offset=124782 */ "dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000" -/* offset=124862 */ "bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000" -/* offset=124964 */ "cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000" -/* offset=125067 */ "tool\000" -/* offset=125072 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000" -/* offset=125148 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000" -/* offset=125218 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000" -/* offset=125286 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000" -/* offset=125362 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000" -/* offset=125507 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000" -/* offset=125610 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000" -/* offset=125727 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000" -/* offset=125803 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000" -/* offset=125889 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000" -/* offset=125999 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000" -/* offset=126106 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000" -/* offset=126205 */ "core_wide\000tool\0001 if not SMT, if SMT are events being gathered on all SMT threads 1 otherwise 0\000config=0xd\000\00000\000\000\000\000\000" -/* offset=126319 */ "target_cpu\000tool\0001 if CPUs being analyzed, 0 if threads/processes\000config=0xe\000\00000\000\000\000\000\000" -/* offset=126403 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000" -/* offset=126465 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000" -/* offset=126527 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000" -/* offset=126625 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000" -/* offset=126727 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000" -/* offset=126860 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000" -/* offset=126978 */ "hisi_sccl,ddrc\000" -/* offset=126993 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000" -/* offset=127063 */ "uncore_cbox\000" -/* offset=127075 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000" -/* offset=127229 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000" -/* offset=127283 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000" -/* offset=127341 */ "hisi_sccl,l3c\000" -/* offset=127355 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000" -/* offset=127423 */ "uncore_imc_free_running\000" -/* offset=127447 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000" -/* offset=127527 */ "uncore_imc\000" -/* offset=127538 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000" -/* offset=127603 */ "uncore_sys_ddr_pmu\000" -/* offset=127622 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000" -/* offset=127698 */ "uncore_sys_ccn_pmu\000" -/* offset=127717 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" -/* offset=127794 */ "uncore_sys_cmn_pmu\000" -/* offset=127813 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" -/* offset=127956 */ "CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011" -/* offset=128142 */ "cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011" -/* offset=128375 */ "migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011" -/* offset=128635 */ "page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011" -/* offset=128866 */ "insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001" -/* offset=128979 */ "stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions if has_event(stalled\\-cycles\\-frontend) & has_event(stalled\\-cycles\\-backend) else (stalled\\-cycles\\-frontend / instructions if has_event(stalled\\-cycles\\-frontend) else (stalled\\-cycles\\-backend / instructions if has_event(stalled\\-cycles\\-backend) else 0)))\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001" -/* offset=129404 */ "frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles if has_event(stalled\\-cycles\\-frontend) else 0)\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001" -/* offset=129583 */ "backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if has_event(stalled\\-cycles\\-backend) else 0)\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001" -/* offset=129757 */ "cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011" -/* offset=129933 */ "branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011" -/* offset=130113 */ "branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001" -/* offset=130217 */ "l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001" -/* offset=130333 */ "llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001" -/* offset=130434 */ "l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001" -/* offset=130549 */ "dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001" -/* offset=130655 */ "itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001" -/* offset=130761 */ "l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001" -/* offset=130909 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000" -/* offset=130932 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000" -/* offset=130996 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000" -/* offset=131163 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" -/* offset=131228 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" -/* offset=131296 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000" -/* offset=131368 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000" -/* offset=131463 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000" -/* offset=131598 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000" -/* offset=131663 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000" -/* offset=131732 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000" -/* offset=131803 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\000000" -/* offset=131826 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\000000" -/* offset=131849 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\000000" -/* offset=131870 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000" +/* offset=0 */ +"default_core\000" +/* offset=13 */ +"l1-dcache\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=99 */ +"l1-dcache-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=190 */ +"l1-dcache-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=286 */ +"l1-dcache-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=387 */ +"l1-dcache-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=482 */ +"l1-dcache-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=580 */ +"l1-dcache-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00000\000\000\000\000\000" +/* offset=682 */ +"l1-dcache-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=782 */ +"l1-dcache-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00000\000\000\000\000\000" +/* offset=874 */ +"l1-dcache-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=971 */ +"l1-dcache-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1073 */ +"l1-dcache-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1169 */ +"l1-dcache-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1268 */ +"l1-dcache-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=1371 */ +"l1-dcache-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=1472 */ +"l1-dcache-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1563 */ +"l1-dcache-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1659 */ +"l1-dcache-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1760 */ +"l1-dcache-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1855 */ +"l1-dcache-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=1953 */ +"l1-dcache-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=2055 */ +"l1-dcache-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=2155 */ +"l1-dcache-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2252 */ +"l1-dcache-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2354 */ +"l1-dcache-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2461 */ +"l1-dcache-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2562 */ +"l1-dcache-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=2666 */ +"l1-dcache-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00000\000\000\000\000\000" +/* offset=2770 */ +"l1-dcache-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=2872 */ +"l1-dcache-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00000\000\000\000\000\000" +/* offset=2970 */ +"l1-dcache-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3073 */ +"l1-dcache-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3181 */ +"l1-dcache-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3283 */ +"l1-dcache-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3388 */ +"l1-dcache-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=3493 */ +"l1-dcache-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=3596 */ +"l1-dcache-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3693 */ +"l1-dcache-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3795 */ +"l1-dcache-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=3902 */ +"l1-dcache-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=4003 */ +"l1-dcache-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=4107 */ +"l1-dcache-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=4211 */ +"l1-dcache-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=4313 */ +"l1-dcache-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4416 */ +"l1-dcache-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4524 */ +"l1-dcache-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4637 */ +"l1-dcache-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4744 */ +"l1-dcache-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=4854 */ +"l1-dcache-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00000\000\000\000\000\000" +/* offset=4964 */ +"l1-dcache-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=5072 */ +"l1-dcache-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00000\000\000\000\000\000" +/* offset=5177 */ +"l1-dcache-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5287 */ +"l1-dcache-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5402 */ +"l1-dcache-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5511 */ +"l1-dcache-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5623 */ +"l1-dcache-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=5735 */ +"l1-dcache-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=5845 */ +"l1-dcache-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=5956 */ +"l1-dcache-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6072 */ +"l1-dcache-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6193 */ +"l1-dcache-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6308 */ +"l1-dcache-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6426 */ +"l1-dcache-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=6544 */ +"l1-dcache-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=6660 */ +"l1-dcache-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6771 */ +"l1-dcache-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=6887 */ +"l1-dcache-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=7008 */ +"l1-dcache-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=7123 */ +"l1-dcache-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=7241 */ +"l1-dcache-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=7359 */ +"l1-dcache-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=7475 */ +"l1-dcache-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=7566 */ +"l1-dcache-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=7662 */ +"l1-dcache-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=7752 */ +"l1-dcache-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=7845 */ +"l1-dcache-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=7942 */ +"l1-dcache-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=8037 */ +"l1-d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8118 */ +"l1-d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8204 */ +"l1-d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8295 */ +"l1-d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8391 */ +"l1-d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8481 */ +"l1-d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8574 */ +"l1-d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=8671 */ +"l1-d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=8766 */ +"l1-d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8853 */ +"l1-d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=8945 */ +"l1-d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9042 */ +"l1-d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9133 */ +"l1-d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9227 */ +"l1-d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=9325 */ +"l1-d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=9421 */ +"l1-d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9507 */ +"l1-d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9598 */ +"l1-d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9694 */ +"l1-d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9784 */ +"l1-d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=9877 */ +"l1-d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=9974 */ +"l1-d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=10069 */ +"l1-d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10161 */ +"l1-d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10258 */ +"l1-d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10360 */ +"l1-d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10456 */ +"l1-d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10555 */ +"l1-d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=10654 */ +"l1-d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=10751 */ +"l1-d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10844 */ +"l1-d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=10942 */ +"l1-d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11045 */ +"l1-d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11142 */ +"l1-d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11242 */ +"l1-d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=11342 */ +"l1-d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=11440 */ +"l1-d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11532 */ +"l1-d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11629 */ +"l1-d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11731 */ +"l1-d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11827 */ +"l1-d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=11926 */ +"l1-d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=12025 */ +"l1-d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=12122 */ +"l1-d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12220 */ +"l1-d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12323 */ +"l1-d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12431 */ +"l1-d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12533 */ +"l1-d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12638 */ +"l1-d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=12743 */ +"l1-d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=12846 */ +"l1-d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=12946 */ +"l1-d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13051 */ +"l1-d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13161 */ +"l1-d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13265 */ +"l1-d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13372 */ +"l1-d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=13479 */ +"l1-d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=13584 */ +"l1-d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13690 */ +"l1-d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13801 */ +"l1-d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=13917 */ +"l1-d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14027 */ +"l1-d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14140 */ +"l1-d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=14253 */ +"l1-d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=14364 */ +"l1-d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14470 */ +"l1-d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14581 */ +"l1-d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14697 */ +"l1-d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14807 */ +"l1-d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=14920 */ +"l1-d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=15033 */ +"l1-d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=15144 */ +"l1-d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15230 */ +"l1-d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15321 */ +"l1-d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15406 */ +"l1-d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15494 */ +"l1-d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=15586 */ +"l1-d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=15676 */ +"l1d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15756 */ +"l1d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15841 */ +"l1d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=15931 */ +"l1d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16026 */ +"l1d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16115 */ +"l1d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16207 */ +"l1d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=16303 */ +"l1d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=16397 */ +"l1d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16483 */ +"l1d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16574 */ +"l1d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16670 */ +"l1d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16760 */ +"l1d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=16853 */ +"l1d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=16950 */ +"l1d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=17045 */ +"l1d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17130 */ +"l1d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17220 */ +"l1d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17315 */ +"l1d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17404 */ +"l1d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=17496 */ +"l1d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=17592 */ +"l1d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=17686 */ +"l1d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=17777 */ +"l1d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=17873 */ +"l1d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=17974 */ +"l1d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18069 */ +"l1d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18167 */ +"l1d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=18265 */ +"l1d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=18361 */ +"l1d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18453 */ +"l1d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18550 */ +"l1d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18652 */ +"l1d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18748 */ +"l1d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=18847 */ +"l1d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=18946 */ +"l1d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=19043 */ +"l1d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19134 */ +"l1d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19230 */ +"l1d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19331 */ +"l1d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19426 */ +"l1d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=19524 */ +"l1d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=19622 */ +"l1d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=19718 */ +"l1d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=19815 */ +"l1d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=19917 */ +"l1d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20024 */ +"l1d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20125 */ +"l1d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20229 */ +"l1d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=20333 */ +"l1d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=20435 */ +"l1d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20534 */ +"l1d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20638 */ +"l1d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20747 */ +"l1d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20850 */ +"l1d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=20956 */ +"l1d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=21062 */ +"l1d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=21166 */ +"l1d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21271 */ +"l1d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21381 */ +"l1d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21496 */ +"l1d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21605 */ +"l1d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=21717 */ +"l1d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=21829 */ +"l1d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=21939 */ +"l1d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22044 */ +"l1d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22154 */ +"l1d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22269 */ +"l1d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22378 */ +"l1d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=22490 */ +"l1d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=22602 */ +"l1d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=22712 */ +"l1d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=22797 */ +"l1d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=22887 */ +"l1d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=22971 */ +"l1d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23058 */ +"l1d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=23149 */ +"l1d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=23238 */ +"l1-data\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23322 */ +"l1-data-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23411 */ +"l1-data-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23505 */ +"l1-data-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23604 */ +"l1-data-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23697 */ +"l1-data-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=23793 */ +"l1-data-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=23893 */ +"l1-data-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=23991 */ +"l1-data-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24081 */ +"l1-data-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24176 */ +"l1-data-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24276 */ +"l1-data-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24370 */ +"l1-data-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24467 */ +"l1-data-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=24568 */ +"l1-data-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=24667 */ +"l1-data-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24756 */ +"l1-data-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24850 */ +"l1-data-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=24949 */ +"l1-data-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=25042 */ +"l1-data-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=25138 */ +"l1-data-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=25238 */ +"l1-data-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=25336 */ +"l1-data-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25431 */ +"l1-data-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25531 */ +"l1-data-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25636 */ +"l1-data-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25735 */ +"l1-data-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=25837 */ +"l1-data-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=25939 */ +"l1-data-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=26039 */ +"l1-data-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26135 */ +"l1-data-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26236 */ +"l1-data-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26342 */ +"l1-data-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26442 */ +"l1-data-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26545 */ +"l1-data-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=26648 */ +"l1-data-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=26749 */ +"l1-data-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26844 */ +"l1-data-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=26944 */ +"l1-data-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=27049 */ +"l1-data-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=27148 */ +"l1-data-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000" +/* offset=27250 */ +"l1-data-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=27352 */ +"l1-data-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000" +/* offset=27452 */ +"l1-data-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27553 */ +"l1-data-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27659 */ +"l1-data-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27770 */ +"l1-data-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27875 */ +"l1-data-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=27983 */ +"l1-data-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=28091 */ +"l1-data-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=28197 */ +"l1-data-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28300 */ +"l1-data-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28408 */ +"l1-data-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28521 */ +"l1-data-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28628 */ +"l1-data-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=28738 */ +"l1-data-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=28848 */ +"l1-data-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=28956 */ +"l1-data-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29065 */ +"l1-data-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29179 */ +"l1-data-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29298 */ +"l1-data-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29411 */ +"l1-data-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29527 */ +"l1-data-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=29643 */ +"l1-data-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=29757 */ +"l1-data-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29866 */ +"l1-data-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=29980 */ +"l1-data-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=30099 */ +"l1-data-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=30212 */ +"l1-data-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000" +/* offset=30328 */ +"l1-data-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=30444 */ +"l1-data-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000" +/* offset=30558 */ +"l1-data-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=30647 */ +"l1-data-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=30741 */ +"l1-data-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=30829 */ +"l1-data-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000" +/* offset=30920 */ +"l1-data-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=31015 */ +"l1-data-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000" +/* offset=31108 */ +"l1-icache\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31201 */ +"l1-icache-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31299 */ +"l1-icache-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31402 */ +"l1-icache-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31510 */ +"l1-icache-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31612 */ +"l1-icache-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=31717 */ +"l1-icache-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00000\000\000\000\000\000" +/* offset=31826 */ +"l1-icache-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=31933 */ +"l1-icache-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00000\000\000\000\000\000" +/* offset=32032 */ +"l1-icache-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32136 */ +"l1-icache-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32245 */ +"l1-icache-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32348 */ +"l1-icache-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32454 */ +"l1-icache-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=32564 */ +"l1-icache-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=32672 */ +"l1-icache-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32770 */ +"l1-icache-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32873 */ +"l1-icache-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=32981 */ +"l1-icache-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=33083 */ +"l1-icache-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=33188 */ +"l1-icache-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=33297 */ +"l1-icache-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=33404 */ +"l1-icache-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33514 */ +"l1-icache-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33629 */ +"l1-icache-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33749 */ +"l1-icache-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33863 */ +"l1-icache-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=33980 */ +"l1-icache-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00000\000\000\000\000\000" +/* offset=34097 */ +"l1-icache-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=34212 */ +"l1-icache-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00000\000\000\000\000\000" +/* offset=34324 */ +"l1-icache-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=34441 */ +"l1-icache-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=34563 */ +"l1-icache-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=34679 */ +"l1-icache-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=34798 */ +"l1-icache-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=34917 */ +"l1-icache-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=35034 */ +"l1-icache-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35152 */ +"l1-icache-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35275 */ +"l1-icache-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35403 */ +"l1-icache-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35525 */ +"l1-icache-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=35650 */ +"l1-icache-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=35775 */ +"l1-icache-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=35898 */ +"l1-icache-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36016 */ +"l1-icache-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36139 */ +"l1-icache-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36267 */ +"l1-icache-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36389 */ +"l1-icache-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=36514 */ +"l1-icache-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=36639 */ +"l1-icache-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=36762 */ +"l1-icache-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=36860 */ +"l1-icache-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=36963 */ +"l1-icache-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37060 */ +"l1-icache-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37160 */ +"l1-icache-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=37264 */ +"l1-icache-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=37366 */ +"l1-i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37454 */ +"l1-i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37547 */ +"l1-i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37645 */ +"l1-i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37748 */ +"l1-i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37845 */ +"l1-i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=37945 */ +"l1-i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=38049 */ +"l1-i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=38151 */ +"l1-i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38245 */ +"l1-i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38344 */ +"l1-i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38448 */ +"l1-i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38546 */ +"l1-i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38647 */ +"l1-i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=38752 */ +"l1-i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=38855 */ +"l1-i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=38948 */ +"l1-i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=39046 */ +"l1-i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=39149 */ +"l1-i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=39246 */ +"l1-i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=39346 */ +"l1-i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=39450 */ +"l1-i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=39552 */ +"l1-i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=39657 */ +"l1-i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=39767 */ +"l1-i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=39882 */ +"l1-i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=39991 */ +"l1-i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40103 */ +"l1-i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=40215 */ +"l1-i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=40325 */ +"l1-i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40432 */ +"l1-i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40544 */ +"l1-i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40661 */ +"l1-i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40772 */ +"l1-i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=40886 */ +"l1-i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=41000 */ +"l1-i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=41112 */ +"l1-i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41225 */ +"l1-i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41343 */ +"l1-i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41466 */ +"l1-i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41583 */ +"l1-i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=41703 */ +"l1-i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=41823 */ +"l1-i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=41941 */ +"l1-i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42054 */ +"l1-i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42172 */ +"l1-i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42295 */ +"l1-i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42412 */ +"l1-i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=42532 */ +"l1-i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=42652 */ +"l1-i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=42770 */ +"l1-i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=42863 */ +"l1-i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=42961 */ +"l1-i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43053 */ +"l1-i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43148 */ +"l1-i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=43247 */ +"l1-i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=43344 */ +"l1i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43431 */ +"l1i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43523 */ +"l1i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43620 */ +"l1i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43722 */ +"l1i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43818 */ +"l1i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=43917 */ +"l1i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=44020 */ +"l1i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=44121 */ +"l1i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44214 */ +"l1i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44312 */ +"l1i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44415 */ +"l1i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44512 */ +"l1i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44612 */ +"l1i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=44716 */ +"l1i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=44818 */ +"l1i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=44910 */ +"l1i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=45007 */ +"l1i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=45109 */ +"l1i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=45205 */ +"l1i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=45304 */ +"l1i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=45407 */ +"l1i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=45508 */ +"l1i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=45612 */ +"l1i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=45721 */ +"l1i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=45835 */ +"l1i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=45943 */ +"l1i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46054 */ +"l1i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=46165 */ +"l1i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=46274 */ +"l1i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46380 */ +"l1i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46491 */ +"l1i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46607 */ +"l1i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46717 */ +"l1i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=46830 */ +"l1i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=46943 */ +"l1i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=47054 */ +"l1i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47166 */ +"l1i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47283 */ +"l1i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47405 */ +"l1i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47521 */ +"l1i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47640 */ +"l1i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=47759 */ +"l1i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=47876 */ +"l1i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=47988 */ +"l1i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=48105 */ +"l1i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=48227 */ +"l1i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=48343 */ +"l1i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=48462 */ +"l1i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=48581 */ +"l1i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=48698 */ +"l1i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=48790 */ +"l1i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=48887 */ +"l1i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=48978 */ +"l1i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49072 */ +"l1i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=49170 */ +"l1i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=49266 */ +"l1-instruction\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49364 */ +"l1-instruction-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49467 */ +"l1-instruction-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49575 */ +"l1-instruction-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49688 */ +"l1-instruction-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49795 */ +"l1-instruction-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=49905 */ +"l1-instruction-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=50019 */ +"l1-instruction-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=50131 */ +"l1-instruction-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50235 */ +"l1-instruction-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50344 */ +"l1-instruction-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50458 */ +"l1-instruction-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50566 */ +"l1-instruction-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=50677 */ +"l1-instruction-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=50792 */ +"l1-instruction-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=50905 */ +"l1-instruction-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51008 */ +"l1-instruction-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51116 */ +"l1-instruction-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51229 */ +"l1-instruction-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51336 */ +"l1-instruction-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=51446 */ +"l1-instruction-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=51560 */ +"l1-instruction-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=51672 */ +"l1-instruction-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=51787 */ +"l1-instruction-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=51907 */ +"l1-instruction-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52032 */ +"l1-instruction-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52151 */ +"l1-instruction-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52273 */ +"l1-instruction-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=52395 */ +"l1-instruction-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=52515 */ +"l1-instruction-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52632 */ +"l1-instruction-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52754 */ +"l1-instruction-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=52881 */ +"l1-instruction-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53002 */ +"l1-instruction-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53126 */ +"l1-instruction-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=53250 */ +"l1-instruction-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=53372 */ +"l1-instruction-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53495 */ +"l1-instruction-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53623 */ +"l1-instruction-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53756 */ +"l1-instruction-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=53883 */ +"l1-instruction-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54013 */ +"l1-instruction-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=54143 */ +"l1-instruction-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=54271 */ +"l1-instruction-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54394 */ +"l1-instruction-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54522 */ +"l1-instruction-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54655 */ +"l1-instruction-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54782 */ +"l1-instruction-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000" +/* offset=54912 */ +"l1-instruction-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=55042 */ +"l1-instruction-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000" +/* offset=55170 */ +"l1-instruction-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=55273 */ +"l1-instruction-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=55381 */ +"l1-instruction-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=55483 */ +"l1-instruction-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000" +/* offset=55588 */ +"l1-instruction-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=55697 */ +"l1-instruction-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000" +/* offset=55804 */ +"llc\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=55882 */ +"llc-load\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=55965 */ +"llc-load-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56053 */ +"llc-load-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56146 */ +"llc-load-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56233 */ +"llc-load-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56323 */ +"llc-load-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00000\000\000\000\000\000" +/* offset=56417 */ +"llc-load-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=56509 */ +"llc-loads\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00000\000\000\000\000\000" +/* offset=56593 */ +"llc-loads-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56682 */ +"llc-loads-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56776 */ +"llc-loads-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56864 */ +"llc-loads-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=56955 */ +"llc-loads-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=57050 */ +"llc-loads-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=57143 */ +"llc-read\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57226 */ +"llc-read-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57314 */ +"llc-read-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57407 */ +"llc-read-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57494 */ +"llc-read-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=57584 */ +"llc-read-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=57678 */ +"llc-read-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=57770 */ +"llc-store\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=57859 */ +"llc-store-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=57953 */ +"llc-store-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58052 */ +"llc-store-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58145 */ +"llc-store-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58241 */ +"llc-store-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00000\000\000\000\000\000" +/* offset=58337 */ +"llc-store-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=58431 */ +"llc-stores\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00000\000\000\000\000\000" +/* offset=58521 */ +"llc-stores-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58616 */ +"llc-stores-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58716 */ +"llc-stores-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58810 */ +"llc-stores-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=58907 */ +"llc-stores-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=59004 */ +"llc-stores-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=59099 */ +"llc-write\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59188 */ +"llc-write-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59282 */ +"llc-write-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59381 */ +"llc-write-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59474 */ +"llc-write-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=59570 */ +"llc-write-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=59666 */ +"llc-write-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=59760 */ +"llc-prefetch\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=59855 */ +"llc-prefetch-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=59955 */ +"llc-prefetch-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60060 */ +"llc-prefetch-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60159 */ +"llc-prefetch-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60261 */ +"llc-prefetch-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00000\000\000\000\000\000" +/* offset=60363 */ +"llc-prefetch-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=60463 */ +"llc-prefetches\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00000\000\000\000\000\000" +/* offset=60560 */ +"llc-prefetches-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60662 */ +"llc-prefetches-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60769 */ +"llc-prefetches-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60870 */ +"llc-prefetches-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=60974 */ +"llc-prefetches-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=61078 */ +"llc-prefetches-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=61180 */ +"llc-speculative-read\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61283 */ +"llc-speculative-read-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61391 */ +"llc-speculative-read-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61504 */ +"llc-speculative-read-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61611 */ +"llc-speculative-read-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=61721 */ +"llc-speculative-read-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=61831 */ +"llc-speculative-read-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=61939 */ +"llc-speculative-load\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62042 */ +"llc-speculative-load-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62150 */ +"llc-speculative-load-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62263 */ +"llc-speculative-load-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62370 */ +"llc-speculative-load-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=62480 */ +"llc-speculative-load-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=62590 */ +"llc-speculative-load-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=62698 */ +"llc-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=62781 */ +"llc-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=62869 */ +"llc-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=62951 */ +"llc-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63036 */ +"llc-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=63125 */ +"llc-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=63212 */ +"l2\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63309 */ +"l2-load\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63411 */ +"l2-load-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63518 */ +"l2-load-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63630 */ +"l2-load-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63736 */ +"l2-load-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=63845 */ +"l2-load-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=63958 */ +"l2-load-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=64069 */ +"l2-loads\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64172 */ +"l2-loads-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64280 */ +"l2-loads-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64393 */ +"l2-loads-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64500 */ +"l2-loads-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64610 */ +"l2-loads-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=64724 */ +"l2-loads-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=64836 */ +"l2-read\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=64938 */ +"l2-read-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=65045 */ +"l2-read-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=65157 */ +"l2-read-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=65263 */ +"l2-read-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=65372 */ +"l2-read-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=65485 */ +"l2-read-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=65596 */ +"l2-store\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=65704 */ +"l2-store-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=65817 */ +"l2-store-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=65935 */ +"l2-store-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66047 */ +"l2-store-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66162 */ +"l2-store-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=66277 */ +"l2-store-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=66390 */ +"l2-stores\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66499 */ +"l2-stores-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66613 */ +"l2-stores-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66732 */ +"l2-stores-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66845 */ +"l2-stores-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=66961 */ +"l2-stores-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=67077 */ +"l2-stores-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=67191 */ +"l2-write\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67299 */ +"l2-write-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67412 */ +"l2-write-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67530 */ +"l2-write-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67642 */ +"l2-write-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000" +/* offset=67757 */ +"l2-write-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=67872 */ +"l2-write-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000" +/* offset=67985 */ +"l2-prefetch\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68099 */ +"l2-prefetch-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68218 */ +"l2-prefetch-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68342 */ +"l2-prefetch-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68460 */ +"l2-prefetch-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68581 */ +"l2-prefetch-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=68702 */ +"l2-prefetch-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=68821 */ +"l2-prefetches\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=68937 */ +"l2-prefetches-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69058 */ +"l2-prefetches-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69184 */ +"l2-prefetches-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69304 */ +"l2-prefetches-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69427 */ +"l2-prefetches-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=69550 */ +"l2-prefetches-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=69671 */ +"l2-speculative-read\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69793 */ +"l2-speculative-read-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=69920 */ +"l2-speculative-read-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70052 */ +"l2-speculative-read-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70178 */ +"l2-speculative-read-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70307 */ +"l2-speculative-read-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=70436 */ +"l2-speculative-read-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=70563 */ +"l2-speculative-load\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70685 */ +"l2-speculative-load-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70812 */ +"l2-speculative-load-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=70944 */ +"l2-speculative-load-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=71070 */ +"l2-speculative-load-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000" +/* offset=71199 */ +"l2-speculative-load-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=71328 */ +"l2-speculative-load-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000" +/* offset=71455 */ +"l2-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=71557 */ +"l2-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=71664 */ +"l2-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=71765 */ +"l2-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000" +/* offset=71869 */ +"l2-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=71977 */ +"l2-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000" +/* offset=72083 */ +"dtlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72154 */ +"dtlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72230 */ +"dtlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72311 */ +"dtlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72397 */ +"dtlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72477 */ +"dtlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72560 */ +"dtlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00000\000\000\000\000\000" +/* offset=72647 */ +"dtlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=72732 */ +"dtlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00000\000\000\000\000\000" +/* offset=72809 */ +"dtlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72891 */ +"dtlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=72978 */ +"dtlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73059 */ +"dtlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73143 */ +"dtlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=73231 */ +"dtlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=73317 */ +"dtlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73393 */ +"dtlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73474 */ +"dtlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73560 */ +"dtlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73640 */ +"dtlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=73723 */ +"dtlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=73810 */ +"dtlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=73895 */ +"dtlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=73977 */ +"dtlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74064 */ +"dtlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74156 */ +"dtlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74242 */ +"dtlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74331 */ +"dtlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00000\000\000\000\000\000" +/* offset=74420 */ +"dtlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=74507 */ +"dtlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00000\000\000\000\000\000" +/* offset=74590 */ +"dtlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74678 */ +"dtlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74771 */ +"dtlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74858 */ +"dtlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=74948 */ +"dtlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=75038 */ +"dtlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=75126 */ +"dtlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75208 */ +"dtlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75295 */ +"dtlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75387 */ +"dtlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75473 */ +"dtlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=75562 */ +"dtlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=75651 */ +"dtlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=75738 */ +"dtlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=75826 */ +"dtlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=75919 */ +"dtlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76017 */ +"dtlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76109 */ +"dtlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76204 */ +"dtlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00000\000\000\000\000\000" +/* offset=76299 */ +"dtlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=76392 */ +"dtlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00000\000\000\000\000\000" +/* offset=76482 */ +"dtlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76577 */ +"dtlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76677 */ +"dtlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76771 */ +"dtlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=76868 */ +"dtlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=76965 */ +"dtlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=77060 */ +"dtlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77156 */ +"dtlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77257 */ +"dtlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77363 */ +"dtlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77463 */ +"dtlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77566 */ +"dtlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=77669 */ +"dtlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=77770 */ +"dtlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77866 */ +"dtlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=77967 */ +"dtlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=78073 */ +"dtlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=78173 */ +"dtlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=78276 */ +"dtlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=78379 */ +"dtlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=78480 */ +"dtlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=78556 */ +"dtlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=78637 */ +"dtlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=78712 */ +"dtlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=78790 */ +"dtlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=78872 */ +"dtlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=78952 */ +"d-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79024 */ +"d-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79101 */ +"d-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79183 */ +"d-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79270 */ +"d-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79351 */ +"d-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79435 */ +"d-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=79523 */ +"d-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=79609 */ +"d-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79687 */ +"d-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79770 */ +"d-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79858 */ +"d-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=79940 */ +"d-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80025 */ +"d-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=80114 */ +"d-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=80201 */ +"d-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80278 */ +"d-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80360 */ +"d-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80447 */ +"d-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80528 */ +"d-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=80612 */ +"d-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=80700 */ +"d-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=80786 */ +"d-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=80869 */ +"d-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=80957 */ +"d-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81050 */ +"d-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81137 */ +"d-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81227 */ +"d-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=81317 */ +"d-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=81405 */ +"d-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81489 */ +"d-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81578 */ +"d-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81672 */ +"d-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81760 */ +"d-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=81851 */ +"d-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=81942 */ +"d-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=82031 */ +"d-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82114 */ +"d-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82202 */ +"d-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82295 */ +"d-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82382 */ +"d-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=82472 */ +"d-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=82562 */ +"d-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=82650 */ +"d-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=82739 */ +"d-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=82833 */ +"d-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=82932 */ +"d-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83025 */ +"d-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83121 */ +"d-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=83217 */ +"d-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=83311 */ +"d-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83402 */ +"d-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83498 */ +"d-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83599 */ +"d-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83694 */ +"d-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=83792 */ +"d-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=83890 */ +"d-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=83986 */ +"d-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84083 */ +"d-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84185 */ +"d-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84292 */ +"d-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84393 */ +"d-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84497 */ +"d-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=84601 */ +"d-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=84703 */ +"d-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84800 */ +"d-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=84902 */ +"d-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=85009 */ +"d-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=85110 */ +"d-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=85214 */ +"d-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=85318 */ +"d-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=85420 */ +"d-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85497 */ +"d-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85579 */ +"d-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85655 */ +"d-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85734 */ +"d-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=85817 */ +"d-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=85898 */ +"data-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=85973 */ +"data-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86053 */ +"data-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86138 */ +"data-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86228 */ +"data-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86312 */ +"data-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86399 */ +"data-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=86490 */ +"data-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=86579 */ +"data-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86660 */ +"data-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86746 */ +"data-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86837 */ +"data-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=86922 */ +"data-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87010 */ +"data-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=87102 */ +"data-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=87192 */ +"data-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87272 */ +"data-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87357 */ +"data-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87447 */ +"data-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87531 */ +"data-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=87618 */ +"data-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=87709 */ +"data-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=87798 */ +"data-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=87884 */ +"data-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=87975 */ +"data-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88071 */ +"data-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88161 */ +"data-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88254 */ +"data-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=88347 */ +"data-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=88438 */ +"data-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88525 */ +"data-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88617 */ +"data-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88714 */ +"data-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88805 */ +"data-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=88899 */ +"data-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=88993 */ +"data-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=89085 */ +"data-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89171 */ +"data-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89262 */ +"data-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89358 */ +"data-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89448 */ +"data-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000" +/* offset=89541 */ +"data-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=89634 */ +"data-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000" +/* offset=89725 */ +"data-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=89817 */ +"data-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=89914 */ +"data-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90016 */ +"data-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90112 */ +"data-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90211 */ +"data-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=90310 */ +"data-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=90407 */ +"data-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90501 */ +"data-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90600 */ +"data-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90704 */ +"data-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90802 */ +"data-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=90903 */ +"data-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=91004 */ +"data-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=91103 */ +"data-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91203 */ +"data-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91308 */ +"data-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91418 */ +"data-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91522 */ +"data-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91629 */ +"data-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=91736 */ +"data-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=91841 */ +"data-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=91941 */ +"data-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=92046 */ +"data-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=92156 */ +"data-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=92260 */ +"data-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000" +/* offset=92367 */ +"data-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=92474 */ +"data-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000" +/* offset=92579 */ +"data-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=92659 */ +"data-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=92744 */ +"data-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=92823 */ +"data-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000" +/* offset=92905 */ +"data-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=92991 */ +"data-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000" +/* offset=93075 */ +"itlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93153 */ +"itlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93236 */ +"itlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93324 */ +"itlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93417 */ +"itlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93504 */ +"itlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93594 */ +"itlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00000\000\000\000\000\000" +/* offset=93688 */ +"itlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=93780 */ +"itlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00000\000\000\000\000\000" +/* offset=93864 */ +"itlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=93953 */ +"itlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94047 */ +"itlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94135 */ +"itlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94226 */ +"itlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=94321 */ +"itlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=94414 */ +"itlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94497 */ +"itlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94585 */ +"itlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94678 */ +"itlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94765 */ +"itlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=94855 */ +"itlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=94949 */ +"itlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=95041 */ +"itlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95124 */ +"itlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95212 */ +"itlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95294 */ +"itlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95379 */ +"itlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=95468 */ +"itlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=95555 */ +"i-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95634 */ +"i-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95718 */ +"i-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95807 */ +"i-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95901 */ +"i-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=95989 */ +"i-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96080 */ +"i-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=96175 */ +"i-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=96268 */ +"i-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96353 */ +"i-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96443 */ +"i-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96538 */ +"i-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96627 */ +"i-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96719 */ +"i-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=96815 */ +"i-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=96909 */ +"i-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=96993 */ +"i-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97082 */ +"i-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97176 */ +"i-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97264 */ +"i-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97355 */ +"i-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=97450 */ +"i-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=97543 */ +"i-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97627 */ +"i-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97716 */ +"i-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97799 */ +"i-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=97885 */ +"i-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=97975 */ +"i-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=98063 */ +"instruction-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98152 */ +"instruction-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98246 */ +"instruction-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98345 */ +"instruction-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98449 */ +"instruction-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98547 */ +"instruction-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98648 */ +"instruction-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=98753 */ +"instruction-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=98856 */ +"instruction-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=98951 */ +"instruction-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99051 */ +"instruction-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99156 */ +"instruction-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99255 */ +"instruction-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99357 */ +"instruction-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=99463 */ +"instruction-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=99567 */ +"instruction-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99661 */ +"instruction-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99760 */ +"instruction-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99864 */ +"instruction-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=99962 */ +"instruction-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100063 */ +"instruction-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=100168 */ +"instruction-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=100271 */ +"instruction-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100365 */ +"instruction-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100464 */ +"instruction-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100557 */ +"instruction-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000" +/* offset=100653 */ +"instruction-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=100753 */ +"instruction-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000" +/* offset=100851 */ +"branch\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=100938 */ +"branch-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101030 */ +"branch-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101127 */ +"branch-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101229 */ +"branch-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101325 */ +"branch-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101424 */ +"branch-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00000\000\000\000\000\000" +/* offset=101527 */ +"branch-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=101628 */ +"branch-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00000\000\000\000\000\000" +/* offset=101721 */ +"branch-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101819 */ +"branch-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=101922 */ +"branch-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102019 */ +"branch-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102119 */ +"branch-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=102223 */ +"branch-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=102325 */ +"branch-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102417 */ +"branch-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102514 */ +"branch-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102616 */ +"branch-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102712 */ +"branch-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=102811 */ +"branch-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=102914 */ +"branch-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=103015 */ +"branch-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103107 */ +"branch-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103204 */ +"branch-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103295 */ +"branch-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103389 */ +"branch-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=103485 */ +"branches-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103579 */ +"branches-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103678 */ +"branches-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103782 */ +"branches-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103880 */ +"branches-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=103981 */ +"branches-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=104086 */ +"branches-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=104189 */ +"branches-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104284 */ +"branches-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104384 */ +"branches-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104489 */ +"branches-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104588 */ +"branches-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104690 */ +"branches-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=104796 */ +"branches-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=104900 */ +"branches-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=104994 */ +"branches-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105093 */ +"branches-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105197 */ +"branches-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105295 */ +"branches-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105396 */ +"branches-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=105501 */ +"branches-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=105604 */ +"branches-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105698 */ +"branches-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105797 */ +"branches-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105890 */ +"branches-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=105986 */ +"branches-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=106086 */ +"branches-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=106184 */ +"bpu\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106268 */ +"bpu-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106357 */ +"bpu-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106451 */ +"bpu-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106550 */ +"bpu-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106643 */ +"bpu-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=106739 */ +"bpu-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=106839 */ +"bpu-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=106937 */ +"bpu-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107027 */ +"bpu-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107122 */ +"bpu-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107222 */ +"bpu-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107316 */ +"bpu-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107413 */ +"bpu-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=107514 */ +"bpu-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=107613 */ +"bpu-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107702 */ +"bpu-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107796 */ +"bpu-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107895 */ +"bpu-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=107988 */ +"bpu-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108084 */ +"bpu-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=108184 */ +"bpu-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=108282 */ +"bpu-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108371 */ +"bpu-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108465 */ +"bpu-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108553 */ +"bpu-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108644 */ +"bpu-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=108739 */ +"bpu-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=108832 */ +"btb\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=108916 */ +"btb-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109005 */ +"btb-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109099 */ +"btb-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109198 */ +"btb-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109291 */ +"btb-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109387 */ +"btb-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=109487 */ +"btb-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=109585 */ +"btb-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109675 */ +"btb-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109770 */ +"btb-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109870 */ +"btb-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=109964 */ +"btb-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110061 */ +"btb-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=110162 */ +"btb-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=110261 */ +"btb-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110350 */ +"btb-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110444 */ +"btb-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110543 */ +"btb-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110636 */ +"btb-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=110732 */ +"btb-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=110832 */ +"btb-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=110930 */ +"btb-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111019 */ +"btb-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111113 */ +"btb-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111201 */ +"btb-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111292 */ +"btb-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=111387 */ +"btb-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=111480 */ +"bpc\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111564 */ +"bpc-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111653 */ +"bpc-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111747 */ +"bpc-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111846 */ +"bpc-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=111939 */ +"bpc-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112035 */ +"bpc-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=112135 */ +"bpc-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=112233 */ +"bpc-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112323 */ +"bpc-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112418 */ +"bpc-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112518 */ +"bpc-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112612 */ +"bpc-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112709 */ +"bpc-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=112810 */ +"bpc-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=112909 */ +"bpc-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=112998 */ +"bpc-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113092 */ +"bpc-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113191 */ +"bpc-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113284 */ +"bpc-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113380 */ +"bpc-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=113480 */ +"bpc-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=113578 */ +"bpc-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113667 */ +"bpc-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113761 */ +"bpc-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113849 */ +"bpc-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000" +/* offset=113940 */ +"bpc-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=114035 */ +"bpc-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000" +/* offset=114128 */ +"node\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114203 */ +"node-load\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114283 */ +"node-load-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114368 */ +"node-load-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114458 */ +"node-load-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114542 */ +"node-load-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114629 */ +"node-load-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00000\000\000\000\000\000" +/* offset=114720 */ +"node-load-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=114809 */ +"node-loads\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00000\000\000\000\000\000" +/* offset=114890 */ +"node-loads-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=114976 */ +"node-loads-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115067 */ +"node-loads-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115152 */ +"node-loads-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115240 */ +"node-loads-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=115332 */ +"node-loads-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=115422 */ +"node-read\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115502 */ +"node-read-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115587 */ +"node-read-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115677 */ +"node-read-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115761 */ +"node-read-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=115848 */ +"node-read-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=115939 */ +"node-read-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=116028 */ +"node-store\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116114 */ +"node-store-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116205 */ +"node-store-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116301 */ +"node-store-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116391 */ +"node-store-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116484 */ +"node-store-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00000\000\000\000\000\000" +/* offset=116577 */ +"node-store-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=116668 */ +"node-stores\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00000\000\000\000\000\000" +/* offset=116755 */ +"node-stores-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116847 */ +"node-stores-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=116944 */ +"node-stores-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117035 */ +"node-stores-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117129 */ +"node-stores-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=117223 */ +"node-stores-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=117315 */ +"node-write\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117401 */ +"node-write-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117492 */ +"node-write-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117588 */ +"node-write-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117678 */ +"node-write-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000" +/* offset=117771 */ +"node-write-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=117864 */ +"node-write-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000" +/* offset=117955 */ +"node-prefetch\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118047 */ +"node-prefetch-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118144 */ +"node-prefetch-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118246 */ +"node-prefetch-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118342 */ +"node-prefetch-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118441 */ +"node-prefetch-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00000\000\000\000\000\000" +/* offset=118540 */ +"node-prefetch-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=118637 */ +"node-prefetches\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00000\000\000\000\000\000" +/* offset=118731 */ +"node-prefetches-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118830 */ +"node-prefetches-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=118934 */ +"node-prefetches-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119032 */ +"node-prefetches-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119133 */ +"node-prefetches-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=119234 */ +"node-prefetches-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=119333 */ +"node-speculative-read\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119433 */ +"node-speculative-read-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119538 */ +"node-speculative-read-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119648 */ +"node-speculative-read-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119752 */ +"node-speculative-read-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=119859 */ +"node-speculative-read-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=119966 */ +"node-speculative-read-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=120071 */ +"node-speculative-load\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120171 */ +"node-speculative-load-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120276 */ +"node-speculative-load-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120386 */ +"node-speculative-load-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120490 */ +"node-speculative-load-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000" +/* offset=120597 */ +"node-speculative-load-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=120704 */ +"node-speculative-load-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000" +/* offset=120809 */ +"node-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=120889 */ +"node-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=120974 */ +"node-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=121053 */ +"node-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000" +/* offset=121135 */ +"node-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=121221 */ +"node-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000" +/* offset=121305 */ +"cpu-cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000" +/* offset=121467 */ +"cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cpu-cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000" +/* offset=121629 */ +"instructions\000legacy hardware\000Retired instructions. Be careful, these can be affected by various issues, most notably hardware interrupt counts\000legacy-hardware-config=1\000\00000\000\000\000\000\000" +/* offset=121805 */ +"cache-references\000legacy hardware\000Cache accesses. Usually this indicates Last Level Cache accesses but this may vary depending on your CPU. This may include prefetches and coherency messages; again this depends on the design of your CPU\000legacy-hardware-config=2\000\00000\000\000\000\000\000" +/* offset=122075 */ +"cache-misses\000legacy hardware\000Cache misses. Usually this indicates Last Level Cache misses; this is intended to be used in conjunction with the PERF_COUNT_HW_CACHE_REFERENCES event to calculate cache miss rates\000legacy-hardware-config=3\000\00000\000\000\000\000\000" +/* offset=122318 */ +"branches\000legacy hardware\000Retired branch instructions [This event is an alias of branch-instructions]\000legacy-hardware-config=4\000\00000\000\000\000\000\000" +/* offset=122452 */ +"branch-instructions\000legacy hardware\000Retired branch instructions [This event is an alias of branches]\000legacy-hardware-config=4\000\00000\000\000\000\000\000" +/* offset=122586 */ +"branch-misses\000legacy hardware\000Mispredicted branch instructions\000legacy-hardware-config=5\000\00000\000\000\000\000\000" +/* offset=122682 */ +"bus-cycles\000legacy hardware\000Bus cycles, which can be different from total cycles\000legacy-hardware-config=6\000\00000\000\000\000\000\000" +/* offset=122795 */ +"stalled-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of idle-cycles-frontend]\000legacy-hardware-config=7\000\00000\000\000\000\000\000" +/* offset=122945 */ +"idle-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of stalled-cycles-fronted]\000legacy-hardware-config=7\000\00000\000\000\000\000\000" +/* offset=123094 */ +"stalled-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of idle-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000" +/* offset=123247 */ +"idle-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of stalled-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000" +/* offset=123400 */ +"ref-cycles\000legacy hardware\000Total cycles; not affected by CPU frequency scaling\000legacy-hardware-config=9\000\00000\000\000\000\000\000" +/* offset=123512 */ +"software\000" +/* offset=123521 */ +"cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\000001e-6msec\000\000\000\000\000" +/* offset=123607 */ +"task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\000001e-6msec\000\000\000\000\000" +/* offset=123695 */ +"faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000" +/* offset=123790 */ +"page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000" +/* offset=123885 */ +"context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000" +/* offset=123986 */ +"cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000" +/* offset=124087 */ +"cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000" +/* offset=124219 */ +"migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000" +/* offset=124351 */ +"minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000" +/* offset=124460 */ +"major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000" +/* offset=124563 */ +"alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000" +/* offset=124655 */ +"emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000" +/* offset=124782 */ +"dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000" +/* offset=124862 */ +"bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000" +/* offset=124964 */ +"cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000" +/* offset=125067 */ +"tool\000" +/* offset=125072 */ +"duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000" +/* offset=125148 */ +"user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000" +/* offset=125218 */ +"system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000" +/* offset=125286 */ +"has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000" +/* offset=125362 */ +"num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000" +/* offset=125507 */ +"num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000" +/* offset=125610 */ +"num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000" +/* offset=125727 */ +"num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000" +/* offset=125803 */ +"num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000" +/* offset=125889 */ +"slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000" +/* offset=125999 */ +"smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000" +/* offset=126106 */ +"system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000" +/* offset=126205 */ +"core_wide\000tool\0001 if not SMT, if SMT are events being gathered on all SMT threads 1 otherwise 0\000config=0xd\000\00000\000\000\000\000\000" +/* offset=126319 */ +"target_cpu\000tool\0001 if CPUs being analyzed, 0 if threads/processes\000config=0xe\000\00000\000\000\000\000\000" +/* offset=126403 */ +"bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000" +/* offset=126465 */ +"bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000" +/* offset=126527 */ +"l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000" +/* offset=126625 */ +"segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000" +/* offset=126727 */ +"dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000" +/* offset=126860 */ +"eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000" +/* offset=126978 */ +"hisi_sccl,ddrc\000" +/* offset=126993 */ +"uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000" +/* offset=127063 */ +"uncore_cbox\000" +/* offset=127075 */ +"unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000" +/* offset=127229 */ +"event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000" +/* offset=127283 */ +"event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000" +/* offset=127341 */ +"hisi_sccl,l3c\000" +/* offset=127355 */ +"uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000" +/* offset=127423 */ +"uncore_imc_free_running\000" +/* offset=127447 */ +"uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000" +/* offset=127527 */ +"uncore_imc\000" +/* offset=127538 */ +"uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000" +/* offset=127603 */ +"uncore_sys_ddr_pmu\000" +/* offset=127622 */ +"sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000" +/* offset=127698 */ +"uncore_sys_ccn_pmu\000" +/* offset=127717 */ +"sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000" +/* offset=127794 */ +"uncore_sys_cmn_pmu\000" +/* offset=127813 */ +"sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000" +/* offset=127956 */ +"CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011" +/* offset=128142 */ +"cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011" +/* offset=128375 */ +"migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011" +/* offset=128635 */ +"page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011" +/* offset=128866 */ +"insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001" +/* offset=128979 */ +"stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions if has_event(stalled\\-cycles\\-frontend) & has_event(stalled\\-cycles\\-backend) else (stalled\\-cycles\\-frontend / instructions if has_event(stalled\\-cycles\\-frontend) else (stalled\\-cycles\\-backend / instructions if has_event(stalled\\-cycles\\-backend) else 0)))\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001" +/* offset=129404 */ +"frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles if has_event(stalled\\-cycles\\-frontend) else 0)\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001" +/* offset=129583 */ +"backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if has_event(stalled\\-cycles\\-backend) else 0)\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001" +/* offset=129757 */ +"cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011" +/* offset=129933 */ +"branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011" +/* offset=130113 */ +"branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001" +/* offset=130217 */ +"l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001" +/* offset=130333 */ +"llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001" +/* offset=130434 */ +"l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001" +/* offset=130549 */ +"dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001" +/* offset=130655 */ +"itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001" +/* offset=130761 */ +"l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001" +/* offset=130909 */ +"CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000" +/* offset=130932 */ +"IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000" +/* offset=130996 */ +"Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000" +/* offset=131163 */ +"dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" +/* offset=131228 */ +"icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000" +/* offset=131296 */ +"cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000" +/* offset=131368 */ +"DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000" +/* offset=131463 */ +"DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000" +/* offset=131598 */ +"DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000" +/* offset=131663 */ +"DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000" +/* offset=131732 */ +"DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000" +/* offset=131803 */ +"M1\000\000ipc + M2\000\000\000\000\000\000\000\000000" +/* offset=131826 */ +"M2\000\000ipc + M1\000\000\000\000\000\000\000\000000" +/* offset=131849 */ +"M3\000\0001 / M3\000\000\000\000\000\000\000\000000" +/* offset=131870 */ +"L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000" ; static const struct compact_pmu_event pmu_events__common_default_core[] = { -{ 111480 }, /* bpc\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 113849 }, /* bpc-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 111564 }, /* bpc-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 111939 }, /* bpc-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 112135 }, /* bpc-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 112035 }, /* bpc-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 111846 }, /* bpc-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 111747 }, /* bpc-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 111653 }, /* bpc-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 112233 }, /* bpc-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 112612 }, /* bpc-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 112810 }, /* bpc-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 112709 }, /* bpc-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 112518 }, /* bpc-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 112418 }, /* bpc-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 112323 }, /* bpc-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 114035 }, /* bpc-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 113940 }, /* bpc-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 113761 }, /* bpc-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 112909 }, /* bpc-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 113284 }, /* bpc-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 113480 }, /* bpc-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 113380 }, /* bpc-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 113191 }, /* bpc-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 113092 }, /* bpc-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 112998 }, /* bpc-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 113667 }, /* bpc-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 113578 }, /* bpc-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 106184 }, /* bpu\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 108553 }, /* bpu-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 106268 }, /* bpu-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 106643 }, /* bpu-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 106839 }, /* bpu-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 106739 }, /* bpu-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 106550 }, /* bpu-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 106451 }, /* bpu-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 106357 }, /* bpu-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 106937 }, /* bpu-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 107316 }, /* bpu-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 107514 }, /* bpu-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 107413 }, /* bpu-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 107222 }, /* bpu-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 107122 }, /* bpu-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 107027 }, /* bpu-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 108739 }, /* bpu-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 108644 }, /* bpu-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 108465 }, /* bpu-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 107613 }, /* bpu-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 107988 }, /* bpu-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 108184 }, /* bpu-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 108084 }, /* bpu-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 107895 }, /* bpu-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 107796 }, /* bpu-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 107702 }, /* bpu-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 108371 }, /* bpu-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 108282 }, /* bpu-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 100851 }, /* branch\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 103295 }, /* branch-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 122452 }, /* branch-instructions\000legacy hardware\000Retired branch instructions [This event is an alias of branches]\000legacy-hardware-config=4\000\00000\000\000\000\000\000 */ -{ 100938 }, /* branch-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 101325 }, /* branch-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 101527 }, /* branch-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 101424 }, /* branch-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00000\000\000\000\000\000 */ -{ 101229 }, /* branch-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 101127 }, /* branch-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 101030 }, /* branch-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 101628 }, /* branch-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00000\000\000\000\000\000 */ -{ 102019 }, /* branch-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 102223 }, /* branch-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 102119 }, /* branch-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 101922 }, /* branch-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 101819 }, /* branch-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 101721 }, /* branch-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 103389 }, /* branch-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 122586 }, /* branch-misses\000legacy hardware\000Mispredicted branch instructions\000legacy-hardware-config=5\000\00000\000\000\000\000\000 */ -{ 103204 }, /* branch-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 102325 }, /* branch-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 102712 }, /* branch-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 102914 }, /* branch-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 102811 }, /* branch-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 102616 }, /* branch-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 102514 }, /* branch-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 102417 }, /* branch-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 103107 }, /* branch-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 103015 }, /* branch-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 122318 }, /* branches\000legacy hardware\000Retired branch instructions [This event is an alias of branch-instructions]\000legacy-hardware-config=4\000\00000\000\000\000\000\000 */ -{ 105890 }, /* branches-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 103485 }, /* branches-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 103880 }, /* branches-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 104086 }, /* branches-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 103981 }, /* branches-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 103782 }, /* branches-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 103678 }, /* branches-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 103579 }, /* branches-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 104189 }, /* branches-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 104588 }, /* branches-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 104796 }, /* branches-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 104690 }, /* branches-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 104489 }, /* branches-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 104384 }, /* branches-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 104284 }, /* branches-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 106086 }, /* branches-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 105986 }, /* branches-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 105797 }, /* branches-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 104900 }, /* branches-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 105295 }, /* branches-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 105501 }, /* branches-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 105396 }, /* branches-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 105197 }, /* branches-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 105093 }, /* branches-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 104994 }, /* branches-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 105698 }, /* branches-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 105604 }, /* branches-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 108832 }, /* btb\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 111201 }, /* btb-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 108916 }, /* btb-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 109291 }, /* btb-load-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 109487 }, /* btb-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 109387 }, /* btb-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 109198 }, /* btb-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 109099 }, /* btb-load-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 109005 }, /* btb-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 109585 }, /* btb-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 109964 }, /* btb-loads-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 110162 }, /* btb-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 110061 }, /* btb-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 109870 }, /* btb-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 109770 }, /* btb-loads-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 109675 }, /* btb-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 111387 }, /* btb-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 111292 }, /* btb-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 111113 }, /* btb-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 110261 }, /* btb-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 110636 }, /* btb-read-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 110832 }, /* btb-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 110732 }, /* btb-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache-config=0x10005\000\00010\000\000\000\000\000 */ -{ 110543 }, /* btb-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 110444 }, /* btb-read-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 110350 }, /* btb-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 111019 }, /* btb-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 110930 }, /* btb-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-config=5\000\00010\000\000\000\000\000 */ -{ 122682 }, /* bus-cycles\000legacy hardware\000Bus cycles, which can be different from total cycles\000legacy-hardware-config=6\000\00000\000\000\000\000\000 */ -{ 122075 }, /* cache-misses\000legacy hardware\000Cache misses. Usually this indicates Last Level Cache misses; this is intended to be used in conjunction with the PERF_COUNT_HW_CACHE_REFERENCES event to calculate cache miss rates\000legacy-hardware-config=3\000\00000\000\000\000\000\000 */ -{ 121805 }, /* cache-references\000legacy hardware\000Cache accesses. Usually this indicates Last Level Cache accesses but this may vary depending on your CPU. This may include prefetches and coherency messages; again this depends on the design of your CPU\000legacy-hardware-config=2\000\00000\000\000\000\000\000 */ -{ 121305 }, /* cpu-cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000 */ -{ 121467 }, /* cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU frequency scaling [This event is an alias of cpu-cycles]\000legacy-hardware-config=0\000\00000\000\000\000\000\000 */ -{ 78952 }, /* d-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 85655 }, /* d-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 79024 }, /* d-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 79351 }, /* d-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 79523 }, /* d-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 79435 }, /* d-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 79270 }, /* d-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 79183 }, /* d-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 79101 }, /* d-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 79609 }, /* d-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 79940 }, /* d-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 80114 }, /* d-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 80025 }, /* d-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 79858 }, /* d-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 79770 }, /* d-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 79687 }, /* d-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 85817 }, /* d-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 85734 }, /* d-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 85579 }, /* d-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 82650 }, /* d-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 83025 }, /* d-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 83217 }, /* d-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 83121 }, /* d-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 82932 }, /* d-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 82833 }, /* d-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 82739 }, /* d-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 83311 }, /* d-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 83694 }, /* d-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 83890 }, /* d-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 83792 }, /* d-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 83599 }, /* d-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 83498 }, /* d-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 83402 }, /* d-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 80201 }, /* d-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 80528 }, /* d-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 80700 }, /* d-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 80612 }, /* d-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 80447 }, /* d-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 80360 }, /* d-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 80278 }, /* d-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 85497 }, /* d-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 85420 }, /* d-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 84703 }, /* d-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 85110 }, /* d-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 85318 }, /* d-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 85214 }, /* d-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 85009 }, /* d-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 84902 }, /* d-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 84800 }, /* d-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 83986 }, /* d-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 84393 }, /* d-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 84601 }, /* d-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 84497 }, /* d-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 84292 }, /* d-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 84185 }, /* d-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 84083 }, /* d-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 80786 }, /* d-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 81137 }, /* d-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 81317 }, /* d-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 81227 }, /* d-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 81050 }, /* d-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 80957 }, /* d-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 80869 }, /* d-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 81405 }, /* d-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 81760 }, /* d-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 81942 }, /* d-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 81851 }, /* d-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 81672 }, /* d-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 81578 }, /* d-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 81489 }, /* d-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 82031 }, /* d-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 82382 }, /* d-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 82562 }, /* d-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 82472 }, /* d-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 82295 }, /* d-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 82202 }, /* d-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 82114 }, /* d-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 85898 }, /* data-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 92823 }, /* data-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 85973 }, /* data-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 86312 }, /* data-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 86490 }, /* data-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 86399 }, /* data-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 86228 }, /* data-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 86138 }, /* data-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 86053 }, /* data-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 86579 }, /* data-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 86922 }, /* data-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 87102 }, /* data-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 87010 }, /* data-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 86837 }, /* data-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 86746 }, /* data-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 86660 }, /* data-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 92991 }, /* data-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 92905 }, /* data-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 92744 }, /* data-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 89725 }, /* data-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 90112 }, /* data-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 90310 }, /* data-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 90211 }, /* data-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 90016 }, /* data-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 89914 }, /* data-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 89817 }, /* data-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 90407 }, /* data-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 90802 }, /* data-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 91004 }, /* data-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 90903 }, /* data-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 90704 }, /* data-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 90600 }, /* data-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 90501 }, /* data-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 87192 }, /* data-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 87531 }, /* data-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 87709 }, /* data-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 87618 }, /* data-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 87447 }, /* data-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 87357 }, /* data-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 87272 }, /* data-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 92659 }, /* data-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 92579 }, /* data-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 91841 }, /* data-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 92260 }, /* data-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 92474 }, /* data-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 92367 }, /* data-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 92156 }, /* data-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 92046 }, /* data-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 91941 }, /* data-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 91103 }, /* data-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 91522 }, /* data-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 91736 }, /* data-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 91629 }, /* data-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 91418 }, /* data-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 91308 }, /* data-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 91203 }, /* data-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 87798 }, /* data-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 88161 }, /* data-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 88347 }, /* data-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 88254 }, /* data-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 88071 }, /* data-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 87975 }, /* data-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 87884 }, /* data-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 88438 }, /* data-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 88805 }, /* data-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 88993 }, /* data-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 88899 }, /* data-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 88714 }, /* data-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 88617 }, /* data-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 88525 }, /* data-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 89085 }, /* data-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 89448 }, /* data-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 89634 }, /* data-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 89541 }, /* data-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 89358 }, /* data-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 89262 }, /* data-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 89171 }, /* data-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 72083 }, /* dtlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 78712 }, /* dtlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 72154 }, /* dtlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 72477 }, /* dtlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 72647 }, /* dtlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 72560 }, /* dtlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00000\000\000\000\000\000 */ -{ 72397 }, /* dtlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 72311 }, /* dtlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 72230 }, /* dtlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 72732 }, /* dtlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00000\000\000\000\000\000 */ -{ 73059 }, /* dtlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 73231 }, /* dtlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 73143 }, /* dtlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 72978 }, /* dtlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 72891 }, /* dtlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 72809 }, /* dtlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 78872 }, /* dtlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 78790 }, /* dtlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 78637 }, /* dtlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 75738 }, /* dtlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 76109 }, /* dtlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 76299 }, /* dtlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 76204 }, /* dtlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00000\000\000\000\000\000 */ -{ 76017 }, /* dtlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 75919 }, /* dtlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 75826 }, /* dtlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 76392 }, /* dtlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00000\000\000\000\000\000 */ -{ 76771 }, /* dtlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 76965 }, /* dtlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 76868 }, /* dtlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 76677 }, /* dtlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 76577 }, /* dtlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 76482 }, /* dtlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 73317 }, /* dtlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 73640 }, /* dtlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 73810 }, /* dtlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 73723 }, /* dtlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003\000\00010\000\000\000\000\000 */ -{ 73560 }, /* dtlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 73474 }, /* dtlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 73393 }, /* dtlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 78556 }, /* dtlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 78480 }, /* dtlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\00010\000\000\000\000\000 */ -{ 77770 }, /* dtlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 78173 }, /* dtlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 78379 }, /* dtlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 78276 }, /* dtlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 78073 }, /* dtlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 77967 }, /* dtlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 77866 }, /* dtlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 77060 }, /* dtlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 77463 }, /* dtlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 77669 }, /* dtlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 77566 }, /* dtlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache-config=0x10203\000\00010\000\000\000\000\000 */ -{ 77363 }, /* dtlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 77257 }, /* dtlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 77156 }, /* dtlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-config=0x203\000\00010\000\000\000\000\000 */ -{ 73895 }, /* dtlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 74242 }, /* dtlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 74420 }, /* dtlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 74331 }, /* dtlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00000\000\000\000\000\000 */ -{ 74156 }, /* dtlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 74064 }, /* dtlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 73977 }, /* dtlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 74507 }, /* dtlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00000\000\000\000\000\000 */ -{ 74858 }, /* dtlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 75038 }, /* dtlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 74948 }, /* dtlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 74771 }, /* dtlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 74678 }, /* dtlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 74590 }, /* dtlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 75126 }, /* dtlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 75473 }, /* dtlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 75651 }, /* dtlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 75562 }, /* dtlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-config=0x10103\000\00010\000\000\000\000\000 */ -{ 75387 }, /* dtlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 75295 }, /* dtlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 75208 }, /* dtlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x103\000\00010\000\000\000\000\000 */ -{ 95555 }, /* i-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 97799 }, /* i-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 95634 }, /* i-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 95989 }, /* i-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 96175 }, /* i-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 96080 }, /* i-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 95901 }, /* i-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 95807 }, /* i-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 95718 }, /* i-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 96268 }, /* i-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 96627 }, /* i-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 96815 }, /* i-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 96719 }, /* i-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 96538 }, /* i-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 96443 }, /* i-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 96353 }, /* i-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 97975 }, /* i-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 97885 }, /* i-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 97716 }, /* i-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 96909 }, /* i-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 97264 }, /* i-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 97450 }, /* i-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 97355 }, /* i-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 97176 }, /* i-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 97082 }, /* i-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 96993 }, /* i-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 97627 }, /* i-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 97543 }, /* i-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 123247 }, /* idle-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of stalled-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000 */ -{ 122945 }, /* idle-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of stalled-cycles-fronted]\000legacy-hardware-config=7\000\00000\000\000\000\000\000 */ -{ 98063 }, /* instruction-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 100557 }, /* instruction-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 98152 }, /* instruction-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 98547 }, /* instruction-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 98753 }, /* instruction-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 98648 }, /* instruction-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 98449 }, /* instruction-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 98345 }, /* instruction-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 98246 }, /* instruction-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 98856 }, /* instruction-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 99255 }, /* instruction-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 99463 }, /* instruction-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 99357 }, /* instruction-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 99156 }, /* instruction-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 99051 }, /* instruction-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 98951 }, /* instruction-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 100753 }, /* instruction-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 100653 }, /* instruction-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 100464 }, /* instruction-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 99567 }, /* instruction-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 99962 }, /* instruction-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 100168 }, /* instruction-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 100063 }, /* instruction-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 99864 }, /* instruction-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 99760 }, /* instruction-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 99661 }, /* instruction-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 100365 }, /* instruction-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 100271 }, /* instruction-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 121629 }, /* instructions\000legacy hardware\000Retired instructions. Be careful, these can be affected by various issues, most notably hardware interrupt counts\000legacy-hardware-config=1\000\00000\000\000\000\000\000 */ -{ 93075 }, /* itlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 95294 }, /* itlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 93153 }, /* itlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 93504 }, /* itlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 93688 }, /* itlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 93594 }, /* itlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00000\000\000\000\000\000 */ -{ 93417 }, /* itlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 93324 }, /* itlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 93236 }, /* itlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 93780 }, /* itlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00000\000\000\000\000\000 */ -{ 94135 }, /* itlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 94321 }, /* itlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 94226 }, /* itlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 94047 }, /* itlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 93953 }, /* itlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 93864 }, /* itlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 95468 }, /* itlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 95379 }, /* itlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 95212 }, /* itlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 94414 }, /* itlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 94765 }, /* itlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 94949 }, /* itlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 94855 }, /* itlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=0x10004\000\00010\000\000\000\000\000 */ -{ 94678 }, /* itlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 94585 }, /* itlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 94497 }, /* itlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 95124 }, /* itlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 95041 }, /* itlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\000\00010\000\000\000\000\000 */ -{ 8037 }, /* l1-d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 15406 }, /* l1-d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 8118 }, /* l1-d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 8481 }, /* l1-d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 8671 }, /* l1-d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 8574 }, /* l1-d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 8391 }, /* l1-d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 8295 }, /* l1-d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 8204 }, /* l1-d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 8766 }, /* l1-d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 9133 }, /* l1-d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 9325 }, /* l1-d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 9227 }, /* l1-d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 9042 }, /* l1-d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 8945 }, /* l1-d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 8853 }, /* l1-d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 15586 }, /* l1-d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 15494 }, /* l1-d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 15321 }, /* l1-d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 12122 }, /* l1-d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 12533 }, /* l1-d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 12743 }, /* l1-d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 12638 }, /* l1-d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 12431 }, /* l1-d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 12323 }, /* l1-d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 12220 }, /* l1-d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 12846 }, /* l1-d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 13265 }, /* l1-d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 13479 }, /* l1-d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 13372 }, /* l1-d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 13161 }, /* l1-d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 13051 }, /* l1-d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 12946 }, /* l1-d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 9421 }, /* l1-d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 9784 }, /* l1-d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 9974 }, /* l1-d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 9877 }, /* l1-d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 9694 }, /* l1-d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 9598 }, /* l1-d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 9507 }, /* l1-d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 15230 }, /* l1-d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 15144 }, /* l1-d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 14364 }, /* l1-d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 14807 }, /* l1-d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 15033 }, /* l1-d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 14920 }, /* l1-d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 14697 }, /* l1-d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 14581 }, /* l1-d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 14470 }, /* l1-d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 13584 }, /* l1-d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 14027 }, /* l1-d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 14253 }, /* l1-d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 14140 }, /* l1-d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 13917 }, /* l1-d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 13801 }, /* l1-d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 13690 }, /* l1-d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 10069 }, /* l1-d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 10456 }, /* l1-d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 10654 }, /* l1-d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 10555 }, /* l1-d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 10360 }, /* l1-d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 10258 }, /* l1-d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 10161 }, /* l1-d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 10751 }, /* l1-d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 11142 }, /* l1-d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 11342 }, /* l1-d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 11242 }, /* l1-d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 11045 }, /* l1-d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 10942 }, /* l1-d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 10844 }, /* l1-d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 11440 }, /* l1-d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 11827 }, /* l1-d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 12025 }, /* l1-d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 11926 }, /* l1-d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 11731 }, /* l1-d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 11629 }, /* l1-d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 11532 }, /* l1-d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 23238 }, /* l1-data\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 30829 }, /* l1-data-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 23322 }, /* l1-data-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 23697 }, /* l1-data-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 23893 }, /* l1-data-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 23793 }, /* l1-data-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 23604 }, /* l1-data-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 23505 }, /* l1-data-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 23411 }, /* l1-data-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 23991 }, /* l1-data-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 24370 }, /* l1-data-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 24568 }, /* l1-data-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 24467 }, /* l1-data-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 24276 }, /* l1-data-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 24176 }, /* l1-data-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 24081 }, /* l1-data-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 31015 }, /* l1-data-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 30920 }, /* l1-data-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 30741 }, /* l1-data-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 27452 }, /* l1-data-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 27875 }, /* l1-data-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 28091 }, /* l1-data-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 27983 }, /* l1-data-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 27770 }, /* l1-data-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 27659 }, /* l1-data-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 27553 }, /* l1-data-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 28197 }, /* l1-data-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 28628 }, /* l1-data-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 28848 }, /* l1-data-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 28738 }, /* l1-data-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 28521 }, /* l1-data-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 28408 }, /* l1-data-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 28300 }, /* l1-data-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 24667 }, /* l1-data-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 25042 }, /* l1-data-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 25238 }, /* l1-data-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 25138 }, /* l1-data-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 24949 }, /* l1-data-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 24850 }, /* l1-data-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 24756 }, /* l1-data-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 30647 }, /* l1-data-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 30558 }, /* l1-data-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 29757 }, /* l1-data-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 30212 }, /* l1-data-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 30444 }, /* l1-data-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 30328 }, /* l1-data-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 30099 }, /* l1-data-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 29980 }, /* l1-data-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 29866 }, /* l1-data-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 28956 }, /* l1-data-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 29411 }, /* l1-data-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 29643 }, /* l1-data-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 29527 }, /* l1-data-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 29298 }, /* l1-data-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 29179 }, /* l1-data-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 29065 }, /* l1-data-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 25336 }, /* l1-data-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 25735 }, /* l1-data-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 25939 }, /* l1-data-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 25837 }, /* l1-data-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 25636 }, /* l1-data-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 25531 }, /* l1-data-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 25431 }, /* l1-data-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 26039 }, /* l1-data-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 26442 }, /* l1-data-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 26648 }, /* l1-data-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 26545 }, /* l1-data-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 26342 }, /* l1-data-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 26236 }, /* l1-data-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 26135 }, /* l1-data-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 26749 }, /* l1-data-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 27148 }, /* l1-data-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 27352 }, /* l1-data-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 27250 }, /* l1-data-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 27049 }, /* l1-data-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 26944 }, /* l1-data-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 26844 }, /* l1-data-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 13 }, /* l1-dcache\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 7752 }, /* l1-dcache-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 99 }, /* l1-dcache-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 482 }, /* l1-dcache-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 682 }, /* l1-dcache-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 580 }, /* l1-dcache-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00000\000\000\000\000\000 */ -{ 387 }, /* l1-dcache-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 286 }, /* l1-dcache-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 190 }, /* l1-dcache-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 782 }, /* l1-dcache-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00000\000\000\000\000\000 */ -{ 1169 }, /* l1-dcache-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 1371 }, /* l1-dcache-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 1268 }, /* l1-dcache-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 1073 }, /* l1-dcache-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 971 }, /* l1-dcache-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 874 }, /* l1-dcache-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 7942 }, /* l1-dcache-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 7845 }, /* l1-dcache-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 7662 }, /* l1-dcache-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 4313 }, /* l1-dcache-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 4744 }, /* l1-dcache-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 4964 }, /* l1-dcache-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 4854 }, /* l1-dcache-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00000\000\000\000\000\000 */ -{ 4637 }, /* l1-dcache-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 4524 }, /* l1-dcache-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 4416 }, /* l1-dcache-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 5072 }, /* l1-dcache-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00000\000\000\000\000\000 */ -{ 5511 }, /* l1-dcache-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 5735 }, /* l1-dcache-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 5623 }, /* l1-dcache-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 5402 }, /* l1-dcache-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 5287 }, /* l1-dcache-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 5177 }, /* l1-dcache-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 1472 }, /* l1-dcache-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 1855 }, /* l1-dcache-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 2055 }, /* l1-dcache-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 1953 }, /* l1-dcache-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 1760 }, /* l1-dcache-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 1659 }, /* l1-dcache-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 1563 }, /* l1-dcache-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 7566 }, /* l1-dcache-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 7475 }, /* l1-dcache-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 6660 }, /* l1-dcache-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 7123 }, /* l1-dcache-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 7359 }, /* l1-dcache-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 7241 }, /* l1-dcache-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 7008 }, /* l1-dcache-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 6887 }, /* l1-dcache-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 6771 }, /* l1-dcache-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 5845 }, /* l1-dcache-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 6308 }, /* l1-dcache-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 6544 }, /* l1-dcache-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 6426 }, /* l1-dcache-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 6193 }, /* l1-dcache-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 6072 }, /* l1-dcache-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 5956 }, /* l1-dcache-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 2155 }, /* l1-dcache-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 2562 }, /* l1-dcache-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 2770 }, /* l1-dcache-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 2666 }, /* l1-dcache-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00000\000\000\000\000\000 */ -{ 2461 }, /* l1-dcache-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 2354 }, /* l1-dcache-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 2252 }, /* l1-dcache-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 2872 }, /* l1-dcache-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00000\000\000\000\000\000 */ -{ 3283 }, /* l1-dcache-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 3493 }, /* l1-dcache-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 3388 }, /* l1-dcache-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 3181 }, /* l1-dcache-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 3073 }, /* l1-dcache-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 2970 }, /* l1-dcache-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 3596 }, /* l1-dcache-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 4003 }, /* l1-dcache-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 4211 }, /* l1-dcache-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 4107 }, /* l1-dcache-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 3902 }, /* l1-dcache-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 3795 }, /* l1-dcache-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 3693 }, /* l1-dcache-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 37366 }, /* l1-i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 43053 }, /* l1-i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 37454 }, /* l1-i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 37845 }, /* l1-i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 38049 }, /* l1-i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 37945 }, /* l1-i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 37748 }, /* l1-i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 37645 }, /* l1-i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 37547 }, /* l1-i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 38151 }, /* l1-i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 38546 }, /* l1-i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 38752 }, /* l1-i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 38647 }, /* l1-i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 38448 }, /* l1-i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 38344 }, /* l1-i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 38245 }, /* l1-i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 43247 }, /* l1-i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 43148 }, /* l1-i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 42961 }, /* l1-i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 39552 }, /* l1-i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 39991 }, /* l1-i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 40215 }, /* l1-i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 40103 }, /* l1-i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 39882 }, /* l1-i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 39767 }, /* l1-i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 39657 }, /* l1-i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 40325 }, /* l1-i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 40772 }, /* l1-i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 41000 }, /* l1-i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 40886 }, /* l1-i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 40661 }, /* l1-i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 40544 }, /* l1-i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 40432 }, /* l1-i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 38855 }, /* l1-i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 39246 }, /* l1-i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 39450 }, /* l1-i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 39346 }, /* l1-i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 39149 }, /* l1-i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 39046 }, /* l1-i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 38948 }, /* l1-i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 42863 }, /* l1-i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 42770 }, /* l1-i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 41941 }, /* l1-i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 42412 }, /* l1-i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 42652 }, /* l1-i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 42532 }, /* l1-i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 42295 }, /* l1-i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 42172 }, /* l1-i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 42054 }, /* l1-i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 41112 }, /* l1-i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 41583 }, /* l1-i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 41823 }, /* l1-i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 41703 }, /* l1-i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 41466 }, /* l1-i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 41343 }, /* l1-i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 41225 }, /* l1-i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 31108 }, /* l1-icache\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 37060 }, /* l1-icache-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 31201 }, /* l1-icache-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 31612 }, /* l1-icache-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 31826 }, /* l1-icache-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 31717 }, /* l1-icache-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00000\000\000\000\000\000 */ -{ 31510 }, /* l1-icache-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 31402 }, /* l1-icache-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 31299 }, /* l1-icache-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 31933 }, /* l1-icache-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00000\000\000\000\000\000 */ -{ 32348 }, /* l1-icache-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 32564 }, /* l1-icache-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 32454 }, /* l1-icache-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 32245 }, /* l1-icache-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 32136 }, /* l1-icache-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 32032 }, /* l1-icache-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 37264 }, /* l1-icache-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 37160 }, /* l1-icache-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 36963 }, /* l1-icache-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 33404 }, /* l1-icache-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 33863 }, /* l1-icache-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 34097 }, /* l1-icache-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 33980 }, /* l1-icache-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00000\000\000\000\000\000 */ -{ 33749 }, /* l1-icache-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 33629 }, /* l1-icache-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 33514 }, /* l1-icache-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 34212 }, /* l1-icache-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00000\000\000\000\000\000 */ -{ 34679 }, /* l1-icache-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 34917 }, /* l1-icache-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 34798 }, /* l1-icache-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 34563 }, /* l1-icache-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 34441 }, /* l1-icache-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 34324 }, /* l1-icache-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 32672 }, /* l1-icache-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 33083 }, /* l1-icache-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 33297 }, /* l1-icache-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 33188 }, /* l1-icache-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 32981 }, /* l1-icache-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 32873 }, /* l1-icache-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 32770 }, /* l1-icache-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 36860 }, /* l1-icache-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 36762 }, /* l1-icache-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 35898 }, /* l1-icache-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 36389 }, /* l1-icache-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 36639 }, /* l1-icache-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 36514 }, /* l1-icache-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 36267 }, /* l1-icache-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 36139 }, /* l1-icache-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 36016 }, /* l1-icache-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 35034 }, /* l1-icache-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 35525 }, /* l1-icache-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 35775 }, /* l1-icache-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 35650 }, /* l1-icache-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 35403 }, /* l1-icache-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 35275 }, /* l1-icache-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 35152 }, /* l1-icache-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 49266 }, /* l1-instruction\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 55483 }, /* l1-instruction-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 49364 }, /* l1-instruction-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 49795 }, /* l1-instruction-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 50019 }, /* l1-instruction-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 49905 }, /* l1-instruction-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 49688 }, /* l1-instruction-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 49575 }, /* l1-instruction-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 49467 }, /* l1-instruction-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 50131 }, /* l1-instruction-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 50566 }, /* l1-instruction-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 50792 }, /* l1-instruction-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 50677 }, /* l1-instruction-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 50458 }, /* l1-instruction-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 50344 }, /* l1-instruction-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 50235 }, /* l1-instruction-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 55697 }, /* l1-instruction-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 55588 }, /* l1-instruction-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 55381 }, /* l1-instruction-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 51672 }, /* l1-instruction-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 52151 }, /* l1-instruction-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 52395 }, /* l1-instruction-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 52273 }, /* l1-instruction-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 52032 }, /* l1-instruction-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 51907 }, /* l1-instruction-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 51787 }, /* l1-instruction-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 52515 }, /* l1-instruction-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 53002 }, /* l1-instruction-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 53250 }, /* l1-instruction-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 53126 }, /* l1-instruction-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 52881 }, /* l1-instruction-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 52754 }, /* l1-instruction-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 52632 }, /* l1-instruction-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 50905 }, /* l1-instruction-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 51336 }, /* l1-instruction-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 51560 }, /* l1-instruction-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 51446 }, /* l1-instruction-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 51229 }, /* l1-instruction-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 51116 }, /* l1-instruction-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 51008 }, /* l1-instruction-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 55273 }, /* l1-instruction-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 55170 }, /* l1-instruction-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 54271 }, /* l1-instruction-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 54782 }, /* l1-instruction-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 55042 }, /* l1-instruction-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 54912 }, /* l1-instruction-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 54655 }, /* l1-instruction-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 54522 }, /* l1-instruction-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 54394 }, /* l1-instruction-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 53372 }, /* l1-instruction-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 53883 }, /* l1-instruction-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 54143 }, /* l1-instruction-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 54013 }, /* l1-instruction-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 53756 }, /* l1-instruction-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 53623 }, /* l1-instruction-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 53495 }, /* l1-instruction-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 15676 }, /* l1d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 22971 }, /* l1d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 15756 }, /* l1d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 16115 }, /* l1d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 16303 }, /* l1d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 16207 }, /* l1d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 16026 }, /* l1d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 15931 }, /* l1d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 15841 }, /* l1d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 16397 }, /* l1d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 16760 }, /* l1d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 16950 }, /* l1d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 16853 }, /* l1d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 16670 }, /* l1d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 16574 }, /* l1d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 16483 }, /* l1d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 23149 }, /* l1d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 23058 }, /* l1d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 22887 }, /* l1d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 19718 }, /* l1d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 20125 }, /* l1d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 20333 }, /* l1d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 20229 }, /* l1d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 20024 }, /* l1d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 19917 }, /* l1d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 19815 }, /* l1d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 20435 }, /* l1d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 20850 }, /* l1d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 21062 }, /* l1d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 20956 }, /* l1d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 20747 }, /* l1d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 20638 }, /* l1d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 20534 }, /* l1d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 17045 }, /* l1d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 17404 }, /* l1d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 17592 }, /* l1d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 17496 }, /* l1d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-config=0x10000\000\00010\000\000\000\000\000 */ -{ 17315 }, /* l1d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 17220 }, /* l1d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 17130 }, /* l1d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 22797 }, /* l1d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 22712 }, /* l1d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0\000\00010\000\000\000\000\000 */ -{ 21939 }, /* l1d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 22378 }, /* l1d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 22602 }, /* l1d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 22490 }, /* l1d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 22269 }, /* l1d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 22154 }, /* l1d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 22044 }, /* l1d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 21166 }, /* l1d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 21605 }, /* l1d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 21829 }, /* l1d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 21717 }, /* l1d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misses\000legacy-cache-config=0x10200\000\00010\000\000\000\000\000 */ -{ 21496 }, /* l1d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 21381 }, /* l1d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 21271 }, /* l1d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-cache-config=0x200\000\00010\000\000\000\000\000 */ -{ 17686 }, /* l1d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 18069 }, /* l1d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 18265 }, /* l1d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 18167 }, /* l1d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 17974 }, /* l1d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 17873 }, /* l1d-store-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 17777 }, /* l1d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 18361 }, /* l1d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 18748 }, /* l1d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 18946 }, /* l1d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 18847 }, /* l1d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 18652 }, /* l1d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 18550 }, /* l1d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 18453 }, /* l1d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 19043 }, /* l1d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 19426 }, /* l1d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 19622 }, /* l1d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 19524 }, /* l1d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-cache-config=0x10100\000\00010\000\000\000\000\000 */ -{ 19331 }, /* l1d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 19230 }, /* l1d-write-reference\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 19134 }, /* l1d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-config=0x100\000\00010\000\000\000\000\000 */ -{ 43344 }, /* l1i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 48978 }, /* l1i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 43431 }, /* l1i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 43818 }, /* l1i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 44020 }, /* l1i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 43917 }, /* l1i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 43722 }, /* l1i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 43620 }, /* l1i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 43523 }, /* l1i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 44121 }, /* l1i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 44512 }, /* l1i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 44716 }, /* l1i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 44612 }, /* l1i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 44415 }, /* l1i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 44312 }, /* l1i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 44214 }, /* l1i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 49170 }, /* l1i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 49072 }, /* l1i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 48887 }, /* l1i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 45508 }, /* l1i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 45943 }, /* l1i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 46165 }, /* l1i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 46054 }, /* l1i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 45835 }, /* l1i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 45721 }, /* l1i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 45612 }, /* l1i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 46274 }, /* l1i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 46717 }, /* l1i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 46943 }, /* l1i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 46830 }, /* l1i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 46607 }, /* l1i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 46491 }, /* l1i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 46380 }, /* l1i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 44818 }, /* l1i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 45205 }, /* l1i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 45407 }, /* l1i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 45304 }, /* l1i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-cache-config=0x10001\000\00010\000\000\000\000\000 */ -{ 45109 }, /* l1i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 45007 }, /* l1i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 44910 }, /* l1i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 48790 }, /* l1i-reference\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 48698 }, /* l1i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-config=1\000\00010\000\000\000\000\000 */ -{ 47876 }, /* l1i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 48343 }, /* l1i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 48581 }, /* l1i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 48462 }, /* l1i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 48227 }, /* l1i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 48105 }, /* l1i-speculative-load-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 47988 }, /* l1i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 47054 }, /* l1i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 47521 }, /* l1i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 47759 }, /* l1i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 47640 }, /* l1i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetch misses\000legacy-cache-config=0x10201\000\00010\000\000\000\000\000 */ -{ 47405 }, /* l1i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 47283 }, /* l1i-speculative-read-reference\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 47166 }, /* l1i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch accesses\000legacy-cache-config=0x201\000\00010\000\000\000\000\000 */ -{ 63212 }, /* l2\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 71765 }, /* l2-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 63309 }, /* l2-load\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 63736 }, /* l2-load-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 63958 }, /* l2-load-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 63845 }, /* l2-load-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 63630 }, /* l2-load-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 63518 }, /* l2-load-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 63411 }, /* l2-load-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 64069 }, /* l2-loads\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 64500 }, /* l2-loads-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 64724 }, /* l2-loads-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 64610 }, /* l2-loads-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 64393 }, /* l2-loads-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 64280 }, /* l2-loads-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 64172 }, /* l2-loads-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 71977 }, /* l2-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 71869 }, /* l2-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 71664 }, /* l2-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 67985 }, /* l2-prefetch\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 68460 }, /* l2-prefetch-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 68702 }, /* l2-prefetch-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 68581 }, /* l2-prefetch-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 68342 }, /* l2-prefetch-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 68218 }, /* l2-prefetch-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 68099 }, /* l2-prefetch-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 68821 }, /* l2-prefetches\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 69304 }, /* l2-prefetches-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 69550 }, /* l2-prefetches-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 69427 }, /* l2-prefetches-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 69184 }, /* l2-prefetches-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 69058 }, /* l2-prefetches-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 68937 }, /* l2-prefetches-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 64836 }, /* l2-read\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 65263 }, /* l2-read-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 65485 }, /* l2-read-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 65372 }, /* l2-read-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 65157 }, /* l2-read-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 65045 }, /* l2-read-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 64938 }, /* l2-read-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 71557 }, /* l2-reference\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 71455 }, /* l2-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 70563 }, /* l2-speculative-load\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 71070 }, /* l2-speculative-load-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 71328 }, /* l2-speculative-load-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 71199 }, /* l2-speculative-load-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 70944 }, /* l2-speculative-load-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 70812 }, /* l2-speculative-load-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 70685 }, /* l2-speculative-load-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 69671 }, /* l2-speculative-read\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 70178 }, /* l2-speculative-read-access\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 70436 }, /* l2-speculative-read-miss\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 70307 }, /* l2-speculative-read-misses\000legacy cache\000Level 2 (or higher) last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 70052 }, /* l2-speculative-read-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 69920 }, /* l2-speculative-read-reference\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 69793 }, /* l2-speculative-read-refs\000legacy cache\000Level 2 (or higher) last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 65596 }, /* l2-store\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 66047 }, /* l2-store-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 66277 }, /* l2-store-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 66162 }, /* l2-store-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 65935 }, /* l2-store-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 65817 }, /* l2-store-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 65704 }, /* l2-store-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 66390 }, /* l2-stores\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 66845 }, /* l2-stores-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 67077 }, /* l2-stores-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 66961 }, /* l2-stores-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 66732 }, /* l2-stores-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 66613 }, /* l2-stores-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 66499 }, /* l2-stores-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 67191 }, /* l2-write\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 67642 }, /* l2-write-access\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 67872 }, /* l2-write-miss\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 67757 }, /* l2-write-misses\000legacy cache\000Level 2 (or higher) last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 67530 }, /* l2-write-ops\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 67412 }, /* l2-write-reference\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 67299 }, /* l2-write-refs\000legacy cache\000Level 2 (or higher) last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 55804 }, /* llc\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 62951 }, /* llc-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 55882 }, /* llc-load\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 56233 }, /* llc-load-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 56417 }, /* llc-load-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 56323 }, /* llc-load-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00000\000\000\000\000\000 */ -{ 56146 }, /* llc-load-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 56053 }, /* llc-load-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 55965 }, /* llc-load-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 56509 }, /* llc-loads\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00000\000\000\000\000\000 */ -{ 56864 }, /* llc-loads-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 57050 }, /* llc-loads-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 56955 }, /* llc-loads-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 56776 }, /* llc-loads-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 56682 }, /* llc-loads-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 56593 }, /* llc-loads-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 63125 }, /* llc-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 63036 }, /* llc-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 62869 }, /* llc-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 59760 }, /* llc-prefetch\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 60159 }, /* llc-prefetch-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 60363 }, /* llc-prefetch-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 60261 }, /* llc-prefetch-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00000\000\000\000\000\000 */ -{ 60060 }, /* llc-prefetch-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 59955 }, /* llc-prefetch-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 59855 }, /* llc-prefetch-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 60463 }, /* llc-prefetches\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00000\000\000\000\000\000 */ -{ 60870 }, /* llc-prefetches-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 61078 }, /* llc-prefetches-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 60974 }, /* llc-prefetches-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 60769 }, /* llc-prefetches-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 60662 }, /* llc-prefetches-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 60560 }, /* llc-prefetches-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 57143 }, /* llc-read\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 57494 }, /* llc-read-access\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 57678 }, /* llc-read-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 57584 }, /* llc-read-misses\000legacy cache\000Last level cache read misses\000legacy-cache-config=0x10002\000\00010\000\000\000\000\000 */ -{ 57407 }, /* llc-read-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 57314 }, /* llc-read-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 57226 }, /* llc-read-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 62781 }, /* llc-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 62698 }, /* llc-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\000\00010\000\000\000\000\000 */ -{ 61939 }, /* llc-speculative-load\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 62370 }, /* llc-speculative-load-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 62590 }, /* llc-speculative-load-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 62480 }, /* llc-speculative-load-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 62263 }, /* llc-speculative-load-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 62150 }, /* llc-speculative-load-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 62042 }, /* llc-speculative-load-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 61180 }, /* llc-speculative-read\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 61611 }, /* llc-speculative-read-access\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 61831 }, /* llc-speculative-read-miss\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 61721 }, /* llc-speculative-read-misses\000legacy cache\000Last level cache prefetch misses\000legacy-cache-config=0x10202\000\00010\000\000\000\000\000 */ -{ 61504 }, /* llc-speculative-read-ops\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 61391 }, /* llc-speculative-read-reference\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 61283 }, /* llc-speculative-read-refs\000legacy cache\000Last level cache prefetch accesses\000legacy-cache-config=0x202\000\00010\000\000\000\000\000 */ -{ 57770 }, /* llc-store\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 58145 }, /* llc-store-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 58337 }, /* llc-store-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 58241 }, /* llc-store-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00000\000\000\000\000\000 */ -{ 58052 }, /* llc-store-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 57953 }, /* llc-store-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 57859 }, /* llc-store-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 58431 }, /* llc-stores\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00000\000\000\000\000\000 */ -{ 58810 }, /* llc-stores-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 59004 }, /* llc-stores-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 58907 }, /* llc-stores-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 58716 }, /* llc-stores-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 58616 }, /* llc-stores-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 58521 }, /* llc-stores-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 59099 }, /* llc-write\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 59474 }, /* llc-write-access\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 59666 }, /* llc-write-miss\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 59570 }, /* llc-write-misses\000legacy cache\000Last level cache write misses\000legacy-cache-config=0x10102\000\00010\000\000\000\000\000 */ -{ 59381 }, /* llc-write-ops\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 59282 }, /* llc-write-reference\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 59188 }, /* llc-write-refs\000legacy cache\000Last level cache write accesses\000legacy-cache-config=0x102\000\00010\000\000\000\000\000 */ -{ 114128 }, /* node\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 121053 }, /* node-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 114203 }, /* node-load\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 114542 }, /* node-load-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 114720 }, /* node-load-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ -{ 114629 }, /* node-load-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00000\000\000\000\000\000 */ -{ 114458 }, /* node-load-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 114368 }, /* node-load-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 114283 }, /* node-load-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 114809 }, /* node-loads\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00000\000\000\000\000\000 */ -{ 115152 }, /* node-loads-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 115332 }, /* node-loads-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ -{ 115240 }, /* node-loads-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ -{ 115067 }, /* node-loads-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 114976 }, /* node-loads-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 114890 }, /* node-loads-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 121221 }, /* node-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ -{ 121135 }, /* node-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ -{ 120974 }, /* node-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 117955 }, /* node-prefetch\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 118342 }, /* node-prefetch-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 118540 }, /* node-prefetch-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ -{ 118441 }, /* node-prefetch-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00000\000\000\000\000\000 */ -{ 118246 }, /* node-prefetch-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 118144 }, /* node-prefetch-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 118047 }, /* node-prefetch-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 118637 }, /* node-prefetches\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00000\000\000\000\000\000 */ -{ 119032 }, /* node-prefetches-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 119234 }, /* node-prefetches-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ -{ 119133 }, /* node-prefetches-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ -{ 118934 }, /* node-prefetches-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 118830 }, /* node-prefetches-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 118731 }, /* node-prefetches-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 115422 }, /* node-read\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 115761 }, /* node-read-access\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 115939 }, /* node-read-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ -{ 115848 }, /* node-read-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0x10006\000\00010\000\000\000\000\000 */ -{ 115677 }, /* node-read-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 115587 }, /* node-read-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 115502 }, /* node-read-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 120889 }, /* node-reference\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 120809 }, /* node-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\00010\000\000\000\000\000 */ -{ 120071 }, /* node-speculative-load\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 120490 }, /* node-speculative-load-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 120704 }, /* node-speculative-load-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ -{ 120597 }, /* node-speculative-load-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ -{ 120386 }, /* node-speculative-load-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 120276 }, /* node-speculative-load-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 120171 }, /* node-speculative-load-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 119333 }, /* node-speculative-read\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 119752 }, /* node-speculative-read-access\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 119966 }, /* node-speculative-read-miss\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ -{ 119859 }, /* node-speculative-read-misses\000legacy cache\000Local memory prefetch misses\000legacy-cache-config=0x10206\000\00010\000\000\000\000\000 */ -{ 119648 }, /* node-speculative-read-ops\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 119538 }, /* node-speculative-read-reference\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 119433 }, /* node-speculative-read-refs\000legacy cache\000Local memory prefetch accesses\000legacy-cache-config=0x206\000\00010\000\000\000\000\000 */ -{ 116028 }, /* node-store\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 116391 }, /* node-store-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 116577 }, /* node-store-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ -{ 116484 }, /* node-store-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00000\000\000\000\000\000 */ -{ 116301 }, /* node-store-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 116205 }, /* node-store-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 116114 }, /* node-store-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 116668 }, /* node-stores\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00000\000\000\000\000\000 */ -{ 117035 }, /* node-stores-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 117223 }, /* node-stores-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ -{ 117129 }, /* node-stores-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ -{ 116944 }, /* node-stores-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 116847 }, /* node-stores-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 116755 }, /* node-stores-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 117315 }, /* node-write\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 117678 }, /* node-write-access\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 117864 }, /* node-write-miss\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ -{ 117771 }, /* node-write-misses\000legacy cache\000Local memory write misses\000legacy-cache-config=0x10106\000\00010\000\000\000\000\000 */ -{ 117588 }, /* node-write-ops\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 117492 }, /* node-write-reference\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 117401 }, /* node-write-refs\000legacy cache\000Local memory write accesses\000legacy-cache-config=0x106\000\00010\000\000\000\000\000 */ -{ 123400 }, /* ref-cycles\000legacy hardware\000Total cycles; not affected by CPU frequency scaling\000legacy-hardware-config=9\000\00000\000\000\000\000\000 */ -{ 123094 }, /* stalled-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This event is an alias of idle-cycles-backend]\000legacy-hardware-config=8\000\00000\000\000\000\000\000 */ -{ 122795 }, /* stalled-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This event is an alias of idle-cycles-frontend]\000legacy-hardware-config=7\000\00000\000\000\000\000\000 */ + /* bpc\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-conf... */ + { 111480 }, + /* bpc-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cac... */ + { 113849 }, + /* bpc-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache... */ + { 111564 }, + /* bpc-load-access\000legacy cache\000Branch prediction unit read accesses\000legac... */ + { 111939 }, + /* bpc-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-ca... */ + { 112135 }, + /* bpc-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-... */ + { 112035 }, + /* bpc-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-c... */ + { 111846 }, + /* bpc-load-reference\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 111747 }, + /* bpc-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 111653 }, + /* bpc-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cach... */ + { 112233 }, + /* bpc-loads-access\000legacy cache\000Branch prediction unit read accesses\000lega... */ + { 112612 }, + /* bpc-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-c... */ + { 112810 }, + /* bpc-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy... */ + { 112709 }, + /* bpc-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 112518 }, + /* bpc-loads-reference\000legacy cache\000Branch prediction unit read accesses\000l... */ + { 112418 }, + /* bpc-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy... */ + { 112323 }, + /* bpc-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-c... */ + { 114035 }, + /* bpc-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache... */ + { 113940 }, + /* bpc-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-... */ + { 113761 }, + /* bpc-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache... */ + { 112909 }, + /* bpc-read-access\000legacy cache\000Branch prediction unit read accesses\000legac... */ + { 113284 }, + /* bpc-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-ca... */ + { 113480 }, + /* bpc-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-... */ + { 113380 }, + /* bpc-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-c... */ + { 113191 }, + /* bpc-read-reference\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 113092 }, + /* bpc-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 112998 }, + /* bpc-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 113667 }, + /* bpc-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache... */ + { 113578 }, + /* bpu\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-conf... */ + { 106184 }, + /* bpu-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cac... */ + { 108553 }, + /* bpu-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache... */ + { 106268 }, + /* bpu-load-access\000legacy cache\000Branch prediction unit read accesses\000legac... */ + { 106643 }, + /* bpu-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-ca... */ + { 106839 }, + /* bpu-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-... */ + { 106739 }, + /* bpu-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-c... */ + { 106550 }, + /* bpu-load-reference\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 106451 }, + /* bpu-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 106357 }, + /* bpu-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cach... */ + { 106937 }, + /* bpu-loads-access\000legacy cache\000Branch prediction unit read accesses\000lega... */ + { 107316 }, + /* bpu-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-c... */ + { 107514 }, + /* bpu-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy... */ + { 107413 }, + /* bpu-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 107222 }, + /* bpu-loads-reference\000legacy cache\000Branch prediction unit read accesses\000l... */ + { 107122 }, + /* bpu-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy... */ + { 107027 }, + /* bpu-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-c... */ + { 108739 }, + /* bpu-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache... */ + { 108644 }, + /* bpu-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-... */ + { 108465 }, + /* bpu-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache... */ + { 107613 }, + /* bpu-read-access\000legacy cache\000Branch prediction unit read accesses\000legac... */ + { 107988 }, + /* bpu-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-ca... */ + { 108184 }, + /* bpu-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-... */ + { 108084 }, + /* bpu-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-c... */ + { 107895 }, + /* bpu-read-reference\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 107796 }, + /* bpu-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 107702 }, + /* bpu-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 108371 }, + /* bpu-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache... */ + { 108282 }, + /* branch\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-c... */ + { 100851 }, + /* branch-access\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 103295 }, + /* branch-instructions\000legacy hardware\000Retired branch instructions [This even... */ + { 122452 }, + /* branch-load\000legacy cache\000Branch prediction unit read accesses\000legacy-ca... */ + { 100938 }, + /* branch-load-access\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 101325 }, + /* branch-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy... */ + { 101527 }, + /* branch-load-misses\000legacy cache\000Branch prediction unit read misses\000lega... */ + { 101424 }, + /* branch-load-ops\000legacy cache\000Branch prediction unit read accesses\000legac... */ + { 101229 }, + /* branch-load-reference\000legacy cache\000Branch prediction unit read accesses\00... */ + { 101127 }, + /* branch-load-refs\000legacy cache\000Branch prediction unit read accesses\000lega... */ + { 101030 }, + /* branch-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-c... */ + { 101628 }, + /* branch-loads-access\000legacy cache\000Branch prediction unit read accesses\000l... */ + { 102019 }, + /* branch-loads-miss\000legacy cache\000Branch prediction unit read misses\000legac... */ + { 102223 }, + /* branch-loads-misses\000legacy cache\000Branch prediction unit read misses\000leg... */ + { 102119 }, + /* branch-loads-ops\000legacy cache\000Branch prediction unit read accesses\000lega... */ + { 101922 }, + /* branch-loads-reference\000legacy cache\000Branch prediction unit read accesses\0... */ + { 101819 }, + /* branch-loads-refs\000legacy cache\000Branch prediction unit read accesses\000leg... */ + { 101721 }, + /* branch-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cach... */ + { 103389 }, + /* branch-misses\000legacy hardware\000Mispredicted branch instructions\000legacy-h... */ + { 122586 }, + /* branch-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cac... */ + { 103204 }, + /* branch-read\000legacy cache\000Branch prediction unit read accesses\000legacy-ca... */ + { 102325 }, + /* branch-read-access\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 102712 }, + /* branch-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy... */ + { 102914 }, + /* branch-read-misses\000legacy cache\000Branch prediction unit read misses\000lega... */ + { 102811 }, + /* branch-read-ops\000legacy cache\000Branch prediction unit read accesses\000legac... */ + { 102616 }, + /* branch-read-reference\000legacy cache\000Branch prediction unit read accesses\00... */ + { 102514 }, + /* branch-read-refs\000legacy cache\000Branch prediction unit read accesses\000lega... */ + { 102417 }, + /* branch-reference\000legacy cache\000Branch prediction unit read accesses\000lega... */ + { 103107 }, + /* branch-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-ca... */ + { 103015 }, + /* branches\000legacy hardware\000Retired branch instructions [This event is an ali... */ + { 122318 }, + /* branches-access\000legacy cache\000Branch prediction unit read accesses\000legac... */ + { 105890 }, + /* branches-load\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 103485 }, + /* branches-load-access\000legacy cache\000Branch prediction unit read accesses\000... */ + { 103880 }, + /* branches-load-miss\000legacy cache\000Branch prediction unit read misses\000lega... */ + { 104086 }, + /* branches-load-misses\000legacy cache\000Branch prediction unit read misses\000le... */ + { 103981 }, + /* branches-load-ops\000legacy cache\000Branch prediction unit read accesses\000leg... */ + { 103782 }, + /* branches-load-reference\000legacy cache\000Branch prediction unit read accesses\... */ + { 103678 }, + /* branches-load-refs\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 103579 }, + /* branches-loads\000legacy cache\000Branch prediction unit read accesses\000legacy... */ + { 104189 }, + /* branches-loads-access\000legacy cache\000Branch prediction unit read accesses\00... */ + { 104588 }, + /* branches-loads-miss\000legacy cache\000Branch prediction unit read misses\000leg... */ + { 104796 }, + /* branches-loads-misses\000legacy cache\000Branch prediction unit read misses\000l... */ + { 104690 }, + /* branches-loads-ops\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 104489 }, + /* branches-loads-reference\000legacy cache\000Branch prediction unit read accesses... */ + { 104384 }, + /* branches-loads-refs\000legacy cache\000Branch prediction unit read accesses\000l... */ + { 104284 }, + /* branches-miss\000legacy cache\000Branch prediction unit read misses\000legacy-ca... */ + { 106086 }, + /* branches-misses\000legacy cache\000Branch prediction unit read misses\000legacy-... */ + { 105986 }, + /* branches-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-c... */ + { 105797 }, + /* branches-read\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 104900 }, + /* branches-read-access\000legacy cache\000Branch prediction unit read accesses\000... */ + { 105295 }, + /* branches-read-miss\000legacy cache\000Branch prediction unit read misses\000lega... */ + { 105501 }, + /* branches-read-misses\000legacy cache\000Branch prediction unit read misses\000le... */ + { 105396 }, + /* branches-read-ops\000legacy cache\000Branch prediction unit read accesses\000leg... */ + { 105197 }, + /* branches-read-reference\000legacy cache\000Branch prediction unit read accesses\... */ + { 105093 }, + /* branches-read-refs\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 104994 }, + /* branches-reference\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 105698 }, + /* branches-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 105604 }, + /* btb\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-conf... */ + { 108832 }, + /* btb-access\000legacy cache\000Branch prediction unit read accesses\000legacy-cac... */ + { 111201 }, + /* btb-load\000legacy cache\000Branch prediction unit read accesses\000legacy-cache... */ + { 108916 }, + /* btb-load-access\000legacy cache\000Branch prediction unit read accesses\000legac... */ + { 109291 }, + /* btb-load-miss\000legacy cache\000Branch prediction unit read misses\000legacy-ca... */ + { 109487 }, + /* btb-load-misses\000legacy cache\000Branch prediction unit read misses\000legacy-... */ + { 109387 }, + /* btb-load-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-c... */ + { 109198 }, + /* btb-load-reference\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 109099 }, + /* btb-load-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 109005 }, + /* btb-loads\000legacy cache\000Branch prediction unit read accesses\000legacy-cach... */ + { 109585 }, + /* btb-loads-access\000legacy cache\000Branch prediction unit read accesses\000lega... */ + { 109964 }, + /* btb-loads-miss\000legacy cache\000Branch prediction unit read misses\000legacy-c... */ + { 110162 }, + /* btb-loads-misses\000legacy cache\000Branch prediction unit read misses\000legacy... */ + { 110061 }, + /* btb-loads-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 109870 }, + /* btb-loads-reference\000legacy cache\000Branch prediction unit read accesses\000l... */ + { 109770 }, + /* btb-loads-refs\000legacy cache\000Branch prediction unit read accesses\000legacy... */ + { 109675 }, + /* btb-miss\000legacy cache\000Branch prediction unit read misses\000legacy-cache-c... */ + { 111387 }, + /* btb-misses\000legacy cache\000Branch prediction unit read misses\000legacy-cache... */ + { 111292 }, + /* btb-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-cache-... */ + { 111113 }, + /* btb-read\000legacy cache\000Branch prediction unit read accesses\000legacy-cache... */ + { 110261 }, + /* btb-read-access\000legacy cache\000Branch prediction unit read accesses\000legac... */ + { 110636 }, + /* btb-read-miss\000legacy cache\000Branch prediction unit read misses\000legacy-ca... */ + { 110832 }, + /* btb-read-misses\000legacy cache\000Branch prediction unit read misses\000legacy-... */ + { 110732 }, + /* btb-read-ops\000legacy cache\000Branch prediction unit read accesses\000legacy-c... */ + { 110543 }, + /* btb-read-reference\000legacy cache\000Branch prediction unit read accesses\000le... */ + { 110444 }, + /* btb-read-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 110350 }, + /* btb-reference\000legacy cache\000Branch prediction unit read accesses\000legacy-... */ + { 111019 }, + /* btb-refs\000legacy cache\000Branch prediction unit read accesses\000legacy-cache... */ + { 110930 }, + /* bus-cycles\000legacy hardware\000Bus cycles, which can be different from total c... */ + { 122682 }, + /* cache-misses\000legacy hardware\000Cache misses. Usually this indicates Last Lev... */ + { 122075 }, + /* cache-references\000legacy hardware\000Cache accesses. Usually this indicates La... */ + { 121805 }, + /* cpu-cycles\000legacy hardware\000Total cycles. Be wary of what happens during CP... */ + { 121305 }, + /* cycles\000legacy hardware\000Total cycles. Be wary of what happens during CPU fr... */ + { 121467 }, + /* d-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\000... */ + { 78952 }, + /* d-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\... */ + { 85655 }, + /* d-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\00... */ + { 79024 }, + /* d-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-conf... */ + { 79351 }, + /* d-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0... */ + { 79523 }, + /* d-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config... */ + { 79435 }, + /* d-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=... */ + { 79270 }, + /* d-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-c... */ + { 79183 }, + /* d-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config... */ + { 79101 }, + /* d-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\0... */ + { 79609 }, + /* d-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-con... */ + { 79940 }, + /* d-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=... */ + { 80114 }, + /* d-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-confi... */ + { 80025 }, + /* d-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config... */ + { 79858 }, + /* d-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-... */ + { 79770 }, + /* d-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-confi... */ + { 79687 }, + /* d-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x1000... */ + { 85817 }, + /* d-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10... */ + { 85734 }, + /* d-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000... */ + { 85579 }, + /* d-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-con... */ + { 82650 }, + /* d-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-ca... */ + { 83025 }, + /* d-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-... */ + { 83217 }, + /* d-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cach... */ + { 83121 }, + /* d-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache... */ + { 82932 }, + /* d-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy... */ + { 82833 }, + /* d-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cach... */ + { 82739 }, + /* d-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-c... */ + { 83311 }, + /* d-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-... */ + { 83694 }, + /* d-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cach... */ + { 83890 }, + /* d-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-ca... */ + { 83792 }, + /* d-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cac... */ + { 83599 }, + /* d-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000lega... */ + { 83498 }, + /* d-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-ca... */ + { 83402 }, + /* d-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\00... */ + { 80201 }, + /* d-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-conf... */ + { 80528 }, + /* d-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0... */ + { 80700 }, + /* d-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config... */ + { 80612 }, + /* d-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=... */ + { 80447 }, + /* d-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-c... */ + { 80360 }, + /* d-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config... */ + { 80278 }, + /* d-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config... */ + { 85497 }, + /* d-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\00... */ + { 85420 }, + /* d-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-c... */ + { 84703 }, + /* d-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000l... */ + { 85110 }, + /* d-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legac... */ + { 85318 }, + /* d-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000leg... */ + { 85214 }, + /* d-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000lega... */ + { 85009 }, + /* d-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\0... */ + { 84902 }, + /* d-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000leg... */ + { 84800 }, + /* d-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-c... */ + { 83986 }, + /* d-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000l... */ + { 84393 }, + /* d-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legac... */ + { 84601 }, + /* d-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000leg... */ + { 84497 }, + /* d-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000lega... */ + { 84292 }, + /* d-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\0... */ + { 84185 }, + /* d-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000leg... */ + { 84083 }, + /* d-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x... */ + { 80786 }, + /* d-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-co... */ + { 81137 }, + /* d-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config... */ + { 81317 }, + /* d-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-conf... */ + { 81227 }, + /* d-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-confi... */ + { 81050 }, + /* d-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache... */ + { 80957 }, + /* d-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-conf... */ + { 80869 }, + /* d-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0... */ + { 81405 }, + /* d-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-c... */ + { 81760 }, + /* d-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-confi... */ + { 81942 }, + /* d-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-con... */ + { 81851 }, + /* d-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-conf... */ + { 81672 }, + /* d-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cach... */ + { 81578 }, + /* d-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-con... */ + { 81489 }, + /* d-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x... */ + { 82031 }, + /* d-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-co... */ + { 82382 }, + /* d-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config... */ + { 82562 }, + /* d-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-conf... */ + { 82472 }, + /* d-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-confi... */ + { 82295 }, + /* d-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache... */ + { 82202 }, + /* d-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-conf... */ + { 82114 }, + /* data-tlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\... */ + { 85898 }, + /* data-tlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config... */ + { 92823 }, + /* data-tlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3... */ + { 85973 }, + /* data-tlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-c... */ + { 86312 }, + /* data-tlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-confi... */ + { 86490 }, + /* data-tlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-con... */ + { 86399 }, + /* data-tlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-conf... */ + { 86228 }, + /* data-tlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cach... */ + { 86138 }, + /* data-tlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-con... */ + { 86053 }, + /* data-tlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=... */ + { 86579 }, + /* data-tlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-... */ + { 86922 }, + /* data-tlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-conf... */ + { 87102 }, + /* data-tlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-co... */ + { 87010 }, + /* data-tlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-con... */ + { 86837 }, + /* data-tlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cac... */ + { 86746 }, + /* data-tlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-co... */ + { 86660 }, + /* data-tlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x1... */ + { 92991 }, + /* data-tlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0... */ + { 92905 }, + /* data-tlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\... */ + { 92744 }, + /* data-tlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-... */ + { 89725 }, + /* data-tlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy... */ + { 90112 }, + /* data-tlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cac... */ + { 90310 }, + /* data-tlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-c... */ + { 90211 }, + /* data-tlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-ca... */ + { 90016 }, + /* data-tlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000leg... */ + { 89914 }, + /* data-tlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-c... */ + { 89817 }, + /* data-tlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cach... */ + { 90407 }, + /* data-tlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000lega... */ + { 90802 }, + /* data-tlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-c... */ + { 91004 }, + /* data-tlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy... */ + { 90903 }, + /* data-tlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-... */ + { 90704 }, + /* data-tlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000l... */ + { 90600 }, + /* data-tlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy... */ + { 90501 }, + /* data-tlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3... */ + { 87192 }, + /* data-tlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-c... */ + { 87531 }, + /* data-tlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-confi... */ + { 87709 }, + /* data-tlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-con... */ + { 87618 }, + /* data-tlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-conf... */ + { 87447 }, + /* data-tlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cach... */ + { 87357 }, + /* data-tlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-con... */ + { 87272 }, + /* data-tlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-con... */ + { 92659 }, + /* data-tlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3... */ + { 92579 }, + /* data-tlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legac... */ + { 91841 }, + /* data-tlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\0... */ + { 92260 }, + /* data-tlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000le... */ + { 92474 }, + /* data-tlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000... */ + { 92367 }, + /* data-tlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000l... */ + { 92156 }, + /* data-tlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesse... */ + { 92046 }, + /* data-tlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000... */ + { 91941 }, + /* data-tlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legac... */ + { 91103 }, + /* data-tlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\0... */ + { 91522 }, + /* data-tlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000le... */ + { 91736 }, + /* data-tlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000... */ + { 91629 }, + /* data-tlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000l... */ + { 91418 }, + /* data-tlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesse... */ + { 91308 }, + /* data-tlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000... */ + { 91203 }, + /* data-tlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config... */ + { 87798 }, + /* data-tlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache... */ + { 88161 }, + /* data-tlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-con... */ + { 88347 }, + /* data-tlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-c... */ + { 88254 }, + /* data-tlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-co... */ + { 88071 }, + /* data-tlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-ca... */ + { 87975 }, + /* data-tlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-c... */ + { 87884 }, + /* data-tlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-confi... */ + { 88438 }, + /* data-tlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cach... */ + { 88805 }, + /* data-tlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-co... */ + { 88993 }, + /* data-tlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-... */ + { 88899 }, + /* data-tlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-c... */ + { 88714 }, + /* data-tlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-c... */ + { 88617 }, + /* data-tlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-... */ + { 88525 }, + /* data-tlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config... */ + { 89085 }, + /* data-tlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache... */ + { 89448 }, + /* data-tlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-con... */ + { 89634 }, + /* data-tlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-c... */ + { 89541 }, + /* data-tlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-co... */ + { 89358 }, + /* data-tlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-ca... */ + { 89262 }, + /* data-tlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-c... */ + { 89171 }, + /* dtlb\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\0001... */ + { 72083 }, + /* dtlb-access\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\0... */ + { 78712 }, + /* dtlb-load\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000... */ + { 72154 }, + /* dtlb-load-access\000legacy cache\000Data TLB read accesses\000legacy-cache-confi... */ + { 72477 }, + /* dtlb-load-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x... */ + { 72647 }, + /* dtlb-load-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=... */ + { 72560 }, + /* dtlb-load-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3... */ + { 72397 }, + /* dtlb-load-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-co... */ + { 72311 }, + /* dtlb-load-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=... */ + { 72230 }, + /* dtlb-loads\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\00... */ + { 72732 }, + /* dtlb-loads-access\000legacy cache\000Data TLB read accesses\000legacy-cache-conf... */ + { 73059 }, + /* dtlb-loads-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0... */ + { 73231 }, + /* dtlb-loads-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config... */ + { 73143 }, + /* dtlb-loads-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=... */ + { 72978 }, + /* dtlb-loads-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-c... */ + { 72891 }, + /* dtlb-loads-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config... */ + { 72809 }, + /* dtlb-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x10003... */ + { 78872 }, + /* dtlb-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x100... */ + { 78790 }, + /* dtlb-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000\... */ + { 78637 }, + /* dtlb-prefetch\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-conf... */ + { 75738 }, + /* dtlb-prefetch-access\000legacy cache\000Data TLB prefetch accesses\000legacy-cac... */ + { 76109 }, + /* dtlb-prefetch-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache-c... */ + { 76299 }, + /* dtlb-prefetch-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cache... */ + { 76204 }, + /* dtlb-prefetch-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-... */ + { 76017 }, + /* dtlb-prefetch-reference\000legacy cache\000Data TLB prefetch accesses\000legacy-... */ + { 75919 }, + /* dtlb-prefetch-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cache... */ + { 75826 }, + /* dtlb-prefetches\000legacy cache\000Data TLB prefetch accesses\000legacy-cache-co... */ + { 76392 }, + /* dtlb-prefetches-access\000legacy cache\000Data TLB prefetch accesses\000legacy-c... */ + { 76771 }, + /* dtlb-prefetches-miss\000legacy cache\000Data TLB prefetch misses\000legacy-cache... */ + { 76965 }, + /* dtlb-prefetches-misses\000legacy cache\000Data TLB prefetch misses\000legacy-cac... */ + { 76868 }, + /* dtlb-prefetches-ops\000legacy cache\000Data TLB prefetch accesses\000legacy-cach... */ + { 76677 }, + /* dtlb-prefetches-reference\000legacy cache\000Data TLB prefetch accesses\000legac... */ + { 76577 }, + /* dtlb-prefetches-refs\000legacy cache\000Data TLB prefetch accesses\000legacy-cac... */ + { 76482 }, + /* dtlb-read\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000... */ + { 73317 }, + /* dtlb-read-access\000legacy cache\000Data TLB read accesses\000legacy-cache-confi... */ + { 73640 }, + /* dtlb-read-miss\000legacy cache\000Data TLB read misses\000legacy-cache-config=0x... */ + { 73810 }, + /* dtlb-read-misses\000legacy cache\000Data TLB read misses\000legacy-cache-config=... */ + { 73723 }, + /* dtlb-read-ops\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3... */ + { 73560 }, + /* dtlb-read-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-co... */ + { 73474 }, + /* dtlb-read-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=... */ + { 73393 }, + /* dtlb-reference\000legacy cache\000Data TLB read accesses\000legacy-cache-config=... */ + { 78556 }, + /* dtlb-refs\000legacy cache\000Data TLB read accesses\000legacy-cache-config=3\000... */ + { 78480 }, + /* dtlb-speculative-load\000legacy cache\000Data TLB prefetch accesses\000legacy-ca... */ + { 77770 }, + /* dtlb-speculative-load-access\000legacy cache\000Data TLB prefetch accesses\000le... */ + { 78173 }, + /* dtlb-speculative-load-miss\000legacy cache\000Data TLB prefetch misses\000legacy... */ + { 78379 }, + /* dtlb-speculative-load-misses\000legacy cache\000Data TLB prefetch misses\000lega... */ + { 78276 }, + /* dtlb-speculative-load-ops\000legacy cache\000Data TLB prefetch accesses\000legac... */ + { 78073 }, + /* dtlb-speculative-load-reference\000legacy cache\000Data TLB prefetch accesses\00... */ + { 77967 }, + /* dtlb-speculative-load-refs\000legacy cache\000Data TLB prefetch accesses\000lega... */ + { 77866 }, + /* dtlb-speculative-read\000legacy cache\000Data TLB prefetch accesses\000legacy-ca... */ + { 77060 }, + /* dtlb-speculative-read-access\000legacy cache\000Data TLB prefetch accesses\000le... */ + { 77463 }, + /* dtlb-speculative-read-miss\000legacy cache\000Data TLB prefetch misses\000legacy... */ + { 77669 }, + /* dtlb-speculative-read-misses\000legacy cache\000Data TLB prefetch misses\000lega... */ + { 77566 }, + /* dtlb-speculative-read-ops\000legacy cache\000Data TLB prefetch accesses\000legac... */ + { 77363 }, + /* dtlb-speculative-read-reference\000legacy cache\000Data TLB prefetch accesses\00... */ + { 77257 }, + /* dtlb-speculative-read-refs\000legacy cache\000Data TLB prefetch accesses\000lega... */ + { 77156 }, + /* dtlb-store\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x1... */ + { 73895 }, + /* dtlb-store-access\000legacy cache\000Data TLB write accesses\000legacy-cache-con... */ + { 74242 }, + /* dtlb-store-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=... */ + { 74420 }, + /* dtlb-store-misses\000legacy cache\000Data TLB write misses\000legacy-cache-confi... */ + { 74331 }, + /* dtlb-store-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config... */ + { 74156 }, + /* dtlb-store-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-... */ + { 74064 }, + /* dtlb-store-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-confi... */ + { 73977 }, + /* dtlb-stores\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x... */ + { 74507 }, + /* dtlb-stores-access\000legacy cache\000Data TLB write accesses\000legacy-cache-co... */ + { 74858 }, + /* dtlb-stores-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config... */ + { 75038 }, + /* dtlb-stores-misses\000legacy cache\000Data TLB write misses\000legacy-cache-conf... */ + { 74948 }, + /* dtlb-stores-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-confi... */ + { 74771 }, + /* dtlb-stores-reference\000legacy cache\000Data TLB write accesses\000legacy-cache... */ + { 74678 }, + /* dtlb-stores-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-conf... */ + { 74590 }, + /* dtlb-write\000legacy cache\000Data TLB write accesses\000legacy-cache-config=0x1... */ + { 75126 }, + /* dtlb-write-access\000legacy cache\000Data TLB write accesses\000legacy-cache-con... */ + { 75473 }, + /* dtlb-write-miss\000legacy cache\000Data TLB write misses\000legacy-cache-config=... */ + { 75651 }, + /* dtlb-write-misses\000legacy cache\000Data TLB write misses\000legacy-cache-confi... */ + { 75562 }, + /* dtlb-write-ops\000legacy cache\000Data TLB write accesses\000legacy-cache-config... */ + { 75387 }, + /* dtlb-write-reference\000legacy cache\000Data TLB write accesses\000legacy-cache-... */ + { 75295 }, + /* dtlb-write-refs\000legacy cache\000Data TLB write accesses\000legacy-cache-confi... */ + { 75208 }, + /* i-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\... */ + { 95555 }, + /* i-tlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-co... */ + { 97799 }, + /* i-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-conf... */ + { 95634 }, + /* i-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cac... */ + { 95989 }, + /* i-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-c... */ + { 96175 }, + /* i-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache... */ + { 96080 }, + /* i-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-... */ + { 95901 }, + /* i-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-... */ + { 95807 }, + /* i-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache... */ + { 95718 }, + /* i-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-con... */ + { 96268 }, + /* i-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-ca... */ + { 96627 }, + /* i-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-... */ + { 96815 }, + /* i-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cach... */ + { 96719 }, + /* i-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache... */ + { 96538 }, + /* i-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy... */ + { 96443 }, + /* i-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cach... */ + { 96353 }, + /* i-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config... */ + { 97975 }, + /* i-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-conf... */ + { 97885 }, + /* i-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-confi... */ + { 97716 }, + /* i-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-conf... */ + { 96909 }, + /* i-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cac... */ + { 97264 }, + /* i-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-c... */ + { 97450 }, + /* i-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache... */ + { 97355 }, + /* i-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-... */ + { 97176 }, + /* i-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-... */ + { 97082 }, + /* i-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache... */ + { 96993 }, + /* i-tlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache... */ + { 97627 }, + /* i-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-conf... */ + { 97543 }, + /* idle-cycles-backend\000legacy hardware\000Stalled cycles during retirement [This... */ + { 123247 }, + /* idle-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This eve... */ + { 122945 }, + /* instruction-tlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache... */ + { 98063 }, + /* instruction-tlb-access\000legacy cache\000Instruction TLB read accesses\000legac... */ + { 100557 }, + /* instruction-tlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-... */ + { 98152 }, + /* instruction-tlb-load-access\000legacy cache\000Instruction TLB read accesses\000... */ + { 98547 }, + /* instruction-tlb-load-miss\000legacy cache\000Instruction TLB read misses\000lega... */ + { 98753 }, + /* instruction-tlb-load-misses\000legacy cache\000Instruction TLB read misses\000le... */ + { 98648 }, + /* instruction-tlb-load-ops\000legacy cache\000Instruction TLB read accesses\000leg... */ + { 98449 }, + /* instruction-tlb-load-reference\000legacy cache\000Instruction TLB read accesses\... */ + { 98345 }, + /* instruction-tlb-load-refs\000legacy cache\000Instruction TLB read accesses\000le... */ + { 98246 }, + /* instruction-tlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy... */ + { 98856 }, + /* instruction-tlb-loads-access\000legacy cache\000Instruction TLB read accesses\00... */ + { 99255 }, + /* instruction-tlb-loads-miss\000legacy cache\000Instruction TLB read misses\000leg... */ + { 99463 }, + /* instruction-tlb-loads-misses\000legacy cache\000Instruction TLB read misses\000l... */ + { 99357 }, + /* instruction-tlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000le... */ + { 99156 }, + /* instruction-tlb-loads-reference\000legacy cache\000Instruction TLB read accesses... */ + { 99051 }, + /* instruction-tlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000l... */ + { 98951 }, + /* instruction-tlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-ca... */ + { 100753 }, + /* instruction-tlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-... */ + { 100653 }, + /* instruction-tlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-c... */ + { 100464 }, + /* instruction-tlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-... */ + { 99567 }, + /* instruction-tlb-read-access\000legacy cache\000Instruction TLB read accesses\000... */ + { 99962 }, + /* instruction-tlb-read-miss\000legacy cache\000Instruction TLB read misses\000lega... */ + { 100168 }, + /* instruction-tlb-read-misses\000legacy cache\000Instruction TLB read misses\000le... */ + { 100063 }, + /* instruction-tlb-read-ops\000legacy cache\000Instruction TLB read accesses\000leg... */ + { 99864 }, + /* instruction-tlb-read-reference\000legacy cache\000Instruction TLB read accesses\... */ + { 99760 }, + /* instruction-tlb-read-refs\000legacy cache\000Instruction TLB read accesses\000le... */ + { 99661 }, + /* instruction-tlb-reference\000legacy cache\000Instruction TLB read accesses\000le... */ + { 100365 }, + /* instruction-tlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-... */ + { 100271 }, + /* instructions\000legacy hardware\000Retired instructions. Be careful, these can b... */ + { 121629 }, + /* itlb\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config=4\0... */ + { 93075 }, + /* itlb-access\000legacy cache\000Instruction TLB read accesses\000legacy-cache-con... */ + { 95294 }, + /* itlb-load\000legacy cache\000Instruction TLB read accesses\000legacy-cache-confi... */ + { 93153 }, + /* itlb-load-access\000legacy cache\000Instruction TLB read accesses\000legacy-cach... */ + { 93504 }, + /* itlb-load-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-co... */ + { 93688 }, + /* itlb-load-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-... */ + { 93594 }, + /* itlb-load-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-c... */ + { 93417 }, + /* itlb-load-reference\000legacy cache\000Instruction TLB read accesses\000legacy-c... */ + { 93324 }, + /* itlb-load-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-... */ + { 93236 }, + /* itlb-loads\000legacy cache\000Instruction TLB read accesses\000legacy-cache-conf... */ + { 93780 }, + /* itlb-loads-access\000legacy cache\000Instruction TLB read accesses\000legacy-cac... */ + { 94135 }, + /* itlb-loads-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-c... */ + { 94321 }, + /* itlb-loads-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache... */ + { 94226 }, + /* itlb-loads-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-... */ + { 94047 }, + /* itlb-loads-reference\000legacy cache\000Instruction TLB read accesses\000legacy-... */ + { 93953 }, + /* itlb-loads-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache... */ + { 93864 }, + /* itlb-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-config=... */ + { 95468 }, + /* itlb-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-confi... */ + { 95379 }, + /* itlb-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-config... */ + { 95212 }, + /* itlb-read\000legacy cache\000Instruction TLB read accesses\000legacy-cache-confi... */ + { 94414 }, + /* itlb-read-access\000legacy cache\000Instruction TLB read accesses\000legacy-cach... */ + { 94765 }, + /* itlb-read-miss\000legacy cache\000Instruction TLB read misses\000legacy-cache-co... */ + { 94949 }, + /* itlb-read-misses\000legacy cache\000Instruction TLB read misses\000legacy-cache-... */ + { 94855 }, + /* itlb-read-ops\000legacy cache\000Instruction TLB read accesses\000legacy-cache-c... */ + { 94678 }, + /* itlb-read-reference\000legacy cache\000Instruction TLB read accesses\000legacy-c... */ + { 94585 }, + /* itlb-read-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-... */ + { 94497 }, + /* itlb-reference\000legacy cache\000Instruction TLB read accesses\000legacy-cache-... */ + { 95124 }, + /* itlb-refs\000legacy cache\000Instruction TLB read accesses\000legacy-cache-confi... */ + { 95041 }, + /* l1-d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=... */ + { 8037 }, + /* l1-d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-... */ + { 15406 }, + /* l1-d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-co... */ + { 8118 }, + /* l1-d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-c... */ + { 8481 }, + /* l1-d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache... */ + { 8671 }, + /* l1-d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cac... */ + { 8574 }, + /* l1-d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cach... */ + { 8391 }, + /* l1-d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legac... */ + { 8295 }, + /* l1-d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cac... */ + { 8204 }, + /* l1-d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-c... */ + { 8766 }, + /* l1-d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-... */ + { 9133 }, + /* l1-d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cach... */ + { 9325 }, + /* l1-d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-ca... */ + { 9227 }, + /* l1-d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cac... */ + { 9042 }, + /* l1-d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000lega... */ + { 8945 }, + /* l1-d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-ca... */ + { 8853 }, + /* l1-d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-conf... */ + { 15586 }, + /* l1-d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-co... */ + { 15494 }, + /* l1-d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-con... */ + { 15321 }, + /* l1-d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-... */ + { 12122 }, + /* l1-d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000... */ + { 12533 }, + /* l1-d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000lega... */ + { 12743 }, + /* l1-d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000le... */ + { 12638 }, + /* l1-d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000leg... */ + { 12431 }, + /* l1-d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\... */ + { 12323 }, + /* l1-d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000le... */ + { 12220 }, + /* l1-d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legac... */ + { 12846 }, + /* l1-d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\0... */ + { 13265 }, + /* l1-d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000le... */ + { 13479 }, + /* l1-d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000... */ + { 13372 }, + /* l1-d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000l... */ + { 13161 }, + /* l1-d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesse... */ + { 13051 }, + /* l1-d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000... */ + { 12946 }, + /* l1-d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-co... */ + { 9421 }, + /* l1-d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-c... */ + { 9784 }, + /* l1-d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache... */ + { 9974 }, + /* l1-d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cac... */ + { 9877 }, + /* l1-d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cach... */ + { 9694 }, + /* l1-d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legac... */ + { 9598 }, + /* l1-d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cac... */ + { 9507 }, + /* l1-d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cac... */ + { 15230 }, + /* l1-d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-co... */ + { 15144 }, + /* l1-d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\00... */ + { 14364 }, + /* l1-d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch acce... */ + { 14807 }, + /* l1-d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses... */ + { 15033 }, + /* l1-d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch miss... */ + { 14920 }, + /* l1-d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesse... */ + { 14697 }, + /* l1-d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch a... */ + { 14581 }, + /* l1-d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch access... */ + { 14470 }, + /* l1-d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\00... */ + { 13584 }, + /* l1-d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch acce... */ + { 14027 }, + /* l1-d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses... */ + { 14253 }, + /* l1-d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch miss... */ + { 14140 }, + /* l1-d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesse... */ + { 13917 }, + /* l1-d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch a... */ + { 13801 }, + /* l1-d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch access... */ + { 13690 }, + /* l1-d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-... */ + { 10069 }, + /* l1-d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy... */ + { 10456 }, + /* l1-d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cac... */ + { 10654 }, + /* l1-d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-c... */ + { 10555 }, + /* l1-d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-ca... */ + { 10360 }, + /* l1-d-store-reference\000legacy cache\000Level 1 data cache write accesses\000leg... */ + { 10258 }, + /* l1-d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-c... */ + { 10161 }, + /* l1-d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache... */ + { 10751 }, + /* l1-d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legac... */ + { 11142 }, + /* l1-d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-ca... */ + { 11342 }, + /* l1-d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-... */ + { 11242 }, + /* l1-d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-c... */ + { 11045 }, + /* l1-d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000le... */ + { 10942 }, + /* l1-d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-... */ + { 10844 }, + /* l1-d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-... */ + { 11440 }, + /* l1-d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy... */ + { 11827 }, + /* l1-d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cac... */ + { 12025 }, + /* l1-d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-c... */ + { 11926 }, + /* l1-d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-ca... */ + { 11731 }, + /* l1-d-write-reference\000legacy cache\000Level 1 data cache write accesses\000leg... */ + { 11629 }, + /* l1-d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-c... */ + { 11532 }, + /* l1-data\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-conf... */ + { 23238 }, + /* l1-data-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cac... */ + { 30829 }, + /* l1-data-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache... */ + { 23322 }, + /* l1-data-load-access\000legacy cache\000Level 1 data cache read accesses\000legac... */ + { 23697 }, + /* l1-data-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-ca... */ + { 23893 }, + /* l1-data-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-... */ + { 23793 }, + /* l1-data-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-c... */ + { 23604 }, + /* l1-data-load-reference\000legacy cache\000Level 1 data cache read accesses\000le... */ + { 23505 }, + /* l1-data-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-... */ + { 23411 }, + /* l1-data-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cach... */ + { 23991 }, + /* l1-data-loads-access\000legacy cache\000Level 1 data cache read accesses\000lega... */ + { 24370 }, + /* l1-data-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-c... */ + { 24568 }, + /* l1-data-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy... */ + { 24467 }, + /* l1-data-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-... */ + { 24276 }, + /* l1-data-loads-reference\000legacy cache\000Level 1 data cache read accesses\000l... */ + { 24176 }, + /* l1-data-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy... */ + { 24081 }, + /* l1-data-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-c... */ + { 31015 }, + /* l1-data-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache... */ + { 30920 }, + /* l1-data-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-... */ + { 30741 }, + /* l1-data-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000lega... */ + { 27452 }, + /* l1-data-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\... */ + { 27875 }, + /* l1-data-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000l... */ + { 28091 }, + /* l1-data-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\00... */ + { 27983 }, + /* l1-data-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000... */ + { 27770 }, + /* l1-data-prefetch-reference\000legacy cache\000Level 1 data cache prefetch access... */ + { 27659 }, + /* l1-data-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\00... */ + { 27553 }, + /* l1-data-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000le... */ + { 28197 }, + /* l1-data-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesse... */ + { 28628 }, + /* l1-data-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\00... */ + { 28848 }, + /* l1-data-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\... */ + { 28738 }, + /* l1-data-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\0... */ + { 28521 }, + /* l1-data-prefetches-reference\000legacy cache\000Level 1 data cache prefetch acce... */ + { 28408 }, + /* l1-data-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\... */ + { 28300 }, + /* l1-data-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache... */ + { 24667 }, + /* l1-data-read-access\000legacy cache\000Level 1 data cache read accesses\000legac... */ + { 25042 }, + /* l1-data-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-ca... */ + { 25238 }, + /* l1-data-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-... */ + { 25138 }, + /* l1-data-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-c... */ + { 24949 }, + /* l1-data-read-reference\000legacy cache\000Level 1 data cache read accesses\000le... */ + { 24850 }, + /* l1-data-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-... */ + { 24756 }, + /* l1-data-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-... */ + { 30647 }, + /* l1-data-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache... */ + { 30558 }, + /* l1-data-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses... */ + { 29757 }, + /* l1-data-speculative-load-access\000legacy cache\000Level 1 data cache prefetch a... */ + { 30212 }, + /* l1-data-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch mis... */ + { 30444 }, + /* l1-data-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch m... */ + { 30328 }, + /* l1-data-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch acce... */ + { 30099 }, + /* l1-data-speculative-load-reference\000legacy cache\000Level 1 data cache prefetc... */ + { 29980 }, + /* l1-data-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch acc... */ + { 29866 }, + /* l1-data-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses... */ + { 28956 }, + /* l1-data-speculative-read-access\000legacy cache\000Level 1 data cache prefetch a... */ + { 29411 }, + /* l1-data-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch mis... */ + { 29643 }, + /* l1-data-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch m... */ + { 29527 }, + /* l1-data-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch acce... */ + { 29298 }, + /* l1-data-speculative-read-reference\000legacy cache\000Level 1 data cache prefetc... */ + { 29179 }, + /* l1-data-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch acc... */ + { 29065 }, + /* l1-data-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cac... */ + { 25336 }, + /* l1-data-store-access\000legacy cache\000Level 1 data cache write accesses\000leg... */ + { 25735 }, + /* l1-data-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-... */ + { 25939 }, + /* l1-data-store-misses\000legacy cache\000Level 1 data cache write misses\000legac... */ + { 25837 }, + /* l1-data-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy... */ + { 25636 }, + /* l1-data-store-reference\000legacy cache\000Level 1 data cache write accesses\000... */ + { 25531 }, + /* l1-data-store-refs\000legacy cache\000Level 1 data cache write accesses\000legac... */ + { 25431 }, + /* l1-data-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-ca... */ + { 26039 }, + /* l1-data-stores-access\000legacy cache\000Level 1 data cache write accesses\000le... */ + { 26442 }, + /* l1-data-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy... */ + { 26648 }, + /* l1-data-stores-misses\000legacy cache\000Level 1 data cache write misses\000lega... */ + { 26545 }, + /* l1-data-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legac... */ + { 26342 }, + /* l1-data-stores-reference\000legacy cache\000Level 1 data cache write accesses\00... */ + { 26236 }, + /* l1-data-stores-refs\000legacy cache\000Level 1 data cache write accesses\000lega... */ + { 26135 }, + /* l1-data-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cac... */ + { 26749 }, + /* l1-data-write-access\000legacy cache\000Level 1 data cache write accesses\000leg... */ + { 27148 }, + /* l1-data-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-... */ + { 27352 }, + /* l1-data-write-misses\000legacy cache\000Level 1 data cache write misses\000legac... */ + { 27250 }, + /* l1-data-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy... */ + { 27049 }, + /* l1-data-write-reference\000legacy cache\000Level 1 data cache write accesses\000... */ + { 26944 }, + /* l1-data-write-refs\000legacy cache\000Level 1 data cache write accesses\000legac... */ + { 26844 }, + /* l1-dcache\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-co... */ + { 13 }, + /* l1-dcache-access\000legacy cache\000Level 1 data cache read accesses\000legacy-c... */ + { 7752 }, + /* l1-dcache-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cac... */ + { 99 }, + /* l1-dcache-load-access\000legacy cache\000Level 1 data cache read accesses\000leg... */ + { 482 }, + /* l1-dcache-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-... */ + { 682 }, + /* l1-dcache-load-misses\000legacy cache\000Level 1 data cache read misses\000legac... */ + { 580 }, + /* l1-dcache-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy... */ + { 387 }, + /* l1-dcache-load-reference\000legacy cache\000Level 1 data cache read accesses\000... */ + { 286 }, + /* l1-dcache-load-refs\000legacy cache\000Level 1 data cache read accesses\000legac... */ + { 190 }, + /* l1-dcache-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-ca... */ + { 782 }, + /* l1-dcache-loads-access\000legacy cache\000Level 1 data cache read accesses\000le... */ + { 1169 }, + /* l1-dcache-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy... */ + { 1371 }, + /* l1-dcache-loads-misses\000legacy cache\000Level 1 data cache read misses\000lega... */ + { 1268 }, + /* l1-dcache-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legac... */ + { 1073 }, + /* l1-dcache-loads-reference\000legacy cache\000Level 1 data cache read accesses\00... */ + { 971 }, + /* l1-dcache-loads-refs\000legacy cache\000Level 1 data cache read accesses\000lega... */ + { 874 }, + /* l1-dcache-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache... */ + { 7942 }, + /* l1-dcache-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cac... */ + { 7845 }, + /* l1-dcache-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cach... */ + { 7662 }, + /* l1-dcache-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000le... */ + { 4313 }, + /* l1-dcache-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesse... */ + { 4744 }, + /* l1-dcache-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\00... */ + { 4964 }, + /* l1-dcache-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\... */ + { 4854 }, + /* l1-dcache-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\0... */ + { 4637 }, + /* l1-dcache-prefetch-reference\000legacy cache\000Level 1 data cache prefetch acce... */ + { 4524 }, + /* l1-dcache-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\... */ + { 4416 }, + /* l1-dcache-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000... */ + { 5072 }, + /* l1-dcache-prefetches-access\000legacy cache\000Level 1 data cache prefetch acces... */ + { 5511 }, + /* l1-dcache-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\... */ + { 5735 }, + /* l1-dcache-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misse... */ + { 5623 }, + /* l1-dcache-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses... */ + { 5402 }, + /* l1-dcache-prefetches-reference\000legacy cache\000Level 1 data cache prefetch ac... */ + { 5287 }, + /* l1-dcache-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesse... */ + { 5177 }, + /* l1-dcache-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cac... */ + { 1472 }, + /* l1-dcache-read-access\000legacy cache\000Level 1 data cache read accesses\000leg... */ + { 1855 }, + /* l1-dcache-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-... */ + { 2055 }, + /* l1-dcache-read-misses\000legacy cache\000Level 1 data cache read misses\000legac... */ + { 1953 }, + /* l1-dcache-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy... */ + { 1760 }, + /* l1-dcache-read-reference\000legacy cache\000Level 1 data cache read accesses\000... */ + { 1659 }, + /* l1-dcache-read-refs\000legacy cache\000Level 1 data cache read accesses\000legac... */ + { 1563 }, + /* l1-dcache-reference\000legacy cache\000Level 1 data cache read accesses\000legac... */ + { 7566 }, + /* l1-dcache-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cac... */ + { 7475 }, + /* l1-dcache-speculative-load\000legacy cache\000Level 1 data cache prefetch access... */ + { 6660 }, + /* l1-dcache-speculative-load-access\000legacy cache\000Level 1 data cache prefetch... */ + { 7123 }, + /* l1-dcache-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch m... */ + { 7359 }, + /* l1-dcache-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch... */ + { 7241 }, + /* l1-dcache-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch ac... */ + { 7008 }, + /* l1-dcache-speculative-load-reference\000legacy cache\000Level 1 data cache prefe... */ + { 6887 }, + /* l1-dcache-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch a... */ + { 6771 }, + /* l1-dcache-speculative-read\000legacy cache\000Level 1 data cache prefetch access... */ + { 5845 }, + /* l1-dcache-speculative-read-access\000legacy cache\000Level 1 data cache prefetch... */ + { 6308 }, + /* l1-dcache-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch m... */ + { 6544 }, + /* l1-dcache-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch... */ + { 6426 }, + /* l1-dcache-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch ac... */ + { 6193 }, + /* l1-dcache-speculative-read-reference\000legacy cache\000Level 1 data cache prefe... */ + { 6072 }, + /* l1-dcache-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch a... */ + { 5956 }, + /* l1-dcache-store\000legacy cache\000Level 1 data cache write accesses\000legacy-c... */ + { 2155 }, + /* l1-dcache-store-access\000legacy cache\000Level 1 data cache write accesses\000l... */ + { 2562 }, + /* l1-dcache-store-miss\000legacy cache\000Level 1 data cache write misses\000legac... */ + { 2770 }, + /* l1-dcache-store-misses\000legacy cache\000Level 1 data cache write misses\000leg... */ + { 2666 }, + /* l1-dcache-store-ops\000legacy cache\000Level 1 data cache write accesses\000lega... */ + { 2461 }, + /* l1-dcache-store-reference\000legacy cache\000Level 1 data cache write accesses\0... */ + { 2354 }, + /* l1-dcache-store-refs\000legacy cache\000Level 1 data cache write accesses\000leg... */ + { 2252 }, + /* l1-dcache-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-... */ + { 2872 }, + /* l1-dcache-stores-access\000legacy cache\000Level 1 data cache write accesses\000... */ + { 3283 }, + /* l1-dcache-stores-miss\000legacy cache\000Level 1 data cache write misses\000lega... */ + { 3493 }, + /* l1-dcache-stores-misses\000legacy cache\000Level 1 data cache write misses\000le... */ + { 3388 }, + /* l1-dcache-stores-ops\000legacy cache\000Level 1 data cache write accesses\000leg... */ + { 3181 }, + /* l1-dcache-stores-reference\000legacy cache\000Level 1 data cache write accesses\... */ + { 3073 }, + /* l1-dcache-stores-refs\000legacy cache\000Level 1 data cache write accesses\000le... */ + { 2970 }, + /* l1-dcache-write\000legacy cache\000Level 1 data cache write accesses\000legacy-c... */ + { 3596 }, + /* l1-dcache-write-access\000legacy cache\000Level 1 data cache write accesses\000l... */ + { 4003 }, + /* l1-dcache-write-miss\000legacy cache\000Level 1 data cache write misses\000legac... */ + { 4211 }, + /* l1-dcache-write-misses\000legacy cache\000Level 1 data cache write misses\000leg... */ + { 4107 }, + /* l1-dcache-write-ops\000legacy cache\000Level 1 data cache write accesses\000lega... */ + { 3902 }, + /* l1-dcache-write-reference\000legacy cache\000Level 1 data cache write accesses\0... */ + { 3795 }, + /* l1-dcache-write-refs\000legacy cache\000Level 1 data cache write accesses\000leg... */ + { 3693 }, + /* l1-i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-... */ + { 37366 }, + /* l1-i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy... */ + { 43053 }, + /* l1-i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-c... */ + { 37454 }, + /* l1-i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000l... */ + { 37845 }, + /* l1-i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legac... */ + { 38049 }, + /* l1-i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000leg... */ + { 37945 }, + /* l1-i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000lega... */ + { 37748 }, + /* l1-i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 37645 }, + /* l1-i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000leg... */ + { 37547 }, + /* l1-i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-... */ + { 38151 }, + /* l1-i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000... */ + { 38546 }, + /* l1-i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000lega... */ + { 38752 }, + /* l1-i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000le... */ + { 38647 }, + /* l1-i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000leg... */ + { 38448 }, + /* l1-i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\... */ + { 38344 }, + /* l1-i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000le... */ + { 38245 }, + /* l1-i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cac... */ + { 43247 }, + /* l1-i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-c... */ + { 43148 }, + /* l1-i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-ca... */ + { 42961 }, + /* l1-i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000... */ + { 39552 }, + /* l1-i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch acces... */ + { 39991 }, + /* l1-i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\... */ + { 40215 }, + /* l1-i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misse... */ + { 40103 }, + /* l1-i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses... */ + { 39882 }, + /* l1-i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch ac... */ + { 39767 }, + /* l1-i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesse... */ + { 39657 }, + /* l1-i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\0... */ + { 40325 }, + /* l1-i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch acc... */ + { 40772 }, + /* l1-i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misse... */ + { 41000 }, + /* l1-i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch mis... */ + { 40886 }, + /* l1-i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch access... */ + { 40661 }, + /* l1-i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 40544 }, + /* l1-i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch acces... */ + { 40432 }, + /* l1-i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-c... */ + { 38855 }, + /* l1-i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000l... */ + { 39246 }, + /* l1-i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legac... */ + { 39450 }, + /* l1-i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000leg... */ + { 39346 }, + /* l1-i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000lega... */ + { 39149 }, + /* l1-i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 39046 }, + /* l1-i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000leg... */ + { 38948 }, + /* l1-i-reference\000legacy cache\000Level 1 instruction cache read accesses\000leg... */ + { 42863 }, + /* l1-i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-c... */ + { 42770 }, + /* l1-i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch acce... */ + { 41941 }, + /* l1-i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefet... */ + { 42412 }, + /* l1-i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch... */ + { 42652 }, + /* l1-i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefet... */ + { 42532 }, + /* l1-i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 42295 }, + /* l1-i-speculative-load-reference\000legacy cache\000Level 1 instruction cache pre... */ + { 42172 }, + /* l1-i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch... */ + { 42054 }, + /* l1-i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch acce... */ + { 41112 }, + /* l1-i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefet... */ + { 41583 }, + /* l1-i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch... */ + { 41823 }, + /* l1-i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefet... */ + { 41703 }, + /* l1-i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 41466 }, + /* l1-i-speculative-read-reference\000legacy cache\000Level 1 instruction cache pre... */ + { 41343 }, + /* l1-i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch... */ + { 41225 }, + /* l1-icache\000legacy cache\000Level 1 instruction cache read accesses\000legacy-c... */ + { 31108 }, + /* l1-icache-access\000legacy cache\000Level 1 instruction cache read accesses\000l... */ + { 37060 }, + /* l1-icache-load\000legacy cache\000Level 1 instruction cache read accesses\000leg... */ + { 31201 }, + /* l1-icache-load-access\000legacy cache\000Level 1 instruction cache read accesses... */ + { 31612 }, + /* l1-icache-load-miss\000legacy cache\000Level 1 instruction cache read misses\000... */ + { 31826 }, + /* l1-icache-load-misses\000legacy cache\000Level 1 instruction cache read misses\0... */ + { 31717 }, + /* l1-icache-load-ops\000legacy cache\000Level 1 instruction cache read accesses\00... */ + { 31510 }, + /* l1-icache-load-reference\000legacy cache\000Level 1 instruction cache read acces... */ + { 31402 }, + /* l1-icache-load-refs\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 31299 }, + /* l1-icache-loads\000legacy cache\000Level 1 instruction cache read accesses\000le... */ + { 31933 }, + /* l1-icache-loads-access\000legacy cache\000Level 1 instruction cache read accesse... */ + { 32348 }, + /* l1-icache-loads-miss\000legacy cache\000Level 1 instruction cache read misses\00... */ + { 32564 }, + /* l1-icache-loads-misses\000legacy cache\000Level 1 instruction cache read misses\... */ + { 32454 }, + /* l1-icache-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 32245 }, + /* l1-icache-loads-reference\000legacy cache\000Level 1 instruction cache read acce... */ + { 32136 }, + /* l1-icache-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\... */ + { 32032 }, + /* l1-icache-miss\000legacy cache\000Level 1 instruction cache read misses\000legac... */ + { 37264 }, + /* l1-icache-misses\000legacy cache\000Level 1 instruction cache read misses\000leg... */ + { 37160 }, + /* l1-icache-ops\000legacy cache\000Level 1 instruction cache read accesses\000lega... */ + { 36963 }, + /* l1-icache-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesse... */ + { 33404 }, + /* l1-icache-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 33863 }, + /* l1-icache-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch mi... */ + { 34097 }, + /* l1-icache-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 33980 }, + /* l1-icache-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch acc... */ + { 33749 }, + /* l1-icache-prefetch-reference\000legacy cache\000Level 1 instruction cache prefet... */ + { 33629 }, + /* l1-icache-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch ac... */ + { 33514 }, + /* l1-icache-prefetches\000legacy cache\000Level 1 instruction cache prefetch acces... */ + { 34212 }, + /* l1-icache-prefetches-access\000legacy cache\000Level 1 instruction cache prefetc... */ + { 34679 }, + /* l1-icache-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 34917 }, + /* l1-icache-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetc... */ + { 34798 }, + /* l1-icache-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch a... */ + { 34563 }, + /* l1-icache-prefetches-reference\000legacy cache\000Level 1 instruction cache pref... */ + { 34441 }, + /* l1-icache-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 34324 }, + /* l1-icache-read\000legacy cache\000Level 1 instruction cache read accesses\000leg... */ + { 32672 }, + /* l1-icache-read-access\000legacy cache\000Level 1 instruction cache read accesses... */ + { 33083 }, + /* l1-icache-read-miss\000legacy cache\000Level 1 instruction cache read misses\000... */ + { 33297 }, + /* l1-icache-read-misses\000legacy cache\000Level 1 instruction cache read misses\0... */ + { 33188 }, + /* l1-icache-read-ops\000legacy cache\000Level 1 instruction cache read accesses\00... */ + { 32981 }, + /* l1-icache-read-reference\000legacy cache\000Level 1 instruction cache read acces... */ + { 32873 }, + /* l1-icache-read-refs\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 32770 }, + /* l1-icache-reference\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 36860 }, + /* l1-icache-refs\000legacy cache\000Level 1 instruction cache read accesses\000leg... */ + { 36762 }, + /* l1-icache-speculative-load\000legacy cache\000Level 1 instruction cache prefetch... */ + { 35898 }, + /* l1-icache-speculative-load-access\000legacy cache\000Level 1 instruction cache p... */ + { 36389 }, + /* l1-icache-speculative-load-miss\000legacy cache\000Level 1 instruction cache pre... */ + { 36639 }, + /* l1-icache-speculative-load-misses\000legacy cache\000Level 1 instruction cache p... */ + { 36514 }, + /* l1-icache-speculative-load-ops\000legacy cache\000Level 1 instruction cache pref... */ + { 36267 }, + /* l1-icache-speculative-load-reference\000legacy cache\000Level 1 instruction cach... */ + { 36139 }, + /* l1-icache-speculative-load-refs\000legacy cache\000Level 1 instruction cache pre... */ + { 36016 }, + /* l1-icache-speculative-read\000legacy cache\000Level 1 instruction cache prefetch... */ + { 35034 }, + /* l1-icache-speculative-read-access\000legacy cache\000Level 1 instruction cache p... */ + { 35525 }, + /* l1-icache-speculative-read-miss\000legacy cache\000Level 1 instruction cache pre... */ + { 35775 }, + /* l1-icache-speculative-read-misses\000legacy cache\000Level 1 instruction cache p... */ + { 35650 }, + /* l1-icache-speculative-read-ops\000legacy cache\000Level 1 instruction cache pref... */ + { 35403 }, + /* l1-icache-speculative-read-reference\000legacy cache\000Level 1 instruction cach... */ + { 35275 }, + /* l1-icache-speculative-read-refs\000legacy cache\000Level 1 instruction cache pre... */ + { 35152 }, + /* l1-instruction\000legacy cache\000Level 1 instruction cache read accesses\000leg... */ + { 49266 }, + /* l1-instruction-access\000legacy cache\000Level 1 instruction cache read accesses... */ + { 55483 }, + /* l1-instruction-load\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 49364 }, + /* l1-instruction-load-access\000legacy cache\000Level 1 instruction cache read acc... */ + { 49795 }, + /* l1-instruction-load-miss\000legacy cache\000Level 1 instruction cache read misse... */ + { 50019 }, + /* l1-instruction-load-misses\000legacy cache\000Level 1 instruction cache read mis... */ + { 49905 }, + /* l1-instruction-load-ops\000legacy cache\000Level 1 instruction cache read access... */ + { 49688 }, + /* l1-instruction-load-reference\000legacy cache\000Level 1 instruction cache read ... */ + { 49575 }, + /* l1-instruction-load-refs\000legacy cache\000Level 1 instruction cache read acces... */ + { 49467 }, + /* l1-instruction-loads\000legacy cache\000Level 1 instruction cache read accesses\... */ + { 50131 }, + /* l1-instruction-loads-access\000legacy cache\000Level 1 instruction cache read ac... */ + { 50566 }, + /* l1-instruction-loads-miss\000legacy cache\000Level 1 instruction cache read miss... */ + { 50792 }, + /* l1-instruction-loads-misses\000legacy cache\000Level 1 instruction cache read mi... */ + { 50677 }, + /* l1-instruction-loads-ops\000legacy cache\000Level 1 instruction cache read acces... */ + { 50458 }, + /* l1-instruction-loads-reference\000legacy cache\000Level 1 instruction cache read... */ + { 50344 }, + /* l1-instruction-loads-refs\000legacy cache\000Level 1 instruction cache read acce... */ + { 50235 }, + /* l1-instruction-miss\000legacy cache\000Level 1 instruction cache read misses\000... */ + { 55697 }, + /* l1-instruction-misses\000legacy cache\000Level 1 instruction cache read misses\0... */ + { 55588 }, + /* l1-instruction-ops\000legacy cache\000Level 1 instruction cache read accesses\00... */ + { 55381 }, + /* l1-instruction-prefetch\000legacy cache\000Level 1 instruction cache prefetch ac... */ + { 51672 }, + /* l1-instruction-prefetch-access\000legacy cache\000Level 1 instruction cache pref... */ + { 52151 }, + /* l1-instruction-prefetch-miss\000legacy cache\000Level 1 instruction cache prefet... */ + { 52395 }, + /* l1-instruction-prefetch-misses\000legacy cache\000Level 1 instruction cache pref... */ + { 52273 }, + /* l1-instruction-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetc... */ + { 52032 }, + /* l1-instruction-prefetch-reference\000legacy cache\000Level 1 instruction cache p... */ + { 51907 }, + /* l1-instruction-prefetch-refs\000legacy cache\000Level 1 instruction cache prefet... */ + { 51787 }, + /* l1-instruction-prefetches\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 52515 }, + /* l1-instruction-prefetches-access\000legacy cache\000Level 1 instruction cache pr... */ + { 53002 }, + /* l1-instruction-prefetches-miss\000legacy cache\000Level 1 instruction cache pref... */ + { 53250 }, + /* l1-instruction-prefetches-misses\000legacy cache\000Level 1 instruction cache pr... */ + { 53126 }, + /* l1-instruction-prefetches-ops\000legacy cache\000Level 1 instruction cache prefe... */ + { 52881 }, + /* l1-instruction-prefetches-reference\000legacy cache\000Level 1 instruction cache... */ + { 52754 }, + /* l1-instruction-prefetches-refs\000legacy cache\000Level 1 instruction cache pref... */ + { 52632 }, + /* l1-instruction-read\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 50905 }, + /* l1-instruction-read-access\000legacy cache\000Level 1 instruction cache read acc... */ + { 51336 }, + /* l1-instruction-read-miss\000legacy cache\000Level 1 instruction cache read misse... */ + { 51560 }, + /* l1-instruction-read-misses\000legacy cache\000Level 1 instruction cache read mis... */ + { 51446 }, + /* l1-instruction-read-ops\000legacy cache\000Level 1 instruction cache read access... */ + { 51229 }, + /* l1-instruction-read-reference\000legacy cache\000Level 1 instruction cache read ... */ + { 51116 }, + /* l1-instruction-read-refs\000legacy cache\000Level 1 instruction cache read acces... */ + { 51008 }, + /* l1-instruction-reference\000legacy cache\000Level 1 instruction cache read acces... */ + { 55273 }, + /* l1-instruction-refs\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 55170 }, + /* l1-instruction-speculative-load\000legacy cache\000Level 1 instruction cache pre... */ + { 54271 }, + /* l1-instruction-speculative-load-access\000legacy cache\000Level 1 instruction ca... */ + { 54782 }, + /* l1-instruction-speculative-load-miss\000legacy cache\000Level 1 instruction cach... */ + { 55042 }, + /* l1-instruction-speculative-load-misses\000legacy cache\000Level 1 instruction ca... */ + { 54912 }, + /* l1-instruction-speculative-load-ops\000legacy cache\000Level 1 instruction cache... */ + { 54655 }, + /* l1-instruction-speculative-load-reference\000legacy cache\000Level 1 instruction... */ + { 54522 }, + /* l1-instruction-speculative-load-refs\000legacy cache\000Level 1 instruction cach... */ + { 54394 }, + /* l1-instruction-speculative-read\000legacy cache\000Level 1 instruction cache pre... */ + { 53372 }, + /* l1-instruction-speculative-read-access\000legacy cache\000Level 1 instruction ca... */ + { 53883 }, + /* l1-instruction-speculative-read-miss\000legacy cache\000Level 1 instruction cach... */ + { 54143 }, + /* l1-instruction-speculative-read-misses\000legacy cache\000Level 1 instruction ca... */ + { 54013 }, + /* l1-instruction-speculative-read-ops\000legacy cache\000Level 1 instruction cache... */ + { 53756 }, + /* l1-instruction-speculative-read-reference\000legacy cache\000Level 1 instruction... */ + { 53623 }, + /* l1-instruction-speculative-read-refs\000legacy cache\000Level 1 instruction cach... */ + { 53495 }, + /* l1d\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-config=0... */ + { 15676 }, + /* l1d-access\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-c... */ + { 22971 }, + /* l1d-load\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-con... */ + { 15756 }, + /* l1d-load-access\000legacy cache\000Level 1 data cache read accesses\000legacy-ca... */ + { 16115 }, + /* l1d-load-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-... */ + { 16303 }, + /* l1d-load-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cach... */ + { 16207 }, + /* l1d-load-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache... */ + { 16026 }, + /* l1d-load-reference\000legacy cache\000Level 1 data cache read accesses\000legacy... */ + { 15931 }, + /* l1d-load-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cach... */ + { 15841 }, + /* l1d-loads\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-co... */ + { 16397 }, + /* l1d-loads-access\000legacy cache\000Level 1 data cache read accesses\000legacy-c... */ + { 16760 }, + /* l1d-loads-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache... */ + { 16950 }, + /* l1d-loads-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cac... */ + { 16853 }, + /* l1d-loads-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cach... */ + { 16670 }, + /* l1d-loads-reference\000legacy cache\000Level 1 data cache read accesses\000legac... */ + { 16574 }, + /* l1d-loads-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cac... */ + { 16483 }, + /* l1d-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-confi... */ + { 23149 }, + /* l1d-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cache-con... */ + { 23058 }, + /* l1d-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-conf... */ + { 22887 }, + /* l1d-prefetch\000legacy cache\000Level 1 data cache prefetch accesses\000legacy-c... */ + { 19718 }, + /* l1d-prefetch-access\000legacy cache\000Level 1 data cache prefetch accesses\000l... */ + { 20125 }, + /* l1d-prefetch-miss\000legacy cache\000Level 1 data cache prefetch misses\000legac... */ + { 20333 }, + /* l1d-prefetch-misses\000legacy cache\000Level 1 data cache prefetch misses\000leg... */ + { 20229 }, + /* l1d-prefetch-ops\000legacy cache\000Level 1 data cache prefetch accesses\000lega... */ + { 20024 }, + /* l1d-prefetch-reference\000legacy cache\000Level 1 data cache prefetch accesses\0... */ + { 19917 }, + /* l1d-prefetch-refs\000legacy cache\000Level 1 data cache prefetch accesses\000leg... */ + { 19815 }, + /* l1d-prefetches\000legacy cache\000Level 1 data cache prefetch accesses\000legacy... */ + { 20435 }, + /* l1d-prefetches-access\000legacy cache\000Level 1 data cache prefetch accesses\00... */ + { 20850 }, + /* l1d-prefetches-miss\000legacy cache\000Level 1 data cache prefetch misses\000leg... */ + { 21062 }, + /* l1d-prefetches-misses\000legacy cache\000Level 1 data cache prefetch misses\000l... */ + { 20956 }, + /* l1d-prefetches-ops\000legacy cache\000Level 1 data cache prefetch accesses\000le... */ + { 20747 }, + /* l1d-prefetches-reference\000legacy cache\000Level 1 data cache prefetch accesses... */ + { 20638 }, + /* l1d-prefetches-refs\000legacy cache\000Level 1 data cache prefetch accesses\000l... */ + { 20534 }, + /* l1d-read\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-con... */ + { 17045 }, + /* l1d-read-access\000legacy cache\000Level 1 data cache read accesses\000legacy-ca... */ + { 17404 }, + /* l1d-read-miss\000legacy cache\000Level 1 data cache read misses\000legacy-cache-... */ + { 17592 }, + /* l1d-read-misses\000legacy cache\000Level 1 data cache read misses\000legacy-cach... */ + { 17496 }, + /* l1d-read-ops\000legacy cache\000Level 1 data cache read accesses\000legacy-cache... */ + { 17315 }, + /* l1d-read-reference\000legacy cache\000Level 1 data cache read accesses\000legacy... */ + { 17220 }, + /* l1d-read-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cach... */ + { 17130 }, + /* l1d-reference\000legacy cache\000Level 1 data cache read accesses\000legacy-cach... */ + { 22797 }, + /* l1d-refs\000legacy cache\000Level 1 data cache read accesses\000legacy-cache-con... */ + { 22712 }, + /* l1d-speculative-load\000legacy cache\000Level 1 data cache prefetch accesses\000... */ + { 21939 }, + /* l1d-speculative-load-access\000legacy cache\000Level 1 data cache prefetch acces... */ + { 22378 }, + /* l1d-speculative-load-miss\000legacy cache\000Level 1 data cache prefetch misses\... */ + { 22602 }, + /* l1d-speculative-load-misses\000legacy cache\000Level 1 data cache prefetch misse... */ + { 22490 }, + /* l1d-speculative-load-ops\000legacy cache\000Level 1 data cache prefetch accesses... */ + { 22269 }, + /* l1d-speculative-load-reference\000legacy cache\000Level 1 data cache prefetch ac... */ + { 22154 }, + /* l1d-speculative-load-refs\000legacy cache\000Level 1 data cache prefetch accesse... */ + { 22044 }, + /* l1d-speculative-read\000legacy cache\000Level 1 data cache prefetch accesses\000... */ + { 21166 }, + /* l1d-speculative-read-access\000legacy cache\000Level 1 data cache prefetch acces... */ + { 21605 }, + /* l1d-speculative-read-miss\000legacy cache\000Level 1 data cache prefetch misses\... */ + { 21829 }, + /* l1d-speculative-read-misses\000legacy cache\000Level 1 data cache prefetch misse... */ + { 21717 }, + /* l1d-speculative-read-ops\000legacy cache\000Level 1 data cache prefetch accesses... */ + { 21496 }, + /* l1d-speculative-read-reference\000legacy cache\000Level 1 data cache prefetch ac... */ + { 21381 }, + /* l1d-speculative-read-refs\000legacy cache\000Level 1 data cache prefetch accesse... */ + { 21271 }, + /* l1d-store\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-c... */ + { 17686 }, + /* l1d-store-access\000legacy cache\000Level 1 data cache write accesses\000legacy-... */ + { 18069 }, + /* l1d-store-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cach... */ + { 18265 }, + /* l1d-store-misses\000legacy cache\000Level 1 data cache write misses\000legacy-ca... */ + { 18167 }, + /* l1d-store-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cac... */ + { 17974 }, + /* l1d-store-reference\000legacy cache\000Level 1 data cache write accesses\000lega... */ + { 17873 }, + /* l1d-store-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-ca... */ + { 17777 }, + /* l1d-stores\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-... */ + { 18361 }, + /* l1d-stores-access\000legacy cache\000Level 1 data cache write accesses\000legacy... */ + { 18748 }, + /* l1d-stores-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cac... */ + { 18946 }, + /* l1d-stores-misses\000legacy cache\000Level 1 data cache write misses\000legacy-c... */ + { 18847 }, + /* l1d-stores-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-ca... */ + { 18652 }, + /* l1d-stores-reference\000legacy cache\000Level 1 data cache write accesses\000leg... */ + { 18550 }, + /* l1d-stores-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-c... */ + { 18453 }, + /* l1d-write\000legacy cache\000Level 1 data cache write accesses\000legacy-cache-c... */ + { 19043 }, + /* l1d-write-access\000legacy cache\000Level 1 data cache write accesses\000legacy-... */ + { 19426 }, + /* l1d-write-miss\000legacy cache\000Level 1 data cache write misses\000legacy-cach... */ + { 19622 }, + /* l1d-write-misses\000legacy cache\000Level 1 data cache write misses\000legacy-ca... */ + { 19524 }, + /* l1d-write-ops\000legacy cache\000Level 1 data cache write accesses\000legacy-cac... */ + { 19331 }, + /* l1d-write-reference\000legacy cache\000Level 1 data cache write accesses\000lega... */ + { 19230 }, + /* l1d-write-refs\000legacy cache\000Level 1 data cache write accesses\000legacy-ca... */ + { 19134 }, + /* l1i\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cache-c... */ + { 43344 }, + /* l1i-access\000legacy cache\000Level 1 instruction cache read accesses\000legacy-... */ + { 48978 }, + /* l1i-load\000legacy cache\000Level 1 instruction cache read accesses\000legacy-ca... */ + { 43431 }, + /* l1i-load-access\000legacy cache\000Level 1 instruction cache read accesses\000le... */ + { 43818 }, + /* l1i-load-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy... */ + { 44020 }, + /* l1i-load-misses\000legacy cache\000Level 1 instruction cache read misses\000lega... */ + { 43917 }, + /* l1i-load-ops\000legacy cache\000Level 1 instruction cache read accesses\000legac... */ + { 43722 }, + /* l1i-load-reference\000legacy cache\000Level 1 instruction cache read accesses\00... */ + { 43620 }, + /* l1i-load-refs\000legacy cache\000Level 1 instruction cache read accesses\000lega... */ + { 43523 }, + /* l1i-loads\000legacy cache\000Level 1 instruction cache read accesses\000legacy-c... */ + { 44121 }, + /* l1i-loads-access\000legacy cache\000Level 1 instruction cache read accesses\000l... */ + { 44512 }, + /* l1i-loads-miss\000legacy cache\000Level 1 instruction cache read misses\000legac... */ + { 44716 }, + /* l1i-loads-misses\000legacy cache\000Level 1 instruction cache read misses\000leg... */ + { 44612 }, + /* l1i-loads-ops\000legacy cache\000Level 1 instruction cache read accesses\000lega... */ + { 44415 }, + /* l1i-loads-reference\000legacy cache\000Level 1 instruction cache read accesses\0... */ + { 44312 }, + /* l1i-loads-refs\000legacy cache\000Level 1 instruction cache read accesses\000leg... */ + { 44214 }, + /* l1i-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy-cach... */ + { 49170 }, + /* l1i-misses\000legacy cache\000Level 1 instruction cache read misses\000legacy-ca... */ + { 49072 }, + /* l1i-ops\000legacy cache\000Level 1 instruction cache read accesses\000legacy-cac... */ + { 48887 }, + /* l1i-prefetch\000legacy cache\000Level 1 instruction cache prefetch accesses\000l... */ + { 45508 }, + /* l1i-prefetch-access\000legacy cache\000Level 1 instruction cache prefetch access... */ + { 45943 }, + /* l1i-prefetch-miss\000legacy cache\000Level 1 instruction cache prefetch misses\0... */ + { 46165 }, + /* l1i-prefetch-misses\000legacy cache\000Level 1 instruction cache prefetch misses... */ + { 46054 }, + /* l1i-prefetch-ops\000legacy cache\000Level 1 instruction cache prefetch accesses\... */ + { 45835 }, + /* l1i-prefetch-reference\000legacy cache\000Level 1 instruction cache prefetch acc... */ + { 45721 }, + /* l1i-prefetch-refs\000legacy cache\000Level 1 instruction cache prefetch accesses... */ + { 45612 }, + /* l1i-prefetches\000legacy cache\000Level 1 instruction cache prefetch accesses\00... */ + { 46274 }, + /* l1i-prefetches-access\000legacy cache\000Level 1 instruction cache prefetch acce... */ + { 46717 }, + /* l1i-prefetches-miss\000legacy cache\000Level 1 instruction cache prefetch misses... */ + { 46943 }, + /* l1i-prefetches-misses\000legacy cache\000Level 1 instruction cache prefetch miss... */ + { 46830 }, + /* l1i-prefetches-ops\000legacy cache\000Level 1 instruction cache prefetch accesse... */ + { 46607 }, + /* l1i-prefetches-reference\000legacy cache\000Level 1 instruction cache prefetch a... */ + { 46491 }, + /* l1i-prefetches-refs\000legacy cache\000Level 1 instruction cache prefetch access... */ + { 46380 }, + /* l1i-read\000legacy cache\000Level 1 instruction cache read accesses\000legacy-ca... */ + { 44818 }, + /* l1i-read-access\000legacy cache\000Level 1 instruction cache read accesses\000le... */ + { 45205 }, + /* l1i-read-miss\000legacy cache\000Level 1 instruction cache read misses\000legacy... */ + { 45407 }, + /* l1i-read-misses\000legacy cache\000Level 1 instruction cache read misses\000lega... */ + { 45304 }, + /* l1i-read-ops\000legacy cache\000Level 1 instruction cache read accesses\000legac... */ + { 45109 }, + /* l1i-read-reference\000legacy cache\000Level 1 instruction cache read accesses\00... */ + { 45007 }, + /* l1i-read-refs\000legacy cache\000Level 1 instruction cache read accesses\000lega... */ + { 44910 }, + /* l1i-reference\000legacy cache\000Level 1 instruction cache read accesses\000lega... */ + { 48790 }, + /* l1i-refs\000legacy cache\000Level 1 instruction cache read accesses\000legacy-ca... */ + { 48698 }, + /* l1i-speculative-load\000legacy cache\000Level 1 instruction cache prefetch acces... */ + { 47876 }, + /* l1i-speculative-load-access\000legacy cache\000Level 1 instruction cache prefetc... */ + { 48343 }, + /* l1i-speculative-load-miss\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 48581 }, + /* l1i-speculative-load-misses\000legacy cache\000Level 1 instruction cache prefetc... */ + { 48462 }, + /* l1i-speculative-load-ops\000legacy cache\000Level 1 instruction cache prefetch a... */ + { 48227 }, + /* l1i-speculative-load-reference\000legacy cache\000Level 1 instruction cache pref... */ + { 48105 }, + /* l1i-speculative-load-refs\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 47988 }, + /* l1i-speculative-read\000legacy cache\000Level 1 instruction cache prefetch acces... */ + { 47054 }, + /* l1i-speculative-read-access\000legacy cache\000Level 1 instruction cache prefetc... */ + { 47521 }, + /* l1i-speculative-read-miss\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 47759 }, + /* l1i-speculative-read-misses\000legacy cache\000Level 1 instruction cache prefetc... */ + { 47640 }, + /* l1i-speculative-read-ops\000legacy cache\000Level 1 instruction cache prefetch a... */ + { 47405 }, + /* l1i-speculative-read-reference\000legacy cache\000Level 1 instruction cache pref... */ + { 47283 }, + /* l1i-speculative-read-refs\000legacy cache\000Level 1 instruction cache prefetch ... */ + { 47166 }, + /* l2\000legacy cache\000Level 2 (or higher) last level cache read accesses\000lega... */ + { 63212 }, + /* l2-access\000legacy cache\000Level 2 (or higher) last level cache read accesses\... */ + { 71765 }, + /* l2-load\000legacy cache\000Level 2 (or higher) last level cache read accesses\00... */ + { 63309 }, + /* l2-load-access\000legacy cache\000Level 2 (or higher) last level cache read acce... */ + { 63736 }, + /* l2-load-miss\000legacy cache\000Level 2 (or higher) last level cache read misses... */ + { 63958 }, + /* l2-load-misses\000legacy cache\000Level 2 (or higher) last level cache read miss... */ + { 63845 }, + /* l2-load-ops\000legacy cache\000Level 2 (or higher) last level cache read accesse... */ + { 63630 }, + /* l2-load-reference\000legacy cache\000Level 2 (or higher) last level cache read a... */ + { 63518 }, + /* l2-load-refs\000legacy cache\000Level 2 (or higher) last level cache read access... */ + { 63411 }, + /* l2-loads\000legacy cache\000Level 2 (or higher) last level cache read accesses\0... */ + { 64069 }, + /* l2-loads-access\000legacy cache\000Level 2 (or higher) last level cache read acc... */ + { 64500 }, + /* l2-loads-miss\000legacy cache\000Level 2 (or higher) last level cache read misse... */ + { 64724 }, + /* l2-loads-misses\000legacy cache\000Level 2 (or higher) last level cache read mis... */ + { 64610 }, + /* l2-loads-ops\000legacy cache\000Level 2 (or higher) last level cache read access... */ + { 64393 }, + /* l2-loads-reference\000legacy cache\000Level 2 (or higher) last level cache read ... */ + { 64280 }, + /* l2-loads-refs\000legacy cache\000Level 2 (or higher) last level cache read acces... */ + { 64172 }, + /* l2-miss\000legacy cache\000Level 2 (or higher) last level cache read misses\000l... */ + { 71977 }, + /* l2-misses\000legacy cache\000Level 2 (or higher) last level cache read misses\00... */ + { 71869 }, + /* l2-ops\000legacy cache\000Level 2 (or higher) last level cache read accesses\000... */ + { 71664 }, + /* l2-prefetch\000legacy cache\000Level 2 (or higher) last level cache prefetch acc... */ + { 67985 }, + /* l2-prefetch-access\000legacy cache\000Level 2 (or higher) last level cache prefe... */ + { 68460 }, + /* l2-prefetch-miss\000legacy cache\000Level 2 (or higher) last level cache prefetc... */ + { 68702 }, + /* l2-prefetch-misses\000legacy cache\000Level 2 (or higher) last level cache prefe... */ + { 68581 }, + /* l2-prefetch-ops\000legacy cache\000Level 2 (or higher) last level cache prefetch... */ + { 68342 }, + /* l2-prefetch-reference\000legacy cache\000Level 2 (or higher) last level cache pr... */ + { 68218 }, + /* l2-prefetch-refs\000legacy cache\000Level 2 (or higher) last level cache prefetc... */ + { 68099 }, + /* l2-prefetches\000legacy cache\000Level 2 (or higher) last level cache prefetch a... */ + { 68821 }, + /* l2-prefetches-access\000legacy cache\000Level 2 (or higher) last level cache pre... */ + { 69304 }, + /* l2-prefetches-miss\000legacy cache\000Level 2 (or higher) last level cache prefe... */ + { 69550 }, + /* l2-prefetches-misses\000legacy cache\000Level 2 (or higher) last level cache pre... */ + { 69427 }, + /* l2-prefetches-ops\000legacy cache\000Level 2 (or higher) last level cache prefet... */ + { 69184 }, + /* l2-prefetches-reference\000legacy cache\000Level 2 (or higher) last level cache ... */ + { 69058 }, + /* l2-prefetches-refs\000legacy cache\000Level 2 (or higher) last level cache prefe... */ + { 68937 }, + /* l2-read\000legacy cache\000Level 2 (or higher) last level cache read accesses\00... */ + { 64836 }, + /* l2-read-access\000legacy cache\000Level 2 (or higher) last level cache read acce... */ + { 65263 }, + /* l2-read-miss\000legacy cache\000Level 2 (or higher) last level cache read misses... */ + { 65485 }, + /* l2-read-misses\000legacy cache\000Level 2 (or higher) last level cache read miss... */ + { 65372 }, + /* l2-read-ops\000legacy cache\000Level 2 (or higher) last level cache read accesse... */ + { 65157 }, + /* l2-read-reference\000legacy cache\000Level 2 (or higher) last level cache read a... */ + { 65045 }, + /* l2-read-refs\000legacy cache\000Level 2 (or higher) last level cache read access... */ + { 64938 }, + /* l2-reference\000legacy cache\000Level 2 (or higher) last level cache read access... */ + { 71557 }, + /* l2-refs\000legacy cache\000Level 2 (or higher) last level cache read accesses\00... */ + { 71455 }, + /* l2-speculative-load\000legacy cache\000Level 2 (or higher) last level cache pref... */ + { 70563 }, + /* l2-speculative-load-access\000legacy cache\000Level 2 (or higher) last level cac... */ + { 71070 }, + /* l2-speculative-load-miss\000legacy cache\000Level 2 (or higher) last level cache... */ + { 71328 }, + /* l2-speculative-load-misses\000legacy cache\000Level 2 (or higher) last level cac... */ + { 71199 }, + /* l2-speculative-load-ops\000legacy cache\000Level 2 (or higher) last level cache ... */ + { 70944 }, + /* l2-speculative-load-reference\000legacy cache\000Level 2 (or higher) last level ... */ + { 70812 }, + /* l2-speculative-load-refs\000legacy cache\000Level 2 (or higher) last level cache... */ + { 70685 }, + /* l2-speculative-read\000legacy cache\000Level 2 (or higher) last level cache pref... */ + { 69671 }, + /* l2-speculative-read-access\000legacy cache\000Level 2 (or higher) last level cac... */ + { 70178 }, + /* l2-speculative-read-miss\000legacy cache\000Level 2 (or higher) last level cache... */ + { 70436 }, + /* l2-speculative-read-misses\000legacy cache\000Level 2 (or higher) last level cac... */ + { 70307 }, + /* l2-speculative-read-ops\000legacy cache\000Level 2 (or higher) last level cache ... */ + { 70052 }, + /* l2-speculative-read-reference\000legacy cache\000Level 2 (or higher) last level ... */ + { 69920 }, + /* l2-speculative-read-refs\000legacy cache\000Level 2 (or higher) last level cache... */ + { 69793 }, + /* l2-store\000legacy cache\000Level 2 (or higher) last level cache write accesses\... */ + { 65596 }, + /* l2-store-access\000legacy cache\000Level 2 (or higher) last level cache write ac... */ + { 66047 }, + /* l2-store-miss\000legacy cache\000Level 2 (or higher) last level cache write miss... */ + { 66277 }, + /* l2-store-misses\000legacy cache\000Level 2 (or higher) last level cache write mi... */ + { 66162 }, + /* l2-store-ops\000legacy cache\000Level 2 (or higher) last level cache write acces... */ + { 65935 }, + /* l2-store-reference\000legacy cache\000Level 2 (or higher) last level cache write... */ + { 65817 }, + /* l2-store-refs\000legacy cache\000Level 2 (or higher) last level cache write acce... */ + { 65704 }, + /* l2-stores\000legacy cache\000Level 2 (or higher) last level cache write accesses... */ + { 66390 }, + /* l2-stores-access\000legacy cache\000Level 2 (or higher) last level cache write a... */ + { 66845 }, + /* l2-stores-miss\000legacy cache\000Level 2 (or higher) last level cache write mis... */ + { 67077 }, + /* l2-stores-misses\000legacy cache\000Level 2 (or higher) last level cache write m... */ + { 66961 }, + /* l2-stores-ops\000legacy cache\000Level 2 (or higher) last level cache write acce... */ + { 66732 }, + /* l2-stores-reference\000legacy cache\000Level 2 (or higher) last level cache writ... */ + { 66613 }, + /* l2-stores-refs\000legacy cache\000Level 2 (or higher) last level cache write acc... */ + { 66499 }, + /* l2-write\000legacy cache\000Level 2 (or higher) last level cache write accesses\... */ + { 67191 }, + /* l2-write-access\000legacy cache\000Level 2 (or higher) last level cache write ac... */ + { 67642 }, + /* l2-write-miss\000legacy cache\000Level 2 (or higher) last level cache write miss... */ + { 67872 }, + /* l2-write-misses\000legacy cache\000Level 2 (or higher) last level cache write mi... */ + { 67757 }, + /* l2-write-ops\000legacy cache\000Level 2 (or higher) last level cache write acces... */ + { 67530 }, + /* l2-write-reference\000legacy cache\000Level 2 (or higher) last level cache write... */ + { 67412 }, + /* l2-write-refs\000legacy cache\000Level 2 (or higher) last level cache write acce... */ + { 67299 }, + /* llc\000legacy cache\000Last level cache read accesses\000legacy-cache-config=2\0... */ + { 55804 }, + /* llc-access\000legacy cache\000Last level cache read accesses\000legacy-cache-con... */ + { 62951 }, + /* llc-load\000legacy cache\000Last level cache read accesses\000legacy-cache-confi... */ + { 55882 }, + /* llc-load-access\000legacy cache\000Last level cache read accesses\000legacy-cach... */ + { 56233 }, + /* llc-load-miss\000legacy cache\000Last level cache read misses\000legacy-cache-co... */ + { 56417 }, + /* llc-load-misses\000legacy cache\000Last level cache read misses\000legacy-cache-... */ + { 56323 }, + /* llc-load-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-c... */ + { 56146 }, + /* llc-load-reference\000legacy cache\000Last level cache read accesses\000legacy-c... */ + { 56053 }, + /* llc-load-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-... */ + { 55965 }, + /* llc-loads\000legacy cache\000Last level cache read accesses\000legacy-cache-conf... */ + { 56509 }, + /* llc-loads-access\000legacy cache\000Last level cache read accesses\000legacy-cac... */ + { 56864 }, + /* llc-loads-miss\000legacy cache\000Last level cache read misses\000legacy-cache-c... */ + { 57050 }, + /* llc-loads-misses\000legacy cache\000Last level cache read misses\000legacy-cache... */ + { 56955 }, + /* llc-loads-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-... */ + { 56776 }, + /* llc-loads-reference\000legacy cache\000Last level cache read accesses\000legacy-... */ + { 56682 }, + /* llc-loads-refs\000legacy cache\000Last level cache read accesses\000legacy-cache... */ + { 56593 }, + /* llc-miss\000legacy cache\000Last level cache read misses\000legacy-cache-config=... */ + { 63125 }, + /* llc-misses\000legacy cache\000Last level cache read misses\000legacy-cache-confi... */ + { 63036 }, + /* llc-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-config... */ + { 62869 }, + /* llc-prefetch\000legacy cache\000Last level cache prefetch accesses\000legacy-cac... */ + { 59760 }, + /* llc-prefetch-access\000legacy cache\000Last level cache prefetch accesses\000leg... */ + { 60159 }, + /* llc-prefetch-miss\000legacy cache\000Last level cache prefetch misses\000legacy-... */ + { 60363 }, + /* llc-prefetch-misses\000legacy cache\000Last level cache prefetch misses\000legac... */ + { 60261 }, + /* llc-prefetch-ops\000legacy cache\000Last level cache prefetch accesses\000legacy... */ + { 60060 }, + /* llc-prefetch-reference\000legacy cache\000Last level cache prefetch accesses\000... */ + { 59955 }, + /* llc-prefetch-refs\000legacy cache\000Last level cache prefetch accesses\000legac... */ + { 59855 }, + /* llc-prefetches\000legacy cache\000Last level cache prefetch accesses\000legacy-c... */ + { 60463 }, + /* llc-prefetches-access\000legacy cache\000Last level cache prefetch accesses\000l... */ + { 60870 }, + /* llc-prefetches-miss\000legacy cache\000Last level cache prefetch misses\000legac... */ + { 61078 }, + /* llc-prefetches-misses\000legacy cache\000Last level cache prefetch misses\000leg... */ + { 60974 }, + /* llc-prefetches-ops\000legacy cache\000Last level cache prefetch accesses\000lega... */ + { 60769 }, + /* llc-prefetches-reference\000legacy cache\000Last level cache prefetch accesses\0... */ + { 60662 }, + /* llc-prefetches-refs\000legacy cache\000Last level cache prefetch accesses\000leg... */ + { 60560 }, + /* llc-read\000legacy cache\000Last level cache read accesses\000legacy-cache-confi... */ + { 57143 }, + /* llc-read-access\000legacy cache\000Last level cache read accesses\000legacy-cach... */ + { 57494 }, + /* llc-read-miss\000legacy cache\000Last level cache read misses\000legacy-cache-co... */ + { 57678 }, + /* llc-read-misses\000legacy cache\000Last level cache read misses\000legacy-cache-... */ + { 57584 }, + /* llc-read-ops\000legacy cache\000Last level cache read accesses\000legacy-cache-c... */ + { 57407 }, + /* llc-read-reference\000legacy cache\000Last level cache read accesses\000legacy-c... */ + { 57314 }, + /* llc-read-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-... */ + { 57226 }, + /* llc-reference\000legacy cache\000Last level cache read accesses\000legacy-cache-... */ + { 62781 }, + /* llc-refs\000legacy cache\000Last level cache read accesses\000legacy-cache-confi... */ + { 62698 }, + /* llc-speculative-load\000legacy cache\000Last level cache prefetch accesses\000le... */ + { 61939 }, + /* llc-speculative-load-access\000legacy cache\000Last level cache prefetch accesse... */ + { 62370 }, + /* llc-speculative-load-miss\000legacy cache\000Last level cache prefetch misses\00... */ + { 62590 }, + /* llc-speculative-load-misses\000legacy cache\000Last level cache prefetch misses\... */ + { 62480 }, + /* llc-speculative-load-ops\000legacy cache\000Last level cache prefetch accesses\0... */ + { 62263 }, + /* llc-speculative-load-reference\000legacy cache\000Last level cache prefetch acce... */ + { 62150 }, + /* llc-speculative-load-refs\000legacy cache\000Last level cache prefetch accesses\... */ + { 62042 }, + /* llc-speculative-read\000legacy cache\000Last level cache prefetch accesses\000le... */ + { 61180 }, + /* llc-speculative-read-access\000legacy cache\000Last level cache prefetch accesse... */ + { 61611 }, + /* llc-speculative-read-miss\000legacy cache\000Last level cache prefetch misses\00... */ + { 61831 }, + /* llc-speculative-read-misses\000legacy cache\000Last level cache prefetch misses\... */ + { 61721 }, + /* llc-speculative-read-ops\000legacy cache\000Last level cache prefetch accesses\0... */ + { 61504 }, + /* llc-speculative-read-reference\000legacy cache\000Last level cache prefetch acce... */ + { 61391 }, + /* llc-speculative-read-refs\000legacy cache\000Last level cache prefetch accesses\... */ + { 61283 }, + /* llc-store\000legacy cache\000Last level cache write accesses\000legacy-cache-con... */ + { 57770 }, + /* llc-store-access\000legacy cache\000Last level cache write accesses\000legacy-ca... */ + { 58145 }, + /* llc-store-miss\000legacy cache\000Last level cache write misses\000legacy-cache-... */ + { 58337 }, + /* llc-store-misses\000legacy cache\000Last level cache write misses\000legacy-cach... */ + { 58241 }, + /* llc-store-ops\000legacy cache\000Last level cache write accesses\000legacy-cache... */ + { 58052 }, + /* llc-store-reference\000legacy cache\000Last level cache write accesses\000legacy... */ + { 57953 }, + /* llc-store-refs\000legacy cache\000Last level cache write accesses\000legacy-cach... */ + { 57859 }, + /* llc-stores\000legacy cache\000Last level cache write accesses\000legacy-cache-co... */ + { 58431 }, + /* llc-stores-access\000legacy cache\000Last level cache write accesses\000legacy-c... */ + { 58810 }, + /* llc-stores-miss\000legacy cache\000Last level cache write misses\000legacy-cache... */ + { 59004 }, + /* llc-stores-misses\000legacy cache\000Last level cache write misses\000legacy-cac... */ + { 58907 }, + /* llc-stores-ops\000legacy cache\000Last level cache write accesses\000legacy-cach... */ + { 58716 }, + /* llc-stores-reference\000legacy cache\000Last level cache write accesses\000legac... */ + { 58616 }, + /* llc-stores-refs\000legacy cache\000Last level cache write accesses\000legacy-cac... */ + { 58521 }, + /* llc-write\000legacy cache\000Last level cache write accesses\000legacy-cache-con... */ + { 59099 }, + /* llc-write-access\000legacy cache\000Last level cache write accesses\000legacy-ca... */ + { 59474 }, + /* llc-write-miss\000legacy cache\000Last level cache write misses\000legacy-cache-... */ + { 59666 }, + /* llc-write-misses\000legacy cache\000Last level cache write misses\000legacy-cach... */ + { 59570 }, + /* llc-write-ops\000legacy cache\000Last level cache write accesses\000legacy-cache... */ + { 59381 }, + /* llc-write-reference\000legacy cache\000Last level cache write accesses\000legacy... */ + { 59282 }, + /* llc-write-refs\000legacy cache\000Last level cache write accesses\000legacy-cach... */ + { 59188 }, + /* node\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\000\... */ + { 114128 }, + /* node-access\000legacy cache\000Local memory read accesses\000legacy-cache-config... */ + { 121053 }, + /* node-load\000legacy cache\000Local memory read accesses\000legacy-cache-config=6... */ + { 114203 }, + /* node-load-access\000legacy cache\000Local memory read accesses\000legacy-cache-c... */ + { 114542 }, + /* node-load-miss\000legacy cache\000Local memory read misses\000legacy-cache-confi... */ + { 114720 }, + /* node-load-misses\000legacy cache\000Local memory read misses\000legacy-cache-con... */ + { 114629 }, + /* node-load-ops\000legacy cache\000Local memory read accesses\000legacy-cache-conf... */ + { 114458 }, + /* node-load-reference\000legacy cache\000Local memory read accesses\000legacy-cach... */ + { 114368 }, + /* node-load-refs\000legacy cache\000Local memory read accesses\000legacy-cache-con... */ + { 114283 }, + /* node-loads\000legacy cache\000Local memory read accesses\000legacy-cache-config=... */ + { 114809 }, + /* node-loads-access\000legacy cache\000Local memory read accesses\000legacy-cache-... */ + { 115152 }, + /* node-loads-miss\000legacy cache\000Local memory read misses\000legacy-cache-conf... */ + { 115332 }, + /* node-loads-misses\000legacy cache\000Local memory read misses\000legacy-cache-co... */ + { 115240 }, + /* node-loads-ops\000legacy cache\000Local memory read accesses\000legacy-cache-con... */ + { 115067 }, + /* node-loads-reference\000legacy cache\000Local memory read accesses\000legacy-cac... */ + { 114976 }, + /* node-loads-refs\000legacy cache\000Local memory read accesses\000legacy-cache-co... */ + { 114890 }, + /* node-miss\000legacy cache\000Local memory read misses\000legacy-cache-config=0x1... */ + { 121221 }, + /* node-misses\000legacy cache\000Local memory read misses\000legacy-cache-config=0... */ + { 121135 }, + /* node-ops\000legacy cache\000Local memory read accesses\000legacy-cache-config=6\... */ + { 120974 }, + /* node-prefetch\000legacy cache\000Local memory prefetch accesses\000legacy-cache-... */ + { 117955 }, + /* node-prefetch-access\000legacy cache\000Local memory prefetch accesses\000legacy... */ + { 118342 }, + /* node-prefetch-miss\000legacy cache\000Local memory prefetch misses\000legacy-cac... */ + { 118540 }, + /* node-prefetch-misses\000legacy cache\000Local memory prefetch misses\000legacy-c... */ + { 118441 }, + /* node-prefetch-ops\000legacy cache\000Local memory prefetch accesses\000legacy-ca... */ + { 118246 }, + /* node-prefetch-reference\000legacy cache\000Local memory prefetch accesses\000leg... */ + { 118144 }, + /* node-prefetch-refs\000legacy cache\000Local memory prefetch accesses\000legacy-c... */ + { 118047 }, + /* node-prefetches\000legacy cache\000Local memory prefetch accesses\000legacy-cach... */ + { 118637 }, + /* node-prefetches-access\000legacy cache\000Local memory prefetch accesses\000lega... */ + { 119032 }, + /* node-prefetches-miss\000legacy cache\000Local memory prefetch misses\000legacy-c... */ + { 119234 }, + /* node-prefetches-misses\000legacy cache\000Local memory prefetch misses\000legacy... */ + { 119133 }, + /* node-prefetches-ops\000legacy cache\000Local memory prefetch accesses\000legacy-... */ + { 118934 }, + /* node-prefetches-reference\000legacy cache\000Local memory prefetch accesses\000l... */ + { 118830 }, + /* node-prefetches-refs\000legacy cache\000Local memory prefetch accesses\000legacy... */ + { 118731 }, + /* node-read\000legacy cache\000Local memory read accesses\000legacy-cache-config=6... */ + { 115422 }, + /* node-read-access\000legacy cache\000Local memory read accesses\000legacy-cache-c... */ + { 115761 }, + /* node-read-miss\000legacy cache\000Local memory read misses\000legacy-cache-confi... */ + { 115939 }, + /* node-read-misses\000legacy cache\000Local memory read misses\000legacy-cache-con... */ + { 115848 }, + /* node-read-ops\000legacy cache\000Local memory read accesses\000legacy-cache-conf... */ + { 115677 }, + /* node-read-reference\000legacy cache\000Local memory read accesses\000legacy-cach... */ + { 115587 }, + /* node-read-refs\000legacy cache\000Local memory read accesses\000legacy-cache-con... */ + { 115502 }, + /* node-reference\000legacy cache\000Local memory read accesses\000legacy-cache-con... */ + { 120889 }, + /* node-refs\000legacy cache\000Local memory read accesses\000legacy-cache-config=6... */ + { 120809 }, + /* node-speculative-load\000legacy cache\000Local memory prefetch accesses\000legac... */ + { 120071 }, + /* node-speculative-load-access\000legacy cache\000Local memory prefetch accesses\0... */ + { 120490 }, + /* node-speculative-load-miss\000legacy cache\000Local memory prefetch misses\000le... */ + { 120704 }, + /* node-speculative-load-misses\000legacy cache\000Local memory prefetch misses\000... */ + { 120597 }, + /* node-speculative-load-ops\000legacy cache\000Local memory prefetch accesses\000l... */ + { 120386 }, + /* node-speculative-load-reference\000legacy cache\000Local memory prefetch accesse... */ + { 120276 }, + /* node-speculative-load-refs\000legacy cache\000Local memory prefetch accesses\000... */ + { 120171 }, + /* node-speculative-read\000legacy cache\000Local memory prefetch accesses\000legac... */ + { 119333 }, + /* node-speculative-read-access\000legacy cache\000Local memory prefetch accesses\0... */ + { 119752 }, + /* node-speculative-read-miss\000legacy cache\000Local memory prefetch misses\000le... */ + { 119966 }, + /* node-speculative-read-misses\000legacy cache\000Local memory prefetch misses\000... */ + { 119859 }, + /* node-speculative-read-ops\000legacy cache\000Local memory prefetch accesses\000l... */ + { 119648 }, + /* node-speculative-read-reference\000legacy cache\000Local memory prefetch accesse... */ + { 119538 }, + /* node-speculative-read-refs\000legacy cache\000Local memory prefetch accesses\000... */ + { 119433 }, + /* node-store\000legacy cache\000Local memory write accesses\000legacy-cache-config... */ + { 116028 }, + /* node-store-access\000legacy cache\000Local memory write accesses\000legacy-cache... */ + { 116391 }, + /* node-store-miss\000legacy cache\000Local memory write misses\000legacy-cache-con... */ + { 116577 }, + /* node-store-misses\000legacy cache\000Local memory write misses\000legacy-cache-c... */ + { 116484 }, + /* node-store-ops\000legacy cache\000Local memory write accesses\000legacy-cache-co... */ + { 116301 }, + /* node-store-reference\000legacy cache\000Local memory write accesses\000legacy-ca... */ + { 116205 }, + /* node-store-refs\000legacy cache\000Local memory write accesses\000legacy-cache-c... */ + { 116114 }, + /* node-stores\000legacy cache\000Local memory write accesses\000legacy-cache-confi... */ + { 116668 }, + /* node-stores-access\000legacy cache\000Local memory write accesses\000legacy-cach... */ + { 117035 }, + /* node-stores-miss\000legacy cache\000Local memory write misses\000legacy-cache-co... */ + { 117223 }, + /* node-stores-misses\000legacy cache\000Local memory write misses\000legacy-cache-... */ + { 117129 }, + /* node-stores-ops\000legacy cache\000Local memory write accesses\000legacy-cache-c... */ + { 116944 }, + /* node-stores-reference\000legacy cache\000Local memory write accesses\000legacy-c... */ + { 116847 }, + /* node-stores-refs\000legacy cache\000Local memory write accesses\000legacy-cache-... */ + { 116755 }, + /* node-write\000legacy cache\000Local memory write accesses\000legacy-cache-config... */ + { 117315 }, + /* node-write-access\000legacy cache\000Local memory write accesses\000legacy-cache... */ + { 117678 }, + /* node-write-miss\000legacy cache\000Local memory write misses\000legacy-cache-con... */ + { 117864 }, + /* node-write-misses\000legacy cache\000Local memory write misses\000legacy-cache-c... */ + { 117771 }, + /* node-write-ops\000legacy cache\000Local memory write accesses\000legacy-cache-co... */ + { 117588 }, + /* node-write-reference\000legacy cache\000Local memory write accesses\000legacy-ca... */ + { 117492 }, + /* node-write-refs\000legacy cache\000Local memory write accesses\000legacy-cache-c... */ + { 117401 }, + /* ref-cycles\000legacy hardware\000Total cycles; not affected by CPU frequency sca... */ + { 123400 }, + /* stalled-cycles-backend\000legacy hardware\000Stalled cycles during retirement [T... */ + { 123094 }, + /* stalled-cycles-frontend\000legacy hardware\000Stalled cycles during issue [This ... */ + { 122795 }, }; static const struct compact_pmu_event pmu_events__common_software[] = { -{ 124563 }, /* alignment-faults\000software\000Number of kernel handled memory alignment faults\000config=7\000\00000\000\000\000\000\000 */ -{ 124862 }, /* bpf-output\000software\000An event used by BPF programs to write to the perf ring buffer\000config=0xa\000\00000\000\000\000\000\000 */ -{ 124964 }, /* cgroup-switches\000software\000Number of context switches to a task in a different cgroup\000config=0xb\000\00000\000\000\000\000\000 */ -{ 123885 }, /* context-switches\000software\000Number of context switches [This event is an alias of cs]\000config=3\000\00000\000\000\000\000\000 */ -{ 123521 }, /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\000\000001e-6msec\000\000\000\000\000 */ -{ 124087 }, /* cpu-migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of migrations]\000config=4\000\00000\000\000\000\000\000 */ -{ 123986 }, /* cs\000software\000Number of context switches [This event is an alias of context-switches]\000config=3\000\00000\000\000\000\000\000 */ -{ 124782 }, /* dummy\000software\000A placeholder event that doesn't count anything\000config=9\000\00000\000\000\000\000\000 */ -{ 124655 }, /* emulation-faults\000software\000Number of kernel handled unimplemented instruction faults handled through emulation\000config=8\000\00000\000\000\000\000\000 */ -{ 123695 }, /* faults\000software\000Number of page faults [This event is an alias of page-faults]\000config=2\000\00000\000\000\000\000\000 */ -{ 124460 }, /* major-faults\000software\000Number of major page faults. Major faults require I/O to handle\000config=6\000\00000\000\000\000\000\000 */ -{ 124219 }, /* migrations\000software\000Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]\000config=4\000\00000\000\000\000\000\000 */ -{ 124351 }, /* minor-faults\000software\000Number of minor page faults. Minor faults don't require I/O to handle\000config=5\000\00000\000\000\000\000\000 */ -{ 123790 }, /* page-faults\000software\000Number of page faults [This event is an alias of faults]\000config=2\000\00000\000\000\000\000\000 */ -{ 123607 }, /* task-clock\000software\000Per-task high-resolution timer based event\000config=1\000\000001e-6msec\000\000\000\000\000 */ + /* alignment-faults\000software\000Number of kernel handled memory alignment faults... */ + { 124563 }, + /* bpf-output\000software\000An event used by BPF programs to write to the perf rin... */ + { 124862 }, + /* cgroup-switches\000software\000Number of context switches to a task in a differe... */ + { 124964 }, + /* context-switches\000software\000Number of context switches [This event is an ali... */ + { 123885 }, + /* cpu-clock\000software\000Per-CPU high-resolution timer based event\000config=0\0... */ + { 123521 }, + /* cpu-migrations\000software\000Number of times a process has migrated to a new CP... */ + { 124087 }, + /* cs\000software\000Number of context switches [This event is an alias of context-... */ + { 123986 }, + /* dummy\000software\000A placeholder event that doesn't count anything\000config=9... */ + { 124782 }, + /* emulation-faults\000software\000Number of kernel handled unimplemented instructi... */ + { 124655 }, + /* faults\000software\000Number of page faults [This event is an alias of page-faul... */ + { 123695 }, + /* major-faults\000software\000Number of major page faults. Major faults require I/... */ + { 124460 }, + /* migrations\000software\000Number of times a process has migrated to a new CPU [T... */ + { 124219 }, + /* minor-faults\000software\000Number of minor page faults. Minor faults don't requ... */ + { 124351 }, + /* page-faults\000software\000Number of page faults [This event is an alias of faul... */ + { 123790 }, + /* task-clock\000software\000Per-task high-resolution timer based event\000config=1... */ + { 123607 }, }; static const struct compact_pmu_event pmu_events__common_tool[] = { -{ 126205 }, /* core_wide\000tool\0001 if not SMT, if SMT are events being gathered on all SMT threads 1 otherwise 0\000config=0xd\000\00000\000\000\000\000\000 */ -{ 125072 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000\000\000\000 */ -{ 125286 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000\000\000\000 */ -{ 125362 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000\000\000\000 */ -{ 125507 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000\000\000\000 */ -{ 125610 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000\000\000\000 */ -{ 125727 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000\000\000\000 */ -{ 125803 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000\000\000\000 */ -{ 125889 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000\000\000\000 */ -{ 125999 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000\000\000\000 */ -{ 125218 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000\000\000\000 */ -{ 126106 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000\000\000\000 */ -{ 126319 }, /* target_cpu\000tool\0001 if CPUs being analyzed, 0 if threads/processes\000config=0xe\000\00000\000\000\000\000\000 */ -{ 125148 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000\000\000\000 */ + /* core_wide\000tool\0001 if not SMT, if SMT are events being gathered on all SMT t... */ + { 126205 }, + /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000... */ + { 125072 }, + /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000... */ + { 125286 }, + /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with ... */ + { 125362 }, + /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPU... */ + { 125507 }, + /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be mul... */ + { 125610 }, + /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000... */ + { 125727 }, + /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000co... */ + { 125803 }, + /* slots\000tool\000Number of functional units that in parallel can execute parts o... */ + { 125889 }, + /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enabl... */ + { 125999 }, + /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\0... */ + { 125218 }, + /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per s... */ + { 126106 }, + /* target_cpu\000tool\0001 if CPUs being analyzed, 0 if threads/processes\000config... */ + { 126319 }, + /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000... */ + { 125148 }, }; static const struct pmu_table_entry pmu_events__common[] = { -{ - .entries = pmu_events__common_default_core, - .num_entries = ARRAY_SIZE(pmu_events__common_default_core), - .pmu_name = { 0 /* default_core\000 */ }, -}, -{ - .entries = pmu_events__common_software, - .num_entries = ARRAY_SIZE(pmu_events__common_software), - .pmu_name = { 123512 /* software\000 */ }, -}, -{ - .entries = pmu_events__common_tool, - .num_entries = ARRAY_SIZE(pmu_events__common_tool), - .pmu_name = { 125067 /* tool\000 */ }, -}, + { + .entries = pmu_events__common_default_core, + .num_entries = ARRAY_SIZE(pmu_events__common_default_core), + .pmu_name = { 0 /* default_core\000 */ }, + }, + { + .entries = pmu_events__common_software, + .num_entries = ARRAY_SIZE(pmu_events__common_software), + .pmu_name = { 123512 /* software\000 */ }, + }, + { + .entries = pmu_events__common_tool, + .num_entries = ARRAY_SIZE(pmu_events__common_tool), + .pmu_name = { 125067 /* tool\000 */ }, + }, }; static const struct compact_pmu_event pmu_metrics__common_default_core[] = { -{ 127956 }, /* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011 */ -{ 129583 }, /* backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if has_event(stalled\\-cycles\\-backend) else 0)\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001 */ -{ 129933 }, /* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011 */ -{ 130113 }, /* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001 */ -{ 128142 }, /* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011 */ -{ 129757 }, /* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011 */ -{ 130549 }, /* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001 */ -{ 129404 }, /* frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles if has_event(stalled\\-cycles\\-frontend) else 0)\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001 */ -{ 128866 }, /* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001 */ -{ 130655 }, /* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001 */ -{ 130761 }, /* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001 */ -{ 130217 }, /* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001 */ -{ 130434 }, /* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001 */ -{ 130333 }, /* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001 */ -{ 128375 }, /* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011 */ -{ 128635 }, /* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011 */ -{ 128979 }, /* stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions if has_event(stalled\\-cycles\\-frontend) & has_event(stalled\\-cycles\\-backend) else (stalled\\-cycles\\-frontend / instructions if has_event(stalled\\-cycles\\-frontend) else (stalled\\-cycles\\-backend / instructions if has_event(stalled\\-cycles\\-backend) else 0)))\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001 */ + /* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #targ... */ + { 127956 }, + /* backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if ... */ + { 129583 }, + /* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-c... */ + { 129933 }, + /* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > ... */ + { 130113 }, + /* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switc... */ + { 128142 }, + /* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu... */ + { 129757 }, + /* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_r... */ + { 130549 }, + /* frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles i... */ + { 129404 }, + /* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\0... */ + { 128866 }, + /* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_r... */ + { 130655 }, + /* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcac... */ + { 130761 }, + /* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\0... */ + { 130217 }, + /* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\0... */ + { 130434 }, + /* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate ... */ + { 130333 }, + /* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-mig... */ + { 128375 }, + /* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faul... */ + { 128635 }, + /* stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, s... */ + { 128979 }, }; static const struct pmu_table_entry pmu_metrics__common[] = { -{ - .entries = pmu_metrics__common_default_core, - .num_entries = ARRAY_SIZE(pmu_metrics__common_default_core), - .pmu_name = { 0 /* default_core\000 */ }, -}, + { + .entries = pmu_metrics__common_default_core, + .num_entries = ARRAY_SIZE(pmu_metrics__common_default_core), + .pmu_name = { 0 /* default_core\000 */ }, + }, }; static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = { -{ 126403 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000 */ -{ 126465 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000 */ -{ 126727 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000 */ -{ 126860 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000 */ -{ 126527 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000 */ -{ 126625 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000 */ + /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000... */ + { 126403 }, + /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000... */ + { 126465 }, + /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispat... */ + { 126727 }, + /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) t... */ + { 126860 }, + /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\00... */ + { 126527 }, + /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,pe... */ + { 126625 }, }; static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = { -{ 126993 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000 */ + /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000... */ + { 126993 }, }; static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = { -{ 127355 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000 */ + /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\0... */ + { 127355 }, }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = { -{ 127229 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000 */ -{ 127283 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000 */ -{ 127075 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000 */ + /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000... */ + { 127229 }, + /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000... */ + { 127283 }, + /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted fro... */ + { 127075 }, }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = { -{ 127538 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000 */ + /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\... */ + { 127538 }, }; static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = { -{ 127447 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000 */ + /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12... */ + { 127447 }, }; static const struct pmu_table_entry pmu_events__test_soc_cpu[] = { -{ - .entries = pmu_events__test_soc_cpu_default_core, - .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core), - .pmu_name = { 0 /* default_core\000 */ }, -}, -{ - .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc, - .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc), - .pmu_name = { 126978 /* hisi_sccl,ddrc\000 */ }, -}, -{ - .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c, - .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c), - .pmu_name = { 127341 /* hisi_sccl,l3c\000 */ }, -}, -{ - .entries = pmu_events__test_soc_cpu_uncore_cbox, - .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox), - .pmu_name = { 127063 /* uncore_cbox\000 */ }, -}, -{ - .entries = pmu_events__test_soc_cpu_uncore_imc, - .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc), - .pmu_name = { 127527 /* uncore_imc\000 */ }, -}, -{ - .entries = pmu_events__test_soc_cpu_uncore_imc_free_running, - .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running), - .pmu_name = { 127423 /* uncore_imc_free_running\000 */ }, -}, + { + .entries = pmu_events__test_soc_cpu_default_core, + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core), + .pmu_name = { 0 /* default_core\000 */ }, + }, + { + .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc, + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc), + .pmu_name = { 126978 /* hisi_sccl,ddrc\000 */ }, + }, + { + .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c, + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c), + .pmu_name = { 127341 /* hisi_sccl,l3c\000 */ }, + }, + { + .entries = pmu_events__test_soc_cpu_uncore_cbox, + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox), + .pmu_name = { 127063 /* uncore_cbox\000 */ }, + }, + { + .entries = pmu_events__test_soc_cpu_uncore_imc, + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc), + .pmu_name = { 127527 /* uncore_imc\000 */ }, + }, + { + .entries = pmu_events__test_soc_cpu_uncore_imc_free_running, + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running), + .pmu_name = { 127423 /* uncore_imc_free_running\000 */ }, + }, }; static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { -{ 130909 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */ -{ 131598 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000 */ -{ 131368 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000 */ -{ 131463 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000 */ -{ 131663 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ -{ 131732 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000 */ -{ 130996 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000 */ -{ 130932 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000 */ -{ 131870 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000 */ -{ 131803 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */ -{ 131826 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */ -{ 131849 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */ -{ 131296 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000 */ -{ 131163 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ -{ 131228 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000 */ + /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */ + { 130909 }, + /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000... */ + { 131598 }, + /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqs... */ + { 131368 }, + /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data... */ + { 131463 }, + /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000... */ + { 131663 }, + /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\0... */ + { 131732 }, + /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.t... */ + { 130996 }, + /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\... */ + { 130932 }, + /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\... */ + { 131870 }, + /* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */ + { 131803 }, + /* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */ + { 131826 }, + /* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */ + { 131849 }, + /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\... */ + { 131296 }, + /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\0... */ + { 131163 }, + /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\00... */ + { 131228 }, }; static const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = { -{ - .entries = pmu_metrics__test_soc_cpu_default_core, - .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core), - .pmu_name = { 0 /* default_core\000 */ }, -}, + { + .entries = pmu_metrics__test_soc_cpu_default_core, + .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core), + .pmu_name = { 0 /* default_core\000 */ }, + }, }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = { -{ 127717 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000 */ + /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x0... */ + { 127717 }, }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = { -{ 127813 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000 */ + /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first looku... */ + { 127813 }, }; static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = { -{ 127622 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000 */ + /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8... */ + { 127622 }, }; static const struct pmu_table_entry pmu_events__test_soc_sys[] = { -{ - .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu, - .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu), - .pmu_name = { 127698 /* uncore_sys_ccn_pmu\000 */ }, -}, -{ - .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu, - .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu), - .pmu_name = { 127794 /* uncore_sys_cmn_pmu\000 */ }, -}, -{ - .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu, - .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu), - .pmu_name = { 127603 /* uncore_sys_ddr_pmu\000 */ }, -}, + { + .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu, + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu), + .pmu_name = { 127698 /* uncore_sys_ccn_pmu\000 */ }, + }, + { + .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu, + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu), + .pmu_name = { 127794 /* uncore_sys_cmn_pmu\000 */ }, + }, + { + .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu, + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu), + .pmu_name = { 127603 /* uncore_sys_ddr_pmu\000 */ }, + }, }; /* Struct used to make the PMU event table implementation opaque to callers. */ struct pmu_events_table { - const struct pmu_table_entry *pmus; - uint32_t num_pmus; + const struct pmu_table_entry *pmus; + uint32_t num_pmus; }; /* Struct used to make the PMU metric table implementation opaque to callers. */ struct pmu_metrics_table { - const struct pmu_table_entry *pmus; - uint32_t num_pmus; + const struct pmu_table_entry *pmus; + uint32_t num_pmus; }; /* @@ -2791,10 +5416,10 @@ struct pmu_metrics_table { * The cpuid can contain any character other than the comma. */ struct pmu_events_map { - const char *arch; - const char *cpuid; - struct pmu_events_table event_table; - struct pmu_metrics_table metric_table; + const char *arch; + const char *cpuid; + struct pmu_events_table event_table; + struct pmu_metrics_table metric_table; }; /* @@ -2915,456 +5540,455 @@ static void decompress_metric(int offset, struct pmu_metric *pm) } static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table, - const struct pmu_table_entry *pmu, - pmu_event_iter_fn fn, - void *data) + const struct pmu_table_entry *pmu, + pmu_event_iter_fn fn, + void *data) { - int ret; - struct pmu_event pe = { - .pmu = &big_c_string[pmu->pmu_name.offset], - }; + int ret; + struct pmu_event pe = { + .pmu = &big_c_string[pmu->pmu_name.offset], + }; - for (uint32_t i = 0; i < pmu->num_entries; i++) { - decompress_event(pmu->entries[i].offset, &pe); - if (!pe.name) - continue; - ret = fn(&pe, table, data); - if (ret) - return ret; - } - return 0; + for (uint32_t i = 0; i < pmu->num_entries; i++) { + decompress_event(pmu->entries[i].offset, &pe); + if (!pe.name) + continue; + ret = fn(&pe, table, data); + if (ret) + return ret; + } + return 0; } static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table, - const struct pmu_table_entry *pmu, - const char *name, - pmu_event_iter_fn fn, - void *data) + const struct pmu_table_entry *pmu, + const char *name, + pmu_event_iter_fn fn, + void *data) { - struct pmu_event pe = { - .pmu = &big_c_string[pmu->pmu_name.offset], - }; - int low = 0, high = pmu->num_entries - 1; + struct pmu_event pe = { + .pmu = &big_c_string[pmu->pmu_name.offset], + }; + int low = 0, high = pmu->num_entries - 1; - while (low <= high) { - int cmp, mid = (low + high) / 2; + while (low <= high) { + int cmp, mid = (low + high) / 2; - decompress_event(pmu->entries[mid].offset, &pe); + decompress_event(pmu->entries[mid].offset, &pe); - if (!pe.name && !name) - goto do_call; + if (!pe.name && !name) + goto do_call; - if (!pe.name && name) { - low = mid + 1; - continue; - } - if (pe.name && !name) { - high = mid - 1; - continue; - } + if (!pe.name && name) { + low = mid + 1; + continue; + } + if (pe.name && !name) { + high = mid - 1; + continue; + } - cmp = strcasecmp(pe.name, name); - if (cmp < 0) { - low = mid + 1; - continue; - } - if (cmp > 0) { - high = mid - 1; - continue; - } + cmp = strcasecmp(pe.name, name); + if (cmp < 0) { + low = mid + 1; + continue; + } + if (cmp > 0) { + high = mid - 1; + continue; + } do_call: - return fn ? fn(&pe, table, data) : 0; - } - return PMU_EVENTS__NOT_FOUND; + return fn ? fn(&pe, table, data) : 0; + } + return PMU_EVENTS__NOT_FOUND; } int pmu_events_table__for_each_event(const struct pmu_events_table *table, - struct perf_pmu *pmu, - pmu_event_iter_fn fn, - void *data) + struct perf_pmu *pmu, + pmu_event_iter_fn fn, + void *data) { - if (!table) - return 0; - for (size_t i = 0; i < table->num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &table->pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - int ret; + if (!table) + return 0; + for (size_t i = 0; i < table->num_pmus; i++) { + const struct pmu_table_entry *table_pmu = &table->pmus[i]; + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; + int ret; - if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) - continue; + if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) + continue; - ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); - if (ret) - return ret; - } - return 0; + ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); + if (ret) + return ret; + } + return 0; } int pmu_events_table__find_event(const struct pmu_events_table *table, - struct perf_pmu *pmu, - const char *name, - pmu_event_iter_fn fn, - void *data) + struct perf_pmu *pmu, + const char *name, + pmu_event_iter_fn fn, + void *data) { - if (!table) - return PMU_EVENTS__NOT_FOUND; - for (size_t i = 0; i < table->num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &table->pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - int ret; + if (!table) + return PMU_EVENTS__NOT_FOUND; + for (size_t i = 0; i < table->num_pmus; i++) { + const struct pmu_table_entry *table_pmu = &table->pmus[i]; + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; + int ret; - if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) - continue; + if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) + continue; - ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data); - if (ret != PMU_EVENTS__NOT_FOUND) - return ret; - } - return PMU_EVENTS__NOT_FOUND; + ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data); + if (ret != PMU_EVENTS__NOT_FOUND) + return ret; + } + return PMU_EVENTS__NOT_FOUND; } -size_t pmu_events_table__num_events(const struct pmu_events_table *table, - struct perf_pmu *pmu) +size_t pmu_events_table__num_events(const struct pmu_events_table *table, struct perf_pmu *pmu) { - size_t count = 0; + size_t count = 0; - if (!table) - return 0; - for (size_t i = 0; i < table->num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &table->pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; + if (!table) + return 0; + for (size_t i = 0; i < table->num_pmus; i++) { + const struct pmu_table_entry *table_pmu = &table->pmus[i]; + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - if (perf_pmu__name_wildcard_match(pmu, pmu_name)) - count += table_pmu->num_entries; - } - return count; + if (perf_pmu__name_wildcard_match(pmu, pmu_name)) + count += table_pmu->num_entries; + } + return count; } static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table, - const struct pmu_table_entry *pmu, - pmu_metric_iter_fn fn, - void *data) + const struct pmu_table_entry *pmu, + pmu_metric_iter_fn fn, + void *data) { - int ret; - struct pmu_metric pm = { - .pmu = &big_c_string[pmu->pmu_name.offset], - }; + int ret; + struct pmu_metric pm = { + .pmu = &big_c_string[pmu->pmu_name.offset], + }; - for (uint32_t i = 0; i < pmu->num_entries; i++) { - decompress_metric(pmu->entries[i].offset, &pm); - if (!pm.metric_expr) - continue; - ret = fn(&pm, table, data); - if (ret) - return ret; - } - return 0; + for (uint32_t i = 0; i < pmu->num_entries; i++) { + decompress_metric(pmu->entries[i].offset, &pm); + if (!pm.metric_expr) + continue; + ret = fn(&pm, table, data); + if (ret) + return ret; + } + return 0; } static int pmu_metrics_table__find_metric_pmu(const struct pmu_metrics_table *table, - const struct pmu_table_entry *pmu, - const char *metric, - pmu_metric_iter_fn fn, - void *data) + const struct pmu_table_entry *pmu, + const char *metric, + pmu_metric_iter_fn fn, + void *data) { - struct pmu_metric pm = { - .pmu = &big_c_string[pmu->pmu_name.offset], - }; - int low = 0, high = pmu->num_entries - 1; + struct pmu_metric pm = { + .pmu = &big_c_string[pmu->pmu_name.offset], + }; + int low = 0, high = pmu->num_entries - 1; - while (low <= high) { - int cmp, mid = (low + high) / 2; + while (low <= high) { + int cmp, mid = (low + high) / 2; - decompress_metric(pmu->entries[mid].offset, &pm); + decompress_metric(pmu->entries[mid].offset, &pm); - if (!pm.metric_name && !metric) - goto do_call; + if (!pm.metric_name && !metric) + goto do_call; - if (!pm.metric_name && metric) { - low = mid + 1; - continue; - } - if (pm.metric_name && !metric) { - high = mid - 1; - continue; - } + if (!pm.metric_name && metric) { + low = mid + 1; + continue; + } + if (pm.metric_name && !metric) { + high = mid - 1; + continue; + } - cmp = strcmp(pm.metric_name, metric); - if (cmp < 0) { - low = mid + 1; - continue; - } - if (cmp > 0) { - high = mid - 1; - continue; - } + cmp = strcmp(pm.metric_name, metric); + if (cmp < 0) { + low = mid + 1; + continue; + } + if (cmp > 0) { + high = mid - 1; + continue; + } do_call: - return fn ? fn(&pm, table, data) : 0; - } - return PMU_METRICS__NOT_FOUND; + return fn ? fn(&pm, table, data) : 0; + } + return PMU_METRICS__NOT_FOUND; } int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, - pmu_metric_iter_fn fn, - void *data) + pmu_metric_iter_fn fn, + void *data) { - if (!table) - return 0; - for (size_t i = 0; i < table->num_pmus; i++) { - int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i], - fn, data); + if (!table) + return 0; + for (size_t i = 0; i < table->num_pmus; i++) { + int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i], fn, data); - if (ret) - return ret; - } - return 0; + if (ret) + return ret; + } + return 0; } int pmu_metrics_table__find_metric(const struct pmu_metrics_table *table, - struct perf_pmu *pmu, - const char *metric, - pmu_metric_iter_fn fn, - void *data) + struct perf_pmu *pmu, + const char *metric, + pmu_metric_iter_fn fn, + void *data) { - if (!table) - return 0; - for (size_t i = 0; i < table->num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &table->pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - int ret; + if (!table) + return 0; + for (size_t i = 0; i < table->num_pmus; i++) { + const struct pmu_table_entry *table_pmu = &table->pmus[i]; + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; + int ret; - if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) - continue; + if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) + continue; - ret = pmu_metrics_table__find_metric_pmu(table, table_pmu, metric, fn, data); - if (ret != PMU_METRICS__NOT_FOUND) - return ret; - } - return PMU_METRICS__NOT_FOUND; + ret = pmu_metrics_table__find_metric_pmu(table, table_pmu, metric, fn, data); + if (ret != PMU_METRICS__NOT_FOUND) + return ret; + } + return PMU_METRICS__NOT_FOUND; } static const struct pmu_events_map *map_for_cpu(struct perf_cpu cpu) { - static struct { - const struct pmu_events_map *map; - struct perf_cpu cpu; - } last_result; - static struct { - const struct pmu_events_map *map; - char *cpuid; - } last_map_search; - static bool has_last_result, has_last_map_search; - const struct pmu_events_map *map = NULL; - char *cpuid = NULL; - size_t i; + static struct { + const struct pmu_events_map *map; + struct perf_cpu cpu; + } last_result; + static struct { + const struct pmu_events_map *map; + char *cpuid; + } last_map_search; + static bool has_last_result, has_last_map_search; + const struct pmu_events_map *map = NULL; + char *cpuid = NULL; + size_t i; - if (has_last_result && last_result.cpu.cpu == cpu.cpu) - return last_result.map; + if (has_last_result && last_result.cpu.cpu == cpu.cpu) + return last_result.map; - cpuid = get_cpuid_allow_env_override(cpu); + cpuid = get_cpuid_allow_env_override(cpu); - /* - * On some platforms which uses cpus map, cpuid can be NULL for - * PMUs other than CORE PMUs. - */ - if (!cpuid) - goto out_update_last_result; + /* + * On some platforms which uses cpus map, cpuid can be NULL for + * PMUs other than CORE PMUs. + */ + if (!cpuid) + goto out_update_last_result; - if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) { - map = last_map_search.map; - free(cpuid); - } else { - i = 0; - for (;;) { - map = &pmu_events_map[i++]; + if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) { + map = last_map_search.map; + free(cpuid); + } else { + i = 0; + for (;;) { + map = &pmu_events_map[i++]; - if (!map->arch) { - map = NULL; - break; - } + if (!map->arch) { + map = NULL; + break; + } - if (!strcmp_cpuid_str(map->cpuid, cpuid)) - break; - } - free(last_map_search.cpuid); - last_map_search.cpuid = cpuid; - last_map_search.map = map; - has_last_map_search = true; - } + if (!strcmp_cpuid_str(map->cpuid, cpuid)) + break; + } + free(last_map_search.cpuid); + last_map_search.cpuid = cpuid; + last_map_search.map = map; + has_last_map_search = true; + } out_update_last_result: - last_result.cpu = cpu; - last_result.map = map; - has_last_result = true; - return map; + last_result.cpu = cpu; + last_result.map = map; + has_last_result = true; + return map; } static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) { - struct perf_cpu cpu = {-1}; + struct perf_cpu cpu = { -1 }; - if (pmu) { - for (size_t i = 0; i < ARRAY_SIZE(pmu_events__common); i++) { - const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset]; + if (pmu) { + for (size_t i = 0; i < ARRAY_SIZE(pmu_events__common); i++) { + const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset]; - if (!strcmp(pmu_name, pmu->name)) { - const struct pmu_events_map *map = &pmu_events_map[0]; + if (!strcmp(pmu_name, pmu->name)) { + const struct pmu_events_map *map = &pmu_events_map[0]; - while (strcmp("common", map->arch)) - map++; - return map; - } - } - cpu = perf_cpu_map__min(pmu->cpus); - } - return map_for_cpu(cpu); + while (strcmp("common", map->arch)) + map++; + return map; + } + } + cpu = perf_cpu_map__min(pmu->cpus); + } + return map_for_cpu(cpu); } const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) { - const struct pmu_events_map *map = map_for_pmu(pmu); + const struct pmu_events_map *map = map_for_pmu(pmu); - if (!map) - return NULL; + if (!map) + return NULL; - if (!pmu) - return &map->event_table; + if (!pmu) + return &map->event_table; - for (size_t i = 0; i < map->event_table.num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; + for (size_t i = 0; i < map->event_table.num_pmus; i++) { + const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i]; + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - if (perf_pmu__name_wildcard_match(pmu, pmu_name)) - return &map->event_table; - } - return NULL; + if (perf_pmu__name_wildcard_match(pmu, pmu_name)) + return &map->event_table; + } + return NULL; } const struct pmu_events_table *perf_pmu__default_core_events_table(void) { - int i = 0; + int i = 0; - for (;;) { - const struct pmu_events_map *map = &pmu_events_map[i++]; + for (;;) { + const struct pmu_events_map *map = &pmu_events_map[i++]; - if (!map->arch) - break; + if (!map->arch) + break; - if (!strcmp(map->cpuid, "common")) - return &map->event_table; - } - return NULL; + if (!strcmp(map->cpuid, "common")) + return &map->event_table; + } + return NULL; } const struct pmu_metrics_table *pmu_metrics_table__find(void) { - struct perf_cpu cpu = {-1}; - const struct pmu_events_map *map = map_for_cpu(cpu); + struct perf_cpu cpu = { -1 }; + const struct pmu_events_map *map = map_for_cpu(cpu); - return map ? &map->metric_table : NULL; + return map ? &map->metric_table : NULL; } const struct pmu_metrics_table *pmu_metrics_table__default(void) { - int i = 0; + int i = 0; - for (;;) { - const struct pmu_events_map *map = &pmu_events_map[i++]; + for (;;) { + const struct pmu_events_map *map = &pmu_events_map[i++]; - if (!map->arch) - break; + if (!map->arch) + break; - if (!strcmp(map->cpuid, "common")) - return &map->metric_table; - } - return NULL; + if (!strcmp(map->cpuid, "common")) + return &map->metric_table; + } + return NULL; } const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) { - for (const struct pmu_events_map *tables = &pmu_events_map[0]; - tables->arch; - tables++) { - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) - return &tables->event_table; - } - return NULL; + for (const struct pmu_events_map *tables = &pmu_events_map[0]; + tables->arch; + tables++) { + if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) + return &tables->event_table; + } + return NULL; } const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid) { - for (const struct pmu_events_map *tables = &pmu_events_map[0]; - tables->arch; - tables++) { - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) - return &tables->metric_table; - } - return NULL; + for (const struct pmu_events_map *tables = &pmu_events_map[0]; + tables->arch; + tables++) { + if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) + return &tables->metric_table; + } + return NULL; } int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data) { - for (const struct pmu_events_map *tables = &pmu_events_map[0]; - tables->arch; - tables++) { - int ret = pmu_events_table__for_each_event(&tables->event_table, - /*pmu=*/ NULL, fn, data); + for (const struct pmu_events_map *tables = &pmu_events_map[0]; + tables->arch; + tables++) { + int ret = pmu_events_table__for_each_event(&tables->event_table, + /*pmu=*/NULL, fn, data); - if (ret) - return ret; - } - return 0; + if (ret) + return ret; + } + return 0; } int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data) { - for (const struct pmu_events_map *tables = &pmu_events_map[0]; - tables->arch; - tables++) { - int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); + for (const struct pmu_events_map *tables = &pmu_events_map[0]; + tables->arch; + tables++) { + int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); - if (ret) - return ret; - } - return 0; + if (ret) + return ret; + } + return 0; } const struct pmu_events_table *find_sys_events_table(const char *name) { - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; - tables->name; - tables++) { - if (!strcmp(tables->name, name)) - return &tables->event_table; - } - return NULL; + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; + tables->name; + tables++) { + if (!strcmp(tables->name, name)) + return &tables->event_table; + } + return NULL; } int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data) { - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; - tables->name; - tables++) { - int ret = pmu_events_table__for_each_event(&tables->event_table, - /*pmu=*/ NULL, fn, data); + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; + tables->name; + tables++) { + int ret = pmu_events_table__for_each_event(&tables->event_table, + /*pmu=*/NULL, fn, data); - if (ret) - return ret; - } - return 0; + if (ret) + return ret; + } + return 0; } int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data) { - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; - tables->name; - tables++) { - int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; + tables->name; + tables++) { + int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); - if (ret) - return ret; - } - return 0; + if (ret) + return ret; + } + return 0; } +/* clang-format on */ static const int metricgroups[][2] = { @@ -3372,20 +5996,19 @@ static const int metricgroups[][2] = { const char *describe_metricgroup(const char *group) { - int low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1; + int low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1; - while (low <= high) { - int mid = (low + high) / 2; - const char *mgroup = &big_c_string[metricgroups[mid][0]]; - int cmp = strcmp(mgroup, group); + while (low <= high) { + int mid = (low + high) / 2; + const char *mgroup = &big_c_string[metricgroups[mid][0]]; + int cmp = strcmp(mgroup, group); - if (cmp == 0) { - return &big_c_string[metricgroups[mid][1]]; - } else if (cmp < 0) { - low = mid + 1; - } else { - high = mid - 1; - } - } - return NULL; + if (cmp == 0) + return &big_c_string[metricgroups[mid][1]]; + else if (cmp < 0) + low = mid + 1; + else + high = mid - 1; + } + return NULL; } diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 7344940e776a..4279e385f243 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -183,7 +183,7 @@ class BigCString: for s in sorted(self.strings, key=string_cmp_key): if s not in folded_strings: self.offsets[s] = big_string_offset - self.big_string.append(f'/* offset={big_string_offset} */ "') + self.big_string.append(f'/* offset={big_string_offset} */\n"') self.big_string.append(s) self.big_string.append('"') if s in fold_into_strings: @@ -450,11 +450,12 @@ class JsonEvent: def to_c_string(self, metric: bool) -> str: """Representation of the event as a C struct initializer.""" - def fix_comment(s: str) -> str: - return s.replace('*/', r'\*\/') + def make_comment(s: str) -> str: + s = s.replace('*/', r'\*\/') + return f'\t/* {s} */\n' if len(s) < 80 else f'\t/* {s[0:80]}... */\n' s = self.build_c_string(metric) - return f'{{ { _bcs.offsets[s] } }}, /* {fix_comment(s)} */\n' + return f'{make_comment(s)}\t{{ { _bcs.offsets[s] } }},\n' @lru_cache(maxsize=None) @@ -558,11 +559,11 @@ static const struct pmu_table_entry {_pending_events_tblname}[] = {{ """) for (pmu, tbl_pmu) in sorted(pmus): pmu_name = f"{pmu}\\000" - _args.output_file.write(f"""{{ - .entries = {_pending_events_tblname}_{tbl_pmu}, - .num_entries = ARRAY_SIZE({_pending_events_tblname}_{tbl_pmu}), - .pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }}, -}}, + _args.output_file.write(f"""\t{{ +\t\t.entries = {_pending_events_tblname}_{tbl_pmu}, +\t\t.num_entries = ARRAY_SIZE({_pending_events_tblname}_{tbl_pmu}), +\t\t.pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }}, +\t}}, """) _args.output_file.write('};\n\n') @@ -613,11 +614,11 @@ static const struct pmu_table_entry {_pending_metrics_tblname}[] = {{ """) for (pmu, tbl_pmu) in sorted(pmus): pmu_name = f"{pmu}\\000" - _args.output_file.write(f"""{{ - .entries = {_pending_metrics_tblname}_{tbl_pmu}, - .num_entries = ARRAY_SIZE({_pending_metrics_tblname}_{tbl_pmu}), - .pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }}, -}}, + _args.output_file.write(f"""\t{{ +\t\t.entries = {_pending_metrics_tblname}_{tbl_pmu}, +\t\t.num_entries = ARRAY_SIZE({_pending_metrics_tblname}_{tbl_pmu}), +\t\t.pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }}, +\t}}, """) _args.output_file.write('};\n\n') @@ -705,14 +706,14 @@ def print_mapping_table(archs: Sequence[str]) -> None: _args.output_file.write(""" /* Struct used to make the PMU event table implementation opaque to callers. */ struct pmu_events_table { - const struct pmu_table_entry *pmus; - uint32_t num_pmus; +\tconst struct pmu_table_entry *pmus; +\tuint32_t num_pmus; }; /* Struct used to make the PMU metric table implementation opaque to callers. */ struct pmu_metrics_table { - const struct pmu_table_entry *pmus; - uint32_t num_pmus; +\tconst struct pmu_table_entry *pmus; +\tuint32_t num_pmus; }; /* @@ -724,10 +725,10 @@ struct pmu_metrics_table { * The cpuid can contain any character other than the comma. */ struct pmu_events_map { - const char *arch; - const char *cpuid; - struct pmu_events_table event_table; - struct pmu_metrics_table metric_table; +\tconst char *arch; +\tconst char *cpuid; +\tstruct pmu_events_table event_table; +\tstruct pmu_metrics_table metric_table; }; /* @@ -896,455 +897,453 @@ static void decompress_metric(int offset, struct pmu_metric *pm) _args.output_file.write("""} static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table, - const struct pmu_table_entry *pmu, - pmu_event_iter_fn fn, - void *data) +\t\t\t\t\t\tconst struct pmu_table_entry *pmu, +\t\t\t\t\t\tpmu_event_iter_fn fn, +\t\t\t\t\t\tvoid *data) { - int ret; - struct pmu_event pe = { - .pmu = &big_c_string[pmu->pmu_name.offset], - }; +\tint ret; +\tstruct pmu_event pe = { +\t\t.pmu = &big_c_string[pmu->pmu_name.offset], +\t}; - for (uint32_t i = 0; i < pmu->num_entries; i++) { - decompress_event(pmu->entries[i].offset, &pe); - if (!pe.name) - continue; - ret = fn(&pe, table, data); - if (ret) - return ret; - } - return 0; +\tfor (uint32_t i = 0; i < pmu->num_entries; i++) { +\t\tdecompress_event(pmu->entries[i].offset, &pe); +\t\tif (!pe.name) +\t\t\tcontinue; +\t\tret = fn(&pe, table, data); +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; } static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table, - const struct pmu_table_entry *pmu, - const char *name, - pmu_event_iter_fn fn, - void *data) +\t\t\t\t\t const struct pmu_table_entry *pmu, +\t\t\t\t\t const char *name, +\t\t\t\t\t pmu_event_iter_fn fn, +\t\t\t\t\t void *data) { - struct pmu_event pe = { - .pmu = &big_c_string[pmu->pmu_name.offset], - }; - int low = 0, high = pmu->num_entries - 1; +\tstruct pmu_event pe = { +\t\t.pmu = &big_c_string[pmu->pmu_name.offset], +\t}; +\tint low = 0, high = pmu->num_entries - 1; - while (low <= high) { - int cmp, mid = (low + high) / 2; +\twhile (low <= high) { +\t\tint cmp, mid = (low + high) / 2; - decompress_event(pmu->entries[mid].offset, &pe); +\t\tdecompress_event(pmu->entries[mid].offset, &pe); - if (!pe.name && !name) - goto do_call; +\t\tif (!pe.name && !name) +\t\t\tgoto do_call; - if (!pe.name && name) { - low = mid + 1; - continue; - } - if (pe.name && !name) { - high = mid - 1; - continue; - } +\t\tif (!pe.name && name) { +\t\t\tlow = mid + 1; +\t\t\tcontinue; +\t\t} +\t\tif (pe.name && !name) { +\t\t\thigh = mid - 1; +\t\t\tcontinue; +\t\t} - cmp = strcasecmp(pe.name, name); - if (cmp < 0) { - low = mid + 1; - continue; - } - if (cmp > 0) { - high = mid - 1; - continue; - } +\t\tcmp = strcasecmp(pe.name, name); +\t\tif (cmp < 0) { +\t\t\tlow = mid + 1; +\t\t\tcontinue; +\t\t} +\t\tif (cmp > 0) { +\t\t\thigh = mid - 1; +\t\t\tcontinue; +\t\t} do_call: - return fn ? fn(&pe, table, data) : 0; - } - return PMU_EVENTS__NOT_FOUND; +\t\treturn fn ? fn(&pe, table, data) : 0; +\t} +\treturn PMU_EVENTS__NOT_FOUND; } int pmu_events_table__for_each_event(const struct pmu_events_table *table, - struct perf_pmu *pmu, - pmu_event_iter_fn fn, - void *data) +\t\t\t\t struct perf_pmu *pmu, +\t\t\t\t pmu_event_iter_fn fn, +\t\t\t\t void *data) { - if (!table) - return 0; - for (size_t i = 0; i < table->num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &table->pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - int ret; +\tif (!table) +\t\treturn 0; +\tfor (size_t i = 0; i < table->num_pmus; i++) { +\t\tconst struct pmu_table_entry *table_pmu = &table->pmus[i]; +\t\tconst char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; +\t\tint ret; - if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) - continue; +\t\tif (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) +\t\t\tcontinue; - ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); - if (ret) - return ret; - } - return 0; +\t\tret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; } int pmu_events_table__find_event(const struct pmu_events_table *table, - struct perf_pmu *pmu, - const char *name, - pmu_event_iter_fn fn, - void *data) +\t\t\t\t struct perf_pmu *pmu, +\t\t\t\t const char *name, +\t\t\t\t pmu_event_iter_fn fn, +\t\t\t\t void *data) { - if (!table) - return PMU_EVENTS__NOT_FOUND; - for (size_t i = 0; i < table->num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &table->pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - int ret; +\tif (!table) +\t\treturn PMU_EVENTS__NOT_FOUND; +\tfor (size_t i = 0; i < table->num_pmus; i++) { +\t\tconst struct pmu_table_entry *table_pmu = &table->pmus[i]; +\t\tconst char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; +\t\tint ret; - if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) - continue; +\t\tif (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) +\t\t\tcontinue; - ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data); - if (ret != PMU_EVENTS__NOT_FOUND) - return ret; - } - return PMU_EVENTS__NOT_FOUND; +\t\tret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data); +\t\tif (ret != PMU_EVENTS__NOT_FOUND) +\t\t\treturn ret; +\t} +\treturn PMU_EVENTS__NOT_FOUND; } -size_t pmu_events_table__num_events(const struct pmu_events_table *table, - struct perf_pmu *pmu) +size_t pmu_events_table__num_events(const struct pmu_events_table *table, struct perf_pmu *pmu) { - size_t count = 0; +\tsize_t count = 0; - if (!table) - return 0; - for (size_t i = 0; i < table->num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &table->pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; +\tif (!table) +\t\treturn 0; +\tfor (size_t i = 0; i < table->num_pmus; i++) { +\t\tconst struct pmu_table_entry *table_pmu = &table->pmus[i]; +\t\tconst char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - if (perf_pmu__name_wildcard_match(pmu, pmu_name)) - count += table_pmu->num_entries; - } - return count; +\t\tif (perf_pmu__name_wildcard_match(pmu, pmu_name)) +\t\t\tcount += table_pmu->num_entries; +\t} +\treturn count; } static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table, - const struct pmu_table_entry *pmu, - pmu_metric_iter_fn fn, - void *data) +\t\t\t\t\t\tconst struct pmu_table_entry *pmu, +\t\t\t\t\t\tpmu_metric_iter_fn fn, +\t\t\t\t\t\tvoid *data) { - int ret; - struct pmu_metric pm = { - .pmu = &big_c_string[pmu->pmu_name.offset], - }; +\tint ret; +\tstruct pmu_metric pm = { +\t\t.pmu = &big_c_string[pmu->pmu_name.offset], +\t}; - for (uint32_t i = 0; i < pmu->num_entries; i++) { - decompress_metric(pmu->entries[i].offset, &pm); - if (!pm.metric_expr) - continue; - ret = fn(&pm, table, data); - if (ret) - return ret; - } - return 0; +\tfor (uint32_t i = 0; i < pmu->num_entries; i++) { +\t\tdecompress_metric(pmu->entries[i].offset, &pm); +\t\tif (!pm.metric_expr) +\t\t\tcontinue; +\t\tret = fn(&pm, table, data); +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; } static int pmu_metrics_table__find_metric_pmu(const struct pmu_metrics_table *table, - const struct pmu_table_entry *pmu, - const char *metric, - pmu_metric_iter_fn fn, - void *data) +\t\t\t\t\t const struct pmu_table_entry *pmu, +\t\t\t\t\t const char *metric, +\t\t\t\t\t pmu_metric_iter_fn fn, +\t\t\t\t\t void *data) { - struct pmu_metric pm = { - .pmu = &big_c_string[pmu->pmu_name.offset], - }; - int low = 0, high = pmu->num_entries - 1; +\tstruct pmu_metric pm = { +\t\t.pmu = &big_c_string[pmu->pmu_name.offset], +\t}; +\tint low = 0, high = pmu->num_entries - 1; - while (low <= high) { - int cmp, mid = (low + high) / 2; +\twhile (low <= high) { +\t\tint cmp, mid = (low + high) / 2; - decompress_metric(pmu->entries[mid].offset, &pm); +\t\tdecompress_metric(pmu->entries[mid].offset, &pm); - if (!pm.metric_name && !metric) - goto do_call; +\t\tif (!pm.metric_name && !metric) +\t\t\tgoto do_call; - if (!pm.metric_name && metric) { - low = mid + 1; - continue; - } - if (pm.metric_name && !metric) { - high = mid - 1; - continue; - } +\t\tif (!pm.metric_name && metric) { +\t\t\tlow = mid + 1; +\t\t\tcontinue; +\t\t} +\t\tif (pm.metric_name && !metric) { +\t\t\thigh = mid - 1; +\t\t\tcontinue; +\t\t} - cmp = strcmp(pm.metric_name, metric); - if (cmp < 0) { - low = mid + 1; - continue; - } - if (cmp > 0) { - high = mid - 1; - continue; - } +\t\tcmp = strcmp(pm.metric_name, metric); +\t\tif (cmp < 0) { +\t\t\tlow = mid + 1; +\t\t\tcontinue; +\t\t} +\t\tif (cmp > 0) { +\t\t\thigh = mid - 1; +\t\t\tcontinue; +\t\t} do_call: - return fn ? fn(&pm, table, data) : 0; - } - return PMU_METRICS__NOT_FOUND; +\t\treturn fn ? fn(&pm, table, data) : 0; +\t} +\treturn PMU_METRICS__NOT_FOUND; } int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, - pmu_metric_iter_fn fn, - void *data) +\t\t\t\t pmu_metric_iter_fn fn, +\t\t\t\t void *data) { - if (!table) - return 0; - for (size_t i = 0; i < table->num_pmus; i++) { - int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i], - fn, data); +\tif (!table) +\t\treturn 0; +\tfor (size_t i = 0; i < table->num_pmus; i++) { +\t\tint ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i], fn, data); - if (ret) - return ret; - } - return 0; +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; } int pmu_metrics_table__find_metric(const struct pmu_metrics_table *table, - struct perf_pmu *pmu, - const char *metric, - pmu_metric_iter_fn fn, - void *data) +\t\t\t\t struct perf_pmu *pmu, +\t\t\t\t const char *metric, +\t\t\t\t pmu_metric_iter_fn fn, +\t\t\t\t void *data) { - if (!table) - return 0; - for (size_t i = 0; i < table->num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &table->pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - int ret; +\tif (!table) +\t\treturn 0; +\tfor (size_t i = 0; i < table->num_pmus; i++) { +\t\tconst struct pmu_table_entry *table_pmu = &table->pmus[i]; +\t\tconst char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; +\t\tint ret; - if (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) - continue; +\t\tif (pmu && !perf_pmu__name_wildcard_match(pmu, pmu_name)) +\t\t\tcontinue; - ret = pmu_metrics_table__find_metric_pmu(table, table_pmu, metric, fn, data); - if (ret != PMU_METRICS__NOT_FOUND) - return ret; - } - return PMU_METRICS__NOT_FOUND; +\t\tret = pmu_metrics_table__find_metric_pmu(table, table_pmu, metric, fn, data); +\t\tif (ret != PMU_METRICS__NOT_FOUND) +\t\t\treturn ret; +\t} +\treturn PMU_METRICS__NOT_FOUND; } static const struct pmu_events_map *map_for_cpu(struct perf_cpu cpu) { - static struct { - const struct pmu_events_map *map; - struct perf_cpu cpu; - } last_result; - static struct { - const struct pmu_events_map *map; - char *cpuid; - } last_map_search; - static bool has_last_result, has_last_map_search; - const struct pmu_events_map *map = NULL; - char *cpuid = NULL; - size_t i; +\tstatic struct { +\t\tconst struct pmu_events_map *map; +\t\tstruct perf_cpu cpu; +\t} last_result; +\tstatic struct { +\t\tconst struct pmu_events_map *map; +\t\tchar *cpuid; +\t} last_map_search; +\tstatic bool has_last_result, has_last_map_search; +\tconst struct pmu_events_map *map = NULL; +\tchar *cpuid = NULL; +\tsize_t i; - if (has_last_result && last_result.cpu.cpu == cpu.cpu) - return last_result.map; +\tif (has_last_result && last_result.cpu.cpu == cpu.cpu) +\t\treturn last_result.map; - cpuid = get_cpuid_allow_env_override(cpu); +\tcpuid = get_cpuid_allow_env_override(cpu); - /* - * On some platforms which uses cpus map, cpuid can be NULL for - * PMUs other than CORE PMUs. - */ - if (!cpuid) - goto out_update_last_result; +\t/* +\t * On some platforms which uses cpus map, cpuid can be NULL for +\t * PMUs other than CORE PMUs. +\t */ +\tif (!cpuid) +\t\tgoto out_update_last_result; - if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) { - map = last_map_search.map; - free(cpuid); - } else { - i = 0; - for (;;) { - map = &pmu_events_map[i++]; +\tif (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) { +\t\tmap = last_map_search.map; +\t\tfree(cpuid); +\t} else { +\t\ti = 0; +\t\tfor (;;) { +\t\t\tmap = &pmu_events_map[i++]; - if (!map->arch) { - map = NULL; - break; - } +\t\t\tif (!map->arch) { +\t\t\t\tmap = NULL; +\t\t\t\tbreak; +\t\t\t} - if (!strcmp_cpuid_str(map->cpuid, cpuid)) - break; - } - free(last_map_search.cpuid); - last_map_search.cpuid = cpuid; - last_map_search.map = map; - has_last_map_search = true; - } +\t\t\tif (!strcmp_cpuid_str(map->cpuid, cpuid)) +\t\t\t\tbreak; +\t\t} +\t\tfree(last_map_search.cpuid); +\t\tlast_map_search.cpuid = cpuid; +\t\tlast_map_search.map = map; +\t\thas_last_map_search = true; +\t} out_update_last_result: - last_result.cpu = cpu; - last_result.map = map; - has_last_result = true; - return map; +\tlast_result.cpu = cpu; +\tlast_result.map = map; +\thas_last_result = true; +\treturn map; } static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) { - struct perf_cpu cpu = {-1}; +\tstruct perf_cpu cpu = { -1 }; - if (pmu) { - for (size_t i = 0; i < ARRAY_SIZE(pmu_events__common); i++) { - const char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset]; +\tif (pmu) { +\t\tfor (size_t i = 0; i < ARRAY_SIZE(pmu_events__common); i++) { +\t\t\tconst char *pmu_name = &big_c_string[pmu_events__common[i].pmu_name.offset]; - if (!strcmp(pmu_name, pmu->name)) { - const struct pmu_events_map *map = &pmu_events_map[0]; +\t\t\tif (!strcmp(pmu_name, pmu->name)) { +\t\t\t\tconst struct pmu_events_map *map = &pmu_events_map[0]; - while (strcmp("common", map->arch)) - map++; - return map; - } - } - cpu = perf_cpu_map__min(pmu->cpus); - } - return map_for_cpu(cpu); +\t\t\t\twhile (strcmp("common", map->arch)) +\t\t\t\t\tmap++; +\t\t\t\treturn map; +\t\t\t} +\t\t} +\t\tcpu = perf_cpu_map__min(pmu->cpus); +\t} +\treturn map_for_cpu(cpu); } const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) { - const struct pmu_events_map *map = map_for_pmu(pmu); +\tconst struct pmu_events_map *map = map_for_pmu(pmu); - if (!map) - return NULL; +\tif (!map) +\t\treturn NULL; - if (!pmu) - return &map->event_table; +\tif (!pmu) +\t\treturn &map->event_table; - for (size_t i = 0; i < map->event_table.num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i]; - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; +\tfor (size_t i = 0; i < map->event_table.num_pmus; i++) { +\t\tconst struct pmu_table_entry *table_pmu = &map->event_table.pmus[i]; +\t\tconst char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; - if (perf_pmu__name_wildcard_match(pmu, pmu_name)) - return &map->event_table; - } - return NULL; +\t\tif (perf_pmu__name_wildcard_match(pmu, pmu_name)) +\t\t\treturn &map->event_table; +\t} +\treturn NULL; } const struct pmu_events_table *perf_pmu__default_core_events_table(void) { - int i = 0; +\tint i = 0; - for (;;) { - const struct pmu_events_map *map = &pmu_events_map[i++]; +\tfor (;;) { +\t\tconst struct pmu_events_map *map = &pmu_events_map[i++]; - if (!map->arch) - break; +\t\tif (!map->arch) +\t\t\tbreak; - if (!strcmp(map->cpuid, "common")) - return &map->event_table; - } - return NULL; +\t\tif (!strcmp(map->cpuid, "common")) +\t\t\treturn &map->event_table; +\t} +\treturn NULL; } const struct pmu_metrics_table *pmu_metrics_table__find(void) { - struct perf_cpu cpu = {-1}; - const struct pmu_events_map *map = map_for_cpu(cpu); +\tstruct perf_cpu cpu = { -1 }; +\tconst struct pmu_events_map *map = map_for_cpu(cpu); - return map ? &map->metric_table : NULL; +\treturn map ? &map->metric_table : NULL; } const struct pmu_metrics_table *pmu_metrics_table__default(void) { - int i = 0; +\tint i = 0; - for (;;) { - const struct pmu_events_map *map = &pmu_events_map[i++]; +\tfor (;;) { +\t\tconst struct pmu_events_map *map = &pmu_events_map[i++]; - if (!map->arch) - break; +\t\tif (!map->arch) +\t\t\tbreak; - if (!strcmp(map->cpuid, "common")) - return &map->metric_table; - } - return NULL; +\t\tif (!strcmp(map->cpuid, "common")) +\t\t\treturn &map->metric_table; +\t} +\treturn NULL; } const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) { - for (const struct pmu_events_map *tables = &pmu_events_map[0]; - tables->arch; - tables++) { - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) - return &tables->event_table; - } - return NULL; +\tfor (const struct pmu_events_map *tables = &pmu_events_map[0]; +\t tables->arch; +\t tables++) { +\t\tif (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) +\t\t\treturn &tables->event_table; +\t} +\treturn NULL; } const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid) { - for (const struct pmu_events_map *tables = &pmu_events_map[0]; - tables->arch; - tables++) { - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) - return &tables->metric_table; - } - return NULL; +\tfor (const struct pmu_events_map *tables = &pmu_events_map[0]; +\t tables->arch; +\t tables++) { +\t\tif (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid)) +\t\t\treturn &tables->metric_table; +\t} +\treturn NULL; } int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data) { - for (const struct pmu_events_map *tables = &pmu_events_map[0]; - tables->arch; - tables++) { - int ret = pmu_events_table__for_each_event(&tables->event_table, - /*pmu=*/ NULL, fn, data); +\tfor (const struct pmu_events_map *tables = &pmu_events_map[0]; +\t tables->arch; +\t tables++) { +\t\tint ret = pmu_events_table__for_each_event(&tables->event_table, +\t\t\t\t\t\t\t /*pmu=*/NULL, fn, data); - if (ret) - return ret; - } - return 0; +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; } int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data) { - for (const struct pmu_events_map *tables = &pmu_events_map[0]; - tables->arch; - tables++) { - int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); +\tfor (const struct pmu_events_map *tables = &pmu_events_map[0]; +\t tables->arch; +\t tables++) { +\t\tint ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); - if (ret) - return ret; - } - return 0; +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; } const struct pmu_events_table *find_sys_events_table(const char *name) { - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; - tables->name; - tables++) { - if (!strcmp(tables->name, name)) - return &tables->event_table; - } - return NULL; +\tfor (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; +\t tables->name; +\t tables++) { +\t\tif (!strcmp(tables->name, name)) +\t\t\treturn &tables->event_table; +\t} +\treturn NULL; } int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data) { - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; - tables->name; - tables++) { - int ret = pmu_events_table__for_each_event(&tables->event_table, - /*pmu=*/ NULL, fn, data); +\tfor (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; +\t tables->name; +\t tables++) { +\t\tint ret = pmu_events_table__for_each_event(&tables->event_table, +\t\t\t\t\t\t\t /*pmu=*/NULL, fn, data); - if (ret) - return ret; - } - return 0; +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; } int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data) { - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; - tables->name; - tables++) { - int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); +\tfor (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; +\t tables->name; +\t tables++) { +\t\tint ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data); - if (ret) - return ret; - } - return 0; +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; } """) @@ -1362,22 +1361,21 @@ static const int metricgroups[][2] = { const char *describe_metricgroup(const char *group) { - int low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1; +\tint low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1; - while (low <= high) { - int mid = (low + high) / 2; - const char *mgroup = &big_c_string[metricgroups[mid][0]]; - int cmp = strcmp(mgroup, group); +\twhile (low <= high) { +\t\tint mid = (low + high) / 2; +\t\tconst char *mgroup = &big_c_string[metricgroups[mid][0]]; +\t\tint cmp = strcmp(mgroup, group); - if (cmp == 0) { - return &big_c_string[metricgroups[mid][1]]; - } else if (cmp < 0) { - low = mid + 1; - } else { - high = mid - 1; - } - } - return NULL; +\t\tif (cmp == 0) +\t\t\treturn &big_c_string[metricgroups[mid][1]]; +\t\telse if (cmp < 0) +\t\t\tlow = mid + 1; +\t\telse +\t\t\thigh = mid - 1; +\t} +\treturn NULL; } """) @@ -1426,9 +1424,8 @@ such as "arm/cortex-a34".''', 'output_string_file', type=argparse.FileType('w', encoding='utf-8'), nargs='?', default=None) _args = ap.parse_args() - _args.output_file.write(f""" -/* SPDX-License-Identifier: GPL-2.0 */ -/* THIS FILE WAS AUTOGENERATED BY jevents.py arch={_args.arch} model={_args.model} ! */ + _args.output_file.write(f"""/* SPDX-License-Identifier: GPL-2.0 */ +/* THIS FILE WAS AUTOGENERATED BY `jevents.py arch={_args.arch} model={_args.model}` ! */ """) _args.output_file.write(""" #include @@ -1438,13 +1435,13 @@ such as "arm/cortex-a34".''', #include struct compact_pmu_event { - int offset; +\tint offset; }; struct pmu_table_entry { - const struct compact_pmu_event *entries; - uint32_t num_entries; - struct compact_pmu_event pmu_name; +\tconst struct compact_pmu_event *entries; +\tuint32_t num_entries; +\tstruct compact_pmu_event pmu_name; }; """) @@ -1465,6 +1462,7 @@ struct pmu_table_entry { ftw(arch_path, [], preprocess_one_file) _bcs.compute() + _args.output_file.write('/* clang-format off */\n') if not _args.output_string_file: _args.output_file.write('static const char *const big_c_string =\n') for s in _bcs.big_string: @@ -1487,6 +1485,7 @@ struct pmu_table_entry { print_mapping_table(archs) print_system_mapping_table() + _args.output_file.write('/* clang-format on */\n') print_metricgroups() _args.output_file.close() if _args.output_string_file: From 53247b207bd02116cefd3409494382e7adf32849 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:14 -0700 Subject: [PATCH 204/343] perf pmu-events: Add API to get metric table name and iterate tables Add name field to struct pmu_metrics_table and populate it in generated tables. Add pmu_metrics_table__name() to retrieve the name. Add pmu_metrics_table__for_each_table() to iterate over all known metric tables. This will be used to break apart slow metric tests per table. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/pmu-events/empty-pmu-events.c | 46 ++++++++++++++++++- tools/perf/pmu-events/jevents.py | 56 +++++++++++++++++++++++- tools/perf/pmu-events/pmu-events.h | 5 +++ 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index ad5ade37adb0..2af4865713be 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -5403,6 +5403,7 @@ struct pmu_events_table { /* Struct used to make the PMU metric table implementation opaque to callers. */ struct pmu_metrics_table { + const char *name; const struct pmu_table_entry *pmus; uint32_t num_pmus; }; @@ -5435,6 +5436,7 @@ static const struct pmu_events_map pmu_events_map[] = { .num_pmus = ARRAY_SIZE(pmu_events__common), }, .metric_table = { + .name = "common", .pmus = pmu_metrics__common, .num_pmus = ARRAY_SIZE(pmu_metrics__common), }, @@ -5447,6 +5449,7 @@ static const struct pmu_events_map pmu_events_map[] = { .num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu), }, .metric_table = { + .name = "test_soc_cpu", .pmus = pmu_metrics__test_soc_cpu, .num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu), } @@ -5455,7 +5458,7 @@ static const struct pmu_events_map pmu_events_map[] = { .arch = 0, .cpuid = 0, .event_table = { 0, 0 }, - .metric_table = { 0, 0 }, + .metric_table = { 0 }, } }; @@ -5475,7 +5478,7 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = { }, { .event_table = { 0, 0 }, - .metric_table = { 0, 0 }, + .metric_table = { 0 }, }, }; @@ -5990,6 +5993,45 @@ int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data) } /* clang-format on */ +const char *pmu_metrics_table__name(const struct pmu_metrics_table *table) +{ + return table ? table->name : NULL; +} + +int pmu_metrics_table__iterate_tables(pmu_metrics_table_iter_t fn, void *data) +{ + size_t i; + int ret; + + for (i = 0; pmu_events_map[i].cpuid; i++) { + size_t j; + bool found = false; + + if (!pmu_events_map[i].metric_table.pmus) + continue; + for (j = 0; j < i; j++) { + if (pmu_events_map[j].metric_table.pmus == + pmu_events_map[i].metric_table.pmus) { + found = true; + break; + } + } + if (found) + continue; + ret = fn(&pmu_events_map[i].metric_table, data); + if (ret) + return ret; + } + for (i = 0; pmu_sys_event_tables[i].name; i++) { + if (!pmu_sys_event_tables[i].metric_table.pmus) + continue; + ret = fn(&pmu_sys_event_tables[i].metric_table, data); + if (ret) + return ret; + } + return 0; +} + static const int metricgroups[][2] = { }; diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 4279e385f243..376dc2d24162 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -712,6 +712,7 @@ struct pmu_events_table { /* Struct used to make the PMU metric table implementation opaque to callers. */ struct pmu_metrics_table { +\tconst char *name; \tconst struct pmu_table_entry *pmus; \tuint32_t num_pmus; }; @@ -747,6 +748,7 @@ static const struct pmu_events_map pmu_events_map[] = { \t\t.num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu), \t}, \t.metric_table = { +\t\t.name = "test_soc_cpu", \t\t.pmus = pmu_metrics__test_soc_cpu, \t\t.num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu), \t} @@ -761,6 +763,7 @@ static const struct pmu_events_map pmu_events_map[] = { \t\t.num_pmus = ARRAY_SIZE(pmu_events__common), \t}, \t.metric_table = { +\t\t.name = "common", \t\t.pmus = pmu_metrics__common, \t\t.num_pmus = ARRAY_SIZE(pmu_metrics__common), \t}, @@ -781,8 +784,10 @@ static const struct pmu_events_map pmu_events_map[] = { event_size = '0' metric_tblname = file_name_to_table_name('pmu_metrics_', [], row[2].replace('/', '_')) if metric_tblname in _metric_tables: + metric_name = f'"{metric_tblname.replace("pmu_metrics__", "")}"' metric_size = f'ARRAY_SIZE({metric_tblname})' else: + metric_name = 'NULL' metric_tblname = 'NULL' metric_size = '0' if event_size == '0' and metric_size == '0': @@ -796,6 +801,7 @@ static const struct pmu_events_map pmu_events_map[] = { \t\t.num_pmus = {event_size} \t}}, \t.metric_table = {{ +\t\t.name = {metric_name}, \t\t.pmus = {metric_tblname}, \t\t.num_pmus = {metric_size} \t}} @@ -807,12 +813,55 @@ static const struct pmu_events_map pmu_events_map[] = { \t.arch = 0, \t.cpuid = 0, \t.event_table = { 0, 0 }, -\t.metric_table = { 0, 0 }, +\t.metric_table = { 0 }, } }; """) +def print_metric_table_functions() -> None: + _args.output_file.write(""" +const char *pmu_metrics_table__name(const struct pmu_metrics_table *table) +{ +\treturn table ? table->name : NULL; +} + +int pmu_metrics_table__iterate_tables(pmu_metrics_table_iter_t fn, void *data) +{ +\tsize_t i; +\tint ret; + +\tfor (i = 0; pmu_events_map[i].cpuid; i++) { +\t\tsize_t j; +\t\tbool found = false; + +\t\tif (!pmu_events_map[i].metric_table.pmus) +\t\t\tcontinue; +\t\tfor (j = 0; j < i; j++) { +\t\t\tif (pmu_events_map[j].metric_table.pmus == +\t\t\t pmu_events_map[i].metric_table.pmus) { +\t\t\t\tfound = true; +\t\t\t\tbreak; +\t\t\t} +\t\t} +\t\tif (found) +\t\t\tcontinue; +\t\tret = fn(&pmu_events_map[i].metric_table, data); +\t\tif (ret) +\t\t\treturn ret; +\t} +\tfor (i = 0; pmu_sys_event_tables[i].name; i++) { +\t\tif (!pmu_sys_event_tables[i].metric_table.pmus) +\t\t\tcontinue; +\t\tret = fn(&pmu_sys_event_tables[i].metric_table, data); +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; +} +""") + + def print_system_mapping_table() -> None: """C struct mapping table array for tables from /sys directories.""" _args.output_file.write(""" @@ -835,6 +884,7 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = { if metric_tblname in _sys_metric_tables: _args.output_file.write(f""" \t\t.metric_table = {{ +\t\t\t.name = "{metric_tblname.replace('pmu_metrics__', '')}", \t\t\t.pmus = {metric_tblname}, \t\t\t.num_pmus = ARRAY_SIZE({metric_tblname}) \t\t}},""") @@ -848,6 +898,7 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = { continue _args.output_file.write(f"""\t{{ \t\t.metric_table = {{ +\t\t\t.name = "{tblname.replace('pmu_metrics__', '')}", \t\t\t.pmus = {tblname}, \t\t\t.num_pmus = ARRAY_SIZE({tblname}) \t\t}}, @@ -856,7 +907,7 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = { """) _args.output_file.write("""\t{ \t\t.event_table = { 0, 0 }, -\t\t.metric_table = { 0, 0 }, +\t\t.metric_table = { 0 }, \t}, }; @@ -1486,6 +1537,7 @@ struct pmu_table_entry { print_mapping_table(archs) print_system_mapping_table() _args.output_file.write('/* clang-format on */\n') + print_metric_table_functions() print_metricgroups() _args.output_file.close() if _args.output_string_file: diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h index d3b24014c6ff..cb55c9fbca43 100644 --- a/tools/perf/pmu-events/pmu-events.h +++ b/tools/perf/pmu-events/pmu-events.h @@ -91,6 +91,9 @@ typedef int (*pmu_metric_iter_fn)(const struct pmu_metric *pm, const struct pmu_metrics_table *table, void *data); +typedef int (*pmu_metrics_table_iter_t)(const struct pmu_metrics_table *table, + void *data); + int pmu_events_table__for_each_event(const struct pmu_events_table *table, struct perf_pmu *pmu, pmu_event_iter_fn fn, @@ -112,6 +115,8 @@ size_t pmu_events_table__num_events(const struct pmu_events_table *table, int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, void *data); +const char *pmu_metrics_table__name(const struct pmu_metrics_table *table); +int pmu_metrics_table__iterate_tables(pmu_metrics_table_iter_t fn, void *data); /* * Search for a table and entry matching with pmu__name_wildcard_match or any * tables if pmu is NULL. Each matching metric has fn called on it. 0 implies to From 744af598719776b2ca8b0f5388b51d2493cc94b7 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:15 -0700 Subject: [PATCH 205/343] perf test: Drain pipe after child finishes to avoid losing output When running tests in parallel, the parent process reads output from the child's pipe. However, it might exit the loop as soon as the child is detected as finished, potentially missing data that arrived in the pipe just after the last poll or before the loop terminated. Address this by draining the pipe after the main loop in finish_test. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index f2c135891477..7946878195b7 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -483,6 +483,16 @@ static void finish_test(struct child_test **child_tests, int running_test, int c if (err_done) err_done = check_if_command_finished(&child_test->process); } + /* Drain any remaining data from the pipe. */ + if (err > 0) { + char buf[512]; + ssize_t len; + + while ((len = read(err, buf, sizeof(buf) - 1)) > 0) { + buf[len] = '\0'; + strbuf_addstr(&err_output, buf); + } + } if (perf_use_color_default && last_running != -1) { /* Erase "Running (.. active)" line printed before poll/sleep. */ fprintf(debug_file(), PERF_COLOR_DELETE_LINE); From 8c8d61c38d8e1755a4325f8acb396137bbd5371a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:16 -0700 Subject: [PATCH 206/343] perf test: Support dynamic test suites with setup callback and private data Add void *priv to struct test_case to allow passing per-test context. Add int (*setup)(struct test_suite *) to struct test_suite to allow dynamic generation of test cases. Update build_suites() to invoke the setup callback for each suite if present, ensuring dynamic cases are available before listing or running. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 17 ++++++++++++++++- tools/perf/tests/tests.h | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 7946878195b7..485ff75ab880 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -765,10 +765,21 @@ static struct test_suite **build_suites(void) for (size_t i = 0, j = 0; i < ARRAY_SIZE(suites); i++, j = 0) \ while ((suite = suites[i][j++]) != NULL) - for_each_suite(t) + for_each_suite(t) { + if (t->setup) { + int ret = t->setup(t); + + if (ret < 0) { + errno = -ret; + return NULL; + } + } num_suites++; + } result = calloc(num_suites + 1, sizeof(struct test_suite *)); + if (!result) + return NULL; for (int pass = 1; pass <= 2; pass++) { for_each_suite(t) { @@ -831,6 +842,8 @@ int cmd_test(int argc, const char **argv) argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0); if (argc >= 1 && !strcmp(argv[0], "list")) { suites = build_suites(); + if (!suites) + return errno ? -errno : -ENOMEM; ret = perf_test__list(stdout, suites, argc - 1, argv + 1); free(suites); return ret; @@ -863,6 +876,8 @@ int cmd_test(int argc, const char **argv) rlimit__bump_memlock(); suites = build_suites(); + if (!suites) + return errno ? -errno : -ENOMEM; ret = __cmd_test(suites, argc, argv, skiplist); free(suites); return ret; diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index ee00518bf36f..9bcf1dbb0663 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -38,12 +38,14 @@ struct test_case { const char *skip_reason; test_fnptr run_case; bool exclusive; + void *priv; }; struct test_suite { const char *desc; struct test_case *test_cases; void *priv; + int (*setup)(struct test_suite *suite); }; #define DECLARE_SUITE(name) \ From 8ae26f6ae7013f0ba753feed723eb0613796cb67 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:17 -0700 Subject: [PATCH 207/343] perf test pmu-events: A sub-test per metric table Break apart the slow "Parsing of PMU event table metrics" tests into one pair of tests (real and fake PMU) per metric table found, storing the specific table pointer in priv data. Implement setup_pmu_events_suite() to dynamically allocate and populate these test cases. Split static parser tests out into a separate test__parsing_fake_static() test case. Update test__parsing() and test__parsing_fake() to retrieve the specific table from priv data and test only that table, maintaining fallback compatibility if priv is NULL. Running these individual tests in parallel significantly reduces overall test execution time. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 156 ++++++++++++++++++++++++++++++++-- 1 file changed, 148 insertions(+), 8 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index b1609a7e1d8c..fd5630f0a13c 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -923,13 +923,20 @@ static int test__parsing_callback(const struct pmu_metric *pm, return err; } -static int test__parsing(struct test_suite *test __maybe_unused, - int subtest __maybe_unused) +static int test__parsing(struct test_suite *test, int subtest) { int failures = 0; + const struct pmu_metrics_table *table = NULL; - pmu_for_each_core_metric(test__parsing_callback, &failures); - pmu_for_each_sys_metric(test__parsing_callback, &failures); + if (test->test_cases) + table = test->test_cases[subtest].priv; + + if (table) { + pmu_metrics_table__for_each_metric(table, test__parsing_callback, &failures); + } else { + pmu_for_each_core_metric(test__parsing_callback, &failures); + pmu_for_each_sys_metric(test__parsing_callback, &failures); + } return failures == 0 ? TEST_OK : TEST_FAIL; } @@ -1020,8 +1027,8 @@ static int test__parsing_fake_callback(const struct pmu_metric *pm, * Parse all the metrics for current architecture, or all defined cpus via the * 'fake_pmu' in parse_events. */ -static int test__parsing_fake(struct test_suite *test __maybe_unused, - int subtest __maybe_unused) +static int test__parsing_fake_static(struct test_suite *test __maybe_unused, + int subtest __maybe_unused) { int err = 0; @@ -1031,6 +1038,26 @@ static int test__parsing_fake(struct test_suite *test __maybe_unused, return err; } + return 0; +} + +static int test__parsing_fake(struct test_suite *test, int subtest) +{ + int err = 0; + const struct pmu_metrics_table *table = NULL; + + if (test->test_cases) + table = test->test_cases[subtest].priv; + + if (table) + return pmu_metrics_table__for_each_metric(table, test__parsing_fake_callback, NULL); + + for (size_t i = 0; i < ARRAY_SIZE(metrics); i++) { + err = metric_parse_fake("", metrics[i].str); + if (err) + return err; + } + err = pmu_for_each_core_metric(test__parsing_fake_callback, NULL); if (err) return err; @@ -1059,17 +1086,130 @@ static int test__parsing_threshold(struct test_suite *test __maybe_unused, return pmu_for_each_sys_metric(test__parsing_threshold_callback, NULL); } +struct populate_cb_data { + struct test_case *test_cases; + size_t curr; +}; + +static int count_metrics_tables_cb(const struct pmu_metrics_table *table __maybe_unused, void *data) +{ + size_t *count = data; + (*count)++; + return 0; +} + +static int populate_metrics_tables_cb(const struct pmu_metrics_table *table, void *data) +{ + struct populate_cb_data *cb_data = data; + const char *table_name = pmu_metrics_table__name(table); + char *desc_real, *desc_fake; + + if (!table_name) + table_name = "unknown"; + + if (asprintf(&desc_real, "PMU metric parsing: %s", table_name) < 0) + return -ENOMEM; + if (asprintf(&desc_fake, "PMU metric parsing with fake PMU: %s", table_name) < 0) { + free(desc_real); + return -ENOMEM; + } + + cb_data->test_cases[cb_data->curr++] = (struct test_case){ + .name = "parsing", + .desc = desc_real, + .run_case = test__parsing, + .priv = (void *)table, + .skip_reason = "some metrics failed", + }; + + cb_data->test_cases[cb_data->curr++] = (struct test_case){ + .name = "parsing_fake", + .desc = desc_fake, + .run_case = test__parsing_fake, + .priv = (void *)table, + }; + + return 0; +} + +static struct test_case pmu_events_tests[]; + +static int setup_pmu_events_suite(struct test_suite *suite) +{ + size_t num_tables = 0; + size_t num_fixed_tests = 4; + size_t tests_per_table = 2; + size_t total_tests; + struct test_case *test_cases; + size_t curr = 0; + struct populate_cb_data cb_data; + int ret; + + if (suite->test_cases != pmu_events_tests) + return 0; + + ret = pmu_metrics_table__iterate_tables(count_metrics_tables_cb, &num_tables); + if (ret) + return ret; + + total_tests = num_fixed_tests + (num_tables * tests_per_table) + 1; + + test_cases = calloc(total_tests, sizeof(*test_cases)); + if (!test_cases) + return -ENOMEM; + + test_cases[curr++] = (struct test_case){ + .name = "pmu_event_table", + .desc = "PMU event table sanity", + .run_case = test__pmu_event_table, + }; + test_cases[curr++] = (struct test_case){ + .name = "aliases", + .desc = "PMU event map aliases", + .run_case = test__aliases, + }; + test_cases[curr++] = (struct test_case){ + .name = "parsing_fake_static", + .desc = "Parsing of static metrics with fake PMU", + .run_case = test__parsing_fake_static, + }; + test_cases[curr++] = (struct test_case){ + .name = "parsing_threshold", + .desc = "Parsing of metric thresholds with fake PMU", + .run_case = test__parsing_threshold, + }; + + cb_data = (struct populate_cb_data){ + .test_cases = test_cases, + .curr = curr, + }; + + ret = pmu_metrics_table__iterate_tables(populate_metrics_tables_cb, &cb_data); + if (ret) { + size_t i; + + for (i = num_fixed_tests; i < cb_data.curr; i++) + free((char *)test_cases[i].desc); + free(test_cases); + return ret; + } + + suite->test_cases = test_cases; + return 0; +} + static struct test_case pmu_events_tests[] = { TEST_CASE("PMU event table sanity", pmu_event_table), TEST_CASE("PMU event map aliases", aliases), TEST_CASE_REASON("Parsing of PMU event table metrics", parsing, "some metrics failed"), - TEST_CASE("Parsing of PMU event table metrics with fake PMUs", parsing_fake), - TEST_CASE("Parsing of metric thresholds with fake PMUs", parsing_threshold), + TEST_CASE("Parsing of PMU event table metrics with fake PMU", parsing_fake), + TEST_CASE("Parsing of metric thresholds with fake PMU", parsing_threshold), { .name = NULL, } }; struct test_suite suite__pmu_events = { .desc = "PMU JSON event tests", .test_cases = pmu_events_tests, + .setup = setup_pmu_events_suite, }; From c7dacfb87beed63ffe360c73c2a284d9e334f135 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:18 -0700 Subject: [PATCH 208/343] tools subcmd: Robust fallback and existence checks for process reaping Update check_if_command_finished() and wait_or_whine() to handle invalid PIDs gracefully (<= 0) by setting cmd->finished = 1 and returning early. This avoids executing waitpid(-1, ...) or waitpid(0, ...) downstream, which can block or reap parallel tests' exit status causing state corruption. Introduce a fallback mechanism in check_if_command_finished() using waitpid(..., WNOHANG) when /proc//status is inaccessible (e.g. due to EMFILE/ENFILE) to safely check and reap finished children. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/subcmd/run-command.c | 69 ++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/tools/lib/subcmd/run-command.c b/tools/lib/subcmd/run-command.c index b7510f83209a..bd21b8bfd58b 100644 --- a/tools/lib/subcmd/run-command.c +++ b/tools/lib/subcmd/run-command.c @@ -169,8 +169,18 @@ int start_command(struct child_process *cmd) static int wait_or_whine(struct child_process *cmd, bool block) { - bool finished = cmd->finished; - int result = cmd->finish_result; + bool finished; + int result; + + if (cmd->pid <= 0) { + cmd->finished = 1; + if (cmd->pid < 0 && cmd->finish_result == 0) + cmd->finish_result = -ERR_RUN_COMMAND_FORK; + return cmd->finish_result; + } + + finished = cmd->finished; + result = cmd->finish_result; while (!finished) { int status, code; @@ -233,7 +243,18 @@ int check_if_command_finished(struct child_process *cmd) char filename[6 + MAX_STRLEN_TYPE(typeof(cmd->pid)) + 7 + 1]; char status_line[256]; FILE *status_file; +#endif + if (cmd->finished) + return 1; + if (cmd->pid <= 0) { + cmd->finished = 1; + if (cmd->pid < 0 && cmd->finish_result == 0) + cmd->finish_result = -ERR_RUN_COMMAND_FORK; + return 1; + } + +#ifdef __linux__ /* * Check by reading /proc//status as calling waitpid causes * stdout/stderr to be closed and data lost. @@ -241,8 +262,48 @@ int check_if_command_finished(struct child_process *cmd) sprintf(filename, "/proc/%u/status", cmd->pid); status_file = fopen(filename, "r"); if (status_file == NULL) { - /* Open failed assume finish_command was called. */ - return true; + int status; + pid_t waiting; + + /* + * fopen() can fail with ENOENT if the process has been reaped. + * It can also fail with EMFILE/ENFILE if RLIMIT_NOFILE is reached. + * In those cases, use waitpid(..., WNOHANG) to robustly check + * and reap the process if it has exited. + */ + if (errno == ENOENT) + return 1; + + waiting = waitpid(cmd->pid, &status, WNOHANG); + if (waiting == cmd->pid) { + int result; + int code; + + cmd->finished = 1; + if (WIFSIGNALED(status)) { + result = -ERR_RUN_COMMAND_WAITPID_SIGNAL; + } else if (!WIFEXITED(status)) { + result = -ERR_RUN_COMMAND_WAITPID_NOEXIT; + } else { + code = WEXITSTATUS(status); + switch (code) { + case 127: + result = -ERR_RUN_COMMAND_EXEC; + break; + case 0: + result = 0; + break; + default: + result = -code; + break; + } + } + cmd->finish_result = result; + return 1; + } + if (waiting < 0 && (errno == ECHILD || errno == ESRCH)) + return 1; + return 0; } while (fgets(status_line, sizeof(status_line), status_file) != NULL) { char *p; From f35450738e789b80b540f41487b9053defd0bb8d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:19 -0700 Subject: [PATCH 209/343] perf test: Refactor parallel poll loop to drain all pipes simultaneously When running tests in parallel with verbose output (-v), child processes write to pipes. If a test produces significant output (e.g. Granite Rapids metric parsing printing hundreds of lines), it fills the 64KB pipe buffer and blocks. Previously, the parent harness (finish_test) only polled the pipe of the current test waiting to be printed. Other children blocked indefinitely until the parent reached them, severely sequentializing execution. Address this by implementing finish_tests_parallel() to poll and drain output pipes from all running children simultaneously into per-child buffers, employing safe strbuf_addstr string operations alongside thorough variable orderings for strict ISO C90 compliance. Reaping occurs out of order as children finish, while final result printing remains strictly in order. This drops parallel verbose execution time for the PMU events suite from ~35 seconds down to ~5.9 seconds. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 267 +++++++++++++++++++++++++++++++- 1 file changed, 259 insertions(+), 8 deletions(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 485ff75ab880..0479184c3dda 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -302,6 +302,9 @@ struct child_test { struct test_suite *test; int suite_num; int test_case_num; + struct strbuf err_output; + int result; + bool done; }; static jmp_buf run_test_jmp_buf; @@ -356,6 +359,11 @@ static int run_test_child(struct child_process *process) #define TEST_RUNNING -3 +static struct pollfd *global_pfds; +static size_t *global_pfd_indices; + +static int strbuf_addstr_safe(struct strbuf *sb, const char *s); + static int print_test_result(struct test_suite *t, int curr_suite, int curr_test_case, int result, int width, int running) { @@ -422,7 +430,7 @@ static void finish_test(struct child_test **child_tests, int running_test, int c * Busy loop reading from the child's stdout/stderr that are set to be * non-blocking until EOF. */ - if (err > 0) + if (err >= 0) fcntl(err, F_SETFL, O_NONBLOCK); if (verbose > 1) { if (test_suite__num_test_cases(t) > 1) @@ -476,7 +484,7 @@ static void finish_test(struct child_test **child_tests, int running_test, int c if (len > 0) { err_done = false; buf[len] = '\0'; - strbuf_addstr(&err_output, buf); + strbuf_addstr_safe(&err_output, buf); } } } @@ -484,13 +492,13 @@ static void finish_test(struct child_test **child_tests, int running_test, int c err_done = check_if_command_finished(&child_test->process); } /* Drain any remaining data from the pipe. */ - if (err > 0) { + if (err >= 0) { char buf[512]; ssize_t len; while ((len = read(err, buf, sizeof(buf) - 1)) > 0) { buf[len] = '\0'; - strbuf_addstr(&err_output, buf); + strbuf_addstr_safe(&err_output, buf); } } if (perf_use_color_default && last_running != -1) { @@ -499,16 +507,253 @@ static void finish_test(struct child_test **child_tests, int running_test, int c } /* Clean up child process. */ ret = finish_command(&child_test->process); + child_test->process.pid = 0; + if (child_test->err_output.len > 0) { + struct strbuf merged = STRBUF_INIT; + + if (child_test->err_output.buf) + strbuf_addstr_safe(&merged, child_test->err_output.buf); + if (err_output.buf) + strbuf_addstr_safe(&merged, err_output.buf); + strbuf_release(&err_output); + err_output = merged; + } if (verbose > 1 || (verbose == 1 && ret == TEST_FAIL)) fprintf(stderr, "%s", err_output.buf); strbuf_release(&err_output); + strbuf_release(&child_test->err_output); print_test_result(t, curr_suite, curr_test_case, ret, width, /*running=*/0); if (err > 0) close(err); zfree(&child_tests[running_test]); } +static int strbuf_addstr_safe(struct strbuf *sb, const char *s) +{ + sigset_t set, oldset; + int ret; + + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + pthread_sigmask(SIG_BLOCK, &set, &oldset); + ret = strbuf_addstr(sb, s); + pthread_sigmask(SIG_SETMASK, &oldset, NULL); + return ret; +} + +static void drain_child_process_err(struct child_test *child) +{ + char buf[512]; + ssize_t len; + + while ((len = read(child->process.err, buf, sizeof(buf) - 1)) > 0) { + buf[len] = '\0'; + strbuf_addstr_safe(&child->err_output, buf); + } +} + +static void handle_child_pipe_activity(struct child_test *child, short revents) +{ + if (!revents) + return; + + drain_child_process_err(child); + /* + * If the child closed its end of the pipe (EOF) or encountered + * an error, close the file descriptor immediately and set it + * to -1. This removes it from the pfds array for subsequent + * iterations, preventing a tight CPU busy-loop while waiting + * for the process itself to exit. + */ + if (revents & (POLLHUP | POLLERR | POLLNVAL)) { + close(child->process.err); + child->process.err = -1; + } +} + +static int finish_tests_parallel(struct child_test **child_tests, size_t num_tests, int width) +{ + size_t next_to_print = 0; + struct pollfd *pfds; + size_t *pfd_indices; + size_t num_pfds = 0; + int last_running = -1; + size_t i; + int last_suite_printed = -1; + sigset_t set, oldset; + + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + + pthread_sigmask(SIG_BLOCK, &set, &oldset); + global_pfds = calloc(num_tests, sizeof(*pfds)); + global_pfd_indices = calloc(num_tests, sizeof(*pfd_indices)); + pfds = global_pfds; + pfd_indices = global_pfd_indices; + if (!pfds || !pfd_indices) { + free(pfds); + free(pfd_indices); + global_pfds = NULL; + global_pfd_indices = NULL; + pthread_sigmask(SIG_SETMASK, &oldset, NULL); + return -ENOMEM; + } + pthread_sigmask(SIG_SETMASK, &oldset, NULL); + + for (i = 0; i < num_tests; i++) { + struct child_test *child = child_tests[i]; + + if (!child) + continue; + strbuf_init(&child->err_output, 0); + if (child->process.err >= 0) + fcntl(child->process.err, F_SETFL, O_NONBLOCK); + } + + while (next_to_print < num_tests) { + size_t running_count = 0; + size_t p; + + while (next_to_print < num_tests && + (!child_tests[next_to_print] || child_tests[next_to_print]->done)) + next_to_print++; + + if (next_to_print >= num_tests) + break; + + num_pfds = 0; + + for (i = next_to_print; i < num_tests; i++) { + struct child_test *child = child_tests[i]; + + if (!child || child->done) + continue; + + if (!check_if_command_finished(&child->process)) + running_count++; + + if (child->process.err >= 0) { + pfds[num_pfds].fd = child->process.err; + pfds[num_pfds].events = POLLIN | POLLERR | POLLHUP | POLLNVAL; + pfd_indices[num_pfds] = i; + num_pfds++; + } + } + + if (perf_use_color_default && running_count != (size_t)last_running) { + struct child_test *next_child = child_tests[next_to_print]; + + if (last_running != -1) + fprintf(debug_file(), PERF_COLOR_DELETE_LINE); + + if (next_child) { + if (test_suite__num_test_cases(next_child->test) > 1 && + last_suite_printed != next_child->suite_num) { + pr_info("%3d: %-*s:\n", next_child->suite_num + 1, width, + test_description(next_child->test, -1)); + last_suite_printed = next_child->suite_num; + } + print_test_result(next_child->test, next_child->suite_num, + next_child->test_case_num, TEST_RUNNING, width, + running_count); + } + last_running = running_count; + } + + if (num_pfds == 0) { + if (running_count > 0) + usleep(10 * 1000); + } else { + int pret = poll(pfds, num_pfds, 100); + + if (pret > 0) { + for (p = 0; p < num_pfds; p++) { + size_t idx = pfd_indices[p]; + + handle_child_pipe_activity(child_tests[idx], + pfds[p].revents); + } + } + } + + for (i = next_to_print; i < num_tests; i++) { + struct child_test *child = child_tests[i]; + + if (!child || child->done) + continue; + + if (check_if_command_finished(&child->process)) { + if (child->process.err >= 0) { + drain_child_process_err(child); + close(child->process.err); + child->process.err = -1; + } + child->result = finish_command(&child->process); + child->process.pid = 0; + child->done = true; + } + } + + while (next_to_print < num_tests) { + struct child_test *child = child_tests[next_to_print]; + + if (!child) { + next_to_print++; + continue; + } + if (!child->done) + break; + + if (perf_use_color_default && last_running != -1) { + fprintf(debug_file(), PERF_COLOR_DELETE_LINE); + last_running = -1; + } + + if (test_suite__num_test_cases(child->test) > 1 && + last_suite_printed != child->suite_num) { + pr_info("%3d: %-*s:\n", child->suite_num + 1, width, + test_description(child->test, -1)); + last_suite_printed = child->suite_num; + } + + if (verbose > 1) { + if (test_suite__num_test_cases(child->test) > 1) { + pr_info("%3d.%1d: %s:\n", child->suite_num + 1, + child->test_case_num + 1, + test_description(child->test, + child->test_case_num)); + } else { + pr_info("%3d: %s:\n", child->suite_num + 1, + test_description(child->test, -1)); + } + } + + if (verbose > 1 || (verbose == 1 && child->result == TEST_FAIL)) + fprintf(stderr, "%s", child->err_output.buf); + + print_test_result(child->test, child->suite_num, child->test_case_num, + child->result, width, 0); + pthread_sigmask(SIG_BLOCK, &set, &oldset); + strbuf_release(&child->err_output); + child_tests[next_to_print] = NULL; + zfree(&child); + pthread_sigmask(SIG_SETMASK, &oldset, NULL); + next_to_print++; + } + } + + pthread_sigmask(SIG_BLOCK, &set, &oldset); + free(global_pfds); + free(global_pfd_indices); + global_pfds = NULL; + global_pfd_indices = NULL; + pthread_sigmask(SIG_SETMASK, &oldset, NULL); + return 0; +} + static int start_test(struct test_suite *test, int curr_suite, int curr_test_case, struct child_test **child, int width, int pass) { @@ -542,13 +787,14 @@ static int start_test(struct test_suite *test, int curr_suite, int curr_test_cas (*child)->test_case_num = curr_test_case; (*child)->process.pid = -1; (*child)->process.no_stdin = 1; + (*child)->process.in = -1; + (*child)->process.out = -1; + (*child)->process.err = -1; if (verbose <= 0) { (*child)->process.no_stdout = 1; (*child)->process.no_stderr = 1; } else { (*child)->process.stdout_to_stderr = 1; - (*child)->process.out = -1; - (*child)->process.err = -1; } (*child)->process.no_exec_cmd = run_test_child; if (sequential || pass == 2) { @@ -671,8 +917,9 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[], } if (!sequential) { /* Parallel mode starts tests but doesn't finish them. Do that now. */ - for (size_t x = 0; x < num_tests; x++) - finish_test(child_tests, x, num_tests, width); + err = finish_tests_parallel(child_tests, num_tests, width); + if (err) + goto err_out; } } err_out: @@ -683,6 +930,10 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[], for (size_t x = 0; x < num_tests; x++) finish_test(child_tests, x, num_tests, width); } + free(global_pfds); + free(global_pfd_indices); + global_pfds = NULL; + global_pfd_indices = NULL; free(child_tests); return err; } From b5a4a361f5cfb8f6f6f0a59536fd5fad11ed9f5f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:20 -0700 Subject: [PATCH 210/343] perf test: Show snippet failure output for verbose=1 Currently, when running tests in verbose mode (-v), if a test case fails, the entire raw standard error buffer is dumped to stderr via fprintf(stderr, "%s", child->err_output.buf). For tests that generate massive amounts of debugging or logging output before dying, this results in multi-page terminal dumps where highly critical diagnostic keywords (error, fail, segv) are easily lost. Implement a smart, bounded snippet string processor to improve failure triaging: 1. Introduce a configurable quota limit static unsigned int failure_snippet_lines = 10; accessible via a new command-line option --failure-snippet-lines . 2. Parse the raw error buffer dynamically into lines and run a three-pass extraction algorithm: - Pass 0: Always select the very first line of the log as an initial outline marker. - Pass 1: Scan forward from the top of the log to pick up to N lines that contain case-insensitive failure keywords (error, fail, segv, abort) to isolate the root cause. Automatically pull in the immediate subsequent line as highly-prioritized context. Allow adjacent matching lines to overlap without dropping context by evaluating keywords for all lines (e.g. when "Failed to report" is followed by "Error:"). - Pass 2: If quota remains, scan backward from the absolute tail of the log to capture trailing crash or abort context. 3. Output the selected lines in their original chronological order, inserting a clear ... separator between non-contiguous line jumps. 4. Wrap matched failure keywords dynamically in bold red (PERF_COLOR_RED) to immediately draw the eye to failures. 5. Invoke the smart processor purely when verbose == 1 && ret == TEST_FAIL in both finish_test and finish_tests_parallel, leaving raw full-output dumping completely untouched when running highly verbose (-vv). Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 203 +++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 0479184c3dda..3401d79a1d24 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -48,6 +48,8 @@ static bool dont_fork; static bool sequential; /* Number of times each test is run. */ static unsigned int runs_per_test = 1; +/* Number of lines to include in failure snippet. */ +static unsigned int failure_snippet_lines = 10; const char *dso_to_test; const char *test_objdump_path = "objdump"; @@ -344,7 +346,7 @@ static int run_test_child(struct child_process *process) for (size_t i = 0; i < ARRAY_SIZE(signals); i++) signal(signals[i], child_test_sig_handler); - pr_debug("--- start ---\n"); + pr_debug("---- start ----\n"); pr_debug("test child forked, pid %d\n", getpid()); err = test_function(child->test, child->test_case_num)(child->test, child->test_case_num); pr_debug("---- end(%d) ----\n", err); @@ -400,6 +402,195 @@ static int print_test_result(struct test_suite *t, int curr_suite, int curr_test return 0; } +static const char * const fail_keywords[] = { + "error", "fail", "segv", "abort", + "signal", "fatal", "panic", "corrupt", NULL +}; + +static const char *find_next_keyword(const char *str, size_t max_len, size_t *kw_len) +{ + const char *best = NULL; + size_t best_len = 0; + int k; + + for (k = 0; fail_keywords[k]; k++) { + const char *s = str; + size_t len = strlen(fail_keywords[k]); + + while ((size_t)(s - str) + len <= max_len) { + size_t i; + + if (best && s >= best) + break; + + for (i = 0; i < len; i++) { + if (tolower(s[i]) != fail_keywords[k][i]) + break; + } + if (i == len) { + if (!best || s < best) { + best = s; + best_len = len; + } + break; + } + s++; + } + } + if (best) { + *kw_len = best_len; + return best; + } + return NULL; +} + +static void print_line_highlighted(FILE *fp, const char *line, size_t len) +{ + const char *s = line; + + while (len > 0) { + size_t kw_len = 0; + const char *match = find_next_keyword(s, len, &kw_len); + + if (!match) { + fwrite(s, 1, len, fp); + break; + } + if (match > s) + fwrite(s, 1, match - s, fp); + if (perf_use_color_default) + fprintf(fp, "%s", PERF_COLOR_RED); + fwrite(match, 1, kw_len, fp); + if (perf_use_color_default) + fprintf(fp, "%s", PERF_COLOR_RESET); + + len -= (match + kw_len) - s; + s = match + kw_len; + } +} + + +static void print_test_failure_snippet(FILE *fp, const char *buf) +{ + size_t num_lines = 0; + size_t max_lines = 128; + const char **lines = calloc(max_lines, sizeof(const char *)); + size_t *line_lens = calloc(max_lines, sizeof(size_t)); + const char *s = buf; + size_t i; + unsigned int picked_count = 0; + bool *pick; + int last_printed = -1; + + if (!lines || !line_lens) { + free(lines); free(line_lens); + fprintf(fp, "%s", buf); + return; + } + + while (*s) { + const char *eol = strchr(s, '\n'); + size_t len; + + if (eol) + len = eol - s + 1; + else + len = strlen(s); + + if (num_lines == max_lines) { + const char **new_lines; + size_t *new_lens; + + max_lines *= 2; + new_lines = realloc(lines, max_lines * sizeof(const char *)); + if (!new_lines) { + free(lines); free(line_lens); + fprintf(fp, "%s", buf); + return; + } + lines = new_lines; + + new_lens = realloc(line_lens, max_lines * sizeof(size_t)); + if (!new_lens) { + free(lines); free(line_lens); + fprintf(fp, "%s", buf); + return; + } + line_lens = new_lens; + } + lines[num_lines] = s; + line_lens[num_lines] = len; + num_lines++; + s += len; + } + + if (num_lines <= failure_snippet_lines) { + for (i = 0; i < num_lines; i++) + print_line_highlighted(fp, lines[i], line_lens[i]); + free(lines); free(line_lens); + return; + } + + pick = calloc(num_lines, sizeof(bool)); + if (!pick) { + for (i = 0; i < num_lines; i++) + print_line_highlighted(fp, lines[i], line_lens[i]); + free(lines); free(line_lens); + return; + } + + /* Pass 0: Always pick the very first line */ + if (num_lines > 0 && picked_count < failure_snippet_lines) { + pick[0] = true; + picked_count++; + } + + /* Pass 1: Pick lines with failure keywords from start (Highest Priority) */ + for (i = 0; i < num_lines && picked_count < failure_snippet_lines; i++) { + size_t dummy; + + if (find_next_keyword(lines[i], line_lens[i], &dummy)) { + if (!pick[i]) { + pick[i] = true; + picked_count++; + } + /* Prioritize getting the immediate next line for context */ + if (i + 1 < num_lines && !pick[i + 1] && + picked_count < failure_snippet_lines) { + pick[i + 1] = true; + picked_count++; + } + } + } + + /* Pass 2: Fill remaining quota from the end backwards */ + i = num_lines; + while (i > 0 && picked_count < failure_snippet_lines) { + i--; + if (!pick[i]) { + pick[i] = true; + picked_count++; + } + } + + for (i = 0; i < num_lines; i++) { + if (!pick[i]) + continue; + if (last_printed != -1 && (int)i > last_printed + 1) { + if (perf_use_color_default) + fprintf(fp, "%s...%s\n", PERF_COLOR_BLUE, PERF_COLOR_RESET); + else + fprintf(fp, "...\n"); + } + print_line_highlighted(fp, lines[i], line_lens[i]); + last_printed = i; + } + + free(pick); + free(lines); + free(line_lens); +} + static void finish_test(struct child_test **child_tests, int running_test, int child_test_num, int width) { @@ -518,8 +709,10 @@ static void finish_test(struct child_test **child_tests, int running_test, int c strbuf_release(&err_output); err_output = merged; } - if (verbose > 1 || (verbose == 1 && ret == TEST_FAIL)) + if (verbose > 1) fprintf(stderr, "%s", err_output.buf); + else if (verbose == 1 && ret == TEST_FAIL) + print_test_failure_snippet(stderr, err_output.buf); strbuf_release(&err_output); strbuf_release(&child_test->err_output); @@ -731,8 +924,10 @@ static int finish_tests_parallel(struct child_test **child_tests, size_t num_tes } } - if (verbose > 1 || (verbose == 1 && child->result == TEST_FAIL)) + if (verbose > 1) fprintf(stderr, "%s", child->err_output.buf); + else if (verbose == 1 && child->result == TEST_FAIL) + print_test_failure_snippet(stderr, child->err_output.buf); print_test_result(child->test, child->suite_num, child->test_case_num, child->result, width, 0); @@ -1075,6 +1270,8 @@ int cmd_test(int argc, const char **argv) OPT_STRING(0, "dso", &dso_to_test, "dso", "dso to test"), OPT_STRING(0, "objdump", &test_objdump_path, "path", "objdump binary to use for disassembly and annotations"), + OPT_UINTEGER(0, "failure-snippet-lines", &failure_snippet_lines, + "Number of lines to include in failure snippet, default 10"), OPT_END() }; const char * const test_subcommands[] = { "list", NULL }; From 33f20342ba525ef75fd9734db71e9823fe65e769 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:21 -0700 Subject: [PATCH 211/343] perf test: Add summary reporting Currently, when running test suites (perf test), users must scroll through hundreds of lines of console output to manually tally the number of passed, skipped, or failed test cases. Introduce an automated, global execution summary printed at the absolute tail of the test run: 1. Track counts mid-flight inside the print_test_result() accumulator, clearly separating pass counts into standalone main tests vs. individual subtests (where num_test_cases > 1). 2. Accumulate the precise descriptions of all failed test cases directly into a global string buffer, formatted with their suite indices (e.g., 3.1: Parse event definition strings) for effortless cross-referencing. 3. Define a summary printer function print_tests_summary() that emits a colored outline of the final pass, skip, and fail totals, followed by the explicit list of failed tests. 4. Invoke the summary printer right before freeing the test array at the absolute tail of __cmd_test(), guaranteeing that the summary is successfully printed even if an internal emergency signal cleanup occurs or if the user interrupts the run early. Example output: ``` $ sudo perf test -v 1: vmlinux symtab matches kallsyms : Skip 2: Detect openat syscall event : Ok 3: Detect openat syscall event on all cpus : Ok ... 163: perf trace summary : Ok === Test Summary === Passed main tests : 123 Passed subtests : 145 Skipped tests : 22 Failed tests : 6 List of failed tests: 92: perf kvm tests 95: kernel lock contention analysis test 120: perf metrics value validation 124: Check branch stack sampling 143: perftool-testsuite_probe 158: test Intel TPEBS counting mode ``` Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 89 +++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 3401d79a1d24..8883d4744057 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -363,8 +363,14 @@ static int run_test_child(struct child_process *process) static struct pollfd *global_pfds; static size_t *global_pfd_indices; +static unsigned int summary_tests_passed; +static unsigned int summary_subtests_passed; +static unsigned int summary_tests_skipped; +static unsigned int summary_tests_failed; +static struct strbuf summary_failed_tests_buf = STRBUF_INIT; static int strbuf_addstr_safe(struct strbuf *sb, const char *s); +static int __printf(2, 3) strbuf_addf_safe(struct strbuf *sb, const char *fmt, ...); static int print_test_result(struct test_suite *t, int curr_suite, int curr_test_case, int result, int width, int running) @@ -382,11 +388,16 @@ static int print_test_result(struct test_suite *t, int curr_suite, int curr_test color_fprintf(stderr, PERF_COLOR_YELLOW, " Running (%d active)\n", running); break; case TEST_OK: + if (test_suite__num_test_cases(t) > 1) + summary_subtests_passed++; + else + summary_tests_passed++; pr_info(" Ok\n"); break; case TEST_SKIP: { const char *reason = skip_reason(t, curr_test_case); + summary_tests_skipped++; if (reason) color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (%s)\n", reason); else @@ -395,6 +406,15 @@ static int print_test_result(struct test_suite *t, int curr_suite, int curr_test break; case TEST_FAIL: default: + summary_tests_failed++; + if (test_suite__num_test_cases(t) > 1) + strbuf_addf_safe(&summary_failed_tests_buf, " %3d.%1d: %s\n", + curr_suite + 1, curr_test_case + 1, + test_description(t, curr_test_case)); + else + strbuf_addf_safe(&summary_failed_tests_buf, " %3d: %s\n", + curr_suite + 1, + test_description(t, curr_test_case)); color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n"); break; } @@ -736,6 +756,47 @@ static int strbuf_addstr_safe(struct strbuf *sb, const char *s) return ret; } +static int __printf(2, 3) strbuf_addf_safe(struct strbuf *sb, const char *fmt, ...) +{ + char buf[1024]; + va_list ap; + int len; + sigset_t set, oldset; + int ret; + + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + sigprocmask(SIG_BLOCK, &set, &oldset); + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + if (len < 0) { + sigprocmask(SIG_SETMASK, &oldset, NULL); + return len; + } + if ((size_t)len >= sizeof(buf)) { + char *dynamic_buf = malloc(len + 1); + + if (!dynamic_buf) { + sigprocmask(SIG_SETMASK, &oldset, NULL); + return -ENOMEM; + } + va_start(ap, fmt); + vsnprintf(dynamic_buf, len + 1, fmt, ap); + va_end(ap); + ret = strbuf_addstr(sb, dynamic_buf); + free(dynamic_buf); + } else { + ret = strbuf_addstr(sb, buf); + } + + sigprocmask(SIG_SETMASK, &oldset, NULL); + return ret; +} + static void drain_child_process_err(struct child_test *child) { char buf[512]; @@ -1013,6 +1074,23 @@ static void cmd_test_sig_handler(int sig) siglongjmp(cmd_test_jmp_buf, sig); } +static void print_tests_summary(void) +{ + pr_info("\n=== Test Summary ===\n"); + pr_info("Passed main tests : %u\n", summary_tests_passed); + pr_info("Passed subtests : %u\n", summary_subtests_passed); + pr_info("Skipped tests : %u\n", summary_tests_skipped); + if (summary_tests_failed > 0) { + color_fprintf(stderr, PERF_COLOR_RED, "Failed tests : %u\n", + summary_tests_failed); + pr_info("List of failed tests:\n"); + pr_info("%s", summary_failed_tests_buf.buf); + } else { + color_fprintf(stderr, PERF_COLOR_GREEN, "Failed tests : 0\n"); + } + strbuf_release(&summary_failed_tests_buf); +} + static int __cmd_test(struct test_suite **suites, int argc, const char *argv[], struct intlist *skiplist) { @@ -1090,9 +1168,13 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[], } if (intlist__find(skiplist, curr_suite + 1)) { - pr_info("%3d: %-*s:", curr_suite + 1, width, - test_description(*t, -1)); - color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); + if (pass == 1) { + pr_info("%3d: %-*s:", curr_suite + 1, width, + test_description(*t, -1)); + color_fprintf(stderr, PERF_COLOR_YELLOW, + " Skip (user override)\n"); + summary_tests_skipped++; + } continue; } @@ -1125,6 +1207,7 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[], for (size_t x = 0; x < num_tests; x++) finish_test(child_tests, x, num_tests, width); } + print_tests_summary(); free(global_pfds); free(global_pfd_indices); global_pfds = NULL; From 94ac3ce427c8f80d699909c85a7cb70a589c562d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:22 -0700 Subject: [PATCH 212/343] perf test: Fix subtest status alignment for multi-digit indexes When running perf test, the status column (: Ok) became misaligned when subtest indexes reached 2 or 3 digits (e.g. 9.100 vs 9.9 vs 10.1). This occurred because the subtest description field width (subw) was statically fixed to width - 2, assuming all subtest index prefixes were exactly 7 characters wide. Dynamically calculate subw based on the exact character length of the test suite and subtest index prefix. This ensures the status column is perfectly aligned vertically across all test outputs regardless of subtest index digit count. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 8883d4744057..4773000f3199 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -376,10 +376,12 @@ static int print_test_result(struct test_suite *t, int curr_suite, int curr_test int result, int width, int running) { if (test_suite__num_test_cases(t) > 1) { - int subw = width > 2 ? width - 2 : width; + char prefix[32]; + int len = snprintf(prefix, sizeof(prefix), "%3d.%1d:", + curr_suite + 1, curr_test_case + 1); + int subw = len >= 4 ? width + 4 - len : width; - pr_info("%3d.%1d: %-*s:", curr_suite + 1, curr_test_case + 1, subw, - test_description(t, curr_test_case)); + pr_info("%s %-*s:", prefix, subw, test_description(t, curr_test_case)); } else pr_info("%3d: %-*s:", curr_suite + 1, width, test_description(t, curr_test_case)); From 85fe2fdb2726e8e85b0dc1217260d7b5bf0a5dca Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:23 -0700 Subject: [PATCH 213/343] perf test: Skip shebang and SPDX comments in shell test descriptions When extracting shell test descriptions in tests-scripts.c, the parser skipped the first line assuming it was the shebang (#!/bin/sh) and then read the first comment line on line 2 as the test description. However, checkpatch.pl expects shell scripts to declare their SPDX license identifier on line 2 (# SPDX-License-Identifier: ...). This caused the test harness to extract the SPDX license string as the test description. Refactor shell_test__description to use io__getline, skipping both shebang and SPDX comment lines. This allows shell tests to include standard SPDX headers without breaking test suite description extraction. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/tests-scripts.c | 80 ++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/tools/perf/tests/tests-scripts.c b/tools/perf/tests/tests-scripts.c index f18c4cd337c8..0370bc701373 100644 --- a/tools/perf/tests/tests-scripts.c +++ b/tools/perf/tests/tests-scripts.c @@ -31,6 +31,7 @@ static int shell_tests__dir_fd(void) { struct stat st; char path[PATH_MAX], path2[PATH_MAX], *exec_path; + ssize_t len; static const char * const devel_dirs[] = { "./tools/perf/tests/shell", "./tests/shell", @@ -47,13 +48,17 @@ static int shell_tests__dir_fd(void) } /* Use directory of executable */ - if (readlink("/proc/self/exe", path2, sizeof path2) < 0) + len = readlink("/proc/self/exe", path2, sizeof(path2) - 1); + if (len < 0) return -1; + path2[len] = '\0'; /* Follow another level of symlink if there */ if (lstat(path2, &st) == 0 && (st.st_mode & S_IFMT) == S_IFLNK) { - scnprintf(path, sizeof(path), path2); - if (readlink(path, path2, sizeof path2) < 0) + scnprintf(path, sizeof(path), "%s", path2); + len = readlink(path, path2, sizeof(path2) - 1); + if (len < 0) return -1; + path2[len] = '\0'; } /* Get directory */ p = strrchr(path2, '/'); @@ -78,43 +83,50 @@ static int shell_tests__dir_fd(void) static char *shell_test__description(int dir_fd, const char *name) { struct io io; - char buf[128], desc[256]; - int ch, pos = 0; + char buf[128], *line = NULL; + size_t line_len = 0; + ssize_t len; + char *desc = NULL; + const char *spdx = "SPDX-License"; io__init(&io, openat(dir_fd, name, O_RDONLY), buf, sizeof(buf)); if (io.fd < 0) return NULL; - /* Skip first line - should be #!/bin/bash Shebang */ - if (io__get_char(&io) != '#') - goto err_out; - if (io__get_char(&io) != '!') - goto err_out; - do { - ch = io__get_char(&io); - if (ch < 0) - goto err_out; - } while (ch != '\n'); + while ((len = io__getline(&io, &line, &line_len)) > 0) { + char *p = line; - do { - ch = io__get_char(&io); - if (ch < 0) - goto err_out; - } while (ch == '#' || isspace(ch)); - while (ch > 0 && ch != '\n') { - desc[pos++] = ch; - if (pos >= (int)sizeof(desc) - 1) + /* Skip leading whitespace */ + while (*p && isspace(*p)) + p++; + + /* Must be a comment */ + if (*p != '#') + continue; + p++; + + /* Skip shebang or SPDX lines */ + if (*p == '!' || (strstr(p, spdx) && strstr(p, "-Identifier:"))) + continue; + + /* Skip whitespace after # */ + while (*p && isspace(*p)) + p++; + + /* If we found non-empty text, this is the description! */ + if (*p && *p != '\n') { + char *end = p + strlen(p); + + while (end > p && isspace(end[-1])) + end--; + *end = '\0'; + desc = strdup(p); break; - ch = io__get_char(&io); + } } - while (pos > 0 && isspace(desc[--pos])) - ; - desc[++pos] = '\0'; + free(line); close(io.fd); - return strdup(desc); -err_out: - close(io.fd); - return NULL; + return desc; } /* Is this full file path a shell script */ @@ -178,9 +190,9 @@ static void append_script(int dir_fd, const char *name, char *desc, char *exclusive; snprintf(link, sizeof(link), "/proc/%d/fd/%d", getpid(), dir_fd); - len = readlink(link, filename, sizeof(filename)); - if (len < 0) { - pr_err("Failed to readlink %s", link); + len = readlink(link, filename, sizeof(filename) - 1); + if (len < 0 || (size_t)len > sizeof(filename) - strlen(name) - 2) { + pr_err("Failed to readlink %s or path too long", link); return; } filename[len++] = '/'; From a540f031bbbceb6e390a71eb9f7f8d65363356ba Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:24 -0700 Subject: [PATCH 214/343] perf test: Split monolithic 'util' test suite into sub-tests Refactor the monolithic 'util' test suite into distinct 'String replacement' and 'BLAKE2s hash' sub-tests using the struct test_case framework. This improves test reporting granularity and is used in a subsequent perf test for JUnit XML test result reporting. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/util.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/util.c b/tools/perf/tests/util.c index bf2c5b133884..f9abd9911e6c 100644 --- a/tools/perf/tests/util.c +++ b/tools/perf/tests/util.c @@ -86,7 +86,12 @@ static int test_blake2s(void) return 0; } -static int test__util(struct test_suite *t __maybe_unused, int subtest __maybe_unused) +static int test__blake2s_case(struct test_suite *t __maybe_unused, int subtest __maybe_unused) +{ + return test_blake2s(); +} + +static int test__strreplace(struct test_suite *t __maybe_unused, int subtest __maybe_unused) { TEST_ASSERT_VAL("empty string", test_strreplace(' ', "", "123", "")); TEST_ASSERT_VAL("no match", test_strreplace('5', "123", "4", "123")); @@ -95,7 +100,16 @@ static int test__util(struct test_suite *t __maybe_unused, int subtest __maybe_u TEST_ASSERT_VAL("replace long", test_strreplace('a', "abcabc", "longlong", "longlongbclonglongbc")); - return test_blake2s(); + return 0; } -DEFINE_SUITE("util", util); +static struct test_case tests__util[] = { + TEST_CASE("String replacement", strreplace), + TEST_CASE("BLAKE2s hash", blake2s_case), + { .name = NULL, } +}; + +struct test_suite suite__util = { + .desc = "util", + .test_cases = tests__util, +}; From e2c545737bf4387d1217d3608274823421e1dbf2 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:25 -0700 Subject: [PATCH 215/343] perf test: Add -j/--junit option for JUnit XML test reports Add a -j/--junit command line option to generate standard JUnit XML format test reports. The generated file defaults to 'test.xml' if no filename is specified, but allows users to override the path (e.g. -jmytest.xml). The XML report captures individual test suite and subtest execution latency, alongside XML-escaped failure logs and skip reasons, while preserving the full multi-process concurrency speed of parallel test execution. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20260602174129.3192312-15-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 148 ++++++++++++++++++++++++++++++-- 1 file changed, 142 insertions(+), 6 deletions(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 4773000f3199..37b91f4e9273 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "builtin.h" #include "config.h" #include "hist.h" @@ -39,6 +40,9 @@ #include "tests-scripts.h" +static const char *junit_filename; +static struct strbuf junit_xml_buf = STRBUF_INIT; + /* * Command line option to not fork the test running in the same process and * making them easier to debug. @@ -307,6 +311,8 @@ struct child_test { struct strbuf err_output; int result; bool done; + struct timespec start_time; + struct timespec end_time; }; static jmp_buf run_test_jmp_buf; @@ -372,8 +378,34 @@ static struct strbuf summary_failed_tests_buf = STRBUF_INIT; static int strbuf_addstr_safe(struct strbuf *sb, const char *s); static int __printf(2, 3) strbuf_addf_safe(struct strbuf *sb, const char *fmt, ...); +static char *xml_escape(const char *str) +{ + struct strbuf buf = STRBUF_INIT; + const char *p; + char *res; + + if (!str) + return strdup(""); + + for (p = str; *p; p++) { + if (*p == '&') + strbuf_addstr(&buf, "&"); + else if (*p == '<') + strbuf_addstr(&buf, "<"); + else if (*p == '>') + strbuf_addstr(&buf, ">"); + else if (*p == '"') + strbuf_addstr(&buf, """); + else if ((unsigned char)*p >= 32 || *p == '\n' || *p == '\t') + strbuf_addch(&buf, *p); + } + res = strbuf_detach(&buf, NULL); + return res ? res : strdup(""); +} + static int print_test_result(struct test_suite *t, int curr_suite, int curr_test_case, - int result, int width, int running) + int result, int width, int running, + const char *err_output, double elapsed) { if (test_suite__num_test_cases(t) > 1) { char prefix[32]; @@ -421,6 +453,34 @@ static int print_test_result(struct test_suite *t, int curr_suite, int curr_test break; } + if (junit_filename && result != TEST_RUNNING) { + const char *classname = t->desc; + const char *testname = test_description(t, curr_test_case); + char *escaped_err = xml_escape(err_output); + char *escaped_class = xml_escape(classname); + char *escaped_test = xml_escape(testname); + + strbuf_addf(&junit_xml_buf, + " \n", + escaped_class, escaped_test, elapsed); + if (result != TEST_OK && result != TEST_SKIP) { + strbuf_addf(&junit_xml_buf, + " \n%s\n \n", + escaped_err); + } else if (result == TEST_SKIP) { + const char *reason = skip_reason(t, curr_test_case); + char *escaped_reason = xml_escape(reason ? reason : "Skip"); + + strbuf_addf(&junit_xml_buf, " \n", + escaped_reason); + free(escaped_reason); + } + strbuf_addstr(&junit_xml_buf, " \n"); + free(escaped_err); + free(escaped_class); + free(escaped_test); + } + return 0; } @@ -623,6 +683,8 @@ static void finish_test(struct child_test **child_tests, int running_test, int c struct strbuf err_output = STRBUF_INIT; int last_running = -1; int ret; + struct timespec end_time; + double elapsed; if (child_test == NULL) { /* Test wasn't started. */ @@ -676,7 +738,7 @@ static void finish_test(struct child_test **child_tests, int running_test, int c fprintf(debug_file(), PERF_COLOR_DELETE_LINE); } print_test_result(t, curr_suite, curr_test_case, TEST_RUNNING, - width, running); + width, running, NULL, 0.0); last_running = running; } } @@ -736,9 +798,14 @@ static void finish_test(struct child_test **child_tests, int running_test, int c else if (verbose == 1 && ret == TEST_FAIL) print_test_failure_snippet(stderr, err_output.buf); + clock_gettime(CLOCK_MONOTONIC, &end_time); + elapsed = (end_time.tv_sec - child_test->start_time.tv_sec) + + (end_time.tv_nsec - child_test->start_time.tv_nsec) / 1000000000.0; + + print_test_result(t, curr_suite, curr_test_case, ret, width, /*running=*/0, + err_output.buf, elapsed); strbuf_release(&err_output); strbuf_release(&child_test->err_output); - print_test_result(t, curr_suite, curr_test_case, ret, width, /*running=*/0); if (err > 0) close(err); zfree(&child_tests[running_test]); @@ -914,7 +981,7 @@ static int finish_tests_parallel(struct child_test **child_tests, size_t num_tes } print_test_result(next_child->test, next_child->suite_num, next_child->test_case_num, TEST_RUNNING, width, - running_count); + running_count, NULL, 0.0); } last_running = running_count; } @@ -949,12 +1016,14 @@ static int finish_tests_parallel(struct child_test **child_tests, size_t num_tes } child->result = finish_command(&child->process); child->process.pid = 0; + clock_gettime(CLOCK_MONOTONIC, &child->end_time); child->done = true; } } while (next_to_print < num_tests) { struct child_test *child = child_tests[next_to_print]; + double elapsed; if (!child) { next_to_print++; @@ -992,8 +1061,12 @@ static int finish_tests_parallel(struct child_test **child_tests, size_t num_tes else if (verbose == 1 && child->result == TEST_FAIL) print_test_failure_snippet(stderr, child->err_output.buf); + elapsed = (child->end_time.tv_sec - child->start_time.tv_sec) + + (child->end_time.tv_nsec - + child->start_time.tv_nsec) / 1000000000.0; + print_test_result(child->test, child->suite_num, child->test_case_num, - child->result, width, 0); + child->result, width, 0, child->err_output.buf, elapsed); pthread_sigmask(SIG_BLOCK, &set, &oldset); strbuf_release(&child->err_output); child_tests[next_to_print] = NULL; @@ -1020,11 +1093,18 @@ static int start_test(struct test_suite *test, int curr_suite, int curr_test_cas *child = NULL; if (dont_fork) { if (pass == 1) { + struct timespec start_time, end_time; + double elapsed; + + clock_gettime(CLOCK_MONOTONIC, &start_time); pr_debug("--- start ---\n"); err = test_function(test, curr_test_case)(test, curr_test_case); pr_debug("---- end ----\n"); + clock_gettime(CLOCK_MONOTONIC, &end_time); + elapsed = (end_time.tv_sec - start_time.tv_sec) + + (end_time.tv_nsec - start_time.tv_nsec) / 1000000000.0; print_test_result(test, curr_suite, curr_test_case, err, width, - /*running=*/0); + /*running=*/0, NULL, elapsed); } return 0; } @@ -1090,6 +1170,41 @@ static void print_tests_summary(void) } else { color_fprintf(stderr, PERF_COLOR_GREEN, "Failed tests : 0\n"); } + + if (junit_filename) { + int fd; + FILE *fp; + + fd = open(junit_filename, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0644); + if (fd >= 0) { + fp = fdopen(fd, "w"); + if (fp) { + unsigned int total = summary_tests_passed + + summary_subtests_passed + + summary_tests_skipped + + summary_tests_failed; + fprintf(fp, "\n"); + fprintf(fp, "\n"); + fprintf(fp, + " \n", + total, summary_tests_failed, + summary_tests_skipped); + fprintf(fp, "%s", junit_xml_buf.buf); + fprintf(fp, " \n"); + fprintf(fp, "\n"); + fclose(fp); + pr_info("Wrote junit XML output to %s\n", junit_filename); + } else { + close(fd); + pr_err("Failed to associate stream with fd for %s: %s\n", + junit_filename, strerror(errno)); + } + } else { + pr_err("Failed to open %s for writing junit XML output: %s\n", + junit_filename, strerror(errno)); + } + } + strbuf_release(&junit_xml_buf); strbuf_release(&summary_failed_tests_buf); } @@ -1176,6 +1291,25 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[], color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); summary_tests_skipped++; + if (junit_filename) { + char *escaped_class = + xml_escape((const char *) + test_description(*t, -1)); + char *escaped_test = xml_escape("override"); + char *escaped_reason = + xml_escape("user override"); + + strbuf_addf(&junit_xml_buf, + " \n", + escaped_class, escaped_test); + strbuf_addf(&junit_xml_buf, + " \n", + escaped_reason); + strbuf_addstr(&junit_xml_buf, " \n"); + free(escaped_reason); + free(escaped_test); + free(escaped_class); + } } continue; } @@ -1357,6 +1491,8 @@ int cmd_test(int argc, const char **argv) "objdump binary to use for disassembly and annotations"), OPT_UINTEGER(0, "failure-snippet-lines", &failure_snippet_lines, "Number of lines to include in failure snippet, default 10"), + OPT_STRING_OPTARG('j', "junit", &junit_filename, "file", + "Generate junit XML output, default test.xml", "test.xml"), OPT_END() }; const char * const test_subcommands[] = { "list", NULL }; From 0dd6025171436822e54ae556dc48aed89c42b6a9 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:26 -0700 Subject: [PATCH 216/343] perf test: Add shell test to validate JUnit XML reporting output Add a shell test script (test_test_junit_output.sh) to execute perf test with the -j/--junit option and validate that the generated test report complies perfectly with standard XML formatting using Python's ElementTree XML parser. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- .../tests/shell/test_test_junit_output.sh | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100755 tools/perf/tests/shell/test_test_junit_output.sh diff --git a/tools/perf/tests/shell/test_test_junit_output.sh b/tools/perf/tests/shell/test_test_junit_output.sh new file mode 100755 index 000000000000..5104ac1e1e6d --- /dev/null +++ b/tools/perf/tests/shell/test_test_junit_output.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# perf test junit XML output validation + +set -e + +err=0 + +shelldir=$(dirname "$0") +# shellcheck source=lib/setup_python.sh +. "${shelldir}"/lib/setup_python.sh + +result=$(mktemp /tmp/__perf_test.output.xml.XXXXX) + +cleanup() +{ + rm -f "${result}" + trap - exit term int +} + +trap_cleanup() +{ + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup + exit 1 +} +trap trap_cleanup exit term int + +test_junit_output() +{ + echo "Testing perf test JUnit XML output command" + perf test -v -j"$result" util || true + if [ -s "$result" ] ; then + echo "perf test JUnit XML output command [SUCCESS]" + else + echo "perf test JUnit XML output command [FAILED]" + err=1 + fi +} + +validate_xml_format() +{ + echo "Validating perf test converted JUnit XML file" + if [ -f "$result" ] ; then + if $PYTHON -c \ + "import xml.etree.ElementTree as ET; ET.parse('$result')" \ + >/dev/null 2>&1 ; then + echo "The file contains valid XML format [SUCCESS]" + else + echo "The file does not contain valid XML format [FAILED]" + err=1 + fi + else + echo "File not found [FAILED]" + err=1 + fi +} + +test_junit_output +validate_xml_format + +cleanup +exit ${err} From a77ecea7ced2fef7cc0a8ad0323542f781ad9788 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 Jun 2026 10:41:27 -0700 Subject: [PATCH 217/343] perf test: Remove /usr/bin/cc dependency from Intel PT shell test In test_intel_pt.sh, the test script compiled two external C programs at runtime using /usr/bin/cc (a thread loop workload and a JIT self- modifying workload). Relying on external C compilers inside shell tests frequently causes failures in continuous integration environments. Create a built-in 'jitdump' workload and switch test_intel_pt.sh to use 'perf test -w thloop' and 'perf test -w jitdump'. Also add multi- architecture compatibility without external C compiler dependencies, the workload instruction arrays dynamically encode CHK_BYTE into opcodes across x86, ARM32, ARM64, RISC-V, PowerPC, MIPS, LoongArch, and s390x. Some minor include fixes for util/jitdump.h. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 1 + tools/perf/tests/shell/test_intel_pt.sh | 169 +------------------ tools/perf/tests/tests.h | 1 + tools/perf/tests/workloads/Build | 1 + tools/perf/tests/workloads/jitdump.c | 210 ++++++++++++++++++++++++ tools/perf/util/jitdump.h | 3 +- 6 files changed, 217 insertions(+), 168 deletions(-) create mode 100644 tools/perf/tests/workloads/jitdump.c diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 37b91f4e9273..b64fc2204f22 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -161,6 +161,7 @@ static struct test_workload *workloads[] = { &workload__landlock, &workload__traploop, &workload__inlineloop, + &workload__jitdump, #ifdef HAVE_RUST_SUPPORT &workload__code_with_type, diff --git a/tools/perf/tests/shell/test_intel_pt.sh b/tools/perf/tests/shell/test_intel_pt.sh index 8ee761f03c38..26243ff760ec 100755 --- a/tools/perf/tests/shell/test_intel_pt.sh +++ b/tools/perf/tests/shell/test_intel_pt.sh @@ -21,9 +21,7 @@ tmpfile="${temp_dir}/tmp-perf.data" perfdatafile="${temp_dir}/test-perf.data" outfile="${temp_dir}/test-out.txt" errfile="${temp_dir}/test-err.txt" -workload="${temp_dir}/workload" awkscript="${temp_dir}/awkscript" -jitdump_workload="${temp_dir}/jitdump_workload" maxbrstack="${temp_dir}/maxbrstack.py" cleanup() @@ -60,37 +58,6 @@ perf_record_no_bpf() perf record --no-bpf-event "$@" } -have_workload=false -cat << _end_of_file_ | /usr/bin/cc -o "${workload}" -xc - -pthread && have_workload=true -#include -#include - -void work(void) { - struct timespec tm = { - .tv_nsec = 1000000, - }; - int i; - - /* Run for about 30 seconds */ - for (i = 0; i < 30000; i++) - nanosleep(&tm, NULL); -} - -void *threadfunc(void *arg) { - work(); - return NULL; -} - -int main(void) { - pthread_t th; - - pthread_create(&th, NULL, threadfunc, NULL); - work(); - pthread_join(th, NULL); - return 0; -} -_end_of_file_ - can_cpu_wide() { echo "Checking for CPU-wide recording on CPU $1" @@ -145,11 +112,6 @@ test_per_thread() echo "--- Test per-thread ${desc}recording ---" - if ! $have_workload ; then - echo "No workload, so skipping" - return 2 - fi - if [ "${k}" = "k" ] ; then can_kernel || return 2 fi @@ -252,9 +214,9 @@ test_per_thread() } _end_of_file_ - $workload & + perf test -w thloop 30 2 & w1=$! - $workload & + perf test -w thloop 30 2 & w2=$! echo "Workload PIDs are $w1 and $w2" wait_for_threads ${w1} 2 @@ -283,139 +245,14 @@ test_jitdump() { echo "--- Test tracing self-modifying code that uses jitdump ---" - script_path=$(realpath "$0") - script_dir=$(dirname "$script_path") - jitdump_incl_dir="${script_dir}/../../util" - jitdump_h="${jitdump_incl_dir}/jitdump.h" - if ! perf check feature -q libelf ; then echo "SKIP: libelf is needed for jitdump" return 2 fi - if [ ! -e "${jitdump_h}" ] ; then - echo "SKIP: Include file jitdump.h not found" - return 2 - fi - - if [ -z "${have_jitdump_workload}" ] ; then - have_jitdump_workload=false - # Create a workload that uses self-modifying code and generates its own jitdump file - cat <<- "_end_of_file_" | /usr/bin/cc -o "${jitdump_workload}" -I "${jitdump_incl_dir}" -xc - -pthread && have_jitdump_workload=true - #define _GNU_SOURCE - #include - #include - #include - #include - #include - #include - #include - - #include "jitdump.h" - - #define CHK_BYTE 0x5a - - static inline uint64_t rdtsc(void) - { - unsigned int low, high; - - asm volatile("rdtsc" : "=a" (low), "=d" (high)); - - return low | ((uint64_t)high) << 32; - } - - static FILE *open_jitdump(void) - { - struct jitheader header = { - .magic = JITHEADER_MAGIC, - .version = JITHEADER_VERSION, - .total_size = sizeof(header), - .pid = getpid(), - .timestamp = rdtsc(), - .flags = JITDUMP_FLAGS_ARCH_TIMESTAMP, - }; - char filename[256]; - FILE *f; - void *m; - - snprintf(filename, sizeof(filename), "jit-%d.dump", getpid()); - f = fopen(filename, "w+"); - if (!f) - goto err; - /* Create an MMAP event for the jitdump file. That is how perf tool finds it. */ - m = mmap(0, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(f), 0); - if (m == MAP_FAILED) - goto err_close; - munmap(m, 4096); - if (fwrite(&header,sizeof(header),1,f) != 1) - goto err_close; - return f; - - err_close: - fclose(f); - err: - return NULL; - } - - static int write_jitdump(FILE *f, void *addr, const uint8_t *dat, size_t sz, uint64_t *idx) - { - struct jr_code_load rec = { - .p.id = JIT_CODE_LOAD, - .p.total_size = sizeof(rec) + sz, - .p.timestamp = rdtsc(), - .pid = getpid(), - .tid = gettid(), - .vma = (unsigned long)addr, - .code_addr = (unsigned long)addr, - .code_size = sz, - .code_index = ++*idx, - }; - - if (fwrite(&rec,sizeof(rec),1,f) != 1 || - fwrite(dat, sz, 1, f) != 1) - return -1; - return 0; - } - - static void close_jitdump(FILE *f) - { - fclose(f); - } - - int main() - { - /* Get a memory page to store executable code */ - void *addr = mmap(0, 4096, PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - /* Code to execute: mov CHK_BYTE, %eax ; ret */ - uint8_t dat[] = {0xb8, CHK_BYTE, 0x00, 0x00, 0x00, 0xc3}; - FILE *f = open_jitdump(); - uint64_t idx = 0; - int ret = 1; - - if (!f) - return 1; - /* Copy executable code to executable memory page */ - memcpy(addr, dat, sizeof(dat)); - /* Record it in the jitdump file */ - if (write_jitdump(f, addr, dat, sizeof(dat), &idx)) - goto out_close; - /* Call it */ - ret = ((int (*)(void))addr)() - CHK_BYTE; - out_close: - close_jitdump(f); - return ret; - } - _end_of_file_ - fi - - if ! $have_jitdump_workload ; then - echo "SKIP: No jitdump workload" - return 2 - fi - # Change to temp_dir so jitdump collateral files go there cd "${temp_dir}" - perf_record_no_bpf -o "${tmpfile}" -e intel_pt//u "${jitdump_workload}" + perf_record_no_bpf -o "${tmpfile}" -e intel_pt//u perf test -w jitdump perf inject -i "${tmpfile}" -o "${perfdatafile}" --jit decode_br_cnt=$(perf script -i "${perfdatafile}" --itrace=b | wc -l) # Note that overflow and lost errors are suppressed for the error count diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 9bcf1dbb0663..bf8ff7d54727 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -244,6 +244,7 @@ DECLARE_WORKLOAD(datasym); DECLARE_WORKLOAD(landlock); DECLARE_WORKLOAD(traploop); DECLARE_WORKLOAD(inlineloop); +DECLARE_WORKLOAD(jitdump); #ifdef HAVE_RUST_SUPPORT DECLARE_WORKLOAD(code_with_type); diff --git a/tools/perf/tests/workloads/Build b/tools/perf/tests/workloads/Build index 2ef97f7affce..0eb6d99528eb 100644 --- a/tools/perf/tests/workloads/Build +++ b/tools/perf/tests/workloads/Build @@ -9,6 +9,7 @@ perf-test-y += datasym.o perf-test-y += landlock.o perf-test-y += traploop.o perf-test-y += inlineloop.o +perf-test-y += jitdump.o ifeq ($(CONFIG_RUST_SUPPORT),y) perf-test-y += code_with_type.o diff --git a/tools/perf/tests/workloads/jitdump.c b/tools/perf/tests/workloads/jitdump.c new file mode 100644 index 000000000000..01cbbbd564e8 --- /dev/null +++ b/tools/perf/tests/workloads/jitdump.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "util/jitdump.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../tests.h" + +#ifndef HAVE_GETTID +#include +static inline pid_t gettid(void) +{ + return (pid_t)syscall(SYS_gettid); +} +#endif + +#define CHK_BYTE 0x5a + +static inline uint64_t get_timestamp(void) +{ +#if defined(__x86_64__) || defined(__i386__) + unsigned int low, high; + + asm volatile("rdtsc" : "=a"(low), "=d"(high)); + + return low | ((uint64_t)high) << 32; +#else + struct timespec ts; + int ret; + + ret = clock_gettime(CLOCK_MONOTONIC, &ts); + if (ret) + return 0; + + return ((uint64_t)ts.tv_sec * 1000000000) + ts.tv_nsec; +#endif +} + +static FILE *open_jitdump(void) +{ + struct jitheader header = { + .magic = JITHEADER_MAGIC, + .version = JITHEADER_VERSION, + .total_size = sizeof(header), + .pid = getpid(), + .timestamp = get_timestamp(), + .flags = +#if defined(__x86_64__) || defined(__i386__) + JITDUMP_FLAGS_ARCH_TIMESTAMP, +#else + 0, +#endif + }; + char filename[256]; + int fd; + FILE *f; + void *m; + + snprintf(filename, sizeof(filename), "jit-%d.dump", getpid()); + /* Securely open using O_CREAT | O_EXCL to prevent symlink attacks. */ + fd = open(filename, O_CREAT | O_EXCL | O_RDWR, 0644); + if (fd < 0) { + pr_err("Failed to open jitdump '%s': %s\n", filename, strerror(errno)); + return NULL; + } + f = fdopen(fd, "w+"); + if (!f) { + pr_err("Failed to associate stream with fd for '%s'\n", filename); + close(fd); + unlink(filename); + return NULL; + } + /* Create an MMAP event for the jitdump file. That is how perf tool finds it. */ + m = mmap(0, getpagesize(), PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(f), 0); + if (m == MAP_FAILED) { + pr_err("mmap failed: %s\n", strerror(errno)); + fclose(f); + unlink(filename); + return NULL; + } + munmap(m, getpagesize()); + + if (fwrite(&header, sizeof(header), 1, f) != 1) { + pr_err("Error writing jitdump header\n"); + fclose(f); + unlink(filename); + return NULL; + } + return f; +} + +static int write_jitdump(FILE *f, void *addr, const void *dat, size_t sz, uint64_t *idx) +{ + const char *sym = "jit_workload"; + size_t sym_len = strlen(sym) + 1; + struct jr_code_load rec = { + .p.id = JIT_CODE_LOAD, + .p.total_size = sizeof(rec) + sym_len + sz, + .p.timestamp = get_timestamp(), + .pid = getpid(), + .tid = gettid(), + .vma = (unsigned long)addr, + .code_addr = (unsigned long)addr, + .code_size = sz, + .code_index = ++*idx, + }; + + if (fwrite(&rec, sizeof(rec), 1, f) != 1 || + fwrite(sym, sym_len, 1, f) != 1 || + fwrite(dat, sz, 1, f) != 1) + return -1; + return 0; +} + +static void close_jitdump(FILE *f) +{ + fclose(f); +} + +static int jitdump(int argc __maybe_unused, const char **argv __maybe_unused) +{ +#if defined(__x86_64__) || defined(__i386__) + /* Code to execute: mov CHK_BYTE, %eax ; ret */ + uint8_t dat[] = { 0xb8, CHK_BYTE, 0x00, 0x00, 0x00, 0xc3 }; +#elif defined(__aarch64__) + /* Code to execute: mov w0, #CHK_BYTE ; ret */ + uint8_t dat[] = { + (CHK_BYTE << 5) & 0xff, (CHK_BYTE >> 3) & 0xff, 0x80, 0x52, + 0xc0, 0x03, 0x5f, 0xd6 + }; +#elif defined(__riscv) + /* Code to execute: li a0, CHK_BYTE ; ret */ + uint8_t dat[] = { + 0x13, 0x05, (CHK_BYTE << 4) & 0xff, (CHK_BYTE >> 4) & 0xff, + 0x67, 0x80, 0x00, 0x00 + }; +#elif defined(__powerpc__) + /* Code to execute: li r3, CHK_BYTE ; blr */ + uint32_t dat[] = { 0x38600000 | (CHK_BYTE & 0xffff), 0x4e800020 }; +#elif defined(__s390x__) + /* Code to execute: lhi %r2, CHK_BYTE ; br %r14 */ + uint8_t dat[] = { 0xa7, 0x28, (CHK_BYTE >> 8) & 0xff, CHK_BYTE & 0xff, 0x07, 0xfe }; +#elif defined(__arm__) + /* Code to execute: mov r0, #CHK_BYTE ; bx lr */ + uint8_t dat[] = { + CHK_BYTE & 0xff, 0x00, 0xa0, 0xe3, + 0x1e, 0xff, 0x2f, 0xe1 + }; +#elif defined(__mips__) + /* Code to execute: addiu $v0, $zero, CHK_BYTE ; jr $ra ; nop */ + uint32_t dat[] = { 0x24020000 | (CHK_BYTE & 0xffff), 0x03e00008, 0x00000000 }; +#elif defined(__loongarch__) + /* Code to execute: addi.w $a0, $zero, CHK_BYTE ; jirl $zero, $ra, 0 */ + uint32_t dat[] = { 0x02800004 | ((CHK_BYTE & 0xfff) << 10), 0x4c000020 }; +#else + uint32_t dat[0]; +#endif + void *addr; + FILE *f; + uint64_t idx = 0; + int ret = 1; + + /* Reachable fallback check for unsupported architectures right at start. */ + if (sizeof(dat) == 0) { + pr_err("JITDUMP workload not supported on this architecture\n"); + return 1; + } + + /* Get a memory page to store executable code. */ + addr = mmap(0, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (addr == MAP_FAILED) { + pr_err("Failed to map 1 -rwx page\n"); + return 1; + } + + f = open_jitdump(); + if (!f) { + pr_err("Failed to open JITDUMP\n"); + munmap(addr, getpagesize()); + return 1; + } + /* Copy executable code to executable memory page. */ + memcpy(addr, dat, sizeof(dat)); + /* Synchronize the Instruction and Data caches. */ + __builtin___clear_cache(addr, (char *)addr + sizeof(dat)); + + /* Record it in the jitdump file */ + if (write_jitdump(f, addr, dat, sizeof(dat), &idx) == 0) { + int (*fn)(void) = addr; + + /* Call the function. */ + ret = fn() - CHK_BYTE; + } + close_jitdump(f); + munmap(addr, getpagesize()); + return ret; +} + +DEFINE_WORKLOAD(jitdump); diff --git a/tools/perf/util/jitdump.h b/tools/perf/util/jitdump.h index ab2842def83d..f57bfebb20ff 100644 --- a/tools/perf/util/jitdump.h +++ b/tools/perf/util/jitdump.h @@ -11,9 +11,8 @@ #ifndef JITDUMP_H #define JITDUMP_H -#include -#include #include +#include /* JiTD */ #define JITHEADER_MAGIC 0x4A695444 From b72ab69175157aac2f3ff1ebc0765e3899ba295b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 4 Jun 2026 10:28:39 -0700 Subject: [PATCH 218/343] perf lock contention: Allow 'mmap_lock' in -L/--lock-filter The -L/--lock-filter option is to specify target locks by name or address. It's basically for global locks where name or address is known and fixed. But 'mmap_lock' is a per-process lock so it cannot be used for the -L option. $ sudo perf lock con -ab -L mmap_lock ignore unknown symbol: mmap_lock libbpf: map 'addr_filter': failed to create: -EINVAL libbpf: failed to load BPF skeleton 'lock_contention_bpf': -EINVAL Failed to load lock-contention BPF skeleton lock contention BPF setup failed However, it's still a common source of contention especially in a large process so we want to use it for the -L/--lock-filter option. As there is check_lock_type() to check mmap_lock at runtime, let's used it to filter mmap_locks as a special case. Of course, this only works with -b/--use-bpf option. $ sudo perf lock con -b -L mmap_lock -- perf bench mem mmap -f demand -t 2 # Running 'mem/mmap' benchmark: # function 'demand' (Demand loaded mmap()) # Copying 1MB bytes ... 2.679184 GB/sec/thread ( +- 1.78% ) contended total wait max wait avg wait type caller 1 15.22 us 15.22 us 15.22 us rwsem:W __vm_munmap+0x7e 1 7.72 us 7.72 us 7.72 us rwsem:R lock_mm_and_find_vma+0x97 Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Suchit Karunakaran Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/lock_contention.sh | 11 ++++++++ tools/perf/util/bpf_lock_contention.c | 9 ++++++- .../perf/util/bpf_skel/lock_contention.bpf.c | 25 +++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/shell/lock_contention.sh b/tools/perf/tests/shell/lock_contention.sh index 6dd90519f45c..52e8b9db9fbd 100755 --- a/tools/perf/tests/shell/lock_contention.sh +++ b/tools/perf/tests/shell/lock_contention.sh @@ -208,6 +208,17 @@ test_lock_filter() err=1 exit fi + + perf lock con -b -L mmap_lock -q -- perf bench mem mmap -t 2 -l 10 > /dev/null 2> ${result} + + # find out the type of mmap_lock + test_lock_filter_type=$(head -1 "${result}" | awk '{ print $8 }' | sed -e 's/:.*//') + + if [ "$(grep -c -v "${test_lock_filter_type}" "${result}")" != "0" ]; then + echo "[Fail] BPF result should not have non-${test_lock_filter_type} locks:" "$(cat "${result}")" + err=1 + exit + fi } test_stack_filter() diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c index cbd7435579fe..eb8e29b8064b 100644 --- a/tools/perf/util/bpf_lock_contention.c +++ b/tools/perf/util/bpf_lock_contention.c @@ -186,6 +186,7 @@ int lock_contention_prepare(struct lock_contention *con) int ncpus = 1, ntasks = 1, ntypes = 1, naddrs = 1, ncgrps = 1, nslabs = 1; struct evlist *evlist = con->evlist; struct target *target = con->target; + bool has_mmap_lock = false; /* make sure it loads the kernel map before lookup */ map__load(machine__kernel_map(con->machine)); @@ -244,6 +245,11 @@ int lock_contention_prepare(struct lock_contention *con) unsigned long *addrs; for (i = 0; i < con->filters->nr_syms; i++) { + if (!strcmp(con->filters->syms[i], "mmap_lock")) { + has_mmap_lock = true; + continue; + } + sym = machine__find_kernel_symbol_by_name(con->machine, con->filters->syms[i], &kmap); @@ -263,7 +269,7 @@ int lock_contention_prepare(struct lock_contention *con) addrs[con->filters->nr_addrs++] = map__unmap_ip(kmap, sym->start); con->filters->addrs = addrs; } - naddrs = con->filters->nr_addrs; + naddrs = con->filters->nr_addrs ?: has_mmap_lock; skel->rodata->has_addr = 1; } @@ -298,6 +304,7 @@ int lock_contention_prepare(struct lock_contention *con) skel->rodata->aggr_mode = con->aggr_mode; skel->rodata->needs_callstack = con->save_callstack; skel->rodata->lock_owner = con->owner; + skel->rodata->has_mmap_lock = has_mmap_lock; if (con->aggr_mode == LOCK_AGGR_CGROUP || con->filters->nr_cgrps) { if (cgroup_is_v2("perf_event")) diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c index 5c8431be674a..d4186ae9f85c 100644 --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c @@ -191,6 +191,7 @@ const volatile int has_type; const volatile int has_addr; const volatile int has_cgroup; const volatile int has_slab; +const volatile int has_mmap_lock; const volatile int needs_callstack; const volatile int stack_skip; const volatile int lock_owner; @@ -221,6 +222,8 @@ int data_map_full; struct task_struct *bpf_task_from_pid(s32 pid) __ksym __weak; void bpf_task_release(struct task_struct *p) __ksym __weak; +static inline __u32 check_lock_type(__u64 lock, __u32 flags); + static inline __u64 get_current_cgroup_id(void) { struct task_struct *task; @@ -246,6 +249,8 @@ static inline __u64 get_current_cgroup_id(void) static inline int can_record(u64 *ctx) { + bool is_addr_ok = false; + if (has_cpu) { __u32 cpu = bpf_get_smp_processor_id(); __u8 *ok; @@ -278,8 +283,10 @@ static inline int can_record(u64 *ctx) __u64 addr = ctx[0]; ok = bpf_map_lookup_elem(&addr_filter, &addr); - if (!ok && !has_slab) + if (!ok && !has_slab && !has_mmap_lock) return 0; + + is_addr_ok = !!ok; } if (has_cgroup) { @@ -291,6 +298,10 @@ static inline int can_record(u64 *ctx) return 0; } + if (is_addr_ok) + return 1; + + /* slab and mmap_lock are part of the addr_filter */ if (has_slab && bpf_get_kmem_cache) { __u8 *ok; __u64 addr = ctx[0]; @@ -298,7 +309,17 @@ static inline int can_record(u64 *ctx) kmem_cache_addr = (long)bpf_get_kmem_cache(addr); ok = bpf_map_lookup_elem(&slab_filter, &kmem_cache_addr); - if (!ok) + if (ok) + return 1; + else if (!has_mmap_lock) + return 0; + } + + if (has_mmap_lock) { + __u64 lock = ctx[0]; + __u32 flag = ctx[1]; + + if (check_lock_type(lock, flag) != LCD_F_MMAP_LOCK) return 0; } From 536e81f07450562caba8e62022763a78fd00a0a7 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Thu, 4 Jun 2026 13:17:05 -0400 Subject: [PATCH 219/343] perf data ctf: replace libbabeltrace with babeltrace2-ctf-writer The 1.x branch of Babeltrace has been superseded by 2.x in 2020 and has been unmaintained since 2022, efforts have started to remove it from popular distributions. Babeltrace 2.x offers a very similar 'ctf-writer' library that can be used with minimal changes for the '--to-ctf' feature and has been packaged since Debian 11 and Fedora 32. This patch replaces the 'libbabeltrace' build feature with 'babeltrace2-ctf-writer' using pkgconfig detection, adjusts the naming of the public headers and applies minor API cleanups. There is no changes to the output ctf traces, the ctf-writer API still implements version 1.8 of the CTF specification that can be read by either Babeltrace 1 / 2 or any CTF compliant reader. Also remove some ifdefs in the cli option parsing to allow printing the helpful error message with '--to-ctf' when built without babeltrace2. Reviewed-by: Ian Rogers Signed-off-by: Michael Jeanson Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Derek Foreman Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Mathieu Desnoyers Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Makefile.feature | 5 +-- tools/build/feature/Makefile | 6 ++-- tools/build/feature/test-all.c | 6 ++-- ...ltrace.c => test-babeltrace2-ctf-writer.c} | 3 +- tools/perf/Makefile.config | 27 +++++++-------- tools/perf/Makefile.perf | 2 +- tools/perf/builtin-check.c | 2 +- tools/perf/builtin-data.c | 18 +++------- tools/perf/tests/make | 4 +-- .../shell/test_perf_data_converter_ctf.sh | 8 ++--- tools/perf/util/Build | 2 +- tools/perf/util/data-convert-bt.c | 33 +++++++++---------- tools/perf/util/data-convert.h | 4 +-- 13 files changed, 53 insertions(+), 67 deletions(-) rename tools/build/feature/{test-libbabeltrace.c => test-babeltrace2-ctf-writer.c} (59%) diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index af79c6cf0229..ed1374af31c1 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -116,7 +116,7 @@ FEATURE_TESTS_EXTRA := \ gtk2 \ gtk2-infobar \ hello \ - libbabeltrace \ + babeltrace2-ctf-writer \ libcapstone \ libcheck \ libbfd-liberty \ @@ -169,6 +169,7 @@ FEATURE_GROUP_MEMBERS-libbfd = libbfd-liberty libbfd-liberty-z # Declare list of feature dependency packages that provide pkg-config files. # FEATURE_PKG_CONFIG ?= \ + babeltrace2-ctf-writer \ libtraceevent \ libtracefs @@ -217,7 +218,7 @@ ifeq ($(feature-all), 1) $(call feature_check,compile-32) $(call feature_check,compile-x32) $(call feature_check,bionic) - $(call feature_check,libbabeltrace) + $(call feature_check,babeltrace2-ctf-writer) $(call feature_check,libunwind) $(call feature_check,libunwind-debug-frame) $(foreach arch,$(LIBUNWIND_ARCHS),$(call feature_check,libunwind-$(arch))) diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 9da5a4fd956a..62909a9c799d 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -45,7 +45,7 @@ FILES= \ test-pthread-barrier.bin \ test-stackprotector-all.bin \ test-timerfd.bin \ - test-libbabeltrace.bin \ + test-babeltrace2-ctf-writer.bin \ test-libcapstone.bin \ test-libcheck.bin \ test-compile-32.bin \ @@ -305,8 +305,8 @@ $(OUTPUT)test-backtrace.bin: $(OUTPUT)test-timerfd.bin: $(BUILD) -$(OUTPUT)test-libbabeltrace.bin: - $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace) +$(OUTPUT)test-babeltrace2-ctf-writer.bin: + $(BUILD) # -lbabeltrace2-ctf-writer provided by $(FEATURE_CHECK_LDFLAGS-babeltrace2-ctf-writer) $(OUTPUT)test-libcapstone.bin: $(BUILD) # -lcapstone provided by $(FEATURE_CHECK_LDFLAGS-libcapstone) diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c index 1488bf6e6078..544563d62950 100644 --- a/tools/build/feature/test-all.c +++ b/tools/build/feature/test-all.c @@ -100,13 +100,13 @@ # if 0 /* - * Disable libbabeltrace check for test-all, because the requested + * Disable babeltrace2-ctf-writer check for test-all, because the requested * library version is not released yet in most distributions. Will * reenable later. */ -#define main main_test_libbabeltrace -# include "test-libbabeltrace.c" +#define main main_test_babeltrace2_ctf_writer +# include "test-babeltrace2-ctf-writer.c" #undef main #endif diff --git a/tools/build/feature/test-libbabeltrace.c b/tools/build/feature/test-babeltrace2-ctf-writer.c similarity index 59% rename from tools/build/feature/test-libbabeltrace.c rename to tools/build/feature/test-babeltrace2-ctf-writer.c index 10bb69d55694..9c89082e9f88 100644 --- a/tools/build/feature/test-libbabeltrace.c +++ b/tools/build/feature/test-babeltrace2-ctf-writer.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 -#include -#include +#include int main(void) { diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index c531b9315609..6e7b15fab2ec 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -184,14 +184,11 @@ endif FEATURE_CHECK_CFLAGS-libdw := $(LIBDW_CFLAGS) FEATURE_CHECK_LDFLAGS-libdw := $(LIBDW_LDFLAGS) $(DWARFLIBS) -# for linking with debug library, run like: -# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/ -ifdef LIBBABELTRACE_DIR - LIBBABELTRACE_CFLAGS := -I$(LIBBABELTRACE_DIR)/include - LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib +ifneq ($(NO_BABELTRACE2),1) + ifeq ($(call get-executable,$(PKG_CONFIG)),) + $(error Error: $(PKG_CONFIG) needed by babeltrace2 is missing on this system, please install it) + endif endif -FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS) -FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf # for linking with debug library, run like: # make DEBUG=1 LIBCAPSTONE_DIR=/opt/capstone/ @@ -1035,15 +1032,15 @@ else NO_PERF_READ_VDSOX32 := 1 endif -ifndef NO_LIBBABELTRACE - $(call feature_check,libbabeltrace) - ifeq ($(feature-libbabeltrace), 1) - CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS) - LDFLAGS += $(LIBBABELTRACE_LDFLAGS) - EXTLIBS += -lbabeltrace-ctf - $(call detected,CONFIG_LIBBABELTRACE) +ifndef NO_BABELTRACE2 + $(call feature_check,babeltrace2-ctf-writer) + ifeq ($(feature-babeltrace2-ctf-writer), 1) + CFLAGS += -DHAVE_BABELTRACE2_CTF_WRITER_SUPPORT $(shell $(PKG_CONFIG) --cflags babeltrace2-ctf-writer) + LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L babeltrace2-ctf-writer) + EXTLIBS += $(shell $(PKG_CONFIG) --libs-only-l babeltrace2-ctf-writer) + $(call detected,CONFIG_BABELTRACE2_CTF_WRITER) else - $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev) + $(warning No babeltrace2 found, disables 'perf data' CTF format support, please install libbabeltrace2-dev[el]) endif endif diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 4ac2a0cec9ee..ab661a1d271c 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -79,7 +79,7 @@ include ../scripts/utilities.mak # # Define NO_ZLIB if you do not want to support compressed kernel modules # -# Define NO_LIBBABELTRACE if you do not want libbabeltrace support +# Define NO_BABELTRACE2 if you do not want babeltrace2-ctf-writer support # for CTF data format. # # Define NO_CAPSTONE if you do not want libcapstone support diff --git a/tools/perf/builtin-check.c b/tools/perf/builtin-check.c index 3641d263b345..60437650c50f 100644 --- a/tools/perf/builtin-check.c +++ b/tools/perf/builtin-check.c @@ -43,7 +43,7 @@ struct feature_status supported_features[] = { FEATURE_STATUS("dwarf_getlocations", HAVE_LIBDW_SUPPORT), FEATURE_STATUS("dwarf-unwind", HAVE_DWARF_UNWIND_SUPPORT), FEATURE_STATUS_TIP("libbfd", HAVE_LIBBFD_SUPPORT, "Deprecated, license incompatibility, use BUILD_NONDISTRO=1 and install binutils-dev[el]"), - FEATURE_STATUS("libbabeltrace", HAVE_LIBBABELTRACE_SUPPORT), + FEATURE_STATUS("babeltrace2-ctf-writer", HAVE_BABELTRACE2_CTF_WRITER_SUPPORT), FEATURE_STATUS("libbpf-strings", HAVE_LIBBPF_STRINGS_SUPPORT), FEATURE_STATUS("libcapstone", HAVE_LIBCAPSTONE_SUPPORT), FEATURE_STATUS("libdw-dwarf-unwind", HAVE_LIBDW_SUPPORT), diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c index 4c08ccb8c06b..1dd73ed6bdcb 100644 --- a/tools/perf/builtin-data.c +++ b/tools/perf/builtin-data.c @@ -40,10 +40,8 @@ static const struct option data_options[] = { OPT_INCR('v', "verbose", &verbose, "be more verbose"), OPT_STRING('i', "input", &input_name, "file", "input file name"), OPT_STRING(0, "to-json", &to_json, NULL, "Convert to JSON format"), -#ifdef HAVE_LIBBABELTRACE_SUPPORT OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"), OPT_BOOLEAN(0, "tod", &opts.tod, "Convert time to wall clock time"), -#endif OPT_BOOLEAN('f', "force", &opts.force, "don't complain, do it"), OPT_BOOLEAN(0, "all", &opts.all, "Convert all events"), OPT_STRING(0, "time", &opts.time_str, "str", @@ -65,29 +63,21 @@ static int cmd_data_convert(int argc, const char **argv) pr_err("You cannot specify both --to-ctf and --to-json.\n"); return -1; } -#ifdef HAVE_LIBBABELTRACE_SUPPORT if (!to_json && !to_ctf) { pr_err("You must specify one of --to-ctf or --to-json.\n"); return -1; } -#else - if (!to_json) { - pr_err("You must specify --to-json.\n"); - return -1; -} -#endif if (to_json) return bt_convert__perf2json(input_name, to_json, &opts); if (to_ctf) { -#if defined(HAVE_LIBBABELTRACE_SUPPORT) && defined(HAVE_LIBTRACEEVENT) +#if defined(HAVE_BABELTRACE2_CTF_WRITER_SUPPORT) && defined(HAVE_LIBTRACEEVENT) return bt_convert__perf2ctf(input_name, to_ctf, &opts); #else - pr_err("The libbabeltrace support is not compiled in. perf should be " - "compiled with environment variables LIBBABELTRACE=1 and " - "LIBBABELTRACE_DIR=/path/to/libbabeltrace/.\n" - "Check also if libbtraceevent devel files are available.\n"); + pr_err("The babeltrace2 ctf support is not compiled in. Ensure you have both\n" + "libbabeltrace2-dev[el] and libtraceevent-dev[el] installed or set\n" + "PKG_CONFIG_PATH to find a local installation of those libraries.\n"); return -1; #endif } diff --git a/tools/perf/tests/make b/tools/perf/tests/make index dbd7c86a2dcc..d2c2f526e1db 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -91,7 +91,7 @@ make_no_libbpf := NO_LIBBPF=1 make_libbpf_dynamic := LIBBPF_DYNAMIC=1 make_no_libbpf_DEBUG := NO_LIBBPF=1 DEBUG=1 make_no_libllvm := NO_LIBLLVM=1 -make_with_babeltrace:= LIBBABELTRACE=1 +make_no_babeltrace2 := NO_BABELTRACE2=1 make_with_coresight := CORESIGHT=1 make_no_sdt := NO_SDT=1 make_no_libpfm4 := NO_LIBPFM4=1 @@ -166,7 +166,7 @@ run += make_no_libbpf_DEBUG run += make_no_libllvm run += make_no_sdt run += make_no_syscall_tbl -run += make_with_babeltrace +run += make_no_babeltrace2 run += make_with_coresight run += make_with_clangllvm run += make_no_libpfm4 diff --git a/tools/perf/tests/shell/test_perf_data_converter_ctf.sh b/tools/perf/tests/shell/test_perf_data_converter_ctf.sh index 334eebc9945e..bc58a8dabf4c 100755 --- a/tools/perf/tests/shell/test_perf_data_converter_ctf.sh +++ b/tools/perf/tests/shell/test_perf_data_converter_ctf.sh @@ -24,11 +24,11 @@ trap_cleanup() } trap trap_cleanup exit term int -check_babeltrace_support() +check_babeltrace2_support() { - if ! perf check feature libbabeltrace + if ! perf check feature babeltrace2-ctf-writer then - echo "perf not linked with libbabeltrace, skipping test" + echo "perf not linked with babeltrace2-ctf-writer, skipping test" exit 2 fi } @@ -97,7 +97,7 @@ test_ctf_converter_pipe() fi } -check_babeltrace_support +check_babeltrace2_support test_ctf_converter_file test_ctf_converter_pipe diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 4bbc78b1f741..b22cdc24082a 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -230,7 +230,7 @@ perf-util-$(CONFIG_LIBUNWIND) += unwind-libunwind.o perf-util-$(CONFIG_LIBUNWIND) += libunwind-arch/ ifeq ($(CONFIG_LIBTRACEEVENT),y) - perf-util-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o + perf-util-$(CONFIG_BABELTRACE2_CTF_WRITER) += data-convert-bt.o endif perf-util-y += data-convert-json.o diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index cc51b8677c8e..5ff46bfcd0e1 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -11,14 +11,13 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "asm/bug.h" #include "data-convert.h" #include "session.h" @@ -121,13 +120,13 @@ static int value_set(struct bt_ctf_field_type *type, } if (sign) { - ret = bt_ctf_field_signed_integer_set_value(field, val); + ret = bt_ctf_field_integer_signed_set_value(field, val); if (ret) { pr_err("failed to set field value %s\n", name); goto err; } } else { - ret = bt_ctf_field_unsigned_integer_set_value(field, val); + ret = bt_ctf_field_integer_unsigned_set_value(field, val); if (ret) { pr_err("failed to set field value %s\n", name); goto err; @@ -374,10 +373,10 @@ static int add_tracepoint_field_value(struct ctf_writer *cw, data + offset + i * len, len); if (!(flags & TEP_FIELD_IS_SIGNED)) - ret = bt_ctf_field_unsigned_integer_set_value( + ret = bt_ctf_field_integer_unsigned_set_value( field, value_int); else - ret = bt_ctf_field_signed_integer_set_value( + ret = bt_ctf_field_integer_signed_set_value( field, adjust_signedness(value_int, len)); } @@ -471,7 +470,7 @@ add_bpf_output_values(struct bt_ctf_event_class *event_class, goto put_len_type; } - ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements); + ret = bt_ctf_field_integer_unsigned_set_value(len_field, nr_elements); if (ret) { pr_err("failed to set field value for raw_len\n"); goto put_len_field; @@ -500,7 +499,7 @@ add_bpf_output_values(struct bt_ctf_event_class *event_class, struct bt_ctf_field *elem_field = bt_ctf_field_sequence_get_field(seq_field, i); - ret = bt_ctf_field_unsigned_integer_set_value(elem_field, + ret = bt_ctf_field_integer_unsigned_set_value(elem_field, ((u32 *)(sample->raw_data))[i]); bt_ctf_field_put(elem_field); @@ -545,7 +544,7 @@ add_callchain_output_values(struct bt_ctf_event_class *event_class, goto put_len_type; } - ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements); + ret = bt_ctf_field_integer_unsigned_set_value(len_field, nr_elements); if (ret) { pr_err("failed to set field value for perf_callchain_size\n"); goto put_len_field; @@ -575,7 +574,7 @@ add_callchain_output_values(struct bt_ctf_event_class *event_class, struct bt_ctf_field *elem_field = bt_ctf_field_sequence_get_field(seq_field, i); - ret = bt_ctf_field_unsigned_integer_set_value(elem_field, + ret = bt_ctf_field_integer_unsigned_set_value(elem_field, ((u64 *)(callchain->ips))[i]); bt_ctf_field_put(elem_field); @@ -728,7 +727,7 @@ static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu) goto out; } - ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu); + ret = bt_ctf_field_integer_unsigned_set_value(cpu_field, (u32) cpu); if (ret) { pr_err("Failed to update CPU number\n"); goto out; diff --git a/tools/perf/util/data-convert.h b/tools/perf/util/data-convert.h index ee651fa680a1..a96240f15671 100644 --- a/tools/perf/util/data-convert.h +++ b/tools/perf/util/data-convert.h @@ -11,10 +11,10 @@ struct perf_data_convert_opts { const char *time_str; }; -#ifdef HAVE_LIBBABELTRACE_SUPPORT +#ifdef HAVE_BABELTRACE2_CTF_WRITER_SUPPORT int bt_convert__perf2ctf(const char *input_name, const char *to_ctf, struct perf_data_convert_opts *opts); -#endif /* HAVE_LIBBABELTRACE_SUPPORT */ +#endif /* HAVE_BABELTRACE2_CTF_WRITER_SUPPORT */ int bt_convert__perf2json(const char *input_name, const char *to_ctf, struct perf_data_convert_opts *opts); From be694c488a1e96e728517b26de9f15fed56b2e74 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 4 Jun 2026 09:36:26 -0700 Subject: [PATCH 220/343] perf pmu: Recognize 'default_core' as a core PMU and document matching The is_pmu_core function checks if a PMU name corresponds to a core CPU PMU. However, it currently fails to recognize "default_core" as a core PMU. When "default_core" is used, the PMU scanning fallback in pmus.c scans the "other_pmus" list. This scan is slow and always misses because "default_core" is a core PMU, leading to unnecessary overhead. Update is_pmu_core to recognize "default_core" directly. Additionally, document the different matching approaches (exact name for x86/s390, sysfs-based cpus file check for ARM/hybrid) to clarify how core PMUs are classified. Also, explicitly treat "default_core" as `all_pmus` in `setup_metric_events()` to preserve the original metric resolution behavior for this pseudo-PMU. Assisted-by: Gemini-CLI:Google Gemini 3.1 Pro Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 3 ++- tools/perf/util/pmu.c | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 5a489e97c413..c2ce3e53aaee 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -295,7 +295,8 @@ static int setup_metric_events(const char *pmu, struct hashmap *ids, const char *metric_id; struct evsel *ev; size_t ids_size, matched_events, i; - bool all_pmus = !strcmp(pmu, "all") || perf_pmus__num_core_pmus() == 1 || !is_pmu_core(pmu); + bool all_pmus = !strcmp(pmu, "all") || !strcmp(pmu, "default_core") || + perf_pmus__num_core_pmus() == 1 || !is_pmu_core(pmu); *out_metric_events = NULL; ids_size = hashmap__size(ids); diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 23337d2fa281..9994709ef12b 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -2029,9 +2029,26 @@ int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_call return 0; } +/** + * is_pmu_core() - Check if the given PMU name corresponds to a core CPU PMU. + * @name: The PMU name to check. + * + * Core PMUs can be identified by: + * 1. Exact name match: + * - "cpu": Typically used on x86 architectures. + * - "cpum_cf": Typically used on s390 architectures (CPU Measurement Counter Facility). + * - "default_core": A generic name used to refer to the default core PMU. + * 2. Sysfs file existence check (is_sysfs_pmu_core): + * - Typically used on ARM systems or Intel hybrid architectures (e.g., "cpu_atom", + * "cpu_core"). This approach checks if the sysfs directory for the PMU + * contains a "cpus" file. + */ bool is_pmu_core(const char *name) { - return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name); + return !strcmp(name, "cpu") || + !strcmp(name, "cpum_cf") || + !strcmp(name, "default_core") || + is_sysfs_pmu_core(name); } bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu) From 824b18f607d82503a956d3e00f9e9c0b24efcbca Mon Sep 17 00:00:00 2001 From: Suchit Karunakaran Date: Sun, 31 May 2026 01:29:40 +0530 Subject: [PATCH 221/343] perf lock contention: Enable end-timestamp accounting for cgroup aggregation update_lock_stat() handles lock contentions that start but never reach a contention_end event (e.g., locks still held when profiling stops), but previously treated LOCK_AGGR_CGROUP as a no-op due to missing cgroup context in userspace. Fix this by adding a cgroup_id field to struct tstamp_data, recording it at contention_begin using get_current_cgroup_id() when aggr_mode is LOCK_AGGR_CGROUP. Capturing it at contention_begin is semantically correct, the contention cost is incurred by the task that had to wait, not by whatever task happens to be running at contention_end. It is also preferable from a performance standpoint, as contention_end runs just before the task enters the critical section. Update contention_end to use pelem->cgroup_id instead of calling get_current_cgroup_id() dynamically, ensuring both complete and incomplete contention events attribute the wait time to the cgroup at wait-start time consistently. Reviewed-by: Namhyung Kim Signed-off-by: Suchit Karunakaran Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Peter Zijlstra Cc: Tycho Andersen (AMD) Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf_lock_contention.c | 4 ++-- tools/perf/util/bpf_skel/lock_contention.bpf.c | 4 +++- tools/perf/util/bpf_skel/lock_data.h | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c index eb8e29b8064b..b1cfa63a488f 100644 --- a/tools/perf/util/bpf_lock_contention.c +++ b/tools/perf/util/bpf_lock_contention.c @@ -470,8 +470,8 @@ static void update_lock_stat(int map_fd, int pid, u64 end_ts, stat_key.lock_addr_or_cgroup = ts_data->lock; break; case LOCK_AGGR_CGROUP: - /* TODO */ - return; + stat_key.lock_addr_or_cgroup = ts_data->cgroup_id; + break; default: return; } diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c index d4186ae9f85c..0d9c6f55050e 100644 --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c @@ -597,6 +597,8 @@ int contention_begin(u64 *ctx) pelem->timestamp = bpf_ktime_get_ns(); pelem->lock = (__u64)ctx[0]; pelem->flags = (__u32)ctx[1]; + if (aggr_mode == LOCK_AGGR_CGROUP) + pelem->cgroup_id = get_current_cgroup_id(); if (needs_callstack) { u32 i = 0; @@ -832,7 +834,7 @@ int contention_end(u64 *ctx) key.stack_id = pelem->stack_id; break; case LOCK_AGGR_CGROUP: - key.lock_addr_or_cgroup = get_current_cgroup_id(); + key.lock_addr_or_cgroup = pelem->cgroup_id; break; default: /* should not happen */ diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_skel/lock_data.h index 28c5e5aced7f..652e114e6b87 100644 --- a/tools/perf/util/bpf_skel/lock_data.h +++ b/tools/perf/util/bpf_skel/lock_data.h @@ -13,6 +13,7 @@ struct owner_tracing_data { struct tstamp_data { u64 timestamp; u64 lock; + u64 cgroup_id; u32 flags; s32 stack_id; }; From a5498ccf8079fc91c938f122ff9697b0c526b2fd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Jun 2026 12:55:06 -0300 Subject: [PATCH 222/343] perf tools: Guard test_bit from out-of-bounds sample CPU When PERF_SAMPLE_CPU is absent from a perf.data file, sample->cpu is initialized to (u32)-1 by evsel__parse_sample(). Five call sites pass this value directly to test_bit(sample->cpu, cpu_bitmap), reading massively out of bounds past the DECLARE_BITMAP(..., MAX_NR_CPUS) allocation of 4096 bits. Add a sample->cpu >= MAX_NR_CPUS guard before each test_bit() call, matching the existing safe pattern in builtin-kwork.c. This catches both the (u32)-1 sentinel and any corrupted CPU value exceeding the bitmap size. Fixes: 5d67be97f890 ("perf report/annotate/script: Add option to specify a CPU range") Cc: Anton Blanchard Reported-by: sashiko-bot Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 3 ++- tools/perf/builtin-diff.c | 3 ++- tools/perf/builtin-report.c | 3 ++- tools/perf/builtin-sched.c | 6 ++++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index b918f9eed5fd..8a0eb30eac24 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -295,7 +295,8 @@ static int process_sample_event(const struct perf_tool *tool, goto out_put; } - if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) + if (ann->cpu_list && (sample->cpu >= MAX_NR_CPUS || + !test_bit(sample->cpu, ann->cpu_bitmap))) goto out_put; if (!al.filtered && diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 9592f44b6545..9fa8e900637b 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -416,7 +416,8 @@ static int diff__process_sample_event(const struct perf_tool *tool, goto out; } - if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) { + if (cpu_list && (sample->cpu >= MAX_NR_CPUS || + !test_bit(sample->cpu, cpu_bitmap))) { ret = 0; goto out; } diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 6f044c3df893..dd1309c32094 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -298,7 +298,8 @@ static int process_sample_event(const struct perf_tool *tool, if (symbol_conf.hide_unresolved && al.sym == NULL) goto out_put; - if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) + if (rep->cpu_list && (sample->cpu >= MAX_NR_CPUS || + !test_bit(sample->cpu, rep->cpu_bitmap))) goto out_put; if (sort__mode == SORT_MODE__BRANCH) { diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 4de2baf03c50..e7bd3f331cb8 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2192,7 +2192,8 @@ static void timehist_print_sample(struct perf_sched *sched, char nstr[30]; u64 wait_time; - if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) + if (cpu_list && (sample->cpu >= MAX_NR_CPUS || + !test_bit(sample->cpu, cpu_bitmap))) return; timestamp__scnprintf_usec(t, tstr, sizeof(tstr)); @@ -2871,7 +2872,8 @@ static int timehist_sched_change_event(const struct perf_tool *tool, } if (!sched->idle_hist || thread__tid(thread) == 0) { - if (!cpu_list || test_bit(sample->cpu, cpu_bitmap)) + if (!cpu_list || (sample->cpu < MAX_NR_CPUS && + test_bit(sample->cpu, cpu_bitmap))) timehist_update_runtime_stats(tr, t, tprev); if (sched->idle_hist) { From 66ea9de60396a4dea5276bc87025884691876c36 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Jun 2026 12:55:29 -0300 Subject: [PATCH 223/343] perf sched: Fix thread reference leak in latency_switch_event In latency_switch_event(), after acquiring thread references for sched_out and sched_in via machine__findnew_thread(), the first add_sched_out_event() failure path does 'return -1', bypassing the out_put label that calls thread__put() on both references. The second and third add_sched_out_event() failures correctly use 'goto out_put'. Fix the first one to match. Fixes: b91fc39f4ad7 ("perf machine: Protect the machine->threads with a rwlock") Reported-by: sashiko-bot Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index e7bd3f331cb8..13b801496a01 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1180,7 +1180,7 @@ static int latency_switch_event(struct perf_sched *sched, } } if (add_sched_out_event(out_events, prev_state, timestamp)) - return -1; + goto out_put; in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid); if (!in_events) { From 8cbca8a480e15f6326ce94287570993f27a4b2d5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Jun 2026 12:56:02 -0300 Subject: [PATCH 224/343] perf sched: Fix NULL dereference in latency_runtime_event latency_runtime_event() passes the return value of machine__findnew_thread() directly to thread_atoms_search() at line 1216, before checking for NULL at line 1220. thread_atoms_search() calls pid_cmp() which dereferences the thread pointer via thread__tid(), causing a NULL pointer dereference if the allocation fails. All other callers of thread_atoms_search() in this file (latency_switch_event, latency_wakeup_event, latency_migrate_task_event) correctly check for NULL first. Move the atoms assignment after the NULL check to match the pattern used by the other callers. Fixes: b91fc39f4ad7 ("perf machine: Protect the machine->threads with a rwlock") Reported-by: sashiko-bot Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 13b801496a01..36da451447b5 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1213,13 +1213,15 @@ static int latency_runtime_event(struct perf_sched *sched, const u32 pid = perf_sample__intval(sample, "pid"); const u64 runtime = perf_sample__intval(sample, "runtime"); struct thread *thread = machine__findnew_thread(machine, -1, pid); - struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); + struct work_atoms *atoms; u64 timestamp = sample->time; int cpu = sample->cpu, err = -1; if (thread == NULL) return -1; + atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); + /* perf.data is untrusted input — CPU may be absent or corrupted */ if (cpu >= MAX_CPUS || cpu < 0) { pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n", From c8b04142078a9ccb9e402ab7c38de7123256f4a5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Jun 2026 13:05:10 -0300 Subject: [PATCH 225/343] perf sched: Fix comp_cpus heap overflow with cross-machine recordings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setup_map_cpus() allocates comp_cpus based on sysconf(_SC_NPROCESSORS_CONF), the host machine's CPU count. But map_switch_event() indexes comp_cpus using cpus_nr derived from bitmap_weight(comp_cpus_mask, MAX_CPUS), where comp_cpus_mask is declared as DECLARE_BITMAP(..., MAX_CPUS) with MAX_CPUS=4096. When analyzing a perf.data recording from a machine with more CPUs than the analysis host (e.g. 128-CPU server recording analyzed on an 8-CPU laptop), cpus_nr exceeds the allocation size, causing a heap buffer overflow. Also fix a type mismatch: comp_cpus is 'struct perf_cpu *' (2 bytes per element) but was allocated with sizeof(int) (4 bytes per element). Allocate comp_cpus with MAX_CPUS entries using the correct element size, matching the comp_cpus_mask bitmap bounds. Remove the sysconf(_SC_NPROCESSORS_CONF) initialization of max_cpu — its only consumer was the comp_cpus allocation, and max_cpu is dynamically updated from the recording's events during processing. Fix the non-compact path to use max_cpu.cpu + 1 as cpus_nr, converting from 0-based index to count — sysconf() returned a count which masked this off-by-one. Fixes: 99623c628f54 ("perf sched: Add compact display option") Reported-by: sashiko-bot Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 36da451447b5..4aa7833cae6e 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1670,7 +1670,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_sample *sampl new_cpu = true; } } else - cpus_nr = sched->max_cpu.cpu; + cpus_nr = sched->max_cpu.cpu + 1; timestamp0 = sched->cpu_last_switched[this_cpu.cpu]; sched->cpu_last_switched[this_cpu.cpu] = timestamp; @@ -3573,10 +3573,8 @@ static int perf_sched__lat(struct perf_sched *sched) static int setup_map_cpus(struct perf_sched *sched) { - sched->max_cpu.cpu = sysconf(_SC_NPROCESSORS_CONF); - if (sched->map.comp) { - sched->map.comp_cpus = calloc(sched->max_cpu.cpu, sizeof(int)); + sched->map.comp_cpus = calloc(MAX_CPUS, sizeof(*sched->map.comp_cpus)); if (!sched->map.comp_cpus) return -1; } From 7ccd2e6cecd5bb02a5a15f0dd7199d1e81380bda Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Jun 2026 18:11:41 -0300 Subject: [PATCH 226/343] perf tools: Guard remaining test_bit calls from OOB sample CPU auxtrace.c:filter_cpu() and builtin-script.c:filter_cpu() call test_bit(cpu, cpu_bitmap) where cpu_bitmap is declared with MAX_NR_CPUS bits. When the CPU value from a perf.data event is corrupt or absent (e.g. negative or >= MAX_NR_CPUS), test_bit reads out of bounds. Add bounds checks before test_bit(): >= 0 for the int16_t cpu.cpu in auxtrace (which also covers the -1 sentinel), and < MAX_NR_CPUS for both sites. Matches the pattern applied in the previous series for builtin-annotate.c, builtin-diff.c, builtin-report.c, and builtin-sched.c. Fixes: 644e0840ad46 ("perf auxtrace: Add CPU filter support") Fixes: 5d67be97f890 ("perf report/annotate/script: Add option to specify a CPU range") Reported-by: sashiko-bot Cc: Adrian Hunter Cc: Anton Blanchard Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 2 +- tools/perf/util/auxtrace.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index f4aa255fc329..9ac29bdc3cd5 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2646,7 +2646,7 @@ static int cleanup_scripting(void) static bool filter_cpu(struct perf_sample *sample) { - if (cpu_list && sample->cpu != (u32)-1) + if (cpu_list && sample->cpu != (u32)-1 && sample->cpu < MAX_NR_CPUS) return !test_bit(sample->cpu, cpu_bitmap); return false; } diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 5f4aa1701aef..4cd2caf54015 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -372,7 +372,8 @@ static bool filter_cpu(struct perf_session *session, struct perf_cpu cpu) { unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap; - return cpu_bitmap && cpu.cpu != -1 && !test_bit(cpu.cpu, cpu_bitmap); + return cpu_bitmap && cpu.cpu >= 0 && cpu.cpu < MAX_NR_CPUS && + !test_bit(cpu.cpu, cpu_bitmap); } static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, From 1e7921d7227de5da0dfc167943092c823ec7e49b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Jun 2026 18:14:23 -0300 Subject: [PATCH 227/343] perf tools: Add bounds check to cpu__get_node() cpu__get_node() accesses cpunode_map[cpu.cpu] without checking against max_cpu_num, the allocation size of cpunode_map. Callers such as builtin-kmem.c:evsel__process_alloc_event() pass sample->cpu from perf.data events, which may exceed the host's CPU count when analyzing cross-machine recordings. Add a bounds check against max_cpu_num before indexing, returning -1 for out-of-range values. This is a central fix that protects all callers. Fixes: 86895b480a2f ("perf stat: Add --per-node agregation support") Reported-by: sashiko-bot Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cpumap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index b1e5c29c6e3e..d3432622b2ad 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -576,6 +576,10 @@ int cpu__get_node(struct perf_cpu cpu) return -1; } + /* cpunode_map allocated for max_cpu_num entries; input may be untrusted */ + if (cpu.cpu < 0 || cpu.cpu >= max_cpu_num.cpu) + return -1; + return cpunode_map[cpu.cpu]; } From fa20c1f8f4e094abe0169d39fce8181bc26d6dab Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Jun 2026 18:18:05 -0300 Subject: [PATCH 228/343] perf sched: Fix thread reference leaks in timehist_get_thread() timehist_get_thread() acquires a thread reference via machine__findnew_thread() and an idle thread reference via get_idle_thread() (which calls thread__get()). Two error paths in the idle_hist block return NULL without releasing these references: - When get_idle_thread() fails, the thread reference leaks. - When thread__priv(idle) returns NULL, both idle and thread leak. Additionally, the idle thread reference acquired on the success path is never released, leaking a reference on every sample when --idle-hist is active. Add thread__put() calls on both error paths and release the idle reference after use on the success path. Fixes: 5d8f17fb5822 ("perf sched timehist: Add -I/--idle-hist option") Reported-by: sashiko-bot Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 4aa7833cae6e..7bd61028327b 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2546,12 +2546,16 @@ static struct thread *timehist_get_thread(struct perf_sched *sched, idle = get_idle_thread(sample->cpu); if (idle == NULL) { pr_err("Failed to get idle thread for cpu %d.\n", sample->cpu); + thread__put(thread); return NULL; } itr = thread__priv(idle); - if (itr == NULL) + if (itr == NULL) { + thread__put(idle); + thread__put(thread); return NULL; + } thread__put(itr->last_thread); itr->last_thread = thread__get(thread); @@ -2559,6 +2563,8 @@ static struct thread *timehist_get_thread(struct perf_sched *sched, /* copy task callchain when entering to idle */ if (perf_sample__intval(sample, "next_pid") == 0) save_idle_callchain(sched, itr, sample); + + thread__put(idle); } } From 06e7994427ab56e32699a5e45d048ff0826f3d53 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Jun 2026 18:23:35 -0300 Subject: [PATCH 229/343] perf sched: Cap max_cpu at MAX_CPUS in timehist sample processing perf_timehist__process_sample() updates sched->max_cpu from the sample CPU without bounds checking. Later code uses max_cpu + 1 as an iteration count over arrays allocated with MAX_CPUS entries (curr_thread, cpu_last_switched). A recording with CPU IDs >= MAX_CPUS causes out-of-bounds array accesses. Also cap the env->nr_cpus_online initialization of max_cpu in perf_sched__timehist(), which could exceed MAX_CPUS on very large systems. Add bounds checks before both max_cpu updates, matching the pattern already used in map_switch_event(). Fixes: 49394a2a24c7 ("perf sched timehist: Introduce timehist command") Reviewed-by: David Ahern Reported-by: sashiko-bot Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 7bd61028327b..87a1f4cf8760 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -3215,7 +3215,9 @@ static int perf_timehist__process_sample(const struct perf_tool *tool, .cpu = sample->cpu, }; - if (this_cpu.cpu > sched->max_cpu.cpu) + /* max_cpu indexes arrays allocated with MAX_CPUS entries */ + if (this_cpu.cpu >= 0 && this_cpu.cpu < MAX_CPUS && + this_cpu.cpu > sched->max_cpu.cpu) sched->max_cpu = this_cpu; if (evsel->handler != NULL) { @@ -3385,8 +3387,8 @@ static int perf_sched__timehist(struct perf_sched *sched) perf_session__set_tracepoints_handlers(session, migrate_handlers)) goto out; - /* pre-allocate struct for per-CPU idle stats */ - sched->max_cpu.cpu = env->nr_cpus_online; + /* pre-allocate struct for per-CPU idle stats; cap to array bounds */ + sched->max_cpu.cpu = min(env->nr_cpus_online, MAX_CPUS); if (sched->max_cpu.cpu == 0) sched->max_cpu.cpu = 4; if (init_idle_threads(sched->max_cpu.cpu)) From 5949d339f5ec98752d56dcd4e36f619a59d513a5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 4 Jun 2026 18:25:57 -0300 Subject: [PATCH 230/343] perf sched: Fix register_pid() overflow, strcpy, and BUG_ON register_pid() has several issues when processing untrusted perf.data: 1. Integer overflow: (pid + 1) * sizeof(struct task_desc *) can wrap to a small value on 32-bit systems when pid is large (e.g. 0x40000000), causing realloc to return a tiny buffer followed by out-of-bounds writes in the initialization loop. 2. Heap buffer overflow: strcpy(task->comm, comm) copies the untrusted comm string into a fixed 20-byte COMM_LEN buffer with no length check. 3. BUG_ON on allocation failure: perf.data is untrusted input, so allocation failures should be handled gracefully rather than killing the process. 4. Realloc of sched->tasks assigned directly back, leaking the old pointer on failure; nr_tasks incremented before the realloc, leaving corrupted state on failure. Cap pid at PID_MAX_LIMIT (4194304, matching the kernel's maximum on 64-bit), replace strcpy with strlcpy, guard against NULL comm, replace BUG_ON with NULL returns using safe realloc patterns, and add NULL checks in callers that dereference the result. Fixes: ec156764d424 ("perf sched: Import schedbench.c") Reported-by: sashiko-bot Cc: Ingo Molnar Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 40 ++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 87a1f4cf8760..21fb820b625b 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -55,6 +55,7 @@ #define COMM_LEN 20 #define SYM_LEN 129 #define MAX_PID 1024000 +#define PID_MAX_LIMIT 4194304 /* kernel limit on 64-bit */ #define MAX_PRIO 140 #define SEP_LEN 100 @@ -448,17 +449,28 @@ static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *ta static struct task_desc *register_pid(struct perf_sched *sched, unsigned long pid, const char *comm) { - struct task_desc *task; + struct task_desc *task, **tasks_p; static int pid_max; + /* perf.data is untrusted — cap pid to prevent overflow in size calculations */ + if (pid >= PID_MAX_LIMIT) { + pr_err("pid %lu exceeds limit %d, skipping\n", pid, PID_MAX_LIMIT); + return NULL; + } + if (sched->pid_to_task == NULL) { if (sysctl__read_int("kernel/pid_max", &pid_max) < 0) pid_max = MAX_PID; - BUG_ON((sched->pid_to_task = calloc(pid_max, sizeof(struct task_desc *))) == NULL); + sched->pid_to_task = calloc(pid_max, sizeof(struct task_desc *)); + if (sched->pid_to_task == NULL) + return NULL; } if (pid >= (unsigned long)pid_max) { - BUG_ON((sched->pid_to_task = realloc(sched->pid_to_task, (pid + 1) * - sizeof(struct task_desc *))) == NULL); + void *p = realloc(sched->pid_to_task, (pid + 1) * sizeof(struct task_desc *)); + + if (p == NULL) + return NULL; + sched->pid_to_task = p; while (pid >= (unsigned long)pid_max) sched->pid_to_task[pid_max++] = NULL; } @@ -469,9 +481,11 @@ static struct task_desc *register_pid(struct perf_sched *sched, return task; task = zalloc(sizeof(*task)); + if (task == NULL) + return NULL; task->pid = pid; - task->nr = sched->nr_tasks; - strcpy(task->comm, comm); + if (comm) + strlcpy(task->comm, comm, sizeof(task->comm)); /* * every task starts in sleeping state - this gets ignored * if there's no wakeup pointing to this sleep state: @@ -479,10 +493,12 @@ static struct task_desc *register_pid(struct perf_sched *sched, add_sched_event_sleep(sched, task, 0); sched->pid_to_task[pid] = task; - sched->nr_tasks++; - sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_desc *)); - BUG_ON(!sched->tasks); - sched->tasks[task->nr] = task; + tasks_p = realloc(sched->tasks, (sched->nr_tasks + 1) * sizeof(struct task_desc *)); + if (!tasks_p) + return NULL; + sched->tasks = tasks_p; + sched->tasks[sched->nr_tasks] = task; + task->nr = sched->nr_tasks++; if (verbose > 0) printf("registered task #%ld, PID %ld (%s)\n", sched->nr_tasks, pid, comm); @@ -841,6 +857,8 @@ replay_wakeup_event(struct perf_sched *sched, waker = register_pid(sched, sample->tid, ""); wakee = register_pid(sched, pid, comm); + if (waker == NULL || wakee == NULL) + return -1; add_sched_event_wakeup(sched, waker, sample->time, wakee); return 0; @@ -881,6 +899,8 @@ static int replay_switch_event(struct perf_sched *sched, prev = register_pid(sched, prev_pid, prev_comm); next = register_pid(sched, next_pid, next_comm); + if (prev == NULL || next == NULL) + return -1; sched->cpu_last_switched[cpu] = timestamp; From f32dc302a090f48893477ef297a888db109ec0bd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Jun 2026 10:56:33 -0300 Subject: [PATCH 231/343] perf mmap: Guard cpu__get_node() return in aio_bind() perf_mmap__aio_bind() passes the cpu__get_node() return value directly to an unsigned long variable (node_index). When cpu__get_node() returns -1 for an unknown CPU, the implicit int-to-unsigned-long conversion sign-extends it to ULONG_MAX. This causes bitmap_zalloc(ULONG_MAX + 1) which wraps to bitmap_zalloc(0), returning a zero-sized allocation. The subsequent __set_bit(ULONG_MAX, node_mask) then writes massively out of bounds. Check the return value in a signed temporary before assigning to node_index, and skip the NUMA binding when the node is unknown. Fixes: c44a8b44ca9f ("perf record: Bind the AIO user space buffers to nodes") Reported-by: sashiko-bot Cc: Alexey Budankov Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/mmap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index b69f926d314b..4404a99eee45 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c @@ -104,9 +104,15 @@ static int perf_mmap__aio_bind(struct mmap *map, int idx, struct perf_cpu cpu, i int err = 0; if (affinity != PERF_AFFINITY_SYS && cpu__max_node() > 1) { + int node; + data = map->aio.data[idx]; mmap_len = mmap__mmap_len(map); - node_index = cpu__get_node(cpu); + node = cpu__get_node(cpu); + /* -1 sign-extends to ULONG_MAX, wrapping bitmap_zalloc(0) and OOB __set_bit */ + if (node < 0) + return 0; + node_index = node; node_mask = bitmap_zalloc(node_index + 1); if (!node_mask) { pr_err("Failed to allocate node mask for mbind: error %m\n"); From 52e69b1c5b606b513d403dd4addc784c27a0c8e2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Jun 2026 10:59:11 -0300 Subject: [PATCH 232/343] perf stat: Bounds-check CPU index in topology aggregation callbacks Six perf_env__get_*_aggr_by_cpu() functions access env->cpu[cpu.cpu] after only checking cpu.cpu != -1. env->cpu[] is allocated with env->nr_cpus_avail entries, so a CPU index from an untrusted perf.data file that exceeds that count causes an out-of-bounds heap read. Replace the != -1 guard with >= 0 && < env->nr_cpus_avail in all six functions. The >= 0 check also catches -1 and any other negative values that could bypass the old check. Affected functions: - perf_env__get_socket_aggr_by_cpu() - perf_env__get_die_aggr_by_cpu() - perf_env__get_cache_aggr_by_cpu() - perf_env__get_cluster_aggr_by_cpu() - perf_env__get_core_aggr_by_cpu() - perf_env__get_cpu_aggr_by_cpu() Fixes: 68d702f7a120 ("perf stat report: Add support to initialize aggr_map from file") Reported-by: sashiko-bot Cc: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 99d7db372b48..9a045811c419 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1638,7 +1638,8 @@ static struct aggr_cpu_id perf_env__get_socket_aggr_by_cpu(struct perf_cpu cpu, struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); - if (cpu.cpu != -1) + /* env->cpu[] has env->nr_cpus_avail entries; reject untrusted indices */ + if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) id.socket = env->cpu[cpu.cpu].socket_id; return id; @@ -1649,7 +1650,7 @@ static struct aggr_cpu_id perf_env__get_die_aggr_by_cpu(struct perf_cpu cpu, voi struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); - if (cpu.cpu != -1) { + if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { /* * die_id is relative to socket, so start * with the socket ID and then add die to @@ -1705,7 +1706,7 @@ static struct aggr_cpu_id perf_env__get_cache_aggr_by_cpu(struct perf_cpu cpu, struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); - if (cpu.cpu != -1) { + if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { u32 cache_level = (perf_stat.aggr_level) ?: stat_config.aggr_level; id.socket = env->cpu[cpu.cpu].socket_id; @@ -1722,7 +1723,7 @@ static struct aggr_cpu_id perf_env__get_cluster_aggr_by_cpu(struct perf_cpu cpu, struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); - if (cpu.cpu != -1) { + if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { id.socket = env->cpu[cpu.cpu].socket_id; id.die = env->cpu[cpu.cpu].die_id; id.cluster = env->cpu[cpu.cpu].cluster_id; @@ -1736,7 +1737,7 @@ static struct aggr_cpu_id perf_env__get_core_aggr_by_cpu(struct perf_cpu cpu, vo struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); - if (cpu.cpu != -1) { + if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { /* * core_id is relative to socket, die and cluster, we need a * global id. So we set socket, die id, cluster id and core id. @@ -1755,7 +1756,7 @@ static struct aggr_cpu_id perf_env__get_cpu_aggr_by_cpu(struct perf_cpu cpu, voi struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); - if (cpu.cpu != -1) { + if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { /* * core_id is relative to socket and die, * we need a global id. So we set From 65117c3da50f749f4c22eb7a7effc53453dff57f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Jun 2026 11:05:13 -0300 Subject: [PATCH 233/343] perf c2c: Bounds-check CPU and node IDs before bitmap and array access c2c_he__set_cpu() passes sample->cpu directly to __set_bit(cpu, cpuset) after only checking for the (u32)-1 sentinel. The cpuset bitmap is allocated with c2c.cpus_cnt bits (from env->nr_cpus_avail), so a crafted perf.data with CPU IDs exceeding that count causes out-of-bounds heap writes. c2c_he__set_node() similarly passes the node ID from mem2node__node() to __set_bit(node, nodeset) after only checking for negative values. The nodeset bitmap is sized to c2c.nodes_cnt (from env->nr_numa_nodes), so a node ID exceeding that causes OOB writes. process_sample_event() indexes c2c.cpu2node[cpu] and c2c_he->node_stats[node] without bounds checking. Both arrays are sized to c2c.cpus_cnt and c2c.nodes_cnt respectively. Add bounds checks in all three paths: - c2c_he__set_cpu(): return if sample->cpu >= c2c.cpus_cnt - c2c_he__set_node(): return if node >= c2c.nodes_cnt - process_sample_event(): clamp cpu to 0 if >= cpus_cnt, guard node_stats access with bounds check Fixes: 1e181b92a2da ("perf c2c report: Add 'node' sort key") Reported-by: sashiko-bot Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 3dd45a550fdb..f060dfbe11c2 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -245,6 +245,10 @@ static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he, "WARNING: no sample cpu value")) return; + /* cpuset bitmap has c2c.cpus_cnt bits from env->nr_cpus_avail */ + if (sample->cpu >= (unsigned int)c2c.cpus_cnt) + return; + __set_bit(sample->cpu, c2c_he->cpuset); } @@ -262,6 +266,10 @@ static void c2c_he__set_node(struct c2c_hist_entry *c2c_he, if (WARN_ONCE(node < 0, "WARNING: failed to find node\n")) return; + /* nodeset bitmap has c2c.nodes_cnt bits from env->nr_numa_nodes */ + if (node >= c2c.nodes_cnt) + return; + __set_bit(node, c2c_he->nodeset); if (c2c_he->paddr != sample->phys_addr) { @@ -391,7 +399,12 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, * Doing node stats only for single callchain data. */ int cpu = sample->cpu == (unsigned int) -1 ? 0 : sample->cpu; - int node = c2c.cpu2node[cpu]; + int node; + + /* cpu2node[] has c2c.cpus_cnt entries; large u32 wraps signed negative */ + if (cpu < 0 || cpu >= c2c.cpus_cnt) + cpu = 0; + node = c2c.cpu2node[cpu]; c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2, machine->env); if (!c2c_hists) { @@ -410,7 +423,9 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused, c2c_he = container_of(he, struct c2c_hist_entry, he); c2c_add_stats(&c2c_he->stats, &stats); c2c_add_stats(&c2c_hists->stats, &stats); - c2c_add_stats(&c2c_he->node_stats[node], &stats); + /* node_stats[] has c2c.nodes_cnt entries */ + if (node >= 0 && node < c2c.nodes_cnt) + c2c_add_stats(&c2c_he->node_stats[node], &stats); compute_stats(c2c_he, &stats, sample->weight); From 5fb2e6ad8c5d6b3b380f94c7456595511f3731be Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Jun 2026 11:06:30 -0300 Subject: [PATCH 234/343] perf c2c: Bounds-check CPU IDs in setup_nodes() topology loop setup_nodes() iterates CPU maps from the perf.data topology header and uses cpu.cpu directly as an array index into cpu2node[] (allocated with c2c.cpus_cnt = env->nr_cpus_avail entries) and __set_bit(cpu.cpu, set) (bitmap also sized to c2c.cpus_cnt). A crafted perf.data with topology CPU IDs exceeding nr_cpus_avail causes out-of-bounds heap writes into both the cpu2node array and the per-node bitmap. Add a bounds check to skip CPU IDs that fall outside the valid range. Fixes: 1e181b92a2da ("perf c2c report: Add 'node' sort key") Reported-by: sashiko-bot Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index f060dfbe11c2..cfc1ebe8c0af 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2371,6 +2371,10 @@ static int setup_nodes(struct perf_session *session) nodes[node] = set; perf_cpu_map__for_each_cpu_skip_any(cpu, idx, map) { + /* topology CPU IDs from perf.data may exceed nr_cpus_avail */ + if (cpu.cpu < 0 || cpu.cpu >= c2c.cpus_cnt) + continue; + __set_bit(cpu.cpu, set); if (WARN_ONCE(cpu2node[cpu.cpu] != -1, "node/cpu topology bug")) From cda5a94ad9181cd60cbf04be11d524201bf489a2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Jun 2026 11:12:08 -0300 Subject: [PATCH 235/343] perf sched: Clean up idle_threads entry on init failure get_idle_thread() allocates a thread via thread__new() and stores it in idle_threads[cpu], then calls init_idle_thread() to set up the private data. If init_idle_thread() fails (e.g. OOM for the idle_thread_runtime struct), the function returns NULL but leaves the partially initialized thread in idle_threads[cpu]. On subsequent calls for the same CPU, get_idle_thread() finds a non-NULL idle_threads[cpu], skips allocation, and returns thread__get() on a thread that has no priv data. Callers then get a thread whose thread__priv() returns NULL, leading to unexpected behavior. Release the thread and reset the slot to NULL on init failure so the entry doesn't persist in a corrupted state. Fixes: 49394a2a24c7 ("perf sched timehist: Introduce timehist command") Reported-by: sashiko-bot Cc: David Ahern Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 21fb820b625b..e4378cc9ab3e 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2514,8 +2514,11 @@ static struct thread *get_idle_thread(int cpu) idle_threads[cpu] = thread__new(0, 0); if (idle_threads[cpu]) { - if (init_idle_thread(idle_threads[cpu]) < 0) + if (init_idle_thread(idle_threads[cpu]) < 0) { + /* clean up so next call doesn't find a half-initialized thread */ + thread__zput(idle_threads[cpu]); return NULL; + } } } From c9b3054c99cafd5f5f92158101760992a83e5a5e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Jun 2026 19:01:35 -0300 Subject: [PATCH 236/343] perf sched: Use is_idle_sample() for idle thread runtime cast guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit timehist_sched_change_event() uses thread__tid(thread) == 0 to decide whether to cast thread_runtime to idle_thread_runtime. However, a crafted perf.data can set common_pid=0 and common_tid=0 (the perf_sample fields) while prev_pid != 0 (the tracepoint field). is_idle_sample() returns false (it checks prev_pid for sched_switch), so timehist_get_thread() goes through machine__findnew_thread() and returns the machine's TID 0 thread — whose priv data is a regular thread_runtime, not the larger idle_thread_runtime allocated by init_idle_thread(). The subsequent cast to idle_thread_runtime reads past the thread_runtime allocation, accessing itr->last_thread, itr->cursor, and itr->callchain from adjacent heap memory. Writing to itr->last_thread corrupts the heap; calling thread__put() on the OOB value frees an arbitrary pointer. Replace the thread__tid() == 0 check with is_idle_sample(), which uses the tracepoint-specific prev_pid field and correctly identifies whether the sample originated from an idle thread with idle_thread_runtime priv. Fixes: 5d8f17fb5822 ("perf sched timehist: Add -I/--idle-hist option") Reported-by: sashiko-bot Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index e4378cc9ab3e..4600d70b4861 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2902,7 +2902,13 @@ static int timehist_sched_change_event(const struct perf_tool *tool, t = ptime->end; } - if (!sched->idle_hist || thread__tid(thread) == 0) { + /* + * Use is_idle_sample() not thread__tid() == 0: a crafted perf.data + * can set common_pid=0 with prev_pid!=0, giving us a machine thread + * whose priv is thread_runtime, not idle_thread_runtime — the cast + * below would read past the allocation. + */ + if (!sched->idle_hist || is_idle_sample(sample)) { if (!cpu_list || (sample->cpu < MAX_NR_CPUS && test_bit(sample->cpu, cpu_bitmap))) timehist_update_runtime_stats(tr, t, tprev); From 662d56d48e527ee21a0b03082ee318258a6f7919 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Jun 2026 11:15:58 -0300 Subject: [PATCH 237/343] perf sched: Fix thread reference leak in idle hist processing timehist_sched_change_event() sets itr->last_thread to NULL at the end of idle hist processing without calling thread__put() first. The thread reference was acquired via thread__get() in timehist_get_thread() (line 2581), so every idle context switch leaks a thread reference when --idle-hist is active. Use thread__zput() to properly release the reference before clearing the pointer. Fixes: 5d8f17fb5822 ("perf sched timehist: Add -I/--idle-hist option") Reported-by: sashiko-bot Cc: David Ahern Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 4600d70b4861..c0cd3cbb602a 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2940,7 +2940,7 @@ static int timehist_sched_change_event(const struct perf_tool *tool, if (itr->cursor.nr) callchain_append(&itr->callchain, &itr->cursor, t - tprev); - itr->last_thread = NULL; + thread__zput(itr->last_thread); } if (!sched->summary_only) From a99d6394cd48fed75b1d24733d5afe6837a61a3f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Jun 2026 11:17:03 -0300 Subject: [PATCH 238/343] perf sched: Use thread__put() in free_idle_threads() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit free_idle_threads() calls thread__delete() directly instead of thread__put(), bypassing the reference counting lifecycle. Under REFCNT_CHECKING builds, this leaks the pointer handle since thread__delete() frees the object without going through the refcount wrapper. The idle threads are created via thread__new() (refcount=1) in get_idle_thread(). Callers get additional references via thread__get() which they release with thread__put(). free_idle_threads() drops the base reference — thread__put() is the correct call, matching the thread__new() acquisition. Fixes: 49394a2a24c7 ("perf sched timehist: Introduce timehist command") Reported-by: sashiko-bot Cc: David Ahern Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index c0cd3cbb602a..732c65008a8a 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2481,7 +2481,7 @@ static void free_idle_threads(void) if (itr) thread__put(itr->last_thread); - thread__delete(idle); + thread__put(idle); } } From 75eafe4a3a93a0143a20c0cc286bfb9008ac1478 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Jun 2026 11:26:28 -0300 Subject: [PATCH 239/343] perf sched: Replace BUG_ON and add NULL checks in replay event helpers get_new_event() has three issues: 1. The zalloc() result is dereferenced without a NULL check, crashing on allocation failure. 2. BUG_ON(!task->atoms) kills the process when realloc() fails. Since perf.data is untrusted input, this should be a graceful error. 3. The realloc pattern assigns directly to task->atoms, losing the old pointer on failure. task->nr_events is also incremented before the realloc, leaving corrupted state on failure. Fix get_new_event() to: - Check the zalloc() result before dereferencing - Use a temporary for realloc() to avoid losing the old pointer - Increment nr_events only after successful realloc - Return NULL instead of calling BUG_ON on failure Also fix add_sched_event_wakeup() where zalloc() for wait_sem is passed to sem_init() without a NULL check. Update all callers (add_sched_event_run, add_sched_event_wakeup, add_sched_event_sleep) to handle NULL returns by returning early. The replay may produce incomplete output on OOM but will not crash. Fixes: ec156764d424 ("perf sched: Import schedbench.c") Reported-by: sashiko-bot Cc: Ingo Molnar Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 732c65008a8a..b7ccdc6a985d 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -365,14 +365,25 @@ get_new_event(struct task_desc *task, u64 timestamp) struct sched_atom *event = zalloc(sizeof(*event)); unsigned long idx = task->nr_events; size_t size; + struct sched_atom **atoms_p; + + if (event == NULL) { + pr_err("ERROR: sched: failed to allocate event\n"); + return NULL; + } event->timestamp = timestamp; event->nr = idx; + size = sizeof(struct sched_atom *) * (task->nr_events + 1); + atoms_p = realloc(task->atoms, size); + if (!atoms_p) { + pr_err("ERROR: sched: failed to grow atoms array\n"); + free(event); + return NULL; + } + task->atoms = atoms_p; task->nr_events++; - size = sizeof(struct sched_atom *) * task->nr_events; - task->atoms = realloc(task->atoms, size); - BUG_ON(!task->atoms); task->atoms[idx] = event; @@ -403,6 +414,8 @@ static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task } event = get_new_event(task, timestamp); + if (event == NULL) + return; event->type = SCHED_EVENT_RUN; event->duration = duration; @@ -416,6 +429,8 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *t struct sched_atom *event, *wakee_event; event = get_new_event(task, timestamp); + if (event == NULL) + return; event->type = SCHED_EVENT_WAKEUP; event->wakee = wakee; @@ -430,6 +445,10 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *t } wakee_event->wait_sem = zalloc(sizeof(*wakee_event->wait_sem)); + if (!wakee_event->wait_sem) { + pr_err("ERROR: sched: failed to allocate semaphore\n"); + return; + } sem_init(wakee_event->wait_sem, 0, 0); event->wait_sem = wakee_event->wait_sem; @@ -441,6 +460,9 @@ static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *ta { struct sched_atom *event = get_new_event(task, timestamp); + if (event == NULL) + return; + event->type = SCHED_EVENT_SLEEP; sched->nr_sleep_events++; From 25627346b10e6a564610ea2c49dc6dd54812226d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 11:03:29 -0300 Subject: [PATCH 240/343] perf mmap: Fix NULL deref in aio cleanup on alloc failure perf_mmap__aio_mmap() sets map->aio.nr_cblocks before allocating the data array. If calloc() for aiocb or cblocks fails before the data array is allocated, the return -1 path leads to perf_mmap__aio_munmap() which loops nr_cblocks times calling perf_mmap__aio_free(). Both versions of perf_mmap__aio_free() (NUMA and non-NUMA) dereference map->aio.data[idx] without checking if data is NULL, causing a NULL pointer dereference. Add NULL checks for map->aio.data at the top of both perf_mmap__aio_free() variants so the cleanup path is safe when allocation fails partway through perf_mmap__aio_mmap(). Fixes: d3d1af6f011a553a ("perf record: Enable asynchronous trace writing") Reported-by: sashiko-bot Cc: Alexey Budankov Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/mmap.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index 4404a99eee45..d64aec6c7c84 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c @@ -89,10 +89,10 @@ static int perf_mmap__aio_alloc(struct mmap *map, int idx) static void perf_mmap__aio_free(struct mmap *map, int idx) { - if (map->aio.data[idx]) { - munmap(map->aio.data[idx], mmap__mmap_len(map)); - map->aio.data[idx] = NULL; - } + if (!map->aio.data || !map->aio.data[idx]) + return; + munmap(map->aio.data[idx], mmap__mmap_len(map)); + map->aio.data[idx] = NULL; } static int perf_mmap__aio_bind(struct mmap *map, int idx, struct perf_cpu cpu, int affinity) @@ -141,6 +141,8 @@ static int perf_mmap__aio_alloc(struct mmap *map, int idx) static void perf_mmap__aio_free(struct mmap *map, int idx) { + if (!map->aio.data) + return; zfree(&(map->aio.data[idx])); } From afa4363a91a19dff65dceb7fbce7bba689bbc854 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 11:17:45 -0300 Subject: [PATCH 241/343] perf stat: Introduce perf_env__get_cpu_topology() to guard NULL env->cpu process_cpu_topology() in header.c frees env->cpu on old-format perf.data files that predate topology information, but leaves nr_cpus_avail set. The six perf_env__get_*_aggr_by_cpu() functions in builtin-stat.c pass the bounds check but dereference a NULL env->cpu pointer, crashing on old recordings. Introduce perf_env__get_cpu_topology() as a safe accessor that validates env->cpu, cpu.cpu >= 0, and cpu.cpu < nr_cpus_avail in one place, returning a struct cpu_topology_map pointer or NULL. Convert all six topology aggregation callbacks to use it. Fixes: 88031a0de7d68d13 ("perf stat: Switch to cpu version of cpu_map__get()") Reported-by: sashiko-bot Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 51 +++++++++++++++++++++------------------ tools/perf/util/env.h | 14 +++++++++++ 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 9a045811c419..a04466ea3b0a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1637,10 +1637,10 @@ static struct aggr_cpu_id perf_env__get_socket_aggr_by_cpu(struct perf_cpu cpu, { struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); + struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu); - /* env->cpu[] has env->nr_cpus_avail entries; reject untrusted indices */ - if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) - id.socket = env->cpu[cpu.cpu].socket_id; + if (topo) + id.socket = topo->socket_id; return id; } @@ -1649,15 +1649,16 @@ static struct aggr_cpu_id perf_env__get_die_aggr_by_cpu(struct perf_cpu cpu, voi { struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); + struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu); - if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { + if (topo) { /* * die_id is relative to socket, so start * with the socket ID and then add die to * make a unique ID. */ - id.socket = env->cpu[cpu.cpu].socket_id; - id.die = env->cpu[cpu.cpu].die_id; + id.socket = topo->socket_id; + id.die = topo->die_id; } return id; @@ -1705,12 +1706,13 @@ static struct aggr_cpu_id perf_env__get_cache_aggr_by_cpu(struct perf_cpu cpu, { struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); + struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu); - if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { + if (topo) { u32 cache_level = (perf_stat.aggr_level) ?: stat_config.aggr_level; - id.socket = env->cpu[cpu.cpu].socket_id; - id.die = env->cpu[cpu.cpu].die_id; + id.socket = topo->socket_id; + id.die = topo->die_id; perf_env__get_cache_id_for_cpu(cpu, env, cache_level, &id); } @@ -1722,11 +1724,12 @@ static struct aggr_cpu_id perf_env__get_cluster_aggr_by_cpu(struct perf_cpu cpu, { struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); + struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu); - if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { - id.socket = env->cpu[cpu.cpu].socket_id; - id.die = env->cpu[cpu.cpu].die_id; - id.cluster = env->cpu[cpu.cpu].cluster_id; + if (topo) { + id.socket = topo->socket_id; + id.die = topo->die_id; + id.cluster = topo->cluster_id; } return id; @@ -1736,16 +1739,17 @@ static struct aggr_cpu_id perf_env__get_core_aggr_by_cpu(struct perf_cpu cpu, vo { struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); + struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu); - if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { + if (topo) { /* * core_id is relative to socket, die and cluster, we need a * global id. So we set socket, die id, cluster id and core id. */ - id.socket = env->cpu[cpu.cpu].socket_id; - id.die = env->cpu[cpu.cpu].die_id; - id.cluster = env->cpu[cpu.cpu].cluster_id; - id.core = env->cpu[cpu.cpu].core_id; + id.socket = topo->socket_id; + id.die = topo->die_id; + id.cluster = topo->cluster_id; + id.core = topo->core_id; } return id; @@ -1755,18 +1759,19 @@ static struct aggr_cpu_id perf_env__get_cpu_aggr_by_cpu(struct perf_cpu cpu, voi { struct perf_env *env = data; struct aggr_cpu_id id = aggr_cpu_id__empty(); + struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu); - if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) { + if (topo) { /* * core_id is relative to socket and die, * we need a global id. So we set * socket, die id and core id */ - id.socket = env->cpu[cpu.cpu].socket_id; - id.die = env->cpu[cpu.cpu].die_id; - id.core = env->cpu[cpu.cpu].core_id; - id.cpu = cpu; + id.socket = topo->socket_id; + id.die = topo->die_id; + id.core = topo->core_id; } + id.cpu = cpu; return id; } diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index 7621d1f73b83..7acca39b42ff 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -187,6 +187,20 @@ const char *perf_env__pmu_mappings(struct perf_env *env); int perf_env__read_cpu_topology_map(struct perf_env *env); +/* + * Safe accessor for env->cpu[] topology array. env->cpu can be NULL when + * reading old-format perf.data that predates topology information — + * process_cpu_topology() in header.c frees it while nr_cpus_avail remains + * set, so callers must not index env->cpu[] without this check. + */ +static inline struct cpu_topology_map * +perf_env__get_cpu_topology(struct perf_env *env, struct perf_cpu cpu) +{ + if (env->cpu && cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) + return &env->cpu[cpu.cpu]; + return NULL; +} + void cpu_cache_level__free(struct cpu_cache_level *cache); uint16_t perf_env__e_machine_nocache(struct perf_env *env, uint32_t *e_flags); From 5e5e6196d737c5be03d20647428316b36621608d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 11:19:10 -0300 Subject: [PATCH 242/343] perf c2c: Fix use-after-free in he__get_c2c_hists() error path he__get_c2c_hists() assigns c2c_he->hists before calling c2c_hists__init(). If init fails, the error path calls free(hists) but leaves c2c_he->hists pointing to freed memory. On teardown, c2c_he_free() finds the non-NULL pointer and calls hists__delete_entries() on it, causing a use-after-free. Set c2c_he->hists to NULL before freeing so teardown skips the already-freed allocation. Fixes: b2252ae67b687d2b ("perf c2c report: Decode c2c_stats for hist entries") Reported-by: sashiko-bot Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index cfc1ebe8c0af..e205f58b2f3d 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -225,6 +225,7 @@ he__get_c2c_hists(struct hist_entry *he, ret = c2c_hists__init(hists, sort, nr_header_lines, env); if (ret) { + c2c_he->hists = NULL; free(hists); return NULL; } From e2496db45bfd8dfb6154ec415798fee330f1cc0a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 11:21:32 -0300 Subject: [PATCH 243/343] perf timechart: Fix cpu2y() OOB read on untrusted CPU index cpu2y() indexes topology_map[cpu] without bounds checking. The array is allocated with nr_cpus entries (from env->nr_cpus_online), but callers pass sample CPU values from perf.data which can exceed that size with cross-machine recordings. Track the topology_map allocation size and bounds-check the CPU argument in cpu2y() before indexing. Out-of-bounds CPUs fall back to the identity mapping (cpu2slot(cpu)), which is the same behavior as when no topology is available. Fixes: c507999790438cde ("perf timechart: Add support for topology") Reported-by: sashiko-bot Cc: Stanislav Fomichev Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/svghelper.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index e360e7736c7b..826bd2577344 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c @@ -47,13 +47,13 @@ static double cpu2slot(int cpu) } static int *topology_map; +static int topology_map_size; static double cpu2y(int cpu) { - if (topology_map) + if (topology_map && cpu >= 0 && cpu < topology_map_size) return cpu2slot(topology_map[cpu]) * SLOT_MULT; - else - return cpu2slot(cpu) * SLOT_MULT; + return cpu2slot(cpu) * SLOT_MULT; } static double time2pixels(u64 __time) @@ -736,7 +736,8 @@ static int str_to_bitmap(char *s, cpumask_t *b, int nr_cpus) return -1; perf_cpu_map__for_each_cpu(cpu, idx, map) { - if (cpu.cpu >= nr_cpus) { + /* perf_cpu_map__new("") returns cpu.cpu == -1 */ + if (cpu.cpu < 0 || cpu.cpu >= nr_cpus) { ret = -1; break; } @@ -794,6 +795,7 @@ int svg_build_topology_map(struct perf_env *env) fprintf(stderr, "topology: no memory\n"); goto exit; } + topology_map_size = nr_cpus; for (i = 0; i < nr_cpus; i++) topology_map[i] = -1; From 33fa2bf5608fc36bc25231592145f4738f14f11b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 11:25:40 -0300 Subject: [PATCH 244/343] perf tools: Fix int16_t truncation of max_cpu_num in set_max_cpu_num() set_max_cpu_num() assigns the sysfs "possible" CPU count to max_cpu_num.cpu which is int16_t (struct perf_cpu). On systems with >32767 possible CPUs the value silently truncates, potentially wrapping negative. This causes cpunode_map to be underallocated and subsequent cpu__get_node() calls to read out of bounds. The matching check for max_present_cpu_num was added by commit c760174401f6 ("perf cpumap: Reduce cpu size from int to int16_t") but max_cpu_num was missed. Add the same INT16_MAX guard. Fixes: c760174401f605cf ("perf cpumap: Reduce cpu size from int to int16_t") Reported-by: sashiko-bot Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cpumap.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index d3432622b2ad..21fa781b03cc 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -494,6 +494,16 @@ static void set_max_cpu_num(void) if (ret) goto out; + /* + * struct perf_cpu.cpu is int16_t (libperf ABI) — clamp to avoid + * truncation to negative. See tools/lib/perf/TODO for the ABI + * widening plan. + */ + if (max > INT16_MAX) { + pr_warning("WARNING: max possible cpus %d exceeds int16_t, clamping to %d\n", + max, INT16_MAX); + max = INT16_MAX; + } max_cpu_num.cpu = max; /* get the highest present cpu number for a sparse allocation */ @@ -506,11 +516,12 @@ static void set_max_cpu_num(void) ret = get_max_num(path, &max); if (!ret && max > INT16_MAX) { - pr_err("Read out of bounds max cpus of %d\n", max); - ret = -1; + pr_warning("WARNING: max present cpus %d exceeds int16_t, clamping to %d\n", + max, INT16_MAX); + max = INT16_MAX; } if (!ret) - max_present_cpu_num.cpu = (int16_t)max; + max_present_cpu_num.cpu = max; out: if (ret) pr_err("Failed to read max cpus, using default of %d\n", max_cpu_num.cpu); @@ -647,7 +658,9 @@ int cpu__setup_cpunode_map(void) while ((dent2 = readdir(dir2)) != NULL) { if (dent2->d_type != DT_LNK || sscanf(dent2->d_name, "cpu%u", &cpu) < 1) continue; - cpunode_map[cpu] = mem; + /* cpunode_map allocated for max_cpu_num entries */ + if (cpu < (unsigned int)max_cpu_num.cpu) + cpunode_map[cpu] = mem; } closedir(dir2); } From c3e51ed45ffa7547495a851e33ce332f81ef3665 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 11:33:41 -0300 Subject: [PATCH 245/343] perf sched: Free callchain nodes in idle thread cleanup free_idle_threads() relies on the thread priv destructor (free()) to clean up idle_thread_runtime structs. But free() doesn't walk the callchain_cursor linked list or the callchain_root tree allocated by callchain_cursor__copy() and callchain_append() during --idle-hist processing. Every idle thread with callchain data leaks these nodes. Introduce callchain_cursor_cleanup() to free the cursor's linked list of callchain_cursor_node entries, and call it together with free_callchain() in free_idle_threads() before thread__put(). Fixes: 225b24f569980ac9 ("perf sched timehist: Save callchain when entering idle") Reported-by: sashiko-bot Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 5 ++++- tools/perf/util/callchain.c | 15 +++++++++++++++ tools/perf/util/callchain.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index b7ccdc6a985d..1ff01f03d2ad 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2500,8 +2500,11 @@ static void free_idle_threads(void) struct idle_thread_runtime *itr; itr = thread__priv(idle); - if (itr) + if (itr) { thread__put(itr->last_thread); + free_callchain(&itr->callchain); + callchain_cursor_cleanup(&itr->cursor); + } thread__put(idle); } diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 8981ae879ebb..31c675cbab63 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -1578,6 +1578,21 @@ void free_callchain(struct callchain_root *root) free_callchain_node(&root->node); } +void callchain_cursor_cleanup(struct callchain_cursor *cursor) +{ + struct callchain_cursor_node *node, *next; + + callchain_cursor_reset(cursor); + + for (node = cursor->first; node; node = next) { + next = node->next; + free(node); + } + cursor->first = NULL; + cursor->last = &cursor->first; + cursor->curr = NULL; +} + static u64 decay_callchain_node(struct callchain_node *node) { struct callchain_node *child; diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 0eb5d7a1a41d..8b1e405d1cdf 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -286,6 +286,7 @@ int callchain_list_counts__printf_value(struct callchain_list *clist, FILE *fp, char *bf, int bfsize); void free_callchain(struct callchain_root *root); +void callchain_cursor_cleanup(struct callchain_cursor *cursor); void decay_callchain(struct callchain_root *root); int callchain_node__make_parent_list(struct callchain_node *node); From f54ce06049bf716f6b1e3a78e72360d583ea2acb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 14:42:09 -0300 Subject: [PATCH 246/343] libperf: Document struct perf_cpu int16_t ABI limitation struct perf_cpu.cpu is int16_t, limiting perf to 32767 CPUs. This is part of the libperf ABI (returned by value from perf_cpu_map__cpu() and friends), so widening it requires an ABI bump. Add a comment on the struct definition noting this, and create a TODO file to collect future ABI changes so they can be batched into a single version bump. Cc: Ian Rogers Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/TODO | 22 ++++++++++++++++++++++ tools/lib/perf/include/perf/cpumap.h | 8 +++++++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tools/lib/perf/TODO diff --git a/tools/lib/perf/TODO b/tools/lib/perf/TODO new file mode 100644 index 000000000000..486dd95dc572 --- /dev/null +++ b/tools/lib/perf/TODO @@ -0,0 +1,22 @@ +Future ABI changes +================== + +This file collects items that require a libperf ABI bump. Each entry +should describe the current limitation, the desired end state, and the +scope of the change so that a future ABI revision can batch them +together. + +1. Widen struct perf_cpu.cpu from int16_t to int + - Current limit: 32767 CPUs. No architecture exceeds this today + (x86_64 max is 8192, arm64 is 4096), but NR_CPUS limits keep + growing. perf clamps to INT16_MAX in set_max_cpu_num() as a + safety net. + - Scope: struct perf_cpu is embedded everywhere — perf_cpu_map__cpu(), + perf_cpu_map__min(), perf_cpu_map__max(), perf_cpu_map__has(), the + for_each_cpu macros, and all internal callers. The perf_cpu_map + internal array (RC_CHK_ACCESS(map)->map[]) stores struct perf_cpu + directly. Widening changes the struct layout and every function + that returns or accepts struct perf_cpu by value. + - Migration: bump LIBPERF version in libperf.map, audit all + sizeof(struct perf_cpu) assumptions, update perf.data + serialization if needed. diff --git a/tools/lib/perf/include/perf/cpumap.h b/tools/lib/perf/include/perf/cpumap.h index a1dd25db65b6..e1a0b0d27210 100644 --- a/tools/lib/perf/include/perf/cpumap.h +++ b/tools/lib/perf/include/perf/cpumap.h @@ -6,7 +6,13 @@ #include #include -/** A wrapper around a CPU to avoid confusion with the perf_cpu_map's map's indices. */ +/** + * struct perf_cpu - wrapper around a CPU number. + * @cpu: CPU number, -1 for the "any CPU"/dummy value. + * + * int16_t limits this to 32767 CPUs. Widening to int requires a libperf + * ABI bump — see tools/lib/perf/TODO for the full scope. + */ struct perf_cpu { int16_t cpu; }; From 0a012113bb3a44482c163f16f4db03ccaa37a339 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 20:37:52 -0300 Subject: [PATCH 247/343] perf tools: Fix get_max_num() size_t underflow on empty sysfs file get_max_num() reads a sysfs file (cpu/possible, cpu/present, or node/possible) and scans backward from the end to find the last number. If the file is empty, filename__read_str() returns num == 0. The loop `while (--num)` decrements the size_t from 0 to SIZE_MAX, reading backward across the heap until a comma or hyphen is found or unmapped memory is hit. Add an early return for empty files before the backward scan. Fixes: 7780c25bae59fd04 ("perf tools: Allow ability to map cpus to nodes easily") Reported-by: sashiko-bot Reviewed-by: Ian Rogers Cc: Don Zickus Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cpumap.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 21fa781b03cc..1fab00ec4a59 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -448,6 +448,12 @@ static int get_max_num(char *path, int *max) buf[num] = '\0'; + /* empty file — nothing to parse */ + if (num == 0) { + err = -1; + goto out; + } + /* start on the right, to find highest node num */ while (--num) { if ((buf[num] == ',') || (buf[num] == '-')) { From 7953a3a9b8e02e98c6e6958f291d0ae22393e46a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 20:43:52 -0300 Subject: [PATCH 248/343] perf tools: Use scnprintf() in cpu_map__snprint() to prevent overflow cpu_map__snprint() accumulates snprintf() return values in ret. snprintf() returns the number of characters that *would have been written* on truncation, not the actual count. When a fragmented CPU list exceeds the buffer, ret grows past size, causing `size - ret` to underflow (both are size_t), and subsequent snprintf() calls write past the end of the caller's stack buffer. Switch to scnprintf() which returns the actual number of characters written, making ret accumulation safe by construction. Fixes: a24020e6b7cf6eb8 ("perf tools: Change cpu_map__fprintf output") Reported-by: sashiko-bot Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cpumap.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 1fab00ec4a59..23ebe9b97f8e 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -692,21 +692,21 @@ size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size) if (start == -1) { start = i; if (last) { - ret += snprintf(buf + ret, size - ret, - "%s%d", COMMA, - perf_cpu_map__cpu(map, i).cpu); + ret += scnprintf(buf + ret, size - ret, + "%s%d", COMMA, + perf_cpu_map__cpu(map, i).cpu); } } else if (((i - start) != (cpu.cpu - perf_cpu_map__cpu(map, start).cpu)) || last) { int end = i - 1; if (start == end) { - ret += snprintf(buf + ret, size - ret, - "%s%d", COMMA, - perf_cpu_map__cpu(map, start).cpu); + ret += scnprintf(buf + ret, size - ret, + "%s%d", COMMA, + perf_cpu_map__cpu(map, start).cpu); } else { - ret += snprintf(buf + ret, size - ret, - "%s%d-%d", COMMA, - perf_cpu_map__cpu(map, start).cpu, perf_cpu_map__cpu(map, end).cpu); + ret += scnprintf(buf + ret, size - ret, + "%s%d-%d", COMMA, + perf_cpu_map__cpu(map, start).cpu, perf_cpu_map__cpu(map, end).cpu); } first = false; start = i; From 5484b43a0ec8231c36fba6ead654cb72dbba8b8f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 20:57:49 -0300 Subject: [PATCH 249/343] perf tools: Use perf_env__get_cpu_topology() in machine__resolve() machine__resolve() accesses env->cpu[al->cpu].socket_id after checking al->cpu >= 0 and env->cpu != NULL, but without validating al->cpu against env->nr_cpus_avail. Since al->cpu comes from the untrusted perf.data sample, a crafted file with a large CPU index causes an out-of-bounds heap read. Use perf_env__get_cpu_topology() which validates both NULL and bounds. Also bounds-check al->cpu before the cast to struct perf_cpu (int16_t): without this, values like 65536 silently truncate to 0, bypassing the accessor's internal check and returning CPU 0's topology. Fixes: 0c4c4debb0adda4c ("perf tools: Add processor socket info to hist_entry and addr_location") Reported-by: sashiko-bot Reviewed-by: Ian Rogers Cc: Kan Liang Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 66f4843bb235..ea75816d126a 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -14,6 +14,7 @@ #include #include "cpumap.h" #include "dso.h" +#include "env.h" #include "event.h" #include "debug.h" #include "hist.h" @@ -836,8 +837,18 @@ int machine__resolve(struct machine *machine, struct addr_location *al, if (al->cpu >= 0) { struct perf_env *env = machine->env; - if (env && env->cpu) - al->socket = env->cpu[al->cpu].socket_id; + /* + * Bounds-check al->cpu (s32) before casting to struct perf_cpu + * (int16_t): without this, e.g. 65536 truncates to 0 and silently + * returns CPU 0's topology. Can go once perf_cpu.cpu is widened. + */ + if (env && al->cpu < env->nr_cpus_avail) { + struct cpu_topology_map *topo; + + topo = perf_env__get_cpu_topology(env, (struct perf_cpu){ al->cpu }); + if (topo) + al->socket = topo->socket_id; + } } /* Account for possible out-of-order switch events. */ From a9e900bc5c5914aca750afafa459363e575d3046 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 21:31:51 -0300 Subject: [PATCH 250/343] perf tools: NULL bitmap pointers after bitmap_free() Two call sites free bitmaps without NULLing the pointer, risking double-free if the structure is reused or cleanup is called twice: - mmap__munmap(): map->affinity_mask.bits - record__mmap_cpu_mask_free(): mask->bits Set each pointer to NULL after bitmap_free(). Fixes: 8384a2600c7ddfc8 ("perf record: Adapt affinity to machines with #CPUs > 1K") Fixes: f466e5ed6c356d1d ("perf record: Extend --threads command line option") Reported-by: sashiko-bot Reviewed-by: Ian Rogers Cc: Alexey Budankov Cc: Alexey Bayduraev Cc: Arnaldo Carvalho de Melo Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 1 + tools/perf/util/mmap.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a33c78f030d9..e91539055675 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -3084,6 +3084,7 @@ static int record__mmap_cpu_mask_alloc(struct mmap_cpu_mask *mask, int nr_bits) static void record__mmap_cpu_mask_free(struct mmap_cpu_mask *mask) { bitmap_free(mask->bits); + mask->bits = NULL; mask->nbits = 0; } diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index d64aec6c7c84..358e70c4f3ed 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c @@ -238,6 +238,8 @@ static void perf_mmap__aio_munmap(struct mmap *map __maybe_unused) void mmap__munmap(struct mmap *map) { bitmap_free(map->affinity_mask.bits); + map->affinity_mask.bits = NULL; + map->affinity_mask.nbits = 0; zstd_fini(&map->zstd_data); From 4477dc01fcfc7f404772a67e0c1e056541ceb61d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 21:48:13 -0300 Subject: [PATCH 251/343] perf sched: Bounds-check prio before test_bit() in timehist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit timehist_skip_sample() reads prio from untrusted tracepoint data via perf_sample__intval(sample, "prev_prio") without bounds validation. A crafted perf.data with prev_prio >= MAX_PRIO (140) causes test_bit() to read past the end of the prio_bitmap, which is only MAX_PRIO bits. Add a prio >= 0 guard before the test_bit() call and skip out-of-range values (>= MAX_PRIO) that can never match the user's filter set. The original prio != -1 already let all negatives other than -1 through (after an undefined-behavior bitmap read); the new prio >= 0 guard preserves that pass-through behavior — negative means "no priority info", so the event is shown unfiltered — while fixing the OOB. Values >= MAX_PRIO are skipped because they cannot be represented in the filter bitmap. Fixes: 9b3a48bbe20d9692 ("perf sched timehist: Add --prio option") Reported-by: sashiko-bot Reviewed-by: Ian Rogers Cc: Yang Jihong Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 1ff01f03d2ad..caf05863a54e 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2645,7 +2645,9 @@ static bool timehist_skip_sample(struct perf_sched *sched, else if (evsel__name_is(sample->evsel, "sched:sched_switch")) prio = perf_sample__intval(sample, "prev_prio"); - if (prio != -1 && !test_bit(prio, sched->prio_bitmap)) { + /* negative prio means no info; out-of-range prio can't match the filter */ + if (prio >= 0 && + (prio >= MAX_PRIO || !test_bit(prio, sched->prio_bitmap))) { rc = true; sched->skipped_samples++; } From d9b99dc8148e0c1f5da3942131b47e0d21187a32 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 21:49:16 -0300 Subject: [PATCH 252/343] perf sched: Fix idle-hist callchain display using wrong rb_first variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit timehist_print_idlehist_callchain() calls rb_first_cached() on sorted_root, but the sort function (callchain_param.sort) populates it via rb_insert_color() on the plain rb_root member — not the cached variant. This means rb_leftmost is never set, so rb_first_cached() always returns NULL and the entire callchain summary is silently dropped from --idle-hist output. The original code in ba957ebb54893aca ("perf sched timehist: Show callchains for idle stat") was correct — it used struct rb_root and rb_first(). The bug was introduced when sorted_root was converted to rb_root_cached without converting the sort insertion path to use rb_insert_color_cached(). Use rb_first(&root->rb_root) to match how the tree was populated. Fixes: cb4c13a5137766c3 ("perf sched: Use cached rbtrees") Reported-by: sashiko-bot Cc: Davidlohr Bueso Cc: Namhyung Kim Acked-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index caf05863a54e..5f16caebd964 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -3130,7 +3130,8 @@ static size_t timehist_print_idlehist_callchain(struct rb_root_cached *root) size_t ret = 0; FILE *fp = stdout; struct callchain_node *chain; - struct rb_node *rb_node = rb_first_cached(root); + /* sort() uses rb_insert_color() on rb_root, not rb_root_cached */ + struct rb_node *rb_node = rb_first(&root->rb_root); printf(" %16s %8s %s\n", "Idle time (msec)", "Count", "Callchains"); printf(" %.16s %.8s %.50s\n", graph_dotted_line, graph_dotted_line, From b145137fec13dc8fc7fcb14193ce395a1164e3a1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 6 Jun 2026 21:51:42 -0300 Subject: [PATCH 253/343] perf tools: Add O_CLOEXEC to open() calls in DSO and ELF code open() calls in dso.c and symbol-elf.c omit O_CLOEXEC, which leaks file descriptors to child processes spawned during symbol resolution (e.g., addr2line, objdump). This can exhaust the fd limit during long profiling sessions or when processing many DSOs. Add O_CLOEXEC to all open() calls in both files (12 call sites). Fixes: cdd059d731eeb466 ("perf tools: Move dso_* related functions into dso object") Fixes: e5a1845fc0aeca85 ("perf symbols: Split out util/symbol-elf.c") Reported-by: sashiko-bot Reviewed-by: Ian Rogers Cc: Jiri Olsa Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 4 ++-- tools/perf/util/symbol-elf.c | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 7dced896c64e..fb2e78fe2aa8 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -344,7 +344,7 @@ int filename__decompress(const char *name, char *pathname, * descriptor to the uncompressed file. */ if (!compressions[comp].is_compressed(name)) - return open(name, O_RDONLY); + return open(name, O_RDONLY | O_CLOEXEC); fd = mkstemp(tmpbuf); if (fd < 0) { @@ -1911,7 +1911,7 @@ static const u8 *__dso__read_symbol(struct dso *dso, const char *symfs_filename, int saved_errno; nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); - fd = open(symfs_filename, O_RDONLY); + fd = open(symfs_filename, O_RDONLY | O_CLOEXEC); saved_errno = errno; nsinfo__mountns_exit(&nsc); if (fd < 0) { diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 186e6d92ac3d..c2bdfd0003df 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -217,7 +217,7 @@ bool filename__has_section(const char *filename, const char *sec) GElf_Shdr shdr; bool found = false; - fd = open(filename, O_RDONLY); + fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) return false; @@ -872,7 +872,7 @@ static int read_build_id(const char *filename, struct build_id *bid) if (size < BUILD_ID_SIZE) goto out; - fd = open(filename, O_RDONLY); + fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) goto out; @@ -935,7 +935,7 @@ int sysfs__read_build_id(const char *filename, struct build_id *bid) size_t size = sizeof(bid->data); int fd, err = -1; - fd = open(filename, O_RDONLY); + fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) goto out; @@ -995,7 +995,7 @@ int filename__read_debuglink(const char *filename, char *debuglink, if (err >= 0) goto out; - fd = open(filename, O_RDONLY); + fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) goto out; @@ -1153,7 +1153,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, type = dso__symtab_type(dso); } else { - fd = open(name, O_RDONLY); + fd = open(name, O_RDONLY | O_CLOEXEC); if (fd < 0) { *dso__load_errno(dso) = errno; return -1; @@ -1952,7 +1952,7 @@ static int kcore__open(struct kcore *kcore, const char *filename) { GElf_Ehdr *ehdr; - kcore->fd = open(filename, O_RDONLY); + kcore->fd = open(filename, O_RDONLY | O_CLOEXEC); if (kcore->fd == -1) return -1; @@ -1985,7 +1985,7 @@ static int kcore__init(struct kcore *kcore, char *filename, int elfclass, if (temp) kcore->fd = mkstemp(filename); else - kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400); + kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0400); if (kcore->fd == -1) return -1; @@ -2461,11 +2461,11 @@ static int kcore_copy__compare_files(const char *from_filename, { int from, to, err = -1; - from = open(from_filename, O_RDONLY); + from = open(from_filename, O_RDONLY | O_CLOEXEC); if (from < 0) return -1; - to = open(to_filename, O_RDONLY); + to = open(to_filename, O_RDONLY | O_CLOEXEC); if (to < 0) goto out_close_from; @@ -2883,7 +2883,7 @@ int get_sdt_note_list(struct list_head *head, const char *target) Elf *elf; int fd, ret; - fd = open(target, O_RDONLY); + fd = open(target, O_RDONLY | O_CLOEXEC); if (fd < 0) return -EBADF; From cab3a9331ed0b3f884dd61c8a25b3cf123705982 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 14:23:15 -0300 Subject: [PATCH 254/343] perf bpf: Use scnprintf() in snprintf_hex() and synthesize_bpf_prog_name() Both functions accumulate formatted output via ret += snprintf(buf + ret, size - ret, ...). If the buffer is too small and snprintf() returns more than the remaining space, ret exceeds size and the next 'size - ret' underflows, causing snprintf() to write past the buffer end. Switch to scnprintf() which returns the actual number of bytes written, making the accumulation safe. Fixes: 7b612e291a5affb1 ("perf tools: Synthesize PERF_RECORD_* for loaded BPF programs") Reported-by: sashiko-bot Reviewed-by: Ian Rogers Cc: Song Liu Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-event.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index a27945c279ef..2c09842469f1 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -36,7 +36,7 @@ static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len) size_t i; for (i = 0; i < len; i++) - ret += snprintf(buf + ret, size - ret, "%02x", data[i]); + ret += scnprintf(buf + ret, size - ret, "%02x", data[i]); return ret; } @@ -140,7 +140,7 @@ static int synthesize_bpf_prog_name(char *buf, int size, const struct btf_type *t; int name_len; - name_len = snprintf(buf, size, "bpf_prog_"); + name_len = scnprintf(buf, size, "bpf_prog_"); name_len += snprintf_hex(buf + name_len, size - name_len, prog_tags[sub_id], BPF_TAG_SIZE); if (btf) { @@ -153,9 +153,10 @@ static int synthesize_bpf_prog_name(char *buf, int size, short_name = info->name; } else short_name = "F"; - if (short_name) - name_len += snprintf(buf + name_len, size - name_len, - "_%s", short_name); + if (short_name) { + name_len += scnprintf(buf + name_len, size - name_len, + "_%s", short_name); + } return name_len; } From 227a8748742f0263f1fe3131449b44563b77a209 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 14:35:28 -0300 Subject: [PATCH 255/343] perf hists: Fix snprintf() in hists__scnprintf_title() UID filter path hists__scnprintf_title() accumulates formatted output into a buffer using scnprintf() for all filter clauses except the UID filter, which uses snprintf(). If the buffer fills up and snprintf() returns more than the remaining space, printed exceeds size and the next 'size - printed' underflows, causing later scnprintf() calls to write past the buffer. Switch the UID filter clause to scnprintf() to match the rest of the function. Fixes: 25c312dbf88ca402 ("perf hists: Move hists__scnprintf_title() away from the TUI code") Reported-by: sashiko-bot Reviewed-by: Ian Rogers Cc: Arnaldo Carvalho de Melo Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 811d68fa6770..df978c996b6c 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -2963,9 +2963,10 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); - if (hists->uid_filter_str) - printed += snprintf(bf + printed, size - printed, - ", UID: %s", hists->uid_filter_str); + if (hists->uid_filter_str) { + printed += scnprintf(bf + printed, size - printed, + ", UID: %s", hists->uid_filter_str); + } if (thread) { if (hists__has(hists, thread)) { printed += scnprintf(bf + printed, size - printed, From e33711d5e757011bb6d3506af4d6c97dad412b8f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 14:36:57 -0300 Subject: [PATCH 256/343] perf tools: Use scnprintf() in build_id__snprintf() and hwmon read_events() build_id__snprintf() and hwmon_pmu__read_events() accumulate formatted output via snprintf(), which returns the would-have-been-written count on truncation. In build_id__snprintf(), this inflates the return value beyond the buffer size. In hwmon_pmu__read_events(), len overshoots out_buf_len and the next 'out_buf_len - len' underflows. Switch both to scnprintf() which returns actual bytes written. In build_id__snprintf(), also tighten the loop guard from 'offs < bf_size' to 'offs + 1 < bf_size': since scnprintf() returns at most size-1, offs never reaches bf_size, and the original condition would spin doing zero-byte writes once the buffer fills. Fixes: fccaaf6fbbc59910 ("perf build-id: Change sprintf functions to snprintf") Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") Reported-by: sashiko-bot Reviewed-by: Ian Rogers Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/build-id.c | 7 +++++-- tools/perf/util/hwmon_pmu.c | 12 ++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 8c0a9ae932aa..eb95ab90f974 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -93,8 +93,11 @@ int build_id__snprintf(const struct build_id *build_id, char *bf, size_t bf_size return 0; } - for (size_t i = 0; i < build_id->size && offs < bf_size; ++i) - offs += snprintf(bf + offs, bf_size - offs, "%02x", build_id->data[i]); + if (bf_size > 0) + bf[0] = '\0'; + + for (size_t i = 0; i < build_id->size && offs + 1 < bf_size; ++i) + offs += scnprintf(bf + offs, bf_size - offs, "%02x", build_id->data[i]); return offs; } diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c index fb3ffa8d32ad..dbf6a71af47f 100644 --- a/tools/perf/util/hwmon_pmu.c +++ b/tools/perf/util/hwmon_pmu.c @@ -442,12 +442,12 @@ static size_t hwmon_pmu__describe_items(struct hwmon_pmu *hwm, char *out_buf, si buf[read_len] = '\0'; val = strtoll(buf, /*endptr=*/NULL, 10); - len += snprintf(out_buf + len, out_buf_len - len, "%s%s%s=%g%s", - len == 0 ? " " : ", ", - hwmon_item_strs[bit], - is_alarm ? "_alarm" : "", - (double)val / 1000.0, - hwmon_units[key.type]); + len += scnprintf(out_buf + len, out_buf_len - len, "%s%s%s=%g%s", + len == 0 ? " " : ", ", + hwmon_item_strs[bit], + is_alarm ? "_alarm" : "", + (double)val / 1000.0, + hwmon_units[key.type]); } close(fd); } From 7435c4069a546a5d2421407b3d43fdc1790ce6cc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 8 Jun 2026 15:32:32 -0300 Subject: [PATCH 257/343] libperf: Document code simplification case for widening struct perf_cpu Add a bullet point to the libperf ABI TODO explaining the code simplification benefit of widening struct perf_cpu.cpu from int16_t to int: the narrow type forces defensive truncation checks at every boundary where wider CPU indices are narrowed, and values > 32767 silently wrap to negative numbers (two's complement), bypassing bounds validation without them. Acked-by: Ian Rogers Cc: Ian Rogers Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/TODO | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/lib/perf/TODO b/tools/lib/perf/TODO index 486dd95dc572..e179728697d8 100644 --- a/tools/lib/perf/TODO +++ b/tools/lib/perf/TODO @@ -11,6 +11,14 @@ together. (x86_64 max is 8192, arm64 is 4096), but NR_CPUS limits keep growing. perf clamps to INT16_MAX in set_max_cpu_num() as a safety net. + - Code simplification: the int16_t forces defensive truncation + checks at every boundary where a wider CPU index (int from + sample->cpu, al->cpu, etc.) is narrowed into struct perf_cpu. + Without these checks, values > 32767 silently wrap to negative + numbers (two's complement), bypassing bounds validation. + Widening to int eliminates this entire class of silent + truncation bugs and removes the need for the INT16_MAX clamp + in set_max_cpu_num(). - Scope: struct perf_cpu is embedded everywhere — perf_cpu_map__cpu(), perf_cpu_map__min(), perf_cpu_map__max(), perf_cpu_map__has(), the for_each_cpu macros, and all internal callers. The perf_cpu_map From d5312a7ef79f5de574bce7b140ea1e48ce7e9262 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Tue, 9 Jun 2026 10:13:08 +0200 Subject: [PATCH 258/343] perf dwarf: Avoid redefinition warnings for REG_DWARFNUM_NAME dwarf-regs.c includes an arch-specific dwarf-regs-table.h for several architectures. This pulls in different definitions of REG_DWARFNUM_NAME and causes compiler warnings for W=1 builds. In file included from util/dwarf-regs.c:23: .../dwarf-regs-table.h:5: error: "REG_DWARFNUM_NAME" redefined [-Werror] #define REG_DWARFNUM_NAME(reg, idx) [idx] = reg Undefine REG_DWARFNUM_NAME before each new definition. Suggested-by: Arnaldo Carvalho de Melo Signed-off-by: Martin Kaiser Cc: Ian Rogers Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/powerpc/include/dwarf-regs-table.h | 1 + tools/perf/arch/riscv/include/dwarf-regs-table.h | 1 + tools/perf/arch/s390/include/dwarf-regs-table.h | 1 + 3 files changed, 3 insertions(+) diff --git a/tools/perf/arch/powerpc/include/dwarf-regs-table.h b/tools/perf/arch/powerpc/include/dwarf-regs-table.h index 66dc015a733d..7e746cb31b66 100644 --- a/tools/perf/arch/powerpc/include/dwarf-regs-table.h +++ b/tools/perf/arch/powerpc/include/dwarf-regs-table.h @@ -7,6 +7,7 @@ * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html * http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf */ +#undef REG_DWARFNUM_NAME #define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg static const char * const powerpc_regstr_tbl[] = { diff --git a/tools/perf/arch/riscv/include/dwarf-regs-table.h b/tools/perf/arch/riscv/include/dwarf-regs-table.h index a45b63a6d5a8..009a4e3c51ab 100644 --- a/tools/perf/arch/riscv/include/dwarf-regs-table.h +++ b/tools/perf/arch/riscv/include/dwarf-regs-table.h @@ -2,6 +2,7 @@ #ifdef DEFINE_DWARF_REGSTR_TABLE /* This is included in perf/util/dwarf-regs.c */ +#undef REG_DWARFNUM_NAME #define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg static const char * const riscv_regstr_tbl[] = { diff --git a/tools/perf/arch/s390/include/dwarf-regs-table.h b/tools/perf/arch/s390/include/dwarf-regs-table.h index 671553525f41..e90b63157702 100644 --- a/tools/perf/arch/s390/include/dwarf-regs-table.h +++ b/tools/perf/arch/s390/include/dwarf-regs-table.h @@ -2,6 +2,7 @@ #ifndef S390_DWARF_REGS_TABLE_H #define S390_DWARF_REGS_TABLE_H +#undef REG_DWARFNUM_NAME #define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg /* From 8d28a56cae9b298a351b361d8d374cb4a9089e3f Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Tue, 9 Jun 2026 10:13:09 +0200 Subject: [PATCH 259/343] perf riscv: fix register name strings On risc-v, pref probe generates an invalid syntax for a named register in a kprobe. $ perf probe --debug verbose --add "n_tty_write tty" ... Writing event: p:probe/n_tty_write _text+8922528 tty=%"%a0":x64 Failed to write event: Invalid argument The problem is the combination of #define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg and entries such as REG_DWARFNUM_NAME("%a0", 10) where #reg will escape the quotes of the first macro parameter. Update the macro definition to produce the correct syntax for a named register in a kprobe, i.e. the unquoted register name with only one leading %. Fixes: a90c4519186dfc08 ("perf riscv: Remove dwarf-regs.c and add dwarf-regs-table.h") Reviewed-by: Ian Rogers Signed-off-by: Martin Kaiser Cc: Ian Rogers Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/riscv/include/dwarf-regs-table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/arch/riscv/include/dwarf-regs-table.h b/tools/perf/arch/riscv/include/dwarf-regs-table.h index 009a4e3c51ab..8c42806d34f1 100644 --- a/tools/perf/arch/riscv/include/dwarf-regs-table.h +++ b/tools/perf/arch/riscv/include/dwarf-regs-table.h @@ -3,7 +3,7 @@ /* This is included in perf/util/dwarf-regs.c */ #undef REG_DWARFNUM_NAME -#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg +#define REG_DWARFNUM_NAME(reg, idx) [idx] = reg static const char * const riscv_regstr_tbl[] = { REG_DWARFNUM_NAME("%zero", 0), From 41c1ce28bbc1d4f7a1b1b711b86448480d2838d2 Mon Sep 17 00:00:00 2001 From: Jens Remus Date: Mon, 8 Jun 2026 18:06:13 +0200 Subject: [PATCH 260/343] perf build: Respect V=1 for Python extension builds Make util/setup.py respect the verbose build flag (V=1) by conditionally passing --quiet only when not in verbose mode. This eases debugging of Python extension compilation issues and aligns with the existing perf build system behavior. Reviewed-by: Ian Rogers Signed-off-by: Jens Remus Tested-by: Jan Polensky Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Heiko Carstens Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index ab661a1d271c..bdedf6620758 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -401,6 +401,10 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf*.so +ifneq ($(quiet),) +python_setup_quiet=--quiet +endif + # Use the detected configuration -include $(OUTPUT).config-detected @@ -526,7 +530,7 @@ $(OUTPUT)python/perf$(PYTHON_EXTENSION_SUFFIX): util/python.c util/setup.py $(PE $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \ CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBS_PY)' \ $(PYTHON_WORD) util/setup.py \ - --quiet build_ext; \ + $(python_setup_quiet) build_ext; \ cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/ python_perf_target: @@ -903,7 +907,7 @@ install-bin: install-tools install-tests install: install-bin try-install-man install-python_ext: - $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' + $(PYTHON_WORD) util/setup.py $(python_setup_quiet) install --root='/$(DESTDIR_SQ)' # 'make install-doc' should call 'make -C Documentation install' $(INSTALL_DOC_TARGETS): From bcd2cc4405bdb9ac77210d0df5990d46c311be66 Mon Sep 17 00:00:00 2001 From: Jens Remus Date: Wed, 10 Jun 2026 13:23:43 +0200 Subject: [PATCH 261/343] perf build: Do not duplicate CFLAGS in Python extension builds setuptools already uses CFLAGS. Passing CFLAGS with additional flags as extra compile arguments causes CFLAGS to effectively get passed twice: $ make -C tools/perf V=1 JOBS=1 ... building 'perf' extension gcc [CFLAGS] -fPIC -Iutil/include -I/usr/include/python3.14 \ -c /root/linux/tools/perf/util/python.c \ -o python_ext_build/tmp/root/linux/tools/perf/util/python.o \ [CFLAGS] \ -fno-strict-aliasing -Wno-write-strings -Wno-unused-parameter \ -Wno-redundant-decls -Wno-cast-function-type \ -Wno-declaration-after-statement Reviewed-by: James Clark Signed-off-by: Jens Remus Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Heiko Carstens Cc: Hendrik Brueckner Cc: Ian Rogers Cc: Ingo Molnar Cc: Jan Polensky Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/setup.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index b65b1792ca05..a0ce76624a23 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py @@ -74,18 +74,17 @@ class install_lib(_install_lib): self.build_dir = build_lib -cflags = getenv('CFLAGS', '').split() # switch off several checks (need to be at the end of cflags list) -cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter', '-Wno-redundant-decls' ] +extra_cflags = ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter', '-Wno-redundant-decls' ] if cc_is_clang: - cflags += ["-Wno-unused-command-line-argument" ] + extra_cflags += ["-Wno-unused-command-line-argument" ] if clang_has_option("-Wno-cast-function-type-mismatch"): - cflags += ["-Wno-cast-function-type-mismatch" ] + extra_cflags += ["-Wno-cast-function-type-mismatch" ] else: - cflags += ['-Wno-cast-function-type' ] + extra_cflags += ['-Wno-cast-function-type' ] # The python headers have mixed code with declarations (decls after asserts, for instance) -cflags += [ "-Wno-declaration-after-statement" ] +extra_cflags += [ "-Wno-declaration-after-statement" ] src_perf = f'{srctree}/tools/perf' build_lib = getenv('PYTHON_EXTBUILD_LIB') @@ -94,7 +93,7 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP') perf = Extension('perf', sources = [ src_perf + '/util/python.c' ], include_dirs = ['util/include'], - extra_compile_args = cflags, + extra_compile_args = extra_cflags, ) setup(name='perf', From 49f5f6ae67dec54014584bb3126a5a94f14e2a5c Mon Sep 17 00:00:00 2001 From: Jens Remus Date: Wed, 10 Jun 2026 13:24:51 +0200 Subject: [PATCH 262/343] perf s390: Fix TEXTREL in Python extension by compiling as PIC On s390 the Python extension build fails as follows when using a linker that is configured to treat text relocations (TEXTREL) in shared libraries as error by default: GEN python/perf.cpython-314-s390x-linux-gnu.so /usr/bin/ld.bfd: error: read-only segment has dynamic relocations This occurrs because util/llvm-c-helpers.o is erroneously built from util/llvm-c-helpers.cpp without compiler option -fPIC but linked into the shared library (via libperf-util.a(perf-util-in.o)). On s390, object files must be compiled as position-indepedent code (PIC) in order to be linked into shared libraries. Commit a9a3f1d18a6c ("perf s390: Always build with -fPIC") added compiler option -fPIC to CFLAGS for s390, which is used in C compiles. Add -fPIC to CXXFLAGS for s390 as well, so that it is also used in C++ compiles. Fixes: a9a3f1d18a6c9ccf ("perf s390: Always build with -fPIC") Reported-by: Thomas Richter Reviewed-by: Ian Rogers Reviewed-by: James Clark Signed-off-by: Jens Remus Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Bill Wendling Cc: Heiko Carstens Cc: Hendrik Brueckner Cc: Ingo Molnar Cc: Jan Polensky Cc: Jiri Olsa Cc: Justin Stitt Cc: Mark Rutland Cc: Namhyung Kim Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 6e7b15fab2ec..0ba307e78fe1 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -77,6 +77,7 @@ endif ifeq ($(ARCH),s390) CFLAGS += -fPIC + CXXFLAGS += -fPIC endif # Unconditionally set up the libunwind feature build flags as a From 2857a5dca750ea989c6fb70b4c14e801e4b7b4ad Mon Sep 17 00:00:00 2001 From: Tanushree Shah Date: Sat, 6 Jun 2026 17:45:29 +0530 Subject: [PATCH 263/343] perf data convert json: Fix addr_location leak on time-filtered samples When samples are skipped due to time filtering in process_sample_event(), the early return path bypasses addr_location__exit(), causing memory leaks of thread, map, and maps references acquired by machine__resolve(). These references must be released through addr_location__exit() before returning. Fixes: 8e746e95c3e4eb56 ("perf data: Allow filtering conversion by time range") Reviewed-by: Ian Rogers Signed-off-by: Tanushree Shah Cc: Adrian Hunter Cc: Athira Rajeev Cc: Derek Foreman Cc: Hari Bathini Cc: Jiri Olsa Cc: Madhavan Srinivasan Cc: Michael Petlan Cc: Namhyung Kim Cc: Shivani.Nittor@ibm.com Cc: Tanushree.Shah@ibm.com Cc: Tejas.Manhas1@ibm.com Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/data-convert-json.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/data-convert-json.c b/tools/perf/util/data-convert-json.c index c71dfb77c697..40412c3dbdb2 100644 --- a/tools/perf/util/data-convert-json.c +++ b/tools/perf/util/data-convert-json.c @@ -177,6 +177,7 @@ static int process_sample_event(const struct perf_tool *tool, if (perf_time__ranges_skip_sample(c->ptime_range, c->range_num, sample->time)) { ++c->skipped; + addr_location__exit(&al); return 0; } From 4bd109899fb51594e0d868238ada109c12d13a74 Mon Sep 17 00:00:00 2001 From: Athira Rajeev Date: Tue, 9 Jun 2026 19:13:31 +0530 Subject: [PATCH 264/343] perf tools: Fix the check for parameterized field in event term The format_alias() function in util/pmu.c has a check to detect whether the event has parameterized field ( =? ). The string alias->terms contains the event and if the event has user configurable parameter, there will be presence of sub string "=?" in the alias->terms. Snippet of code: /* Paramemterized events have the parameters shown. */ if (strstr(alias->terms, "=?")) { /* No parameters. */ snprintf(buf, len, "%.*s/%s/", (int)pmu_name_len, pmu->name, alias->name); if "strstr" contains the substring, it returns a pointer and hence enters the above check which is not the expected check. And hence "perf list" doesn't have the parameterized fields in the result. Fix this check to use: if (!strstr(alias->terms, "=?")) { With this change, perf list shows the events correctly with the strings showing parameters. Before the fix: # ./perf list|grep -w PM_PAU_CYC hv_24x7/PM_PAU_CYC/ [Kernel PMU event] With this fix: # ./perf list|grep -w PM_PAU_CYC hv_24x7/PM_PAU_CYC,chip=?/ [Kernel PMU event] Reviewed-by: Ian Rogers Signed-off-by: Athira Rajeev Tested-by: Venkat Rao Bagalkote Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Hari Bathini Cc: Jiri Olsa Cc: Madhavan Srinivasan Cc: Michael Petlan Cc: Shivani Nittor Cc: Tanushree.Shah@ibm.com Cc: Tejas.Manhas1@ibm.com Cc: Thomas Richter Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 9994709ef12b..e765a7ffb0d6 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -2134,7 +2134,7 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, skip_duplicate_pmus); /* Paramemterized events have the parameters shown. */ - if (strstr(alias->terms, "=?")) { + if (!strstr(alias->terms, "=?")) { /* No parameters. */ snprintf(buf, len, "%.*s/%s/", (int)pmu_name_len, pmu->name, alias->name); return buf; From 4aa4d246c81f360d2609c6ffe0b72f2895973447 Mon Sep 17 00:00:00 2001 From: Athira Rajeev Date: Tue, 9 Jun 2026 19:13:32 +0530 Subject: [PATCH 265/343] perf pmu: Use scnprintf in buffer offset calculations Replace snprintf with scnprintf in buffer offset calculations to ensure the 'used' count will not exceed the "len". The current logic in perf_pmu__for_each_event uses an unconditional + 1 increment to buf_used to account for null terminators. This can cause a stack buffer overflow in the subsequent scnprintf call. When the local stack buffer buf (1024 bytes) is full, buf_used can reach 1025. This causes the subsequent remaining space calculation sizeof(buf) - buf_used to underflow. Use sub_non_neg() to see if space actually existed, and only increment the offset if remaining space is present. Changes includes: - Use sub_non_neg to check if space exists - Replacing snprintf with scnprintf to ensure the return value reflects the actual bytes written into the buffer. - Only increment buf_used by 1 if space exists - If a parameterized event uses a built-in perf keyword for its parameter name (eg, config=?), the lexer parses it as a predefined term token, which sets term->config to NULL. Add check to use parse_events__term_type_str() if term->config is NULL. Signed-off-by: Athira Rajeev Cc: Adrian Hunter Cc: Hari Bathini Cc: Ian Rogers Cc: Jiri Olsa Cc: Madhavan Srinivasan Cc: Michael Petlan Cc: Namhyung Kim Cc: Shivani Nittor Cc: Tanushree.Shah@ibm.com Cc: Tejas.Manhas1@ibm.com Cc: Thomas Richter Cc: Venkat Rao Bagalkote Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index e765a7ffb0d6..1539960ba23b 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -2146,15 +2146,19 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, pr_err("Failure to parse '%s' terms '%s': %d\n", alias->name, alias->terms, ret); parse_events_terms__exit(&terms); - snprintf(buf, len, "%.*s/%s/", (int)pmu_name_len, pmu->name, alias->name); + scnprintf(buf, len, "%.*s/%s/", (int)pmu_name_len, pmu->name, alias->name); return buf; } - used = snprintf(buf, len, "%.*s/%s", (int)pmu_name_len, pmu->name, alias->name); + used = scnprintf(buf, len, "%.*s/%s", (int)pmu_name_len, pmu->name, alias->name); list_for_each_entry(term, &terms.terms, list) { + const char *name = term->config; + + if (!name) + name = parse_events__term_type_str(term->type_term); if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) - used += snprintf(buf + used, sub_non_neg(len, used), - ",%s=%s", term->config, + used += scnprintf(buf + used, sub_non_neg(len, used), + ",%s=%s", name, term->val.str); } parse_events_terms__exit(&terms); @@ -2218,6 +2222,7 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, int ret = 0; struct hashmap_entry *entry; size_t bkt; + size_t size_rem; if (perf_pmu__is_tracepoint(pmu)) return tp_pmu__for_each_event(pmu, state, cb); @@ -2251,17 +2256,30 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, } buf_used = strlen(buf) + 1; } + info.scale_unit = NULL; if (strlen(event->unit) || event->scale != 1.0) { - info.scale_unit = buf + buf_used; - buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, - "%G%s", event->scale, event->unit) + 1; + /* Check the remaining space */ + size_rem = sub_non_neg(sizeof(buf), buf_used); + + if (size_rem > 0) { + info.scale_unit = buf + buf_used; + buf_used += scnprintf(buf + buf_used, size_rem, "%G%s", + event->scale, event->unit) + 1; + } } info.desc = event->desc; info.long_desc = event->long_desc; - info.encoding_desc = buf + buf_used; - buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, - "%.*s/%s/", (int)pmu_name_len, info.pmu_name, event->terms) + 1; + info.encoding_desc = NULL; + + /* Check the remaining space */ + size_rem = sub_non_neg(sizeof(buf), buf_used); + if (size_rem > 0) { + info.encoding_desc = buf + buf_used; + buf_used += scnprintf(buf + buf_used, size_rem, "%.*s/%s/", + (int)pmu_name_len, info.pmu_name, event->terms) + 1; + } + info.str = event->terms; info.topic = event->topic; info.deprecated = perf_pmu_alias__check_deprecated(pmu, event); @@ -2271,7 +2289,7 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, } if (pmu->selectable) { info.name = buf; - snprintf(buf, sizeof(buf), "%s//", pmu->name); + scnprintf(buf, sizeof(buf), "%s//", pmu->name); info.alias = NULL; info.scale_unit = NULL; info.desc = NULL; From 68ca50bc0fa64841cd73b8a1538df1d7f7eb4108 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:06 +0100 Subject: [PATCH 266/343] perf cs-etm: Queue context packets for frontend PE_CONTEXT elements update the context ID and exception level, but the decoder may still have prior packets cached for frontend processing. Updating the context immediately in the decoder backend can make those cached packets get consumed with the wrong thread or EL state. Add a CS_ETM_CONTEXT packet carrying the TID and EL to the frontend, this keeps context changes ordered with the rest of the packet stream and avoids mismatches when synthesizing samples from cached packets. Separate the memory access function into one for the frontend and one for decoding. The frontend also needs memory access to attach the instruction to samples. Because the frontend does memory access for both previous and current packets, change all the frontend memory access function signatures to take both a tidq and packet. But backend always uses the current backend EL and thread from the tidq. Treat context packets as a boundary for branch sample generation and remove tidq->prev_packet_thread because it's not possible to branch to a different thread, so only tracking the current thread is required for sample generation. Fixes: e573e978fb12e160 ("perf cs-etm: Inject capabilitity for CoreSight traces") Reported-by: Amir Ayupov Closes: https://lore.kernel.org/linux-perf-users/20260515021135.1729028-1-aaupov@meta.com/ Co-authored-by: James Clark Signed-off-by: Leo Yan Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: linux-doc@vger.kernel.org Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Robert Walker Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: James Clark Signed-off-by: Arnaldo Carvalho de Melo --- .../perf/util/cs-etm-decoder/cs-etm-decoder.c | 21 +- tools/perf/util/cs-etm.c | 236 +++++++++++------- tools/perf/util/cs-etm.h | 8 +- 3 files changed, 163 insertions(+), 102 deletions(-) diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c index dee3020ceaa9..26940f1f1b0b 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c @@ -402,6 +402,8 @@ cs_etm_decoder__buffer_packet(struct cs_etm_queue *etmq, packet_queue->packet_buffer[et].flags = 0; packet_queue->packet_buffer[et].exception_number = UINT32_MAX; packet_queue->packet_buffer[et].trace_chan_id = trace_chan_id; + packet_queue->packet_buffer[et].el = ocsd_EL_unknown; + packet_queue->packet_buffer[et].tid = -1; if (packet_queue->packet_count == CS_ETM_PACKET_MAX_BUFFER - 1) return OCSD_RESP_WAIT; @@ -449,6 +451,7 @@ cs_etm_decoder__buffer_range(struct cs_etm_queue *etmq, packet->last_instr_type = elem->last_i_type; packet->last_instr_subtype = elem->last_i_subtype; packet->last_instr_cond = elem->last_instr_cond; + packet->el = elem->context.exception_level; if (elem->last_i_type == OCSD_INSTR_BR || elem->last_i_type == OCSD_INSTR_BR_INDIRECT) packet->last_instr_taken_branch = elem->last_instr_exec; @@ -525,7 +528,9 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq, const ocsd_generic_trace_elem *elem, const uint8_t trace_chan_id) { + struct cs_etm_packet *packet; pid_t tid = -1; + int ret; /* * Process the PE_CONTEXT packets if we have a valid contextID or VMID. @@ -546,12 +551,18 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq, break; } - if (cs_etm__etmq_set_tid_el(etmq, tid, trace_chan_id, - elem->context.exception_level)) + if (cs_etm__etmq_update_decode_context(etmq, trace_chan_id, + elem->context.exception_level, tid)) return OCSD_RESP_FATAL_SYS_ERR; - if (tid == -1) - return OCSD_RESP_CONT; + ret = cs_etm_decoder__buffer_packet(etmq, packet_queue, trace_chan_id, + CS_ETM_CONTEXT); + if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT) + return ret; + + packet = &packet_queue->packet_buffer[packet_queue->tail]; + packet->tid = tid; + packet->el = elem->context.exception_level; /* * A timestamp is generated after a PE_CONTEXT element so make sure @@ -559,7 +570,7 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq, */ cs_etm_decoder__reset_timestamp(packet_queue); - return OCSD_RESP_CONT; + return ret; } static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 40c6ddfa8c8d..5e92359f51a7 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -85,15 +85,22 @@ struct cs_etm_traceid_queue { u64 period_instructions; size_t last_branch_pos; union perf_event *event_buf; - struct thread *thread; - struct thread *prev_packet_thread; - ocsd_ex_level prev_packet_el; - ocsd_ex_level el; struct branch_stack *last_branch; struct branch_stack *last_branch_rb; struct cs_etm_packet *prev_packet; struct cs_etm_packet *packet; struct cs_etm_packet_queue packet_queue; + + struct thread *decode_thread; + ocsd_ex_level decode_el; + + /* + * The frontend accesses the EL from '[prev_]packet' because it needs + * previous EL for branch and current EL for instruction samples. It's + * not possible to change thread in a single branch sample so no need to + * store or access the thread through the packet. + */ + struct thread *frontend_thread; }; enum cs_etm_format { @@ -614,10 +621,11 @@ static int cs_etm__init_traceid_queue(struct cs_etm_queue *etmq, queue = &etmq->etm->queues.queue_array[etmq->queue_nr]; tidq->trace_chan_id = trace_chan_id; - tidq->el = tidq->prev_packet_el = ocsd_EL_unknown; - tidq->thread = machine__findnew_thread(&etm->session->machines.host, -1, + tidq->decode_el = ocsd_EL_unknown; + tidq->frontend_thread = machine__findnew_thread(&etm->session->machines.host, -1, + queue->tid); + tidq->decode_thread = machine__findnew_thread(&etm->session->machines.host, -1, queue->tid); - tidq->prev_packet_thread = machine__idle_thread(&etm->session->machines.host); tidq->packet = zalloc(sizeof(struct cs_etm_packet)); if (!tidq->packet) @@ -750,21 +758,10 @@ static void cs_etm__packet_swap(struct cs_etm_auxtrace *etm, /* * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for * the next incoming packet. - * - * Threads and exception levels are also tracked for both the - * previous and current packets. This is because the previous - * packet is used for the 'from' IP for branch samples, so the - * thread at that time must also be assigned to that sample. - * Across discontinuity packets the thread can change, so by - * tracking the thread for the previous packet the branch sample - * will have the correct info. */ tmp = tidq->packet; tidq->packet = tidq->prev_packet; tidq->prev_packet = tmp; - tidq->prev_packet_el = tidq->el; - thread__put(tidq->prev_packet_thread); - tidq->prev_packet_thread = thread__get(tidq->thread); } } @@ -937,8 +934,8 @@ static void cs_etm__free_traceid_queues(struct cs_etm_queue *etmq) /* Free this traceid_queue from the array */ tidq = etmq->traceid_queues[idx]; - thread__zput(tidq->thread); - thread__zput(tidq->prev_packet_thread); + thread__zput(tidq->frontend_thread); + thread__zput(tidq->decode_thread); zfree(&tidq->event_buf); zfree(&tidq->last_branch); zfree(&tidq->last_branch_rb); @@ -1083,47 +1080,43 @@ static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address, } } -static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id, - u64 address, size_t size, u8 *buffer, - const ocsd_mem_space_acc_t mem_space) +static u32 __cs_etm__mem_access(struct cs_etm_queue *etmq, + u64 address, size_t size, u8 *buffer, + const ocsd_mem_space_acc_t mem_space, + ocsd_ex_level el, struct thread *thread) { u8 cpumode; u64 offset; int len; struct addr_location al; struct dso *dso; - struct cs_etm_traceid_queue *tidq; int ret = 0; if (!etmq) return 0; addr_location__init(&al); - tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id); - if (!tidq) - goto out; /* - * We've already tracked EL along side the PID in cs_etm__set_thread() - * so double check that it matches what OpenCSD thinks as well. It - * doesn't distinguish between EL0 and EL1 for this mem access callback - * so we had to do the extra tracking. Skip validation if it's any of - * the 'any' values. + * We track EL for the frontend and the backend when receiving context + * and range packets. OpenCSD doesn't distinguish between EL0 and EL1 + * for this mem access callback so we had to do the extra tracking. Skip + * validation if it's any of the 'any' values. */ if (!(mem_space == OCSD_MEM_SPACE_ANY || mem_space == OCSD_MEM_SPACE_N || mem_space == OCSD_MEM_SPACE_S)) { if (mem_space & OCSD_MEM_SPACE_EL1N) { /* Includes both non secure EL1 and EL0 */ - assert(tidq->el == ocsd_EL1 || tidq->el == ocsd_EL0); + assert(el == ocsd_EL1 || el == ocsd_EL0); } else if (mem_space & OCSD_MEM_SPACE_EL2) - assert(tidq->el == ocsd_EL2); + assert(el == ocsd_EL2); else if (mem_space & OCSD_MEM_SPACE_EL3) - assert(tidq->el == ocsd_EL3); + assert(el == ocsd_EL3); } - cpumode = cs_etm__cpu_mode(etmq, address, tidq->el); + cpumode = cs_etm__cpu_mode(etmq, address, el); - if (!thread__find_map(tidq->thread, cpumode, address, &al)) + if (!thread__find_map(thread, cpumode, address, &al)) goto out; dso = map__dso(al.map); @@ -1138,7 +1131,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id, map__load(al.map); - len = dso__data_read_offset(dso, maps__machine(thread__maps(tidq->thread)), + len = dso__data_read_offset(dso, maps__machine(thread__maps(thread)), offset, buffer, size); if (len <= 0) { @@ -1158,6 +1151,30 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id, return ret; } +static u32 cs_etm__frontend_mem_access(struct cs_etm_queue *etmq, + struct cs_etm_traceid_queue *tidq, + struct cs_etm_packet *packet, + u64 address, size_t size, u8 *buffer) +{ + return __cs_etm__mem_access(etmq, address, size, buffer, 0, packet->el, + tidq->frontend_thread); +} + +static u32 cs_etm__decoder_mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id, + u64 address, size_t size, u8 *buffer, + const ocsd_mem_space_acc_t mem_space) +{ + struct cs_etm_traceid_queue *tidq; + + tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id); + if (!tidq) + return 0; + + return __cs_etm__mem_access(etmq, address, size, buffer, + mem_space, tidq->decode_el, + tidq->decode_thread); +} + static struct cs_etm_queue *cs_etm__alloc_queue(void) { struct cs_etm_queue *etmq = zalloc(sizeof(*etmq)); @@ -1333,12 +1350,13 @@ void cs_etm__reset_last_branch_rb(struct cs_etm_traceid_queue *tidq) } static inline int cs_etm__t32_instr_size(struct cs_etm_queue *etmq, - u8 trace_chan_id, u64 addr) + struct cs_etm_traceid_queue *tidq, + struct cs_etm_packet *packet, u64 addr) { u8 instrBytes[2]; - cs_etm__mem_access(etmq, trace_chan_id, addr, ARRAY_SIZE(instrBytes), - instrBytes, 0); + cs_etm__frontend_mem_access(etmq, tidq, packet, addr, + ARRAY_SIZE(instrBytes), instrBytes); /* * T32 instruction size is indicated by bits[15:11] of the first * 16-bit word of the instruction: 0b11101, 0b11110 and 0b11111 @@ -1371,16 +1389,16 @@ u64 cs_etm__last_executed_instr(const struct cs_etm_packet *packet) } static inline u64 cs_etm__instr_addr(struct cs_etm_queue *etmq, - u64 trace_chan_id, - const struct cs_etm_packet *packet, + struct cs_etm_traceid_queue *tidq, + struct cs_etm_packet *packet, u64 offset) { if (packet->isa == CS_ETM_ISA_T32) { u64 addr = packet->start_addr; while (offset) { - addr += cs_etm__t32_instr_size(etmq, - trace_chan_id, addr); + addr += cs_etm__t32_instr_size(etmq, tidq, packet, + addr); offset--; } return addr; @@ -1490,34 +1508,51 @@ cs_etm__get_trace(struct cs_etm_queue *etmq) return etmq->buf_len; } -static void cs_etm__set_thread(struct cs_etm_queue *etmq, - struct cs_etm_traceid_queue *tidq, pid_t tid, - ocsd_ex_level el) +/* + * Convert a raw thread number to a thread struct and assign it to **thread. + */ +static int cs_etm__etmq_update_thread(struct cs_etm_queue *etmq, + ocsd_ex_level el, pid_t tid, + struct thread **thread) { struct machine *machine = cs_etm__get_machine(etmq, el); + if (!machine || !*thread) + return -EINVAL; + if (tid != -1) { - thread__zput(tidq->thread); - tidq->thread = machine__find_thread(machine, -1, tid); + thread__zput(*thread); + *thread = machine__find_thread(machine, -1, tid); } /* Couldn't find a known thread */ - if (!tidq->thread) - tidq->thread = machine__idle_thread(machine); + if (!*thread) + *thread = machine__idle_thread(machine); - tidq->el = el; + return 0; } -int cs_etm__etmq_set_tid_el(struct cs_etm_queue *etmq, pid_t tid, - u8 trace_chan_id, ocsd_ex_level el) +/* + * Set the thread and EL of the decode context which is ahead in time of the + * frontend context. + */ +int cs_etm__etmq_update_decode_context(struct cs_etm_queue *etmq, + u8 trace_chan_id, + ocsd_ex_level el, pid_t tid) { struct cs_etm_traceid_queue *tidq; + int ret; tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id); if (!tidq) return -EINVAL; - cs_etm__set_thread(etmq, tidq, tid, el); + ret = cs_etm__etmq_update_thread(etmq, el, tid, + &tidq->decode_thread); + if (ret) + return ret; + + tidq->decode_el = el; return 0; } @@ -1527,8 +1562,8 @@ bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq) } static void cs_etm__copy_insn(struct cs_etm_queue *etmq, - u64 trace_chan_id, - const struct cs_etm_packet *packet, + struct cs_etm_traceid_queue *tidq, + struct cs_etm_packet *packet, struct perf_sample *sample) { /* @@ -1545,14 +1580,14 @@ static void cs_etm__copy_insn(struct cs_etm_queue *etmq, * cs_etm__t32_instr_size(). */ if (packet->isa == CS_ETM_ISA_T32) - sample->insn_len = cs_etm__t32_instr_size(etmq, trace_chan_id, + sample->insn_len = cs_etm__t32_instr_size(etmq, tidq, packet, sample->ip); /* Otherwise, A64 and A32 instruction size are always 32-bit. */ else sample->insn_len = 4; - cs_etm__mem_access(etmq, trace_chan_id, sample->ip, sample->insn_len, - (void *)sample->insn, 0); + cs_etm__frontend_mem_access(etmq, tidq, packet, sample->ip, + sample->insn_len, (void *)sample->insn); } u64 cs_etm__convert_sample_time(struct cs_etm_queue *etmq, u64 cs_timestamp) @@ -1579,6 +1614,7 @@ static inline u64 cs_etm__resolve_sample_time(struct cs_etm_queue *etmq, static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq, struct cs_etm_traceid_queue *tidq, + struct cs_etm_packet *packet, u64 addr, u64 period) { int ret = 0; @@ -1588,23 +1624,23 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq, perf_sample__init(&sample, /*all=*/true); event->sample.header.type = PERF_RECORD_SAMPLE; - event->sample.header.misc = cs_etm__cpu_mode(etmq, addr, tidq->el); + event->sample.header.misc = cs_etm__cpu_mode(etmq, addr, packet->el); event->sample.header.size = sizeof(struct perf_event_header); /* Set time field based on etm auxtrace config. */ sample.time = cs_etm__resolve_sample_time(etmq, tidq); sample.ip = addr; - sample.pid = thread__pid(tidq->thread); - sample.tid = thread__tid(tidq->thread); + sample.pid = thread__pid(tidq->frontend_thread); + sample.tid = thread__tid(tidq->frontend_thread); sample.id = etmq->etm->instructions_id; sample.stream_id = etmq->etm->instructions_id; sample.period = period; - sample.cpu = tidq->packet->cpu; + sample.cpu = packet->cpu; sample.flags = tidq->prev_packet->flags; sample.cpumode = event->sample.header.misc; - cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->packet, &sample); + cs_etm__copy_insn(etmq, tidq, packet, &sample); if (etm->synth_opts.last_branch) sample.branch_stack = tidq->last_branch; @@ -1649,15 +1685,15 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, event->sample.header.type = PERF_RECORD_SAMPLE; event->sample.header.misc = cs_etm__cpu_mode(etmq, ip, - tidq->prev_packet_el); + tidq->prev_packet->el); event->sample.header.size = sizeof(struct perf_event_header); /* Set time field based on etm auxtrace config. */ sample.time = cs_etm__resolve_sample_time(etmq, tidq); sample.ip = ip; - sample.pid = thread__pid(tidq->prev_packet_thread); - sample.tid = thread__tid(tidq->prev_packet_thread); + sample.pid = thread__pid(tidq->frontend_thread); + sample.tid = thread__tid(tidq->frontend_thread); sample.addr = cs_etm__first_executed_instr(tidq->packet); sample.id = etmq->etm->branches_id; sample.stream_id = etmq->etm->branches_id; @@ -1666,8 +1702,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, sample.flags = tidq->prev_packet->flags; sample.cpumode = event->sample.header.misc; - cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->prev_packet, - &sample); + cs_etm__copy_insn(etmq, tidq, tidq->prev_packet, &sample); /* * perf report cannot handle events without a branch stack @@ -1788,7 +1823,6 @@ static int cs_etm__sample(struct cs_etm_queue *etmq, { struct cs_etm_auxtrace *etm = etmq->etm; int ret; - u8 trace_chan_id = tidq->trace_chan_id; u64 instrs_prev; /* Get instructions remainder from previous packet */ @@ -1874,10 +1908,10 @@ static int cs_etm__sample(struct cs_etm_queue *etmq, * been executed, but PC has not advanced to next * instruction) */ - addr = cs_etm__instr_addr(etmq, trace_chan_id, - tidq->packet, offset - 1); + addr = cs_etm__instr_addr(etmq, tidq, tidq->packet, + offset - 1); ret = cs_etm__synth_instruction_sample( - etmq, tidq, addr, + etmq, tidq, tidq->packet, addr, etm->instructions_sample_period); if (ret) return ret; @@ -1959,7 +1993,7 @@ static int cs_etm__flush(struct cs_etm_queue *etmq, addr = cs_etm__last_executed_instr(tidq->prev_packet); err = cs_etm__synth_instruction_sample( - etmq, tidq, addr, + etmq, tidq, tidq->prev_packet, addr, tidq->period_instructions); if (err) return err; @@ -2014,7 +2048,7 @@ static int cs_etm__end_block(struct cs_etm_queue *etmq, addr = cs_etm__last_executed_instr(tidq->prev_packet); err = cs_etm__synth_instruction_sample( - etmq, tidq, addr, + etmq, tidq, tidq->prev_packet, addr, tidq->period_instructions); if (err) return err; @@ -2051,9 +2085,9 @@ static int cs_etm__get_data_block(struct cs_etm_queue *etmq) return etmq->buf_len; } -static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id, - struct cs_etm_packet *packet, - u64 end_addr) +static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, + struct cs_etm_traceid_queue *tidq, + struct cs_etm_packet *packet, u64 end_addr) { /* Initialise to keep compiler happy */ u16 instr16 = 0; @@ -2075,8 +2109,8 @@ static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id, * so below only read 2 bytes as instruction size for T32. */ addr = end_addr - 2; - cs_etm__mem_access(etmq, trace_chan_id, addr, sizeof(instr16), - (u8 *)&instr16, 0); + cs_etm__frontend_mem_access(etmq, tidq, packet, addr, + sizeof(instr16), (u8 *)&instr16); if ((instr16 & 0xFF00) == 0xDF00) return true; @@ -2091,8 +2125,8 @@ static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id, * +---------+---------+-------------------------+ */ addr = end_addr - 4; - cs_etm__mem_access(etmq, trace_chan_id, addr, sizeof(instr32), - (u8 *)&instr32, 0); + cs_etm__frontend_mem_access(etmq, tidq, packet, addr, + sizeof(instr32), (u8 *)&instr32); if ((instr32 & 0x0F000000) == 0x0F000000 && (instr32 & 0xF0000000) != 0xF0000000) return true; @@ -2108,8 +2142,8 @@ static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id, * +-----------------------+---------+-----------+ */ addr = end_addr - 4; - cs_etm__mem_access(etmq, trace_chan_id, addr, sizeof(instr32), - (u8 *)&instr32, 0); + cs_etm__frontend_mem_access(etmq, tidq, packet, addr, + sizeof(instr32), (u8 *)&instr32); if ((instr32 & 0xFFE0001F) == 0xd4000001) return true; @@ -2125,7 +2159,6 @@ static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id, static bool cs_etm__is_syscall(struct cs_etm_queue *etmq, struct cs_etm_traceid_queue *tidq, u64 magic) { - u8 trace_chan_id = tidq->trace_chan_id; struct cs_etm_packet *packet = tidq->packet; struct cs_etm_packet *prev_packet = tidq->prev_packet; @@ -2140,7 +2173,7 @@ static bool cs_etm__is_syscall(struct cs_etm_queue *etmq, */ if (magic == __perf_cs_etmv4_magic) { if (packet->exception_number == CS_ETMV4_EXC_CALL && - cs_etm__is_svc_instr(etmq, trace_chan_id, prev_packet, + cs_etm__is_svc_instr(etmq, tidq, prev_packet, prev_packet->end_addr)) return true; } @@ -2178,7 +2211,6 @@ static bool cs_etm__is_sync_exception(struct cs_etm_queue *etmq, struct cs_etm_traceid_queue *tidq, u64 magic) { - u8 trace_chan_id = tidq->trace_chan_id; struct cs_etm_packet *packet = tidq->packet; struct cs_etm_packet *prev_packet = tidq->prev_packet; @@ -2204,7 +2236,7 @@ static bool cs_etm__is_sync_exception(struct cs_etm_queue *etmq, * (SMC, HVC) are taken as sync exceptions. */ if (packet->exception_number == CS_ETMV4_EXC_CALL && - !cs_etm__is_svc_instr(etmq, trace_chan_id, prev_packet, + !cs_etm__is_svc_instr(etmq, tidq, prev_packet, prev_packet->end_addr)) return true; @@ -2228,7 +2260,6 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq, { struct cs_etm_packet *packet = tidq->packet; struct cs_etm_packet *prev_packet = tidq->prev_packet; - u8 trace_chan_id = tidq->trace_chan_id; u64 magic; int ret; @@ -2309,11 +2340,11 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq, if (prev_packet->flags == (PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT) && - cs_etm__is_svc_instr(etmq, trace_chan_id, - packet, packet->start_addr)) + cs_etm__is_svc_instr(etmq, tidq, packet, packet->start_addr)) { prev_packet->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET; + } break; case CS_ETM_DISCONTINUITY: /* @@ -2394,6 +2425,7 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq, PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT; break; + case CS_ETM_CONTEXT: case CS_ETM_EMPTY: default: break; @@ -2469,6 +2501,19 @@ static int cs_etm__process_traceid_queue(struct cs_etm_queue *etmq, */ cs_etm__sample(etmq, tidq); break; + case CS_ETM_CONTEXT: + /* + * Update context but don't swap packet. Keep the + * previous one for branch source address info, if + * tracing the kernel the context packet will be emitted + * between two ranges. + */ + ret = cs_etm__etmq_update_thread(etmq, tidq->packet->el, + tidq->packet->tid, + &tidq->frontend_thread); + if (ret) + goto out; + break; case CS_ETM_EXCEPTION: case CS_ETM_EXCEPTION_RET: /* @@ -2497,6 +2542,7 @@ static int cs_etm__process_traceid_queue(struct cs_etm_queue *etmq, } } +out: return ret; } @@ -2620,7 +2666,7 @@ static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm, if (!tidq) continue; - if (tid == -1 || thread__tid(tidq->thread) == tid) + if (tid == -1 || thread__tid(tidq->frontend_thread) == tid) cs_etm__run_per_thread_timeless_decoder(etmq); } else cs_etm__run_per_cpu_timeless_decoder(etmq); @@ -3328,7 +3374,7 @@ static int cs_etm__create_queue_decoders(struct cs_etm_queue *etmq) */ if (cs_etm_decoder__add_mem_access_cb(etmq->decoder, 0x0L, ((u64) -1L), - cs_etm__mem_access)) + cs_etm__decoder_mem_access)) goto out_free_decoder; zfree(&t_params); diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h index aa9bb4a32eca..b81099c2b301 100644 --- a/tools/perf/util/cs-etm.h +++ b/tools/perf/util/cs-etm.h @@ -158,6 +158,7 @@ enum cs_etm_sample_type { CS_ETM_DISCONTINUITY, CS_ETM_EXCEPTION, CS_ETM_EXCEPTION_RET, + CS_ETM_CONTEXT, }; enum cs_etm_isa { @@ -184,6 +185,8 @@ struct cs_etm_packet { u8 last_instr_size; u8 trace_chan_id; int cpu; + int el; + pid_t tid; }; #define CS_ETM_PACKET_MAX_BUFFER 1024 @@ -259,8 +262,9 @@ enum cs_etm_pid_fmt { #include int cs_etm__get_cpu(struct cs_etm_queue *etmq, u8 trace_chan_id, int *cpu); enum cs_etm_pid_fmt cs_etm__get_pid_fmt(struct cs_etm_queue *etmq); -int cs_etm__etmq_set_tid_el(struct cs_etm_queue *etmq, pid_t tid, - u8 trace_chan_id, ocsd_ex_level el); +int cs_etm__etmq_update_decode_context(struct cs_etm_queue *etmq, + u8 trace_chan_id, ocsd_ex_level el, + pid_t tid); bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq); void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq, u8 trace_chan_id); From d281fb9dfdaf30af4dfc68262b6b4997439a6aea Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:07 +0100 Subject: [PATCH 267/343] perf test: Add workload-ctl option Add a --workload-ctl=fifo:ctl-fifo[,ack-fifo] option for 'perf test -w'. When set, run_workload() opens the named FIFO, writes enable before invoking the builtin workload, writes disable before returning, and waits for ack responses when an ack FIFO is provided to ensure that the workload doesn't run until the events are enabled. This can be used to limit the scope of the recording to only the workload execution and avoid recording Perf setup and teardown code if Perf record is started with events disabled (-D 1). Assisted-by: Codex:GPT-5.5 Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Leo Yan Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-test.txt | 12 ++ tools/perf/tests/builtin-test.c | 184 ++++++++++++++++++++++++- 2 files changed, 194 insertions(+), 2 deletions(-) diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt index 32da0d1fa86a..2f4a91f5b9dc 100644 --- a/tools/perf/Documentation/perf-test.txt +++ b/tools/perf/Documentation/perf-test.txt @@ -69,3 +69,15 @@ OPTIONS --list-workloads:: List the available workloads to use with -w/--workload. + +--record-ctl=fifo:ctl-fifo[,ack-fifo]:: + This option is used to communicate with a perf record session in order + to control the recording scope to only the workload and avoid recording + setup and teardown code. When specifying this option, the same FIFO path + must be specified in the record session via: + + perf record -D -1 --control=fifo:ctl-fifo[,ack-fifo] ... + + Perf test sends 'enable' and 'disable' commands through ctl-fifo to + control event recording. If 'ack-fifo' is provided, the workload runner + waits for an 'ack' response after each command. diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index b64fc2204f22..86ea427eb0aa 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -56,6 +56,7 @@ static unsigned int runs_per_test = 1; static unsigned int failure_snippet_lines = 10; const char *dso_to_test; const char *test_objdump_path = "objdump"; +static const char *workload_control; /* * List of architecture specific tests. Not a weak symbol as the array length is @@ -168,6 +169,11 @@ static struct test_workload *workloads[] = { #endif }; +struct workload_control { + int ctl_fd; + int ack_fd; +}; + #define workloads__for_each(workload) \ for (unsigned i = 0; i < ARRAY_SIZE(workloads) && ({ workload = workloads[i]; 1; }); i++) @@ -1387,13 +1393,185 @@ static int workloads__fprintf_list(FILE *fp) return printed; } +static int perf_control_open_fifo(struct workload_control *ctl, const char *str) +{ + char *s, *p; + int ret; + + if (strncmp(str, "fifo:", 5)) + return -EINVAL; + + str += 5; + if (!*str || *str == ',') + return -EINVAL; + + s = strdup(str); + if (!s) + return -ENOMEM; + + p = strchr(s, ','); + if (p) + *p = '\0'; + + ctl->ctl_fd = open(s, O_WRONLY | O_CLOEXEC); + if (ctl->ctl_fd < 0) { + ret = -errno; + pr_err("Failed to open workload control FIFO '%s': %m\n", s); + free(s); + return ret; + } + + if (p && *++p) { + ctl->ack_fd = open(p, O_RDONLY | O_CLOEXEC); + if (ctl->ack_fd < 0) { + ret = -errno; + pr_err("Failed to open workload control ack FIFO '%s': %m\n", p); + close(ctl->ctl_fd); + ctl->ctl_fd = -1; + free(s); + return ret; + } + } + + free(s); + return 0; +} + +static int perf_control_open(struct workload_control *ctl) +{ + int ret; + + if (!workload_control) + return 0; + + ret = perf_control_open_fifo(ctl, workload_control); + + if (ret == -EINVAL) { + pr_err("Unsupported workload control spec '%s', expected fifo:ctl-fifo[,ack-fifo]\n", + workload_control); + } + + return ret; +} + +static void perf_control_close(struct workload_control *ctl) +{ + if (ctl->ctl_fd >= 0) { + close(ctl->ctl_fd); + ctl->ctl_fd = -1; + } + if (ctl->ack_fd >= 0) { + close(ctl->ack_fd); + ctl->ack_fd = -1; + } +} + +static int perf_control_write_cmd(int fd, const char *cmd) +{ + size_t len = strlen(cmd); + ssize_t ret; + + while (len) { + ret = write(fd, cmd, len); + if (ret < 0) { + if (errno == EINTR) + continue; + pr_err("Failed to write perf control command: %m\n"); + return -1; + } + + if (!ret) { + pr_err("Failed to write perf control command: short write\n"); + return -1; + } + + cmd += ret; + len -= ret; + } + + return 0; +} + +static int perf_control_read_ack(int fd) +{ + char buf[16]; + ssize_t ret; + + do { + ret = read(fd, buf, sizeof(buf) - 1); + } while (ret < 0 && errno == EINTR); + + if (ret < 0) { + pr_err("Failed to read perf control ack: %m\n"); + return -1; + } + + if (!ret) { + pr_err("Unexpected EOF while reading perf control ack\n"); + return -1; + } + + buf[ret] = '\0'; + for (ssize_t i = 0; i < ret; i++) { + if (buf[i] == '\n' || buf[i] == '\0') { + buf[i] = '\0'; + break; + } + } + + if (strcmp(buf, "ack")) { + pr_err("Unexpected perf control ack: %s\n", buf); + return -1; + } + + return 0; +} + +static int perf_control_send(struct workload_control *ctl, const char *cmd) +{ + if (ctl->ctl_fd < 0) + return 0; + + if (perf_control_write_cmd(ctl->ctl_fd, cmd)) + return -1; + + if (ctl->ack_fd >= 0 && perf_control_read_ack(ctl->ack_fd)) + return -1; + + return 0; +} + static int run_workload(const char *work, int argc, const char **argv) { struct test_workload *twl; workloads__for_each(twl) { - if (!strcmp(twl->name, work)) - return twl->func(argc, argv); + struct workload_control ctl = { + .ctl_fd = -1, + .ack_fd = -1, + }; + int control_ret, ret; + + if (strcmp(twl->name, work)) + continue; + + ret = perf_control_open(&ctl); + if (ret) + return ret; + + if (perf_control_send(&ctl, "enable\n")) { + perf_control_close(&ctl); + return -1; + } + + ret = twl->func(argc, argv); + + control_ret = perf_control_send(&ctl, "disable\n"); + perf_control_close(&ctl); + if (control_ret) + return -1; + + return ret; } pr_info("No workload found: %s\n", work); @@ -1486,6 +1664,8 @@ int cmd_test(int argc, const char **argv) OPT_UINTEGER('r', "runs-per-test", &runs_per_test, "Run each test the given number of times, default 1"), OPT_STRING('w', "workload", &workload, "work", "workload to run for testing, use '--list-workloads' to list the available ones."), + OPT_STRING(0, "record-ctl", &workload_control, "fifo:ctl-fifo[,ack-fifo]", + "Write enable to the fifo just before running the workload and disable after, with optional ack from ack-fifo"), OPT_BOOLEAN(0, "list-workloads", &list_workloads, "List the available builtin workloads to use with -w/--workload"), OPT_STRING(0, "dso", &dso_to_test, "dso", "dso to test"), OPT_STRING(0, "objdump", &test_objdump_path, "path", From 4cb5dd0379999af455941ab87d0b30c2ba7d9d66 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:08 +0100 Subject: [PATCH 268/343] perf test: Add a workload that forces context switches This workload launches two processes that block when reading and writing to each other forcing the other process to be scheduled for each read/write pair. Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Leo Yan Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-test.txt | 7 +- tools/perf/tests/builtin-test.c | 1 + tools/perf/tests/tests.h | 1 + tools/perf/tests/workloads/Build | 1 + .../tests/workloads/context_switch_loop.c | 110 ++++++++++++++++++ 5 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 tools/perf/tests/workloads/context_switch_loop.c diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt index 2f4a91f5b9dc..213eb62603eb 100644 --- a/tools/perf/Documentation/perf-test.txt +++ b/tools/perf/Documentation/perf-test.txt @@ -55,15 +55,16 @@ OPTIONS -w:: --workload=:: - Run a built-in workload, to list them use '--list-workloads', current ones include: - noploop, thloop, leafloop, sqrtloop, brstack, datasym and landlock. + Run a built-in workload, to list them use '--list-workloads', current + ones include: noploop, thloop, leafloop, sqrtloop, brstack, datasym, + context_switch_loop and landlock. Used with the shell script regression tests. Some accept an extra parameter: seconds: leafloop, noploop, sqrtloop, thloop - nrloops: brstack + nrloops: brstack, context_switch_loop The datasym and landlock workloads don't accept any. diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 86ea427eb0aa..9284f897de3c 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -163,6 +163,7 @@ static struct test_workload *workloads[] = { &workload__traploop, &workload__inlineloop, &workload__jitdump, + &workload__context_switch_loop, #ifdef HAVE_RUST_SUPPORT &workload__code_with_type, diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index bf8ff7d54727..7cd4da4e96d3 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -245,6 +245,7 @@ DECLARE_WORKLOAD(landlock); DECLARE_WORKLOAD(traploop); DECLARE_WORKLOAD(inlineloop); DECLARE_WORKLOAD(jitdump); +DECLARE_WORKLOAD(context_switch_loop); #ifdef HAVE_RUST_SUPPORT DECLARE_WORKLOAD(code_with_type); diff --git a/tools/perf/tests/workloads/Build b/tools/perf/tests/workloads/Build index 0eb6d99528eb..7134a031cb7c 100644 --- a/tools/perf/tests/workloads/Build +++ b/tools/perf/tests/workloads/Build @@ -10,6 +10,7 @@ perf-test-y += landlock.o perf-test-y += traploop.o perf-test-y += inlineloop.o perf-test-y += jitdump.o +perf-test-y += context_switch_loop.o ifeq ($(CONFIG_RUST_SUPPORT),y) perf-test-y += code_with_type.o diff --git a/tools/perf/tests/workloads/context_switch_loop.c b/tools/perf/tests/workloads/context_switch_loop.c new file mode 100644 index 000000000000..5431af6147e6 --- /dev/null +++ b/tools/perf/tests/workloads/context_switch_loop.c @@ -0,0 +1,110 @@ + +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include + +#include "../tests.h" + +static int loops = 100; +static char buf; +int context_switch_loop_work = 1234; + +#define write_block(fd) \ + do { \ + if (write(fd, &buf, 1) <= 0) \ + return 1; \ + } while (0) + +#define read_block(fd) \ + do { \ + if (read(fd, &buf, 1) <= 0) \ + return 1; \ + } while (0) + +/* Not static to avoid LTO clobbering the function name */ +int context_switch_loop_proc1(int in_fd, int out_fd); +int context_switch_loop_proc1(int in_fd, int out_fd) +{ + for (int i = 0; i < loops; i++) { + read_block(in_fd); + context_switch_loop_work += i * 3; + write_block(out_fd); + } + return 0; +} + +int context_switch_loop_proc2(int in_fd, int out_fd); +int context_switch_loop_proc2(int in_fd, int out_fd) +{ + for (int i = 0; i < loops; i++) { + write_block(out_fd); + context_switch_loop_work += i * 7; + read_block(in_fd); + } + return 0; +} + +/* + * Launches two processes that take turns to execute a multiplication N times + */ +static int context_switch_loop(int argc, const char **argv) +{ + int a_to_b[2], b_to_a[2]; + pid_t proc1_pid; + int status; + int ret; + + if (argc > 0) { + loops = atoi(argv[0]); + if (loops < 0) { + fprintf(stderr, "Invalid number of loops: %s\n", argv[0]); + return 1; + } + } + + if (pipe(a_to_b) || pipe(b_to_a)) { + perror("Pipe error"); + return 1; + } + + proc1_pid = fork(); + if (proc1_pid < 0) { + perror("Fork error"); + return 1; + } + + if (!proc1_pid) { + close(a_to_b[0]); + close(b_to_a[1]); + prctl(PR_SET_NAME, "proc1", 0, 0, 0); + ret = context_switch_loop_proc1(b_to_a[0], a_to_b[1]); + close(a_to_b[1]); + close(b_to_a[0]); + exit(ret); + } + + close(a_to_b[1]); + close(b_to_a[0]); + prctl(PR_SET_NAME, "proc2", 0, 0, 0); + ret = context_switch_loop_proc2(a_to_b[0], b_to_a[1]); + close(a_to_b[0]); + close(b_to_a[1]); + + if (ret) { + kill(proc1_pid, SIGKILL); + return ret; + } + + if (waitpid(proc1_pid, &status, 0) != proc1_pid || !WIFEXITED(status) || + WEXITSTATUS(status)) + return 1; + + return 0; +} + +DEFINE_WORKLOAD(context_switch_loop); From be7ef892f306fc9bb07e2d1a0699de14159fe219 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:09 +0100 Subject: [PATCH 269/343] perf test cs-etm: Test process attribution Run the context switch workload on one CPU and trace it to test that symbols are attributed to the correct process and that the attribution changes at the exact point that the context switch happened. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- .../shell/coresight/context_switch_thread.sh | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 tools/perf/tests/shell/coresight/context_switch_thread.sh diff --git a/tools/perf/tests/shell/coresight/context_switch_thread.sh b/tools/perf/tests/shell/coresight/context_switch_thread.sh new file mode 100755 index 000000000000..2b9c44b86c59 --- /dev/null +++ b/tools/perf/tests/shell/coresight/context_switch_thread.sh @@ -0,0 +1,69 @@ +#!/bin/bash -e +# CoreSight context switch thread attribution (exclusive) + +# SPDX-License-Identifier: GPL-2.0 + +# If CoreSight is not available, skip the test +perf list pmu | grep -q cs_etm || exit 2 + +if [ "$(id -u)" != 0 ]; then + # Requires root for "-C 0" in record command + echo "[Skip] No root permission" + exit 2 +fi + +tmpdir=$(mktemp -d /tmp/__perf_test.coresight_context_switch.XXXXX) + +cleanup() { + rm -rf "${tmpdir}" + trap - EXIT TERM INT +} + +trap_cleanup() { + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +check_samples() { + owner_samples=$(grep -c "proc1.*context_switch_loop_proc1" "$tmpdir/script" || true) + next_samples=$(grep -c "proc2.*context_switch_loop_proc2" "$tmpdir/script" || true) + + if [ "$owner_samples" -eq 0 ] || [ "$next_samples" -eq 0 ]; then + echo "No samples found" + cleanup + exit 1 + fi + + if grep "proc2.*context_switch_loop_proc1" "$tmpdir/script"; then + echo "Thread1 symbol was attributed to proc2" + cleanup + exit 1 + fi + + if grep "proc1.*context_switch_loop_proc2" "$tmpdir/script"; then + echo "Thread2 symbol was attributed to proc1" + cleanup + exit 1 + fi +} + +cf="$tmpdir/ctl" +af="$tmpdir/ack" +mkfifo "$cf" "$af" + +# Pin to one CPU so the two threads alternate running but record into the same +# trace buffer. Start disabled and use the control FIFO to only record the +# workload and not startup. +perf record -o "$tmpdir/data" -e cs_etm/timestamp=0/u -C 0 -D -1 --control fifo:"$cf","$af" -- \ + taskset --cpu-list 0 perf test --record-ctl fifo:"$cf","$af" \ + -w context_switch_loop > /dev/null 2>&1 + +# Test both instruction and branch sample generation modes. +perf script -i "$tmpdir/data" --itrace=i4 -F comm,pid,tid,ip,sym > "$tmpdir/script" 2>/dev/null +check_samples +perf script -i "$tmpdir/data" --itrace=b -F comm,pid,tid,ip,sym > "$tmpdir/script" 2>/dev/null +check_samples + +cleanup +exit 0 From 3fdf30607e28290d914c44b035f35a9a92512562 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:10 +0100 Subject: [PATCH 270/343] perf test: Add deterministic workload Add a workload that does the same thing every time for testing CPU trace decoding. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-test.txt | 4 +-- tools/perf/tests/builtin-test.c | 1 + tools/perf/tests/tests.h | 1 + tools/perf/tests/workloads/Build | 2 ++ tools/perf/tests/workloads/deterministic.c | 39 ++++++++++++++++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tools/perf/tests/workloads/deterministic.c diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt index 213eb62603eb..c50a4b2d2d29 100644 --- a/tools/perf/Documentation/perf-test.txt +++ b/tools/perf/Documentation/perf-test.txt @@ -57,7 +57,7 @@ OPTIONS --workload=:: Run a built-in workload, to list them use '--list-workloads', current ones include: noploop, thloop, leafloop, sqrtloop, brstack, datasym, - context_switch_loop and landlock. + context_switch_loop, deterministic and landlock. Used with the shell script regression tests. @@ -66,7 +66,7 @@ OPTIONS seconds: leafloop, noploop, sqrtloop, thloop nrloops: brstack, context_switch_loop - The datasym and landlock workloads don't accept any. + The datasym, landlock and deterministic workloads don't accept any. --list-workloads:: List the available workloads to use with -w/--workload. diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 9284f897de3c..ef7e3f52a383 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -164,6 +164,7 @@ static struct test_workload *workloads[] = { &workload__inlineloop, &workload__jitdump, &workload__context_switch_loop, + &workload__deterministic, #ifdef HAVE_RUST_SUPPORT &workload__code_with_type, diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 7cd4da4e96d3..bcfe9c33fc66 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -246,6 +246,7 @@ DECLARE_WORKLOAD(traploop); DECLARE_WORKLOAD(inlineloop); DECLARE_WORKLOAD(jitdump); DECLARE_WORKLOAD(context_switch_loop); +DECLARE_WORKLOAD(deterministic); #ifdef HAVE_RUST_SUPPORT DECLARE_WORKLOAD(code_with_type); diff --git a/tools/perf/tests/workloads/Build b/tools/perf/tests/workloads/Build index 7134a031cb7c..90f2d8aa4941 100644 --- a/tools/perf/tests/workloads/Build +++ b/tools/perf/tests/workloads/Build @@ -11,6 +11,7 @@ perf-test-y += traploop.o perf-test-y += inlineloop.o perf-test-y += jitdump.o perf-test-y += context_switch_loop.o +perf-test-y += deterministic.o ifeq ($(CONFIG_RUST_SUPPORT),y) perf-test-y += code_with_type.o @@ -23,3 +24,4 @@ CFLAGS_brstack.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE CFLAGS_datasym.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE CFLAGS_traploop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE CFLAGS_inlineloop.o = -g -O2 +CFLAGS_deterministic.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE diff --git a/tools/perf/tests/workloads/deterministic.c b/tools/perf/tests/workloads/deterministic.c new file mode 100644 index 000000000000..8a78519fd075 --- /dev/null +++ b/tools/perf/tests/workloads/deterministic.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include "../tests.h" + +int dt_work = 1234; + +static void function1(void) +{ + dt_work += 7; + dt_work += 7; + dt_work += 7; +} + +static void function2(void) +{ + dt_work += 7; + dt_work += 7; + dt_work += 7; +} + +static int deterministic(int argc __maybe_unused, + const char **argv __maybe_unused) +{ + dt_work += 7; + dt_work += 7; + dt_work += 7; + + function1(); + + dt_work += 7; + dt_work += 7; + dt_work += 7; + + function2(); + + return 0; +} + +DEFINE_WORKLOAD(deterministic); From ccf62a267a660cbc2c5ca0208a94fee4ef256926 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:11 +0100 Subject: [PATCH 271/343] perf test cs-etm: Replace unroll loop thread with deterministic decode test Testing a long sequence without branches seems like it would be better as a decoder unit test, and this test doesn't test decoding either, so it's not clear what bugs this is trying to catch. The new deterministic workload has somewhat long sequences when built unoptimized, and we can always increase them later if we want to. But now we test that decoding always gives the same result for the same sequence of code which we've never had before. Signed-off-by: James Clark Tested-by: Leo Yan Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- .../tests/shell/coresight/deterministic.sh | 72 +++++++++++++++++++ .../shell/coresight/unroll_loop_thread_10.sh | 22 ------ 2 files changed, 72 insertions(+), 22 deletions(-) create mode 100755 tools/perf/tests/shell/coresight/deterministic.sh delete mode 100755 tools/perf/tests/shell/coresight/unroll_loop_thread_10.sh diff --git a/tools/perf/tests/shell/coresight/deterministic.sh b/tools/perf/tests/shell/coresight/deterministic.sh new file mode 100755 index 000000000000..75d4973056f0 --- /dev/null +++ b/tools/perf/tests/shell/coresight/deterministic.sh @@ -0,0 +1,72 @@ +#!/bin/bash -e +# CoreSight deterministic workload decode (exclusive) + +# SPDX-License-Identifier: GPL-2.0 + +# If CoreSight is not available, skip the test +perf list pmu | grep -q cs_etm || exit 2 + +tmpdir=$(mktemp -d /tmp/__perf_test.coresight_deterministic.XXXXX) + +cleanup() { + rm -rf "${tmpdir}" + trap - EXIT TERM INT +} + +trap_cleanup() { + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +cf="$tmpdir/ctl" +af="$tmpdir/ack" +mkfifo "$cf" "$af" + +# Start disabled and use the control FIFO to only record the workload and not +# startup. +perf record -o "$tmpdir/data" -e cs_etm//u -D -1 --control fifo:"$cf","$af" -- \ + perf test --record-ctl fifo:"$cf","$af" -w deterministic > /dev/null 2>&1 + +perf script -i "$tmpdir/data" --itrace=i1i -F ip,srcline | \ + grep "deterministic.c" | uniq > "$tmpdir/script" 2>/dev/null + + +# Remove brace lines and call sites as they may not be hit or may have +# extra hits after returning, depending on the compiler. +sed -i \ + -e '/deterministic.c:8$/d' \ + -e '/deterministic.c:12$/d' \ + -e '/deterministic.c:15$/d' \ + -e '/deterministic.c:19$/d' \ + -e '/deterministic.c:23$/d' \ + -e '/deterministic.c:28$/d' \ + -e '/deterministic.c:34$/d' \ + -e '/deterministic.c:36$/d' \ + -e '/deterministic.c:37$/d' \ + "$tmpdir/script" + +cat > "$tmpdir/expected" << EOF + deterministic.c:24 + deterministic.c:25 + deterministic.c:26 + deterministic.c:9 + deterministic.c:10 + deterministic.c:11 + deterministic.c:30 + deterministic.c:31 + deterministic.c:32 + deterministic.c:16 + deterministic.c:17 + deterministic.c:18 +EOF + +if ! diff -q "$tmpdir/script" "$tmpdir/expected"; then + echo "FAIL: line numbers don't match expected: " + head -n 100 "$tmpdir/script" + cleanup + exit 1 +fi + +cleanup +exit 0 diff --git a/tools/perf/tests/shell/coresight/unroll_loop_thread_10.sh b/tools/perf/tests/shell/coresight/unroll_loop_thread_10.sh deleted file mode 100755 index cb3e97a0a89f..000000000000 --- a/tools/perf/tests/shell/coresight/unroll_loop_thread_10.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -e -# CoreSight / Unroll Loop Thread 10 (exclusive) - -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 - -TEST="unroll_loop_thread" - -# shellcheck source=../lib/coresight.sh -. "$(dirname $0)"/../lib/coresight.sh - -ARGS="10" -DATV="10" -# shellcheck disable=SC2153 -DATA="$DATD/perf-$TEST-$DATV.data" - -perf record $PERFRECOPT -o "$DATA" "$BIN" $ARGS - -perf_dump_aux_verify "$DATA" 10 10 10 - -err=$? -exit $err From f6708947e686281400e0c026f0d2c58d83a8c0e0 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:12 +0100 Subject: [PATCH 272/343] perf test cs-etm: Remove asm_pure_loop test It's not obvious what this test is for so remove it. It's not a stress test because it doesn't output lots of data and it's not a functional test because it only looks for raw trace output. It seems to imply that a program written in assembly influences whether trace would be generated by the CPU or not, but the CPU doesn't know what language the program is written in. We already have lots of Coresight tests that test the full pipeline including decoding, and in many more modes of operation than this one, so if no trace was collected they will already fail leaving this one redundant. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- .../tests/shell/coresight/asm_pure_loop.sh | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100755 tools/perf/tests/shell/coresight/asm_pure_loop.sh diff --git a/tools/perf/tests/shell/coresight/asm_pure_loop.sh b/tools/perf/tests/shell/coresight/asm_pure_loop.sh deleted file mode 100755 index 0301904b9637..000000000000 --- a/tools/perf/tests/shell/coresight/asm_pure_loop.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -e -# CoreSight / ASM Pure Loop (exclusive) - -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 - -TEST="asm_pure_loop" - -# shellcheck source=../lib/coresight.sh -. "$(dirname $0)"/../lib/coresight.sh - -ARGS="" -DATV="out" -# shellcheck disable=SC2153 -DATA="$DATD/perf-$TEST-$DATV.data" - -perf record $PERFRECOPT -o "$DATA" "$BIN" $ARGS - -perf_dump_aux_verify "$DATA" 10 10 10 - -err=$? -exit $err From 6948b32c3a74706a1da451191b1d792615f3f91d Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:13 +0100 Subject: [PATCH 273/343] perf test cs-etm: Replace memcpy test with raw dump stress test Like asm_pure_loop, this memcpy test only checks that 10 of each of a few trace packet types occur after recording a lot of trace, which isn't more specific than other existing Coresight tests. Assume it was supposed to be a stress test for dumping and replace it with one that doesn't require a custom binary and checks for a specific amount of raw output. Don't bother checking for packets because the other tests that test decoding will catch issues with malformed data. This also adds coverage for exit snapshot mode which was missing. Signed-off-by: James Clark Tested-by: Leo Yan Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- .../shell/coresight/memcpy_thread_16k_10.sh | 22 ------- .../tests/shell/coresight/raw_dump_stress.sh | 65 +++++++++++++++++++ 2 files changed, 65 insertions(+), 22 deletions(-) delete mode 100755 tools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh create mode 100755 tools/perf/tests/shell/coresight/raw_dump_stress.sh diff --git a/tools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh b/tools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh deleted file mode 100755 index 1f765d69acc3..000000000000 --- a/tools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -e -# CoreSight / Memcpy 16k 10 Threads (exclusive) - -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 - -TEST="memcpy_thread" - -# shellcheck source=../lib/coresight.sh -. "$(dirname $0)"/../lib/coresight.sh - -ARGS="16 10 1" -DATV="16k_10" -# shellcheck disable=SC2153 -DATA="$DATD/perf-$TEST-$DATV.data" - -perf record $PERFRECOPT -o "$DATA" "$BIN" $ARGS - -perf_dump_aux_verify "$DATA" 10 10 10 - -err=$? -exit $err diff --git a/tools/perf/tests/shell/coresight/raw_dump_stress.sh b/tools/perf/tests/shell/coresight/raw_dump_stress.sh new file mode 100755 index 000000000000..bea70d825596 --- /dev/null +++ b/tools/perf/tests/shell/coresight/raw_dump_stress.sh @@ -0,0 +1,65 @@ +#!/bin/bash -e +# CoreSight raw dump stress (exclusive) + +# SPDX-License-Identifier: GPL-2.0 + +if [ "$(id -u)" != 0 ]; then + # Requires root for larger buffer size + echo "[Skip] No root permission" + exit 2 +fi + +# If CoreSight is not available, skip the test +perf list pmu | grep -q cs_etm || exit 2 + +tmpdir=$(mktemp -d /tmp/__perf_test.coresight_raw_dump_stress.XXXXX) + +cleanup() { + rm -r "${tmpdir}" + trap - EXIT TERM INT +} + +trap_cleanup() { + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +# Use exit snapshot to record 2M of trace to make about 80MB of raw dump data. +echo "Recording..." +perf record -e cs_etm/timestamp=0/u -m,2M -Se -o "$tmpdir/data" -- \ + perf test -w brstack 20000 > /dev/null 2>&1 + +# Test raw dump runs to completion but don't decode because that's too slow for +# a test +echo "Dumping raw trace..." +perf report --dump-raw-trace -i "$tmpdir/data" 2>/dev/null > "$tmpdir/rawdump" + +# Get the size and offset of the first AUXTRACE buffer and the index of the last +# packet in the raw dump. +read -r size offset last_idx <<< "$(awk ' + found && /PERF_RECORD_/ { exit } + /PERF_RECORD_AUXTRACE / { found = 1; size = $7; offset = $9; next } + found && /Idx:/ { last_idx = $1; gsub(/Idx:|;/, "", last_idx) } + END { if (last_idx) print size, offset, last_idx } +' "$tmpdir/rawdump")" + +# The last Idx minus start offset should equal the size of the buffer if +# everything was dumped. Allow 48 bytes difference to cover 3 frames: current +# frame length, a partial frame and a final empty one, all of which aren't +# dumped. +# +# TODO: for a single snapshot, offset should always be zero. However, we +# currently output AUX records in snapshot mode when we shouldn't, which +# increments the offset. Allow for that until it's fixed so we can test raw +# dumping. +decode_size=$((1 + last_idx - offset)) +if [ "$decode_size" -gt "$((size - 48))" ] && [ "$decode_size" -le "$((size))" ]; then + echo "PASS: AUXTRACE buffer length matches dumped packet index" + cleanup + exit 0 +fi + +echo "FAIL: AUXTRACE buffer length mismatch: size=$size offset=$offset last_idx=$last_idx decode_size=$decode_size" +cleanup +exit 1 From 2540d48595b9289f1fe6288e080c329a0fd7ce47 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:14 +0100 Subject: [PATCH 274/343] perf test: Add named_threads workload Add a workload that runs X threads that run a unique function named "named_threads_thread[x]" which performs a multiplication in a loop for Y loops. Each thread sets its name to "thread[x]". This can be used to test that processor trace decoding handles concurrent threads correctly and the correct symbols and thread names are assigned to samples. Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Leo Yan Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-test.txt | 5 +- tools/perf/tests/builtin-test.c | 1 + tools/perf/tests/tests.h | 1 + tools/perf/tests/workloads/Build | 1 + tools/perf/tests/workloads/named_threads.c | 109 +++++++++++++++++++++ 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 tools/perf/tests/workloads/named_threads.c diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt index c50a4b2d2d29..81c8525f5946 100644 --- a/tools/perf/Documentation/perf-test.txt +++ b/tools/perf/Documentation/perf-test.txt @@ -57,7 +57,7 @@ OPTIONS --workload=:: Run a built-in workload, to list them use '--list-workloads', current ones include: noploop, thloop, leafloop, sqrtloop, brstack, datasym, - context_switch_loop, deterministic and landlock. + context_switch_loop, deterministic, named_threads and landlock. Used with the shell script regression tests. @@ -66,6 +66,9 @@ OPTIONS seconds: leafloop, noploop, sqrtloop, thloop nrloops: brstack, context_switch_loop + 'named_threads' accepts the number of threads and the number of loops to + do in each thread. + The datasym, landlock and deterministic workloads don't accept any. --list-workloads:: diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index ef7e3f52a383..afc06cec4954 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -155,6 +155,7 @@ static struct test_suite *generic_tests[] = { static struct test_workload *workloads[] = { &workload__noploop, &workload__thloop, + &workload__named_threads, &workload__leafloop, &workload__sqrtloop, &workload__brstack, diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index bcfe9c33fc66..7cedf05be544 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -237,6 +237,7 @@ struct test_workload workload__##work = { \ /* The list of test workloads */ DECLARE_WORKLOAD(noploop); DECLARE_WORKLOAD(thloop); +DECLARE_WORKLOAD(named_threads); DECLARE_WORKLOAD(leafloop); DECLARE_WORKLOAD(sqrtloop); DECLARE_WORKLOAD(brstack); diff --git a/tools/perf/tests/workloads/Build b/tools/perf/tests/workloads/Build index 90f2d8aa4941..75b377934a0e 100644 --- a/tools/perf/tests/workloads/Build +++ b/tools/perf/tests/workloads/Build @@ -2,6 +2,7 @@ perf-test-y += noploop.o perf-test-y += thloop.o +perf-test-y += named_threads.o perf-test-y += leafloop.o perf-test-y += sqrtloop.o perf-test-y += brstack.o diff --git a/tools/perf/tests/workloads/named_threads.c b/tools/perf/tests/workloads/named_threads.c new file mode 100644 index 000000000000..d051d41a3cfe --- /dev/null +++ b/tools/perf/tests/workloads/named_threads.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include "../tests.h" + +#define MAX_THREADS 25 + +static int iterations = 500; +int named_threads_work = 1234; + +typedef void *(*thread_fn_t)(void *); + +#define DEFINE_THREAD(n) \ +noinline void *named_threads_thread##n(void *arg __maybe_unused) \ +{ \ + pthread_setname_np(pthread_self(), "thread" #n); \ + for (int i = 0; i < iterations; i++) \ + named_threads_work += 3; \ + \ + return NULL; \ +} + +#define THREAD_LIST(macro) \ + macro(1) \ + macro(2) \ + macro(3) \ + macro(4) \ + macro(5) \ + macro(6) \ + macro(7) \ + macro(8) \ + macro(9) \ + macro(10) \ + macro(11) \ + macro(12) \ + macro(13) \ + macro(14) \ + macro(15) \ + macro(16) \ + macro(17) \ + macro(18) \ + macro(19) \ + macro(20) \ + macro(21) \ + macro(22) \ + macro(23) \ + macro(24) \ + macro(25) + +#define DECLARE_THREAD(n) void *named_threads_thread##n(void *arg); + +THREAD_LIST(DECLARE_THREAD) +THREAD_LIST(DEFINE_THREAD) + +#define THREAD_ENTRY(n) named_threads_thread##n, + +static thread_fn_t thread_fns[MAX_THREADS] = { + THREAD_LIST(THREAD_ENTRY) +}; + +/* + * Creates argv[0] threads that run a unique function named "thread[x]" which performs + * a multiplication in a loop for argv[1] loops. + */ +static int named_threads(int argc, const char **argv) +{ + pthread_t threads[MAX_THREADS]; + int nr_threads = 1; + int err = 0; + + if (argc > 0) + nr_threads = atoi(argv[0]); + + if (nr_threads <= 0 || nr_threads > MAX_THREADS) { + fprintf(stderr, "Error: num threads must be 1 - %d\n", MAX_THREADS); + return 1; + } + + if (argc > 1) + iterations = atoi(argv[1]); + + if (iterations < 0) { + fprintf(stderr, "Error: iterations must be non-negative\n"); + return 1; + } + + for (int i = 0; i < nr_threads; i++) { + int ret; + + ret = pthread_create(&threads[i], NULL, thread_fns[i], NULL); + if (ret) { + fprintf(stderr, "Error: failed to create thread%d: %s\n", + i + 1, strerror(ret)); + return 1; + } + } + + for (int i = 0; i < nr_threads; i++) + pthread_join(threads[i], NULL); + + return err; +} + +DEFINE_WORKLOAD(named_threads); From 0b6d6376d7408130b1b3840a948e1a250a02c547 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:15 +0100 Subject: [PATCH 275/343] perf test cs-etm: Test decoding for concurrent threads test The thread_loop test only looks for context IDs in the raw trace. There's a lot more that can go wrong when decoding these, so replace it with a test that looks at the final output for matching thread names and symbols. In the future we might use timestamps and context switch events to track threads, so looking at context IDs in the raw trace wouldn't always work. Reviewed-by: Leo Yan Signed-off-by: James Clark Tested-by: Leo Yan Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- .../shell/coresight/concurrent_threads.sh | 45 +++++++++++++++++++ .../coresight/thread_loop_check_tid_10.sh | 23 ---------- .../coresight/thread_loop_check_tid_2.sh | 23 ---------- 3 files changed, 45 insertions(+), 46 deletions(-) create mode 100755 tools/perf/tests/shell/coresight/concurrent_threads.sh delete mode 100755 tools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh delete mode 100755 tools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh diff --git a/tools/perf/tests/shell/coresight/concurrent_threads.sh b/tools/perf/tests/shell/coresight/concurrent_threads.sh new file mode 100755 index 000000000000..3349fff8c767 --- /dev/null +++ b/tools/perf/tests/shell/coresight/concurrent_threads.sh @@ -0,0 +1,45 @@ +#!/bin/bash -e +# CoreSight concurrent threads (exclusive) + +# SPDX-License-Identifier: GPL-2.0 + +# If CoreSight is not available, skip the test +perf list pmu | grep -q cs_etm || exit 2 + +tmpdir=$(mktemp -d /tmp/__perf_test.coresight_concurrent_threads.XXXXX) + +cleanup() { + rm -rf "${tmpdir}" + trap - EXIT TERM INT +} + +trap_cleanup() { + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +cf="$tmpdir/ctl" +af="$tmpdir/ack" +mkfifo "$cf" "$af" + +nthreads=10 + +# Timestamps off to reduce trace size, start disabled and use the control FIFO +# to only record the workload and not startup. +perf record -o "$tmpdir/data" -e cs_etm/timestamp=0/u -D -1 --control fifo:"$cf","$af" \ + -- perf test --record-ctl fifo:"$cf","$af" -w named_threads $nthreads 1 > /dev/null 2>&1 + +perf script -i "$tmpdir/data" > "$tmpdir/script" 2>/dev/null + +# Check all threads were traced and they have the correct thread name and symbol +for i in $(seq 1 $nthreads); do + if ! grep -q "thread${i} .* named_threads_thread${i}" "$tmpdir/script"; then + echo "Error: thread${i} missing" >&2 + cleanup + exit 1 + fi +done + +cleanup +exit 0 diff --git a/tools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh b/tools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh deleted file mode 100755 index 7f43a93a2ac2..000000000000 --- a/tools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -e -# CoreSight / Thread Loop 10 Threads - Check TID (exclusive) - -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 - -TEST="thread_loop" - -# shellcheck source=../lib/coresight.sh -. "$(dirname $0)"/../lib/coresight.sh - -ARGS="10 1" -DATV="check-tid-10th" -# shellcheck disable=SC2153 -DATA="$DATD/perf-$TEST-$DATV.data" -STDO="$DATD/perf-$TEST-$DATV.stdout" - -SHOW_TID=1 perf record -s $PERFRECOPT -o "$DATA" "$BIN" $ARGS > $STDO - -perf_dump_aux_tid_verify "$DATA" "$STDO" - -err=$? -exit $err diff --git a/tools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh b/tools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh deleted file mode 100755 index a94d2079ed06..000000000000 --- a/tools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -e -# CoreSight / Thread Loop 2 Threads - Check TID (exclusive) - -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 - -TEST="thread_loop" - -# shellcheck source=../lib/coresight.sh -. "$(dirname $0)"/../lib/coresight.sh - -ARGS="2 20" -DATV="check-tid-2th" -# shellcheck disable=SC2153 -DATA="$DATD/perf-$TEST-$DATV.data" -STDO="$DATD/perf-$TEST-$DATV.stdout" - -SHOW_TID=1 perf record -s $PERFRECOPT -o "$DATA" "$BIN" $ARGS > $STDO - -perf_dump_aux_tid_verify "$DATA" "$STDO" - -err=$? -exit $err From f8fabdccdeb4adea3b29e2678bf8289f477f6763 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:16 +0100 Subject: [PATCH 276/343] perf test cs-etm: Remove duplicate branch tests We already test branch output in perf script mode, but then retest it in Perf report mode. This is more of a test of Perf itself than Coresight because Perf uses the same samples to generate both outputs. Also we're already testing instruction output in Perf report mode. Remove this test for a speedup. On the systemwide test also remove the Perf report test because systemwide mode records a lot more data so running multiple tests on it has a big runtime impact. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/test_arm_coresight.sh | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh index bbf89e944e7b..39553702c1f3 100755 --- a/tools/perf/tests/shell/test_arm_coresight.sh +++ b/tools/perf/tests/shell/test_arm_coresight.sh @@ -52,17 +52,6 @@ perf_script_branch_samples() { grep -E " +$1 +[0-9]+ .* +branches:(.*:)? +" > /dev/null 2>&1 } -perf_report_branch_samples() { - echo "Looking at perf.data file for reporting branch samples:" - - # Below is an example of the branch samples reporting: - # 73.04% 73.04% touch libc-2.27.so [.] _dl_addr - # 7.71% 7.71% touch libc-2.27.so [.] getenv - # 2.59% 2.59% touch ld-2.27.so [.] strcmp - perf report --stdio -i ${perfdata} 2>&1 | \ - grep -E " +[0-9]+\.[0-9]+% +[0-9]+\.[0-9]+% +$1 " > /dev/null 2>&1 -} - perf_report_instruction_samples() { echo "Looking at perf.data file for instruction samples:" @@ -123,7 +112,6 @@ arm_cs_iterate_devices() { record_touch_file $device_name $2 && perf_script_branch_samples touch && - perf_report_branch_samples touch && perf_report_instruction_samples touch err=$? @@ -154,9 +142,7 @@ arm_cs_etm_system_wide_test() { # System-wide mode should include perf samples so test for that # instead of ls - perf_script_branch_samples perf && - perf_report_branch_samples perf && - perf_report_instruction_samples perf + perf_script_branch_samples perf err=$? arm_cs_report "CoreSight system wide testing" $err @@ -179,7 +165,6 @@ arm_cs_etm_snapshot_test() { wait $PERFPID perf_script_branch_samples dd && - perf_report_branch_samples dd && perf_report_instruction_samples dd err=$? @@ -191,7 +176,6 @@ arm_cs_etm_basic_test() { perf record -o ${perfdata} "$@" -m,8M -- ls > /dev/null 2>&1 perf_script_branch_samples ls && - perf_report_branch_samples ls && perf_report_instruction_samples ls err=$? From ac390ed34317144589cc8b6b374dbed137c7f076 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:17 +0100 Subject: [PATCH 277/343] perf test cs-etm: Skip if not root Use the common idiom for skipping tests if not running as root, which is required for these tests. Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Leo Yan Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/test_arm_coresight.sh | 6 ++++++ tools/perf/tests/shell/test_arm_coresight_disasm.sh | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh index 39553702c1f3..8ed2c934c87d 100755 --- a/tools/perf/tests/shell/test_arm_coresight.sh +++ b/tools/perf/tests/shell/test_arm_coresight.sh @@ -20,6 +20,12 @@ skip_if_no_cs_etm_event() { skip_if_no_cs_etm_event || exit 2 +if [ "$(id -u)" != 0 ]; then + # Requires root for -C and system wide tests + echo "[Skip] No root permission" + exit 2 +fi + perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) file=$(mktemp /tmp/temporary_file.XXXXX) diff --git a/tools/perf/tests/shell/test_arm_coresight_disasm.sh b/tools/perf/tests/shell/test_arm_coresight_disasm.sh index 0dfb4fadf531..339ae4831868 100755 --- a/tools/perf/tests/shell/test_arm_coresight_disasm.sh +++ b/tools/perf/tests/shell/test_arm_coresight_disasm.sh @@ -42,7 +42,7 @@ sep="\s\|\s" branch_search="\sbl${sep}b${sep}b.ne${sep}b.eq${sep}cbz\s" ## Test kernel ## -if [ -e /proc/kcore ]; then +if [ "$(id -u)" == 0 ] && [ -e /proc/kcore ]; then echo "Testing kernel disassembly" perf record -o ${perfdata} -e cs_etm//k --kcore -- touch $file > /dev/null 2>&1 perf script -i ${perfdata} -s python:${script_path} -- \ @@ -50,8 +50,8 @@ if [ -e /proc/kcore ]; then grep -q -e ${branch_search} ${file} echo "Found kernel branches" else - # kcore is required for correct kernel decode due to runtime code patching - echo "No kcore, skipping kernel test" + # Root and kcore are required for correct kernel decode due to runtime code patching + echo "No root or kcore, skipping kernel test" fi ## Test user ## From c13fe5f07518526416284d63acc1c50af88b03e3 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:18 +0100 Subject: [PATCH 278/343] perf test cs-etm: Reduce snapshot size The default buffer size for root is 4MB which is very slow to decode. We only need a few KB to verify that the dd process is hit so reduce the size to 128KB. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/test_arm_coresight.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh index 8ed2c934c87d..da2f599393e2 100755 --- a/tools/perf/tests/shell/test_arm_coresight.sh +++ b/tools/perf/tests/shell/test_arm_coresight.sh @@ -156,7 +156,7 @@ arm_cs_etm_system_wide_test() { arm_cs_etm_snapshot_test() { echo "Recording trace with snapshot mode" - perf record -o ${perfdata} -e cs_etm// -S \ + perf record -o ${perfdata} -e cs_etm// -S -m,128K \ -- dd if=/dev/zero of=/dev/null > /dev/null 2>&1 & PERFPID=$! From 04d8a36625efe5ad20d7c2c04cdae960af70d118 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:19 +0100 Subject: [PATCH 279/343] perf test cs-etm: Speed up basic test Like the name says, this should be the most basic test possible. Kernel recording is slow and already has coverage on the systemwide test. Perf report output also has coverage elsewhere. 'ls' also produces more trace than 'true'. We only want to test if the combination of recording options works at all, so fix all of these things to make it as fast as possible. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/test_arm_coresight.sh | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh index da2f599393e2..83295a8fe179 100755 --- a/tools/perf/tests/shell/test_arm_coresight.sh +++ b/tools/perf/tests/shell/test_arm_coresight.sh @@ -179,10 +179,9 @@ arm_cs_etm_snapshot_test() { arm_cs_etm_basic_test() { echo "Recording trace with '$*'" - perf record -o ${perfdata} "$@" -m,8M -- ls > /dev/null 2>&1 + perf record -o ${perfdata} "$@" -- true > /dev/null 2>&1 - perf_script_branch_samples ls && - perf_report_instruction_samples ls + perf_script_branch_samples true err=$? arm_cs_report "CoreSight basic testing with '$*'" $err @@ -246,12 +245,12 @@ arm_cs_etm_snapshot_test # Test all combinations of per-thread, system-wide and normal mode with # and without timestamps -arm_cs_etm_basic_test -e cs_etm/timestamp=0/ --per-thread -arm_cs_etm_basic_test -e cs_etm/timestamp=1/ --per-thread -arm_cs_etm_basic_test -e cs_etm/timestamp=0/ -a -arm_cs_etm_basic_test -e cs_etm/timestamp=1/ -a -arm_cs_etm_basic_test -e cs_etm/timestamp=0/ -arm_cs_etm_basic_test -e cs_etm/timestamp=1/ +arm_cs_etm_basic_test -e cs_etm/timestamp=0/u --per-thread +arm_cs_etm_basic_test -e cs_etm/timestamp=1/u --per-thread +arm_cs_etm_basic_test -e cs_etm/timestamp=0/u -a +arm_cs_etm_basic_test -e cs_etm/timestamp=1/u -a +arm_cs_etm_basic_test -e cs_etm/timestamp=0/u +arm_cs_etm_basic_test -e cs_etm/timestamp=1/u arm_cs_etm_sparse_cpus_test From 2f36f22f2b440c20cb63ff2917fc9a36e7462143 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:20 +0100 Subject: [PATCH 280/343] perf test cs-etm: Remove unused Coresight workloads These are now unused and had various issues like not working with out of source builds and being slow to compile. Delete them. Signed-off-by: James Clark Tested-by: Leo Yan Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- .../trace/coresight/coresight-perf.rst | 76 +--------- MAINTAINERS | 1 - tools/perf/Makefile.perf | 14 +- tools/perf/tests/shell/coresight/Makefile | 29 ---- .../tests/shell/coresight/Makefile.miniconfig | 14 -- .../shell/coresight/asm_pure_loop/.gitignore | 1 - .../shell/coresight/asm_pure_loop/Makefile | 34 ----- .../coresight/asm_pure_loop/asm_pure_loop.S | 30 ---- .../shell/coresight/memcpy_thread/.gitignore | 1 - .../shell/coresight/memcpy_thread/Makefile | 33 ----- .../coresight/memcpy_thread/memcpy_thread.c | 80 ----------- .../shell/coresight/thread_loop/.gitignore | 1 - .../shell/coresight/thread_loop/Makefile | 33 ----- .../shell/coresight/thread_loop/thread_loop.c | 85 ----------- .../coresight/unroll_loop_thread/.gitignore | 1 - .../coresight/unroll_loop_thread/Makefile | 33 ----- .../unroll_loop_thread/unroll_loop_thread.c | 75 ---------- tools/perf/tests/shell/lib/coresight.sh | 134 ------------------ 18 files changed, 4 insertions(+), 671 deletions(-) delete mode 100644 tools/perf/tests/shell/coresight/Makefile delete mode 100644 tools/perf/tests/shell/coresight/Makefile.miniconfig delete mode 100644 tools/perf/tests/shell/coresight/asm_pure_loop/.gitignore delete mode 100644 tools/perf/tests/shell/coresight/asm_pure_loop/Makefile delete mode 100644 tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S delete mode 100644 tools/perf/tests/shell/coresight/memcpy_thread/.gitignore delete mode 100644 tools/perf/tests/shell/coresight/memcpy_thread/Makefile delete mode 100644 tools/perf/tests/shell/coresight/memcpy_thread/memcpy_thread.c delete mode 100644 tools/perf/tests/shell/coresight/thread_loop/.gitignore delete mode 100644 tools/perf/tests/shell/coresight/thread_loop/Makefile delete mode 100644 tools/perf/tests/shell/coresight/thread_loop/thread_loop.c delete mode 100644 tools/perf/tests/shell/coresight/unroll_loop_thread/.gitignore delete mode 100644 tools/perf/tests/shell/coresight/unroll_loop_thread/Makefile delete mode 100644 tools/perf/tests/shell/coresight/unroll_loop_thread/unroll_loop_thread.c delete mode 100644 tools/perf/tests/shell/lib/coresight.sh diff --git a/Documentation/trace/coresight/coresight-perf.rst b/Documentation/trace/coresight/coresight-perf.rst index 30be89320621..0a77741a431e 100644 --- a/Documentation/trace/coresight/coresight-perf.rst +++ b/Documentation/trace/coresight/coresight-perf.rst @@ -112,78 +112,6 @@ Example for triggering AUX pause and resume with PMU event:: Perf test - Verify kernel and userspace perf CoreSight work ----------------------------------------------------------- -When you run perf test, it will do a lot of self tests. Some of those -tests will cover CoreSight (only if enabled and on ARM64). You -generally would run perf test from the tools/perf directory in the -kernel tree. Some tests will check some internal perf support like: +There are a set of Perf tests for CoreSight which can be run with:: - Check Arm CoreSight trace data recording and synthesized samples - Check Arm SPE trace data recording and synthesized samples - -Some others will actually use perf record and some test binaries that -are in tests/shell/coresight and will collect traces to ensure a -minimum level of functionality is met. The scripts that launch these -tests are in the same directory. These will all look like: - - CoreSight / ASM Pure Loop - CoreSight / Memcpy 16k 10 Threads - CoreSight / Thread Loop 10 Threads - Check TID - etc. - -These perf record tests will not run if the tool binaries do not exist -in tests/shell/coresight/\*/ and will be skipped. If you do not have -CoreSight support in hardware then either do not build perf with -CoreSight support or remove these binaries in order to not have these -tests fail and have them skip instead. - -These tests will log historical results in the current working -directory (e.g. tools/perf) and will be named stats-\*.csv like: - - stats-asm_pure_loop-out.csv - stats-memcpy_thread-16k_10.csv - ... - -These statistic files log some aspects of the AUX data sections in -the perf data output counting some numbers of certain encodings (a -good way to know that it's working in a very simple way). One problem -with CoreSight is that given a large enough amount of data needing to -be logged, some of it can be lost due to the processor not waking up -in time to read out all the data from buffers etc.. You will notice -that the amount of data collected can vary a lot per run of perf test. -If you wish to see how this changes over time, simply run perf test -multiple times and all these csv files will have more and more data -appended to it that you can later examine, graph and otherwise use to -figure out if things have become worse or better. - -This means sometimes these tests fail as they don't capture all the -data needed. This is about tracking quality and amount of data -produced over time and to see when changes to the Linux kernel improve -quality of traces. - -Be aware that some of these tests take quite a while to run, specifically -in processing the perf data file and dumping contents to then examine what -is inside. - -You can change where these csv logs are stored by setting the -PERF_TEST_CORESIGHT_STATDIR environment variable before running perf -test like:: - - export PERF_TEST_CORESIGHT_STATDIR=/var/tmp - perf test - -They will also store resulting perf output data in the current -directory for later inspection like:: - - perf-asm_pure_loop-out.data - perf-memcpy_thread-16k_10.data - ... - -You can alter where the perf data files are stored by setting the -PERF_TEST_CORESIGHT_DATADIR environment variable such as:: - - PERF_TEST_CORESIGHT_DATADIR=/var/tmp - perf test - -You may wish to set these above environment variables if you wish to -keep the output of tests outside of the current working directory for -longer term storage and examination. + sudo perf test coresight diff --git a/MAINTAINERS b/MAINTAINERS index b539be153f6a..7efb893edcbb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2751,7 +2751,6 @@ F: tools/perf/arch/arm/util/cs-etm.h F: tools/perf/arch/arm/util/pmu.c F: tools/perf/tests/shell/*coresight* F: tools/perf/tests/shell/coresight/* -F: tools/perf/tests/shell/lib/*coresight* F: tools/perf/util/cs-etm-decoder/* F: tools/perf/util/cs-etm.* diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index bdedf6620758..476b8dcaef58 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -512,16 +512,7 @@ arm64-sysreg-defs-clean: $(Q)$(MAKE) -C $(arm64_gen_sysreg_dir) O=$(arm64_gen_sysreg_outdir) \ prefix= subdir= clean > /dev/null -TESTS_CORESIGHT_DIR := $(srctree)/tools/perf/tests/shell/coresight - -tests-coresight-targets: FORCE - $(Q)$(MAKE) -C $(TESTS_CORESIGHT_DIR) - -tests-coresight-targets-clean: - $(call QUIET_CLEAN, coresight) - $(Q)$(MAKE) -C $(TESTS_CORESIGHT_DIR) O=$(OUTPUT) clean >/dev/null - -all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) tests-coresight-targets +all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) # Create python binding output directory if not already present $(shell [ -d '$(OUTPUT)python' ] || mkdir -p '$(OUTPUT)python') @@ -900,7 +891,6 @@ install-tests: all install-gtk $(INSTALL) tests/shell/base_report/*.txt '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/base_report'; \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/coresight' ; \ $(INSTALL) tests/shell/coresight/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/coresight' - $(Q)$(MAKE) -C tests/shell/coresight install-tests install-bin: install-tools install-tests @@ -943,7 +933,7 @@ endif clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(LIBPERF)-clean \ arm64-sysreg-defs-clean fixdep-clean python-clean bpf-skel-clean \ - tests-coresight-targets-clean pmu-events-clean + pmu-events-clean $(call QUIET_CLEAN, core-objs) $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive \ $(OUTPUT)perf-iostat $(LANG_BINDINGS) $(Q)find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '*.a' -delete -o \ diff --git a/tools/perf/tests/shell/coresight/Makefile b/tools/perf/tests/shell/coresight/Makefile deleted file mode 100644 index fa08fd9a5991..000000000000 --- a/tools/perf/tests/shell/coresight/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Carsten Haitzler , 2021 -include ../../../../../tools/scripts/Makefile.include -include ../../../../../tools/scripts/Makefile.arch -include ../../../../../tools/scripts/utilities.mak - -SUBDIRS = \ - asm_pure_loop \ - memcpy_thread \ - thread_loop \ - unroll_loop_thread - -all: $(SUBDIRS) -$(SUBDIRS): - @$(MAKE) -C $@ >/dev/null - -INSTALLDIRS = $(SUBDIRS:%=install-%) - -install-tests: $(INSTALLDIRS) -$(INSTALLDIRS): - @$(MAKE) -C $(@:install-%=%) install-tests >/dev/null - -CLEANDIRS = $(SUBDIRS:%=clean-%) - -clean: $(CLEANDIRS) -$(CLEANDIRS): - $(call QUIET_CLEAN, test-$(@:clean-%=%)) $(MAKE) -C $(@:clean-%=%) clean >/dev/null - -.PHONY: all clean $(SUBDIRS) $(CLEANDIRS) $(INSTALLDIRS) diff --git a/tools/perf/tests/shell/coresight/Makefile.miniconfig b/tools/perf/tests/shell/coresight/Makefile.miniconfig deleted file mode 100644 index 5f72a9cb43f3..000000000000 --- a/tools/perf/tests/shell/coresight/Makefile.miniconfig +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Carsten Haitzler , 2021 - -ifndef DESTDIR -prefix ?= $(HOME) -endif - -DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) -INSTALL = install -INSTDIR_SUB = tests/shell/coresight - -include ../../../../../scripts/Makefile.include -include ../../../../../scripts/Makefile.arch -include ../../../../../scripts/utilities.mak diff --git a/tools/perf/tests/shell/coresight/asm_pure_loop/.gitignore b/tools/perf/tests/shell/coresight/asm_pure_loop/.gitignore deleted file mode 100644 index 468673ac32e8..000000000000 --- a/tools/perf/tests/shell/coresight/asm_pure_loop/.gitignore +++ /dev/null @@ -1 +0,0 @@ -asm_pure_loop diff --git a/tools/perf/tests/shell/coresight/asm_pure_loop/Makefile b/tools/perf/tests/shell/coresight/asm_pure_loop/Makefile deleted file mode 100644 index 206849e92bc9..000000000000 --- a/tools/perf/tests/shell/coresight/asm_pure_loop/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 - -include ../Makefile.miniconfig - -# Binary to produce -BIN=asm_pure_loop -# Any linking/libraries needed for the binary - empty if none needed -LIB= - -all: $(BIN) - -$(BIN): $(BIN).S -ifdef CORESIGHT -ifeq ($(ARCH),arm64) -# Build line - this is raw asm with no libc to have an always exact binary - $(Q)$(CC) $(BIN).S -nostdlib -static -o $(BIN) $(LIB) -endif -endif - -install-tests: all -ifdef CORESIGHT -ifeq ($(ARCH),arm64) -# Install the test tool in the right place - $(call QUIET_INSTALL, tests) \ - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$(INSTDIR_SUB)/$(BIN)'; \ - $(INSTALL) $(BIN) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$(INSTDIR_SUB)/$(BIN)/$(BIN)' -endif -endif - -clean: - $(Q)$(RM) -f $(BIN) - -.PHONY: all clean install-tests diff --git a/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S b/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S deleted file mode 100644 index 577760046772..000000000000 --- a/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Tamas Zsoldos , 2021 */ - -.globl _start -_start: - mov x0, 0x0000ffff - mov x1, xzr -loop: - nop - nop - cbnz x1, noskip - nop - nop - adrp x2, skip - add x2, x2, :lo12:skip - br x2 - nop - nop -noskip: - nop - nop -skip: - sub x0, x0, 1 - cbnz x0, loop - - mov x0, #0 - mov x8, #93 // __NR_exit syscall - svc #0 - -.section .note.GNU-stack, "", @progbits diff --git a/tools/perf/tests/shell/coresight/memcpy_thread/.gitignore b/tools/perf/tests/shell/coresight/memcpy_thread/.gitignore deleted file mode 100644 index f8217e56091e..000000000000 --- a/tools/perf/tests/shell/coresight/memcpy_thread/.gitignore +++ /dev/null @@ -1 +0,0 @@ -memcpy_thread diff --git a/tools/perf/tests/shell/coresight/memcpy_thread/Makefile b/tools/perf/tests/shell/coresight/memcpy_thread/Makefile deleted file mode 100644 index 2db637eb2c26..000000000000 --- a/tools/perf/tests/shell/coresight/memcpy_thread/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 -include ../Makefile.miniconfig - -# Binary to produce -BIN=memcpy_thread -# Any linking/libraries needed for the binary - empty if none needed -LIB=-pthread - -all: $(BIN) - -$(BIN): $(BIN).c -ifdef CORESIGHT -ifeq ($(ARCH),arm64) -# Build line - $(Q)$(CC) $(BIN).c -o $(BIN) $(LIB) -endif -endif - -install-tests: all -ifdef CORESIGHT -ifeq ($(ARCH),arm64) -# Install the test tool in the right place - $(call QUIET_INSTALL, tests) \ - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$(INSTDIR_SUB)/$(BIN)'; \ - $(INSTALL) $(BIN) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$(INSTDIR_SUB)/$(BIN)/$(BIN)' -endif -endif - -clean: - $(Q)$(RM) -f $(BIN) - -.PHONY: all clean install-tests diff --git a/tools/perf/tests/shell/coresight/memcpy_thread/memcpy_thread.c b/tools/perf/tests/shell/coresight/memcpy_thread/memcpy_thread.c deleted file mode 100644 index 7e879217be30..000000000000 --- a/tools/perf/tests/shell/coresight/memcpy_thread/memcpy_thread.c +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// Carsten Haitzler , 2021 -#include -#include -#include -#include -#include - -struct args { - unsigned long loops; - unsigned long size; - pthread_t th; - void *ret; -}; - -static void *thrfn(void *arg) -{ - struct args *a = arg; - unsigned long i, len = a->loops; - unsigned char *src, *dst; - - src = malloc(a->size * 1024); - dst = malloc(a->size * 1024); - if ((!src) || (!dst)) { - printf("ERR: Can't allocate memory\n"); - exit(1); - } - for (i = 0; i < len; i++) - memcpy(dst, src, a->size * 1024); - - return NULL; -} - -static pthread_t new_thr(void *(*fn) (void *arg), void *arg) -{ - pthread_t t; - pthread_attr_t attr; - - pthread_attr_init(&attr); - pthread_create(&t, &attr, fn, arg); - return t; -} - -int main(int argc, char **argv) -{ - unsigned long i, len, size, thr; - struct args args[256]; - long long v; - - if (argc < 4) { - printf("ERR: %s [copysize Kb] [numthreads] [numloops (hundreds)]\n", argv[0]); - exit(1); - } - - v = atoll(argv[1]); - if ((v < 1) || (v > (1024 * 1024))) { - printf("ERR: max memory 1GB (1048576 KB)\n"); - exit(1); - } - size = v; - thr = atol(argv[2]); - if ((thr < 1) || (thr > 256)) { - printf("ERR: threads 1-256\n"); - exit(1); - } - v = atoll(argv[3]); - if ((v < 1) || (v > 40000000000ll)) { - printf("ERR: loops 1-40000000000 (hundreds)\n"); - exit(1); - } - len = v * 100; - for (i = 0; i < thr; i++) { - args[i].loops = len; - args[i].size = size; - args[i].th = new_thr(thrfn, &(args[i])); - } - for (i = 0; i < thr; i++) - pthread_join(args[i].th, &(args[i].ret)); - return 0; -} diff --git a/tools/perf/tests/shell/coresight/thread_loop/.gitignore b/tools/perf/tests/shell/coresight/thread_loop/.gitignore deleted file mode 100644 index 6d4c33eaa9e8..000000000000 --- a/tools/perf/tests/shell/coresight/thread_loop/.gitignore +++ /dev/null @@ -1 +0,0 @@ -thread_loop diff --git a/tools/perf/tests/shell/coresight/thread_loop/Makefile b/tools/perf/tests/shell/coresight/thread_loop/Makefile deleted file mode 100644 index ea846c038e7a..000000000000 --- a/tools/perf/tests/shell/coresight/thread_loop/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 -include ../Makefile.miniconfig - -# Binary to produce -BIN=thread_loop -# Any linking/libraries needed for the binary - empty if none needed -LIB=-pthread - -all: $(BIN) - -$(BIN): $(BIN).c -ifdef CORESIGHT -ifeq ($(ARCH),arm64) -# Build line - $(Q)$(CC) $(BIN).c -o $(BIN) $(LIB) -endif -endif - -install-tests: all -ifdef CORESIGHT -ifeq ($(ARCH),arm64) -# Install the test tool in the right place - $(call QUIET_INSTALL, tests) \ - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$(INSTDIR_SUB)/$(BIN)'; \ - $(INSTALL) $(BIN) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$(INSTDIR_SUB)/$(BIN)/$(BIN)' -endif -endif - -clean: - $(Q)$(RM) -f $(BIN) - -.PHONY: all clean install-tests diff --git a/tools/perf/tests/shell/coresight/thread_loop/thread_loop.c b/tools/perf/tests/shell/coresight/thread_loop/thread_loop.c deleted file mode 100644 index 86f3f548b006..000000000000 --- a/tools/perf/tests/shell/coresight/thread_loop/thread_loop.c +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// Carsten Haitzler , 2021 - -// define this for gettid() -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#ifndef SYS_gettid -// gettid is 178 on arm64 -# define SYS_gettid 178 -#endif -#define gettid() syscall(SYS_gettid) - -struct args { - unsigned int loops; - pthread_t th; - void *ret; -}; - -static void *thrfn(void *arg) -{ - struct args *a = arg; - int i = 0, len = a->loops; - - if (getenv("SHOW_TID")) { - unsigned long long tid = gettid(); - - printf("%llu\n", tid); - } - asm volatile( - "loop:\n" - "add %w[i], %w[i], #1\n" - "cmp %w[i], %w[len]\n" - "blt loop\n" - : /* out */ - : /* in */ [i] "r" (i), [len] "r" (len) - : /* clobber */ - ); - return (void *)(long)i; -} - -static pthread_t new_thr(void *(*fn) (void *arg), void *arg) -{ - pthread_t t; - pthread_attr_t attr; - - pthread_attr_init(&attr); - pthread_create(&t, &attr, fn, arg); - return t; -} - -int main(int argc, char **argv) -{ - unsigned int i, len, thr; - struct args args[256]; - - if (argc < 3) { - printf("ERR: %s [numthreads] [numloops (millions)]\n", argv[0]); - exit(1); - } - - thr = atoi(argv[1]); - if ((thr < 1) || (thr > 256)) { - printf("ERR: threads 1-256\n"); - exit(1); - } - len = atoi(argv[2]); - if ((len < 1) || (len > 4000)) { - printf("ERR: max loops 4000 (millions)\n"); - exit(1); - } - len *= 1000000; - for (i = 0; i < thr; i++) { - args[i].loops = len; - args[i].th = new_thr(thrfn, &(args[i])); - } - for (i = 0; i < thr; i++) - pthread_join(args[i].th, &(args[i].ret)); - return 0; -} diff --git a/tools/perf/tests/shell/coresight/unroll_loop_thread/.gitignore b/tools/perf/tests/shell/coresight/unroll_loop_thread/.gitignore deleted file mode 100644 index 2cb4e996dbf3..000000000000 --- a/tools/perf/tests/shell/coresight/unroll_loop_thread/.gitignore +++ /dev/null @@ -1 +0,0 @@ -unroll_loop_thread diff --git a/tools/perf/tests/shell/coresight/unroll_loop_thread/Makefile b/tools/perf/tests/shell/coresight/unroll_loop_thread/Makefile deleted file mode 100644 index 6264c4e3abd1..000000000000 --- a/tools/perf/tests/shell/coresight/unroll_loop_thread/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 -include ../Makefile.miniconfig - -# Binary to produce -BIN=unroll_loop_thread -# Any linking/libraries needed for the binary - empty if none needed -LIB=-pthread - -all: $(BIN) - -$(BIN): $(BIN).c -ifdef CORESIGHT -ifeq ($(ARCH),arm64) -# Build line - $(Q)$(CC) $(BIN).c -o $(BIN) $(LIB) -endif -endif - -install-tests: all -ifdef CORESIGHT -ifeq ($(ARCH),arm64) -# Install the test tool in the right place - $(call QUIET_INSTALL, tests) \ - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$(INSTDIR_SUB)/$(BIN)'; \ - $(INSTALL) $(BIN) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$(INSTDIR_SUB)/$(BIN)/$(BIN)' -endif -endif - -clean: - $(Q)$(RM) -f $(BIN) - -.PHONY: all clean install-tests diff --git a/tools/perf/tests/shell/coresight/unroll_loop_thread/unroll_loop_thread.c b/tools/perf/tests/shell/coresight/unroll_loop_thread/unroll_loop_thread.c deleted file mode 100644 index 8f4e1c985ca3..000000000000 --- a/tools/perf/tests/shell/coresight/unroll_loop_thread/unroll_loop_thread.c +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// Carsten Haitzler , 2021 -#include -#include -#include -#include -#include - -struct args { - pthread_t th; - unsigned int in; - void *ret; -}; - -static void *thrfn(void *arg) -{ - struct args *a = arg; - unsigned int i, in = a->in; - - for (i = 0; i < 10000; i++) { - asm volatile ( -// force an unroll of thia add instruction so we can test long runs of code -#define SNIP1 "add %w[in], %w[in], #1\n" -// 10 -#define SNIP2 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 -// 100 -#define SNIP3 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 -// 1000 -#define SNIP4 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 -// 10000 -#define SNIP5 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 -// 100000 - SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 - : /* out */ - : /* in */ [in] "r" (in) - : /* clobber */ - ); - } - - return NULL; -} - -static pthread_t new_thr(void *(*fn) (void *arg), void *arg) -{ - pthread_t t; - pthread_attr_t attr; - - pthread_attr_init(&attr); - pthread_create(&t, &attr, fn, arg); - return t; -} - -int main(int argc, char **argv) -{ - unsigned int i, thr; - struct args args[256]; - - if (argc < 2) { - printf("ERR: %s [numthreads]\n", argv[0]); - exit(1); - } - - thr = atoi(argv[1]); - if ((thr > 256) || (thr < 1)) { - printf("ERR: threads 1-256\n"); - exit(1); - } - for (i = 0; i < thr; i++) { - args[i].in = rand(); - args[i].th = new_thr(thrfn, &(args[i])); - } - for (i = 0; i < thr; i++) - pthread_join(args[i].th, &(args[i].ret)); - return 0; -} diff --git a/tools/perf/tests/shell/lib/coresight.sh b/tools/perf/tests/shell/lib/coresight.sh deleted file mode 100644 index 184d62e7e5bd..000000000000 --- a/tools/perf/tests/shell/lib/coresight.sh +++ /dev/null @@ -1,134 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Carsten Haitzler , 2021 - -# This is sourced from a driver script so no need for #!/bin... etc. at the -# top - the assumption below is that it runs as part of sourcing after the -# test sets up some basic env vars to say what it is. - -# This currently works with ETMv4 / ETF not any other packet types at thi -# point. This will need changes if that changes. - -# perf record options for the perf tests to use -PERFRECMEM="-m ,16M" -PERFRECOPT="$PERFRECMEM -e cs_etm//u" - -TOOLS=$(dirname $0) -DIR="$TOOLS/$TEST" -BIN="$DIR/$TEST" -# If the test tool/binary does not exist and is executable then skip the test -if ! test -x "$BIN"; then exit 2; fi -# If CoreSight is not available, skip the test -perf list pmu | grep -q cs_etm || exit 2 -DATD="." -# If the data dir env is set then make the data dir use that instead of ./ -if test -n "$PERF_TEST_CORESIGHT_DATADIR"; then - DATD="$PERF_TEST_CORESIGHT_DATADIR"; -fi -# If the stat dir env is set then make the data dir use that instead of ./ -STATD="." -if test -n "$PERF_TEST_CORESIGHT_STATDIR"; then - STATD="$PERF_TEST_CORESIGHT_STATDIR"; -fi - -# Called if the test fails - error code 1 -err() { - echo "$1" - exit 1 -} - -# Check that some statistics from our perf -check_val_min() { - STATF="$4" - if test "$2" -lt "$3"; then - echo ", FAILED" >> "$STATF" - err "Sanity check number of $1 is too low ($2 < $3)" - fi -} - -perf_dump_aux_verify() { - # Some basic checking that the AUX chunk contains some sensible data - # to see that we are recording something and at least a minimum - # amount of it. We should almost always see Fn packets in just about - # anything but certainly we will see some trace info and async - # packets - DUMP="$DATD/perf-tmp-aux-dump.txt" - perf report --stdio --dump -i "$1" | \ - grep -o -e I_ATOM_F -e I_ASYNC -e I_TRACE_INFO > "$DUMP" - # Simply count how many of these packets we find to see that we are - # producing a reasonable amount of data - exact checks are not sane - # as this is a lossy process where we may lose some blocks and the - # compiler may produce different code depending on the compiler and - # optimization options, so this is rough just to see if we're - # either missing almost all the data or all of it - ATOM_FX_NUM=$(grep -c I_ATOM_F "$DUMP") - ASYNC_NUM=$(grep -c I_ASYNC "$DUMP") - TRACE_INFO_NUM=$(grep -c I_TRACE_INFO "$DUMP") - rm -f "$DUMP" - - # Arguments provide minimums for a pass - CHECK_FX_MIN="$2" - CHECK_ASYNC_MIN="$3" - CHECK_TRACE_INFO_MIN="$4" - - # Write out statistics, so over time you can track results to see if - # there is a pattern - for example we have less "noisy" results that - # produce more consistent amounts of data each run, to see if over - # time any techinques to minimize data loss are having an effect or - # not - STATF="$STATD/stats-$TEST-$DATV.csv" - if ! test -f "$STATF"; then - echo "ATOM Fx Count, Minimum, ASYNC Count, Minimum, TRACE INFO Count, Minimum" > "$STATF" - fi - echo -n "$ATOM_FX_NUM, $CHECK_FX_MIN, $ASYNC_NUM, $CHECK_ASYNC_MIN, $TRACE_INFO_NUM, $CHECK_TRACE_INFO_MIN" >> "$STATF" - - # Actually check to see if we passed or failed. - check_val_min "ATOM_FX" "$ATOM_FX_NUM" "$CHECK_FX_MIN" "$STATF" - check_val_min "ASYNC" "$ASYNC_NUM" "$CHECK_ASYNC_MIN" "$STATF" - check_val_min "TRACE_INFO" "$TRACE_INFO_NUM" "$CHECK_TRACE_INFO_MIN" "$STATF" - echo ", Ok" >> "$STATF" -} - -perf_dump_aux_tid_verify() { - # Specifically crafted test will produce a list of Tread ID's to - # stdout that need to be checked to see that they have had trace - # info collected in AUX blocks in the perf data. This will go - # through all the TID's that are listed as CID=0xabcdef and see - # that all the Thread IDs the test tool reports are in the perf - # data AUX chunks - - # The TID test tools will print a TID per stdout line that are being - # tested - TIDS=$(cat "$2") - # Scan the perf report to find the TIDs that are actually CID in hex - # and build a list of the ones found - FOUND_TIDS=$(perf report --stdio --dump -i "$1" | \ - grep -o "CID=0x[0-9a-z]\+" | sed 's/CID=//g' | \ - uniq | sort | uniq) - # No CID=xxx found - maybe your kernel is reporting these as - # VMID=xxx so look there - if test -z "$FOUND_TIDS"; then - FOUND_TIDS=$(perf report --stdio --dump -i "$1" | \ - grep -o "VMID=0x[0-9a-z]\+" | sed 's/VMID=//g' | \ - uniq | sort | uniq) - fi - - # Iterate over the list of TIDs that the test says it has and find - # them in the TIDs found in the perf report - MISSING="" - for TID2 in $TIDS; do - FOUND="" - for TIDHEX in $FOUND_TIDS; do - TID=$(printf "%i" $TIDHEX) - if test "$TID" -eq "$TID2"; then - FOUND="y" - break - fi - done - if test -z "$FOUND"; then - MISSING="$MISSING $TID" - fi - done - if test -n "$MISSING"; then - err "Thread IDs $MISSING not found in perf AUX data" - fi -} From 3c84ec94a68ad73663b9c1ac7543b59453f64678 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:21 +0100 Subject: [PATCH 281/343] perf test cs-etm: Make disassembly test use kcore Hits in modules return empty disassembly with vmlinux as an input to objdump. Make the disassembly test more reliable by always using kcore. And update the comments to say that this is supported by the script. Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Leo Yan Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- .../scripts/python/arm-cs-trace-disasm.py | 20 +++++++++---------- .../tests/shell/test_arm_coresight_disasm.sh | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tools/perf/scripts/python/arm-cs-trace-disasm.py b/tools/perf/scripts/python/arm-cs-trace-disasm.py index ba208c90d631..8f6fa4a007b4 100755 --- a/tools/perf/scripts/python/arm-cs-trace-disasm.py +++ b/tools/perf/scripts/python/arm-cs-trace-disasm.py @@ -18,29 +18,29 @@ from perf_trace_context import perf_sample_srccode, perf_config_get # Below are some example commands for using this script. # Note a --kcore recording is required for accurate decode -# due to the alternatives patching mechanism. However this -# script only supports reading vmlinux for disassembly dump, -# meaning that any patched instructions will appear -# as unpatched, but the instruction ranges themselves will -# be correct. In addition to this, source line info comes -# from Perf, and when using kcore there is no debug info. The -# following lists the supported features in each mode: +# due to the alternatives patching mechanism. In addition to this, +# source line info comes from Perf, and when using kcore there is +# no debug info. The following lists the supported features in each mode: # # +-----------+-----------------+------------------+------------------+ # | Recording | Accurate decode | Source line dump | Disassembly dump | # +-----------+-----------------+------------------+------------------+ # | --kcore | yes | no | yes | -# | normal | no | yes | yes | +# | normal | no | yes (inaccurate) | yes (inaccurate) | # +-----------+-----------------+------------------+------------------+ # # Output disassembly with objdump and auto detect vmlinux -# (when running on same machine.) +# (when running on same machine.): # perf script -s scripts/python/arm-cs-trace-disasm.py -d # # Output disassembly with llvm-objdump: # perf script -s scripts/python/arm-cs-trace-disasm.py \ # -- -d llvm-objdump-11 -k path/to/vmlinux # +# Output accurate disassembly by passing kcore to script: +# perf script -s scripts/python/arm-cs-trace-disasm.py \ +# -- -d -k perf.data/kcore_dir/kcore +# # Output only source line and symbols: # perf script -s scripts/python/arm-cs-trace-disasm.py @@ -57,7 +57,7 @@ def int_arg(v): args = argparse.ArgumentParser() args.add_argument("-k", "--vmlinux", - help="Set path to vmlinux file. Omit to autodetect if running on same machine") + help="Set path to vmlinux or kcore file. Omit to autodetect if running on same machine") args.add_argument("-d", "--objdump", nargs="?", const=default_objdump(), help="Show disassembly. Can also be used to change the objdump path"), args.add_argument("-v", "--verbose", action="store_true", help="Enable debugging log") diff --git a/tools/perf/tests/shell/test_arm_coresight_disasm.sh b/tools/perf/tests/shell/test_arm_coresight_disasm.sh index 339ae4831868..87797d239f76 100755 --- a/tools/perf/tests/shell/test_arm_coresight_disasm.sh +++ b/tools/perf/tests/shell/test_arm_coresight_disasm.sh @@ -46,7 +46,7 @@ if [ "$(id -u)" == 0 ] && [ -e /proc/kcore ]; then echo "Testing kernel disassembly" perf record -o ${perfdata} -e cs_etm//k --kcore -- touch $file > /dev/null 2>&1 perf script -i ${perfdata} -s python:${script_path} -- \ - -d --stop-sample=30 2> /dev/null > ${file} + -d --stop-sample=30 -k ${perfdata}/kcore_dir/kcore 2> /dev/null > ${file} grep -q -e ${branch_search} ${file} echo "Found kernel branches" else From 0f900110c7b49cae863c19960991033e55c0ad2e Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:22 +0100 Subject: [PATCH 282/343] perf test cs-etm: Add all branch instructions to test If we reduce the number of samples searched to speed up the test, then there will be less chance of hitting one of these branches. Extend the regex to cover all branches so the test will always pass. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/test_arm_coresight_disasm.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/perf/tests/shell/test_arm_coresight_disasm.sh b/tools/perf/tests/shell/test_arm_coresight_disasm.sh index 87797d239f76..f78dfb6bf73e 100755 --- a/tools/perf/tests/shell/test_arm_coresight_disasm.sh +++ b/tools/perf/tests/shell/test_arm_coresight_disasm.sh @@ -38,8 +38,7 @@ cleanup_files() trap cleanup_files EXIT TERM INT # Ranges start and end on branches, so check for some likely branch instructions -sep="\s\|\s" -branch_search="\sbl${sep}b${sep}b.ne${sep}b.eq${sep}cbz\s" +branch_search='[[:space:]](bl|b(\.(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al))?|br|blr|ret|cbz|cbnz|tbz|tbnz|svc|eret)([[:space:]]|$)' ## Test kernel ## if [ "$(id -u)" == 0 ] && [ -e /proc/kcore ]; then @@ -47,7 +46,7 @@ if [ "$(id -u)" == 0 ] && [ -e /proc/kcore ]; then perf record -o ${perfdata} -e cs_etm//k --kcore -- touch $file > /dev/null 2>&1 perf script -i ${perfdata} -s python:${script_path} -- \ -d --stop-sample=30 -k ${perfdata}/kcore_dir/kcore 2> /dev/null > ${file} - grep -q -e ${branch_search} ${file} + grep -q -E ${branch_search} ${file} echo "Found kernel branches" else # Root and kcore are required for correct kernel decode due to runtime code patching @@ -59,7 +58,7 @@ echo "Testing userspace disassembly" perf record -o ${perfdata} -e cs_etm//u -- touch $file > /dev/null 2>&1 perf script -i ${perfdata} -s python:${script_path} -- \ -d --stop-sample=30 2> /dev/null > ${file} -grep -q -e ${branch_search} ${file} +grep -q -E ${branch_search} ${file} echo "Found userspace branches" glb_err=0 From 0e16b544165822cd1452d446308fa3ec9311d05e Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:23 +0100 Subject: [PATCH 283/343] perf test cs-etm: Speed up disassembly test We can use exit snapshot to limit the amount of trace to decode here too. Also each call to objdump is quite expensive on kcore so limit it to 2 samples instead of 30. We only want to see if there is no data at all. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/test_arm_coresight_disasm.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/tests/shell/test_arm_coresight_disasm.sh b/tools/perf/tests/shell/test_arm_coresight_disasm.sh index f78dfb6bf73e..f2fb1aa92252 100755 --- a/tools/perf/tests/shell/test_arm_coresight_disasm.sh +++ b/tools/perf/tests/shell/test_arm_coresight_disasm.sh @@ -43,9 +43,9 @@ branch_search='[[:space:]](bl|b(\.(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al) ## Test kernel ## if [ "$(id -u)" == 0 ] && [ -e /proc/kcore ]; then echo "Testing kernel disassembly" - perf record -o ${perfdata} -e cs_etm//k --kcore -- touch $file > /dev/null 2>&1 + perf record -o ${perfdata} -e cs_etm//k --kcore -Se -m,64K -- touch $file > /dev/null 2>&1 perf script -i ${perfdata} -s python:${script_path} -- \ - -d --stop-sample=30 -k ${perfdata}/kcore_dir/kcore 2> /dev/null > ${file} + -d --stop-sample=2 -k ${perfdata}/kcore_dir/kcore 2> /dev/null > ${file} grep -q -E ${branch_search} ${file} echo "Found kernel branches" else @@ -55,9 +55,9 @@ fi ## Test user ## echo "Testing userspace disassembly" -perf record -o ${perfdata} -e cs_etm//u -- touch $file > /dev/null 2>&1 +perf record -o ${perfdata} -e cs_etm//u -Se -m,64K -- touch $file > /dev/null 2>&1 perf script -i ${perfdata} -s python:${script_path} -- \ - -d --stop-sample=30 2> /dev/null > ${file} + -d --stop-sample=2 2> /dev/null > ${file} grep -q -E ${branch_search} ${file} echo "Found userspace branches" From 46510981d6c5e6cfa963e924b9e65b2f56222431 Mon Sep 17 00:00:00 2001 From: James Clark Date: Tue, 9 Jun 2026 15:40:24 +0100 Subject: [PATCH 284/343] perf test cs-etm: Move existing tests to coresight folder There is a subfolder for Coresight tests so might as well keep them all in here. Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Amir Ayupov Cc: Ian Rogers Cc: Jiri Olsa Cc: Jonathan Corbet Cc: Mike Leach Cc: Namhyung Kim Cc: Paschalis Mpeis Cc: Shuah Khan Cc: Suzuki Poulouse Signed-off-by: Arnaldo Carvalho de Melo --- MAINTAINERS | 1 - tools/perf/tests/shell/{ => coresight}/test_arm_coresight.sh | 0 .../tests/shell/{ => coresight}/test_arm_coresight_disasm.sh | 2 +- 3 files changed, 1 insertion(+), 2 deletions(-) rename tools/perf/tests/shell/{ => coresight}/test_arm_coresight.sh (100%) rename tools/perf/tests/shell/{ => coresight}/test_arm_coresight_disasm.sh (96%) diff --git a/MAINTAINERS b/MAINTAINERS index 7efb893edcbb..ff8935b459ea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2749,7 +2749,6 @@ F: tools/perf/arch/arm/util/auxtrace.c F: tools/perf/arch/arm/util/cs-etm.c F: tools/perf/arch/arm/util/cs-etm.h F: tools/perf/arch/arm/util/pmu.c -F: tools/perf/tests/shell/*coresight* F: tools/perf/tests/shell/coresight/* F: tools/perf/util/cs-etm-decoder/* F: tools/perf/util/cs-etm.* diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/coresight/test_arm_coresight.sh similarity index 100% rename from tools/perf/tests/shell/test_arm_coresight.sh rename to tools/perf/tests/shell/coresight/test_arm_coresight.sh diff --git a/tools/perf/tests/shell/test_arm_coresight_disasm.sh b/tools/perf/tests/shell/coresight/test_arm_coresight_disasm.sh similarity index 96% rename from tools/perf/tests/shell/test_arm_coresight_disasm.sh rename to tools/perf/tests/shell/coresight/test_arm_coresight_disasm.sh index f2fb1aa92252..ccb90dda2475 100755 --- a/tools/perf/tests/shell/test_arm_coresight_disasm.sh +++ b/tools/perf/tests/shell/coresight/test_arm_coresight_disasm.sh @@ -24,7 +24,7 @@ perfdata_dir=$(mktemp -d /tmp/__perf_test.perf.data.XXXXX) perfdata=${perfdata_dir}/perf.data file=$(mktemp /tmp/temporary_file.XXXXX) # Relative path works whether it's installed or running from repo -script_path=$(dirname "$0")/../../scripts/python/arm-cs-trace-disasm.py +script_path=$(dirname "$0")/../../../scripts/python/arm-cs-trace-disasm.py cleanup_files() { From 2f4e244b5968b1f7392d7de31dc961ef80f2e42e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 4 Jun 2026 23:49:32 -0700 Subject: [PATCH 285/343] perf jitdump: Fix a build error with ASAN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I found this error when I pass EXTRA_CFLAGS=-fsanitize=address on Fedora 44 with GCC 16. Fix it by copying one less byte. CC util/jitdump.o util/jitdump.c: In function ‘jit_process’: util/jitdump.c:237:9: error: ‘__builtin_strncpy’ specified bound 4096 equals destination size [-Werror=stringop-truncation] 237 | strncpy(jd->dir, name, PATH_MAX); | ^ cc1: all warnings being treated as errors make[4]: *** [tools/build/Makefile.build:95: util/jitdump.o] Error 1 make[4]: *** Waiting for unfinished jobs.... make[3]: *** [tools/build/Makefile.build:158: util] Error 2 make[2]: *** [Makefile.perf:578: perf-util-in.o] Error 2 make[1]: *** [Makefile.perf:288: sub-make] Error 2 make: *** [Makefile:76: all] Error 2 Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/jitdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 18fd84a82153..83005b30b9bf 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -234,7 +234,7 @@ jit_open(struct jit_buf_desc *jd, const char *name) /* * keep dirname for generating files and mmap records */ - strncpy(jd->dir, name, PATH_MAX); + strncpy(jd->dir, name, PATH_MAX - 1); jd->dir[PATH_MAX - 1] = '\0'; dirname(jd->dir); free(buf); From 836455e6dbd34eb3d12eeab5e2d2b9a7f1512459 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 21:01:43 -0300 Subject: [PATCH 286/343] perf pmu: Fix pmu_id() heap underwrite on empty identifier file pmu_id() calls filename__read_str() then strips the trailing newline via str[len - 1] = 0. If the PMU identifier file is empty, filename__read_str() succeeds with len = 0. len - 1 underflows size_t to SIZE_MAX, writing a null byte before the heap allocation. Add a len == 0 check before the newline stripping. Fixes: 51d548471510843e ("perf pmu: Add pmu_id()") Reported-by: sashiko-bot Cc: John Garry Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 1539960ba23b..f588cce60194 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -865,6 +865,12 @@ static char *pmu_id(const char *name) if (filename__read_str(path, &str, &len) < 0) return NULL; + /* empty identifier file — nothing useful */ + if (len == 0) { + free(str); + return NULL; + } + str[len - 1] = 0; /* remove line feed */ return str; From 33035f7dd4e49f3f117e70c5e36c8c1ae88d37f2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 21:03:13 -0300 Subject: [PATCH 287/343] perf pmu: Fix perf_pmu__parse_scale/unit() OOB access on empty sysfs file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit perf_pmu__parse_scale() reads a PMU scale file then accesses scale[sret - 1] to strip a trailing newline. Only sret < 0 is guarded, so an empty file (sret == 0) causes scale[-1] — a stack buffer underflow that reads and potentially writes out of bounds. perf_pmu__parse_unit() has the same pattern: alias->unit[sret - 1] with sret == 0 accesses the byte before the struct member, which may corrupt the adjacent pmu_name pointer field. Change both guards from sret < 0 to sret <= 0 so that empty files are treated as read errors. Fixes: 410136f5dd96b601 ("tools/perf/stat: Add event unit and scale support") Reported-by: sashiko-bot Cc: Stephane Eranian Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index f588cce60194..a550f030b85d 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -314,7 +314,7 @@ static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *al goto error; sret = read(fd, scale, sizeof(scale)-1); - if (sret < 0) + if (sret <= 0) goto error; if (scale[sret - 1] == '\n') @@ -346,7 +346,7 @@ static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *ali return -1; sret = read(fd, alias->unit, UNIT_MAX_LEN); - if (sret < 0) + if (sret <= 0) goto error; close(fd); From 52b1f9678499b13b7aeb0186d9c6f486c043283f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 21:03:55 -0300 Subject: [PATCH 288/343] tools lib api: Fix missing null termination in filename__read_int/ull() filename__read_int() passes a stack buffer to read() using the full sizeof(line) and then hands it to atoi() without null-terminating. If a sysfs file fills the 64-byte buffer exactly, atoi() reads past the array into uninitialized stack memory. filename__read_ull_base() has the same issue with strtoull(). Fix both by reading sizeof(line) - 1 bytes and explicitly null-terminating after a successful read. Fixes: 3a351127cbc682c3 ("tools lib fs: Adopt filename__read_int from tools/perf/") Reported-by: sashiko-bot Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/api/fs/fs.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c index edec23406dbc..3cc302d4c47b 100644 --- a/tools/lib/api/fs/fs.c +++ b/tools/lib/api/fs/fs.c @@ -294,11 +294,14 @@ int filename__read_int(const char *filename, int *value) { char line[64]; int fd = open(filename, O_RDONLY), err = -1; + ssize_t n; if (fd < 0) return -errno; - if (read(fd, line, sizeof(line)) > 0) { + n = read(fd, line, sizeof(line) - 1); + if (n > 0) { + line[n] = '\0'; *value = atoi(line); err = 0; } @@ -312,11 +315,14 @@ static int filename__read_ull_base(const char *filename, { char line[64]; int fd = open(filename, O_RDONLY), err = -1; + ssize_t n; if (fd < 0) return -errno; - if (read(fd, line, sizeof(line)) > 0) { + n = read(fd, line, sizeof(line) - 1); + if (n > 0) { + line[n] = '\0'; *value = strtoull(line, NULL, base); if (*value != ULLONG_MAX) err = 0; From 6eaa8ee3e2abe5112e80e94c27196bb175689469 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 21:04:50 -0300 Subject: [PATCH 289/343] perf symbols: Fix signed overflow in sysfs__read_build_id() size check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sysfs__read_build_id() reads ELF note headers from sysfs files. The note's namesz and descsz fields are used to compute the skip size: int n = namesz + descsz; if (n > (int)sizeof(bf)) Both namesz and descsz are size_t from NOTE_ALIGN() of 32-bit note header fields. Their sum can exceed INT_MAX, overflowing the signed int n to a negative value. The check n > sizeof(bf) then evaluates false (negative < positive in signed comparison), and read(fd, bf, n) reinterprets the negative n as a huge size_t count — the kernel writes up to MAX_RW_COUNT bytes into the 8192-byte stack buffer. In practice the overflow is bounded by the sysfs file's actual size, so a real sysfs notes file won't trigger it organically. But crafted input (e.g. via a mounted debugfs/sysfs image) could. Fix by validating namesz and descsz individually against the buffer size before summing, and change n to size_t to avoid the signed overflow entirely. Fixes: f1617b40596cb341 ("perf symbols: Record the build_ids of kernel modules too") Reported-by: sashiko-bot Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index c2bdfd0003df..8fb25a5692b5 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -964,14 +964,17 @@ int sysfs__read_build_id(const char *filename, struct build_id *bid) } else if (read(fd, bf, descsz) != (ssize_t)descsz) break; } else { - int n = namesz + descsz; + size_t n; - if (n > (int)sizeof(bf)) { + /* int sum of namesz+descsz can overflow negative, bypassing size check */ + if (namesz > sizeof(bf) || descsz > sizeof(bf) - namesz) { n = sizeof(bf); pr_debug("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n", __func__, filename, nhdr.n_namesz, nhdr.n_descsz); + } else { + n = namesz + descsz; } - if (read(fd, bf, n) != n) + if (read(fd, bf, n) != (ssize_t)n) break; } } From 9c74f0aab398cb32ab250401f323c0fdc9a3a496 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 21:05:15 -0300 Subject: [PATCH 290/343] perf symbols: Bounds-check .gnu_debuglink section data filename__read_debuglink() copies .gnu_debuglink section data into a caller-provided buffer via: strncpy(debuglink, data->d_buf, size); where size is PATH_MAX. If the ELF section is smaller than size and lacks a null terminator, strncpy reads past data->d_buf into adjacent memory. A malformed ELF file can trigger this, potentially causing a segfault or leaking heap data. Additionally, strncpy does not guarantee null termination when the source fills the buffer. Replace with an explicit memcpy bounded by both the output buffer size and the actual section data size (data->d_size), followed by explicit null termination. Fixes: e5a1845fc0aeca85 ("perf symbols: Split out util/symbol-elf.c") Reported-by: sashiko-bot Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 8fb25a5692b5..51e7cfe0f593 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1027,7 +1027,14 @@ int filename__read_debuglink(const char *filename, char *debuglink, goto out_elf_end; /* the start of this section is a zero-terminated string */ - strncpy(debuglink, data->d_buf, size); + if (data->d_size > 0) { + size_t len = min(size - 1, data->d_size); + + memcpy(debuglink, data->d_buf, len); + debuglink[len] = '\0'; + } else { + debuglink[0] = '\0'; + } err = 0; From b8acc68f1382a3f380a0e7320a95d328ac5e9027 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 21:06:12 -0300 Subject: [PATCH 291/343] perf tools: Use mkostemp() for O_CLOEXEC on temporary files mkstemp() creates file descriptors without the close-on-exec flag. These fds leak to child processes spawned during symbol resolution (addr2line, objdump), wasting descriptors and potentially exposing temporary file contents. Replace mkstemp() with mkostemp(tmpbuf, O_CLOEXEC) at all three call sites: - filename__decompress() in dso.c - read_gnu_debugdata() in symbol-elf.c - kcore__init() in symbol-elf.c Fixes: 42b3fa670825983f ("perf tools: Introduce dso__decompress_kmodule_{fd,path}") Fixes: b10f74308e130527 ("perf symbol: Support .gnu_debugdata for symbols") Fixes: afba19d9dc8eba66 ("perf symbols: Workaround objdump difficulties with kcore") Reported-by: sashiko-bot Cc: Adrian Hunter Cc: Namhyung Kim Cc: Stephen Brennan Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 2 +- tools/perf/util/symbol-elf.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index fb2e78fe2aa8..ee06a252a54d 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -346,7 +346,7 @@ int filename__decompress(const char *name, char *pathname, if (!compressions[comp].is_compressed(name)) return open(name, O_RDONLY | O_CLOEXEC); - fd = mkstemp(tmpbuf); + fd = mkostemp(tmpbuf, O_CLOEXEC); if (fd < 0) { *err = errno; return -1; diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 51e7cfe0f593..36a0304707e1 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1119,9 +1119,9 @@ static Elf *read_gnu_debugdata(struct dso *dso, Elf *elf, const char *name, int return NULL; } - temp_fd = mkstemp(temp_filename); + temp_fd = mkostemp(temp_filename, O_CLOEXEC); if (temp_fd < 0) { - pr_debug("%s: mkstemp: %m\n", __func__); + pr_debug("%s: mkostemp: %m\n", __func__); *dso__load_errno(dso) = -errno; fclose(wrapped); return NULL; @@ -1993,7 +1993,7 @@ static int kcore__init(struct kcore *kcore, char *filename, int elfclass, kcore->elfclass = elfclass; if (temp) - kcore->fd = mkstemp(filename); + kcore->fd = mkostemp(filename, O_CLOEXEC); else kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0400); if (kcore->fd == -1) From b6bb3b005dcdd960b8e0b7f9d6869132b3de08d5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 21:06:54 -0300 Subject: [PATCH 292/343] perf intel-pt: Fix snprintf size tracking bug in insn decoder dump_insn() tracks remaining buffer space with a 'left' variable, but the loop subtracts the cumulative offset 'n' each iteration instead of just the per-iteration delta: n += snprintf(x->out + n, left, "%02x ", inbuf[i]); left -= n; /* BUG: n is cumulative, not the delta */ After two iterations left goes massively negative, wrapping to a huge value when passed as size_t to snprintf(), disabling all bounds checking for the rest of the loop. Switch to scnprintf() accumulation using sizeof(x->out) - n as the remaining space, which is always correct and eliminates the separate 'left' variable entirely. Fixes: 48d02a1d5c137d36 ("perf script: Add 'brstackinsn' for branch stacks") Reported-by: sashiko-bot Cc: Adrian Hunter Cc: Andi Kleen Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- .../util/intel-pt-decoder/intel-pt-insn-decoder.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c index 72c7a4e15d61..f90fcbc4302d 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c @@ -220,7 +220,6 @@ const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused, { struct insn insn; int n, i, ret; - int left; ret = insn_decode(&insn, inbuf, inlen, x->is64bit ? INSN_MODE_64 : INSN_MODE_32); @@ -229,13 +228,9 @@ const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused, return ""; if (lenp) *lenp = insn.length; - left = sizeof(x->out); - n = snprintf(x->out, left, "insn: "); - left -= n; - for (i = 0; i < insn.length; i++) { - n += snprintf(x->out + n, left, "%02x ", inbuf[i]); - left -= n; - } + n = scnprintf(x->out, sizeof(x->out), "insn: "); + for (i = 0; i < insn.length; i++) + n += scnprintf(x->out + n, sizeof(x->out) - n, "%02x ", inbuf[i]); return x->out; } From 31d596054550f793508abe7dd593853ece47d428 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 22:37:55 -0300 Subject: [PATCH 293/343] perf tools: Fix thread__set_comm_from_proc() on empty comm file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit thread__set_comm_from_proc() calls procfs__read_str() then strips the trailing newline via comm[sz - 1] = '\0'. procfs__read_str() allocates the buffer before reading, so on an empty /proc/pid/comm (reachable during late exit teardown) it returns success with sz = 0 and an unterminated heap buffer. The sz - 1 underflow was the original sashiko finding: it writes a null byte before the allocation. But even with a sz > 0 guard on the newline strip, the unterminated buffer would still be passed to thread__set_comm() which calls strlen() — an unbounded heap read. Fix by treating sz == 0 as failure: free the buffer and return -1. This is consistent with pmu.c's perf_pmu__parse_scale/unit which already treat len == 0 from filename__read_str as an error. Fixes: 2f3027ac28bf6bc3 ("perf thread: Introduce method to set comm from /proc/pid/self") Reported-by: sashiko-bot Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index ba33c0dfc18f..e483ffcb5d93 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -295,6 +295,11 @@ int thread__set_comm_from_proc(struct thread *thread) if (!(snprintf(path, sizeof(path), "%d/task/%d/comm", thread__pid(thread), thread__tid(thread)) >= (int)sizeof(path)) && procfs__read_str(path, &comm, &sz) == 0) { + /* sz==0: read got nothing, e.g. race during exit teardown */ + if (sz == 0) { + free(comm); + return -1; + } comm[sz - 1] = '\0'; err = thread__set_comm(thread, comm, 0); } From 1847c5fae344a0fb9cc0f95be40b378359c6fc3b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 22:38:26 -0300 Subject: [PATCH 294/343] perf hwmon: Fix off-by-one null termination on sysfs reads Three functions read sysfs files into fixed-size stack buffers using the full buffer size, then null-terminate at buf[read_len]. If the read fills the buffer exactly, read_len equals sizeof(buf) and the null byte writes one past the array, corrupting an adjacent stack variable. Fix all three by reading sizeof(buf) - 1 bytes, reserving space for the null terminator: - hwmon_pmu__read_events(): buf[128] - hwmon_pmu__describe_items(): buf[64] - evsel__hwmon_pmu_read(): buf[32] Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") Reported-by: sashiko-bot Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hwmon_pmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c index dbf6a71af47f..d895cd74f2a0 100644 --- a/tools/perf/util/hwmon_pmu.c +++ b/tools/perf/util/hwmon_pmu.c @@ -289,7 +289,7 @@ static int hwmon_pmu__read_events(struct hwmon_pmu *pmu) if (fd < 0) continue; - read_len = read(fd, buf, sizeof(buf)); + read_len = read(fd, buf, sizeof(buf) - 1); while (read_len > 0 && buf[read_len - 1] == '\n') read_len--; @@ -432,7 +432,7 @@ static size_t hwmon_pmu__describe_items(struct hwmon_pmu *hwm, char *out_buf, si is_alarm ? "_alarm" : ""); fd = openat(dir, buf, O_RDONLY); if (fd > 0) { - ssize_t read_len = read(fd, buf, sizeof(buf)); + ssize_t read_len = read(fd, buf, sizeof(buf) - 1); while (read_len > 0 && buf[read_len - 1] == '\n') read_len--; @@ -816,7 +816,7 @@ int evsel__hwmon_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) count = perf_counts(evsel->counts, cpu_map_idx, thread); fd = FD(evsel, cpu_map_idx, thread); - len = pread(fd, buf, sizeof(buf), 0); + len = pread(fd, buf, sizeof(buf) - 1, 0); if (len <= 0) { count->lost++; return -EINVAL; From ae75956c166fe169b8c137bf375305fc97820a62 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 22:38:48 -0300 Subject: [PATCH 295/343] perf hwmon: Use scnprintf() in hwmon_pmu__for_each_event() hwmon_pmu__for_each_event() formats description strings via: len = snprintf(desc_buf, sizeof(desc_buf), "%s in unit %s named %s.", ...); len += hwmon_pmu__describe_items(hwm, desc_buf + len, sizeof(desc_buf) - len, ...); If value->label is long enough to cause snprintf() to truncate, it returns the would-have-been-written count, making len exceed sizeof(desc_buf). The subsequent sizeof(desc_buf) - len underflows to a huge size_t value, disabling bounds checking in hwmon_pmu__describe_items(). The alias_buf snprintf has the same issue. Switch both to scnprintf() which returns actual bytes written. Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") Reported-by: sashiko-bot Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hwmon_pmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c index d895cd74f2a0..fbfb872ceb18 100644 --- a/tools/perf/util/hwmon_pmu.c +++ b/tools/perf/util/hwmon_pmu.c @@ -514,14 +514,14 @@ int hwmon_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callb int ret; size_t len; - len = snprintf(alias_buf, sizeof(alias_buf), "%s%d", - hwmon_type_strs[key.type], key.num); + scnprintf(alias_buf, sizeof(alias_buf), "%s%d", + hwmon_type_strs[key.type], key.num); if (!info.name) { info.name = info.alias; info.alias = NULL; } - len = snprintf(desc_buf, sizeof(desc_buf), "%s in unit %s named %s.", + len = scnprintf(desc_buf, sizeof(desc_buf), "%s in unit %s named %s.", hwmon_desc[key.type], pmu->name + 6, value->label ?: info.name); From e1a2c9d70b312acc262f6be936dd5bbd9bbc6236 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 22:39:53 -0300 Subject: [PATCH 296/343] perf hwmon: Fix parse_hwmon_filename() strlcpy buffer overflow parse_hwmon_filename() strips the "_alarm" suffix from event names by copying into a 24-byte stack buffer: strlcpy(fn_type, fn_item, fn_item_len - 5); The third argument is the source length minus the suffix, not the destination buffer capacity. A long event name ending in "_alarm" can have fn_item_len - 5 > sizeof(fn_type), causing strlcpy() to write past the 24-byte fn_type[] array. The assert() only validates that the longest *valid* hwmon item fits, but does not protect against crafted input. Clamp the strlcpy size to min(fn_item_len - 5, sizeof(fn_type)). Fixes: 4810b761f812da3c ("perf hwmon_pmu: Add hwmon filename parser") Reported-by: sashiko-bot Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hwmon_pmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c index fbfb872ceb18..bdcbe887579a 100644 --- a/tools/perf/util/hwmon_pmu.c +++ b/tools/perf/util/hwmon_pmu.c @@ -202,7 +202,8 @@ bool parse_hwmon_filename(const char *filename, fn_item_len = strlen(fn_item); if (fn_item_len > 6 && !strcmp(&fn_item[fn_item_len - 6], "_alarm")) { assert(strlen(LONGEST_HWMON_ITEM_STR) < sizeof(fn_type)); - strlcpy(fn_type, fn_item, fn_item_len - 5); + /* fn_item_len - 5 strips "_alarm"; clamp to buffer size */ + strlcpy(fn_type, fn_item, min_t(size_t, fn_item_len - 5, sizeof(fn_type))); fn_item = fn_type; *alarm = true; } From 1b4e9fbdeabc549965e70ac0cd8095d57ff6df06 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 22:40:20 -0300 Subject: [PATCH 297/343] perf symbols: Bounds-check descsz in sysfs__read_build_id() GNU fallback When sysfs__read_build_id() matches NT_GNU_BUILD_ID with the right namesz but the name content is not "GNU", it falls back to reading descsz bytes into the stack buffer bf[BUFSIZ]: } else if (read(fd, bf, descsz) != (ssize_t)descsz) Unlike the else branch which validates namesz + descsz against sizeof(bf), this path passes descsz directly to read() without any bounds check. A crafted sysfs file with a large n_descsz overflows the 8192-byte stack buffer. Add a descsz > sizeof(bf) check before the read, breaking out of the loop on oversized values. Fixes: e5a1845fc0aeca85 ("perf symbols: Split out util/symbol-elf.c") Reported-by: sashiko-bot Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 36a0304707e1..06cfb84f86eb 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -961,8 +961,13 @@ int sysfs__read_build_id(const char *filename, struct build_id *bid) err = 0; break; } - } else if (read(fd, bf, descsz) != (ssize_t)descsz) - break; + } else { + /* descsz from untrusted file — clamp to buffer */ + if (descsz > sizeof(bf)) + break; + if (read(fd, bf, descsz) != (ssize_t)descsz) + break; + } } else { size_t n; From 51cdb188edeaf389e4377859b9c483c19ce5a259 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jun 2026 22:43:09 -0300 Subject: [PATCH 298/343] perf tools: Fix uninitialized pathname on uncompressed fallback in filename__decompress() filename__decompress() has an early return path for files that are not actually compressed. This path returns the fd from open() directly but never writes to the pathname output parameter, leaving the caller with an uninitialized buffer despite a successful return. Callers like dso__decompress_kmodule_path() pass pathname to decompress_kmodule() which uses it to set the decompressed file path. If pathname is uninitialized, subsequent operations on the path produce undefined behavior. Fix by setting pathname to an empty string on the uncompressed path. Callers already check for an empty pathname to distinguish temporary decompressed files (which need unlink) from the original file. Reported-by: sashiko-bot Fixes: 7ac22b088afe26a4 ("perf tools: Add filename__decompress function") Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/code-reading.c | 7 +++++-- tools/perf/util/disasm.c | 7 +++++-- tools/perf/util/dso.c | 12 +++++++++--- tools/perf/util/symbol-elf.c | 6 ++++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 47043a3a2fb4..e82ecdc95777 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -471,8 +471,11 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, goto out; } - decomp = true; - objdump_name = decomp_name; + /* empty pathname means file wasn't actually compressed */ + if (decomp_name[0] != '\0') { + decomp = true; + objdump_name = decomp_name; + } } /* Read the object code using objdump */ diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c index 59ba88e1f744..0a1a7e9cf3ef 100644 --- a/tools/perf/util/disasm.c +++ b/tools/perf/util/disasm.c @@ -1577,8 +1577,11 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args) if (dso__decompress_kmodule_path(dso, symfs_filename, tmp, sizeof(tmp)) < 0) return -1; - decomp = true; - strcpy(symfs_filename, tmp); + /* empty pathname means file wasn't actually compressed */ + if (tmp[0] != '\0') { + decomp = true; + strcpy(symfs_filename, tmp); + } } /* diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index ee06a252a54d..6a34717c9f31 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -343,8 +343,11 @@ int filename__decompress(const char *name, char *pathname, * To keep this transparent, we detect this and return the file * descriptor to the uncompressed file. */ - if (!compressions[comp].is_compressed(name)) + if (!compressions[comp].is_compressed(name)) { + if (pathname && len > 0) + pathname[0] = '\0'; return open(name, O_RDONLY | O_CLOEXEC); + } fd = mkostemp(tmpbuf, O_CLOEXEC); if (fd < 0) { @@ -598,8 +601,11 @@ static char *dso__get_filename(struct dso *dso, const char *root_dir, goto out; } - *decomp = true; - strcpy(name, newpath); + /* empty pathname means file wasn't actually compressed */ + if (newpath[0] != '\0') { + *decomp = true; + strcpy(name, newpath); + } } return name; diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 06cfb84f86eb..10902a5dc6db 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -920,12 +920,14 @@ int filename__read_build_id(const char *filename, struct build_id *bid) return -1; } close(fd); - filename = path; + /* non-empty path means a temp file was created */ + if (path[0] != '\0') + filename = path; } err = read_build_id(filename, bid); - if (m.comp) + if (m.comp && filename == path) unlink(filename); return err; } From 34d3d93fac6d92237cb9d730ca04c37ed361c7a6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 8 Jun 2026 07:03:04 -0300 Subject: [PATCH 299/343] perf hwmon: Guard label read against empty or failed reads hwmon_pmu__read_events() reads label files with read() into a stack buffer, strips trailing newlines, then checks buf[0] == '\0'. When read() returns 0 (empty file) or -1 (error), the buffer is never written, so buf[0] reads uninitialized stack memory. If the garbage byte is non-zero, the code falls through to strdup(buf) which copies arbitrary stack data as the label string. Fix by checking read_len <= 0 before accessing buf contents, closing the fd and skipping the entry. Reported-by: sashiko-bot Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hwmon_pmu.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c index bdcbe887579a..efd3067a2e59 100644 --- a/tools/perf/util/hwmon_pmu.c +++ b/tools/perf/util/hwmon_pmu.c @@ -295,8 +295,11 @@ static int hwmon_pmu__read_events(struct hwmon_pmu *pmu) while (read_len > 0 && buf[read_len - 1] == '\n') read_len--; - if (read_len > 0) - buf[read_len] = '\0'; + if (read_len <= 0) { + close(fd); + continue; + } + buf[read_len] = '\0'; if (buf[0] == '\0') { pr_debug("hwmon_pmu: empty label file %s %s\n", From 2ea64782a428bed74f595961e651ceb8c4c5bf22 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 8 Jun 2026 07:04:25 -0300 Subject: [PATCH 300/343] perf tools: Use snprintf() in dso__read_running_kernel_build_id() dso__read_running_kernel_build_id() uses sprintf() to format a sysfs path from machine->root_dir into a PATH_MAX buffer. If root_dir is close to PATH_MAX in length, appending "/sys/kernel/notes" (18 bytes) overflows the stack buffer. Switch to snprintf() with sizeof(path) to prevent the overflow. Reported-by: sashiko-bot Fixes: cdd059d731eeb466 ("perf tools: Move dso_* related functions into dso object") Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 6a34717c9f31..5d0179758738 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1779,7 +1779,7 @@ void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine) if (machine__is_default_guest(machine)) return; - sprintf(path, "%s/sys/kernel/notes", machine->root_dir); + snprintf(path, sizeof(path), "%s/sys/kernel/notes", machine->root_dir); sysfs__read_build_id(path, &bid); dso__set_build_id(dso, &bid); } From 438ece06185696e14c63c6113d5e2d34ec0a9680 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 8 Jun 2026 07:05:19 -0300 Subject: [PATCH 301/343] tools lib api: Fix filename__write_int() writing uninitialized stack data filename__write_int() formats an integer into a 64-byte buffer with sprintf() then passes sizeof(buf) (64) as the write length. This writes all 64 bytes including uninitialized stack data past the formatted string. Most sysfs files reject the oversized write, making the function always return -1. Fix by capturing the sprintf() return value and using it as the write length. Reported-by: sashiko-bot Fixes: 3b00ea938653d136 ("tools lib api fs: Add sysfs__write_int function") Cc: Kan Liang Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/api/fs/fs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c index 3cc302d4c47b..d16911818d4d 100644 --- a/tools/lib/api/fs/fs.c +++ b/tools/lib/api/fs/fs.c @@ -376,12 +376,13 @@ int filename__write_int(const char *filename, int value) { int fd = open(filename, O_WRONLY), err = -1; char buf[64]; + int len; if (fd < 0) return -errno; - sprintf(buf, "%d", value); - if (write(fd, buf, sizeof(buf)) == sizeof(buf)) + len = sprintf(buf, "%d", value); + if (write(fd, buf, len) == len) err = 0; close(fd); From fd1f70776add263f8ef38a87ae593c75303f1dcd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 8 Jun 2026 08:10:18 -0300 Subject: [PATCH 302/343] tools lib api: Fix mount_overload() snprintf truncation and toupper range mount_overload() builds an environment variable name like "PERF_SYSFS_ENVIRONMENT" from fs->name. Two bugs: 1) snprintf() uses name_len as the buffer size instead of sizeof(upper_name). For fs->name = "sysfs" (len=5), the output is truncated to "PERF" (4 chars + null), so getenv() never finds the intended variable. 2) mem_toupper() only uppercases name_len bytes, converting just the "PERF" prefix rather than the full string including the filesystem name portion. Fix by using sizeof(upper_name) for snprintf and strlen(upper_name) for mem_toupper, so the full "PERF_SYSFS_ENVIRONMENT" string is correctly formatted and uppercased. Reported-by: sashiko-bot Fixes: 73ca85ad364769ff ("tools lib api fs: Add FSTYPE__mount() method") Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/api/fs/fs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c index d16911818d4d..cbd8eab0d1df 100644 --- a/tools/lib/api/fs/fs.c +++ b/tools/lib/api/fs/fs.c @@ -261,8 +261,8 @@ static const char *mount_overload(struct fs *fs) /* "PERF_" + name + "_ENVIRONMENT" + '\0' */ char upper_name[5 + name_len + 12 + 1]; - snprintf(upper_name, name_len, "PERF_%s_ENVIRONMENT", fs->name); - mem_toupper(upper_name, name_len); + snprintf(upper_name, sizeof(upper_name), "PERF_%s_ENVIRONMENT", fs->name); + mem_toupper(upper_name, strlen(upper_name)); return getenv(upper_name) ?: *fs->mounts; } From 903b0526dcf86d030c5970b4b0a67f9c227368e2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 8 Jun 2026 08:10:43 -0300 Subject: [PATCH 303/343] perf bpf: Add NULL check for btf__type_by_id() in synthesize_bpf_prog_name() synthesize_bpf_prog_name() calls btf__type_by_id() and immediately dereferences the result via t->name_off without checking for NULL. btf__type_by_id() returns NULL when the type_id is invalid or out of range. When processing perf.data files, finfo->type_id comes from untrusted input, so an invalid ID causes a NULL pointer dereference. Fix by checking t for NULL before dereferencing. Reported-by: sashiko-bot Fixes: fc462ac75b36daaa ("perf bpf: Extract logic to create program names from perf_event__synthesize_one_bpf_prog()") Cc: Song Liu Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 2c09842469f1..fe01551dc3e6 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -146,7 +146,8 @@ static int synthesize_bpf_prog_name(char *buf, int size, if (btf) { finfo = func_infos + sub_id * info->func_info_rec_size; t = btf__type_by_id(btf, finfo->type_id); - short_name = btf__name_by_offset(btf, t->name_off); + if (t) + short_name = btf__name_by_offset(btf, t->name_off); } else if (sub_id == 0 && sub_prog_cnt == 1) { /* no subprog */ if (info->name[0]) From aece2b8966fc8de5be46ee9287d0f60d6690c300 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 8 Jun 2026 08:11:28 -0300 Subject: [PATCH 304/343] perf bpf: Fix map data leak in bpf_metadata_create() on alloc failure bpf_metadata_create() calls bpf_metadata_read_map_data() which allocates map.btf and map.rodata. If the subsequent bpf_metadata_alloc() fails, the code does 'continue' which skips bpf_metadata_free_map_data(), permanently leaking both allocations. Fix by calling bpf_metadata_free_map_data() before continue. Reported-by: sashiko-bot Fixes: ab38e84ba9a80581 ("perf record: collect BPF metadata from existing BPF programs") Cc: Blake Jones Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-event.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index fe01551dc3e6..b65ad28cd950 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -395,8 +395,10 @@ static struct bpf_metadata *bpf_metadata_create(struct bpf_prog_info *info) continue; metadata = bpf_metadata_alloc(info->nr_prog_tags, map.num_vars); - if (!metadata) + if (!metadata) { + bpf_metadata_free_map_data(&map); continue; + } bpf_metadata_fill_event(&map, &metadata->event->bpf_metadata); From a0e4362a3e7b592f1d58949ffe3d6decad39a17c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 8 Jun 2026 08:12:04 -0300 Subject: [PATCH 305/343] perf bpf: Fix metadata leak in perf_env__add_bpf_info() on duplicate insert When perf_env__insert_bpf_prog_info() returns false (duplicate program), the error path frees info_linear and info_node but not info_node->metadata. If bpf_metadata_create() had succeeded, the metadata allocation is permanently leaked. Fix by calling bpf_metadata_free() on info_node->metadata before freeing info_node. bpf_metadata_free() handles NULL, so this is safe even when bpf_metadata_create() returned NULL. Reported-by: sashiko-bot Fixes: fdc3441f2d317b40 ("perf record: collect BPF metadata from new programs") Cc: Blake Jones Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-event.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index b65ad28cd950..c4594969d767 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -873,6 +873,7 @@ static int perf_env__add_bpf_info(struct perf_env *env, u32 id) if (!perf_env__insert_bpf_prog_info(env, info_node)) { pr_debug("%s: duplicate add bpf info request for id %u\n", __func__, btf_id); + bpf_metadata_free(info_node->metadata); free(info_linear); free(info_node); goto out; From acc56d3941fc2997a5a21ea9233a8ac3d87c4f2f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 8 Jun 2026 08:12:34 -0300 Subject: [PATCH 306/343] perf symbols: Add bounds checks to elf_read_build_id() note iteration elf_read_build_id() iterates ELF notes using pointer arithmetic driven by n_namesz and n_descsz from the note headers. Neither the note header read nor the subsequent name/desc advances are checked against the section boundary. A malformed ELF file with oversized note sizes causes out-of-bounds reads past the section data buffer. Add two bounds checks: verify the note header fits within the remaining section data, and verify that namesz + descsz (after alignment) fits before advancing the pointer. Fixes: fd7a346ea292074e ("perf symbols: Filename__read_build_id should look at .notes section too") Reported-by: sashiko-bot Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 10902a5dc6db..d84e2e031d43 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -835,10 +835,24 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size) ptr = data->d_buf; while (ptr < (data->d_buf + data->d_size)) { GElf_Nhdr *nhdr = ptr; - size_t namesz = NOTE_ALIGN(nhdr->n_namesz), - descsz = NOTE_ALIGN(nhdr->n_descsz); + size_t namesz, descsz, remaining; const char *name; + /* ensure the note header fits within the section */ + if (ptr + sizeof(*nhdr) > data->d_buf + data->d_size) + break; + + namesz = NOTE_ALIGN(nhdr->n_namesz); + descsz = NOTE_ALIGN(nhdr->n_descsz); + + /* validate individually to avoid size_t overflow on 32-bit */ + remaining = data->d_buf + data->d_size - ptr - sizeof(*nhdr); + if (namesz > remaining || descsz > remaining - namesz) { + pr_warning("%s: oversized note: n_namesz=%u, n_descsz=%u\n", + __func__, nhdr->n_namesz, nhdr->n_descsz); + break; + } + ptr += sizeof(*nhdr); name = ptr; ptr += namesz; From 52e582e316c48c53bb3082c29f7862ebc554087e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 16:09:45 -0300 Subject: [PATCH 307/343] perf symbols: Add bounds checks to read_build_id() note iteration in minimal build symbol-minimal.c's read_build_id() iterates ELF notes with the same pattern as symbol-elf.c's elf_read_build_id(): pointer arithmetic driven by n_namesz and n_descsz from 32-bit note header fields, without validating that the name and desc fit within the note section data. A malformed ELF file with oversized note sizes causes out-of-bounds reads past the section data buffer. Add the same bounds check as the libelf path: validate namesz and descsz individually against remaining data before advancing the pointer, avoiding size_t overflow on 32-bit. Fixes: b691f64360ecec49 ("perf symbols: Implement poor man's ELF parser") Reported-by: sashiko-bot Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-minimal.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 8221dc9868f7..091071d06416 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c @@ -1,3 +1,4 @@ +#include "debug.h" #include "dso.h" #include "symbol.h" #include "symsrc.h" @@ -44,7 +45,7 @@ static int read_build_id(void *note_data, size_t note_len, struct build_id *bid, ptr = note_data; while ((ptr + sizeof(*nhdr)) < (note_data + note_len)) { const char *name; - size_t namesz, descsz; + size_t namesz, descsz, remaining; nhdr = ptr; if (need_swap) { @@ -56,6 +57,14 @@ static int read_build_id(void *note_data, size_t note_len, struct build_id *bid, namesz = NOTE_ALIGN(nhdr->n_namesz); descsz = NOTE_ALIGN(nhdr->n_descsz); + /* validate individually to avoid size_t overflow on 32-bit */ + remaining = note_data + note_len - ptr - sizeof(*nhdr); + if (namesz > remaining || descsz > remaining - namesz) { + pr_warning("%s: oversized note: n_namesz=%u, n_descsz=%u\n", + __func__, nhdr->n_namesz, nhdr->n_descsz); + break; + } + ptr += sizeof(*nhdr); name = ptr; ptr += namesz; From 9e3fcab6fbecebbcffeafeb5db612a57688cb7f4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 4 Jun 2026 15:06:27 -0700 Subject: [PATCH 308/343] perf test: Truncate printed test descriptions dynamically to avoid terminal wrapping When test descriptions are extremely long (e.g., the truncated perf.data graceful handling test is 103 characters long), they wrap across terminal boundaries. Because the ANSI escape code to delete the line (PERF_COLOR_DELETE_LINE) only clears a single terminal line, visual wrapping leaves orphan wrapped lines on the screen, which results in the test description being printed multiple times. Resolve this by checking the terminal width (get_term_dimensions) and dynamically truncating the printed test description to fit within the available columns, leaving safety space for the prefix index and status suffix. Also, remove the width padding from the test suite headers which do not display inline status messages. This prevents their trailing colons from wrapping onto new lines on standard width terminals. Finally, avoid GCC 16's -Wformat-truncation warnings by delegating the description padding to pr_info's %-*s format specifier instead of padding within a temporary buffer, and clamp the truncation limit to the temporary buffer's size. JUnit XML output and the failure summary report still print the full, untruncated test descriptions. Assisted-by: Gemini-CLI:Google Gemini 3.1 Pro Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/builtin-test.c | 66 +++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index afc06cec4954..7e75f590f225 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include "util/term.h" #include "builtin.h" #include "config.h" #include "hist.h" @@ -413,19 +415,69 @@ static char *xml_escape(const char *str) return res ? res : strdup(""); } +static const char *format_test_description(const char *desc, int max_desc_width, + char *buf, size_t buf_sz) +{ + int len = strlen(desc); + + /* + * Clamp to buf_sz to prevent GCC format-truncation warnings + * when terminal width is very large. + */ + if (max_desc_width >= (int)buf_sz) + max_desc_width = buf_sz - 1; + + if (len > max_desc_width) { + snprintf(buf, buf_sz, "%.*s...", max_desc_width - 3, desc); + return buf; + } + return desc; +} + static int print_test_result(struct test_suite *t, int curr_suite, int curr_test_case, int result, int width, int running, const char *err_output, double elapsed) { + char desc_buf[256]; + const char *desc = test_description(t, curr_test_case); + struct winsize ws; + int max_desc_area_width; + int target_desc_area_width; + int desc_padding; + + get_term_dimensions(&ws); + /* + * Total terminal columns minus space for status e.g. " Running (12 active)" + * which is 20 chars, plus a margin of 3 chars = 23 chars. + */ + max_desc_area_width = ws.ws_col - 23; + if (max_desc_area_width < 40) + max_desc_area_width = 40; + + /* Standard test has prefix "%3d: " which is 5 chars */ + target_desc_area_width = width + 5; + if (target_desc_area_width > max_desc_area_width) + target_desc_area_width = max_desc_area_width; + if (test_suite__num_test_cases(t) > 1) { char prefix[32]; int len = snprintf(prefix, sizeof(prefix), "%3d.%1d:", curr_suite + 1, curr_test_case + 1); - int subw = len >= 4 ? width + 4 - len : width; - pr_info("%s %-*s:", prefix, subw, test_description(t, curr_test_case)); - } else - pr_info("%3d: %-*s:", curr_suite + 1, width, test_description(t, curr_test_case)); + desc_padding = target_desc_area_width - (len + 1); + if (desc_padding < 20) + desc_padding = 20; + + desc = format_test_description(desc, desc_padding, desc_buf, sizeof(desc_buf)); + pr_info("%s %-*s:", prefix, desc_padding, desc); + } else { + desc_padding = target_desc_area_width - 5; + if (desc_padding < 20) + desc_padding = 20; + + desc = format_test_description(desc, desc_padding, desc_buf, sizeof(desc_buf)); + pr_info("%3d: %-*s:", curr_suite + 1, desc_padding, desc); + } switch (result) { case TEST_RUNNING: @@ -709,7 +761,7 @@ static void finish_test(struct child_test **child_tests, int running_test, int c * sub test names. */ if (test_suite__num_test_cases(t) > 1 && curr_test_case == 0) - pr_info("%3d: %-*s:\n", curr_suite + 1, width, test_description(t, -1)); + pr_info("%3d: %s:\n", curr_suite + 1, test_description(t, -1)); /* * Busy loop reading from the child's stdout/stderr that are set to be @@ -985,7 +1037,7 @@ static int finish_tests_parallel(struct child_test **child_tests, size_t num_tes if (next_child) { if (test_suite__num_test_cases(next_child->test) > 1 && last_suite_printed != next_child->suite_num) { - pr_info("%3d: %-*s:\n", next_child->suite_num + 1, width, + pr_info("%3d: %s:\n", next_child->suite_num + 1, test_description(next_child->test, -1)); last_suite_printed = next_child->suite_num; } @@ -1049,7 +1101,7 @@ static int finish_tests_parallel(struct child_test **child_tests, size_t num_tes if (test_suite__num_test_cases(child->test) > 1 && last_suite_printed != child->suite_num) { - pr_info("%3d: %-*s:\n", child->suite_num + 1, width, + pr_info("%3d: %s:\n", child->suite_num + 1, test_description(child->test, -1)); last_suite_printed = child->suite_num; } From 904708945c07b2b27558b6ffe8923b3df99448f4 Mon Sep 17 00:00:00 2001 From: James Clark Date: Thu, 11 Jun 2026 12:13:46 +0100 Subject: [PATCH 309/343] perf test: Compile named_threads workload with -O0 The work loop relies on the compiler not optimizing it away, although named_threads_work is not static for that reason, the compiler could still do it. Fix it by compiling without optimization. Also add -fno-inline for consistency and in case anyone wants to look at callstacks. Fixes: b5dd510be55e8670 ("perf test: Add named_threads workload") Closes: https://lore.kernel.org/all/20260609160001.2739E1F00893@smtp.kernel.org Reported-by: sashiko-bot Reviewed-by: Leo Yan Signed-off-by: James Clark Cc: Ian Rogers Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/workloads/Build | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/tests/workloads/Build b/tools/perf/tests/workloads/Build index 75b377934a0e..7bb4b9829ba2 100644 --- a/tools/perf/tests/workloads/Build +++ b/tools/perf/tests/workloads/Build @@ -26,3 +26,4 @@ CFLAGS_datasym.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE CFLAGS_traploop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE CFLAGS_inlineloop.o = -g -O2 CFLAGS_deterministic.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE +CFLAGS_named_threads.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE From 325aabebbbc0520f95db3974d46e13a081cf6c28 Mon Sep 17 00:00:00 2001 From: Chun-Tse Shao Date: Thu, 11 Jun 2026 14:56:32 -0700 Subject: [PATCH 310/343] perf stat: Fix false NMI watchdog warning in aggregation modes In aggregation modes (e.g. --per-socket, --per-die, etc.), a counter might not be scheduled or counted on specific aggregate groups if it was not assigned to the CPUs belonging to those groups. However, the printout() check triggers the "print_free_counters_hint" logic unconditionally for any supported counter with a missing count. This results in a false "Some events weren't counted. Try disabling the NMI watchdog" warning. Furthermore, the NMI watchdog only reserves performance counters on core PMUs. Uncore PMU events (e.g. CHA, IMC) are not affected by the NMI watchdog, but their failures also falsely triggered this warning. This warning was originally introduced in commit 02d492e5dcb72c00 ("perf stat: Issue a HW watchdog disable hint") To fix this, restrict setting of print_free_counters_hint to only trigger for core PMU events by checking counter->pmu and counter->pmu->is_core. Example before/after: $ perf stat -M lpm_miss_lat --metric-only --per-socket -a -- sleep 1 Before: Performance counter stats for 'system wide': ns lpm_miss_lat_rem ns lpm_miss_lat_loc S0 126 202.3 207.9 S1 126 231.9 259.3 1.006029831 seconds time elapsed Some events weren't counted. Try disabling the NMI watchdog: echo 0 > /proc/sys/kernel/nmi_watchdog perf stat ... echo 1 > /proc/sys/kernel/nmi_watchdog After: Performance counter stats for 'system wide': ns lpm_miss_lat_rem ns lpm_miss_lat_loc S0 126 202.3 207.9 S1 126 231.9 259.3 1.006029831 seconds time elapsed Assisted-by: Gemini:gemini-next Reviewed-by: Ian Rogers Signed-off-by: Chun-Tse Shao Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 2b69d238858c..0a5750bb59fa 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -821,9 +821,9 @@ static void printout(struct perf_stat_config *config, struct outstate *os, ok = false; if (counter->supported) { - if (!evlist__has_hybrid_pmus(counter->evlist)) { + if (!evlist__has_hybrid_pmus(counter->evlist) && + counter->pmu && counter->pmu->is_core) config->print_free_counters_hint = 1; - } } } From 75a4888b7029a1f98613aef91f517b2ee1f03d43 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 11 Jun 2026 09:41:18 -0700 Subject: [PATCH 311/343] perf maps: Add maps__mutate_mapping During kernel ELF symbol parsing (dso__process_kernel_symbol), proc kallsyms image loading (dso__load_kernel_sym, dso__load_guest_kernel_sym), and dynamic kernel memory map alignment updates (machine__update_kernel_mmap), the loader directly modifies live virtual address boundary keys fields on map objects. If these boundaries are mutated while the map pointer actively resides inside the parent maps cache array list (kmaps) outside of any lock closure, an unsafe concurrent window is exposed where parallel worker lookup threads (e.g., inside perf top) can mistakenly assume the cache remains sorted based on stale parameters, executing binary search queries (bsearch) across an unsorted range and triggering lookup failures. Fix this by introducing maps__mutate_mapping() that explicitly acquires the parent maps write semaphore lock, executes an incoming mutation callback block to perform the field updates under lock protection, and invalidates the sorted tracking flags prior to releasing the write lock. This guarantees synchronization invariants, closing the concurrent lookup race window. The adjacent module alignment pass inside machine__create_kernel_maps() is safely preserved as a high-performance lockless pass, as its invocation lifecycle bounds remain strictly single-threaded by contract during session initialization construction. To safely support this unconditional down_write write lock mutator without recursive read-to-write self-deadlock upgrades during lazy symbol loading, we introduce a public maps__load_maps() API. It copies map pointers under a brief read lock and force-loads all modules locklessly outside the lock. Callers (such as perf inject) must pre-load all kernel symbol maps up front at startup using maps__load_maps(), completely bypassing dynamic runtime mutations. Fixes: 39b12f781271 ("perf tools: Make it possible to read object code from vmlinux") Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Gabriel Marin Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 32 ++++--- tools/perf/util/maps.c | 156 ++++++++++++++++++++++++++++------- tools/perf/util/maps.h | 3 + tools/perf/util/symbol-elf.c | 41 +++++---- tools/perf/util/symbol.c | 17 +++- 5 files changed, 187 insertions(+), 62 deletions(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index da1ad58758af..1ea06fde14e0 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1539,22 +1539,30 @@ static void machine__set_kernel_mmap(struct machine *machine, map__set_end(machine->vmlinux_map, ~0ULL); } -static int machine__update_kernel_mmap(struct machine *machine, - u64 start, u64 end) +struct kernel_mmap_mutation_ctx { + u64 start; + u64 end; +}; + +static int kernel_mmap_mutate_cb(struct map *map, void *data) { - struct map *orig, *updated; - int err; + struct kernel_mmap_mutation_ctx *ctx = data; - orig = machine->vmlinux_map; - updated = map__get(orig); + map__set_start(map, ctx->start); + map__set_end(map, ctx->end); + if (ctx->start == 0 && ctx->end == 0) + map__set_end(map, ~0ULL); + return 0; +} - machine->vmlinux_map = updated; - maps__remove(machine__kernel_maps(machine), orig); - machine__set_kernel_mmap(machine, start, end); - err = maps__insert(machine__kernel_maps(machine), updated); - map__put(orig); +static int machine__update_kernel_mmap(struct machine *machine, + u64 start, u64 end) +{ + struct kernel_mmap_mutation_ctx ctx = { .start = start, .end = end }; - return err; + return maps__mutate_mapping(machine__kernel_maps(machine), + machine->vmlinux_map, + kernel_mmap_mutate_cb, &ctx); } int machine__create_kernel_maps(struct machine *machine) diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c index 923935ee21b6..f808df2fe77b 100644 --- a/tools/perf/util/maps.c +++ b/tools/perf/util/maps.c @@ -576,6 +576,48 @@ void maps__remove(struct maps *maps, struct map *map) #endif } +/** + * maps__mutate_mapping - Apply write-protected mutations to a map. + * @maps: The maps collection containing the map. + * @map: The map to mutate. + * @mutate_cb: Callback function that performs the actual mutations. + * @data: Private data passed to the callback. + * + * This acquires the write lock on the maps semaphore to safely protect + * concurrent readers from seeing partially mutated or unsorted map boundaries. + * + * WARNING: Acquiring down_write() here can trigger a recursive self-deadlock if + * the caller already holds the read lock (e.g., during maps__for_each_map() or + * maps__find() iteration paths that trigger lazy symbol loading). To completely + * avoid this deadlock, all kernel/module maps must be pre-loaded up-front (via + * maps__load_maps()) under a clean, single-threaded context before entering + * multi-threaded event processing loops. + */ +int maps__mutate_mapping(struct maps *maps, struct map *map, + int (*mutate_cb)(struct map *map, void *data), void *data) +{ + int err = 0; + + if (maps) { + down_write(maps__lock(maps)); + + err = mutate_cb(map, data); + + RC_CHK_ACCESS(maps)->maps_by_address_sorted = false; + RC_CHK_ACCESS(maps)->maps_by_name_sorted = false; + + up_write(maps__lock(maps)); + +#ifdef HAVE_LIBDW_SUPPORT + libdw__invalidate_dwfl(maps, maps__libdw_addr_space_dwfl(maps)); +#endif + } else { + err = mutate_cb(map, data); + } + + return err; +} + bool maps__empty(struct maps *maps) { bool res; @@ -626,6 +668,41 @@ int maps__for_each_map(struct maps *maps, int (*cb)(struct map *map, void *data) return ret; } +int maps__load_maps(struct maps *maps) +{ + struct map **maps_copy; + unsigned int nr_maps; + int err = 0; + + if (!maps) + return 0; + + down_read(maps__lock(maps)); + nr_maps = maps__nr_maps(maps); + if (nr_maps == 0) { + up_read(maps__lock(maps)); + return 0; + } + maps_copy = calloc(nr_maps, sizeof(*maps_copy)); + if (!maps_copy) { + up_read(maps__lock(maps)); + return -ENOMEM; + } + for (unsigned int i = 0; i < nr_maps; i++) + maps_copy[i] = map__get(maps__maps_by_address(maps)[i]); + up_read(maps__lock(maps)); + + for (unsigned int i = 0; i < nr_maps; i++) { + if (map__load(maps_copy[i]) < 0) { + pr_warning("Failed to load map %s\n", dso__name(map__dso(maps_copy[i]))); + err = -1; + } + map__put(maps_copy[i]); + } + free(maps_copy); + return err; +} + void maps__remove_maps(struct maps *maps, bool (*cb)(struct map *map, void *data), void *data) { struct map **maps_by_address; @@ -668,40 +745,57 @@ struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp) return result; } -struct maps__find_symbol_by_name_args { - struct map **mapp; - const char *name; - struct symbol *sym; -}; - -static int maps__find_symbol_by_name_cb(struct map *map, void *data) -{ - struct maps__find_symbol_by_name_args *args = data; - - args->sym = map__find_symbol_by_name(map, args->name); - if (!args->sym) - return 0; - - if (!map__contains_symbol(map, args->sym)) { - args->sym = NULL; - return 0; - } - - if (args->mapp != NULL) - *args->mapp = map__get(map); - return 1; -} - struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp) { - struct maps__find_symbol_by_name_args args = { - .mapp = mapp, - .name = name, - .sym = NULL, - }; + struct map **maps_copy; + unsigned int nr_maps; + struct symbol *sym = NULL; - maps__for_each_map(maps, maps__find_symbol_by_name_cb, &args); - return args.sym; + if (!maps) + return NULL; + + /* + * First, ensure all maps are loaded. We pre-load them outside of any + * read-to-write locks to avoid deadlocks. Even if some fail, we proceed. + */ + maps__load_maps(maps); + + /* + * Create a local snapshot of the maps while holding the read lock. + * This prevents deadlocking if iteration triggers further map insertions. + */ + down_read(maps__lock(maps)); + nr_maps = maps__nr_maps(maps); + maps_copy = calloc(nr_maps, sizeof(*maps_copy)); + if (maps_copy) { + for (unsigned int i = 0; i < nr_maps; i++) { + struct map *map = maps__maps_by_address(maps)[i]; + + maps_copy[i] = map__get(map); + } + } + up_read(maps__lock(maps)); + + if (!maps_copy) + return NULL; + + for (unsigned int i = 0; i < nr_maps; i++) { + struct map *map = maps_copy[i]; + + sym = map__find_symbol_by_name(map, name); + if (sym && map__contains_symbol(map, sym)) { + if (mapp) + *mapp = map__get(map); + break; + } + sym = NULL; + } + + for (unsigned int i = 0; i < nr_maps; i++) + map__put(maps_copy[i]); + + free(maps_copy); + return sym; } int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams) diff --git a/tools/perf/util/maps.h b/tools/perf/util/maps.h index 5b80b199685e..4ec9b7453a3b 100644 --- a/tools/perf/util/maps.h +++ b/tools/perf/util/maps.h @@ -59,8 +59,11 @@ void maps__set_libdw_addr_space_dwfl(struct maps *maps, void *dwfl); size_t maps__fprintf(struct maps *maps, FILE *fp); +int maps__load_maps(struct maps *maps); int maps__insert(struct maps *maps, struct map *map); void maps__remove(struct maps *maps, struct map *map); +int maps__mutate_mapping(struct maps *maps, struct map *map, + int (*mutate_cb)(struct map *map, void *data), void *data); struct map *maps__find(struct maps *maps, u64 addr); struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp); diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index d84e2e031d43..c301c298ded9 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1373,6 +1373,24 @@ static u64 ref_reloc(struct kmap *kmap) void __weak arch__sym_update(struct symbol *s __maybe_unused, GElf_Sym *sym __maybe_unused) { } +struct remap_kernel_ctx { + u64 sh_addr; + u64 sh_size; + u64 sh_offset; + struct kmap *kmap; +}; + +static int remap_kernel_cb(struct map *map, void *data) +{ + struct remap_kernel_ctx *ctx = data; + + map__set_start(map, ctx->sh_addr + ref_reloc(ctx->kmap)); + map__set_end(map, map__start(map) + ctx->sh_size); + map__set_pgoff(map, ctx->sh_offset); + map__set_mapping_type(map, MAPPING_TYPE__DSO); + return 0; +} + static int dso__process_kernel_symbol(struct dso *dso, struct map *map, GElf_Sym *sym, GElf_Shdr *shdr, struct maps *kmaps, struct kmap *kmap, @@ -1403,22 +1421,15 @@ static int dso__process_kernel_symbol(struct dso *dso, struct map *map, * map to the kernel dso. */ if (*remap_kernel && dso__kernel(dso) && !kmodule) { - *remap_kernel = false; - map__set_start(map, shdr->sh_addr + ref_reloc(kmap)); - map__set_end(map, map__start(map) + shdr->sh_size); - map__set_pgoff(map, shdr->sh_offset); - map__set_mapping_type(map, MAPPING_TYPE__DSO); - /* Ensure maps are correctly ordered */ - if (kmaps) { - int err; - struct map *tmp = map__get(map); + struct remap_kernel_ctx ctx = { + .sh_addr = shdr->sh_addr, + .sh_size = shdr->sh_size, + .sh_offset = shdr->sh_offset, + .kmap = kmap + }; - maps__remove(kmaps, map); - err = maps__insert(kmaps, map); - map__put(tmp); - if (err) - return err; - } + *remap_kernel = false; + maps__mutate_mapping(kmaps, map, remap_kernel_cb, &ctx); } /* diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 0c46b24ee098..2cc911af8c81 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -48,6 +48,13 @@ #include #include +static int map_fixup_cb(struct map *map, void *data __maybe_unused) +{ + map__fixup_start(map); + map__fixup_end(map); + return 0; +} + static int dso__load_kernel_sym(struct dso *dso, struct map *map); static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map); @@ -2240,10 +2247,11 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map) free(kallsyms_allocated_filename); if (err > 0 && !dso__is_kcore(dso)) { + struct maps *kmaps = map__kmaps(map); + dso__set_binary_type(dso, DSO_BINARY_TYPE__KALLSYMS); dso__set_long_name(dso, DSO__NAME_KALLSYMS, false); - map__fixup_start(map); - map__fixup_end(map); + maps__mutate_mapping(kmaps, map, map_fixup_cb, NULL); } return err; @@ -2283,10 +2291,11 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map) if (err > 0) pr_debug("Using %s for symbols\n", kallsyms_filename); if (err > 0 && !dso__is_kcore(dso)) { + struct maps *kmaps = map__kmaps(map); + dso__set_binary_type(dso, DSO_BINARY_TYPE__GUEST_KALLSYMS); dso__set_long_name(dso, machine->mmap_name, false); - map__fixup_start(map); - map__fixup_end(map); + maps__mutate_mapping(kmaps, map, map_fixup_cb, NULL); } return err; From febea9ec382f5616954c1e3578e70308f4762e59 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 11 Jun 2026 09:41:19 -0700 Subject: [PATCH 312/343] perf inject/aslr: Add ASLR tool infrastructure and MMAP tracking If perf.data files are taken from one machine to another they may leak virtual addresses and so weaken ASLR on the machine they are coming from. Add an aslr option for perf inject that remaps all virtual addresses, or drops data/events, so that the virtual address information isn't leaked. This patch introduces the core ASLR remapping tool infrastructure and implements remapping/tracking for metadata events (MMAP, MMAP2, COMM, FORK, EXIT, KSYMBOL, TEXT_POKE). Sample events are delegated without remapping for now. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers Co-developed-by: Gabriel Marin Signed-off-by: Gabriel Marin Tested-by: James Clark Cc: Adrian Hunter Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 63 ++- tools/perf/util/Build | 1 + tools/perf/util/aslr.c | 814 ++++++++++++++++++++++++++++++++++++ tools/perf/util/aslr.h | 41 ++ 4 files changed, 909 insertions(+), 10 deletions(-) create mode 100644 tools/perf/util/aslr.c create mode 100644 tools/perf/util/aslr.h diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 75ffe31d03fe..8bb37095e2de 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -8,6 +8,7 @@ */ #include "builtin.h" +#include "util/aslr.h" #include "util/color.h" #include "util/dso.h" #include "util/vdso.h" @@ -24,6 +25,7 @@ #include "util/string2.h" #include "util/symbol.h" #include "util/synthetic-events.h" +#include "util/pmus.h" #include "util/thread.h" #include "util/namespaces.h" #include "util/unwind.h" @@ -124,6 +126,7 @@ struct perf_inject { bool in_place_update_dry_run; bool copy_kcore_dir; bool convert_callchain; + bool aslr; const char *input_name; struct perf_data output; u64 bytes_written; @@ -234,20 +237,36 @@ static int perf_event__repipe_attr(const struct perf_tool *tool, u64 *ids; int ret; + union perf_event *aslr_event = NULL; + ret = perf_event__process_attr(tool, event, pevlist); if (ret) return ret; - /* If the output isn't a pipe then the attributes will be written as part of the header. */ - if (!inject->output.is_pipe) - return 0; + if (inject->aslr) { + aslr_event = malloc(event->header.size); + if (!aslr_event) + return -ENOMEM; + memcpy(aslr_event, event, event->header.size); + aslr_tool__strip_attr_event(aslr_event, pevlist); + event = aslr_event; + } - if (!inject->itrace_synth_opts.set) - return perf_event__repipe_synth(tool, event); + /* If the output isn't a pipe then the attributes will be written as part of the header. */ + if (!inject->output.is_pipe) { + ret = 0; + goto out; + } + + if (!inject->itrace_synth_opts.set) { + ret = perf_event__repipe_synth(tool, event); + goto out; + } if (event->header.size < sizeof(struct perf_event_header) + PERF_ATTR_SIZE_VER0) { pr_err("Attribute event size %u is too small\n", event->header.size); - return -EINVAL; + ret = -EINVAL; + goto out; } /* @@ -263,7 +282,8 @@ static int perf_event__repipe_attr(const struct perf_tool *tool, raw_attr_size > event->header.size - sizeof(event->header))) { pr_err("Attribute event size %u is too small for attr.size %u\n", event->header.size, raw_attr_size); - return -EINVAL; + ret = -EINVAL; + goto out; } memset(&attr, 0, sizeof(attr)); @@ -281,8 +301,11 @@ static int perf_event__repipe_attr(const struct perf_tool *tool, attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX; } - return perf_event__synthesize_attr(tool, &attr, (u32)n_ids, ids, + ret = perf_event__synthesize_attr(tool, &attr, (u32)n_ids, ids, perf_event__repipe_synth_cb); +out: + free(aslr_event); + return ret; } static int perf_event__repipe_event_update(const struct perf_tool *tool, @@ -2594,7 +2617,6 @@ static int __cmd_inject(struct perf_inject *inject) evsel->core.attr.exclude_callchain_user = 0; } } - session->header.data_offset = output_data_offset; session->header.data_size = inject->bytes_written; perf_session__inject_header(session, session->evlist, fd, &inj_fc.fc, @@ -2704,6 +2726,8 @@ int cmd_inject(int argc, const char **argv) unwind__option), OPT_BOOLEAN(0, "convert-callchain", &inject.convert_callchain, "Generate callchains using DWARF and drop register/stack data"), + OPT_BOOLEAN(0, "aslr", &inject.aslr, + "Remap virtual memory addresses similar to ASLR"), OPT_END() }; const char * const inject_usage[] = { @@ -2711,6 +2735,7 @@ int cmd_inject(int argc, const char **argv) NULL }; bool ordered_events; + struct perf_tool *tool = &inject.tool; if (!inject.itrace_synth_opts.set) { /* Disable eager loading of kernel symbols that adds overhead to perf inject. */ @@ -2731,6 +2756,11 @@ int cmd_inject(int argc, const char **argv) if (argc) usage_with_options(inject_usage, options); + if (inject.aslr && inject.convert_callchain) { + pr_err("Error: --aslr and --convert-callchain are mutually exclusive features.\n"); + return -EINVAL; + } + if (inject.strip && !inject.itrace_synth_opts.set) { pr_err("--strip option requires --itrace option\n"); return -1; @@ -2824,12 +2854,21 @@ int cmd_inject(int argc, const char **argv) inject.tool.schedstat_domain = perf_event__repipe_op2_synth; inject.tool.dont_split_sample_group = true; inject.tool.merge_deferred_callchains = false; - inject.session = __perf_session__new(&data, &inject.tool, + if (inject.aslr) { + tool = aslr_tool__new(&inject.tool); + if (!tool) { + ret = -ENOMEM; + goto out_close_output; + } + } + inject.session = __perf_session__new(&data, tool, /*trace_event_repipe=*/inject.output.is_pipe, /*host_env=*/NULL); if (IS_ERR(inject.session)) { ret = PTR_ERR(inject.session); + if (inject.aslr) + aslr_tool__delete(tool); goto out_close_output; } @@ -2922,6 +2961,8 @@ int cmd_inject(int argc, const char **argv) goto out_delete; ret = __cmd_inject(&inject); + if (inject.aslr) + aslr_tool__strip_evlist(tool, inject.session->evlist); guest_session__exit(&inject.guest_session); @@ -2929,6 +2970,8 @@ int cmd_inject(int argc, const char **argv) strlist__delete(inject.known_build_ids); zstd_fini(&(inject.session->zstd_data)); perf_session__delete(inject.session); + if (inject.aslr) + aslr_tool__delete(tool); out_close_output: if (!inject.in_place_update) perf_data__close(&inject.output); diff --git a/tools/perf/util/Build b/tools/perf/util/Build index b22cdc24082a..5e2265018826 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -6,6 +6,7 @@ perf-util-y += arm64-frame-pointer-unwind-support.o perf-util-y += addr2line.o perf-util-y += addr_location.o perf-util-y += annotate.o +perf-util-y += aslr.o perf-util-y += blake2s.o perf-util-y += block-info.o perf-util-y += block-range.o diff --git a/tools/perf/util/aslr.c b/tools/perf/util/aslr.c new file mode 100644 index 000000000000..56fc444fbf54 --- /dev/null +++ b/tools/perf/util/aslr.c @@ -0,0 +1,814 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "aslr.h" + +#include "addr_location.h" +#include "debug.h" +#include "event.h" +#include "evsel.h" +#include "evlist.h" +#include "machine.h" +#include "map.h" +#include "thread.h" +#include "tool.h" +#include "session.h" +#include "data.h" +#include "dso.h" +#include "pmus.h" + +#include /* page_size */ +#include +#include +#include +#include + +/** + * struct remap_addresses_key - Key for mapping original addresses to remapped ones. + * @dso: Pointer to the DSO (Dynamic Shared Object) associated with the mapping. + * @invariant: Unique offset invariant within the VMA (Virtual Memory Area). + * Calculated as `start - pgoff`. This value remains constant when + * perf's internal `maps__fixup_overlap_and_insert` splits a map into + * fragmented VMA pieces due to overlapping events, allowing us to + * resolve split maps consistently back to the original VMA. + * @pid: Process ID associated with the mapping. + */ +struct remap_addresses_key { + struct machine *machine; + struct dso *dso; + u64 invariant; + pid_t pid; +}; + +struct aslr_mapping { + struct list_head node; + u64 orig_start; + u64 len; + u64 remap_start; +}; + +struct process_top_address { + u64 remapped_max; +}; +struct aslr_tool { + /** @tool: The tool implemented here and a pointer to a delegate to process the data. */ + struct delegate_tool tool; + /** @machines: The machines with the input, not remapped, virtual address layout. */ + struct machines machines; + /** @event_copy: Buffer used to create an event to pass to the delegate. */ + char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); + /** @remap_addresses: mapping from remap_addresses_key to remapped address. */ + struct hashmap remap_addresses; + /** @top_addresses: mapping from process to max remapped address. */ + struct hashmap top_addresses; +}; + +static const pid_t kernel_pid = -1; + +/* Start remapping user processes from a small non-zero offset. */ +static const u64 user_space_start = 0x200000; +static const u64 kernel_space_start_64 = 0xffff800010000000ULL; +static const u64 kernel_space_start_32 = 0x80000000ULL; + +static size_t remap_addresses__hash(long _key, void *ctx __maybe_unused) +{ + struct remap_addresses_key *key = (struct remap_addresses_key *)_key; + void *dso_ptr = key->dso ? RC_CHK_ACCESS(key->dso) : NULL; + + return (size_t)key->machine ^ (size_t)dso_ptr ^ key->invariant ^ key->pid; +} + +static bool remap_addresses__equal(long _key1, long _key2, void *ctx __maybe_unused) +{ + struct remap_addresses_key *key1 = (struct remap_addresses_key *)_key1; + struct remap_addresses_key *key2 = (struct remap_addresses_key *)_key2; + + return key1->machine == key2->machine && + RC_CHK_EQUAL(key1->dso, key2->dso) && + key1->invariant == key2->invariant && + key1->pid == key2->pid; +} + +struct top_addresses_key { + struct machine *machine; + pid_t pid; +}; + +static size_t top_addresses__hash(long _key, void *ctx __maybe_unused) +{ + struct top_addresses_key *key = (struct top_addresses_key *)_key; + + return (size_t)key->machine ^ key->pid; +} + +static bool top_addresses__equal(long _key1, long _key2, void *ctx __maybe_unused) +{ + struct top_addresses_key *key1 = (struct top_addresses_key *)_key1; + struct top_addresses_key *key2 = (struct top_addresses_key *)_key2; + + return key1->machine == key2->machine && key1->pid == key2->pid; +} + +static u64 round_up_to_page_size(u64 addr) +{ + return (addr + page_size - 1) & ~((u64)page_size - 1); +} + +struct aslr_machine_priv { + bool kernel_maps_loaded; +}; + +static int aslr_tool__preload_kernel_maps(struct machine *machine) +{ + struct aslr_machine_priv *mpriv = machine->priv; + + if (!mpriv) { + mpriv = zalloc(sizeof(*mpriv)); + if (!mpriv) + return -ENOMEM; + machine->priv = mpriv; + } + + if (!mpriv->kernel_maps_loaded) { + struct maps *kmaps = machine__kernel_maps(machine); + + if (kmaps) { + int err = maps__load_maps(kmaps); + + if (err < 0) { + pr_err("ASLR: Failed to preload kernel maps for machine pid %d\n", + machine->pid); + return err; + } + } + mpriv->kernel_maps_loaded = true; + } + return 0; +} + +static void aslr_tool__free_machine_priv(struct machine *machine) +{ + free(machine->priv); + machine->priv = NULL; +} + +static void aslr_tool__destroy_machines_priv(struct machines *machines) +{ + struct rb_node *nd; + + aslr_tool__free_machine_priv(&machines->host); + for (nd = rb_first_cached(&machines->guests); nd; nd = rb_next(nd)) { + struct machine *machine = rb_entry(nd, struct machine, rb_node); + + aslr_tool__free_machine_priv(machine); + } +} + +static u64 aslr_tool__findnew_mapping(struct aslr_tool *aslr, + struct machine *session_machine, + struct thread *aslr_thread, + u8 cpumode, u64 start, + u64 len, u64 pgoff) +{ + /* Address location for dso lookup. */ + struct addr_location al; + /* Original ASLR address based key for the remap table. */ + struct remap_addresses_key remap_key; + /* The address in the ASLR sanitized address space less pg_off. */ + u64 *remapped_invariant_ptr; + /* Key for the maximum address in a process. */ + struct top_addresses_key top_addr_key; + /* Value in top address table. */ + struct process_top_address *top = NULL; + /* Address in ASLR sanitized address space. */ + u64 remap_addr; + /* Potentially allocated remap table key. */ + struct remap_addresses_key *new_remap_key = NULL; + /* + * Potentially allocated remap table key. + * TODO: Avoid allocation necessary for perf 32-bit binary support. + */ + u64 *new_remap_val = NULL; + int err; + + if (!aslr_thread) + return 0; + + /* The key to look up an incoming address to the outgoing value. */ + addr_location__init(&al); + remap_key.machine = maps__machine(thread__maps(aslr_thread)); + remap_key.pid = (cpumode == PERF_RECORD_MISC_KERNEL || + cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ? + kernel_pid : thread__pid(aslr_thread); + if (thread__find_map(aslr_thread, cpumode, start, &al)) { + struct dso *dso = map__dso(al.map); + const char *dso_name = dso ? dso__long_name(dso) : NULL; + + remap_key.dso = dso; + if (dso && !is_anon_memory(dso_name) && !is_no_dso_memory(dso_name)) + remap_key.invariant = map__start(al.map) - map__pgoff(al.map); + else + remap_key.invariant = map__start(al.map); + } else { + remap_key.dso = NULL; + remap_key.invariant = start; + } + + /* The key to look up top allocated address. */ + top_addr_key.machine = remap_key.machine; + top_addr_key.pid = remap_key.pid; + + if (hashmap__find(&aslr->remap_addresses, &remap_key, &remapped_invariant_ptr)) { + /* Mmap already exists. */ + u64 calculated_max; + + if (al.map) { + /* + * The cached value is the base of the invariant. We add the + * offset into the VMA (start - map__start), plus the map's + * pgoff, to get the precise virtual address within this chunk. + */ + remap_addr = *remapped_invariant_ptr + map__pgoff(al.map) + + (start - map__start(al.map)); + } else { + /* + * For unmapped memory (e.g. kernel anonymous), the cached value + * was stored offset by pgoff. Adding pgoff yields the true remap_addr. + */ + remap_addr = *remapped_invariant_ptr + pgoff; + } + + calculated_max = remap_addr + len; + + /* See if top mapping was expanded. */ + if (hashmap__find(&aslr->top_addresses, &top_addr_key, &top)) { + if (calculated_max > top->remapped_max) + top->remapped_max = calculated_max; + } + addr_location__exit(&al); + return remap_addr; + } + /* No mmap, create an entry from the top address. */ + if (hashmap__find(&aslr->top_addresses, &top_addr_key, &top)) { + struct addr_location prev_al; + bool is_contiguous = false; + + /* Current max allocated mmap address within the process. */ + remap_addr = top->remapped_max; + + addr_location__init(&prev_al); + if (thread__find_map(aslr_thread, cpumode, start - 1, &prev_al)) { + if (map__end(prev_al.map) == start) + is_contiguous = true; + } + addr_location__exit(&prev_al); + + if (is_contiguous) { + /* Contiguous mapping, do not add 1 page gap! */ + remap_addr = round_up_to_page_size(remap_addr); + } else { + /* Give 1 page gap from current max page. */ + remap_addr = round_up_to_page_size(remap_addr); + remap_addr += page_size; + } + if (remap_addr + len > top->remapped_max) + top->remapped_max = remap_addr + len; + } else { + /* First address of the process, allocate key and first top address. */ + struct top_addresses_key *tk; + struct process_top_address *top_val; + struct perf_env *env = session_machine ? session_machine->env : NULL; + bool is_64 = env ? perf_env__kernel_is_64_bit(env) : (sizeof(void *) == 8); + u64 kernel_start_addr = is_64 ? kernel_space_start_64 : kernel_space_start_32; + + remap_addr = (cpumode == PERF_RECORD_MISC_KERNEL || + cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ? + kernel_start_addr : user_space_start; + remap_addr = round_up_to_page_size(remap_addr); + + tk = malloc(sizeof(*tk)); + top_val = malloc(sizeof(*top_val)); + if (!tk || !top_val) { + err = -ENOMEM; + } else { + *tk = top_addr_key; + top_val->remapped_max = remap_addr + len; + err = hashmap__insert(&aslr->top_addresses, tk, top_val, + HASHMAP_ADD, NULL, NULL); + } + if (err) { + errno = -err; + pr_err("Failure to add ASLR process top address %m\n"); + free(tk); + free(top_val); + addr_location__exit(&al); + return 0; + } + } + /* Create rmeapping entry. */ + new_remap_key = malloc(sizeof(*new_remap_key)); + new_remap_val = malloc(sizeof(u64)); + if (!new_remap_key || !new_remap_val) { + err = -ENOMEM; + } else { + *new_remap_key = remap_key; + new_remap_key->dso = dso__get(remap_key.dso); + if (cpumode == PERF_RECORD_MISC_KERNEL || + cpumode == PERF_RECORD_MISC_GUEST_KERNEL) { + if (al.map) { + *new_remap_val = remap_addr - + (start - map__start(al.map)) - + map__pgoff(al.map); + } else { + /* + * Subtract pgoff from the base virtual address so that + * when the lookup path adds pgoff back, it perfectly + * cancels out and returns remap_addr. + */ + *new_remap_val = remap_addr - pgoff; + } + } else { + *new_remap_val = remap_addr - (al.map ? (start - map__start(al.map)) + + map__pgoff(al.map) : pgoff); + } + err = hashmap__add(&aslr->remap_addresses, new_remap_key, new_remap_val); + if (err) + dso__put(new_remap_key->dso); + } + if (err) { + errno = -err; + pr_err("Failure to add ASLR remapping %m\n"); + free(new_remap_key); + free(new_remap_val); + addr_location__exit(&al); + return 0; + } + addr_location__exit(&al); + return remap_addr; +} + +static int aslr_tool__process_mmap(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct delegate_tool *del_tool; + struct aslr_tool *aslr; + struct perf_tool *delegate; + union perf_event *new_event; + u8 cpumode; + struct thread *thread; + struct machine *aslr_machine; + int err; + + del_tool = container_of(tool, struct delegate_tool, tool); + aslr = container_of(del_tool, struct aslr_tool, tool); + delegate = aslr->tool.delegate; + new_event = (union perf_event *)aslr->event_copy; + cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + + aslr_machine = machines__findnew(&aslr->machines, machine->pid); + if (!aslr_machine) + return -ENOMEM; + if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) + return -ENOMEM; + + /* Create the thread, map, etc. in the ASLR before virtual address space. */ + err = perf_event__process_mmap(tool, event, sample, aslr_machine); + if (err) + return err; + + thread = machine__findnew_thread(aslr_machine, event->mmap.pid, event->mmap.tid); + if (!thread) + return -ENOMEM; + memcpy(&new_event->mmap, &event->mmap, event->mmap.header.size); + /* Remaps the mmap.start. */ + new_event->mmap.start = aslr_tool__findnew_mapping(aslr, machine, thread, cpumode, + event->mmap.start, + event->mmap.len, + event->mmap.pgoff); + /* + * For anonymous memory (and kernel maps), the kernel populates the + * event's pgoff field with the original un-obfuscated virtual address + * in bytes (i.e. (addr >> PAGE_SHIFT) << PAGE_SHIFT). + * We must overwrite pgoff with the new remapped byte address to prevent + * leaking the original ASLR layout. + */ + if (is_anon_memory(event->mmap.filename) || is_no_dso_memory(event->mmap.filename) || + ((cpumode == PERF_RECORD_MISC_KERNEL || cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && + !is_kernel_module(event->mmap.filename, cpumode))) + new_event->mmap.pgoff = new_event->mmap.start; + err = delegate->mmap(delegate, new_event, sample, machine); + thread__put(thread); + return err; +} + +static int aslr_tool__process_mmap2(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct delegate_tool *del_tool; + struct aslr_tool *aslr; + struct perf_tool *delegate; + union perf_event *new_event; + u8 cpumode; + struct thread *thread; + struct machine *aslr_machine; + int err; + + del_tool = container_of(tool, struct delegate_tool, tool); + aslr = container_of(del_tool, struct aslr_tool, tool); + delegate = aslr->tool.delegate; + new_event = (union perf_event *)aslr->event_copy; + cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + + aslr_machine = machines__findnew(&aslr->machines, machine->pid); + if (!aslr_machine) + return -ENOMEM; + if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) + return -ENOMEM; + + /* Create the thread, map, etc. in the ASLR before virtual address space. */ + err = perf_event__process_mmap2(tool, event, sample, aslr_machine); + if (err) + return err; + + thread = machine__findnew_thread(aslr_machine, event->mmap2.pid, event->mmap2.tid); + if (!thread) + return -ENOMEM; + memcpy(&new_event->mmap2, &event->mmap2, event->mmap2.header.size); + /* Remaps the mmap.start. */ + new_event->mmap2.start = aslr_tool__findnew_mapping(aslr, machine, thread, cpumode, + event->mmap2.start, + event->mmap2.len, + event->mmap2.pgoff); + /* + * For anonymous memory (and kernel maps), the kernel populates the + * event's pgoff field with the original un-obfuscated virtual address + * in bytes (i.e. (addr >> PAGE_SHIFT) << PAGE_SHIFT). + * We must overwrite pgoff with the new remapped byte address to prevent + * leaking the original ASLR layout. + */ + if (is_anon_memory(event->mmap2.filename) || is_no_dso_memory(event->mmap2.filename) || + ((cpumode == PERF_RECORD_MISC_KERNEL || cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && + !is_kernel_module(event->mmap2.filename, cpumode))) + new_event->mmap2.pgoff = new_event->mmap2.start; + err = delegate->mmap2(delegate, new_event, sample, machine); + thread__put(thread); + return err; +} + +static int aslr_tool__process_comm(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct delegate_tool *del_tool; + struct aslr_tool *aslr; + struct perf_tool *delegate; + struct machine *aslr_machine; + int err; + + del_tool = container_of(tool, struct delegate_tool, tool); + aslr = container_of(del_tool, struct aslr_tool, tool); + delegate = aslr->tool.delegate; + + aslr_machine = machines__findnew(&aslr->machines, machine->pid); + if (!aslr_machine) + return -ENOMEM; + if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) + return -ENOMEM; + + /* Create the thread, map, etc. in the ASLR before virtual address space. */ + err = perf_event__process_comm(tool, event, sample, aslr_machine); + if (err) + return err; + + return delegate->comm(delegate, event, sample, machine); +} + +static int aslr_tool__process_fork(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct delegate_tool *del_tool; + struct aslr_tool *aslr; + struct perf_tool *delegate; + struct machine *aslr_machine; + int err; + + del_tool = container_of(tool, struct delegate_tool, tool); + aslr = container_of(del_tool, struct aslr_tool, tool); + delegate = aslr->tool.delegate; + + aslr_machine = machines__findnew(&aslr->machines, machine->pid); + if (!aslr_machine) + return -ENOMEM; + if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) + return -ENOMEM; + + /* Create the thread, map, etc. in the ASLR before virtual address space. */ + err = perf_event__process_fork(tool, event, sample, aslr_machine); + if (err) + return err; + + return delegate->fork(delegate, event, sample, machine); +} + +static int aslr_tool__process_exit(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct delegate_tool *del_tool; + struct aslr_tool *aslr; + struct perf_tool *delegate; + struct machine *aslr_machine; + int err; + + del_tool = container_of(tool, struct delegate_tool, tool); + aslr = container_of(del_tool, struct aslr_tool, tool); + delegate = aslr->tool.delegate; + + aslr_machine = machines__findnew(&aslr->machines, machine->pid); + if (!aslr_machine) + return -ENOMEM; + if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) + return -ENOMEM; + + /* Create the thread, map, etc. in the ASLR before virtual address space. */ + err = perf_event__process_exit(tool, event, sample, aslr_machine); + if (err) + return err; + + return delegate->exit(delegate, event, sample, machine); +} + +static int aslr_tool__process_text_poke(const struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused, + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) +{ + /* Drop in case the instruction encodes an ASLR revealing address. */ + return 0; +} + +static int aslr_tool__process_ksymbol(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct delegate_tool *del_tool; + struct aslr_tool *aslr; + struct perf_tool *delegate; + union perf_event *new_event; + struct thread *thread; + struct machine *aslr_machine; + bool is_unregister; + int err; + + del_tool = container_of(tool, struct delegate_tool, tool); + aslr = container_of(del_tool, struct aslr_tool, tool); + delegate = aslr->tool.delegate; + new_event = (union perf_event *)aslr->event_copy; + + aslr_machine = machines__findnew(&aslr->machines, machine->pid); + if (!aslr_machine) + return -ENOMEM; + if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) + return -ENOMEM; + + thread = machine__findnew_thread(aslr_machine, kernel_pid, 0); + if (!thread) + return -ENOMEM; + + is_unregister = (event->ksymbol.flags & PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER); + + memcpy(&new_event->ksymbol, &event->ksymbol, event->ksymbol.header.size); + + if (is_unregister) { + new_event->ksymbol.addr = aslr_tool__findnew_mapping(aslr, machine, thread, + PERF_RECORD_MISC_KERNEL, + event->ksymbol.addr, + event->ksymbol.len, + /*pgoff=*/0); + err = perf_event__process_ksymbol(tool, event, sample, aslr_machine); + } else { + err = perf_event__process_ksymbol(tool, event, sample, aslr_machine); + new_event->ksymbol.addr = aslr_tool__findnew_mapping(aslr, machine, thread, + PERF_RECORD_MISC_KERNEL, + event->ksymbol.addr, + event->ksymbol.len, + /*pgoff=*/0); + } + if (err) { + thread__put(thread); + return err; + } + + err = delegate->ksymbol(delegate, new_event, sample, machine); + thread__put(thread); + return err; +} + +static int aslr_tool__process_sample(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); + struct aslr_tool *aslr = container_of(del_tool, struct aslr_tool, tool); + struct perf_tool *delegate = aslr->tool.delegate; + + return delegate->sample(delegate, event, sample, machine); +} + +static int skipn(int fd, off_t n) +{ + char buf[4096]; + ssize_t ret; + + while (n > 0) { + ret = read(fd, buf, min_t(off_t, n, (off_t)sizeof(buf))); + if (ret <= 0) + return ret; + n -= ret; + } + + return 0; +} + +static s64 aslr_tool__process_auxtrace(const struct perf_tool *tool __maybe_unused, + struct perf_session *session, + union perf_event *event) +{ + pr_warning_once("ASLR: Dropping auxtrace data as it cannot be obfuscated.\n"); + if (perf_data__is_pipe(session->data)) { + /* Copy behavior of the stub by reading all pipe data. */ + int err = skipn(perf_data__fd(session->data), event->auxtrace.size); + + if (err < 0) + return err; + } + return event->auxtrace.size; +} + +static int aslr_tool__process_auxtrace_info(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) +{ + return 0; +} + +static int aslr_tool__process_auxtrace_error(const struct perf_tool *tool __maybe_unused, + struct perf_session *session __maybe_unused, + union perf_event *event __maybe_unused) +{ + return 0; +} + + +void aslr_tool__strip_attr_event(union perf_event *event, struct evlist **pevlist __maybe_unused) +{ + u32 attr_size; + + attr_size = event->attr.attr.size ?: PERF_ATTR_SIZE_VER0; + + if (attr_size >= (offsetof(struct perf_event_attr, sample_type) + sizeof(u64))) { + event->attr.attr.sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE; + } + + if (attr_size >= (offsetof(struct perf_event_attr, type) + sizeof(u32))) { + u32 type = event->attr.attr.type; + + if (type == PERF_TYPE_BREAKPOINT && + attr_size >= (offsetof(struct perf_event_attr, bp_addr) + sizeof(u64))) { + event->attr.attr.bp_addr = 0; + } else if (type >= PERF_TYPE_MAX) { + struct perf_pmu *pmu; + + pmu = perf_pmus__find_by_type(type); + if (pmu && (!strcmp(pmu->name, "kprobe") || + !strcmp(pmu->name, "uprobe"))) { + if (attr_size >= (offsetof(struct perf_event_attr, config1) + sizeof(u64))) + event->attr.attr.config1 = 0; + if (attr_size >= (offsetof(struct perf_event_attr, config2) + sizeof(u64))) + event->attr.attr.config2 = 0; + } + } + } +} + +void aslr_tool__strip_evlist(struct perf_tool *tool __maybe_unused, + struct evlist *evlist) +{ + struct evsel *evsel; + + evlist__for_each_entry(evlist, evsel) { + evsel->core.attr.sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE; + + if (evsel->core.attr.type == PERF_TYPE_BREAKPOINT) + evsel->core.attr.bp_addr = 0; + else if (evsel->core.attr.type >= PERF_TYPE_MAX) { + struct perf_pmu *pmu = perf_pmus__find_by_type(evsel->core.attr.type); + + if (pmu && (!strcmp(pmu->name, "kprobe") || + !strcmp(pmu->name, "uprobe"))) { + evsel->core.attr.config1 = 0; + evsel->core.attr.config2 = 0; + } + } + } +} + +static void aslr_tool__init(struct aslr_tool *aslr, struct perf_tool *delegate) +{ + delegate_tool__init(&aslr->tool, delegate); + aslr->tool.tool.ordered_events = true; + + machines__init(&aslr->machines); + + hashmap__init(&aslr->remap_addresses, + remap_addresses__hash, remap_addresses__equal, + /*ctx=*/NULL); + hashmap__init(&aslr->top_addresses, + top_addresses__hash, top_addresses__equal, + /*ctx=*/NULL); + + aslr->tool.tool.sample = aslr_tool__process_sample; + /* read - reads a counter, okay to delegate. */ + aslr->tool.tool.mmap = aslr_tool__process_mmap; + aslr->tool.tool.mmap2 = aslr_tool__process_mmap2; + aslr->tool.tool.comm = aslr_tool__process_comm; + aslr->tool.tool.fork = aslr_tool__process_fork; + aslr->tool.tool.exit = aslr_tool__process_exit; + /* namesspaces, cgroup, lost, lost_sample, aux, */ + /* itrace_start, aux_output_hw_id, context_switch, throttle, unthrottle */ + /* - no virtual addresses. */ + aslr->tool.tool.ksymbol = aslr_tool__process_ksymbol; + /* bpf - no virtual address. */ + aslr->tool.tool.text_poke = aslr_tool__process_text_poke; + /* + * event_update, tracing_data, finished_round, build_id, id_index, + * auxtrace_info, auxtrace_error, time_conv, thread_map, cpu_map, + * stat_config, stat, feature, finished_init, bpf_metadata, compressed, + * auxtrace - no virtual addresses. + */ + aslr->tool.tool.auxtrace = aslr_tool__process_auxtrace; + aslr->tool.tool.auxtrace_info = aslr_tool__process_auxtrace_info; + aslr->tool.tool.auxtrace_error = aslr_tool__process_auxtrace_error; +} + +struct perf_tool *aslr_tool__new(struct perf_tool *delegate) +{ + struct aslr_tool *aslr = zalloc(sizeof(*aslr)); + + if (!aslr) + return NULL; + + aslr_tool__init(aslr, delegate); + return &aslr->tool.tool; +} + +void aslr_tool__delete(struct perf_tool *tool) +{ + struct delegate_tool *del_tool; + struct aslr_tool *aslr; + struct hashmap_entry *cur; + size_t bkt; + struct rb_node *nd; + + if (!tool) + return; + + del_tool = container_of(tool, struct delegate_tool, tool); + aslr = container_of(del_tool, struct aslr_tool, tool); + + hashmap__for_each_entry(&aslr->remap_addresses, cur, bkt) { + struct remap_addresses_key *key = (struct remap_addresses_key *)cur->pkey; + + if (key) + dso__put(key->dso); + zfree(&cur->pkey); + zfree(&cur->pvalue); + } + hashmap__for_each_entry(&aslr->top_addresses, cur, bkt) { + zfree(&cur->pkey); + zfree(&cur->pvalue); + } + + hashmap__clear(&aslr->remap_addresses); + hashmap__clear(&aslr->top_addresses); + aslr_tool__destroy_machines_priv(&aslr->machines); + machines__destroy_kernel_maps(&aslr->machines); + + while ((nd = rb_first_cached(&aslr->machines.guests)) != NULL) { + struct machine *machine = rb_entry(nd, struct machine, rb_node); + + rb_erase_cached(nd, &aslr->machines.guests); + machine__delete(machine); + } + + machines__exit(&aslr->machines); + free(aslr); +} diff --git a/tools/perf/util/aslr.h b/tools/perf/util/aslr.h new file mode 100644 index 000000000000..2b82f711bc67 --- /dev/null +++ b/tools/perf/util/aslr.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PERF_ASLR_H +#define __PERF_ASLR_H + +#include + +#define ASLR_SUPPORTED_SAMPLE_TYPE ( \ + PERF_SAMPLE_IDENTIFIER | \ + PERF_SAMPLE_IP | \ + PERF_SAMPLE_TID | \ + PERF_SAMPLE_TIME | \ + PERF_SAMPLE_ADDR | \ + PERF_SAMPLE_ID | \ + PERF_SAMPLE_STREAM_ID | \ + PERF_SAMPLE_CPU | \ + PERF_SAMPLE_PERIOD | \ + PERF_SAMPLE_READ | \ + PERF_SAMPLE_CALLCHAIN | \ + PERF_SAMPLE_RAW | \ + PERF_SAMPLE_BRANCH_STACK | \ + PERF_SAMPLE_STACK_USER | \ + PERF_SAMPLE_WEIGHT_TYPE | \ + PERF_SAMPLE_DATA_SRC | \ + PERF_SAMPLE_TRANSACTION | \ + PERF_SAMPLE_PHYS_ADDR | \ + PERF_SAMPLE_CGROUP | \ + PERF_SAMPLE_DATA_PAGE_SIZE | \ + PERF_SAMPLE_CODE_PAGE_SIZE | \ + PERF_SAMPLE_AUX) + +struct perf_tool; +struct evsel; +struct evlist; +union perf_event; + +struct perf_tool *aslr_tool__new(struct perf_tool *delegate); +void aslr_tool__delete(struct perf_tool *aslr); +void aslr_tool__strip_attr_event(union perf_event *event, struct evlist **pevlist); +void aslr_tool__strip_evlist(struct perf_tool *tool, struct evlist *evlist); + +#endif /* __PERF_ASLR_H */ From 575c6d2bc470ec809d6c803ec0db9e61762cfa32 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 11 Jun 2026 09:41:20 -0700 Subject: [PATCH 313/343] perf inject/aslr: Implement sample address remapping Add the sample address remapping logic to the ASLR tool. This patch implements aslr_tool__process_sample, which parses sample events, remaps IPs, ADDRs, callchains, and branch stacks using the mappings collected from metadata events, and drops potentially leaking raw, register, stack, physical address, and aux samples. Also adds the aslr_tool__remap_address helper function. Note on cross-endian compatibility: 'perf inject' functions as an endianness converter. Input files are read, and their events are byte-swapped to host endianness in memory. When the tool emits its output, it writes a host-endian PERF_MAGIC in the file header, thereby marking the output file as host-endian natively. Because the output file is always written in host endianness, events and payloads must be constructed entirely using host-endian layouts. For this reason, this patch explicitly un-packs and repacks PERF_SAMPLE_TID (and PERF_SAMPLE_CPU) using unions to ensure that the sequential 32-bit layout is correctly aligned in host endianness. Similarly, branch stack flags (which are modified in-place to host-endian bitfields by the parser) are copied directly to the newly synthesized event. When re-parsing the newly synthesized event, 'needs_swap=false' is explicitly used to prevent double swapping the already host-endian fields. Committer notes: Removed several unused variables, they will be reintroduced in the following patches where they are finally used: struct aslr_evsel_priv *priv = NULL; u64 orig_sample_type; u64 orig_regs_user; u64 orig_regs_intr; Also used PRIx64 for two u64 args (addresses) and %zu for a size_t arg (map__size()) to fix the build on 32-bit architectures. Assisted-by: Antigravity:gemini-3.1-pro Co-developed-by: Gabriel Marin Signed-off-by: Gabriel Marin Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/aslr.c | 459 +++++++++++++++++++++++++++++++++++++++- tools/perf/util/evsel.c | 6 +- tools/perf/util/evsel.h | 10 +- 3 files changed, 466 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/aslr.c b/tools/perf/util/aslr.c index 56fc444fbf54..d0760ca8926d 100644 --- a/tools/perf/util/aslr.c +++ b/tools/perf/util/aslr.c @@ -20,6 +20,7 @@ #include #include #include +#include /** * struct remap_addresses_key - Key for mapping original addresses to remapped ones. @@ -112,6 +113,60 @@ static u64 round_up_to_page_size(u64 addr) return (addr + page_size - 1) & ~((u64)page_size - 1); } +static u64 aslr_tool__remap_address(struct aslr_tool *aslr, + struct thread *aslr_thread, + u8 cpumode, + u64 addr) +{ + struct addr_location al; + struct remap_addresses_key key; + u64 *remapped_invariant_ptr = NULL; + u64 remap_addr = 0; + u8 effective_cpumode = cpumode; + + if (!aslr_thread) + return 0; /* No thread. */ + + addr_location__init(&al); + if (!thread__find_map(aslr_thread, cpumode, addr, &al)) { + /* + * If lookup fails with specified cpumode, try fallback to the other space + * to be robust against bad cpumode in samples. + */ + if (cpumode == PERF_RECORD_MISC_KERNEL) + effective_cpumode = PERF_RECORD_MISC_USER; + else if (cpumode == PERF_RECORD_MISC_USER) + effective_cpumode = PERF_RECORD_MISC_KERNEL; + else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL) + effective_cpumode = PERF_RECORD_MISC_GUEST_USER; + else if (cpumode == PERF_RECORD_MISC_GUEST_USER) + effective_cpumode = PERF_RECORD_MISC_GUEST_KERNEL; + + if (!thread__find_map(aslr_thread, effective_cpumode, addr, &al)) { + addr_location__exit(&al); + return 0; /* No mmap. */ + } + } + + key.machine = maps__machine(thread__maps(aslr_thread)); + key.dso = map__dso(al.map); + key.invariant = map__start(al.map) - map__pgoff(al.map); + key.pid = (effective_cpumode == PERF_RECORD_MISC_KERNEL || + effective_cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ? + kernel_pid : thread__pid(aslr_thread); + + if (hashmap__find(&aslr->remap_addresses, &key, &remapped_invariant_ptr)) { + remap_addr = *remapped_invariant_ptr + map__pgoff(al.map) + + (addr - map__start(al.map)); + } else { + pr_debug("Cannot find a remapped entry for address %" PRIx64 " in mapping %" PRIx64 "(%zu) for pid=%d\n", + addr, map__start(al.map), map__size(al.map), key.pid); + } + + addr_location__exit(&al); + return remap_addr; +} + struct aslr_machine_priv { bool kernel_maps_loaded; }; @@ -616,13 +671,409 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, struct perf_sample *sample, struct machine *machine) { - struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); - struct aslr_tool *aslr = container_of(del_tool, struct aslr_tool, tool); - struct perf_tool *delegate = aslr->tool.delegate; + struct evsel *evsel = sample->evsel; + struct delegate_tool *del_tool; + struct aslr_tool *aslr; + struct perf_tool *delegate; + int ret; + u64 sample_type; + struct thread *thread; + struct machine *aslr_machine; + __u64 max_i; + __u64 max_j; + union perf_event *new_event; + struct perf_sample new_sample; + __u64 *in_array, *out_array; + u8 cpumode; + u64 addr; + size_t i; + size_t j; - return delegate->sample(delegate, event, sample, machine); + del_tool = container_of(tool, struct delegate_tool, tool); + aslr = container_of(del_tool, struct aslr_tool, tool); + delegate = aslr->tool.delegate; + + if (evsel__is_dummy_event(evsel)) + return delegate->sample(delegate, event, sample, machine); + + ret = -EFAULT; + sample_type = evsel->core.attr.sample_type; + max_i = (event->header.size - sizeof(struct perf_event_header)) / sizeof(__u64); + max_j = (PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_event_header)) / sizeof(__u64); + new_event = (union perf_event *)aslr->event_copy; + cpumode = sample->cpumode; + i = 0; + j = 0; + + aslr_machine = machines__findnew(&aslr->machines, machine->pid); + if (!aslr_machine) + return -ENOMEM; + if (aslr_tool__preload_kernel_maps(aslr_machine) < 0) + return -ENOMEM; + + thread = machine__findnew_thread(aslr_machine, sample->pid, sample->tid); + + if (!thread) + return -ENOMEM; + + if (max_i > PERF_SAMPLE_MAX_SIZE / sizeof(u64)) + goto out_put; + + new_event->sample.header = event->sample.header; + + in_array = &event->sample.array[0]; + out_array = &new_event->sample.array[0]; + +#define CHECK_BOUNDS(required_i, required_j) \ + (i + (required_i) > max_i || j + (required_j) > max_j) + +#define COPY_U64() \ + do { \ + if (CHECK_BOUNDS(1, 1)) { \ + ret = -EFAULT; \ + goto out_put; \ + } \ + out_array[j++] = in_array[i++]; \ + } while (0) + +#define REMAP_U64(addr_field) \ + do { \ + u64 remapped; \ + if (CHECK_BOUNDS(1, 1)) { \ + ret = -EFAULT; \ + goto out_put; \ + } \ + remapped = aslr_tool__remap_address(aslr, thread, cpumode, addr_field); \ + out_array[j++] = remapped; \ + i++; \ + } while (0) + + if (sample_type & PERF_SAMPLE_IDENTIFIER) + COPY_U64(); /* id */ + if (sample_type & PERF_SAMPLE_IP) + REMAP_U64(sample->ip); + if (sample_type & PERF_SAMPLE_TID) { + union { + u64 val64; + u32 val32[2]; + } u; + + if (CHECK_BOUNDS(1, 1)) { + ret = -EFAULT; + goto out_put; + } + u.val32[0] = sample->pid; + u.val32[1] = sample->tid; + out_array[j++] = u.val64; + i++; + } + if (sample_type & PERF_SAMPLE_TIME) + COPY_U64(); /* time */ + if (sample_type & PERF_SAMPLE_ADDR) + REMAP_U64(sample->addr); + if (sample_type & PERF_SAMPLE_ID) + COPY_U64(); /* id */ + if (sample_type & PERF_SAMPLE_STREAM_ID) + COPY_U64(); /* stream_id */ + if (sample_type & PERF_SAMPLE_CPU) + COPY_U64(); /* cpu, res */ + if (sample_type & PERF_SAMPLE_PERIOD) + COPY_U64(); /* period */ + if (sample_type & PERF_SAMPLE_READ) { + if ((evsel->core.attr.read_format & PERF_FORMAT_GROUP) == 0) { + COPY_U64(); /* value */ + if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + COPY_U64(); /* time_enabled */ + if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + COPY_U64(); /* time_running */ + if (evsel->core.attr.read_format & PERF_FORMAT_ID) + COPY_U64(); /* id */ + if (evsel->core.attr.read_format & PERF_FORMAT_LOST) + COPY_U64(); /* lost */ + } else { + u64 nr; + + if (CHECK_BOUNDS(1, 1)) { + ret = -EFAULT; + goto out_put; + } + nr = in_array[i]; + COPY_U64(); + if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) + COPY_U64(); /* time_enabled */ + if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + COPY_U64(); /* time_running */ + for (u64 cntr = 0; cntr < nr; cntr++) { + COPY_U64(); /* value */ + if (evsel->core.attr.read_format & PERF_FORMAT_ID) + COPY_U64(); /* id */ + if (evsel->core.attr.read_format & PERF_FORMAT_LOST) + COPY_U64(); /* lost */ + } + } + } + if (sample_type & PERF_SAMPLE_CALLCHAIN) { + u64 nr; + + if (CHECK_BOUNDS(1, 1)) { + ret = -EFAULT; + goto out_put; + } + nr = in_array[i]; + COPY_U64(); + + for (u64 cntr = 0; cntr < nr; cntr++) { + if (CHECK_BOUNDS(1, 1)) { + ret = -EFAULT; + goto out_put; + } + addr = in_array[i++]; + if (addr >= PERF_CONTEXT_MAX) { + out_array[j++] = addr; + switch (addr) { + case PERF_CONTEXT_HV: + cpumode = PERF_RECORD_MISC_HYPERVISOR; + break; + case PERF_CONTEXT_KERNEL: + cpumode = PERF_RECORD_MISC_KERNEL; + break; + case PERF_CONTEXT_USER: + cpumode = PERF_RECORD_MISC_USER; + break; + case PERF_CONTEXT_GUEST: + cpumode = PERF_RECORD_MISC_GUEST_KERNEL; + break; + case PERF_CONTEXT_GUEST_KERNEL: + cpumode = PERF_RECORD_MISC_GUEST_KERNEL; + break; + case PERF_CONTEXT_GUEST_USER: + cpumode = PERF_RECORD_MISC_GUEST_USER; + break; + case PERF_CONTEXT_USER_DEFERRED: + if (cntr + 1 >= nr) { + pr_debug("Truncated callchain deferred cookie context\n"); + ret = 0; + goto out_put; + } + /* + * Immediately followed by a 64-bit + * stitching cookie. Skip/Copy it! + */ + if (CHECK_BOUNDS(1, 1)) { + ret = -EFAULT; + goto out_put; + } + out_array[j++] = in_array[i++]; + cntr++; + cpumode = PERF_RECORD_MISC_USER; + break; + default: + pr_debug("invalid callchain context: %"PRIx64"\n", addr); + ret = 0; + goto out_put; + } + continue; + } + addr = aslr_tool__remap_address(aslr, thread, cpumode, addr); + out_array[j++] = addr; + } + } + if (sample_type & PERF_SAMPLE_RAW) { + size_t bytes = sizeof(u32) + sample->raw_size; + size_t u64_words = (bytes + 7) / 8; + + if (i + u64_words > max_i || j + u64_words > max_j) { + ret = -EFAULT; + goto out_put; + } + memcpy(&out_array[j], &in_array[i], bytes); + i += u64_words; + j += u64_words; + /* + * TODO: certain raw samples can be remapped, such as + * tracepoints by examining their fields. + */ + pr_debug("Dropping raw samples as possible ASLR leak\n"); + ret = 0; + goto out_put; + } + if (sample_type & PERF_SAMPLE_BRANCH_STACK) { + u64 nr; + + if (CHECK_BOUNDS(1, 1)) { + ret = -EFAULT; + goto out_put; + } + nr = in_array[i]; + COPY_U64(); + + if (evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX) + COPY_U64(); /* hw_idx */ + + if (nr > (ULLONG_MAX / 3)) { + ret = -EFAULT; + goto out_put; + } + if (nr * 3 > max_i - i || nr * 3 > max_j - j) { + ret = -EFAULT; + goto out_put; + } + for (u64 cntr = 0; cntr < nr; cntr++) { + u64 from = in_array[i++]; + u64 to = in_array[i++]; + + from = aslr_tool__remap_address(aslr, thread, sample->cpumode, from); + to = aslr_tool__remap_address(aslr, thread, sample->cpumode, to); + + out_array[j++] = from; + out_array[j++] = to; + out_array[j++] = in_array[i++]; /* flags */ + } + if (evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_COUNTERS) { + if (nr > max_i - i || nr > max_j - j) { + ret = -EFAULT; + goto out_put; + } + for (u64 cntr = 0; cntr < nr; cntr++) + COPY_U64(); + } + } + if (sample_type & PERF_SAMPLE_REGS_USER) { + if (CHECK_BOUNDS(1, 0)) { + ret = -EFAULT; + goto out_put; + } + /* abi */ + COPY_U64(); + /* TODO: can this be less conservative? */ + pr_debug("Dropping regs user sample as possible ASLR leak\n"); + ret = 0; + goto out_put; + } + if (sample_type & PERF_SAMPLE_STACK_USER) { + u64 size; + + if (CHECK_BOUNDS(1, 1)) { + ret = -EFAULT; + goto out_put; + } + size = in_array[i]; + COPY_U64(); + if (size > 0) { + size_t u64_words = size / 8 + (size % 8 ? 1 : 0); + + if (u64_words > max_i - i || u64_words > max_j - j) { + ret = -EFAULT; + goto out_put; + } + memcpy(&out_array[j], &in_array[i], size); + if (size % 8) { + size_t pad = 8 - (size % 8); + + memset(((char *)&out_array[j]) + size, 0, pad); + } + i += u64_words; + j += u64_words; + } + /* TODO: can this be less conservative? */ + pr_debug("Dropping stack user sample as possible ASLR leak\n"); + ret = 0; + goto out_put; + } + if (sample_type & PERF_SAMPLE_WEIGHT_TYPE) + COPY_U64(); /* perf_sample_weight */ + if (sample_type & PERF_SAMPLE_DATA_SRC) + COPY_U64(); /* data_src */ + if (sample_type & PERF_SAMPLE_TRANSACTION) + COPY_U64(); /* transaction */ + if (sample_type & PERF_SAMPLE_REGS_INTR) { + if (CHECK_BOUNDS(1, 0)) { + ret = -EFAULT; + goto out_put; + } + /* abi */ + COPY_U64(); + /* TODO: can this be less conservative? */ + pr_debug("Dropping interrupt register sample as possible ASLR leak\n"); + ret = 0; + goto out_put; + } + if (sample_type & PERF_SAMPLE_PHYS_ADDR) { + COPY_U64(); /* phys_addr */ + /* TODO: can this be less conservative? */ + pr_debug("Dropping physical address sample as possible ASLR leak\n"); + ret = 0; + goto out_put; + } + if (sample_type & PERF_SAMPLE_CGROUP) + COPY_U64(); /* cgroup */ + if (sample_type & PERF_SAMPLE_DATA_PAGE_SIZE) + COPY_U64(); /* data_page_size */ + if (sample_type & PERF_SAMPLE_CODE_PAGE_SIZE) + COPY_U64(); /* code_page_size */ + + if (sample_type & PERF_SAMPLE_AUX) { + u64 size; + + if (CHECK_BOUNDS(1, 1)) { + ret = -EFAULT; + goto out_put; + } + out_array[j] = in_array[i]; + size = out_array[j++]; + i++; + if (size > 0) { + size_t u64_words = size / 8 + (size % 8 ? 1 : 0); + + if (u64_words > max_i - i || u64_words > max_j - j) { + ret = -EFAULT; + goto out_put; + } + memcpy(&out_array[j], &in_array[i], size); + if (size % 8) { + size_t pad = 8 - (size % 8); + + memset(((char *)&out_array[j]) + size, 0, pad); + } + i += u64_words; + j += u64_words; + } + /* TODO: can this be less conservative? */ + pr_debug("Dropping aux sample as possible ASLR leak\n"); + ret = 0; + goto out_put; + } + + if (evsel__is_offcpu_event(evsel)) { + /* TODO: can this be less conservative? */ + pr_debug("Dropping off-CPU sample as possible ASLR leak\n"); + ret = 0; + goto out_put; + } + + new_event->sample.header.size = sizeof(struct perf_event_header) + j * sizeof(u64); + + perf_sample__init(&new_sample, /*all=*/ true); + ret = __evsel__parse_sample(evsel, new_event, &new_sample, /*needs_swap=*/false); + + if (ret) { + perf_sample__exit(&new_sample); + goto out_put; + } + + new_sample.evsel = evsel; + ret = delegate->sample(delegate, new_event, &new_sample, machine); + perf_sample__exit(&new_sample); + +out_put: + thread__put(thread); + return ret; } +#undef CHECK_BOUNDS +#undef COPY_U64 +#undef REMAP_U64 + static int skipn(int fd, off_t n) { char buf[4096]; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 34c03f47a913..05fa0010c858 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3337,11 +3337,11 @@ static int __set_offcpu_sample(struct perf_sample *data) return -EFAULT; } -int evsel__parse_sample(struct evsel *evsel, union perf_event *event, - struct perf_sample *data) +int __evsel__parse_sample(struct evsel *evsel, union perf_event *event, + struct perf_sample *data, bool needs_swap) { u64 type = evsel->core.attr.sample_type; - bool swapped = evsel->needs_swap; + bool swapped = needs_swap; const __u64 *array; u16 max_size = event->header.size; const void *endp = (void *)event + max_size; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 8178858d168a..8009be22cc3f 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -432,8 +432,14 @@ static inline int evsel__read_on_cpu_scaled(struct evsel *evsel, int cpu_map_idx return __evsel__read_on_cpu(evsel, cpu_map_idx, thread, true); } -int evsel__parse_sample(struct evsel *evsel, union perf_event *event, - struct perf_sample *sample); +int __evsel__parse_sample(struct evsel *evsel, union perf_event *event, + struct perf_sample *data, bool needs_swap); + +static inline int evsel__parse_sample(struct evsel *evsel, union perf_event *event, + struct perf_sample *data) +{ + return __evsel__parse_sample(evsel, event, data, evsel->needs_swap); +} int evsel__parse_sample_timestamp(struct evsel *evsel, union perf_event *event, u64 *timestamp); From d6dbf2d4a9009a9cec1b33325308fa5b3a7b6ba9 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 11 Jun 2026 09:41:21 -0700 Subject: [PATCH 314/343] perf aslr: Strip sample registers Extend the ASLR tool stripping helpers to drop register dump payloads by masking out the relevant perf_event_attr fields (sample_regs_user, sample_regs_intr) when the delegated tool is handling the data. struct aslr_evsel_priv maintains the original perf_event_attr values and is looked up via the evsel_orig_attrs hashmap so that sample sizes can be properly parsed even when bits are stripped from the pipeline. This is critical for bounded array copying within aslr_tool__process_sample, which relies on orig_sample_type to determine exactly which fields were captured by the kernel before any stripping occurred. This allows us to keep samples that would otherwise be dropped because they contain registers, while still obfuscating the registers. Committer notes: Moved now used variables from the previous patch: struct aslr_evsel_priv *priv = NULL; u64 orig_sample_type; u64 orig_regs_user; u64 orig_regs_intr; Assisted-by: Antigravity:gemini-3.1-pro Co-developed-by: Gabriel Marin Signed-off-by: Gabriel Marin Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 28 +++- tools/perf/util/aslr.c | 266 +++++++++++++++++++++++++++--------- tools/perf/util/aslr.h | 9 +- 3 files changed, 233 insertions(+), 70 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 8bb37095e2de..6d6cce4765a7 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -248,7 +248,7 @@ static int perf_event__repipe_attr(const struct perf_tool *tool, if (!aslr_event) return -ENOMEM; memcpy(aslr_event, event, event->header.size); - aslr_tool__strip_attr_event(aslr_event, pevlist); + aslr_tool__strip_attr_event(aslr_event, *pevlist); event = aslr_event; } @@ -297,6 +297,7 @@ static int perf_event__repipe_attr(const struct perf_tool *tool, attr.size = sizeof(struct perf_event_attr); attr.sample_type &= ~PERF_SAMPLE_AUX; + if (inject->itrace_synth_opts.add_last_branch) { attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX; @@ -2617,6 +2618,10 @@ static int __cmd_inject(struct perf_inject *inject) evsel->core.attr.exclude_callchain_user = 0; } } + + if (inject->aslr) + aslr_tool__strip_evlist(inject->session->tool, session->evlist); + session->header.data_offset = output_data_offset; session->header.data_size = inject->bytes_written; perf_session__inject_header(session, session->evlist, fd, &inj_fc.fc, @@ -2875,6 +2880,18 @@ int cmd_inject(int argc, const char **argv) if (zstd_init(&(inject.session->zstd_data), 0) < 0) pr_warning("Decompression initialization failed.\n"); + if (inject.aslr) { + struct evsel *evsel; + + evlist__for_each_entry(inject.session->evlist, evsel) { + ret = aslr_tool__cache_orig_attrs(tool, evsel); + if (ret) { + pr_err("Failed to cache original attributes: %d\n", ret); + goto out_delete; + } + } + } + /* Save original section info before feature bits change */ ret = save_section_info(&inject); if (ret) @@ -2893,10 +2910,17 @@ int cmd_inject(int argc, const char **argv) * the input. */ if (!data.is_pipe) { + if (inject.aslr) + aslr_tool__strip_evlist(tool, inject.session->evlist); + ret = perf_event__synthesize_for_pipe(&inject.tool, inject.session, &inject.output, perf_event__repipe); + + if (inject.aslr) + aslr_tool__restore_evlist(tool, inject.session->evlist); + if (ret < 0) goto out_delete; } @@ -2961,8 +2985,6 @@ int cmd_inject(int argc, const char **argv) goto out_delete; ret = __cmd_inject(&inject); - if (inject.aslr) - aslr_tool__strip_evlist(tool, inject.session->evlist); guest_session__exit(&inject.guest_session); diff --git a/tools/perf/util/aslr.c b/tools/perf/util/aslr.c index d0760ca8926d..a946fff2ac4d 100644 --- a/tools/perf/util/aslr.c +++ b/tools/perf/util/aslr.c @@ -18,6 +18,7 @@ #include /* page_size */ #include #include +#include #include #include #include @@ -46,6 +47,23 @@ struct aslr_mapping { u64 remap_start; }; +struct aslr_evsel_priv { + u64 orig_sample_type; + u64 orig_sample_regs_user; + u64 orig_sample_regs_intr; + int orig_sample_size; +}; + +static size_t evsel_hash(long key, void *ctx __maybe_unused) +{ + return (size_t)key; +} + +static bool evsel_equal(long key1, long key2, void *ctx __maybe_unused) +{ + return key1 == key2; +} + struct process_top_address { u64 remapped_max; }; @@ -60,6 +78,11 @@ struct aslr_tool { struct hashmap remap_addresses; /** @top_addresses: mapping from process to max remapped address. */ struct hashmap top_addresses; + /** + * @evsel_orig_attrs: mapping from evsel pointer to its original + * unstripped sample_type and registers bitmasks. + */ + struct hashmap evsel_orig_attrs; }; static const pid_t kernel_pid = -1; @@ -123,6 +146,8 @@ static u64 aslr_tool__remap_address(struct aslr_tool *aslr, u64 *remapped_invariant_ptr = NULL; u64 remap_addr = 0; u8 effective_cpumode = cpumode; + struct dso *dso; + const char *dso_name; if (!aslr_thread) return 0; /* No thread. */ @@ -148,9 +173,15 @@ static u64 aslr_tool__remap_address(struct aslr_tool *aslr, } } + dso = map__dso(al.map); + dso_name = dso ? dso__long_name(dso) : NULL; + key.machine = maps__machine(thread__maps(aslr_thread)); - key.dso = map__dso(al.map); - key.invariant = map__start(al.map) - map__pgoff(al.map); + key.dso = dso; + if (dso && !is_anon_memory(dso_name) && !is_no_dso_memory(dso_name)) + key.invariant = map__start(al.map) - map__pgoff(al.map); + else + key.invariant = map__start(al.map); key.pid = (effective_cpumode == PERF_RECORD_MISC_KERNEL || effective_cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ? kernel_pid : thread__pid(aslr_thread); @@ -676,6 +707,7 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, struct aslr_tool *aslr; struct perf_tool *delegate; int ret; + int orig_sample_size; u64 sample_type; struct thread *thread; struct machine *aslr_machine; @@ -688,6 +720,10 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, u64 addr; size_t i; size_t j; + struct aslr_evsel_priv *priv = NULL; + u64 orig_sample_type; + u64 orig_regs_user; + u64 orig_regs_intr; del_tool = container_of(tool, struct delegate_tool, tool); aslr = container_of(del_tool, struct aslr_tool, tool); @@ -697,7 +733,24 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, return delegate->sample(delegate, event, sample, machine); ret = -EFAULT; - sample_type = evsel->core.attr.sample_type; + + if (hashmap__find(&aslr->evsel_orig_attrs, evsel, &priv)) { + orig_sample_type = priv->orig_sample_type; + orig_regs_user = priv->orig_sample_regs_user; + orig_regs_intr = priv->orig_sample_regs_intr; + } else { + orig_sample_type = evsel->core.attr.sample_type; + orig_regs_user = evsel->core.attr.sample_regs_user; + orig_regs_intr = evsel->core.attr.sample_regs_intr; + } + + orig_sample_size = evsel->sample_size; + + sample_type = orig_sample_type; + sample_type &= ~PERF_SAMPLE_REGS_USER; + sample_type &= ~PERF_SAMPLE_REGS_INTR; + sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE; + max_i = (event->header.size - sizeof(struct perf_event_header)) / sizeof(__u64); max_j = (PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_event_header)) / sizeof(__u64); new_event = (union perf_event *)aslr->event_copy; @@ -748,11 +801,11 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, i++; \ } while (0) - if (sample_type & PERF_SAMPLE_IDENTIFIER) + if (orig_sample_type & PERF_SAMPLE_IDENTIFIER) COPY_U64(); /* id */ - if (sample_type & PERF_SAMPLE_IP) + if (orig_sample_type & PERF_SAMPLE_IP) REMAP_U64(sample->ip); - if (sample_type & PERF_SAMPLE_TID) { + if (orig_sample_type & PERF_SAMPLE_TID) { union { u64 val64; u32 val32[2]; @@ -767,19 +820,19 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, out_array[j++] = u.val64; i++; } - if (sample_type & PERF_SAMPLE_TIME) + if (orig_sample_type & PERF_SAMPLE_TIME) COPY_U64(); /* time */ - if (sample_type & PERF_SAMPLE_ADDR) + if (orig_sample_type & PERF_SAMPLE_ADDR) REMAP_U64(sample->addr); - if (sample_type & PERF_SAMPLE_ID) + if (orig_sample_type & PERF_SAMPLE_ID) COPY_U64(); /* id */ - if (sample_type & PERF_SAMPLE_STREAM_ID) + if (orig_sample_type & PERF_SAMPLE_STREAM_ID) COPY_U64(); /* stream_id */ - if (sample_type & PERF_SAMPLE_CPU) + if (orig_sample_type & PERF_SAMPLE_CPU) COPY_U64(); /* cpu, res */ - if (sample_type & PERF_SAMPLE_PERIOD) + if (orig_sample_type & PERF_SAMPLE_PERIOD) COPY_U64(); /* period */ - if (sample_type & PERF_SAMPLE_READ) { + if (orig_sample_type & PERF_SAMPLE_READ) { if ((evsel->core.attr.read_format & PERF_FORMAT_GROUP) == 0) { COPY_U64(); /* value */ if (evsel->core.attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) @@ -812,7 +865,7 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, } } } - if (sample_type & PERF_SAMPLE_CALLCHAIN) { + if (orig_sample_type & PERF_SAMPLE_CALLCHAIN) { u64 nr; if (CHECK_BOUNDS(1, 1)) { @@ -878,7 +931,7 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, out_array[j++] = addr; } } - if (sample_type & PERF_SAMPLE_RAW) { + if (orig_sample_type & PERF_SAMPLE_RAW) { size_t bytes = sizeof(u32) + sample->raw_size; size_t u64_words = (bytes + 7) / 8; @@ -897,7 +950,7 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, ret = 0; goto out_put; } - if (sample_type & PERF_SAMPLE_BRANCH_STACK) { + if (orig_sample_type & PERF_SAMPLE_BRANCH_STACK) { u64 nr; if (CHECK_BOUNDS(1, 1)) { @@ -938,19 +991,25 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, COPY_U64(); } } - if (sample_type & PERF_SAMPLE_REGS_USER) { + if (orig_sample_type & PERF_SAMPLE_REGS_USER) { + u64 abi; + if (CHECK_BOUNDS(1, 0)) { ret = -EFAULT; goto out_put; } - /* abi */ - COPY_U64(); - /* TODO: can this be less conservative? */ - pr_debug("Dropping regs user sample as possible ASLR leak\n"); - ret = 0; - goto out_put; + abi = in_array[i++]; + if (abi != PERF_SAMPLE_REGS_ABI_NONE) { + u64 nr = hweight64(orig_regs_user); + + if (nr > max_i - i) { + ret = -EFAULT; + goto out_put; + } + i += nr; + } } - if (sample_type & PERF_SAMPLE_STACK_USER) { + if (orig_sample_type & PERF_SAMPLE_STACK_USER) { u64 size; if (CHECK_BOUNDS(1, 1)) { @@ -980,39 +1039,45 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, ret = 0; goto out_put; } - if (sample_type & PERF_SAMPLE_WEIGHT_TYPE) + if (orig_sample_type & PERF_SAMPLE_WEIGHT_TYPE) COPY_U64(); /* perf_sample_weight */ - if (sample_type & PERF_SAMPLE_DATA_SRC) + if (orig_sample_type & PERF_SAMPLE_DATA_SRC) COPY_U64(); /* data_src */ - if (sample_type & PERF_SAMPLE_TRANSACTION) + if (orig_sample_type & PERF_SAMPLE_TRANSACTION) COPY_U64(); /* transaction */ - if (sample_type & PERF_SAMPLE_REGS_INTR) { + if (orig_sample_type & PERF_SAMPLE_REGS_INTR) { + u64 abi; + if (CHECK_BOUNDS(1, 0)) { ret = -EFAULT; goto out_put; } - /* abi */ - COPY_U64(); - /* TODO: can this be less conservative? */ - pr_debug("Dropping interrupt register sample as possible ASLR leak\n"); - ret = 0; - goto out_put; + abi = in_array[i++]; + if (abi != PERF_SAMPLE_REGS_ABI_NONE) { + u64 nr = hweight64(orig_regs_intr); + + if (nr > max_i - i) { + ret = -EFAULT; + goto out_put; + } + i += nr; + } } - if (sample_type & PERF_SAMPLE_PHYS_ADDR) { + if (orig_sample_type & PERF_SAMPLE_PHYS_ADDR) { COPY_U64(); /* phys_addr */ /* TODO: can this be less conservative? */ pr_debug("Dropping physical address sample as possible ASLR leak\n"); ret = 0; goto out_put; } - if (sample_type & PERF_SAMPLE_CGROUP) + if (orig_sample_type & PERF_SAMPLE_CGROUP) COPY_U64(); /* cgroup */ - if (sample_type & PERF_SAMPLE_DATA_PAGE_SIZE) + if (orig_sample_type & PERF_SAMPLE_DATA_PAGE_SIZE) COPY_U64(); /* data_page_size */ - if (sample_type & PERF_SAMPLE_CODE_PAGE_SIZE) + if (orig_sample_type & PERF_SAMPLE_CODE_PAGE_SIZE) COPY_U64(); /* code_page_size */ - if (sample_type & PERF_SAMPLE_AUX) { + if (orig_sample_type & PERF_SAMPLE_AUX) { u64 size; if (CHECK_BOUNDS(1, 1)) { @@ -1052,11 +1117,20 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, } new_event->sample.header.size = sizeof(struct perf_event_header) + j * sizeof(u64); - + /* Temporarily override evsel attributes to match the stripped new_event format! */ + evsel->sample_size = __evsel__sample_size(sample_type); + evsel->core.attr.sample_type = sample_type; + evsel->core.attr.sample_regs_user = 0; + evsel->core.attr.sample_regs_intr = 0; perf_sample__init(&new_sample, /*all=*/ true); ret = __evsel__parse_sample(evsel, new_event, &new_sample, /*needs_swap=*/false); if (ret) { + /* Restore original attributes immediately if parsing fails */ + evsel->sample_size = orig_sample_size; + evsel->core.attr.sample_type = orig_sample_type; + evsel->core.attr.sample_regs_user = orig_regs_user; + evsel->core.attr.sample_regs_intr = orig_regs_intr; perf_sample__exit(&new_sample); goto out_put; } @@ -1065,6 +1139,12 @@ static int aslr_tool__process_sample(const struct perf_tool *tool, ret = delegate->sample(delegate, new_event, &new_sample, machine); perf_sample__exit(&new_sample); + /* Restore original attributes so trace ingestion never desynchronizes! */ + evsel->sample_size = orig_sample_size; + evsel->core.attr.sample_type = orig_sample_type; + evsel->core.attr.sample_regs_user = orig_regs_user; + evsel->core.attr.sample_regs_intr = orig_regs_intr; + out_put: thread__put(thread); return ret; @@ -1118,15 +1198,22 @@ static int aslr_tool__process_auxtrace_error(const struct perf_tool *tool __mayb return 0; } - -void aslr_tool__strip_attr_event(union perf_event *event, struct evlist **pevlist __maybe_unused) +void aslr_tool__strip_attr_event(union perf_event *event, struct evlist *evlist) { u32 attr_size; + if (!evlist) + return; + attr_size = event->attr.attr.size ?: PERF_ATTR_SIZE_VER0; if (attr_size >= (offsetof(struct perf_event_attr, sample_type) + sizeof(u64))) { event->attr.attr.sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE; + + if (attr_size >= (offsetof(struct perf_event_attr, sample_regs_user) + sizeof(u64))) + event->attr.attr.sample_regs_user = 0; + if (attr_size >= (offsetof(struct perf_event_attr, sample_regs_intr) + sizeof(u64))) + event->attr.attr.sample_regs_intr = 0; } if (attr_size >= (offsetof(struct perf_event_attr, type) + sizeof(u32))) { @@ -1150,28 +1237,6 @@ void aslr_tool__strip_attr_event(union perf_event *event, struct evlist **pevlis } } -void aslr_tool__strip_evlist(struct perf_tool *tool __maybe_unused, - struct evlist *evlist) -{ - struct evsel *evsel; - - evlist__for_each_entry(evlist, evsel) { - evsel->core.attr.sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE; - - if (evsel->core.attr.type == PERF_TYPE_BREAKPOINT) - evsel->core.attr.bp_addr = 0; - else if (evsel->core.attr.type >= PERF_TYPE_MAX) { - struct perf_pmu *pmu = perf_pmus__find_by_type(evsel->core.attr.type); - - if (pmu && (!strcmp(pmu->name, "kprobe") || - !strcmp(pmu->name, "uprobe"))) { - evsel->core.attr.config1 = 0; - evsel->core.attr.config2 = 0; - } - } - } -} - static void aslr_tool__init(struct aslr_tool *aslr, struct perf_tool *delegate) { delegate_tool__init(&aslr->tool, delegate); @@ -1185,6 +1250,9 @@ static void aslr_tool__init(struct aslr_tool *aslr, struct perf_tool *delegate) hashmap__init(&aslr->top_addresses, top_addresses__hash, top_addresses__equal, /*ctx=*/NULL); + hashmap__init(&aslr->evsel_orig_attrs, + evsel_hash, evsel_equal, + /*ctx=*/NULL); aslr->tool.tool.sample = aslr_tool__process_sample; /* read - reads a counter, okay to delegate. */ @@ -1247,9 +1315,13 @@ void aslr_tool__delete(struct perf_tool *tool) zfree(&cur->pkey); zfree(&cur->pvalue); } + hashmap__for_each_entry(&aslr->evsel_orig_attrs, cur, bkt) { + zfree(&cur->pvalue); + } hashmap__clear(&aslr->remap_addresses); hashmap__clear(&aslr->top_addresses); + hashmap__clear(&aslr->evsel_orig_attrs); aslr_tool__destroy_machines_priv(&aslr->machines); machines__destroy_kernel_maps(&aslr->machines); @@ -1263,3 +1335,69 @@ void aslr_tool__delete(struct perf_tool *tool) machines__exit(&aslr->machines); free(aslr); } + +int aslr_tool__cache_orig_attrs(struct perf_tool *tool, struct evsel *evsel) +{ + struct delegate_tool *del_tool = container_of(tool, struct delegate_tool, tool); + struct aslr_tool *aslr = container_of(del_tool, struct aslr_tool, tool); + struct aslr_evsel_priv *priv = zalloc(sizeof(*priv)); + int err; + + if (!priv) + return -ENOMEM; + + priv->orig_sample_type = evsel->core.attr.sample_type; + priv->orig_sample_regs_user = evsel->core.attr.sample_regs_user; + priv->orig_sample_regs_intr = evsel->core.attr.sample_regs_intr; + priv->orig_sample_size = evsel->sample_size; + + err = hashmap__add(&aslr->evsel_orig_attrs, evsel, priv); + if (err) { + free(priv); + return err; + } + return 0; +} + +void aslr_tool__strip_evlist(const struct perf_tool *tool __maybe_unused, struct evlist *evlist) +{ + struct evsel *evsel; + + evlist__for_each_entry(evlist, evsel) { + evsel->core.attr.sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE; + evsel->core.attr.sample_regs_user = 0; + evsel->core.attr.sample_regs_intr = 0; + evsel->sample_size = __evsel__sample_size(evsel->core.attr.sample_type); + evsel__calc_id_pos(evsel); + + if (evsel->core.attr.type == PERF_TYPE_BREAKPOINT) { + evsel->core.attr.bp_addr = 0; + } else if (evsel->core.attr.type >= PERF_TYPE_MAX) { + struct perf_pmu *pmu = perf_pmus__find_by_type(evsel->core.attr.type); + + if (pmu && (!strcmp(pmu->name, "kprobe") || + !strcmp(pmu->name, "uprobe"))) { + evsel->core.attr.config1 = 0; + evsel->core.attr.config2 = 0; + } + } + } +} + +void aslr_tool__restore_evlist(const struct perf_tool *tool, struct evlist *evlist) +{ + const struct delegate_tool *del_tool = container_of(tool, const struct delegate_tool, tool); + const struct aslr_tool *aslr = container_of(del_tool, const struct aslr_tool, tool); + struct evsel *evsel; + struct aslr_evsel_priv *priv; + + evlist__for_each_entry(evlist, evsel) { + if (hashmap__find(&aslr->evsel_orig_attrs, evsel, &priv)) { + evsel->core.attr.sample_type = priv->orig_sample_type; + evsel->core.attr.sample_regs_user = priv->orig_sample_regs_user; + evsel->core.attr.sample_regs_intr = priv->orig_sample_regs_intr; + evsel->sample_size = priv->orig_sample_size; + evsel__calc_id_pos(evsel); + } + } +} diff --git a/tools/perf/util/aslr.h b/tools/perf/util/aslr.h index 2b82f711bc67..522e31c8e2c0 100644 --- a/tools/perf/util/aslr.h +++ b/tools/perf/util/aslr.h @@ -34,8 +34,11 @@ struct evlist; union perf_event; struct perf_tool *aslr_tool__new(struct perf_tool *delegate); -void aslr_tool__delete(struct perf_tool *aslr); -void aslr_tool__strip_attr_event(union perf_event *event, struct evlist **pevlist); -void aslr_tool__strip_evlist(struct perf_tool *tool, struct evlist *evlist); +void aslr_tool__delete(struct perf_tool *tool); + +void aslr_tool__strip_attr_event(union perf_event *event, struct evlist *evlist); +int aslr_tool__cache_orig_attrs(struct perf_tool *tool, struct evsel *evsel); +void aslr_tool__strip_evlist(const struct perf_tool *tool, struct evlist *evlist); +void aslr_tool__restore_evlist(const struct perf_tool *tool, struct evlist *evlist); #endif /* __PERF_ASLR_H */ From 190c4546384461f3dee70a649b438aa41c24d01e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 11 Jun 2026 09:41:22 -0700 Subject: [PATCH 315/343] perf test: Add inject ASLR test Add a new shell test to verify the feature. The test covers: - Basic address remapping for user space samples. - Pipe mode coverage for piped into. - Callchain address remapping. - Consistency of output before and after injection. - Pipe mode report consistency. - Dropping of samples that leak ASLR info (physical addresses). - Kernel address remapping (utilizing a dedicated kernel-intensive VFS dd workload to guarantee continuous timer interrupts sampling flow inside kernel privilege states). - Kernel report consistency with address normalization. The test suite is hardened with global 'set -o pipefail' assertions to catch pipeline failures, stream-consuming awk processors to handle SIGPIPE signals, and a dedicated pipe output scenario validating raw 'perf inject -o -' stdout streams. Note on kernel DSO normalization in the test script: The test script deliberately normalizes all kernel DSOs to a generic [kernel] tag before diffing, as obfuscating physical kernel addresses forces perf report to occasionally shift samples between individual modules and [kernel.kallsyms] due to the lack of valid host module boundary maps. Note on ARM: Kernel-based ASLR test cases (test_kernel_aslr and test_kernel_report_aslr) are skipped on ARM architectures (aarch64 and arm*) to bypass high latency constraints (such as check_invariants() spending excessive execution time in maps__split_kallsyms() on debug builds) and symbolization inconsistencies. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers Tested-by: James Clark Cc: Adrian Hunter Cc: Gabriel Marin Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/shell/inject_aslr.sh | 533 ++++++++++++++++++++++++++ 1 file changed, 533 insertions(+) create mode 100755 tools/perf/tests/shell/inject_aslr.sh diff --git a/tools/perf/tests/shell/inject_aslr.sh b/tools/perf/tests/shell/inject_aslr.sh new file mode 100755 index 000000000000..c00461828ea7 --- /dev/null +++ b/tools/perf/tests/shell/inject_aslr.sh @@ -0,0 +1,533 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# perf inject --aslr test + +set -e +set -o pipefail + +shelldir=$(dirname "$0") +# shellcheck source=lib/perf_has_symbol.sh +. "${shelldir}"/lib/perf_has_symbol.sh + +sym="noploop" + +skip_test_missing_symbol ${sym} + +# Create global temp directory +temp_dir=$(mktemp -d /tmp/perf-test-aslr.XXXXXXXXXX) + +prog="perf test -w noploop" +[ "$(uname -m)" = "s390x" ] && prog="$prog 3" +err=0 +kprog="dd if=/dev/urandom of=/dev/null bs=1M count=50" + +cleanup() { + local exit_code=${1:-$?} + trap - EXIT TERM INT + if [ "${exit_code}" -ne 0 ] || [ "${err}" -ne 0 ]; then + echo "Test failed! Preserving temp directory: ${temp_dir}" + return + fi + # Check if temp_dir is set and looks sane before removing + if [[ "${temp_dir}" =~ ^/tmp/perf-test-aslr\. ]]; then + rm -rf "${temp_dir}" + fi +} + +trap_cleanup() { + local exit_code=$? + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup ${exit_code} + exit ${exit_code} +} +trap trap_cleanup EXIT TERM INT + +get_noploop_addr() { + local file=$1 + perf script -i "$file" | awk ' + BEGIN { found=0 } + { + for (i=1; i<=NF; i++) { + if ($i ~ /noploop\+/) { + if (!found) { + print $(i-1) + found=1 + } + } + } + }' +} + +test_basic_aslr() { + echo "Test basic ASLR remapping" + local data + data=$(mktemp "${temp_dir}/perf.data.basic.XXXXXX") + local data2 + data2=$(mktemp "${temp_dir}/perf.data2.basic.XXXXXX") + + perf record -e task-clock:u -o "${data}" ${prog} + perf inject -v --aslr -i "${data}" -o "${data2}" + + orig_addr=$(get_noploop_addr "${data}") + new_addr=$(get_noploop_addr "${data2}") + + echo "Basic ASLR: orig_addr=$orig_addr, new_addr=$new_addr" + + if [ -z "$orig_addr" ]; then + echo "Basic ASLR test [Failed - no noploop samples in original file]" + err=1 + elif [ -z "$new_addr" ]; then + echo "Basic ASLR test [Failed - could not find remapped address]" + err=1 + elif [ "$orig_addr" = "$new_addr" ]; then + echo "Basic ASLR test [Failed - addresses are not remapped]" + err=1 + else + echo "Basic ASLR test [Success]" + fi +} + +test_pipe_aslr() { + echo "Test pipe mode ASLR remapping" + local data + data=$(mktemp "${temp_dir}/perf.data.pipe.XXXXXX") + local data2 + data2=$(mktemp "${temp_dir}/perf.data2.pipe.XXXXXX") + + # Use tee to save the original pipe data for comparison + perf record -e task-clock:u -o - ${prog} | tee "${data}" | perf inject --aslr -o "${data2}" + + orig_addr=$(get_noploop_addr "${data}") + new_addr=$(get_noploop_addr "${data2}") + + echo "Pipe ASLR: orig_addr=$orig_addr, new_addr=$new_addr" + + if [ -z "$orig_addr" ]; then + echo "Pipe ASLR test [Failed - no noploop samples in original file]" + err=1 + elif [ -z "$new_addr" ]; then + echo "Pipe ASLR test [Failed - could not find remapped address]" + err=1 + elif [ "$orig_addr" = "$new_addr" ]; then + echo "Pipe ASLR test [Failed - addresses are not remapped]" + err=1 + else + echo "Pipe ASLR test [Success]" + fi +} + +test_callchain_aslr() { + echo "Test Callchain ASLR remapping" + local data + data=$(mktemp "${temp_dir}/perf.data.callchain.XXXXXX") + local data2 + data2=$(mktemp "${temp_dir}/perf.data2.callchain.XXXXXX") + + perf record -g -e task-clock:u -o "${data}" ${prog} + perf inject --aslr -i "${data}" -o "${data2}" + + orig_addr=$(get_noploop_addr "${data}") + new_addr=$(get_noploop_addr "${data2}") + + echo "Callchain ASLR: orig_addr=$orig_addr, new_addr=$new_addr" + + if [ -z "$orig_addr" ]; then + echo "Callchain ASLR test [Failed - no noploop samples in original file]" + err=1 + elif [ -z "$new_addr" ]; then + echo "Callchain ASLR test [Failed - could not find remapped address]" + err=1 + elif [ "$orig_addr" = "$new_addr" ]; then + echo "Callchain ASLR test [Failed - addresses are not remapped]" + err=1 + else + # Extract callchain addresses (indented lines starting with hex addresses) + orig_callchain=$(perf script -i "${data}" | awk '/^[[:space:]]+[0-9a-f]+/ {print $1}') + new_callchain=$(perf script -i "${data2}" | awk '/^[[:space:]]+[0-9a-f]+/ {print $1}') + + if [ -z "$orig_callchain" ]; then + echo "Callchain ASLR test [Failed - no callchain samples in original file]" + err=1 + elif [ -z "$new_callchain" ]; then + echo "Callchain ASLR test [Failed - callchain data was dropped]" + err=1 + elif [ "$orig_callchain" = "$new_callchain" ]; then + echo "Callchain ASLR test [Failed - callchain addresses were not remapped]" + err=1 + else + echo "Callchain ASLR test [Success]" + fi + fi +} + +test_report_aslr() { + echo "Test perf report consistency" + local data + data=$(mktemp "${temp_dir}/perf.data.report.XXXXXX") + local data2 + data2=$(mktemp "${temp_dir}/perf.data2.report.XXXXXX") + local data_clean + data_clean=$(mktemp "${temp_dir}/perf.data.clean.XXXXXX") + + perf record -e task-clock:u -o "${data}" ${prog} + # Use -b to inject build-ids and force ordered events processing in both + perf inject -b -i "${data}" -o "${data_clean}" + perf inject -v -b --aslr -i "${data}" -o "${data2}" + + local report1="${temp_dir}/report1_basic" + local report2="${temp_dir}/report2_basic" + local report1_clean="${temp_dir}/report1_basic.clean" + local report2_clean="${temp_dir}/report2_basic.clean" + local diff_file="${temp_dir}/diff_basic" + + perf report -i "${data_clean}" --stdio > "${report1}" + perf report -i "${data2}" --stdio > "${report2}" + + # Strip headers and compare lines with percentages + grep '%' "${report1}" | grep -v '^#' | \ + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' | sort > "${report1_clean}" || true + grep '%' "${report2}" | grep -v '^#' | \ + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' | sort > "${report2_clean}" || true + + diff -u -w "${report1_clean}" "${report2_clean}" > "${diff_file}" || true + + if [ ! -s "${report1_clean}" ]; then + echo "Report ASLR test [Failed - no samples captured]" + err=1 + elif [ -s "${diff_file}" ]; then + echo "Report ASLR test [Failed - reports differ]" + echo "Showing first 20 lines of diff:" + head -n 20 "${diff_file}" + err=1 + else + echo "Report ASLR test [Success]" + fi +} + +test_pipe_report_aslr() { + echo "Test pipe mode perf report consistency" + local data + data=$(mktemp "${temp_dir}/perf.data.pipe_report.XXXXXX") + local data2 + data2=$(mktemp "${temp_dir}/perf.data2.pipe_report.XXXXXX") + local data_clean + data_clean=$(mktemp "${temp_dir}/perf.data.clean.XXXXXX") + + # Use tee to save the original pipe data, then process it with inject -b + perf record -e task-clock:u -o - ${prog} | \ + tee "${data}" | \ + perf inject -b --aslr -o "${data2}" + perf inject -b -i "${data}" -o "${data_clean}" + + local report1="${temp_dir}/report1_pipe" + local report2="${temp_dir}/report2_pipe" + local report1_clean="${temp_dir}/report1_pipe.clean" + local report2_clean="${temp_dir}/report2_pipe.clean" + local diff_file="${temp_dir}/diff_pipe" + + perf report -i "${data_clean}" --stdio > "${report1}" + perf report -i "${data2}" --stdio > "${report2}" + + # Strip headers and compare lines with percentages + grep '%' "${report1}" | grep -v '^#' | \ + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' | sort > "${report1_clean}" || true + grep '%' "${report2}" | grep -v '^#' | \ + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' | sort > "${report2_clean}" || true + + diff -u -w "${report1_clean}" "${report2_clean}" > "${diff_file}" || true + + if [ ! -s "${report1_clean}" ]; then + echo "Pipe Report ASLR test [Failed - no samples captured]" + err=1 + elif [ -s "${diff_file}" ]; then + echo "Pipe Report ASLR test [Failed - reports differ]" + echo "Showing first 20 lines of diff:" + head -n 20 "${diff_file}" + err=1 + else + echo "Pipe Report ASLR test [Success]" + fi +} + +test_pipe_out_report_aslr() { + echo "Test pipe output mode perf report consistency" + local data + data=$(mktemp "${temp_dir}/perf.data.pipe_out_report.XXXXXX") + local data_clean + data_clean=$(mktemp "${temp_dir}/perf.data.clean.XXXXXX") + + perf record -e task-clock:u -o "${data}" ${prog} + perf inject -b -i "${data}" -o "${data_clean}" + + local report1="${temp_dir}/report1_pipe_out" + local report2="${temp_dir}/report2_pipe_out" + local report1_clean="${temp_dir}/report1_pipe_out.clean" + local report2_clean="${temp_dir}/report2_pipe_out.clean" + local diff_file="${temp_dir}/diff_pipe_out" + + perf report -i "${data_clean}" --stdio > "${report1}" + perf inject -b --aslr -i "${data}" -o - | perf report -i - --stdio > "${report2}" + + # Strip headers and compare lines with percentages + grep '%' "${report1}" | grep -v '^#' | \ + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' | sort > "${report1_clean}" || true + grep '%' "${report2}" | grep -v '^#' | \ + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' | sort > "${report2_clean}" || true + + diff -u -w "${report1_clean}" "${report2_clean}" > "${diff_file}" || true + + if [ ! -s "${report1_clean}" ]; then + echo "Pipe Output Report ASLR test [Failed - no samples captured]" + err=1 + elif [ -s "${diff_file}" ]; then + echo "Pipe Output Report ASLR test [Failed - reports differ]" + echo "Showing first 20 lines of diff:" + head -n 20 "${diff_file}" + err=1 + else + echo "Pipe Output Report ASLR test [Success]" + fi +} + +test_dropped_samples() { + echo "Test dropped samples (phys-data)" + local data + data=$(mktemp "${temp_dir}/perf.data.dropped.XXXXXX") + local data2 + data2=$(mktemp "${temp_dir}/perf.data2.dropped.XXXXXX") + + # Check if --phys-data is supported by recording a short run + if ! perf record -e task-clock:u --phys-data -o "${data}" -- sleep 0.1 > /dev/null 2>&1; then + echo "Skipping dropped samples test as --phys-data is not supported" + return + fi + + perf record -e task-clock:u --phys-data -o "${data}" ${prog} + perf inject --aslr -i "${data}" -o "${data2}" + + # Verify that the original file actually contained samples! + orig_samples=$(perf script -i "${data}" | wc -l) + if [ "$orig_samples" -eq 0 ]; then + echo "Dropped samples test [Failed - no samples in original file]" + err=1 + else + # Verify that samples are dropped. + samples_count=$(perf script -i "${data2}" | wc -l) + + if [ "$samples_count" -gt 0 ]; then + echo "Dropped samples test [Failed - samples were not dropped]" + err=1 + else + echo "Dropped samples test [Success]" + fi + fi +} + +test_kernel_aslr() { + echo "Test kernel ASLR remapping" + local kdata + kdata=$(mktemp "${temp_dir}/perf.data.kernel.XXXXXX") + local kdata2 + kdata2=$(mktemp "${temp_dir}/perf.data2.kernel.XXXXXX") + local log_file + log_file=$(mktemp "${temp_dir}/kernel_record.log.XXXXXX") + + # Try to record kernel samples + if ! perf record -e task-clock:k -o "${kdata}" ${kprog} > "${log_file}" 2>&1; then + echo "Skipping kernel ASLR test as recording failed (maybe no permissions)" + return + fi + + # Check for warning about kernel map restriction + if grep -q "Couldn't record kernel reference relocation symbol" "${log_file}"; then + echo "Skipping kernel ASLR test as kernel map could not be recorded (permissions restricted)" + return + fi + + perf inject -v --aslr -i "${kdata}" -o "${kdata2}" + + # Check if kernel addresses are remapped. + # Find the field that ends with :k: (the event name) and take the next field! + orig_addr=$(perf script -i "${kdata}" | awk ' + BEGIN { found=0 } + { + for (i=1; i "${log_file}" 2>&1; then + echo "Skipping kernel report test as recording failed (maybe no permissions)" + return + fi + + # Check for warning about kernel map restriction + if grep -q "Couldn't record kernel reference relocation symbol" "${log_file}"; then + echo "Skipping kernel report test as kernel map could not be recorded (permissions restricted)" + return + fi + + # Use -b to inject build-ids and force ordered events processing in both + perf inject -b -i "${kdata}" -o "${data_clean}" + perf inject -v -b --aslr -i "${kdata}" -o "${kdata2}" + + local report1="${temp_dir}/report_kernel1" + local report2="${temp_dir}/report_kernel2" + local report1_clean="${temp_dir}/report_kernel1.clean" + local report2_clean="${temp_dir}/report_kernel2.clean" + + perf report -i "${data_clean}" --stdio > "${report1}" + perf report -i "${kdata2}" --stdio > "${report2}" + + # Strip headers and compare lines with percentages + grep '%' "${report1}" | grep -v '^#' > "${report1_clean}" || true + grep '%' "${report2}" | grep -v '^#' > "${report2_clean}" || true + + # Normalize kernel DSOs and addresses in clean reports + # This allows kernel modules to be either a module or kernel.kallsyms + local report1_norm="${temp_dir}/report_kernel1.norm" + local report2_norm="${temp_dir}/report_kernel2.norm" + local diff_file="${temp_dir}/diff_kernel" + + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' "${report1_clean}" | \ + awk '{gsub(/\[[a-zA-Z0-9_.-]{2,}\](\.[a-zA-Z0-9_]+)?/, "[kernel]", $0); print}' | \ + sort > "${report1_norm}" || true + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' "${report2_clean}" | \ + awk '{gsub(/\[[a-zA-Z0-9_.-]{2,}\](\.[a-zA-Z0-9_]+)?/, "[kernel]", $0); print}' | \ + sort > "${report2_norm}" || true + + diff -u -w "${report1_norm}" "${report2_norm}" > "${diff_file}" || true + + if [ ! -s "${report1_norm}" ]; then + echo "Kernel Report ASLR test [Failed - no samples captured]" + err=1 + elif [ -s "${diff_file}" ]; then + echo "Kernel Report ASLR test [Failed - reports differ]" + echo "Showing first 20 lines of diff:" + head -n 20 "${diff_file}" + err=1 + else + echo "Kernel Report ASLR test [Success]" + fi +} + +test_regs_stripping() { + echo "Test user register stripping" + local rdata="${temp_dir}/perf.data.regs" + local rdata2="${temp_dir}/perf.data.regs.injected" + local rdata_clean="${temp_dir}/perf.data.regs.clean" + + if ! perf record -e cycles:u --user-regs -o "${rdata}" ${prog} > /dev/null 2>&1; then + echo "Skipping user registers test as recording failed (unsupported flag/platform)" + return + fi + + perf inject -b -i "${rdata}" -o "${rdata_clean}" + perf inject -v -b --aslr -i "${rdata}" -o "${rdata2}" + + local report1="${temp_dir}/report_regs1" + local report2="${temp_dir}/report_regs2" + local report1_clean="${temp_dir}/report_regs1.clean" + local report2_clean="${temp_dir}/report_regs2.clean" + local diff_file="${temp_dir}/diff_regs" + + perf report -i "${rdata_clean}" --stdio > "${report1}" 2>/dev/null || true + perf report -i "${rdata2}" --stdio > "${report2}" 2>/dev/null || true + + grep '%' "${report1}" | grep -v '^#' | \ + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' | \ + sort > "${report1_clean}" || true + grep '%' "${report2}" | grep -v '^#' | \ + grep -v -E '0x[0-9a-f]{8,}|0000000000000000' | \ + sort > "${report2_clean}" || true + + diff -u -w "${report1_clean}" "${report2_clean}" > "${diff_file}" || true + + if [ ! -s "${report1_clean}" ]; then + echo "User registers stripping test [Failed - profile trace starved/empty]" + err=1 + return + elif [ -s "${diff_file}" ]; then + echo "User registers stripping test [Failed - report parsing differs]" + echo "Showing first 20 lines of diff:" + head -n 20 "${diff_file}" + err=1 + return + fi + + local script_dump="${temp_dir}/script_regs_dump" + perf script -D -i "${rdata2}" > "${script_dump}" 2>/dev/null || true + if grep -q "user regs:" "${script_dump}"; then + echo "User registers stripping test [Failed - register dumps still present]" + err=1 + else + echo "User registers stripping test [Success]" + fi +} + +test_basic_aslr +test_pipe_aslr +test_callchain_aslr +test_report_aslr +test_pipe_report_aslr +test_pipe_out_report_aslr +test_dropped_samples +case "$(uname -m)" in + aarch64*|arm*) + echo "Skipping kernel ASLR tests on ARM" + ;; + *) + test_kernel_aslr + test_kernel_report_aslr + ;; +esac + +test_regs_stripping + +cleanup ${err} +exit $err From cd355f6dc70503191249c5147e2f2e8f3c8838bd Mon Sep 17 00:00:00 2001 From: Aaron Tomlin Date: Fri, 12 Jun 2026 18:56:10 -0400 Subject: [PATCH 316/343] perf trace: Fix noise and signed formatting of __probe_ip in bare dynamic probes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a dynamic probe is created without explicitly requested arguments via perf probe --add, the Ftrace subsystem automatically appends "__probe_ip" to the tracepoint format to record the instruction pointer. Currently, perf trace prints this implicit field by default. Furthermore, because the formatting logic defaults to a standard signed integer representation, the kernel space memory address is erroneously displayed as a meaningless negative integer. ❯ sudo ./perf trace --event probe:proc_sys_open --max-events 1 0.000 ps/1316543 probe:proc_sys_open(__probe_ip: -1406056956) This patch addresses the user experience by combining two refinements: 1. "__probe_ip" is now hidden from the standard output, as its presence adds no contextual value for a bare probe. 2. If the user explicitly requests verbose output (--verbose), "__probe_ip" is intercepted and properly formatted as a hexadecimal kernel address, restoring its utility for debugging inline function hits. ❯ sudo ./perf trace --event probe:proc_sys_open --max-events 1 0.000 ps/1314074 probe:proc_sys_open() ❯ sudo ./perf trace --verbose --event probe:proc_sys_open --max-events 1 Using CPUID GenuineIntel-6-8E-C mmap size 528384B 0.000 ps/1314366 probe:proc_sys_open(__probe_ip: 0xffffffffac314604) Reviewed-by: James Clark Signed-off-by: Aaron Tomlin Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Daniel Vacek Cc: Howard Chu Cc: Ian Rogers Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Sean Ashe Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 377f0a18b00e..a8492da23a9c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3261,6 +3261,27 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct perf_sample * if (val == 0 && !trace->show_zeros && !arg->show_zero && arg->strtoul != STUL_BTF_TYPE) continue; + /* + * __probe_ip is implicitly added to bare dynamic probes. + * Suppress it by default to avoid cluttering the output. + * If verbose mode is enabled, ensure it is formatted as a + * hexadecimal memory address rather than a signed integer. + */ + if (!strcmp(field->name, "__probe_ip")) { + if (!verbose) + continue; + + printed += scnprintf(bf + printed, size - printed, + "%s", printed ? ", " : ""); + if (trace->show_arg_names) + printed += scnprintf(bf + printed, size - printed, + "%s: ", field->name); + + printed += scnprintf(bf + printed, size - printed, "%#016llx", + (unsigned long long)val); + continue; + } + printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : ""); if (trace->show_arg_names) From 1221e50b4aa60b98aade37eb4e536d4a2cb93e75 Mon Sep 17 00:00:00 2001 From: Thomas Falcon Date: Fri, 12 Jun 2026 14:28:47 -0500 Subject: [PATCH 317/343] perf tools: Document recent additions to the perf.data file header Add documentation for recently added HEADER_E_MACHINE and HEADER_CLN_SIZE data to the perf.data file. Also fix a typo at the end of the header section. Reviewed-by: Ian Rogers Signed-off-by: Thomas Falcon Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Dapeng Mi Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- .../perf/Documentation/perf.data-file-format.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt index 0e4d0ecc9e12..b90cba9168f8 100644 --- a/tools/perf/Documentation/perf.data-file-format.txt +++ b/tools/perf/Documentation/perf.data-file-format.txt @@ -464,7 +464,21 @@ struct cpu_domain_info { struct domain_info domains[]; }; - other bits are reserved and should ignored for now + HEADER_E_MACHINE = 33, + +ELF machine and flags data. e_machine is expanded from 16 to 32 bits +for alignment. Format: + + u32 e_machine; + u32 e_flags; + + HEADER_CLN_SIZE = 34, + +The size of the cacheline in bytes. Format: + + unsigned int cln_size; + + other bits are reserved and should be ignored for now HEADER_FEAT_BITS = 256, Attributes From 081b387c7397498c583b1ba7c2fdaf4c6da6b538 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 19:28:43 -0300 Subject: [PATCH 318/343] perf symbols: Fix bswap copy-paste error for 32-bit ELF p_filesz filename__read_build_id() byte-swaps 32-bit ELF program headers on cross-endian files, but line 178 passes p_offset to bswap_32() instead of p_filesz: hdrs.phdr32[i].p_filesz = bswap_32(hdrs.phdr32[i].p_offset); This clobbers p_filesz with the already-swapped p_offset value. The 64-bit path on line 182 is correct and swaps p_filesz from p_filesz. The consequence is that the PT_NOTE segment read uses the wrong size, which can cause either a short read (missing the build-id) or an oversized read (reading past the segment into adjacent data). Fix by swapping the correct field. Reported-by: sashiko-bot Fixes: fef8f648bb47726d ("perf symbol: Fix use-after-free in filename__read_build_id") Reviewed-by: Ian Rogers Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-minimal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 091071d06416..f4b0a711a62c 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c @@ -175,7 +175,7 @@ int filename__read_build_id(const char *filename, struct build_id *bid) if (elf32) { hdrs.phdr32[i].p_type = bswap_32(hdrs.phdr32[i].p_type); hdrs.phdr32[i].p_offset = bswap_32(hdrs.phdr32[i].p_offset); - hdrs.phdr32[i].p_filesz = bswap_32(hdrs.phdr32[i].p_offset); + hdrs.phdr32[i].p_filesz = bswap_32(hdrs.phdr32[i].p_filesz); } else { hdrs.phdr64[i].p_type = bswap_32(hdrs.phdr64[i].p_type); hdrs.phdr64[i].p_offset = bswap_64(hdrs.phdr64[i].p_offset); From 2a3716544359d4312c81b0fa909a13301186da17 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 19:29:34 -0300 Subject: [PATCH 319/343] perf symbols: Validate p_filesz before use in filename__read_build_id() filename__read_build_id() stores ELF p_filesz in a ssize_t variable. A crafted 32-bit ELF with p_filesz = 0xFFFFFFFF produces ssize_t value -1. The comparison `p_filesz > buf_size` evaluates false because signed -1 is less than any non-negative buf_size, so the realloc is skipped and buf remains NULL. The subsequent read(fd, NULL, -1) returns -1, which equals p_filesz, passing the error check. read_build_id() then dereferences the NULL buffer. Add an explicit check for p_filesz <= 0 before using the value, catching both zero-length and sign-wrapped negative sizes from crafted ELF files. Reported-by: sashiko-bot Fixes: ba0b7081f7a521d7 ("perf symbol-minimal: Fix ehdr reading in filename__read_build_id") Reviewed-by: Ian Rogers Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-minimal.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index f4b0a711a62c..0a71d1463952 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c @@ -186,6 +186,9 @@ int filename__read_build_id(const char *filename, struct build_id *bid) continue; p_filesz = elf32 ? hdrs.phdr32[i].p_filesz : hdrs.phdr64[i].p_filesz; + /* ssize_t can go negative with crafted ELF p_filesz values */ + if (p_filesz <= 0) + continue; if (p_filesz > buf_size) { void *tmp; From 063c647b24f640657d6d9e2e90d620ea3ee19ae6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 19:32:22 -0300 Subject: [PATCH 320/343] perf symbols: Break infinite loop on zero-filled notes in sysfs__read_build_id() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sysfs__read_build_id() iterates ELF note headers from sysfs files in a while(1) loop. If the file contains a zero-filled note header (both n_namesz and n_descsz are 0), the code computes n = namesz + descsz = 0 and calls read(fd, bf, 0). read() with count 0 returns 0, which matches the expected (ssize_t)n value, so the error check passes and the loop repeats — reading the same zero bytes and spinning forever. This can happen with corrupted or zero-padded sysfs pseudo-files. Add a check for n == 0 before the read, since no valid ELF note has both name and description of zero length. Reported-by: sashiko-bot Fixes: f1617b40596cb341 ("perf symbols: Record the build_ids of kernel modules too") Reviewed-by: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol-elf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index c301c298ded9..39562bdec8b9 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -995,6 +995,9 @@ int sysfs__read_build_id(const char *filename, struct build_id *bid) } else { n = namesz + descsz; } + /* no valid note has both namesz and descsz zero */ + if (n == 0) + break; if (read(fd, bf, n) != (ssize_t)n) break; } From f973e52a99776fcc473488984828d1fce56d5382 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 19:33:48 -0300 Subject: [PATCH 321/343] perf dso: Fix heap overflow in dso__get_filename() on decompressed path dso__get_filename() allocates name with malloc(PATH_MAX), but the dso__filename_with_chroot() path replaces name with an asprintf'd exact-size string (e.g. 8 bytes for "/a/b.ko"). When the DSO needs decompression, dso__decompress_kmodule_path() writes the temp path ("/tmp/perf-kmod-XXXXXX", 22 bytes) into newpath, and strcpy(name, newpath) overflows the smaller allocation. Replace the strcpy with strdup(newpath) + free(name) so the buffer is always correctly sized for its content. Reported-by: sashiko-bot Fixes: 1d6b3c9ba756a513 ("perf tools: Decompress kernel module when reading DSO data") Reviewed-by: Ian Rogers Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 5d0179758738..511921bd901d 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -603,8 +603,15 @@ static char *dso__get_filename(struct dso *dso, const char *root_dir, /* empty pathname means file wasn't actually compressed */ if (newpath[0] != '\0') { + char *tmp = strdup(newpath); + + if (!tmp) { + unlink(newpath); + goto out; + } + free(name); + name = tmp; *decomp = true; - strcpy(name, newpath); } } return name; From d2c6069d68ee9d53b05fe38bc2049cc4286fbb16 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 20:16:02 -0300 Subject: [PATCH 322/343] perf dso: Set error code when open() fails on uncompressed fallback path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit filename__decompress() has an early return for files that are not actually compressed, where it calls open() directly. When open() fails, the function returns -1 but never sets *err. The caller chain (decompress_kmodule → dso__decompress_kmodule_path → dso__get_filename) then reads *dso__load_errno(dso) to set errno, but that field was never populated, so errno gets a stale or zero value. With errno=0, __open_dso() computes fd = -errno = 0, which is non- negative, so callers treat fd 0 (stdin) as a valid DSO file descriptor. Set *err = errno when open() fails on the uncompressed path, matching the error handling on the compressed path at line 354. Reported-by: sashiko-bot Fixes: 8b42b7e5e8b5692b ("perf tools: Add is_compressed callback to compressions array") Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 511921bd901d..1a2fc6d18da7 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -344,9 +344,12 @@ int filename__decompress(const char *name, char *pathname, * descriptor to the uncompressed file. */ if (!compressions[comp].is_compressed(name)) { + fd = open(name, O_RDONLY | O_CLOEXEC); + if (fd < 0) + *err = errno; if (pathname && len > 0) pathname[0] = '\0'; - return open(name, O_RDONLY | O_CLOEXEC); + return fd; } fd = mkostemp(tmpbuf, O_CLOEXEC); From 7b0df6f4d498b1608afccfd6dffb264e6da91693 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 20:34:38 -0300 Subject: [PATCH 323/343] perf tools: Use snprintf() for root_dir path construction get_kernel_version() in machine.c and dso__load_guest_kernel_sym() in symbol.c use sprintf() to construct paths by prepending root_dir to "/proc/version" and "/proc/kallsyms" respectively. Both write into PATH_MAX stack buffers, but root_dir comes from --guestmount or KVM configuration and is not length-checked. A root_dir at or near PATH_MAX causes a stack buffer overflow. Switch to snprintf() with sizeof(path) to prevent overflow. Reported-by: sashiko-bot Fixes: a1645ce12adb6c9c ("perf: 'perf kvm' tool for monitoring guest performance from host") Cc: Zhang Yanmin Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 2 +- tools/perf/util/symbol.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 1ea06fde14e0..31715366e29f 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1336,7 +1336,7 @@ static char *get_kernel_version(const char *root_dir) char *name, *tmp; const char *prefix = "Linux version "; - sprintf(version, "%s/proc/version", root_dir); + snprintf(version, sizeof(version), "%s/proc/version", root_dir); file = fopen(version, "r"); if (!file) return NULL; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 2cc911af8c81..cd379ced19e5 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -2283,7 +2283,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map) if (!kallsyms_filename) return -1; } else { - sprintf(path, "%s/proc/kallsyms", machine->root_dir); + snprintf(path, sizeof(path), "%s/proc/kallsyms", machine->root_dir); kallsyms_filename = path; } From cfafef390ca9c753b34c7e97b5abee4cab0ce270 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 20:40:34 -0300 Subject: [PATCH 324/343] perf hwmon: Fix fd check to accept fd 0 in hwmon_pmu__describe_items() hwmon_pmu__describe_items() checks 'if (fd > 0)' after openat(), which incorrectly rejects fd 0. While fd 0 is normally stdin, if stdin has been closed (common in daemon/service contexts), the kernel reuses fd 0 for the next open. With fd > 0, the sysfs file is not read and the fd is leaked. Change to 'if (fd >= 0)' to match the standard openat() error check. Reported-by: sashiko-bot Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") Reviewed-by: Ian Rogers Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hwmon_pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c index efd3067a2e59..ed544dca70c3 100644 --- a/tools/perf/util/hwmon_pmu.c +++ b/tools/perf/util/hwmon_pmu.c @@ -435,7 +435,7 @@ static size_t hwmon_pmu__describe_items(struct hwmon_pmu *hwm, char *out_buf, si hwmon_item_strs[bit], is_alarm ? "_alarm" : ""); fd = openat(dir, buf, O_RDONLY); - if (fd > 0) { + if (fd >= 0) { ssize_t read_len = read(fd, buf, sizeof(buf) - 1); while (read_len > 0 && buf[read_len - 1] == '\n') From 500f5dd0a8b6f7bd174102587c7dff5a7d2fecbf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 21:00:11 -0300 Subject: [PATCH 325/343] perf sched: Replace (void*)1 sentinel with proper runtime allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit map__findnew_thread() marks color-pid threads by storing (void*)1 as the thread private data via thread__set_priv(). This sentinel value causes two problems: 1. thread__get_runtime() returns (void*)1 as a struct thread_runtime pointer. Any field access (e.g. tr->shortname) dereferences address 1, which is an unmapped page — immediate segfault. 2. cmd_sched() registers free() as the thread priv destructor, so thread cleanup calls free((void*)1) — undefined behavior that corrupts the heap on many allocators. Fix by adding a 'color' flag to struct thread_runtime and allocating a real runtime struct for color-pid threads. thread__has_color() now checks the flag instead of relying on priv being non-NULL. Reported-by: sashiko-bot Fixes: 58a606149c60d5da ("perf sched: Avoid union type punning undefined behavior") Reviewed-by: Ian Rogers Cc: Ian Rogers Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 5f16caebd964..7fd63a9db457 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -274,6 +274,7 @@ struct thread_runtime { u64 migrations; int prio; + bool color; }; /* per event run time data */ @@ -1589,22 +1590,32 @@ static int process_sched_wakeup_ignore(const struct perf_tool *tool __maybe_unus static bool thread__has_color(struct thread *thread) { - return thread__priv(thread) != NULL; + struct thread_runtime *tr = thread__priv(thread); + + return tr != NULL && tr->color; } static struct thread* map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid, pid_t tid) { struct thread *thread = machine__findnew_thread(machine, pid, tid); - bool color = false; - if (!sched->map.color_pids || !thread || thread__priv(thread)) + if (!sched->map.color_pids || !thread) return thread; - if (thread_map__has(sched->map.color_pids, tid)) - color = true; + /* + * Always check the color-pids map, even if thread__priv() is + * already set. COMM events processed before the first sched_switch + * allocate a thread_runtime via thread__get_runtime(), so priv is + * non-NULL before we ever get here. Skipping the check on non-NULL + * priv would prevent those threads from being colored. + */ + if (thread_map__has(sched->map.color_pids, tid)) { + struct thread_runtime *tr = thread__get_runtime(thread); - thread__set_priv(thread, color ? ((void*)1) : NULL); + if (tr) + tr->color = true; + } return thread; } From 10b3c3d63ecc17c6acb855bac5f40367f1115765 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 21:01:15 -0300 Subject: [PATCH 326/343] perf bpf: Validate func_info_rec_size and sub_id in synthesize_bpf_prog_name() synthesize_bpf_prog_name() computes a pointer into the func_info array using sub_id * info->func_info_rec_size without validating either value. Both come from perf.data and are untrusted: - A func_info_rec_size smaller than sizeof(struct bpf_func_info) means the finfo pointer would reference a truncated entry, reading past it into adjacent data. - A sub_id >= nr_func_info computes an offset past the func_info buffer, causing an out-of-bounds read. Add bounds checks for both values before computing the pointer offset. When validation fails, fall through to the non-BTF name path instead of reading garbage. Reported-by: sashiko-bot Fixes: 7b612e291a5affb1 ("perf tools: Synthesize PERF_RECORD_* for loaded BPF programs") Cc: Song Liu Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-event.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index c4594969d767..fe6fbca508c5 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -143,7 +143,9 @@ static int synthesize_bpf_prog_name(char *buf, int size, name_len = scnprintf(buf, size, "bpf_prog_"); name_len += snprintf_hex(buf + name_len, size - name_len, prog_tags[sub_id], BPF_TAG_SIZE); - if (btf) { + if (btf && + info->func_info_rec_size >= sizeof(*finfo) && + sub_id < info->nr_func_info) { finfo = func_infos + sub_id * info->func_info_rec_size; t = btf__type_by_id(btf, finfo->type_id); if (t) From 2d6ea0875093da9033fcb62c09a9e2f1de49fe91 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 21:02:25 -0300 Subject: [PATCH 327/343] perf bpf: Reject oversized BPF metadata events that truncate header.size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bpf_metadata_alloc() computes event_size from the number of BPF metadata variables and stores it in header.size, which is __u16. With 204 or more .rodata variables prefixed "bpf_metadata_", event_size exceeds 65535 and silently truncates. The truncated header.size causes synthesize_perf_record_bpf_metadata() to allocate a buffer sized by the truncated value, then memcpy the full event data into it — a heap buffer overflow. Add a check that event_size fits in __u16 before proceeding. BPF programs with that many metadata variables are exotic enough that silently dropping the metadata is acceptable. Reported-by: sashiko-bot Fixes: ab38e84ba9a80581 ("perf record: collect BPF metadata from existing BPF programs") Reviewed-by: Ian Rogers Cc: Blake Jones Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-event.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index fe6fbca508c5..57d53ba84835 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -369,6 +369,15 @@ static struct bpf_metadata *bpf_metadata_alloc(__u32 nr_prog_tags, event_size = sizeof(metadata->event->bpf_metadata) + nr_variables * sizeof(metadata->event->bpf_metadata.entries[0]); + /* + * header.size is __u16. synthesize_perf_record_bpf_metadata() + * adds machine->id_hdr_size (up to ~64 bytes) after this, so + * leave headroom to prevent the final size from wrapping. + */ + if (event_size > UINT16_MAX - 256) { + bpf_metadata_free(metadata); + return NULL; + } metadata->event = zalloc(event_size); if (!metadata->event) { bpf_metadata_free(metadata); From 033e85edfbf271f92979d2a39aeaf40f8472a795 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 21:03:16 -0300 Subject: [PATCH 328/343] perf bpf: Bounds-check array offsets in bpil_offs_to_addr() bpil_offs_to_addr() converts offsets stored in perf.data's bpf_prog_info_linear structure into heap pointers by adding the offset to the data allocation base. The offsets come from untrusted file input and are not validated against data_len. If an offset exceeds data_len, the computed address points outside the allocated data buffer. Callers like synthesize_bpf_prog_name() then dereference prog_tags[sub_id] or func_info pointers, reading arbitrary heap memory. Add a bounds check: when an offset exceeds data_len, zero the field and skip the conversion. This prevents out-of-bounds pointer construction from crafted perf.data files. Reported-by: sashiko-bot Fixes: 6ac22d036f86c4e2 ("perf bpf: Pull in bpf_program__get_prog_info_linear()") Cc: Dave Marchevsky Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-utils.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/perf/util/bpf-utils.c b/tools/perf/util/bpf-utils.c index d6d2c9c190f7..69148197b1ef 100644 --- a/tools/perf/util/bpf-utils.c +++ b/tools/perf/util/bpf-utils.c @@ -264,12 +264,28 @@ void bpil_offs_to_addr(struct perf_bpil *info_linear) for (i = PERF_BPIL_FIRST_ARRAY; i < PERF_BPIL_LAST_ARRAY; ++i) { const struct bpil_array_desc *desc = &bpil_array_desc[i]; __u64 addr, offs; + __u32 count, size; if ((info_linear->arrays & (1UL << i)) == 0) continue; offs = bpf_prog_info_read_offset_u64(&info_linear->info, desc->array_offset); + count = bpf_prog_info_read_offset_u32(&info_linear->info, + desc->count_offset); + size = bpf_prog_info_read_offset_u32(&info_linear->info, + desc->size_offset); + /* offset and extent from perf.data are untrusted — keep within data[] */ + if (offs >= info_linear->data_len || + (u64)count * size > info_linear->data_len - offs) { + bpf_prog_info_set_offset_u64(&info_linear->info, + desc->array_offset, 0); + bpf_prog_info_set_offset_u32(&info_linear->info, + desc->count_offset, 0); + /* clear the bit so bpil_addr_to_offs() won't reverse a zeroed address */ + info_linear->arrays &= ~(1UL << i); + continue; + } addr = offs + ptr_to_u64(info_linear->data); bpf_prog_info_set_offset_u64(&info_linear->info, desc->array_offset, addr); From 4a7500d772fe59653053db22ca83c9e2232b22e1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 21:23:35 -0300 Subject: [PATCH 329/343] perf c2c: Free format list entries when releasing c2c hist entries c2c_hists__init() calls hpp_list__parse() which allocates and registers format entries on hists->list. When c2c_he_free() destroys a c2c hist entry, it deletes the histogram entries and frees the hists container but never unregisters the format list entries, leaking them. Call perf_hpp__reset_output_field() before freeing the hists to properly unregister and free all format entries. Fixes: f485e33c4543ac31 ("perf c2c report: Add cacheline hists processing") Reported-by: sashiko-bot Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index e205f58b2f3d..07c7e8fb315e 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -185,6 +185,7 @@ static void c2c_he_free(void *he) c2c_he = container_of(he, struct c2c_hist_entry, he); if (c2c_he->hists) { hists__delete_entries(&c2c_he->hists->hists); + perf_hpp__reset_output_field(&c2c_he->hists->list); zfree(&c2c_he->hists); } From 542e88a4c6f7b6edd1326ce767d4cb3c2ea9d61d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2026 22:45:08 -0300 Subject: [PATCH 330/343] perf cs-etm: Reject CPU IDs that would overflow signed comparison metadata[j][CS_ETM_CPU] is a u64 from perf.data, but the comparison with max_cpu casts it to (int). A crafted value like 0xFFFFFFFF becomes -1 after the cast, which compares less than max_cpu (0), so the queue array is never sized to accommodate it. When the value is later passed to cs_etm__get_queue(), it indexes queue_array with the original large value, causing an out-of-bounds access. Validate that CS_ETM_CPU fits in an int before using it in the signed comparison. Fixes: 57880a7966be510c ("perf: cs-etm: Allocate queues for all CPUs") Reported-by: sashiko-bot Cc: James Clark Cc: Adrian Hunter Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cs-etm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 5e92359f51a7..0927b0b9c06b 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -6,6 +6,7 @@ * Author: Mathieu Poirier */ +#include #include #include #include @@ -3468,7 +3469,13 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event, goto err_free_metadata; } - if ((int) metadata[j][CS_ETM_CPU] > max_cpu) + /* CPU id comes from perf.data and must fit max_cpu + 1 without overflow */ + if (metadata[j][CS_ETM_CPU] >= INT_MAX) { + err = -EINVAL; + goto err_free_metadata; + } + + if ((int)metadata[j][CS_ETM_CPU] > max_cpu) max_cpu = metadata[j][CS_ETM_CPU]; } From e22a4228546f7220d0425630abf703fd2ef7c600 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jun 2026 16:37:09 -0300 Subject: [PATCH 331/343] perf evsel: Add no-libtraceevent stubs for evsel__field() and evsel__common_field() When building without libtraceevent (NO_LIBTRACEEVENT=1), evsel__field() and evsel__common_field() are declared but never defined, causing link errors in any code path that references them. Add inline stubs that return NULL when HAVE_LIBTRACEEVENT is not defined, matching the pattern used by other evsel accessor functions. Cc: Aaron Tomlin Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 8009be22cc3f..b959d4797b14 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -397,8 +397,22 @@ struct tep_format_field; u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap); +#ifdef HAVE_LIBTRACEEVENT struct tep_format_field *evsel__field(struct evsel *evsel, const char *name); struct tep_format_field *evsel__common_field(struct evsel *evsel, const char *name); +#else +static inline struct tep_format_field * +evsel__field(struct evsel *evsel __maybe_unused, const char *name __maybe_unused) +{ + return NULL; +} + +static inline struct tep_format_field * +evsel__common_field(struct evsel *evsel __maybe_unused, const char *name __maybe_unused) +{ + return NULL; +} +#endif bool __evsel__match(const struct evsel *evsel, u32 type, u64 config); From 9212e395c64d80f7b6af314ff6dfc4b526571493 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 16 Jun 2026 16:35:43 -0300 Subject: [PATCH 332/343] perf evsel: Add lazy-initialized probe type detection helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several places in perf need to check whether an evsel is a kprobe or uprobe, which requires looking up the PMU by name via evsel__find_pmu(). This lookup walks the PMU list each time, which is wasteful when the same evsel is checked repeatedly. Add evsel__is_kprobe(), evsel__is_uprobe(), and evsel__is_probe() that resolve the probe type on first call via evsel__pmu_name() and cache the result in a 3-bit field (probe_type) in struct evsel. The field fits in existing padding after the bool fields, so struct size does not grow. The enum uses PROBE__UNKNOWN (0) as the uninitialized sentinel — explicitly set in evsel__init() — so the lookup happens on first use. PROBE__NOPE (1) caches "not a probe" to avoid repeated negative lookups. PMU-based probes (kprobe/uprobe PMU) are detected by PMU name. Ftrace-based dynamic probes (created via tracefs, reported as PMU "tracepoint") are detected by the __probe_ip field that the kernel adds to all dynamic probe formats. This covers kprobes, uprobes, and fprobes regardless of their group/system name. Cc: Aaron Tomlin Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 53 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/evsel.h | 5 ++++ 2 files changed, 58 insertions(+) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 05fa0010c858..ea9fa04429f0 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -254,6 +254,58 @@ const char *evsel__pmu_name(const struct evsel *evsel) return event_type(evsel->core.attr.type); } +enum evsel_probe_type { + PROBE__UNKNOWN = 0, + PROBE__NOPE = 1, + PROBE__KPROBE = 2, + PROBE__UPROBE = 3, + /* + * Ftrace-based dynamic probes (kprobes/uprobes/fprobes created via + * tracefs) report PMU "tracepoint", not "kprobe"/"uprobe". Detect + * them by the __probe_ip field that the kernel adds to all dynamic + * probe formats. + */ + PROBE__FTRACE = 4, +}; + +static void evsel__resolve_probe_type(struct evsel *evsel) +{ + const char *name = evsel__pmu_name(evsel); + + if (!strcmp(name, "kprobe")) + evsel->probe_type = PROBE__KPROBE; + else if (!strcmp(name, "uprobe")) + evsel->probe_type = PROBE__UPROBE; + else if (!strcmp(name, "tracepoint") && evsel__field(evsel, "__probe_ip")) + evsel->probe_type = PROBE__FTRACE; + else + evsel->probe_type = PROBE__NOPE; +} + +bool evsel__is_probe(struct evsel *evsel) +{ + if (evsel->probe_type == PROBE__UNKNOWN) + evsel__resolve_probe_type(evsel); + + return evsel->probe_type > PROBE__NOPE; +} + +bool evsel__is_kprobe(struct evsel *evsel) +{ + if (evsel->probe_type == PROBE__UNKNOWN) + evsel__resolve_probe_type(evsel); + + return evsel->probe_type == PROBE__KPROBE; +} + +bool evsel__is_uprobe(struct evsel *evsel) +{ + if (evsel->probe_type == PROBE__UNKNOWN) + evsel__resolve_probe_type(evsel); + + return evsel->probe_type == PROBE__UPROBE; +} + #define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y)) int __evsel__sample_size(u64 sample_type) @@ -413,6 +465,7 @@ void evsel__init(struct evsel *evsel, evsel->supported = true; evsel->alternate_hw_config = PERF_COUNT_HW_MAX; evsel->script_output_type = -1; // FIXME: OUTPUT_TYPE_UNSET, see builtin-script.c + evsel->probe_type = PROBE__UNKNOWN; } struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index b959d4797b14..163fc2b6a7ea 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -126,6 +126,7 @@ struct evsel { bool needs_uniquify; bool fallenback_eacces; bool fallenback_eopnotsupp; + u8 probe_type:3; struct hashmap *per_pkg_mask; int err; int script_output_type; @@ -259,6 +260,10 @@ struct perf_pmu *evsel__find_pmu(const struct evsel *evsel); const char *evsel__pmu_name(const struct evsel *evsel); bool evsel__is_aux_event(const struct evsel *evsel); +bool evsel__is_probe(struct evsel *evsel); +bool evsel__is_kprobe(struct evsel *evsel); +bool evsel__is_uprobe(struct evsel *evsel); + struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx); static inline struct evsel *evsel__new(struct perf_event_attr *attr) From d669529868b355e1f10ff869539dc995cd25db3f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Jun 2026 22:17:41 -0300 Subject: [PATCH 333/343] perf trace: Guard __probe_ip suppression with evsel__is_probe() trace__fprintf_tp_fields() compares every field name against "__probe_ip" for all tracepoint events, but this field is only implicitly added by the Ftrace subsystem to bare dynamic probes. Add an evsel__is_probe() check before the strcmp so the string comparison is skipped entirely for non-probe events. Reviewed-by: Aaron Tomlin Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index a8492da23a9c..57f3f14c5d43 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3267,7 +3267,7 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct perf_sample * * If verbose mode is enabled, ensure it is formatted as a * hexadecimal memory address rather than a signed integer. */ - if (!strcmp(field->name, "__probe_ip")) { + if (evsel__is_probe(evsel) && !strcmp(field->name, "__probe_ip")) { if (!verbose) continue; From 8a4506595857356fcef9f7aad3506593e9fabbbc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Jun 2026 13:46:29 -0300 Subject: [PATCH 334/343] perf machine: Propagate machine__init() error to callers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit machine__init() always returns 0 even when memory allocation fails, because commit 81f981d7ec43ed93 ("perf machine: Free root_dir in machine__init() error path") introduced 'int err = -ENOMEM' and an error cleanup path but left the final 'return 0' instead of 'return err'. Fix by returning err, check the return value in __machine__new_host() which was ignoring it, and change machines__init() from void to int so it too can propagate the error to perf_session__new(), aslr_tool__init() and test callers. The error cleanup also used zfree(&machine->kmaps), but kmaps is a refcounted maps structure — use maps__zput() to properly drop the reference, matching machine__exit(). Move dsos__init() and threads__init() before the first fallible allocation (maps__new) so that machine__exit() is safe to call on any machine struct that machine__init() touched, even on early failure. Fixes: 81f981d7ec43ed93 ("perf machine: Free root_dir in machine__init() error path") Reported-by: sashiko-bot Cc: Ian Rogers Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/hists_cumulate.c | 5 +++-- tools/perf/tests/hists_filter.c | 5 +++-- tools/perf/tests/hists_link.c | 5 +++-- tools/perf/tests/hists_output.c | 5 +++-- tools/perf/tests/kallsyms-split.c | 7 +++++-- tools/perf/tests/thread-maps-share.c | 2 +- tools/perf/tests/vmlinux-kallsyms.c | 8 +++++--- tools/perf/util/aslr.c | 12 +++++++++--- tools/perf/util/machine.c | 24 ++++++++++++++---------- tools/perf/util/machine.h | 2 +- tools/perf/util/session.c | 7 ++++--- 11 files changed, 51 insertions(+), 31 deletions(-) diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index 267cbc24691a..09ee08085b06 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c @@ -704,7 +704,7 @@ static int test4(struct evsel *evsel, struct machine *machine) static int test__hists_cumulate(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { int err = TEST_FAIL; - struct machines machines; + struct machines machines = { 0 }; struct machine *machine; struct evsel *evsel; struct evlist *evlist = evlist__new(); @@ -723,7 +723,8 @@ static int test__hists_cumulate(struct test_suite *test __maybe_unused, int subt goto out; err = TEST_FAIL; - machines__init(&machines); + if (machines__init(&machines)) + goto out; /* setup threads/dso/map/symbols also */ machine = setup_fake_machine(&machines); diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 002e3a4c1ca5..ac5affb7afff 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c @@ -116,7 +116,7 @@ static void put_fake_samples(void) static int test__hists_filter(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { int err = TEST_FAIL; - struct machines machines; + struct machines machines = { 0 }; struct machine *machine; struct evsel *evsel; struct evlist *evlist = evlist__new(); @@ -131,7 +131,8 @@ static int test__hists_filter(struct test_suite *test __maybe_unused, int subtes goto out; err = TEST_FAIL; - machines__init(&machines); + if (machines__init(&machines)) + goto out; /* setup threads/dso/map/symbols also */ machine = setup_fake_machine(&machines); diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 996f5f0b3bd1..e55990163865 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c @@ -287,7 +287,7 @@ static int test__hists_link(struct test_suite *test __maybe_unused, int subtest { int err = -1; struct hists *hists, *first_hists; - struct machines machines; + struct machines machines = { 0 }; struct machine *machine = NULL; struct evsel *evsel, *first; struct evlist *evlist = evlist__new(); @@ -303,7 +303,8 @@ static int test__hists_link(struct test_suite *test __maybe_unused, int subtest goto out; err = TEST_FAIL; - machines__init(&machines); + if (machines__init(&machines)) + goto out; /* setup threads/dso/map/symbols also */ machine = setup_fake_machine(&machines); diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index fa683fd7b1e5..5e59dba92e81 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c @@ -590,7 +590,7 @@ static int test5(struct evsel *evsel, struct machine *machine) static int test__hists_output(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { int err = TEST_FAIL; - struct machines machines; + struct machines machines = { 0 }; struct machine *machine; struct evsel *evsel; struct evlist *evlist = evlist__new(); @@ -610,7 +610,8 @@ static int test__hists_output(struct test_suite *test __maybe_unused, int subtes goto out; err = TEST_FAIL; - machines__init(&machines); + if (machines__init(&machines)) + goto out; /* setup threads/dso/map/symbols also */ machine = setup_fake_machine(&machines); diff --git a/tools/perf/tests/kallsyms-split.c b/tools/perf/tests/kallsyms-split.c index 117ed3b70f63..244daa01bd5d 100644 --- a/tools/perf/tests/kallsyms-split.c +++ b/tools/perf/tests/kallsyms-split.c @@ -97,7 +97,7 @@ static int create_proc_dir(void) static int test__kallsyms_split(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { - struct machine m; + struct machine m = { 0 }; struct map *map = NULL; int ret = TEST_FAIL; @@ -113,7 +113,10 @@ static int test__kallsyms_split(struct test_suite *test __maybe_unused, signal(SIGTERM, remove_proc_dir); pr_debug("create kernel maps from the fake root directory\n"); - machine__init(&m, root_dir, HOST_KERNEL_ID); + if (machine__init(&m, root_dir, HOST_KERNEL_ID)) { + pr_debug("FAIL: failed to init machine\n"); + goto out; + } if (machine__create_kernel_maps(&m) < 0) { pr_debug("FAIL: failed to create kernel maps\n"); goto out; diff --git a/tools/perf/tests/thread-maps-share.c b/tools/perf/tests/thread-maps-share.c index e9ecd30a5c05..0431bff31b3a 100644 --- a/tools/perf/tests/thread-maps-share.c +++ b/tools/perf/tests/thread-maps-share.c @@ -27,7 +27,7 @@ static int test__thread_maps_share(struct test_suite *test __maybe_unused, int s * other group (pid: 4, tids: 4, 5) */ - machines__init(&machines); + TEST_ASSERT_VAL("failed to init machines", machines__init(&machines) == 0); machine = &machines.host; /* create process with 4 threads */ diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c index 7409abe4aa36..9396c8a77c86 100644 --- a/tools/perf/tests/vmlinux-kallsyms.c +++ b/tools/perf/tests/vmlinux-kallsyms.c @@ -192,7 +192,7 @@ static int test__vmlinux_matches_kallsyms(struct test_suite *test __maybe_unused struct rb_node *nd; struct symbol *sym; struct map *kallsyms_map; - struct machine vmlinux; + struct machine vmlinux = { 0 }; struct maps *maps; u64 mem_start, mem_end; struct test__vmlinux_matches_kallsyms_cb_args args; @@ -203,8 +203,10 @@ static int test__vmlinux_matches_kallsyms(struct test_suite *test __maybe_unused * Init the machines that will hold kernel, modules obtained from * both vmlinux + .ko files and from /proc/kallsyms split by modules. */ - machine__init(&args.kallsyms, "", HOST_KERNEL_ID); - machine__init(&vmlinux, "", HOST_KERNEL_ID); + if (machine__init(&args.kallsyms, "", HOST_KERNEL_ID)) + goto out; + if (machine__init(&vmlinux, "", HOST_KERNEL_ID)) + goto out; maps = machine__kernel_maps(&vmlinux); diff --git a/tools/perf/util/aslr.c b/tools/perf/util/aslr.c index a946fff2ac4d..6a7542e7db82 100644 --- a/tools/perf/util/aslr.c +++ b/tools/perf/util/aslr.c @@ -1237,12 +1237,13 @@ void aslr_tool__strip_attr_event(union perf_event *event, struct evlist *evlist) } } -static void aslr_tool__init(struct aslr_tool *aslr, struct perf_tool *delegate) +static int aslr_tool__init(struct aslr_tool *aslr, struct perf_tool *delegate) { delegate_tool__init(&aslr->tool, delegate); aslr->tool.tool.ordered_events = true; - machines__init(&aslr->machines); + if (machines__init(&aslr->machines)) + return -ENOMEM; hashmap__init(&aslr->remap_addresses, remap_addresses__hash, remap_addresses__equal, @@ -1276,6 +1277,8 @@ static void aslr_tool__init(struct aslr_tool *aslr, struct perf_tool *delegate) aslr->tool.tool.auxtrace = aslr_tool__process_auxtrace; aslr->tool.tool.auxtrace_info = aslr_tool__process_auxtrace_info; aslr->tool.tool.auxtrace_error = aslr_tool__process_auxtrace_error; + + return 0; } struct perf_tool *aslr_tool__new(struct perf_tool *delegate) @@ -1285,7 +1288,10 @@ struct perf_tool *aslr_tool__new(struct perf_tool *delegate) if (!aslr) return NULL; - aslr_tool__init(aslr, delegate); + if (aslr_tool__init(aslr, delegate)) { + free(aslr); + return NULL; + } return &aslr->tool.tool; } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 31715366e29f..9329d319bd03 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -79,15 +79,14 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) int err = -ENOMEM; memset(machine, 0, sizeof(*machine)); - machine->kmaps = maps__new(machine); - if (machine->kmaps == NULL) - return -ENOMEM; - RB_CLEAR_NODE(&machine->rb_node); dsos__init(&machine->dsos); - threads__init(&machine->threads); + machine->kmaps = maps__new(machine); + if (machine->kmaps == NULL) + goto out; + machine->vdso_info = NULL; machine->env = NULL; @@ -124,11 +123,11 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) out: if (err) { - zfree(&machine->kmaps); + maps__zput(machine->kmaps); zfree(&machine->root_dir); zfree(&machine->mmap_name); } - return 0; + return err; } static struct machine *__machine__new_host(struct perf_env *host_env, bool kernel_maps) @@ -138,7 +137,10 @@ static struct machine *__machine__new_host(struct perf_env *host_env, bool kerne if (!machine) return NULL; - machine__init(machine, "", HOST_KERNEL_ID); + if (machine__init(machine, "", HOST_KERNEL_ID) != 0) { + free(machine); + return NULL; + } if (kernel_maps && machine__create_kernel_maps(machine) < 0) { free(machine); @@ -231,10 +233,12 @@ void machine__delete(struct machine *machine) } } -void machines__init(struct machines *machines) +int machines__init(struct machines *machines) { - machine__init(&machines->host, "", HOST_KERNEL_ID); + int err = machine__init(&machines->host, "", HOST_KERNEL_ID); + machines->guests = RB_ROOT_CACHED; + return err; } void machines__exit(struct machines *machines) diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index aaddfb70ea66..26f9827062f5 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -152,7 +152,7 @@ struct machines { struct rb_root_cached guests; }; -void machines__init(struct machines *machines); +int machines__init(struct machines *machines); void machines__exit(struct machines *machines); void machines__process_guests(struct machines *machines, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1a9a008ddda3..f391a822480d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -160,11 +160,12 @@ struct perf_session *__perf_session__new(struct perf_data *data, session->decomp_data.zstd_decomp = &session->zstd_data; session->active_decomp = &session->decomp_data; INIT_LIST_HEAD(&session->auxtrace_index); - machines__init(&session->machines); + perf_env__init(&session->header.env); + if (machines__init(&session->machines)) + goto out_delete; + ordered_events__init(&session->ordered_events, ordered_events__deliver_event, NULL); - - perf_env__init(&session->header.env); if (data) { ret = perf_data__open(data); if (ret < 0) From fe63d3bca288c5bb983304efd5fc3a5ff3183403 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Jun 2026 13:59:39 -0300 Subject: [PATCH 335/343] perf machine: Use snprintf() for guestmount path construction machines__findnew() and machines__create_guest_kernel_maps() use sprintf() to build paths by prepending symbol_conf.guestmount. Both write into PATH_MAX stack buffers, but guestmount comes from user configuration and is not length-checked. A guestmount path at or near PATH_MAX causes a stack buffer overflow. Switch to snprintf() with sizeof() to prevent overflow. The subsequent access()/fopen() calls will fail on a truncated path. Fixes: a1645ce12adb6c9c ("perf: 'perf kvm' tool for monitoring guest performance from host") Reported-by: sashiko-bot Cc: Zhang, Yanmin Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 9329d319bd03..0d2ebf6a84bc 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -333,7 +333,7 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid) if ((pid != HOST_KERNEL_ID) && (pid != DEFAULT_GUEST_KERNEL_ID) && (symbol_conf.guestmount)) { - sprintf(path, "%s/%d", symbol_conf.guestmount, pid); + snprintf(path, sizeof(path), "%s/%d", symbol_conf.guestmount, pid); if (access(path, R_OK)) { static struct strlist *seen; @@ -1260,9 +1260,9 @@ int machines__create_guest_kernel_maps(struct machines *machines) namelist[i]->d_name); continue; } - sprintf(path, "%s/%s/proc/kallsyms", - symbol_conf.guestmount, - namelist[i]->d_name); + snprintf(path, sizeof(path), "%s/%s/proc/kallsyms", + symbol_conf.guestmount, + namelist[i]->d_name); ret = access(path, R_OK); if (ret) { pr_debug("Can't access file %s\n", path); From 312d91329b8fc6989a916a3f9a12d0674167b7e4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Jun 2026 14:16:45 -0300 Subject: [PATCH 336/343] perf cs-etm: Validate num_cpu before metadata allocation cs_etm__process_auxtrace_info_full() reads num_cpu from untrusted perf.data and uses it to allocate the metadata pointer array: metadata = zalloc(sizeof(*metadata) * num_cpu); On 32-bit, sizeof(*metadata) is 4, so num_cpu = 0x40000000 overflows the multiplication to 0, causing zalloc(0) to return a valid zero-sized allocation followed by out-of-bounds writes in the population loop. Fix by computing priv_size early and using it to bound num_cpu: each CPU needs at least one u64 metadata entry, so num_cpu cannot exceed the total number of u64 entries in the event's private data area. Fixes: cd8bfd8c973eaff8 ("perf tools: Add processing of coresight metadata") Reported-by: sashiko-bot Cc: Adrian Hunter Cc: James Clark Cc: Leo Yan Cc: Tor Jeremiassen Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cs-etm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 0927b0b9c06b..d121c8f22028 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -3431,6 +3431,18 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event, /* First the global part */ ptr = (u64 *) auxtrace_info->priv; num_cpu = ptr[CS_PMU_TYPE_CPUS] & 0xffffffff; + + /* + * Bound num_cpu by the event size: the global header consumes + * CS_ETM_HEADER_SIZE bytes, and each CPU needs at least one u64 + * metadata entry after that. + */ + priv_size = total_size - event_header_size - INFO_HEADER_SIZE - + CS_ETM_HEADER_SIZE; + if (num_cpu <= 0 || priv_size <= 0 || + num_cpu > priv_size / (int)sizeof(u64)) + return -EINVAL; + metadata = zalloc(sizeof(*metadata) * num_cpu); if (!metadata) return -ENOMEM; From 78d8ba680126f3545e8d0fba667e12d79fd4353b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Jun 2026 14:40:36 -0300 Subject: [PATCH 337/343] perf cs-etm: Require full global header in auxtrace_info size check cs_etm__process_auxtrace_info() checks that header.size covers event_header_size + INFO_HEADER_SIZE (16 bytes total), but then accesses ptr[CS_PMU_TYPE_CPUS] at offset 24 from the start of the event. A crafted 16-byte auxtrace_info event passes the size check but reads out-of-bounds. Include CS_ETM_HEADER_SIZE in the minimum size check so that the global header entries (version, pmu_type_cpus, snapshot) are guaranteed to fit within the event. Fixes: 55c1de9973d66516 ("perf cs-etm: Print auxtrace info even if OpenCSD isn't linked") Reported-by: sashiko-bot Cc: Adrian Hunter Cc: James Clark Cc: Leo Yan Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cs-etm-base.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/cs-etm-base.c b/tools/perf/util/cs-etm-base.c index 4abe416e3feb..aebef71d3a0a 100644 --- a/tools/perf/util/cs-etm-base.c +++ b/tools/perf/util/cs-etm-base.c @@ -170,7 +170,9 @@ int cs_etm__process_auxtrace_info(union perf_event *event, u64 *ptr = NULL; u64 hdr_version; - if (auxtrace_info->header.size < (event_header_size + INFO_HEADER_SIZE)) + /* Ensure priv[] is large enough for the global header entries */ + if (auxtrace_info->header.size < (event_header_size + INFO_HEADER_SIZE + + CS_ETM_HEADER_SIZE)) return -EINVAL; /* First the global part */ From 9a989e60cc6e29d98aed2087425cba53bf4b392d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Jun 2026 14:55:32 -0300 Subject: [PATCH 338/343] perf cs-etm: Bounds-check CPU in cs_etm__get_queue() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cs_etm__get_queue() indexes etm->queues.queue_array[cpu] without validating that cpu is within nr_queues. When processing AUX_OUTPUT_HW_ID events, the cpu value comes from untrusted perf.data trace payload and flows through cs_etm__process_trace_id_v0_1() and cs_etm__queue_aux_fragment() without bounds checking, allowing an out-of-bounds read with a crafted file. Add a bounds check in cs_etm__get_queue() and NULL checks in all callers. Also add NULL checks for queue_array[i].priv in the queue iteration loops in cs_etm__map_trace_id_v0() and cs_etm__process_trace_id_v0_1() — after auxtrace_queues__grow() new entries are zero-initialized so .priv can be NULL. Add a get_cpu_data() NULL check in cs_etm__process_trace_id_v0_1(), matching the existing check in cs_etm__process_trace_id_v0(). Fixes: 77c123f53e97ad4b ("perf: cs-etm: Move traceid_list to each queue") Reported-by: sashiko-bot Cc: Adrian Hunter Cc: James Clark Cc: Leo Yan Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cs-etm.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index d121c8f22028..5d0664ff73b7 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -292,8 +292,11 @@ static struct cs_etm_queue *cs_etm__get_queue(struct cs_etm_auxtrace *etm, int c { if (etm->per_thread_decoding) return etm->queues.queue_array[0].priv; - else - return etm->queues.queue_array[cpu].priv; + + if (cpu < 0 || cpu >= (int)etm->queues.nr_queues) + return NULL; + + return etm->queues.queue_array[cpu].priv; } static int cs_etm__map_trace_id_v0(struct cs_etm_auxtrace *etm, u8 trace_chan_id, @@ -306,6 +309,9 @@ static int cs_etm__map_trace_id_v0(struct cs_etm_auxtrace *etm, u8 trace_chan_id * queue associated with that CPU so only one decoder is made. */ etmq = cs_etm__get_queue(etm, cpu_metadata[CS_ETM_CPU]); + if (!etmq) + return -EINVAL; + if (etmq->format == UNFORMATTED) return cs_etm__insert_trace_id_node(etmq, trace_chan_id, cpu_metadata); @@ -318,6 +324,9 @@ static int cs_etm__map_trace_id_v0(struct cs_etm_auxtrace *etm, u8 trace_chan_id int ret; etmq = etm->queues.queue_array[i].priv; + if (!etmq) + continue; + ret = cs_etm__insert_trace_id_node(etmq, trace_chan_id, cpu_metadata); if (ret) @@ -358,6 +367,9 @@ static int cs_etm__process_trace_id_v0_1(struct cs_etm_auxtrace *etm, int cpu, u32 sink_id = FIELD_GET(CS_AUX_HW_ID_SINK_ID_MASK, hw_id); u8 trace_id = FIELD_GET(CS_AUX_HW_ID_TRACE_ID_MASK, hw_id); + if (!etmq) + return -EINVAL; + /* * Check sink id hasn't changed in per-cpu mode. In per-thread mode, * let it pass for now until an actual overlapping trace ID is hit. In @@ -375,6 +387,9 @@ static int cs_etm__process_trace_id_v0_1(struct cs_etm_auxtrace *etm, int cpu, for (unsigned int i = 0; i < etm->queues.nr_queues; ++i) { struct cs_etm_queue *other_etmq = etm->queues.queue_array[i].priv; + if (!other_etmq) + continue; + /* Different sinks, skip */ if (other_etmq->sink_id != etmq->sink_id) continue; @@ -396,6 +411,9 @@ static int cs_etm__process_trace_id_v0_1(struct cs_etm_auxtrace *etm, int cpu, } cpu_data = get_cpu_data(etm, cpu); + if (!cpu_data) + return -EINVAL; + ret = cs_etm__insert_trace_id_node(etmq, trace_id, cpu_data); if (ret) return ret; @@ -3144,6 +3162,9 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o aux_offset + aux_size <= auxtrace_event->offset + auxtrace_event->size) { struct cs_etm_queue *etmq = cs_etm__get_queue(etm, auxtrace_event->cpu); + if (!etmq) + return -EINVAL; + /* * If this AUX event was inside this buffer somewhere, create a new auxtrace event * based on the sizes of the aux event, and queue that fragment. From 61a21d11afd8dd83b2260ae00541bed62a843219 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Jun 2026 15:13:54 -0300 Subject: [PATCH 339/343] perf c2c: Free format list entries when c2c_hists__init() fails When c2c_hists__init() fails partway through hpp_list__parse(), dynamically allocated format structures that were already added to hists->list are leaked because he__get_c2c_hists() frees the hists container without first unregistering the format entries. Call perf_hpp__reset_output_field() before freeing the hists container on the error path, matching what c2c_he_free() already does on the normal destruction path. Fixes: 17a7c5946d79a12c ("perf c2c report: Decode c2c_stats for hist entries") Reported-by: sashiko-bot Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 07c7e8fb315e..eabb922ef295 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -226,6 +226,7 @@ he__get_c2c_hists(struct hist_entry *he, ret = c2c_hists__init(hists, sort, nr_header_lines, env); if (ret) { + perf_hpp__reset_output_field(&hists->list); c2c_he->hists = NULL; free(hists); return NULL; From fe68cf349fb343c0a7cb6c4fe6c3de4f4afe8d1c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Jun 2026 15:16:42 -0300 Subject: [PATCH 340/343] perf c2c: Fix hist entry and format list leaks in c2c_he_free() c2c_he_free() calls hists__delete_entries() which only walks the output-sorted entries tree. During c2c resort, when cacheline entries are merged and the redundant entry is freed, the inner hists have not been output-resorted yet, so hists->entries is empty. The actual inner hist_entry objects live in entries_in_array[] and entries_collapsed, which are never walked, leaking all inner hist_entry objects for every merged cacheline. Additionally, the dynamically allocated format entries on hists->list are never unregistered or freed. Fix both issues by switching to hists__delete_all_entries() which walks all rb_root trees, and calling perf_hpp__reset_output_field() to clean up format entries. Fixes: bf0e0d407ea09ce5 ("perf c2c report: Add sample processing") Reported-by: sashiko-bot Cc: Jiri Olsa Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 2 +- tools/perf/util/hist.c | 2 +- tools/perf/util/hist.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index eabb922ef295..c9584dbedf77 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -184,7 +184,7 @@ static void c2c_he_free(void *he) c2c_he = container_of(he, struct c2c_hist_entry, he); if (c2c_he->hists) { - hists__delete_entries(&c2c_he->hists->hists); + hists__delete_all_entries(&c2c_he->hists->hists); perf_hpp__reset_output_field(&c2c_he->hists->list); zfree(&c2c_he->hists); } diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index df978c996b6c..c93915625ee7 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -3041,7 +3041,7 @@ static void hists__delete_remaining_entries(struct rb_root_cached *root) } } -static void hists__delete_all_entries(struct hists *hists) +void hists__delete_all_entries(struct hists *hists) { hists__delete_entries(hists); hists__delete_remaining_entries(&hists->entries_in_array[0]); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 8fb89d81ef06..b830cbe7f95b 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -391,6 +391,7 @@ int hists__collapse_resort(struct hists *hists, struct ui_progress *prog); void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); void hists__delete_entries(struct hists *hists); +void hists__delete_all_entries(struct hists *hists); void hists__output_recalc_col_len(struct hists *hists, int max_rows); struct hist_entry *hists__get_entry(struct hists *hists, int idx); From 5ebf4137d23a4fd6c0cc6a6fb766ee60d2b09193 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Jun 2026 15:25:11 -0300 Subject: [PATCH 341/343] perf bpf: Validate array presence before casting BPF prog info pointers Several functions cast bpf_prog_info fields (jited_ksyms, jited_func_lens, jited_prog_insns) from u64 to pointers and dereference them. These fields are only valid pointers if bpil_offs_to_addr() converted their file offsets to addresses, which only happens when the corresponding PERF_BPIL_* bits are set in info_linear->arrays. A crafted perf.data can leave these bits unset while setting non-zero counts and offset values, causing the functions to dereference raw file offsets as pointers. Add array bitmask validation to all perf.data processing paths: - __bpf_event__print_bpf_prog_info(): check JITED_KSYMS and JITED_FUNC_LENS (changed to take struct perf_bpil *) - machine__process_bpf_event_load(): check JITED_KSYMS - bpf_read(): check JITED_INSNS before memcpy from jited_prog_insns - dso__disassemble_filename(): check JITED_INSNS before returning jited_prog_insns pointer Fixes: f8dfeae009effc0b ("perf bpf: Show more BPF program info in print_bpf_prog_info()") Reported-by: sashiko-bot Cc: Song Liu Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-event.c | 20 +++++++++++++++++--- tools/perf/util/bpf-event.h | 4 ++-- tools/perf/util/dso.c | 10 ++++++++++ tools/perf/util/header.c | 3 +-- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 57d53ba84835..fa3ebc8ea7f0 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -59,6 +59,10 @@ static int machine__process_bpf_event_load(struct machine *machine, return 0; info_linear = info_node->info_linear; + /* jited_ksyms is only valid if bpil_offs_to_addr() converted it */ + if (!(info_linear->arrays & (1UL << PERF_BPIL_JITED_KSYMS))) + return 0; + for (i = 0; i < info_linear->info.nr_jited_ksyms; i++) { u64 *addrs = (u64 *)(uintptr_t)(info_linear->info.jited_ksyms); u64 addr = addrs[i]; @@ -959,12 +963,15 @@ int evlist__add_bpf_sb_event(struct evlist *evlist, struct perf_env *env) return evlist__add_sb_event(evlist, &attr, bpf_event__sb_cb, env); } -void __bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, +void __bpf_event__print_bpf_prog_info(struct perf_bpil *info_linear, struct perf_env *env, FILE *fp) { - __u32 *prog_lens = (__u32 *)(uintptr_t)(info->jited_func_lens); - __u64 *prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms); + struct bpf_prog_info *info = &info_linear->info; + __u64 required_arrays = (1UL << PERF_BPIL_JITED_KSYMS) | + (1UL << PERF_BPIL_JITED_FUNC_LENS); + __u32 *prog_lens; + __u64 *prog_addrs; char name[KSYM_NAME_LEN]; struct btf *btf = NULL; u32 sub_prog_cnt, i; @@ -974,6 +981,13 @@ void __bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, sub_prog_cnt != info->nr_jited_func_lens) return; + /* Ensure the arrays were present and converted by bpil_offs_to_addr() */ + if ((info_linear->arrays & required_arrays) != required_arrays) + return; + + prog_lens = (__u32 *)(uintptr_t)(info->jited_func_lens); + prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms); + if (info->btf_id) { struct btf_node *node; diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h index 60d2c6637af5..da4eeb4a1a73 100644 --- a/tools/perf/util/bpf-event.h +++ b/tools/perf/util/bpf-event.h @@ -40,7 +40,7 @@ struct btf_node { int machine__process_bpf(struct machine *machine, union perf_event *event, struct perf_sample *sample); int evlist__add_bpf_sb_event(struct evlist *evlist, struct perf_env *env); -void __bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, +void __bpf_event__print_bpf_prog_info(struct perf_bpil *info_linear, struct perf_env *env, FILE *fp); void bpf_metadata_free(struct bpf_metadata *metadata); @@ -58,7 +58,7 @@ static inline int evlist__add_bpf_sb_event(struct evlist *evlist __maybe_unused, return 0; } -static inline void __bpf_event__print_bpf_prog_info(struct bpf_prog_info *info __maybe_unused, +static inline void __bpf_event__print_bpf_prog_info(struct perf_bpil *info_linear __maybe_unused, struct perf_env *env __maybe_unused, FILE *fp __maybe_unused) { diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 1a2fc6d18da7..79f1a30f3683 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -880,6 +880,12 @@ static ssize_t bpf_read(struct dso *dso, u64 offset, char *data) return -1; } + /* jited_prog_insns is only valid if bpil_offs_to_addr() converted it */ + if (!(node->info_linear->arrays & (1UL << PERF_BPIL_JITED_INSNS))) { + dso__data(dso)->status = DSO_DATA_STATUS_ERROR; + return -1; + } + len = node->info_linear->info.jited_prog_len; buf = (u8 *)(uintptr_t)node->info_linear->info.jited_prog_insns; @@ -1995,6 +2001,10 @@ const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename, return NULL; } info_linear = info_node->info_linear; + if (!(info_linear->arrays & (1UL << PERF_BPIL_JITED_INSNS))) { + errno = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF; + return NULL; + } assert(len <= info_linear->info.jited_prog_len); *out_buf_len = len; return (const u8 *)(uintptr_t)(info_linear->info.jited_prog_insns); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index d7f41db7322c..091d8f7f6bd2 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2107,8 +2107,7 @@ static void print_bpf_prog_info(struct feat_fd *ff __maybe_unused, FILE *fp) node = rb_entry(next, struct bpf_prog_info_node, rb_node); next = rb_next(&node->rb_node); - __bpf_event__print_bpf_prog_info(&node->info_linear->info, - env, fp); + __bpf_event__print_bpf_prog_info(node->info_linear, env, fp); } up_read(&env->bpf_progs.lock); From 1a5f9334a45a6b0c1cd7341cc72a3b87adad1d27 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 13 Jun 2026 15:55:33 -0300 Subject: [PATCH 342/343] perf dso: Set standard errno on decompression failure dso__get_filename() sets errno to a negative custom DSO_LOAD_ERRNO value when kernel module decompression fails: errno = *dso__load_errno(dso); /* e.g. -9996 */ The caller __open_dso() then computes fd = -errno, producing a large positive value (9996) that looks like a valid file descriptor. This can cause close_data_fd() to close an unrelated fd used by another subsystem. Set errno to EIO instead. The detailed error code is already stored in dso__load_errno(dso) for diagnostic messages. Fixes: 1d6b3c9ba756a513 ("perf tools: Decompress kernel module when reading DSO data") Reported-by: sashiko-bot Cc: Namhyung Kim Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 79f1a30f3683..2309196d8df3 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -600,7 +600,13 @@ static char *dso__get_filename(struct dso *dso, const char *root_dir, size_t len = sizeof(newpath); if (dso__decompress_kmodule_path(dso, name, newpath, len) < 0) { - errno = *dso__load_errno(dso); + /* + * Use a standard errno value, not the negative custom + * DSO_LOAD_ERRNO stored in dso__load_errno(dso): + * __open_dso() computes fd = -errno, so a negative + * errno produces a positive fd that looks valid. + */ + errno = EIO; goto out; } From 3287a1881ca528b89b964d9fa6d28880d277d9e2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 17 Jun 2026 14:00:38 +0100 Subject: [PATCH 343/343] perf bpf: Fix up build failure due to change of btf_vlen() return type Fix: util/btf.c: In function '__btf_type__find_member_by_name': util/btf.c:19:43: error: comparison of integer expressions of different signedness: 'int' and '__u32' {aka 'unsigned int'} [-Werror=sign-compare] 19 | for (i = 0, m = btf_members(t); i < btf_vlen(t); i++, m++) { | ^ builtin-trace.c: In function 'syscall_arg__strtoul_btf_enum': builtin-trace.c:967:27: error: comparison of integer expressions of different signedness: 'int' and '__u32' {aka 'unsigned int'} [-Werror=sign-compare] 967 | for (int i = 0; i < btf_vlen(bt); ++i, ++be) { | ^ by making the variable the same type as the function. Committer note: Add an extra hunk from Alan Maguire, fixing btf_enum_scnprintf(). Reviewed-by: Alan Maguire Signed-off-by: Mark Brown Cc: Alexei Starovoitov Cc: Linus Torvalds Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 6 +++--- tools/perf/util/btf.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 57f3f14c5d43..ba0f8749fc7d 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -972,7 +972,7 @@ static bool syscall_arg__strtoul_btf_enum(char *bf, size_t size, struct syscall_ struct btf *btf = arg->trace->btf; struct btf_enum *be = btf_enum(bt); - for (int i = 0; i < btf_vlen(bt); ++i, ++be) { + for (u32 i = 0; i < btf_vlen(bt); ++i, ++be) { const char *name = btf__name_by_offset(btf, be->name_off); int max_len = max(size, strlen(name)); @@ -1017,9 +1017,9 @@ static bool syscall_arg__strtoul_btf_type(char *bf, size_t size, struct syscall_ static size_t btf_enum_scnprintf(const struct btf_type *type, struct btf *btf, char *bf, size_t size, int val) { struct btf_enum *be = btf_enum(type); - const int nr_entries = btf_vlen(type); + const unsigned int nr_entries = btf_vlen(type); - for (int i = 0; i < nr_entries; ++i, ++be) { + for (unsigned int i = 0; i < nr_entries; ++i, ++be) { if (be->val == val) { return scnprintf(bf, size, "%s", btf__name_by_offset(btf, be->name_off)); diff --git a/tools/perf/util/btf.c b/tools/perf/util/btf.c index bb163fe87767..50d98f3e83bf 100644 --- a/tools/perf/util/btf.c +++ b/tools/perf/util/btf.c @@ -14,7 +14,7 @@ const struct btf_member *__btf_type__find_member_by_name(struct btf *btf, { const struct btf_type *t = btf__type_by_id(btf, type_id); const struct btf_member *m; - int i; + u32 i; for (i = 0, m = btf_members(t); i < btf_vlen(t); i++, m++) { const char *current_member_name = btf__name_by_offset(btf, m->name_off);