xref: /openbmc/linux/tools/perf/util/perf_regs.c (revision 27e45f2e)
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 
7 int __weak arch_sdt_arg_parse_op(char *old_op __maybe_unused,
8 				 char **new_op __maybe_unused)
9 {
10 	return SDT_ARG_SKIP;
11 }
12 
13 uint64_t __weak arch__intr_reg_mask(void)
14 {
15 	return PERF_REGS_MASK;
16 }
17 
18 uint64_t __weak arch__user_reg_mask(void)
19 {
20 	return PERF_REGS_MASK;
21 }
22 
23 #ifdef HAVE_PERF_REGS_SUPPORT
24 
25 #define perf_event_arm_regs perf_event_arm64_regs
26 #include "../../arch/arm64/include/uapi/asm/perf_regs.h"
27 #undef perf_event_arm_regs
28 
29 #include "../../arch/arm/include/uapi/asm/perf_regs.h"
30 #include "../../arch/csky/include/uapi/asm/perf_regs.h"
31 #include "../../arch/mips/include/uapi/asm/perf_regs.h"
32 #include "../../arch/powerpc/include/uapi/asm/perf_regs.h"
33 #include "../../arch/riscv/include/uapi/asm/perf_regs.h"
34 #include "../../arch/s390/include/uapi/asm/perf_regs.h"
35 #include "../../arch/x86/include/uapi/asm/perf_regs.h"
36 
37 static const char *__perf_reg_name_arm64(int id)
38 {
39 	switch (id) {
40 	case PERF_REG_ARM64_X0:
41 		return "x0";
42 	case PERF_REG_ARM64_X1:
43 		return "x1";
44 	case PERF_REG_ARM64_X2:
45 		return "x2";
46 	case PERF_REG_ARM64_X3:
47 		return "x3";
48 	case PERF_REG_ARM64_X4:
49 		return "x4";
50 	case PERF_REG_ARM64_X5:
51 		return "x5";
52 	case PERF_REG_ARM64_X6:
53 		return "x6";
54 	case PERF_REG_ARM64_X7:
55 		return "x7";
56 	case PERF_REG_ARM64_X8:
57 		return "x8";
58 	case PERF_REG_ARM64_X9:
59 		return "x9";
60 	case PERF_REG_ARM64_X10:
61 		return "x10";
62 	case PERF_REG_ARM64_X11:
63 		return "x11";
64 	case PERF_REG_ARM64_X12:
65 		return "x12";
66 	case PERF_REG_ARM64_X13:
67 		return "x13";
68 	case PERF_REG_ARM64_X14:
69 		return "x14";
70 	case PERF_REG_ARM64_X15:
71 		return "x15";
72 	case PERF_REG_ARM64_X16:
73 		return "x16";
74 	case PERF_REG_ARM64_X17:
75 		return "x17";
76 	case PERF_REG_ARM64_X18:
77 		return "x18";
78 	case PERF_REG_ARM64_X19:
79 		return "x19";
80 	case PERF_REG_ARM64_X20:
81 		return "x20";
82 	case PERF_REG_ARM64_X21:
83 		return "x21";
84 	case PERF_REG_ARM64_X22:
85 		return "x22";
86 	case PERF_REG_ARM64_X23:
87 		return "x23";
88 	case PERF_REG_ARM64_X24:
89 		return "x24";
90 	case PERF_REG_ARM64_X25:
91 		return "x25";
92 	case PERF_REG_ARM64_X26:
93 		return "x26";
94 	case PERF_REG_ARM64_X27:
95 		return "x27";
96 	case PERF_REG_ARM64_X28:
97 		return "x28";
98 	case PERF_REG_ARM64_X29:
99 		return "x29";
100 	case PERF_REG_ARM64_SP:
101 		return "sp";
102 	case PERF_REG_ARM64_LR:
103 		return "lr";
104 	case PERF_REG_ARM64_PC:
105 		return "pc";
106 	case PERF_REG_ARM64_VG:
107 		return "vg";
108 	default:
109 		return NULL;
110 	}
111 
112 	return NULL;
113 }
114 
115 static const char *__perf_reg_name_arm(int id)
116 {
117 	switch (id) {
118 	case PERF_REG_ARM_R0:
119 		return "r0";
120 	case PERF_REG_ARM_R1:
121 		return "r1";
122 	case PERF_REG_ARM_R2:
123 		return "r2";
124 	case PERF_REG_ARM_R3:
125 		return "r3";
126 	case PERF_REG_ARM_R4:
127 		return "r4";
128 	case PERF_REG_ARM_R5:
129 		return "r5";
130 	case PERF_REG_ARM_R6:
131 		return "r6";
132 	case PERF_REG_ARM_R7:
133 		return "r7";
134 	case PERF_REG_ARM_R8:
135 		return "r8";
136 	case PERF_REG_ARM_R9:
137 		return "r9";
138 	case PERF_REG_ARM_R10:
139 		return "r10";
140 	case PERF_REG_ARM_FP:
141 		return "fp";
142 	case PERF_REG_ARM_IP:
143 		return "ip";
144 	case PERF_REG_ARM_SP:
145 		return "sp";
146 	case PERF_REG_ARM_LR:
147 		return "lr";
148 	case PERF_REG_ARM_PC:
149 		return "pc";
150 	default:
151 		return NULL;
152 	}
153 
154 	return NULL;
155 }
156 
157 static const char *__perf_reg_name_csky(int id)
158 {
159 	switch (id) {
160 	case PERF_REG_CSKY_A0:
161 		return "a0";
162 	case PERF_REG_CSKY_A1:
163 		return "a1";
164 	case PERF_REG_CSKY_A2:
165 		return "a2";
166 	case PERF_REG_CSKY_A3:
167 		return "a3";
168 	case PERF_REG_CSKY_REGS0:
169 		return "regs0";
170 	case PERF_REG_CSKY_REGS1:
171 		return "regs1";
172 	case PERF_REG_CSKY_REGS2:
173 		return "regs2";
174 	case PERF_REG_CSKY_REGS3:
175 		return "regs3";
176 	case PERF_REG_CSKY_REGS4:
177 		return "regs4";
178 	case PERF_REG_CSKY_REGS5:
179 		return "regs5";
180 	case PERF_REG_CSKY_REGS6:
181 		return "regs6";
182 	case PERF_REG_CSKY_REGS7:
183 		return "regs7";
184 	case PERF_REG_CSKY_REGS8:
185 		return "regs8";
186 	case PERF_REG_CSKY_REGS9:
187 		return "regs9";
188 	case PERF_REG_CSKY_SP:
189 		return "sp";
190 	case PERF_REG_CSKY_LR:
191 		return "lr";
192 	case PERF_REG_CSKY_PC:
193 		return "pc";
194 #if defined(__CSKYABIV2__)
195 	case PERF_REG_CSKY_EXREGS0:
196 		return "exregs0";
197 	case PERF_REG_CSKY_EXREGS1:
198 		return "exregs1";
199 	case PERF_REG_CSKY_EXREGS2:
200 		return "exregs2";
201 	case PERF_REG_CSKY_EXREGS3:
202 		return "exregs3";
203 	case PERF_REG_CSKY_EXREGS4:
204 		return "exregs4";
205 	case PERF_REG_CSKY_EXREGS5:
206 		return "exregs5";
207 	case PERF_REG_CSKY_EXREGS6:
208 		return "exregs6";
209 	case PERF_REG_CSKY_EXREGS7:
210 		return "exregs7";
211 	case PERF_REG_CSKY_EXREGS8:
212 		return "exregs8";
213 	case PERF_REG_CSKY_EXREGS9:
214 		return "exregs9";
215 	case PERF_REG_CSKY_EXREGS10:
216 		return "exregs10";
217 	case PERF_REG_CSKY_EXREGS11:
218 		return "exregs11";
219 	case PERF_REG_CSKY_EXREGS12:
220 		return "exregs12";
221 	case PERF_REG_CSKY_EXREGS13:
222 		return "exregs13";
223 	case PERF_REG_CSKY_EXREGS14:
224 		return "exregs14";
225 	case PERF_REG_CSKY_TLS:
226 		return "tls";
227 	case PERF_REG_CSKY_HI:
228 		return "hi";
229 	case PERF_REG_CSKY_LO:
230 		return "lo";
231 #endif
232 	default:
233 		return NULL;
234 	}
235 
236 	return NULL;
237 }
238 
239 static const char *__perf_reg_name_mips(int id)
240 {
241 	switch (id) {
242 	case PERF_REG_MIPS_PC:
243 		return "PC";
244 	case PERF_REG_MIPS_R1:
245 		return "$1";
246 	case PERF_REG_MIPS_R2:
247 		return "$2";
248 	case PERF_REG_MIPS_R3:
249 		return "$3";
250 	case PERF_REG_MIPS_R4:
251 		return "$4";
252 	case PERF_REG_MIPS_R5:
253 		return "$5";
254 	case PERF_REG_MIPS_R6:
255 		return "$6";
256 	case PERF_REG_MIPS_R7:
257 		return "$7";
258 	case PERF_REG_MIPS_R8:
259 		return "$8";
260 	case PERF_REG_MIPS_R9:
261 		return "$9";
262 	case PERF_REG_MIPS_R10:
263 		return "$10";
264 	case PERF_REG_MIPS_R11:
265 		return "$11";
266 	case PERF_REG_MIPS_R12:
267 		return "$12";
268 	case PERF_REG_MIPS_R13:
269 		return "$13";
270 	case PERF_REG_MIPS_R14:
271 		return "$14";
272 	case PERF_REG_MIPS_R15:
273 		return "$15";
274 	case PERF_REG_MIPS_R16:
275 		return "$16";
276 	case PERF_REG_MIPS_R17:
277 		return "$17";
278 	case PERF_REG_MIPS_R18:
279 		return "$18";
280 	case PERF_REG_MIPS_R19:
281 		return "$19";
282 	case PERF_REG_MIPS_R20:
283 		return "$20";
284 	case PERF_REG_MIPS_R21:
285 		return "$21";
286 	case PERF_REG_MIPS_R22:
287 		return "$22";
288 	case PERF_REG_MIPS_R23:
289 		return "$23";
290 	case PERF_REG_MIPS_R24:
291 		return "$24";
292 	case PERF_REG_MIPS_R25:
293 		return "$25";
294 	case PERF_REG_MIPS_R28:
295 		return "$28";
296 	case PERF_REG_MIPS_R29:
297 		return "$29";
298 	case PERF_REG_MIPS_R30:
299 		return "$30";
300 	case PERF_REG_MIPS_R31:
301 		return "$31";
302 	default:
303 		break;
304 	}
305 	return NULL;
306 }
307 
308 static const char *__perf_reg_name_powerpc(int id)
309 {
310 	switch (id) {
311 	case PERF_REG_POWERPC_R0:
312 		return "r0";
313 	case PERF_REG_POWERPC_R1:
314 		return "r1";
315 	case PERF_REG_POWERPC_R2:
316 		return "r2";
317 	case PERF_REG_POWERPC_R3:
318 		return "r3";
319 	case PERF_REG_POWERPC_R4:
320 		return "r4";
321 	case PERF_REG_POWERPC_R5:
322 		return "r5";
323 	case PERF_REG_POWERPC_R6:
324 		return "r6";
325 	case PERF_REG_POWERPC_R7:
326 		return "r7";
327 	case PERF_REG_POWERPC_R8:
328 		return "r8";
329 	case PERF_REG_POWERPC_R9:
330 		return "r9";
331 	case PERF_REG_POWERPC_R10:
332 		return "r10";
333 	case PERF_REG_POWERPC_R11:
334 		return "r11";
335 	case PERF_REG_POWERPC_R12:
336 		return "r12";
337 	case PERF_REG_POWERPC_R13:
338 		return "r13";
339 	case PERF_REG_POWERPC_R14:
340 		return "r14";
341 	case PERF_REG_POWERPC_R15:
342 		return "r15";
343 	case PERF_REG_POWERPC_R16:
344 		return "r16";
345 	case PERF_REG_POWERPC_R17:
346 		return "r17";
347 	case PERF_REG_POWERPC_R18:
348 		return "r18";
349 	case PERF_REG_POWERPC_R19:
350 		return "r19";
351 	case PERF_REG_POWERPC_R20:
352 		return "r20";
353 	case PERF_REG_POWERPC_R21:
354 		return "r21";
355 	case PERF_REG_POWERPC_R22:
356 		return "r22";
357 	case PERF_REG_POWERPC_R23:
358 		return "r23";
359 	case PERF_REG_POWERPC_R24:
360 		return "r24";
361 	case PERF_REG_POWERPC_R25:
362 		return "r25";
363 	case PERF_REG_POWERPC_R26:
364 		return "r26";
365 	case PERF_REG_POWERPC_R27:
366 		return "r27";
367 	case PERF_REG_POWERPC_R28:
368 		return "r28";
369 	case PERF_REG_POWERPC_R29:
370 		return "r29";
371 	case PERF_REG_POWERPC_R30:
372 		return "r30";
373 	case PERF_REG_POWERPC_R31:
374 		return "r31";
375 	case PERF_REG_POWERPC_NIP:
376 		return "nip";
377 	case PERF_REG_POWERPC_MSR:
378 		return "msr";
379 	case PERF_REG_POWERPC_ORIG_R3:
380 		return "orig_r3";
381 	case PERF_REG_POWERPC_CTR:
382 		return "ctr";
383 	case PERF_REG_POWERPC_LINK:
384 		return "link";
385 	case PERF_REG_POWERPC_XER:
386 		return "xer";
387 	case PERF_REG_POWERPC_CCR:
388 		return "ccr";
389 	case PERF_REG_POWERPC_SOFTE:
390 		return "softe";
391 	case PERF_REG_POWERPC_TRAP:
392 		return "trap";
393 	case PERF_REG_POWERPC_DAR:
394 		return "dar";
395 	case PERF_REG_POWERPC_DSISR:
396 		return "dsisr";
397 	case PERF_REG_POWERPC_SIER:
398 		return "sier";
399 	case PERF_REG_POWERPC_MMCRA:
400 		return "mmcra";
401 	case PERF_REG_POWERPC_MMCR0:
402 		return "mmcr0";
403 	case PERF_REG_POWERPC_MMCR1:
404 		return "mmcr1";
405 	case PERF_REG_POWERPC_MMCR2:
406 		return "mmcr2";
407 	case PERF_REG_POWERPC_MMCR3:
408 		return "mmcr3";
409 	case PERF_REG_POWERPC_SIER2:
410 		return "sier2";
411 	case PERF_REG_POWERPC_SIER3:
412 		return "sier3";
413 	case PERF_REG_POWERPC_PMC1:
414 		return "pmc1";
415 	case PERF_REG_POWERPC_PMC2:
416 		return "pmc2";
417 	case PERF_REG_POWERPC_PMC3:
418 		return "pmc3";
419 	case PERF_REG_POWERPC_PMC4:
420 		return "pmc4";
421 	case PERF_REG_POWERPC_PMC5:
422 		return "pmc5";
423 	case PERF_REG_POWERPC_PMC6:
424 		return "pmc6";
425 	case PERF_REG_POWERPC_SDAR:
426 		return "sdar";
427 	case PERF_REG_POWERPC_SIAR:
428 		return "siar";
429 	default:
430 		break;
431 	}
432 	return NULL;
433 }
434 
435 static const char *__perf_reg_name_riscv(int id)
436 {
437 	switch (id) {
438 	case PERF_REG_RISCV_PC:
439 		return "pc";
440 	case PERF_REG_RISCV_RA:
441 		return "ra";
442 	case PERF_REG_RISCV_SP:
443 		return "sp";
444 	case PERF_REG_RISCV_GP:
445 		return "gp";
446 	case PERF_REG_RISCV_TP:
447 		return "tp";
448 	case PERF_REG_RISCV_T0:
449 		return "t0";
450 	case PERF_REG_RISCV_T1:
451 		return "t1";
452 	case PERF_REG_RISCV_T2:
453 		return "t2";
454 	case PERF_REG_RISCV_S0:
455 		return "s0";
456 	case PERF_REG_RISCV_S1:
457 		return "s1";
458 	case PERF_REG_RISCV_A0:
459 		return "a0";
460 	case PERF_REG_RISCV_A1:
461 		return "a1";
462 	case PERF_REG_RISCV_A2:
463 		return "a2";
464 	case PERF_REG_RISCV_A3:
465 		return "a3";
466 	case PERF_REG_RISCV_A4:
467 		return "a4";
468 	case PERF_REG_RISCV_A5:
469 		return "a5";
470 	case PERF_REG_RISCV_A6:
471 		return "a6";
472 	case PERF_REG_RISCV_A7:
473 		return "a7";
474 	case PERF_REG_RISCV_S2:
475 		return "s2";
476 	case PERF_REG_RISCV_S3:
477 		return "s3";
478 	case PERF_REG_RISCV_S4:
479 		return "s4";
480 	case PERF_REG_RISCV_S5:
481 		return "s5";
482 	case PERF_REG_RISCV_S6:
483 		return "s6";
484 	case PERF_REG_RISCV_S7:
485 		return "s7";
486 	case PERF_REG_RISCV_S8:
487 		return "s8";
488 	case PERF_REG_RISCV_S9:
489 		return "s9";
490 	case PERF_REG_RISCV_S10:
491 		return "s10";
492 	case PERF_REG_RISCV_S11:
493 		return "s11";
494 	case PERF_REG_RISCV_T3:
495 		return "t3";
496 	case PERF_REG_RISCV_T4:
497 		return "t4";
498 	case PERF_REG_RISCV_T5:
499 		return "t5";
500 	case PERF_REG_RISCV_T6:
501 		return "t6";
502 	default:
503 		return NULL;
504 	}
505 
506 	return NULL;
507 }
508 
509 static const char *__perf_reg_name_s390(int id)
510 {
511 	switch (id) {
512 	case PERF_REG_S390_R0:
513 		return "R0";
514 	case PERF_REG_S390_R1:
515 		return "R1";
516 	case PERF_REG_S390_R2:
517 		return "R2";
518 	case PERF_REG_S390_R3:
519 		return "R3";
520 	case PERF_REG_S390_R4:
521 		return "R4";
522 	case PERF_REG_S390_R5:
523 		return "R5";
524 	case PERF_REG_S390_R6:
525 		return "R6";
526 	case PERF_REG_S390_R7:
527 		return "R7";
528 	case PERF_REG_S390_R8:
529 		return "R8";
530 	case PERF_REG_S390_R9:
531 		return "R9";
532 	case PERF_REG_S390_R10:
533 		return "R10";
534 	case PERF_REG_S390_R11:
535 		return "R11";
536 	case PERF_REG_S390_R12:
537 		return "R12";
538 	case PERF_REG_S390_R13:
539 		return "R13";
540 	case PERF_REG_S390_R14:
541 		return "R14";
542 	case PERF_REG_S390_R15:
543 		return "R15";
544 	case PERF_REG_S390_FP0:
545 		return "FP0";
546 	case PERF_REG_S390_FP1:
547 		return "FP1";
548 	case PERF_REG_S390_FP2:
549 		return "FP2";
550 	case PERF_REG_S390_FP3:
551 		return "FP3";
552 	case PERF_REG_S390_FP4:
553 		return "FP4";
554 	case PERF_REG_S390_FP5:
555 		return "FP5";
556 	case PERF_REG_S390_FP6:
557 		return "FP6";
558 	case PERF_REG_S390_FP7:
559 		return "FP7";
560 	case PERF_REG_S390_FP8:
561 		return "FP8";
562 	case PERF_REG_S390_FP9:
563 		return "FP9";
564 	case PERF_REG_S390_FP10:
565 		return "FP10";
566 	case PERF_REG_S390_FP11:
567 		return "FP11";
568 	case PERF_REG_S390_FP12:
569 		return "FP12";
570 	case PERF_REG_S390_FP13:
571 		return "FP13";
572 	case PERF_REG_S390_FP14:
573 		return "FP14";
574 	case PERF_REG_S390_FP15:
575 		return "FP15";
576 	case PERF_REG_S390_MASK:
577 		return "MASK";
578 	case PERF_REG_S390_PC:
579 		return "PC";
580 	default:
581 		return NULL;
582 	}
583 
584 	return NULL;
585 }
586 
587 static const char *__perf_reg_name_x86(int id)
588 {
589 	switch (id) {
590 	case PERF_REG_X86_AX:
591 		return "AX";
592 	case PERF_REG_X86_BX:
593 		return "BX";
594 	case PERF_REG_X86_CX:
595 		return "CX";
596 	case PERF_REG_X86_DX:
597 		return "DX";
598 	case PERF_REG_X86_SI:
599 		return "SI";
600 	case PERF_REG_X86_DI:
601 		return "DI";
602 	case PERF_REG_X86_BP:
603 		return "BP";
604 	case PERF_REG_X86_SP:
605 		return "SP";
606 	case PERF_REG_X86_IP:
607 		return "IP";
608 	case PERF_REG_X86_FLAGS:
609 		return "FLAGS";
610 	case PERF_REG_X86_CS:
611 		return "CS";
612 	case PERF_REG_X86_SS:
613 		return "SS";
614 	case PERF_REG_X86_DS:
615 		return "DS";
616 	case PERF_REG_X86_ES:
617 		return "ES";
618 	case PERF_REG_X86_FS:
619 		return "FS";
620 	case PERF_REG_X86_GS:
621 		return "GS";
622 	case PERF_REG_X86_R8:
623 		return "R8";
624 	case PERF_REG_X86_R9:
625 		return "R9";
626 	case PERF_REG_X86_R10:
627 		return "R10";
628 	case PERF_REG_X86_R11:
629 		return "R11";
630 	case PERF_REG_X86_R12:
631 		return "R12";
632 	case PERF_REG_X86_R13:
633 		return "R13";
634 	case PERF_REG_X86_R14:
635 		return "R14";
636 	case PERF_REG_X86_R15:
637 		return "R15";
638 
639 #define XMM(x) \
640 	case PERF_REG_X86_XMM ## x:	\
641 	case PERF_REG_X86_XMM ## x + 1:	\
642 		return "XMM" #x;
643 	XMM(0)
644 	XMM(1)
645 	XMM(2)
646 	XMM(3)
647 	XMM(4)
648 	XMM(5)
649 	XMM(6)
650 	XMM(7)
651 	XMM(8)
652 	XMM(9)
653 	XMM(10)
654 	XMM(11)
655 	XMM(12)
656 	XMM(13)
657 	XMM(14)
658 	XMM(15)
659 #undef XMM
660 	default:
661 		return NULL;
662 	}
663 
664 	return NULL;
665 }
666 
667 const char *perf_reg_name(int id, const char *arch)
668 {
669 	const char *reg_name = NULL;
670 
671 	if (!strcmp(arch, "csky"))
672 		reg_name = __perf_reg_name_csky(id);
673 	else if (!strcmp(arch, "mips"))
674 		reg_name = __perf_reg_name_mips(id);
675 	else if (!strcmp(arch, "powerpc"))
676 		reg_name = __perf_reg_name_powerpc(id);
677 	else if (!strcmp(arch, "riscv"))
678 		reg_name = __perf_reg_name_riscv(id);
679 	else if (!strcmp(arch, "s390"))
680 		reg_name = __perf_reg_name_s390(id);
681 	else if (!strcmp(arch, "x86"))
682 		reg_name = __perf_reg_name_x86(id);
683 	else if (!strcmp(arch, "arm"))
684 		reg_name = __perf_reg_name_arm(id);
685 	else if (!strcmp(arch, "arm64"))
686 		reg_name = __perf_reg_name_arm64(id);
687 
688 	return reg_name ?: "unknown";
689 }
690 
691 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
692 {
693 	int i, idx = 0;
694 	u64 mask = regs->mask;
695 
696 	if ((u64)id >= PERF_SAMPLE_REGS_CACHE_SIZE)
697 		return -EINVAL;
698 
699 	if (regs->cache_mask & (1ULL << id))
700 		goto out;
701 
702 	if (!(mask & (1ULL << id)))
703 		return -EINVAL;
704 
705 	for (i = 0; i < id; i++) {
706 		if (mask & (1ULL << i))
707 			idx++;
708 	}
709 
710 	regs->cache_mask |= (1ULL << id);
711 	regs->cache_regs[id] = regs->regs[idx];
712 
713 out:
714 	*valp = regs->cache_regs[id];
715 	return 0;
716 }
717 #endif
718