]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - tools/testing/selftests/powerpc/ptrace/ptrace.h
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152
[mirror_ubuntu-focal-kernel.git] / tools / testing / selftests / powerpc / ptrace / ptrace.h
CommitLineData
2874c5fd 1/* SPDX-License-Identifier: GPL-2.0-or-later */
f666ad41
AK
2/*
3 * Ptrace interface test helper functions
4 *
5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
f666ad41
AK
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
32struct fpr_regs {
33 unsigned long fpr[32];
34 unsigned long fpscr;
35};
36
5bdac52f
AK
37struct tm_spr_regs {
38 unsigned long tm_tfhar;
39 unsigned long tm_texasr;
40 unsigned long tm_tfiar;
41};
f666ad41
AK
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 */
60int 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
77int 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
89int 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
1f7256e7
TJB
101int 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
121long 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
254dae59
AK
139/* TAR, PPR, DSCR */
140int 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;
180fail:
181 free(reg);
182 return TEST_FAIL;
183}
184
185int 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;
224fail:
225 free(reg);
226 return TEST_FAIL;
227}
228
229int 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
271fail:
272 free(reg);
273 return TEST_FAIL;
274}
275
276int 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;
315fail:
316 free(reg);
317 return TEST_FAIL;
318}
319
f666ad41
AK
320/* FPR */
321int 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
340int 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
363int 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
387int 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 */
415int 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
440int 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
468int 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
497int 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
0da535c0
AK
528/* VMX */
529int 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
541int 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
559int 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
571int 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 */
589int 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
601int 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
618int 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
630int 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
5bdac52f
AK
647/* TM SPR */
648int 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
f666ad41
AK
677/* Analyse TEXASR after TM failure */
678inline 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
686void 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
744void store_gpr(unsigned long *addr);
745void store_fpr(float *addr);