Linux-libre 5.7.3-gnu
[librecmc/linux-libre.git] / tools / testing / selftests / powerpc / ptrace / ptrace.h
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Ptrace interface test helper functions
4  *
5  * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
6  */
7 #include <inttypes.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <malloc.h>
12 #include <errno.h>
13 #include <time.h>
14 #include <sys/ptrace.h>
15 #include <sys/ioctl.h>
16 #include <sys/uio.h>
17 #include <sys/types.h>
18 #include <sys/wait.h>
19 #include <sys/signal.h>
20 #include <sys/ipc.h>
21 #include <sys/shm.h>
22 #include <sys/user.h>
23 #include <linux/elf.h>
24 #include <linux/types.h>
25 #include <linux/auxvec.h>
26 #include "reg.h"
27 #include "utils.h"
28
29 #define TEST_PASS 0
30 #define TEST_FAIL 1
31
32 struct fpr_regs {
33         unsigned long fpr[32];
34         unsigned long fpscr;
35 };
36
37 struct tm_spr_regs {
38         unsigned long tm_tfhar;
39         unsigned long tm_texasr;
40         unsigned long tm_tfiar;
41 };
42
43 #ifndef NT_PPC_TAR
44 #define NT_PPC_TAR      0x103
45 #define NT_PPC_PPR      0x104
46 #define NT_PPC_DSCR     0x105
47 #define NT_PPC_EBB      0x106
48 #define NT_PPC_PMU      0x107
49 #define NT_PPC_TM_CGPR  0x108
50 #define NT_PPC_TM_CFPR  0x109
51 #define NT_PPC_TM_CVMX  0x10a
52 #define NT_PPC_TM_CVSX  0x10b
53 #define NT_PPC_TM_SPR   0x10c
54 #define NT_PPC_TM_CTAR  0x10d
55 #define NT_PPC_TM_CPPR  0x10e
56 #define NT_PPC_TM_CDSCR 0x10f
57 #endif
58
59 /* Basic ptrace operations */
60 int start_trace(pid_t child)
61 {
62         int ret;
63
64         ret = ptrace(PTRACE_ATTACH, child, NULL, NULL);
65         if (ret) {
66                 perror("ptrace(PTRACE_ATTACH) failed");
67                 return TEST_FAIL;
68         }
69         ret = waitpid(child, NULL, 0);
70         if (ret != child) {
71                 perror("waitpid() failed");
72                 return TEST_FAIL;
73         }
74         return TEST_PASS;
75 }
76
77 int stop_trace(pid_t child)
78 {
79         int ret;
80
81         ret = ptrace(PTRACE_DETACH, child, NULL, NULL);
82         if (ret) {
83                 perror("ptrace(PTRACE_DETACH) failed");
84                 return TEST_FAIL;
85         }
86         return TEST_PASS;
87 }
88
89 int cont_trace(pid_t child)
90 {
91         int ret;
92
93         ret = ptrace(PTRACE_CONT, child, NULL, NULL);
94         if (ret) {
95                 perror("ptrace(PTRACE_CONT) failed");
96                 return TEST_FAIL;
97         }
98         return TEST_PASS;
99 }
100
101 int ptrace_read_regs(pid_t child, unsigned long type, unsigned long regs[],
102                      int n)
103 {
104         struct iovec iov;
105         long ret;
106
107         FAIL_IF(start_trace(child));
108
109         iov.iov_base = regs;
110         iov.iov_len = n * sizeof(unsigned long);
111
112         ret = ptrace(PTRACE_GETREGSET, child, type, &iov);
113         if (ret)
114                 return ret;
115
116         FAIL_IF(stop_trace(child));
117
118         return TEST_PASS;
119 }
120
121 long ptrace_write_regs(pid_t child, unsigned long type, unsigned long regs[],
122                        int n)
123 {
124         struct iovec iov;
125         long ret;
126
127         FAIL_IF(start_trace(child));
128
129         iov.iov_base = regs;
130         iov.iov_len = n * sizeof(unsigned long);
131
132         ret = ptrace(PTRACE_SETREGSET, child, type, &iov);
133
134         FAIL_IF(stop_trace(child));
135
136         return ret;
137 }
138
139 /* TAR, PPR, DSCR */
140 int show_tar_registers(pid_t child, unsigned long *out)
141 {
142         struct iovec iov;
143         unsigned long *reg;
144         int ret;
145
146         reg = malloc(sizeof(unsigned long));
147         if (!reg) {
148                 perror("malloc() failed");
149                 return TEST_FAIL;
150         }
151         iov.iov_base = (u64 *) reg;
152         iov.iov_len = sizeof(unsigned long);
153
154         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TAR, &iov);
155         if (ret) {
156                 perror("ptrace(PTRACE_GETREGSET) failed");
157                 goto fail;
158         }
159         if (out)
160                 out[0] = *reg;
161
162         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_PPR, &iov);
163         if (ret) {
164                 perror("ptrace(PTRACE_GETREGSET) failed");
165                 goto fail;
166         }
167         if (out)
168                 out[1] = *reg;
169
170         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_DSCR, &iov);
171         if (ret) {
172                 perror("ptrace(PTRACE_GETREGSET) failed");
173                 goto fail;
174         }
175         if (out)
176                 out[2] = *reg;
177
178         free(reg);
179         return TEST_PASS;
180 fail:
181         free(reg);
182         return TEST_FAIL;
183 }
184
185 int write_tar_registers(pid_t child, unsigned long tar,
186                 unsigned long ppr, unsigned long dscr)
187 {
188         struct iovec iov;
189         unsigned long *reg;
190         int ret;
191
192         reg = malloc(sizeof(unsigned long));
193         if (!reg) {
194                 perror("malloc() failed");
195                 return TEST_FAIL;
196         }
197
198         iov.iov_base = (u64 *) reg;
199         iov.iov_len = sizeof(unsigned long);
200
201         *reg = tar;
202         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TAR, &iov);
203         if (ret) {
204                 perror("ptrace(PTRACE_SETREGSET) failed");
205                 goto fail;
206         }
207
208         *reg = ppr;
209         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_PPR, &iov);
210         if (ret) {
211                 perror("ptrace(PTRACE_SETREGSET) failed");
212                 goto fail;
213         }
214
215         *reg = dscr;
216         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_DSCR, &iov);
217         if (ret) {
218                 perror("ptrace(PTRACE_SETREGSET) failed");
219                 goto fail;
220         }
221
222         free(reg);
223         return TEST_PASS;
224 fail:
225         free(reg);
226         return TEST_FAIL;
227 }
228
229 int show_tm_checkpointed_state(pid_t child, unsigned long *out)
230 {
231         struct iovec iov;
232         unsigned long *reg;
233         int ret;
234
235         reg = malloc(sizeof(unsigned long));
236         if (!reg) {
237                 perror("malloc() failed");
238                 return TEST_FAIL;
239         }
240
241         iov.iov_base = (u64 *) reg;
242         iov.iov_len = sizeof(unsigned long);
243
244         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CTAR, &iov);
245         if (ret) {
246                 perror("ptrace(PTRACE_GETREGSET) failed");
247                 goto fail;
248         }
249         if (out)
250                 out[0] = *reg;
251
252         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CPPR, &iov);
253         if (ret) {
254                 perror("ptrace(PTRACE_GETREGSET) failed");
255                 goto fail;
256         }
257         if (out)
258                 out[1] = *reg;
259
260         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CDSCR, &iov);
261         if (ret) {
262                 perror("ptrace(PTRACE_GETREGSET) failed");
263                 goto fail;
264         }
265         if (out)
266                 out[2] = *reg;
267
268         free(reg);
269         return TEST_PASS;
270
271 fail:
272         free(reg);
273         return TEST_FAIL;
274 }
275
276 int write_ckpt_tar_registers(pid_t child, unsigned long tar,
277                 unsigned long ppr, unsigned long dscr)
278 {
279         struct iovec iov;
280         unsigned long *reg;
281         int ret;
282
283         reg = malloc(sizeof(unsigned long));
284         if (!reg) {
285                 perror("malloc() failed");
286                 return TEST_FAIL;
287         }
288
289         iov.iov_base = (u64 *) reg;
290         iov.iov_len = sizeof(unsigned long);
291
292         *reg = tar;
293         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CTAR, &iov);
294         if (ret) {
295                 perror("ptrace(PTRACE_GETREGSET) failed");
296                 goto fail;
297         }
298
299         *reg = ppr;
300         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CPPR, &iov);
301         if (ret) {
302                 perror("ptrace(PTRACE_GETREGSET) failed");
303                 goto fail;
304         }
305
306         *reg = dscr;
307         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CDSCR, &iov);
308         if (ret) {
309                 perror("ptrace(PTRACE_GETREGSET) failed");
310                 goto fail;
311         }
312
313         free(reg);
314         return TEST_PASS;
315 fail:
316         free(reg);
317         return TEST_FAIL;
318 }
319
320 /* FPR */
321 int show_fpr(pid_t child, unsigned long *fpr)
322 {
323         struct fpr_regs *regs;
324         int ret, i;
325
326         regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
327         ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
328         if (ret) {
329                 perror("ptrace(PTRACE_GETREGSET) failed");
330                 return TEST_FAIL;
331         }
332
333         if (fpr) {
334                 for (i = 0; i < 32; i++)
335                         fpr[i] = regs->fpr[i];
336         }
337         return TEST_PASS;
338 }
339
340 int write_fpr(pid_t child, unsigned long val)
341 {
342         struct fpr_regs *regs;
343         int ret, i;
344
345         regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
346         ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
347         if (ret) {
348                 perror("ptrace(PTRACE_GETREGSET) failed");
349                 return TEST_FAIL;
350         }
351
352         for (i = 0; i < 32; i++)
353                 regs->fpr[i] = val;
354
355         ret = ptrace(PTRACE_SETFPREGS, child, NULL, regs);
356         if (ret) {
357                 perror("ptrace(PTRACE_GETREGSET) failed");
358                 return TEST_FAIL;
359         }
360         return TEST_PASS;
361 }
362
363 int show_ckpt_fpr(pid_t child, unsigned long *fpr)
364 {
365         struct fpr_regs *regs;
366         struct iovec iov;
367         int ret, i;
368
369         regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
370         iov.iov_base = regs;
371         iov.iov_len = sizeof(struct fpr_regs);
372
373         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
374         if (ret) {
375                 perror("ptrace(PTRACE_GETREGSET) failed");
376                 return TEST_FAIL;
377         }
378
379         if (fpr) {
380                 for (i = 0; i < 32; i++)
381                         fpr[i] = regs->fpr[i];
382         }
383
384         return TEST_PASS;
385 }
386
387 int write_ckpt_fpr(pid_t child, unsigned long val)
388 {
389         struct fpr_regs *regs;
390         struct iovec iov;
391         int ret, i;
392
393         regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
394         iov.iov_base = regs;
395         iov.iov_len = sizeof(struct fpr_regs);
396
397         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
398         if (ret) {
399                 perror("ptrace(PTRACE_GETREGSET) failed");
400                 return TEST_FAIL;
401         }
402
403         for (i = 0; i < 32; i++)
404                 regs->fpr[i] = val;
405
406         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CFPR, &iov);
407         if (ret) {
408                 perror("ptrace(PTRACE_GETREGSET) failed");
409                 return TEST_FAIL;
410         }
411         return TEST_PASS;
412 }
413
414 /* GPR */
415 int show_gpr(pid_t child, unsigned long *gpr)
416 {
417         struct pt_regs *regs;
418         int ret, i;
419
420         regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
421         if (!regs) {
422                 perror("malloc() failed");
423                 return TEST_FAIL;
424         }
425
426         ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
427         if (ret) {
428                 perror("ptrace(PTRACE_GETREGSET) failed");
429                 return TEST_FAIL;
430         }
431
432         if (gpr) {
433                 for (i = 14; i < 32; i++)
434                         gpr[i-14] = regs->gpr[i];
435         }
436
437         return TEST_PASS;
438 }
439
440 int write_gpr(pid_t child, unsigned long val)
441 {
442         struct pt_regs *regs;
443         int i, ret;
444
445         regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
446         if (!regs) {
447                 perror("malloc() failed");
448                 return TEST_FAIL;
449         }
450
451         ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
452         if (ret) {
453                 perror("ptrace(PTRACE_GETREGSET) failed");
454                 return TEST_FAIL;
455         }
456
457         for (i = 14; i < 32; i++)
458                 regs->gpr[i] = val;
459
460         ret = ptrace(PTRACE_SETREGS, child, NULL, regs);
461         if (ret) {
462                 perror("ptrace(PTRACE_GETREGSET) failed");
463                 return TEST_FAIL;
464         }
465         return TEST_PASS;
466 }
467
468 int show_ckpt_gpr(pid_t child, unsigned long *gpr)
469 {
470         struct pt_regs *regs;
471         struct iovec iov;
472         int ret, i;
473
474         regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
475         if (!regs) {
476                 perror("malloc() failed");
477                 return TEST_FAIL;
478         }
479
480         iov.iov_base = (u64 *) regs;
481         iov.iov_len = sizeof(struct pt_regs);
482
483         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
484         if (ret) {
485                 perror("ptrace(PTRACE_GETREGSET) failed");
486                 return TEST_FAIL;
487         }
488
489         if (gpr) {
490                 for (i = 14; i < 32; i++)
491                         gpr[i-14] = regs->gpr[i];
492         }
493
494         return TEST_PASS;
495 }
496
497 int write_ckpt_gpr(pid_t child, unsigned long val)
498 {
499         struct pt_regs *regs;
500         struct iovec iov;
501         int ret, i;
502
503         regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
504         if (!regs) {
505                 perror("malloc() failed\n");
506                 return TEST_FAIL;
507         }
508         iov.iov_base = (u64 *) regs;
509         iov.iov_len = sizeof(struct pt_regs);
510
511         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
512         if (ret) {
513                 perror("ptrace(PTRACE_GETREGSET) failed");
514                 return TEST_FAIL;
515         }
516
517         for (i = 14; i < 32; i++)
518                 regs->gpr[i] = val;
519
520         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov);
521         if (ret) {
522                 perror("ptrace(PTRACE_GETREGSET) failed");
523                 return TEST_FAIL;
524         }
525         return TEST_PASS;
526 }
527
528 /* VMX */
529 int show_vmx(pid_t child, unsigned long vmx[][2])
530 {
531         int ret;
532
533         ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx);
534         if (ret) {
535                 perror("ptrace(PTRACE_GETVRREGS) failed");
536                 return TEST_FAIL;
537         }
538         return TEST_PASS;
539 }
540
541 int show_vmx_ckpt(pid_t child, unsigned long vmx[][2])
542 {
543         unsigned long regs[34][2];
544         struct iovec iov;
545         int ret;
546
547         iov.iov_base = (u64 *) regs;
548         iov.iov_len = sizeof(regs);
549         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov);
550         if (ret) {
551                 perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed");
552                 return TEST_FAIL;
553         }
554         memcpy(vmx, regs, sizeof(regs));
555         return TEST_PASS;
556 }
557
558
559 int write_vmx(pid_t child, unsigned long vmx[][2])
560 {
561         int ret;
562
563         ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx);
564         if (ret) {
565                 perror("ptrace(PTRACE_SETVRREGS) failed");
566                 return TEST_FAIL;
567         }
568         return TEST_PASS;
569 }
570
571 int write_vmx_ckpt(pid_t child, unsigned long vmx[][2])
572 {
573         unsigned long regs[34][2];
574         struct iovec iov;
575         int ret;
576
577         memcpy(regs, vmx, sizeof(regs));
578         iov.iov_base = (u64 *) regs;
579         iov.iov_len = sizeof(regs);
580         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov);
581         if (ret) {
582                 perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed");
583                 return TEST_FAIL;
584         }
585         return TEST_PASS;
586 }
587
588 /* VSX */
589 int show_vsx(pid_t child, unsigned long *vsx)
590 {
591         int ret;
592
593         ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx);
594         if (ret) {
595                 perror("ptrace(PTRACE_GETVSRREGS) failed");
596                 return TEST_FAIL;
597         }
598         return TEST_PASS;
599 }
600
601 int show_vsx_ckpt(pid_t child, unsigned long *vsx)
602 {
603         unsigned long regs[32];
604         struct iovec iov;
605         int ret;
606
607         iov.iov_base = (u64 *) regs;
608         iov.iov_len = sizeof(regs);
609         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov);
610         if (ret) {
611                 perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed");
612                 return TEST_FAIL;
613         }
614         memcpy(vsx, regs, sizeof(regs));
615         return TEST_PASS;
616 }
617
618 int write_vsx(pid_t child, unsigned long *vsx)
619 {
620         int ret;
621
622         ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx);
623         if (ret) {
624                 perror("ptrace(PTRACE_SETVSRREGS) failed");
625                 return TEST_FAIL;
626         }
627         return TEST_PASS;
628 }
629
630 int write_vsx_ckpt(pid_t child, unsigned long *vsx)
631 {
632         unsigned long regs[32];
633         struct iovec iov;
634         int ret;
635
636         memcpy(regs, vsx, sizeof(regs));
637         iov.iov_base = (u64 *) regs;
638         iov.iov_len = sizeof(regs);
639         ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov);
640         if (ret) {
641                 perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed");
642                 return TEST_FAIL;
643         }
644         return TEST_PASS;
645 }
646
647 /* TM SPR */
648 int show_tm_spr(pid_t child, struct tm_spr_regs *out)
649 {
650         struct tm_spr_regs *regs;
651         struct iovec iov;
652         int ret;
653
654         regs = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs));
655         if (!regs) {
656                 perror("malloc() failed");
657                 return TEST_FAIL;
658         }
659
660         iov.iov_base = (u64 *) regs;
661         iov.iov_len = sizeof(struct tm_spr_regs);
662
663         ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov);
664         if (ret) {
665                 perror("ptrace(PTRACE_GETREGSET) failed");
666                 return TEST_FAIL;
667         }
668
669         if (out)
670                 memcpy(out, regs, sizeof(struct tm_spr_regs));
671
672         return TEST_PASS;
673 }
674
675
676
677 /* Analyse TEXASR after TM failure */
678 inline unsigned long get_tfiar(void)
679 {
680         unsigned long ret;
681
682         asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_TFIAR));
683         return ret;
684 }
685
686 void analyse_texasr(unsigned long texasr)
687 {
688         printf("TEXASR: %16lx\t", texasr);
689
690         if (texasr & TEXASR_FP)
691                 printf("TEXASR_FP  ");
692
693         if (texasr & TEXASR_DA)
694                 printf("TEXASR_DA  ");
695
696         if (texasr & TEXASR_NO)
697                 printf("TEXASR_NO  ");
698
699         if (texasr & TEXASR_FO)
700                 printf("TEXASR_FO  ");
701
702         if (texasr & TEXASR_SIC)
703                 printf("TEXASR_SIC  ");
704
705         if (texasr & TEXASR_NTC)
706                 printf("TEXASR_NTC  ");
707
708         if (texasr & TEXASR_TC)
709                 printf("TEXASR_TC  ");
710
711         if (texasr & TEXASR_TIC)
712                 printf("TEXASR_TIC  ");
713
714         if (texasr & TEXASR_IC)
715                 printf("TEXASR_IC  ");
716
717         if (texasr & TEXASR_IFC)
718                 printf("TEXASR_IFC  ");
719
720         if (texasr & TEXASR_ABT)
721                 printf("TEXASR_ABT  ");
722
723         if (texasr & TEXASR_SPD)
724                 printf("TEXASR_SPD  ");
725
726         if (texasr & TEXASR_HV)
727                 printf("TEXASR_HV  ");
728
729         if (texasr & TEXASR_PR)
730                 printf("TEXASR_PR  ");
731
732         if (texasr & TEXASR_FS)
733                 printf("TEXASR_FS  ");
734
735         if (texasr & TEXASR_TE)
736                 printf("TEXASR_TE  ");
737
738         if (texasr & TEXASR_ROT)
739                 printf("TEXASR_ROT  ");
740
741         printf("TFIAR :%lx\n", get_tfiar());
742 }
743
744 void store_gpr(unsigned long *addr);
745 void store_fpr(float *addr);