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