]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf dwarf-regs: Add powerpc perf to DWARF register number mapping functions
authorIan Rogers <irogers@google.com>
Sat, 17 Jan 2026 05:28:43 +0000 (21:28 -0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 20 Jan 2026 18:43:56 +0000 (15:43 -0300)
These functions allow the generic initial register state code in
unwind-libdw to be used.

Note, the link register was being coped to DWARF register 65 that the
SysV ABI spec claims is FPSCR. It is corrected here to 108, but this is
unlikely to matter as FPSCR has little to no impact on unwinding.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Aditya Bodkhe <aditya.b1@linux.ibm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Alexandre Ghiti <alex@ghiti.fr>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.ibm.com>
Cc: Chun-Tse Shao <ctshao@google.com>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Dr. David Alan Gilbert <linux@treblig.org>
Cc: Guo Ren <guoren@kernel.org>
Cc: Haibo Xu <haibo1.xu@intel.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Krzysztof Ɓopatowski <krzysztof.m.lopatowski@gmail.com>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: Mark Wielaard <mark@klomp.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Walmsley <pjw@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sergei Trofimovich <slyich@gmail.com>
Cc: Shimin Guo <shimin.guo@skydio.com>
Cc: Stephen Brennan <stephen.s.brennan@oracle.com>
Cc: Thomas Falcon <thomas.falcon@intel.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/dwarf-regs-arch/dwarf-regs-powerpc.c
tools/perf/util/dwarf-regs.c
tools/perf/util/include/dwarf-regs.h
tools/perf/util/unwind-libdw-arch/Build
tools/perf/util/unwind-libdw-arch/unwind-libdw-powerpc.c [deleted file]
tools/perf/util/unwind-libdw.c
tools/perf/util/unwind-libdw.h

index caf77a234c785ae46cea37f2b354e0ca1af0634c..51892a09725b4d8cc23de6f6619ec8215db3d6fd 100644 (file)
@@ -4,8 +4,9 @@
  *
  * Copyright (C) 2010 Ian Munsie, IBM Corporation.
  */
-
+#include <errno.h>
 #include <dwarf-regs.h>
+#include "../../../arch/powerpc/include/uapi/asm/perf_regs.h"
 
 #define PPC_OP(op)     (((op) >> 26) & 0x3F)
 #define PPC_RA(a)      (((a) >> 16) & 0x1f)
@@ -59,3 +60,77 @@ void get_powerpc_regs(u32 raw_insn, int is_source,
        if ((op_loc->mem_ref) && (PPC_OP(raw_insn) != 31))
                op_loc->offset = get_offset_opcode(raw_insn);
 }
+
+int __get_dwarf_regnum_for_perf_regnum_powerpc(int perf_regnum)
+{
+       static const int dwarf_powerpc_regnums[] = {
+               [PERF_REG_POWERPC_R0] = 0,
+               [PERF_REG_POWERPC_R1] = 1,
+               [PERF_REG_POWERPC_R2] = 2,
+               [PERF_REG_POWERPC_R3] = 3,
+               [PERF_REG_POWERPC_R4] = 4,
+               [PERF_REG_POWERPC_R5] = 5,
+               [PERF_REG_POWERPC_R6] = 6,
+               [PERF_REG_POWERPC_R7] = 7,
+               [PERF_REG_POWERPC_R8] = 8,
+               [PERF_REG_POWERPC_R9] = 9,
+               [PERF_REG_POWERPC_R10] = 10,
+               [PERF_REG_POWERPC_R11] = 11,
+               [PERF_REG_POWERPC_R12] = 12,
+               [PERF_REG_POWERPC_R13] = 13,
+               [PERF_REG_POWERPC_R14] = 14,
+               [PERF_REG_POWERPC_R15] = 15,
+               [PERF_REG_POWERPC_R16] = 16,
+               [PERF_REG_POWERPC_R17] = 17,
+               [PERF_REG_POWERPC_R18] = 18,
+               [PERF_REG_POWERPC_R19] = 19,
+               [PERF_REG_POWERPC_R20] = 20,
+               [PERF_REG_POWERPC_R21] = 21,
+               [PERF_REG_POWERPC_R22] = 22,
+               [PERF_REG_POWERPC_R23] = 23,
+               [PERF_REG_POWERPC_R24] = 24,
+               [PERF_REG_POWERPC_R25] = 25,
+               [PERF_REG_POWERPC_R26] = 26,
+               [PERF_REG_POWERPC_R27] = 27,
+               [PERF_REG_POWERPC_R28] = 28,
+               [PERF_REG_POWERPC_R29] = 29,
+               [PERF_REG_POWERPC_R30] = 30,
+               [PERF_REG_POWERPC_R31] = 31,
+               /* TODO: PERF_REG_POWERPC_NIP */
+               [PERF_REG_POWERPC_MSR] = 66,
+               /* TODO: PERF_REG_POWERPC_ORIG_R3 */
+               [PERF_REG_POWERPC_CTR] = 109,
+               [PERF_REG_POWERPC_LINK] = 108, /* Note, previously in perf encoded as 65? */
+               [PERF_REG_POWERPC_XER] = 101,
+               /* TODO: PERF_REG_POWERPC_CCR */
+               /* TODO: PERF_REG_POWERPC_SOFTE */
+               /* TODO: PERF_REG_POWERPC_TRAP */
+               /* TODO: PERF_REG_POWERPC_DAR */
+               /* TODO: PERF_REG_POWERPC_DSISR */
+               /* TODO: PERF_REG_POWERPC_SIER */
+               /* TODO: PERF_REG_POWERPC_MMCRA */
+               /* TODO: PERF_REG_POWERPC_MMCR0 */
+               /* TODO: PERF_REG_POWERPC_MMCR1 */
+               /* TODO: PERF_REG_POWERPC_MMCR2 */
+               /* TODO: PERF_REG_POWERPC_MMCR3 */
+               /* TODO: PERF_REG_POWERPC_SIER2 */
+               /* TODO: PERF_REG_POWERPC_SIER3 */
+               /* TODO: PERF_REG_POWERPC_PMC1 */
+               /* TODO: PERF_REG_POWERPC_PMC2 */
+               /* TODO: PERF_REG_POWERPC_PMC3 */
+               /* TODO: PERF_REG_POWERPC_PMC4 */
+               /* TODO: PERF_REG_POWERPC_PMC5 */
+               /* TODO: PERF_REG_POWERPC_PMC6 */
+               /* TODO: PERF_REG_POWERPC_SDAR */
+               /* TODO: PERF_REG_POWERPC_SIAR */
+       };
+
+       if (perf_regnum == 0)
+               return 0;
+
+       if (perf_regnum <  0 || perf_regnum > (int)ARRAY_SIZE(dwarf_powerpc_regnums) ||
+           dwarf_powerpc_regnums[perf_regnum] == 0)
+               return -ENOENT;
+
+       return dwarf_powerpc_regnums[perf_regnum];
+}
index 033218f14b367346104874f084b2a879abce06ce..3b1c2a436806e0512085f7cdc8b62aa22a712c31 100644 (file)
@@ -205,6 +205,10 @@ int get_dwarf_regnum_for_perf_regnum(int perf_regnum, unsigned int machine,
        case EM_CSKY:
                reg = __get_dwarf_regnum_for_perf_regnum_csky(perf_regnum, flags);
                break;
+       case EM_PPC:
+       case EM_PPC64:
+               reg = __get_dwarf_regnum_for_perf_regnum_powerpc(perf_regnum);
+               break;
        case EM_LOONGARCH:
                reg = __get_dwarf_regnum_for_perf_regnum_loongarch(perf_regnum);
                break;
index bec15fb53e73ab5b8dc5a8697895da3e5e966a39..9ebb3ba33fba9c2c59031fff2755de0b351999f0 100644 (file)
@@ -110,6 +110,7 @@ int __get_dwarf_regnum_for_perf_regnum_arm64(int perf_regnum);
 
 int __get_dwarf_regnum_for_perf_regnum_csky(int perf_regnum, unsigned int flags);
 int __get_dwarf_regnum_for_perf_regnum_loongarch(int perf_regnum);
+int __get_dwarf_regnum_for_perf_regnum_powerpc(int perf_regnum);
 
 /*
  * get_dwarf_regnum - Returns DWARF regnum from register name
index 62a4cbf2dca8e98ee992ceff4d0cff47da02d7d0..e6c97e842cd66e8b0b218203e2bca665b32088fe 100644 (file)
@@ -1,3 +1,2 @@
-perf-util-y += unwind-libdw-powerpc.o
 perf-util-y += unwind-libdw-riscv.o
 perf-util-y += unwind-libdw-s390.o
diff --git a/tools/perf/util/unwind-libdw-arch/unwind-libdw-powerpc.c b/tools/perf/util/unwind-libdw-arch/unwind-libdw-powerpc.c
deleted file mode 100644 (file)
index 1560db4..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <elfutils/libdwfl.h>
-#include <linux/kernel.h>
-#include "../arch/powerpc/include/uapi/asm/perf_regs.h"
-#include "util/unwind-libdw.h"
-#include "util/perf_regs.h"
-#include "util/sample.h"
-
-/* See backends/ppc_initreg.c and backends/ppc_regs.c in elfutils.  */
-static const int special_regs[3][2] = {
-       { 65, PERF_REG_POWERPC_LINK },
-       { 101, PERF_REG_POWERPC_XER },
-       { 109, PERF_REG_POWERPC_CTR },
-};
-
-bool libdw_set_initial_registers_powerpc(Dwfl_Thread *thread, void *arg)
-{
-       struct unwind_info *ui = arg;
-       struct regs_dump *user_regs = perf_sample__user_regs(ui->sample);
-       Dwarf_Word dwarf_regs[32], dwarf_nip;
-       size_t i;
-
-#define REG(r) ({                                              \
-       Dwarf_Word val = 0;                                     \
-       perf_reg_value(&val, user_regs, PERF_REG_POWERPC_##r);  \
-       val;                                                    \
-})
-
-       dwarf_regs[0]  = REG(R0);
-       dwarf_regs[1]  = REG(R1);
-       dwarf_regs[2]  = REG(R2);
-       dwarf_regs[3]  = REG(R3);
-       dwarf_regs[4]  = REG(R4);
-       dwarf_regs[5]  = REG(R5);
-       dwarf_regs[6]  = REG(R6);
-       dwarf_regs[7]  = REG(R7);
-       dwarf_regs[8]  = REG(R8);
-       dwarf_regs[9]  = REG(R9);
-       dwarf_regs[10] = REG(R10);
-       dwarf_regs[11] = REG(R11);
-       dwarf_regs[12] = REG(R12);
-       dwarf_regs[13] = REG(R13);
-       dwarf_regs[14] = REG(R14);
-       dwarf_regs[15] = REG(R15);
-       dwarf_regs[16] = REG(R16);
-       dwarf_regs[17] = REG(R17);
-       dwarf_regs[18] = REG(R18);
-       dwarf_regs[19] = REG(R19);
-       dwarf_regs[20] = REG(R20);
-       dwarf_regs[21] = REG(R21);
-       dwarf_regs[22] = REG(R22);
-       dwarf_regs[23] = REG(R23);
-       dwarf_regs[24] = REG(R24);
-       dwarf_regs[25] = REG(R25);
-       dwarf_regs[26] = REG(R26);
-       dwarf_regs[27] = REG(R27);
-       dwarf_regs[28] = REG(R28);
-       dwarf_regs[29] = REG(R29);
-       dwarf_regs[30] = REG(R30);
-       dwarf_regs[31] = REG(R31);
-       if (!dwfl_thread_state_registers(thread, 0, 32, dwarf_regs))
-               return false;
-
-       dwarf_nip = REG(NIP);
-       dwfl_thread_state_register_pc(thread, dwarf_nip);
-       for (i = 0; i < ARRAY_SIZE(special_regs); i++) {
-               Dwarf_Word val = 0;
-               perf_reg_value(&val, user_regs, special_regs[i][1]);
-               if (!dwfl_thread_state_registers(thread,
-                                                special_regs[i][0], 1,
-                                                &val))
-                       return false;
-       }
-
-       return true;
-}
index 9c8dad643cd06f3d0b3c40d3d01e71b78271cfa6..e9ba050e7ab1a3a8a9cecd43bb5b60c722046318 100644 (file)
@@ -292,15 +292,12 @@ static const Dwfl_Thread_Callbacks callbacks_generic = {
        .set_initial_registers = libdw_set_initial_registers_generic,
 };
 
-DEFINE_DWFL_THREAD_CALLBACKS(powerpc);
 DEFINE_DWFL_THREAD_CALLBACKS(riscv);
 DEFINE_DWFL_THREAD_CALLBACKS(s390);
 
 static const Dwfl_Thread_Callbacks *get_thread_callbacks(const char *arch)
 {
-       if (!strcmp(arch, "powerpc"))
-               return &callbacks_powerpc;
-       else if (!strcmp(arch, "riscv"))
+       if (!strcmp(arch, "riscv"))
                return &callbacks_riscv;
        else if (!strcmp(arch, "s390"))
                return &callbacks_s390;
index 9d177d70f15c0868c93484e95a98380e45016f55..0ec1abdabbe7a4e90c809c5b0871bbc60cc170c7 100644 (file)
@@ -10,7 +10,6 @@ struct perf_sample;
 struct thread;
 
 bool libdw_set_initial_registers_mips(Dwfl_Thread *thread, void *arg);
-bool libdw_set_initial_registers_powerpc(Dwfl_Thread *thread, void *arg);
 bool libdw_set_initial_registers_riscv(Dwfl_Thread *thread, void *arg);
 bool libdw_set_initial_registers_s390(Dwfl_Thread *thread, void *arg);