1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <errno.h> |
3 | #include <string.h> |
4 | #include "perf_regs.h" |
5 | #include "util/sample.h" |
6 | #include "debug.h" |
7 | |
8 | int __weak arch_sdt_arg_parse_op(char *old_op __maybe_unused, |
9 | char **new_op __maybe_unused) |
10 | { |
11 | return SDT_ARG_SKIP; |
12 | } |
13 | |
14 | uint64_t __weak arch__intr_reg_mask(void) |
15 | { |
16 | return 0; |
17 | } |
18 | |
19 | uint64_t __weak arch__user_reg_mask(void) |
20 | { |
21 | return 0; |
22 | } |
23 | |
24 | static const struct sample_reg sample_reg_masks[] = { |
25 | SMPL_REG_END |
26 | }; |
27 | |
28 | const struct sample_reg * __weak arch__sample_reg_masks(void) |
29 | { |
30 | return sample_reg_masks; |
31 | } |
32 | |
33 | const char *perf_reg_name(int id, const char *arch) |
34 | { |
35 | const char *reg_name = NULL; |
36 | |
37 | if (!strcmp(arch, "csky" )) |
38 | reg_name = __perf_reg_name_csky(id); |
39 | else if (!strcmp(arch, "loongarch" )) |
40 | reg_name = __perf_reg_name_loongarch(id); |
41 | else if (!strcmp(arch, "mips" )) |
42 | reg_name = __perf_reg_name_mips(id); |
43 | else if (!strcmp(arch, "powerpc" )) |
44 | reg_name = __perf_reg_name_powerpc(id); |
45 | else if (!strcmp(arch, "riscv" )) |
46 | reg_name = __perf_reg_name_riscv(id); |
47 | else if (!strcmp(arch, "s390" )) |
48 | reg_name = __perf_reg_name_s390(id); |
49 | else if (!strcmp(arch, "x86" )) |
50 | reg_name = __perf_reg_name_x86(id); |
51 | else if (!strcmp(arch, "arm" )) |
52 | reg_name = __perf_reg_name_arm(id); |
53 | else if (!strcmp(arch, "arm64" )) |
54 | reg_name = __perf_reg_name_arm64(id); |
55 | |
56 | return reg_name ?: "unknown" ; |
57 | } |
58 | |
59 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) |
60 | { |
61 | int i, idx = 0; |
62 | u64 mask = regs->mask; |
63 | |
64 | if ((u64)id >= PERF_SAMPLE_REGS_CACHE_SIZE) |
65 | return -EINVAL; |
66 | |
67 | if (regs->cache_mask & (1ULL << id)) |
68 | goto out; |
69 | |
70 | if (!(mask & (1ULL << id))) |
71 | return -EINVAL; |
72 | |
73 | for (i = 0; i < id; i++) { |
74 | if (mask & (1ULL << i)) |
75 | idx++; |
76 | } |
77 | |
78 | regs->cache_mask |= (1ULL << id); |
79 | regs->cache_regs[id] = regs->regs[idx]; |
80 | |
81 | out: |
82 | *valp = regs->cache_regs[id]; |
83 | return 0; |
84 | } |
85 | |
86 | uint64_t perf_arch_reg_ip(const char *arch) |
87 | { |
88 | if (!strcmp(arch, "arm" )) |
89 | return __perf_reg_ip_arm(); |
90 | else if (!strcmp(arch, "arm64" )) |
91 | return __perf_reg_ip_arm64(); |
92 | else if (!strcmp(arch, "csky" )) |
93 | return __perf_reg_ip_csky(); |
94 | else if (!strcmp(arch, "loongarch" )) |
95 | return __perf_reg_ip_loongarch(); |
96 | else if (!strcmp(arch, "mips" )) |
97 | return __perf_reg_ip_mips(); |
98 | else if (!strcmp(arch, "powerpc" )) |
99 | return __perf_reg_ip_powerpc(); |
100 | else if (!strcmp(arch, "riscv" )) |
101 | return __perf_reg_ip_riscv(); |
102 | else if (!strcmp(arch, "s390" )) |
103 | return __perf_reg_ip_s390(); |
104 | else if (!strcmp(arch, "x86" )) |
105 | return __perf_reg_ip_x86(); |
106 | |
107 | pr_err("Fail to find IP register for arch %s, returns 0\n" , arch); |
108 | return 0; |
109 | } |
110 | |
111 | uint64_t perf_arch_reg_sp(const char *arch) |
112 | { |
113 | if (!strcmp(arch, "arm" )) |
114 | return __perf_reg_sp_arm(); |
115 | else if (!strcmp(arch, "arm64" )) |
116 | return __perf_reg_sp_arm64(); |
117 | else if (!strcmp(arch, "csky" )) |
118 | return __perf_reg_sp_csky(); |
119 | else if (!strcmp(arch, "loongarch" )) |
120 | return __perf_reg_sp_loongarch(); |
121 | else if (!strcmp(arch, "mips" )) |
122 | return __perf_reg_sp_mips(); |
123 | else if (!strcmp(arch, "powerpc" )) |
124 | return __perf_reg_sp_powerpc(); |
125 | else if (!strcmp(arch, "riscv" )) |
126 | return __perf_reg_sp_riscv(); |
127 | else if (!strcmp(arch, "s390" )) |
128 | return __perf_reg_sp_s390(); |
129 | else if (!strcmp(arch, "x86" )) |
130 | return __perf_reg_sp_x86(); |
131 | |
132 | pr_err("Fail to find SP register for arch %s, returns 0\n" , arch); |
133 | return 0; |
134 | } |
135 | |