1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * Ptrace interface test helper functions
5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
8 #define __SANE_USERSPACE_TYPES__
17 #include <sys/ptrace.h>
18 #include <sys/ioctl.h>
20 #include <sys/types.h>
22 #include <sys/signal.h>
26 #include <sys/syscall.h>
27 #include <linux/elf.h>
28 #include <linux/types.h>
29 #include <linux/auxvec.h>
42 unsigned long tm_tfhar;
43 unsigned long tm_texasr;
44 unsigned long tm_tfiar;
48 #define NT_PPC_TAR 0x103
49 #define NT_PPC_PPR 0x104
50 #define NT_PPC_DSCR 0x105
51 #define NT_PPC_EBB 0x106
52 #define NT_PPC_PMU 0x107
53 #define NT_PPC_TM_CGPR 0x108
54 #define NT_PPC_TM_CFPR 0x109
55 #define NT_PPC_TM_CVMX 0x10a
56 #define NT_PPC_TM_CVSX 0x10b
57 #define NT_PPC_TM_SPR 0x10c
58 #define NT_PPC_TM_CTAR 0x10d
59 #define NT_PPC_TM_CPPR 0x10e
60 #define NT_PPC_TM_CDSCR 0x10f
63 /* Basic ptrace operations */
64 int start_trace(pid_t child)
68 ret = ptrace(PTRACE_ATTACH, child, NULL, NULL);
70 perror("ptrace(PTRACE_ATTACH) failed");
73 ret = waitpid(child, NULL, 0);
75 perror("waitpid() failed");
81 int stop_trace(pid_t child)
85 ret = ptrace(PTRACE_DETACH, child, NULL, NULL);
87 perror("ptrace(PTRACE_DETACH) failed");
93 int cont_trace(pid_t child)
97 ret = ptrace(PTRACE_CONT, child, NULL, NULL);
99 perror("ptrace(PTRACE_CONT) failed");
105 int ptrace_read_regs(pid_t child, unsigned long type, unsigned long regs[],
111 FAIL_IF(start_trace(child));
114 iov.iov_len = n * sizeof(unsigned long);
116 ret = ptrace(PTRACE_GETREGSET, child, type, &iov);
120 FAIL_IF(stop_trace(child));
125 long ptrace_write_regs(pid_t child, unsigned long type, unsigned long regs[],
131 FAIL_IF(start_trace(child));
134 iov.iov_len = n * sizeof(unsigned long);
136 ret = ptrace(PTRACE_SETREGSET, child, type, &iov);
138 FAIL_IF(stop_trace(child));
144 int show_tar_registers(pid_t child, unsigned long *out)
150 reg = malloc(sizeof(unsigned long));
152 perror("malloc() failed");
155 iov.iov_base = (u64 *) reg;
156 iov.iov_len = sizeof(unsigned long);
158 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TAR, &iov);
160 perror("ptrace(PTRACE_GETREGSET) failed");
166 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_PPR, &iov);
168 perror("ptrace(PTRACE_GETREGSET) failed");
174 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_DSCR, &iov);
176 perror("ptrace(PTRACE_GETREGSET) failed");
189 int write_tar_registers(pid_t child, unsigned long tar,
190 unsigned long ppr, unsigned long dscr)
196 reg = malloc(sizeof(unsigned long));
198 perror("malloc() failed");
202 iov.iov_base = (u64 *) reg;
203 iov.iov_len = sizeof(unsigned long);
206 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TAR, &iov);
208 perror("ptrace(PTRACE_SETREGSET) failed");
213 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_PPR, &iov);
215 perror("ptrace(PTRACE_SETREGSET) failed");
220 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_DSCR, &iov);
222 perror("ptrace(PTRACE_SETREGSET) failed");
233 int show_tm_checkpointed_state(pid_t child, unsigned long *out)
239 reg = malloc(sizeof(unsigned long));
241 perror("malloc() failed");
245 iov.iov_base = (u64 *) reg;
246 iov.iov_len = sizeof(unsigned long);
248 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CTAR, &iov);
250 perror("ptrace(PTRACE_GETREGSET) failed");
256 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CPPR, &iov);
258 perror("ptrace(PTRACE_GETREGSET) failed");
264 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CDSCR, &iov);
266 perror("ptrace(PTRACE_GETREGSET) failed");
280 int write_ckpt_tar_registers(pid_t child, unsigned long tar,
281 unsigned long ppr, unsigned long dscr)
287 reg = malloc(sizeof(unsigned long));
289 perror("malloc() failed");
293 iov.iov_base = (u64 *) reg;
294 iov.iov_len = sizeof(unsigned long);
297 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CTAR, &iov);
299 perror("ptrace(PTRACE_GETREGSET) failed");
304 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CPPR, &iov);
306 perror("ptrace(PTRACE_GETREGSET) failed");
311 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CDSCR, &iov);
313 perror("ptrace(PTRACE_GETREGSET) failed");
325 int show_fpr(pid_t child, __u64 *fpr)
327 struct fpr_regs *regs;
330 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
331 ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
333 perror("ptrace(PTRACE_GETREGSET) failed");
338 for (i = 0; i < 32; i++)
339 fpr[i] = regs->fpr[i];
344 int write_fpr(pid_t child, __u64 val)
346 struct fpr_regs *regs;
349 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
350 ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
352 perror("ptrace(PTRACE_GETREGSET) failed");
356 for (i = 0; i < 32; i++)
359 ret = ptrace(PTRACE_SETFPREGS, child, NULL, regs);
361 perror("ptrace(PTRACE_GETREGSET) failed");
367 int show_ckpt_fpr(pid_t child, __u64 *fpr)
369 struct fpr_regs *regs;
373 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
375 iov.iov_len = sizeof(struct fpr_regs);
377 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
379 perror("ptrace(PTRACE_GETREGSET) failed");
384 for (i = 0; i < 32; i++)
385 fpr[i] = regs->fpr[i];
391 int write_ckpt_fpr(pid_t child, unsigned long val)
393 struct fpr_regs *regs;
397 regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
399 iov.iov_len = sizeof(struct fpr_regs);
401 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
403 perror("ptrace(PTRACE_GETREGSET) failed");
407 for (i = 0; i < 32; i++)
410 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CFPR, &iov);
412 perror("ptrace(PTRACE_GETREGSET) failed");
419 int show_gpr(pid_t child, unsigned long *gpr)
421 struct pt_regs *regs;
424 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
426 perror("malloc() failed");
430 ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
432 perror("ptrace(PTRACE_GETREGSET) failed");
437 for (i = 14; i < 32; i++)
438 gpr[i-14] = regs->gpr[i];
444 long sys_ptrace(enum __ptrace_request request, pid_t pid, unsigned long addr, unsigned long data)
446 return syscall(__NR_ptrace, request, pid, (void *)addr, data);
449 // 33 because of FPSCR
450 #define PT_NUM_FPRS (33 * (sizeof(__u64) / sizeof(unsigned long)))
452 __u64 *peek_fprs(pid_t child)
454 unsigned long *fprs, *p, addr;
458 fprs = malloc(sizeof(unsigned long) * PT_NUM_FPRS);
460 perror("malloc() failed");
464 for (i = 0, p = fprs; i < PT_NUM_FPRS; i++, p++) {
465 addr = sizeof(unsigned long) * (PT_FPR0 + i);
466 ret = sys_ptrace(PTRACE_PEEKUSER, child, addr, (unsigned long)p);
468 perror("ptrace(PTRACE_PEEKUSR) failed");
473 addr = sizeof(unsigned long) * (PT_FPR0 + i);
474 ret = sys_ptrace(PTRACE_PEEKUSER, child, addr, (unsigned long)&addr);
476 printf("ptrace(PTRACE_PEEKUSR) succeeded unexpectedly!\n");
480 return (__u64 *)fprs;
483 int poke_fprs(pid_t child, unsigned long *fprs)
485 unsigned long *p, addr;
489 for (i = 0, p = fprs; i < PT_NUM_FPRS; i++, p++) {
490 addr = sizeof(unsigned long) * (PT_FPR0 + i);
491 ret = sys_ptrace(PTRACE_POKEUSER, child, addr, *p);
493 perror("ptrace(PTRACE_POKEUSR) failed");
498 addr = sizeof(unsigned long) * (PT_FPR0 + i);
499 ret = sys_ptrace(PTRACE_POKEUSER, child, addr, addr);
501 printf("ptrace(PTRACE_POKEUSR) succeeded unexpectedly!\n");
508 int write_gpr(pid_t child, unsigned long val)
510 struct pt_regs *regs;
513 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
515 perror("malloc() failed");
519 ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
521 perror("ptrace(PTRACE_GETREGSET) failed");
525 for (i = 14; i < 32; i++)
528 ret = ptrace(PTRACE_SETREGS, child, NULL, regs);
530 perror("ptrace(PTRACE_GETREGSET) failed");
536 int show_ckpt_gpr(pid_t child, unsigned long *gpr)
538 struct pt_regs *regs;
542 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
544 perror("malloc() failed");
548 iov.iov_base = (u64 *) regs;
549 iov.iov_len = sizeof(struct pt_regs);
551 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
553 perror("ptrace(PTRACE_GETREGSET) failed");
558 for (i = 14; i < 32; i++)
559 gpr[i-14] = regs->gpr[i];
565 int write_ckpt_gpr(pid_t child, unsigned long val)
567 struct pt_regs *regs;
571 regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
573 perror("malloc() failed\n");
576 iov.iov_base = (u64 *) regs;
577 iov.iov_len = sizeof(struct pt_regs);
579 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
581 perror("ptrace(PTRACE_GETREGSET) failed");
585 for (i = 14; i < 32; i++)
588 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov);
590 perror("ptrace(PTRACE_GETREGSET) failed");
597 int show_vmx(pid_t child, unsigned long vmx[][2])
601 ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx);
603 perror("ptrace(PTRACE_GETVRREGS) failed");
609 int show_vmx_ckpt(pid_t child, unsigned long vmx[][2])
611 unsigned long regs[34][2];
615 iov.iov_base = (u64 *) regs;
616 iov.iov_len = sizeof(regs);
617 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov);
619 perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed");
622 memcpy(vmx, regs, sizeof(regs));
627 int write_vmx(pid_t child, unsigned long vmx[][2])
631 ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx);
633 perror("ptrace(PTRACE_SETVRREGS) failed");
639 int write_vmx_ckpt(pid_t child, unsigned long vmx[][2])
641 unsigned long regs[34][2];
645 memcpy(regs, vmx, sizeof(regs));
646 iov.iov_base = (u64 *) regs;
647 iov.iov_len = sizeof(regs);
648 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov);
650 perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed");
657 int show_vsx(pid_t child, unsigned long *vsx)
661 ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx);
663 perror("ptrace(PTRACE_GETVSRREGS) failed");
669 int show_vsx_ckpt(pid_t child, unsigned long *vsx)
671 unsigned long regs[32];
675 iov.iov_base = (u64 *) regs;
676 iov.iov_len = sizeof(regs);
677 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov);
679 perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed");
682 memcpy(vsx, regs, sizeof(regs));
686 int write_vsx(pid_t child, unsigned long *vsx)
690 ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx);
692 perror("ptrace(PTRACE_SETVSRREGS) failed");
698 int write_vsx_ckpt(pid_t child, unsigned long *vsx)
700 unsigned long regs[32];
704 memcpy(regs, vsx, sizeof(regs));
705 iov.iov_base = (u64 *) regs;
706 iov.iov_len = sizeof(regs);
707 ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov);
709 perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed");
716 int show_tm_spr(pid_t child, struct tm_spr_regs *out)
718 struct tm_spr_regs *regs;
722 regs = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs));
724 perror("malloc() failed");
728 iov.iov_base = (u64 *) regs;
729 iov.iov_len = sizeof(struct tm_spr_regs);
731 ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov);
733 perror("ptrace(PTRACE_GETREGSET) failed");
738 memcpy(out, regs, sizeof(struct tm_spr_regs));
745 /* Analyse TEXASR after TM failure */
746 inline unsigned long get_tfiar(void)
750 asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_TFIAR));
754 void analyse_texasr(unsigned long texasr)
756 printf("TEXASR: %16lx\t", texasr);
758 if (texasr & TEXASR_FP)
759 printf("TEXASR_FP ");
761 if (texasr & TEXASR_DA)
762 printf("TEXASR_DA ");
764 if (texasr & TEXASR_NO)
765 printf("TEXASR_NO ");
767 if (texasr & TEXASR_FO)
768 printf("TEXASR_FO ");
770 if (texasr & TEXASR_SIC)
771 printf("TEXASR_SIC ");
773 if (texasr & TEXASR_NTC)
774 printf("TEXASR_NTC ");
776 if (texasr & TEXASR_TC)
777 printf("TEXASR_TC ");
779 if (texasr & TEXASR_TIC)
780 printf("TEXASR_TIC ");
782 if (texasr & TEXASR_IC)
783 printf("TEXASR_IC ");
785 if (texasr & TEXASR_IFC)
786 printf("TEXASR_IFC ");
788 if (texasr & TEXASR_ABT)
789 printf("TEXASR_ABT ");
791 if (texasr & TEXASR_SPD)
792 printf("TEXASR_SPD ");
794 if (texasr & TEXASR_HV)
795 printf("TEXASR_HV ");
797 if (texasr & TEXASR_PR)
798 printf("TEXASR_PR ");
800 if (texasr & TEXASR_FS)
801 printf("TEXASR_FS ");
803 if (texasr & TEXASR_TE)
804 printf("TEXASR_TE ");
806 if (texasr & TEXASR_ROT)
807 printf("TEXASR_ROT ");
809 printf("TFIAR :%lx\n", get_tfiar());
812 void store_gpr(unsigned long *addr);