mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
perf dwarf-regs: Add powerpc perf to DWARF register number mapping functions
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>
This commit is contained in:
parent
1f10d82e6a
commit
f005302294
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user