This patch add support for DWARF register mappings and libdw registers
initialization, which is used by perf callchain analyzing when
--call-graph=dwarf is given.

CC: Peter Zijlstra <pet...@infradead.org>
CC: Ingo Molnar <mi...@redhat.com>
CC: Arnaldo Carvalho de Melo <a...@kernel.org>
CC: Alexander Shishkin <alexander.shish...@linux.intel.com>
CC: Jiri Olsa <jo...@redhat.com>
CC: Namhyung Kim <namhy...@kernel.org>
CC: Guo Ren <guo...@kernel.org>

Signed-off-by: Mao Han <han_...@c-sky.com>
---
 tools/arch/csky/include/uapi/asm/perf_regs.h | 48 ++++++++++++++
 tools/perf/Makefile.config                   |  6 +-
 tools/perf/arch/csky/Build                   |  1 +
 tools/perf/arch/csky/Makefile                |  3 +
 tools/perf/arch/csky/include/perf_regs.h     | 98 ++++++++++++++++++++++++++++
 tools/perf/arch/csky/util/Build              |  2 +
 tools/perf/arch/csky/util/dwarf-regs.c       | 25 +++++++
 tools/perf/arch/csky/util/unwind-libdw.c     | 58 ++++++++++++++++
 8 files changed, 240 insertions(+), 1 deletion(-)
 create mode 100644 tools/arch/csky/include/uapi/asm/perf_regs.h
 create mode 100644 tools/perf/arch/csky/Build
 create mode 100644 tools/perf/arch/csky/Makefile
 create mode 100644 tools/perf/arch/csky/include/perf_regs.h
 create mode 100644 tools/perf/arch/csky/util/Build
 create mode 100644 tools/perf/arch/csky/util/dwarf-regs.c
 create mode 100644 tools/perf/arch/csky/util/unwind-libdw.c

diff --git a/tools/arch/csky/include/uapi/asm/perf_regs.h 
b/tools/arch/csky/include/uapi/asm/perf_regs.h
new file mode 100644
index 0000000..337d8fa
--- /dev/null
+++ b/tools/arch/csky/include/uapi/asm/perf_regs.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+
+#ifndef _ASM_CSKY_PERF_REGS_H
+#define _ASM_CSKY_PERF_REGS_H
+
+enum perf_event_csky_regs {
+       PERF_REG_CSKY_TLS,
+       PERF_REG_CSKY_LR,
+       PERF_REG_CSKY_PC,
+       PERF_REG_CSKY_SR,
+       PERF_REG_CSKY_SP,
+       PERF_REG_CSKY_ORIG_A0,
+       PERF_REG_CSKY_R0,
+       PERF_REG_CSKY_R1,
+       PERF_REG_CSKY_R2,
+       PERF_REG_CSKY_R3,
+       PERF_REG_CSKY_R4,
+       PERF_REG_CSKY_R5,
+       PERF_REG_CSKY_R6,
+       PERF_REG_CSKY_R7,
+       PERF_REG_CSKY_R8,
+       PERF_REG_CSKY_R9,
+       PERF_REG_CSKY_R10,
+       PERF_REG_CSKY_R11,
+       PERF_REG_CSKY_R12,
+       PERF_REG_CSKY_R13,
+       PERF_REG_CSKY_R16,
+       PERF_REG_CSKY_R17,
+       PERF_REG_CSKY_R18,
+       PERF_REG_CSKY_R19,
+       PERF_REG_CSKY_R20,
+       PERF_REG_CSKY_R21,
+       PERF_REG_CSKY_R22,
+       PERF_REG_CSKY_R23,
+       PERF_REG_CSKY_R24,
+       PERF_REG_CSKY_R25,
+       PERF_REG_CSKY_R26,
+       PERF_REG_CSKY_R27,
+       PERF_REG_CSKY_R28,
+       PERF_REG_CSKY_R29,
+       PERF_REG_CSKY_R30,
+       PERF_REG_CSKY_HI,
+       PERF_REG_CSKY_LO,
+       PERF_REG_CSKY_DCSR,
+       PERF_REG_CSKY_MAX,
+};
+#endif /* _ASM_CSKY_PERF_REGS_H */
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index fe3f97e..42985ae 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -59,6 +59,10 @@ ifeq ($(SRCARCH),arm64)
   LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
 endif
 
+ifeq ($(SRCARCH),csky)
+  NO_PERF_REGS := 0
+endif
+
 ifeq ($(ARCH),s390)
   NO_PERF_REGS := 0
   NO_SYSCALL_TABLE := 0
@@ -77,7 +81,7 @@ endif
 # Disable it on all other architectures in case libdw unwind
 # support is detected in system. Add supported architectures
 # to the check.
-ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc s390))
+ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc s390 csky))
   NO_LIBDW_DWARF_UNWIND := 1
 endif
 
diff --git a/tools/perf/arch/csky/Build b/tools/perf/arch/csky/Build
new file mode 100644
index 0000000..54afe4a
--- /dev/null
+++ b/tools/perf/arch/csky/Build
@@ -0,0 +1 @@
+libperf-y += util/
diff --git a/tools/perf/arch/csky/Makefile b/tools/perf/arch/csky/Makefile
new file mode 100644
index 0000000..7fbca17
--- /dev/null
+++ b/tools/perf/arch/csky/Makefile
@@ -0,0 +1,3 @@
+ifndef NO_DWARF
+PERF_HAVE_DWARF_REGS := 1
+endif
diff --git a/tools/perf/arch/csky/include/perf_regs.h 
b/tools/perf/arch/csky/include/perf_regs.h
new file mode 100644
index 0000000..6baae28
--- /dev/null
+++ b/tools/perf/arch/csky/include/perf_regs.h
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+
+#ifndef ARCH_PERF_REGS_H
+#define ARCH_PERF_REGS_H
+
+#include <stdlib.h>
+#include <linux/types.h>
+#include <asm/perf_regs.h>
+
+#define PERF_REGS_MASK ((1ULL << PERF_REG_CSKY_MAX) - 1)
+#define PERF_REGS_MAX  PERF_REG_CSKY_MAX
+#define PERF_SAMPLE_REGS_ABI   PERF_SAMPLE_REGS_ABI_32
+
+#define PERF_REG_IP    PERF_REG_CSKY_PC
+#define PERF_REG_SP    PERF_REG_CSKY_SP
+
+static inline const char *perf_reg_name(int id)
+{
+       switch (id) {
+       case PERF_REG_CSKY_R0:
+               return "r0";
+       case PERF_REG_CSKY_R1:
+               return "r1";
+       case PERF_REG_CSKY_R2:
+               return "r2";
+       case PERF_REG_CSKY_R3:
+               return "r3";
+       case PERF_REG_CSKY_R4:
+               return "r4";
+       case PERF_REG_CSKY_R5:
+               return "r5";
+       case PERF_REG_CSKY_R6:
+               return "r6";
+       case PERF_REG_CSKY_R7:
+               return "r7";
+       case PERF_REG_CSKY_R8:
+               return "r8";
+       case PERF_REG_CSKY_R9:
+               return "r9";
+       case PERF_REG_CSKY_R10:
+               return "r10";
+       case PERF_REG_CSKY_R11:
+               return "r11";
+       case PERF_REG_CSKY_R12:
+               return "r12";
+       case PERF_REG_CSKY_R13:
+               return "r13";
+       case PERF_REG_CSKY_SP:
+               return "sp";
+       case PERF_REG_CSKY_LR:
+               return "lr";
+       case PERF_REG_CSKY_R16:
+               return "r16";
+       case PERF_REG_CSKY_R17:
+               return "r17";
+       case PERF_REG_CSKY_R18:
+               return "r18";
+       case PERF_REG_CSKY_R19:
+               return "r19";
+       case PERF_REG_CSKY_R20:
+               return "r20";
+       case PERF_REG_CSKY_R21:
+               return "r21";
+       case PERF_REG_CSKY_R22:
+               return "r22";
+       case PERF_REG_CSKY_R23:
+               return "r23";
+       case PERF_REG_CSKY_R24:
+               return "r24";
+       case PERF_REG_CSKY_R25:
+               return "r25";
+       case PERF_REG_CSKY_R26:
+               return "r26";
+       case PERF_REG_CSKY_R27:
+               return "r27";
+       case PERF_REG_CSKY_R28:
+               return "r28";
+       case PERF_REG_CSKY_R29:
+               return "r29";
+       case PERF_REG_CSKY_R30:
+               return "r30";
+       case PERF_REG_CSKY_TLS:
+               return "tls";
+       case PERF_REG_CSKY_PC:
+               return "pc";
+       case PERF_REG_CSKY_HI:
+               return "hi";
+       case PERF_REG_CSKY_LO:
+               return "lo";
+       default:
+               return NULL;
+       }
+
+       return NULL;
+}
+
+#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/csky/util/Build b/tools/perf/arch/csky/util/Build
new file mode 100644
index 0000000..8e45471
--- /dev/null
+++ b/tools/perf/arch/csky/util/Build
@@ -0,0 +1,2 @@
+libperf-$(CONFIG_DWARF) += dwarf-regs.o
+libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/csky/util/dwarf-regs.c 
b/tools/perf/arch/csky/util/dwarf-regs.c
new file mode 100644
index 0000000..d9b78e2
--- /dev/null
+++ b/tools/perf/arch/csky/util/dwarf-regs.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+// Mapping of DWARF debug register numbers into register names.
+
+#include <stddef.h>
+#include <dwarf-regs.h>
+
+#define CSKY_MAX_REGS 71
+
+const char *csky_regs_table[CSKY_MAX_REGS] = {
+        "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
+        "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%sp", "%lr",
+        "%r16", "%r17", "%r18", "%r19", "%r20", "%21", "%22", "%23",
+        "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%tls",
+        "%pc", "%cc", "%hi", "%lo", "%rr", "%rr", "%rr", "%rr",
+        "%rr", "%rr", "%rr", "%rr", "%rr", "%rr", "%rr", "%rr",
+        "%rr", "%rr", "%rr", "%rr", "%vr0", "%vr1", "%vr2", "%vr3",
+        "%vr4", "%vr5", "%vr6", "%vr7", "%vr8", "%vr9", "%vr10", "%vr11",
+        "%vr12", "%vr13", "%vr14", "%vr15", "%rr", "%rr", "%epc",
+};
+
+const char *get_arch_regstr(unsigned int n)
+{
+        return (n < CSKY_MAX_REGS) ? csky_regs_table[n] : NULL;
+}
diff --git a/tools/perf/arch/csky/util/unwind-libdw.c 
b/tools/perf/arch/csky/util/unwind-libdw.c
new file mode 100644
index 0000000..1b5b845
--- /dev/null
+++ b/tools/perf/arch/csky/util/unwind-libdw.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+
+#include <elfutils/libdwfl.h>
+#include "../../util/unwind-libdw.h"
+#include "../../util/perf_regs.h"
+#include "../../util/event.h"
+
+bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
+{
+       struct unwind_info *ui = arg;
+       struct regs_dump *user_regs = &ui->sample->user_regs;
+       Dwarf_Word dwarf_regs[PERF_REG_CSKY_MAX];
+
+#define REG(r) ({                                              \
+       Dwarf_Word val = 0;                                     \
+       perf_reg_value(&val, user_regs, PERF_REG_CSKY_##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(SP);
+       dwarf_regs[15] = REG(LR);
+       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(TLS);
+       dwarf_regs[32] = REG(PC);
+       dwfl_thread_state_register_pc(thread, dwarf_regs[32]);
+
+       return dwfl_thread_state_registers(thread, 0, PERF_REG_CSKY_MAX,
+                                          dwarf_regs);
+}
-- 
2.7.4

Reply via email to