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