1
2
3
4
5
6
7
8
9
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
36struct fpr_regs {
37 unsigned long fpr[32];
38 unsigned long fpscr;
39};
40
41struct 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
64int 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
81int 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
93int 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
106int 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;
146fail:
147 free(reg);
148 return TEST_FAIL;
149}
150
151int 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;
190fail:
191 free(reg);
192 return TEST_FAIL;
193}
194
195int 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
237fail:
238 free(reg);
239 return TEST_FAIL;
240}
241
242int 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;
281fail:
282 free(reg);
283 return TEST_FAIL;
284}
285
286
287int 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
306int 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
329int 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
353int 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
381int 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
406int 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
434int 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
463int 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
495int 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
507int 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
525int 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
537int 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
555int 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
567int 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
584int 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
596int 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
614int 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
644inline 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
652void 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
710void store_gpr(unsigned long *addr);
711void store_fpr(float *addr);
712