diff options
author | Jean Pihet <jean.pihet@linaro.org> | 2014-04-28 08:32:33 -0400 |
---|---|---|
committer | Jiri Olsa <jolsa@kernel.org> | 2014-04-29 09:31:19 -0400 |
commit | 8ab596afb97bc9e2f9140dc1d993e81749acff42 (patch) | |
tree | 76e352baf6cf3e1029c37bc2866775f3e32abb9d | |
parent | 88080ce7f6af1ad99ad4b2825938411975910116 (diff) |
perf tools ARM64: Wire up perf_regs and unwind support
This patch hooks in the perf_regs and libunwind code for ARM64.
The tools/perf/arch/arm64 is created; it contains the arch specific
code for DWARF unwinding.
Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
Link: http://lkml.kernel.org/r/1398688353-3737-1-git-send-email-jean.pihet@linaro.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
-rw-r--r-- | tools/perf/arch/arm64/Makefile | 7 | ||||
-rw-r--r-- | tools/perf/arch/arm64/include/perf_regs.h | 88 | ||||
-rw-r--r-- | tools/perf/arch/arm64/util/dwarf-regs.c | 80 | ||||
-rw-r--r-- | tools/perf/arch/arm64/util/unwind-libunwind.c | 82 | ||||
-rw-r--r-- | tools/perf/config/Makefile | 8 |
5 files changed, 264 insertions, 1 deletions
diff --git a/tools/perf/arch/arm64/Makefile b/tools/perf/arch/arm64/Makefile new file mode 100644 index 000000000000..67e9b3d38e89 --- /dev/null +++ b/tools/perf/arch/arm64/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | ifndef NO_DWARF | ||
2 | PERF_HAVE_DWARF_REGS := 1 | ||
3 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o | ||
4 | endif | ||
5 | ifndef NO_LIBUNWIND | ||
6 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o | ||
7 | endif | ||
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h new file mode 100644 index 000000000000..23595467402d --- /dev/null +++ b/tools/perf/arch/arm64/include/perf_regs.h | |||
@@ -0,0 +1,88 @@ | |||
1 | #ifndef ARCH_PERF_REGS_H | ||
2 | #define ARCH_PERF_REGS_H | ||
3 | |||
4 | #include <stdlib.h> | ||
5 | #include "../../util/types.h" | ||
6 | #include <asm/perf_regs.h> | ||
7 | |||
8 | #define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1) | ||
9 | #define PERF_REG_IP PERF_REG_ARM64_PC | ||
10 | #define PERF_REG_SP PERF_REG_ARM64_SP | ||
11 | |||
12 | static inline const char *perf_reg_name(int id) | ||
13 | { | ||
14 | switch (id) { | ||
15 | case PERF_REG_ARM64_X0: | ||
16 | return "x0"; | ||
17 | case PERF_REG_ARM64_X1: | ||
18 | return "x1"; | ||
19 | case PERF_REG_ARM64_X2: | ||
20 | return "x2"; | ||
21 | case PERF_REG_ARM64_X3: | ||
22 | return "x3"; | ||
23 | case PERF_REG_ARM64_X4: | ||
24 | return "x4"; | ||
25 | case PERF_REG_ARM64_X5: | ||
26 | return "x5"; | ||
27 | case PERF_REG_ARM64_X6: | ||
28 | return "x6"; | ||
29 | case PERF_REG_ARM64_X7: | ||
30 | return "x7"; | ||
31 | case PERF_REG_ARM64_X8: | ||
32 | return "x8"; | ||
33 | case PERF_REG_ARM64_X9: | ||
34 | return "x9"; | ||
35 | case PERF_REG_ARM64_X10: | ||
36 | return "x10"; | ||
37 | case PERF_REG_ARM64_X11: | ||
38 | return "x11"; | ||
39 | case PERF_REG_ARM64_X12: | ||
40 | return "x12"; | ||
41 | case PERF_REG_ARM64_X13: | ||
42 | return "x13"; | ||
43 | case PERF_REG_ARM64_X14: | ||
44 | return "x14"; | ||
45 | case PERF_REG_ARM64_X15: | ||
46 | return "x15"; | ||
47 | case PERF_REG_ARM64_X16: | ||
48 | return "x16"; | ||
49 | case PERF_REG_ARM64_X17: | ||
50 | return "x17"; | ||
51 | case PERF_REG_ARM64_X18: | ||
52 | return "x18"; | ||
53 | case PERF_REG_ARM64_X19: | ||
54 | return "x19"; | ||
55 | case PERF_REG_ARM64_X20: | ||
56 | return "x20"; | ||
57 | case PERF_REG_ARM64_X21: | ||
58 | return "x21"; | ||
59 | case PERF_REG_ARM64_X22: | ||
60 | return "x22"; | ||
61 | case PERF_REG_ARM64_X23: | ||
62 | return "x23"; | ||
63 | case PERF_REG_ARM64_X24: | ||
64 | return "x24"; | ||
65 | case PERF_REG_ARM64_X25: | ||
66 | return "x25"; | ||
67 | case PERF_REG_ARM64_X26: | ||
68 | return "x26"; | ||
69 | case PERF_REG_ARM64_X27: | ||
70 | return "x27"; | ||
71 | case PERF_REG_ARM64_X28: | ||
72 | return "x28"; | ||
73 | case PERF_REG_ARM64_X29: | ||
74 | return "x29"; | ||
75 | case PERF_REG_ARM64_SP: | ||
76 | return "sp"; | ||
77 | case PERF_REG_ARM64_LR: | ||
78 | return "lr"; | ||
79 | case PERF_REG_ARM64_PC: | ||
80 | return "pc"; | ||
81 | default: | ||
82 | return NULL; | ||
83 | } | ||
84 | |||
85 | return NULL; | ||
86 | } | ||
87 | |||
88 | #endif /* ARCH_PERF_REGS_H */ | ||
diff --git a/tools/perf/arch/arm64/util/dwarf-regs.c b/tools/perf/arch/arm64/util/dwarf-regs.c new file mode 100644 index 000000000000..d49efeb8172e --- /dev/null +++ b/tools/perf/arch/arm64/util/dwarf-regs.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Mapping of DWARF debug register numbers into register names. | ||
3 | * | ||
4 | * Copyright (C) 2010 Will Deacon, ARM Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <stddef.h> | ||
12 | #include <dwarf-regs.h> | ||
13 | |||
14 | struct pt_regs_dwarfnum { | ||
15 | const char *name; | ||
16 | unsigned int dwarfnum; | ||
17 | }; | ||
18 | |||
19 | #define STR(s) #s | ||
20 | #define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} | ||
21 | #define GPR_DWARFNUM_NAME(num) \ | ||
22 | {.name = STR(%x##num), .dwarfnum = num} | ||
23 | #define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} | ||
24 | |||
25 | /* | ||
26 | * Reference: | ||
27 | * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0057b/IHI0057B_aadwarf64.pdf | ||
28 | */ | ||
29 | static const struct pt_regs_dwarfnum regdwarfnum_table[] = { | ||
30 | GPR_DWARFNUM_NAME(0), | ||
31 | GPR_DWARFNUM_NAME(1), | ||
32 | GPR_DWARFNUM_NAME(2), | ||
33 | GPR_DWARFNUM_NAME(3), | ||
34 | GPR_DWARFNUM_NAME(4), | ||
35 | GPR_DWARFNUM_NAME(5), | ||
36 | GPR_DWARFNUM_NAME(6), | ||
37 | GPR_DWARFNUM_NAME(7), | ||
38 | GPR_DWARFNUM_NAME(8), | ||
39 | GPR_DWARFNUM_NAME(9), | ||
40 | GPR_DWARFNUM_NAME(10), | ||
41 | GPR_DWARFNUM_NAME(11), | ||
42 | GPR_DWARFNUM_NAME(12), | ||
43 | GPR_DWARFNUM_NAME(13), | ||
44 | GPR_DWARFNUM_NAME(14), | ||
45 | GPR_DWARFNUM_NAME(15), | ||
46 | GPR_DWARFNUM_NAME(16), | ||
47 | GPR_DWARFNUM_NAME(17), | ||
48 | GPR_DWARFNUM_NAME(18), | ||
49 | GPR_DWARFNUM_NAME(19), | ||
50 | GPR_DWARFNUM_NAME(20), | ||
51 | GPR_DWARFNUM_NAME(21), | ||
52 | GPR_DWARFNUM_NAME(22), | ||
53 | GPR_DWARFNUM_NAME(23), | ||
54 | GPR_DWARFNUM_NAME(24), | ||
55 | GPR_DWARFNUM_NAME(25), | ||
56 | GPR_DWARFNUM_NAME(26), | ||
57 | GPR_DWARFNUM_NAME(27), | ||
58 | GPR_DWARFNUM_NAME(28), | ||
59 | GPR_DWARFNUM_NAME(29), | ||
60 | REG_DWARFNUM_NAME("%lr", 30), | ||
61 | REG_DWARFNUM_NAME("%sp", 31), | ||
62 | REG_DWARFNUM_END, | ||
63 | }; | ||
64 | |||
65 | /** | ||
66 | * get_arch_regstr() - lookup register name from it's DWARF register number | ||
67 | * @n: the DWARF register number | ||
68 | * | ||
69 | * get_arch_regstr() returns the name of the register in struct | ||
70 | * regdwarfnum_table from it's DWARF register number. If the register is not | ||
71 | * found in the table, this returns NULL; | ||
72 | */ | ||
73 | const char *get_arch_regstr(unsigned int n) | ||
74 | { | ||
75 | const struct pt_regs_dwarfnum *roff; | ||
76 | for (roff = regdwarfnum_table; roff->name != NULL; roff++) | ||
77 | if (roff->dwarfnum == n) | ||
78 | return roff->name; | ||
79 | return NULL; | ||
80 | } | ||
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c new file mode 100644 index 000000000000..436ee43859dc --- /dev/null +++ b/tools/perf/arch/arm64/util/unwind-libunwind.c | |||
@@ -0,0 +1,82 @@ | |||
1 | |||
2 | #include <errno.h> | ||
3 | #include <libunwind.h> | ||
4 | #include "perf_regs.h" | ||
5 | #include "../../util/unwind.h" | ||
6 | |||
7 | int libunwind__arch_reg_id(int regnum) | ||
8 | { | ||
9 | switch (regnum) { | ||
10 | case UNW_AARCH64_X0: | ||
11 | return PERF_REG_ARM64_X0; | ||
12 | case UNW_AARCH64_X1: | ||
13 | return PERF_REG_ARM64_X1; | ||
14 | case UNW_AARCH64_X2: | ||
15 | return PERF_REG_ARM64_X2; | ||
16 | case UNW_AARCH64_X3: | ||
17 | return PERF_REG_ARM64_X3; | ||
18 | case UNW_AARCH64_X4: | ||
19 | return PERF_REG_ARM64_X4; | ||
20 | case UNW_AARCH64_X5: | ||
21 | return PERF_REG_ARM64_X5; | ||
22 | case UNW_AARCH64_X6: | ||
23 | return PERF_REG_ARM64_X6; | ||
24 | case UNW_AARCH64_X7: | ||
25 | return PERF_REG_ARM64_X7; | ||
26 | case UNW_AARCH64_X8: | ||
27 | return PERF_REG_ARM64_X8; | ||
28 | case UNW_AARCH64_X9: | ||
29 | return PERF_REG_ARM64_X9; | ||
30 | case UNW_AARCH64_X10: | ||
31 | return PERF_REG_ARM64_X10; | ||
32 | case UNW_AARCH64_X11: | ||
33 | return PERF_REG_ARM64_X11; | ||
34 | case UNW_AARCH64_X12: | ||
35 | return PERF_REG_ARM64_X12; | ||
36 | case UNW_AARCH64_X13: | ||
37 | return PERF_REG_ARM64_X13; | ||
38 | case UNW_AARCH64_X14: | ||
39 | return PERF_REG_ARM64_X14; | ||
40 | case UNW_AARCH64_X15: | ||
41 | return PERF_REG_ARM64_X15; | ||
42 | case UNW_AARCH64_X16: | ||
43 | return PERF_REG_ARM64_X16; | ||
44 | case UNW_AARCH64_X17: | ||
45 | return PERF_REG_ARM64_X17; | ||
46 | case UNW_AARCH64_X18: | ||
47 | return PERF_REG_ARM64_X18; | ||
48 | case UNW_AARCH64_X19: | ||
49 | return PERF_REG_ARM64_X19; | ||
50 | case UNW_AARCH64_X20: | ||
51 | return PERF_REG_ARM64_X20; | ||
52 | case UNW_AARCH64_X21: | ||
53 | return PERF_REG_ARM64_X21; | ||
54 | case UNW_AARCH64_X22: | ||
55 | return PERF_REG_ARM64_X22; | ||
56 | case UNW_AARCH64_X23: | ||
57 | return PERF_REG_ARM64_X23; | ||
58 | case UNW_AARCH64_X24: | ||
59 | return PERF_REG_ARM64_X24; | ||
60 | case UNW_AARCH64_X25: | ||
61 | return PERF_REG_ARM64_X25; | ||
62 | case UNW_AARCH64_X26: | ||
63 | return PERF_REG_ARM64_X26; | ||
64 | case UNW_AARCH64_X27: | ||
65 | return PERF_REG_ARM64_X27; | ||
66 | case UNW_AARCH64_X28: | ||
67 | return PERF_REG_ARM64_X28; | ||
68 | case UNW_AARCH64_X29: | ||
69 | return PERF_REG_ARM64_X29; | ||
70 | case UNW_AARCH64_X30: | ||
71 | return PERF_REG_ARM64_LR; | ||
72 | case UNW_AARCH64_SP: | ||
73 | return PERF_REG_ARM64_SP; | ||
74 | case UNW_AARCH64_PC: | ||
75 | return PERF_REG_ARM64_PC; | ||
76 | default: | ||
77 | pr_err("unwind: invalid reg id %d\n", regnum); | ||
78 | return -EINVAL; | ||
79 | } | ||
80 | |||
81 | return -EINVAL; | ||
82 | } | ||
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index a71fb395e38f..cd568699157c 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -29,11 +29,17 @@ ifeq ($(ARCH),x86) | |||
29 | endif | 29 | endif |
30 | NO_PERF_REGS := 0 | 30 | NO_PERF_REGS := 0 |
31 | endif | 31 | endif |
32 | |||
32 | ifeq ($(ARCH),arm) | 33 | ifeq ($(ARCH),arm) |
33 | NO_PERF_REGS := 0 | 34 | NO_PERF_REGS := 0 |
34 | LIBUNWIND_LIBS = -lunwind -lunwind-arm | 35 | LIBUNWIND_LIBS = -lunwind -lunwind-arm |
35 | endif | 36 | endif |
36 | 37 | ||
38 | ifeq ($(ARCH),arm64) | ||
39 | NO_PERF_REGS := 0 | ||
40 | LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 | ||
41 | endif | ||
42 | |||
37 | # So far there's only x86 libdw unwind support merged in perf. | 43 | # So far there's only x86 libdw unwind support merged in perf. |
38 | # Disable it on all other architectures in case libdw unwind | 44 | # Disable it on all other architectures in case libdw unwind |
39 | # support is detected in system. Add supported architectures | 45 | # support is detected in system. Add supported architectures |
@@ -363,7 +369,7 @@ else | |||
363 | endif | 369 | endif |
364 | 370 | ||
365 | ifndef NO_LIBUNWIND | 371 | ifndef NO_LIBUNWIND |
366 | ifeq ($(ARCH),arm) | 372 | ifeq ($(ARCH),$(filter $(ARCH),arm arm64)) |
367 | $(call feature_check,libunwind-debug-frame) | 373 | $(call feature_check,libunwind-debug-frame) |
368 | ifneq ($(feature-libunwind-debug-frame), 1) | 374 | ifneq ($(feature-libunwind-debug-frame), 1) |
369 | msg := $(warning No debug_frame support found in libunwind); | 375 | msg := $(warning No debug_frame support found in libunwind); |