perf annotate-data: Track instructions with a this-cpu variable
authorNamhyung Kim <namhyung@kernel.org>
Tue, 19 Mar 2024 05:51:10 +0000 (22:51 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 21 Mar 2024 13:41:29 +0000 (10:41 -0300)
Like global variables, this per-cpu variables should be tracked
correctly.  Factor our get_global_var_type() to handle both global
and per-cpu (for this cpu) variables in the same manner.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: https://lore.kernel.org/r/20240319055115.4063940-19-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/annotate-data.c

index d57622ddd5d317ec71a29c2c7bf3cf10788e1341..48fea0c716ef9d304f1680e17e33034bdcf37c6c 100644 (file)
@@ -553,12 +553,41 @@ static void update_insn_state_x86(struct type_state *state,
                        fbreg = -1;
        }
 
-       /* Case 1. register to register transfers */
+       /* Case 1. register to register or segment:offset to register transfers */
        if (!src->mem_ref && !dst->mem_ref) {
                if (!has_reg_type(state, dst->reg1))
                        return;
 
                tsr = &state->regs[dst->reg1];
+               if (map__dso(dloc->ms->map)->kernel &&
+                   src->segment == INSN_SEG_X86_GS && src->imm) {
+                       u64 ip = dloc->ms->sym->start + dl->al.offset;
+                       u64 var_addr;
+                       int offset;
+
+                       /*
+                        * In kernel, %gs points to a per-cpu region for the
+                        * current CPU.  Access with a constant offset should
+                        * be treated as a global variable access.
+                        */
+                       var_addr = src->offset;
+
+                       if (!get_global_var_type(cu_die, dloc, ip, var_addr,
+                                                &offset, &type_die) ||
+                           !die_get_member_type(&type_die, offset, &type_die)) {
+                               tsr->ok = false;
+                               return;
+                       }
+
+                       tsr->type = type_die;
+                       tsr->ok = true;
+
+                       pr_debug_dtp("mov [%x] this-cpu addr=%#"PRIx64" -> reg%d",
+                                    insn_offset, var_addr, dst->reg1);
+                       pr_debug_type_name(&tsr->type);
+                       return;
+               }
+
                if (!has_reg_type(state, src->reg1) ||
                    !state->regs[src->reg1].ok) {
                        tsr->ok = false;