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 
8 #define __SANE_USERSPACE_TYPES__
9 
10 #include <inttypes.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <malloc.h>
15 #include <errno.h>
16 #include <time.h>
17 #include <sys/ptrace.h>
18 #include <sys/ioctl.h>
19 #include <sys/uio.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22 #include <sys/signal.h>
23 #include <sys/ipc.h>
24 #include <sys/shm.h>
25 #include <sys/user.h>
26 #include <sys/syscall.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 	__u64 fpr[32];
38 	__u64 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, __u64 *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, __u64 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, __u64 *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 long sys_ptrace(enum __ptrace_request request, pid_t pid, unsigned long addr, unsigned long data)
445 {
446 	return syscall(__NR_ptrace, request, pid, (void *)addr, data);
447 }
448 
449 // 33 because of FPSCR
450 #define PT_NUM_FPRS	(33 * (sizeof(__u64) / sizeof(unsigned long)))
451 
452 __u64 *peek_fprs(pid_t child)
453 {
454 	unsigned long *fprs, *p, addr;
455 	long ret;
456 	int i;
457 
458 	fprs = malloc(sizeof(unsigned long) * PT_NUM_FPRS);
459 	if (!fprs) {
460 		perror("malloc() failed");
461 		return NULL;
462 	}
463 
464 	for (i = 0, p = fprs; i < PT_NUM_FPRS; i++, p++) {
465 		addr = sizeof(unsigned long) * (PT_FPR0 + i);
466 		ret = sys_ptrace(PTRACE_PEEKUSER, child, addr, (unsigned long)p);
467 		if (ret) {
468 			perror("ptrace(PTRACE_PEEKUSR) failed");
469 			return NULL;
470 		}
471 	}
472 
473 	addr = sizeof(unsigned long) * (PT_FPR0 + i);
474 	ret = sys_ptrace(PTRACE_PEEKUSER, child, addr, (unsigned long)&addr);
475 	if (!ret) {
476 		printf("ptrace(PTRACE_PEEKUSR) succeeded unexpectedly!\n");
477 		return NULL;
478 	}
479 
480 	return (__u64 *)fprs;
481 }
482 
483 int poke_fprs(pid_t child, unsigned long *fprs)
484 {
485 	unsigned long *p, addr;
486 	long ret;
487 	int i;
488 
489 	for (i = 0, p = fprs; i < PT_NUM_FPRS; i++, p++) {
490 		addr = sizeof(unsigned long) * (PT_FPR0 + i);
491 		ret = sys_ptrace(PTRACE_POKEUSER, child, addr, *p);
492 		if (ret) {
493 			perror("ptrace(PTRACE_POKEUSR) failed");
494 			return -1;
495 		}
496 	}
497 
498 	addr = sizeof(unsigned long) * (PT_FPR0 + i);
499 	ret = sys_ptrace(PTRACE_POKEUSER, child, addr, addr);
500 	if (!ret) {
501 		printf("ptrace(PTRACE_POKEUSR) succeeded unexpectedly!\n");
502 		return -1;
503 	}
504 
505 	return 0;
506 }
507 
508 int write_gpr(pid_t child, unsigned long val)
509 {
510 	struct pt_regs *regs;
511 	int i, ret;
512 
513 	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
514 	if (!regs) {
515 		perror("malloc() failed");
516 		return TEST_FAIL;
517 	}
518 
519 	ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
520 	if (ret) {
521 		perror("ptrace(PTRACE_GETREGSET) failed");
522 		return TEST_FAIL;
523 	}
524 
525 	for (i = 14; i < 32; i++)
526 		regs->gpr[i] = val;
527 
528 	ret = ptrace(PTRACE_SETREGS, child, NULL, regs);
529 	if (ret) {
530 		perror("ptrace(PTRACE_GETREGSET) failed");
531 		return TEST_FAIL;
532 	}
533 	return TEST_PASS;
534 }
535 
536 int show_ckpt_gpr(pid_t child, unsigned long *gpr)
537 {
538 	struct pt_regs *regs;
539 	struct iovec iov;
540 	int ret, i;
541 
542 	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
543 	if (!regs) {
544 		perror("malloc() failed");
545 		return TEST_FAIL;
546 	}
547 
548 	iov.iov_base = (u64 *) regs;
549 	iov.iov_len = sizeof(struct pt_regs);
550 
551 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
552 	if (ret) {
553 		perror("ptrace(PTRACE_GETREGSET) failed");
554 		return TEST_FAIL;
555 	}
556 
557 	if (gpr) {
558 		for (i = 14; i < 32; i++)
559 			gpr[i-14] = regs->gpr[i];
560 	}
561 
562 	return TEST_PASS;
563 }
564 
565 int write_ckpt_gpr(pid_t child, unsigned long val)
566 {
567 	struct pt_regs *regs;
568 	struct iovec iov;
569 	int ret, i;
570 
571 	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
572 	if (!regs) {
573 		perror("malloc() failed\n");
574 		return TEST_FAIL;
575 	}
576 	iov.iov_base = (u64 *) regs;
577 	iov.iov_len = sizeof(struct pt_regs);
578 
579 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
580 	if (ret) {
581 		perror("ptrace(PTRACE_GETREGSET) failed");
582 		return TEST_FAIL;
583 	}
584 
585 	for (i = 14; i < 32; i++)
586 		regs->gpr[i] = val;
587 
588 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov);
589 	if (ret) {
590 		perror("ptrace(PTRACE_GETREGSET) failed");
591 		return TEST_FAIL;
592 	}
593 	return TEST_PASS;
594 }
595 
596 /* VMX */
597 int show_vmx(pid_t child, unsigned long vmx[][2])
598 {
599 	int ret;
600 
601 	ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx);
602 	if (ret) {
603 		perror("ptrace(PTRACE_GETVRREGS) failed");
604 		return TEST_FAIL;
605 	}
606 	return TEST_PASS;
607 }
608 
609 int show_vmx_ckpt(pid_t child, unsigned long vmx[][2])
610 {
611 	unsigned long regs[34][2];
612 	struct iovec iov;
613 	int ret;
614 
615 	iov.iov_base = (u64 *) regs;
616 	iov.iov_len = sizeof(regs);
617 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov);
618 	if (ret) {
619 		perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed");
620 		return TEST_FAIL;
621 	}
622 	memcpy(vmx, regs, sizeof(regs));
623 	return TEST_PASS;
624 }
625 
626 
627 int write_vmx(pid_t child, unsigned long vmx[][2])
628 {
629 	int ret;
630 
631 	ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx);
632 	if (ret) {
633 		perror("ptrace(PTRACE_SETVRREGS) failed");
634 		return TEST_FAIL;
635 	}
636 	return TEST_PASS;
637 }
638 
639 int write_vmx_ckpt(pid_t child, unsigned long vmx[][2])
640 {
641 	unsigned long regs[34][2];
642 	struct iovec iov;
643 	int ret;
644 
645 	memcpy(regs, vmx, sizeof(regs));
646 	iov.iov_base = (u64 *) regs;
647 	iov.iov_len = sizeof(regs);
648 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov);
649 	if (ret) {
650 		perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed");
651 		return TEST_FAIL;
652 	}
653 	return TEST_PASS;
654 }
655 
656 /* VSX */
657 int show_vsx(pid_t child, unsigned long *vsx)
658 {
659 	int ret;
660 
661 	ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx);
662 	if (ret) {
663 		perror("ptrace(PTRACE_GETVSRREGS) failed");
664 		return TEST_FAIL;
665 	}
666 	return TEST_PASS;
667 }
668 
669 int show_vsx_ckpt(pid_t child, unsigned long *vsx)
670 {
671 	unsigned long regs[32];
672 	struct iovec iov;
673 	int ret;
674 
675 	iov.iov_base = (u64 *) regs;
676 	iov.iov_len = sizeof(regs);
677 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov);
678 	if (ret) {
679 		perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed");
680 		return TEST_FAIL;
681 	}
682 	memcpy(vsx, regs, sizeof(regs));
683 	return TEST_PASS;
684 }
685 
686 int write_vsx(pid_t child, unsigned long *vsx)
687 {
688 	int ret;
689 
690 	ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx);
691 	if (ret) {
692 		perror("ptrace(PTRACE_SETVSRREGS) failed");
693 		return TEST_FAIL;
694 	}
695 	return TEST_PASS;
696 }
697 
698 int write_vsx_ckpt(pid_t child, unsigned long *vsx)
699 {
700 	unsigned long regs[32];
701 	struct iovec iov;
702 	int ret;
703 
704 	memcpy(regs, vsx, sizeof(regs));
705 	iov.iov_base = (u64 *) regs;
706 	iov.iov_len = sizeof(regs);
707 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov);
708 	if (ret) {
709 		perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed");
710 		return TEST_FAIL;
711 	}
712 	return TEST_PASS;
713 }
714 
715 /* TM SPR */
716 int show_tm_spr(pid_t child, struct tm_spr_regs *out)
717 {
718 	struct tm_spr_regs *regs;
719 	struct iovec iov;
720 	int ret;
721 
722 	regs = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs));
723 	if (!regs) {
724 		perror("malloc() failed");
725 		return TEST_FAIL;
726 	}
727 
728 	iov.iov_base = (u64 *) regs;
729 	iov.iov_len = sizeof(struct tm_spr_regs);
730 
731 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov);
732 	if (ret) {
733 		perror("ptrace(PTRACE_GETREGSET) failed");
734 		return TEST_FAIL;
735 	}
736 
737 	if (out)
738 		memcpy(out, regs, sizeof(struct tm_spr_regs));
739 
740 	return TEST_PASS;
741 }
742 
743 
744 
745 /* Analyse TEXASR after TM failure */
746 inline unsigned long get_tfiar(void)
747 {
748 	unsigned long ret;
749 
750 	asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_TFIAR));
751 	return ret;
752 }
753 
754 void analyse_texasr(unsigned long texasr)
755 {
756 	printf("TEXASR: %16lx\t", texasr);
757 
758 	if (texasr & TEXASR_FP)
759 		printf("TEXASR_FP  ");
760 
761 	if (texasr & TEXASR_DA)
762 		printf("TEXASR_DA  ");
763 
764 	if (texasr & TEXASR_NO)
765 		printf("TEXASR_NO  ");
766 
767 	if (texasr & TEXASR_FO)
768 		printf("TEXASR_FO  ");
769 
770 	if (texasr & TEXASR_SIC)
771 		printf("TEXASR_SIC  ");
772 
773 	if (texasr & TEXASR_NTC)
774 		printf("TEXASR_NTC  ");
775 
776 	if (texasr & TEXASR_TC)
777 		printf("TEXASR_TC  ");
778 
779 	if (texasr & TEXASR_TIC)
780 		printf("TEXASR_TIC  ");
781 
782 	if (texasr & TEXASR_IC)
783 		printf("TEXASR_IC  ");
784 
785 	if (texasr & TEXASR_IFC)
786 		printf("TEXASR_IFC  ");
787 
788 	if (texasr & TEXASR_ABT)
789 		printf("TEXASR_ABT  ");
790 
791 	if (texasr & TEXASR_SPD)
792 		printf("TEXASR_SPD  ");
793 
794 	if (texasr & TEXASR_HV)
795 		printf("TEXASR_HV  ");
796 
797 	if (texasr & TEXASR_PR)
798 		printf("TEXASR_PR  ");
799 
800 	if (texasr & TEXASR_FS)
801 		printf("TEXASR_FS  ");
802 
803 	if (texasr & TEXASR_TE)
804 		printf("TEXASR_TE  ");
805 
806 	if (texasr & TEXASR_ROT)
807 		printf("TEXASR_ROT  ");
808 
809 	printf("TFIAR :%lx\n", get_tfiar());
810 }
811 
812 void store_gpr(unsigned long *addr);
813