xref: /linux/tools/perf/util/perf_regs.c (revision 16dccbb84203196dab2e578b27c3c8f549ebff66)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <elf.h>
3 #include <errno.h>
4 #include <string.h>
5 #include "dwarf-regs.h"
6 #include "perf_regs.h"
7 #include "util/sample.h"
8 #include "debug.h"
9 
10 int __weak arch_sdt_arg_parse_op(char *old_op __maybe_unused,
11 				 char **new_op __maybe_unused)
12 {
13 	return SDT_ARG_SKIP;
14 }
15 
16 uint64_t perf_intr_reg_mask(uint16_t e_machine)
17 {
18 	uint64_t mask = 0;
19 
20 	switch (e_machine) {
21 	case EM_ARM:
22 		mask = __perf_reg_mask_arm(/*intr=*/true);
23 		break;
24 	case EM_AARCH64:
25 		mask = __perf_reg_mask_arm64(/*intr=*/true);
26 		break;
27 	case EM_CSKY:
28 		mask = __perf_reg_mask_csky(/*intr=*/true);
29 		break;
30 	case EM_LOONGARCH:
31 		mask = __perf_reg_mask_loongarch(/*intr=*/true);
32 		break;
33 	case EM_MIPS:
34 		mask = __perf_reg_mask_mips(/*intr=*/true);
35 		break;
36 	case EM_PPC:
37 	case EM_PPC64:
38 		mask = __perf_reg_mask_powerpc(/*intr=*/true);
39 		break;
40 	case EM_RISCV:
41 		mask = __perf_reg_mask_riscv(/*intr=*/true);
42 		break;
43 	case EM_S390:
44 		mask = __perf_reg_mask_s390(/*intr=*/true);
45 		break;
46 	case EM_386:
47 	case EM_X86_64:
48 		mask = __perf_reg_mask_x86(/*intr=*/true);
49 		break;
50 	default:
51 		pr_debug("Unknown ELF machine %d, interrupt sampling register mask will be empty.\n",
52 			 e_machine);
53 		break;
54 	}
55 
56 	return mask;
57 }
58 
59 uint64_t perf_user_reg_mask(uint16_t e_machine)
60 {
61 	uint64_t mask = 0;
62 
63 	switch (e_machine) {
64 	case EM_ARM:
65 		mask = __perf_reg_mask_arm(/*intr=*/false);
66 		break;
67 	case EM_AARCH64:
68 		mask = __perf_reg_mask_arm64(/*intr=*/false);
69 		break;
70 	case EM_CSKY:
71 		mask = __perf_reg_mask_csky(/*intr=*/false);
72 		break;
73 	case EM_LOONGARCH:
74 		mask = __perf_reg_mask_loongarch(/*intr=*/false);
75 		break;
76 	case EM_MIPS:
77 		mask = __perf_reg_mask_mips(/*intr=*/false);
78 		break;
79 	case EM_PPC:
80 	case EM_PPC64:
81 		mask = __perf_reg_mask_powerpc(/*intr=*/false);
82 		break;
83 	case EM_RISCV:
84 		mask = __perf_reg_mask_riscv(/*intr=*/false);
85 		break;
86 	case EM_S390:
87 		mask = __perf_reg_mask_s390(/*intr=*/false);
88 		break;
89 	case EM_386:
90 	case EM_X86_64:
91 		mask = __perf_reg_mask_x86(/*intr=*/false);
92 		break;
93 	default:
94 		pr_debug("Unknown ELF machine %d, user sampling register mask will be empty.\n",
95 			 e_machine);
96 		break;
97 	}
98 
99 	return mask;
100 }
101 
102 const char *perf_reg_name(int id, uint16_t e_machine, uint32_t e_flags)
103 {
104 	const char *reg_name = NULL;
105 
106 	switch (e_machine) {
107 	case EM_ARM:
108 		reg_name = __perf_reg_name_arm(id);
109 		break;
110 	case EM_AARCH64:
111 		reg_name = __perf_reg_name_arm64(id);
112 		break;
113 	case EM_CSKY:
114 		reg_name = __perf_reg_name_csky(id, e_flags);
115 		break;
116 	case EM_LOONGARCH:
117 		reg_name = __perf_reg_name_loongarch(id);
118 		break;
119 	case EM_MIPS:
120 		reg_name = __perf_reg_name_mips(id);
121 		break;
122 	case EM_PPC:
123 	case EM_PPC64:
124 		reg_name = __perf_reg_name_powerpc(id);
125 		break;
126 	case EM_RISCV:
127 		reg_name = __perf_reg_name_riscv(id);
128 		break;
129 	case EM_S390:
130 		reg_name = __perf_reg_name_s390(id);
131 		break;
132 	case EM_386:
133 	case EM_X86_64:
134 		reg_name = __perf_reg_name_x86(id);
135 		break;
136 	default:
137 		break;
138 	}
139 	if (reg_name)
140 		return reg_name;
141 
142 	pr_debug("Failed to find register %d for ELF machine type %u\n", id, e_machine);
143 	return "unknown";
144 }
145 
146 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
147 {
148 	int i, idx = 0;
149 	u64 mask = regs->mask;
150 
151 	if ((u64)id >= PERF_SAMPLE_REGS_CACHE_SIZE)
152 		return -EINVAL;
153 
154 	if (regs->cache_mask & (1ULL << id))
155 		goto out;
156 
157 	if (!(mask & (1ULL << id)))
158 		return -EINVAL;
159 
160 	for (i = 0; i < id; i++) {
161 		if (mask & (1ULL << i))
162 			idx++;
163 	}
164 
165 	regs->cache_mask |= (1ULL << id);
166 	regs->cache_regs[id] = regs->regs[idx];
167 
168 out:
169 	*valp = regs->cache_regs[id];
170 	return 0;
171 }
172 
173 uint64_t perf_arch_reg_ip(uint16_t e_machine)
174 {
175 	switch (e_machine) {
176 	case EM_ARM:
177 		return __perf_reg_ip_arm();
178 	case EM_AARCH64:
179 		return __perf_reg_ip_arm64();
180 	case EM_CSKY:
181 		return __perf_reg_ip_csky();
182 	case EM_LOONGARCH:
183 		return __perf_reg_ip_loongarch();
184 	case EM_MIPS:
185 		return __perf_reg_ip_mips();
186 	case EM_PPC:
187 	case EM_PPC64:
188 		return __perf_reg_ip_powerpc();
189 	case EM_RISCV:
190 		return __perf_reg_ip_riscv();
191 	case EM_S390:
192 		return __perf_reg_ip_s390();
193 	case EM_386:
194 	case EM_X86_64:
195 		return __perf_reg_ip_x86();
196 	default:
197 		pr_err("Failed to find IP register for ELF machine type %u\n", e_machine);
198 		return 0;
199 	}
200 }
201 
202 uint64_t perf_arch_reg_sp(uint16_t e_machine)
203 {
204 	switch (e_machine) {
205 	case EM_ARM:
206 		return __perf_reg_sp_arm();
207 	case EM_AARCH64:
208 		return __perf_reg_sp_arm64();
209 	case EM_CSKY:
210 		return __perf_reg_sp_csky();
211 	case EM_LOONGARCH:
212 		return __perf_reg_sp_loongarch();
213 	case EM_MIPS:
214 		return __perf_reg_sp_mips();
215 	case EM_PPC:
216 	case EM_PPC64:
217 		return __perf_reg_sp_powerpc();
218 	case EM_RISCV:
219 		return __perf_reg_sp_riscv();
220 	case EM_S390:
221 		return __perf_reg_sp_s390();
222 	case EM_386:
223 	case EM_X86_64:
224 		return __perf_reg_sp_x86();
225 	default:
226 		pr_err("Failed to find SP register for ELF machine type %u\n", e_machine);
227 		return 0;
228 	}
229 }
230