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