Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/powerpc: Add ptrace tests for GPR/FPR registers

This patch adds ptrace interface test for GPR/FPR registers.
This adds ptrace interface based helper functions related to
GPR/FPR access and some assembly helper functions related to
GPR/FPR registers.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Signed-off-by: Simon Guo <wei.guo.simon@gmail.com>
[mpe: Add #defines for the new note types when headers don't define them]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Anshuman Khandual and committed by
Michael Ellerman
f666ad41 15ec3997

+781 -1
+2 -1
tools/testing/selftests/powerpc/Makefile
··· 26 26 syscalls \ 27 27 tm \ 28 28 vphn \ 29 - math 29 + math \ 30 + ptrace 30 31 31 32 endif 32 33
+61
tools/testing/selftests/powerpc/include/reg.h
··· 81 81 #define STXVD2X(xs, ra, rb) .long (0x7c000798 | VSX_XX1((xs), (ra), (rb))) 82 82 #define LXVD2X(xs, ra, rb) .long (0x7c000698 | VSX_XX1((xs), (ra), (rb))) 83 83 84 + #define ASM_LOAD_GPR_IMMED(_asm_symbol_name_immed) \ 85 + "li 14, %[" #_asm_symbol_name_immed "];" \ 86 + "li 15, %[" #_asm_symbol_name_immed "];" \ 87 + "li 16, %[" #_asm_symbol_name_immed "];" \ 88 + "li 17, %[" #_asm_symbol_name_immed "];" \ 89 + "li 18, %[" #_asm_symbol_name_immed "];" \ 90 + "li 19, %[" #_asm_symbol_name_immed "];" \ 91 + "li 20, %[" #_asm_symbol_name_immed "];" \ 92 + "li 21, %[" #_asm_symbol_name_immed "];" \ 93 + "li 22, %[" #_asm_symbol_name_immed "];" \ 94 + "li 23, %[" #_asm_symbol_name_immed "];" \ 95 + "li 24, %[" #_asm_symbol_name_immed "];" \ 96 + "li 25, %[" #_asm_symbol_name_immed "];" \ 97 + "li 26, %[" #_asm_symbol_name_immed "];" \ 98 + "li 27, %[" #_asm_symbol_name_immed "];" \ 99 + "li 28, %[" #_asm_symbol_name_immed "];" \ 100 + "li 29, %[" #_asm_symbol_name_immed "];" \ 101 + "li 30, %[" #_asm_symbol_name_immed "];" \ 102 + "li 31, %[" #_asm_symbol_name_immed "];" 103 + 104 + #define ASM_LOAD_FPR_SINGLE_PRECISION(_asm_symbol_name_addr) \ 105 + "lfs 0, 0(%[" #_asm_symbol_name_addr "]);" \ 106 + "lfs 1, 0(%[" #_asm_symbol_name_addr "]);" \ 107 + "lfs 2, 0(%[" #_asm_symbol_name_addr "]);" \ 108 + "lfs 3, 0(%[" #_asm_symbol_name_addr "]);" \ 109 + "lfs 4, 0(%[" #_asm_symbol_name_addr "]);" \ 110 + "lfs 5, 0(%[" #_asm_symbol_name_addr "]);" \ 111 + "lfs 6, 0(%[" #_asm_symbol_name_addr "]);" \ 112 + "lfs 7, 0(%[" #_asm_symbol_name_addr "]);" \ 113 + "lfs 8, 0(%[" #_asm_symbol_name_addr "]);" \ 114 + "lfs 9, 0(%[" #_asm_symbol_name_addr "]);" \ 115 + "lfs 10, 0(%[" #_asm_symbol_name_addr "]);" \ 116 + "lfs 11, 0(%[" #_asm_symbol_name_addr "]);" \ 117 + "lfs 12, 0(%[" #_asm_symbol_name_addr "]);" \ 118 + "lfs 13, 0(%[" #_asm_symbol_name_addr "]);" \ 119 + "lfs 14, 0(%[" #_asm_symbol_name_addr "]);" \ 120 + "lfs 15, 0(%[" #_asm_symbol_name_addr "]);" \ 121 + "lfs 16, 0(%[" #_asm_symbol_name_addr "]);" \ 122 + "lfs 17, 0(%[" #_asm_symbol_name_addr "]);" \ 123 + "lfs 18, 0(%[" #_asm_symbol_name_addr "]);" \ 124 + "lfs 19, 0(%[" #_asm_symbol_name_addr "]);" \ 125 + "lfs 20, 0(%[" #_asm_symbol_name_addr "]);" \ 126 + "lfs 21, 0(%[" #_asm_symbol_name_addr "]);" \ 127 + "lfs 22, 0(%[" #_asm_symbol_name_addr "]);" \ 128 + "lfs 23, 0(%[" #_asm_symbol_name_addr "]);" \ 129 + "lfs 24, 0(%[" #_asm_symbol_name_addr "]);" \ 130 + "lfs 25, 0(%[" #_asm_symbol_name_addr "]);" \ 131 + "lfs 26, 0(%[" #_asm_symbol_name_addr "]);" \ 132 + "lfs 27, 0(%[" #_asm_symbol_name_addr "]);" \ 133 + "lfs 28, 0(%[" #_asm_symbol_name_addr "]);" \ 134 + "lfs 29, 0(%[" #_asm_symbol_name_addr "]);" \ 135 + "lfs 30, 0(%[" #_asm_symbol_name_addr "]);" \ 136 + "lfs 31, 0(%[" #_asm_symbol_name_addr "]);" 137 + 138 + #ifndef __ASSEMBLER__ 139 + void store_gpr(unsigned long *addr); 140 + void load_gpr(unsigned long *addr); 141 + void load_fpr_single_precision(float *addr); 142 + void store_fpr_single_precision(float *addr); 143 + #endif /* end of __ASSEMBLER__ */ 144 + 84 145 #endif /* _SELFTESTS_POWERPC_REG_H */
+132
tools/testing/selftests/powerpc/lib/reg.S
··· 1 + /* 2 + * test helper assembly functions 3 + * 4 + * Copyright (C) 2016 Simon Guo, 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 <ppc-asm.h> 12 + #include "reg.h" 13 + 14 + 15 + /* Non volatile GPR - unsigned long buf[18] */ 16 + FUNC_START(load_gpr) 17 + ld 14, 0*8(3) 18 + ld 15, 1*8(3) 19 + ld 16, 2*8(3) 20 + ld 17, 3*8(3) 21 + ld 18, 4*8(3) 22 + ld 19, 5*8(3) 23 + ld 20, 6*8(3) 24 + ld 21, 7*8(3) 25 + ld 22, 8*8(3) 26 + ld 23, 9*8(3) 27 + ld 24, 10*8(3) 28 + ld 25, 11*8(3) 29 + ld 26, 12*8(3) 30 + ld 27, 13*8(3) 31 + ld 28, 14*8(3) 32 + ld 29, 15*8(3) 33 + ld 30, 16*8(3) 34 + ld 31, 17*8(3) 35 + blr 36 + FUNC_END(load_gpr) 37 + 38 + FUNC_START(store_gpr) 39 + std 14, 0*8(3) 40 + std 15, 1*8(3) 41 + std 16, 2*8(3) 42 + std 17, 3*8(3) 43 + std 18, 4*8(3) 44 + std 19, 5*8(3) 45 + std 20, 6*8(3) 46 + std 21, 7*8(3) 47 + std 22, 8*8(3) 48 + std 23, 9*8(3) 49 + std 24, 10*8(3) 50 + std 25, 11*8(3) 51 + std 26, 12*8(3) 52 + std 27, 13*8(3) 53 + std 28, 14*8(3) 54 + std 29, 15*8(3) 55 + std 30, 16*8(3) 56 + std 31, 17*8(3) 57 + blr 58 + FUNC_END(store_gpr) 59 + 60 + /* Single Precision Float - float buf[32] */ 61 + FUNC_START(load_fpr_single_precision) 62 + lfs 0, 0*4(3) 63 + lfs 1, 1*4(3) 64 + lfs 2, 2*4(3) 65 + lfs 3, 3*4(3) 66 + lfs 4, 4*4(3) 67 + lfs 5, 5*4(3) 68 + lfs 6, 6*4(3) 69 + lfs 7, 7*4(3) 70 + lfs 8, 8*4(3) 71 + lfs 9, 9*4(3) 72 + lfs 10, 10*4(3) 73 + lfs 11, 11*4(3) 74 + lfs 12, 12*4(3) 75 + lfs 13, 13*4(3) 76 + lfs 14, 14*4(3) 77 + lfs 15, 15*4(3) 78 + lfs 16, 16*4(3) 79 + lfs 17, 17*4(3) 80 + lfs 18, 18*4(3) 81 + lfs 19, 19*4(3) 82 + lfs 20, 20*4(3) 83 + lfs 21, 21*4(3) 84 + lfs 22, 22*4(3) 85 + lfs 23, 23*4(3) 86 + lfs 24, 24*4(3) 87 + lfs 25, 25*4(3) 88 + lfs 26, 26*4(3) 89 + lfs 27, 27*4(3) 90 + lfs 28, 28*4(3) 91 + lfs 29, 29*4(3) 92 + lfs 30, 30*4(3) 93 + lfs 31, 31*4(3) 94 + blr 95 + FUNC_END(load_fpr_single_precision) 96 + 97 + /* Single Precision Float - float buf[32] */ 98 + FUNC_START(store_fpr_single_precision) 99 + stfs 0, 0*4(3) 100 + stfs 1, 1*4(3) 101 + stfs 2, 2*4(3) 102 + stfs 3, 3*4(3) 103 + stfs 4, 4*4(3) 104 + stfs 5, 5*4(3) 105 + stfs 6, 6*4(3) 106 + stfs 7, 7*4(3) 107 + stfs 8, 8*4(3) 108 + stfs 9, 9*4(3) 109 + stfs 10, 10*4(3) 110 + stfs 11, 11*4(3) 111 + stfs 12, 12*4(3) 112 + stfs 13, 13*4(3) 113 + stfs 14, 14*4(3) 114 + stfs 15, 15*4(3) 115 + stfs 16, 16*4(3) 116 + stfs 17, 17*4(3) 117 + stfs 18, 18*4(3) 118 + stfs 19, 19*4(3) 119 + stfs 20, 20*4(3) 120 + stfs 21, 21*4(3) 121 + stfs 22, 22*4(3) 122 + stfs 23, 23*4(3) 123 + stfs 24, 24*4(3) 124 + stfs 25, 25*4(3) 125 + stfs 26, 26*4(3) 126 + stfs 27, 27*4(3) 127 + stfs 28, 28*4(3) 128 + stfs 29, 29*4(3) 129 + stfs 30, 30*4(3) 130 + stfs 31, 31*4(3) 131 + blr 132 + FUNC_END(store_fpr_single_precision)
+1
tools/testing/selftests/powerpc/ptrace/.gitignore
··· 1 + ptrace-gpr
+12
tools/testing/selftests/powerpc/ptrace/Makefile
··· 1 + TEST_PROGS := ptrace-gpr 2 + 3 + include ../../lib.mk 4 + 5 + all: $(TEST_PROGS) 6 + 7 + CFLAGS += -m64 -I../../../../../usr/include 8 + 9 + $(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h 10 + 11 + clean: 12 + rm -f $(TEST_PROGS) *.o
+123
tools/testing/selftests/powerpc/ptrace/ptrace-gpr.c
··· 1 + /* 2 + * Ptrace test for GPR/FPR registers 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 "ptrace.h" 12 + #include "ptrace-gpr.h" 13 + #include "reg.h" 14 + 15 + /* Tracer and Tracee Shared Data */ 16 + int shm_id; 17 + int *cptr, *pptr; 18 + 19 + float a = FPR_1; 20 + float b = FPR_2; 21 + float c = FPR_3; 22 + 23 + void gpr(void) 24 + { 25 + unsigned long gpr_buf[18]; 26 + float fpr_buf[32]; 27 + 28 + cptr = (int *)shmat(shm_id, NULL, 0); 29 + 30 + asm __volatile__( 31 + ASM_LOAD_GPR_IMMED(gpr_1) 32 + ASM_LOAD_FPR_SINGLE_PRECISION(flt_1) 33 + : 34 + : [gpr_1]"i"(GPR_1), [flt_1] "r" (&a) 35 + : "memory", "r6", "r7", "r8", "r9", "r10", 36 + "r11", "r12", "r13", "r14", "r15", "r16", "r17", 37 + "r18", "r19", "r20", "r21", "r22", "r23", "r24", 38 + "r25", "r26", "r27", "r28", "r29", "r30", "r31" 39 + ); 40 + 41 + cptr[1] = 1; 42 + 43 + while (!cptr[0]) 44 + asm volatile("" : : : "memory"); 45 + 46 + shmdt((void *)cptr); 47 + store_gpr(gpr_buf); 48 + store_fpr_single_precision(fpr_buf); 49 + 50 + if (validate_gpr(gpr_buf, GPR_3)) 51 + exit(1); 52 + 53 + if (validate_fpr_float(fpr_buf, c)) 54 + exit(1); 55 + 56 + exit(0); 57 + } 58 + 59 + int trace_gpr(pid_t child) 60 + { 61 + unsigned long gpr[18]; 62 + unsigned long fpr[32]; 63 + 64 + FAIL_IF(start_trace(child)); 65 + FAIL_IF(show_gpr(child, gpr)); 66 + FAIL_IF(validate_gpr(gpr, GPR_1)); 67 + FAIL_IF(show_fpr(child, fpr)); 68 + FAIL_IF(validate_fpr(fpr, FPR_1_REP)); 69 + FAIL_IF(write_gpr(child, GPR_3)); 70 + FAIL_IF(write_fpr(child, FPR_3_REP)); 71 + FAIL_IF(stop_trace(child)); 72 + 73 + return TEST_PASS; 74 + } 75 + 76 + int ptrace_gpr(void) 77 + { 78 + pid_t pid; 79 + int ret, status; 80 + 81 + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); 82 + pid = fork(); 83 + if (pid < 0) { 84 + perror("fork() failed"); 85 + return TEST_FAIL; 86 + } 87 + if (pid == 0) 88 + gpr(); 89 + 90 + if (pid) { 91 + pptr = (int *)shmat(shm_id, NULL, 0); 92 + while (!pptr[1]) 93 + asm volatile("" : : : "memory"); 94 + 95 + ret = trace_gpr(pid); 96 + if (ret) { 97 + kill(pid, SIGTERM); 98 + shmdt((void *)pptr); 99 + shmctl(shm_id, IPC_RMID, NULL); 100 + return TEST_FAIL; 101 + } 102 + 103 + pptr[0] = 1; 104 + shmdt((void *)pptr); 105 + 106 + ret = wait(&status); 107 + shmctl(shm_id, IPC_RMID, NULL); 108 + if (ret != pid) { 109 + printf("Child's exit status not captured\n"); 110 + return TEST_FAIL; 111 + } 112 + 113 + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : 114 + TEST_PASS; 115 + } 116 + 117 + return TEST_PASS; 118 + } 119 + 120 + int main(int argc, char *argv[]) 121 + { 122 + return test_harness(ptrace_gpr, "ptrace_gpr"); 123 + }
+74
tools/testing/selftests/powerpc/ptrace/ptrace-gpr.h
··· 1 + /* 2 + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation; either version 7 + * 2 of the License, or (at your option) any later version. 8 + */ 9 + #define GPR_1 1 10 + #define GPR_2 2 11 + #define GPR_3 3 12 + #define GPR_4 4 13 + 14 + #define FPR_1 0.001 15 + #define FPR_2 0.002 16 + #define FPR_3 0.003 17 + #define FPR_4 0.004 18 + 19 + #define FPR_1_REP 0x3f50624de0000000 20 + #define FPR_2_REP 0x3f60624de0000000 21 + #define FPR_3_REP 0x3f689374c0000000 22 + #define FPR_4_REP 0x3f70624de0000000 23 + 24 + /* Buffer must have 18 elements */ 25 + int validate_gpr(unsigned long *gpr, unsigned long val) 26 + { 27 + int i, found = 1; 28 + 29 + for (i = 0; i < 18; i++) { 30 + if (gpr[i] != val) { 31 + printf("GPR[%d]: %lx Expected: %lx\n", 32 + i+14, gpr[i], val); 33 + found = 0; 34 + } 35 + } 36 + 37 + if (!found) 38 + return TEST_FAIL; 39 + return TEST_PASS; 40 + } 41 + 42 + /* Buffer must have 32 elements */ 43 + int validate_fpr(unsigned long *fpr, unsigned long val) 44 + { 45 + int i, found = 1; 46 + 47 + for (i = 0; i < 32; i++) { 48 + if (fpr[i] != val) { 49 + printf("FPR[%d]: %lx Expected: %lx\n", i, fpr[i], val); 50 + found = 0; 51 + } 52 + } 53 + 54 + if (!found) 55 + return TEST_FAIL; 56 + return TEST_PASS; 57 + } 58 + 59 + /* Buffer must have 32 elements */ 60 + int validate_fpr_float(float *fpr, float val) 61 + { 62 + int i, found = 1; 63 + 64 + for (i = 0; i < 32; i++) { 65 + if (fpr[i] != val) { 66 + printf("FPR[%d]: %f Expected: %f\n", i, fpr[i], val); 67 + found = 0; 68 + } 69 + } 70 + 71 + if (!found) 72 + return TEST_FAIL; 73 + return TEST_PASS; 74 + }
+376
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 + 42 + #ifndef NT_PPC_TAR 43 + #define NT_PPC_TAR 0x103 44 + #define NT_PPC_PPR 0x104 45 + #define NT_PPC_DSCR 0x105 46 + #define NT_PPC_EBB 0x106 47 + #define NT_PPC_PMU 0x107 48 + #define NT_PPC_TM_CGPR 0x108 49 + #define NT_PPC_TM_CFPR 0x109 50 + #define NT_PPC_TM_CVMX 0x10a 51 + #define NT_PPC_TM_CVSX 0x10b 52 + #define NT_PPC_TM_SPR 0x10c 53 + #define NT_PPC_TM_CTAR 0x10d 54 + #define NT_PPC_TM_CPPR 0x10e 55 + #define NT_PPC_TM_CDSCR 0x10f 56 + #endif 57 + 58 + /* Basic ptrace operations */ 59 + int start_trace(pid_t child) 60 + { 61 + int ret; 62 + 63 + ret = ptrace(PTRACE_ATTACH, child, NULL, NULL); 64 + if (ret) { 65 + perror("ptrace(PTRACE_ATTACH) failed"); 66 + return TEST_FAIL; 67 + } 68 + ret = waitpid(child, NULL, 0); 69 + if (ret != child) { 70 + perror("waitpid() failed"); 71 + return TEST_FAIL; 72 + } 73 + return TEST_PASS; 74 + } 75 + 76 + int stop_trace(pid_t child) 77 + { 78 + int ret; 79 + 80 + ret = ptrace(PTRACE_DETACH, child, NULL, NULL); 81 + if (ret) { 82 + perror("ptrace(PTRACE_DETACH) failed"); 83 + return TEST_FAIL; 84 + } 85 + return TEST_PASS; 86 + } 87 + 88 + int cont_trace(pid_t child) 89 + { 90 + int ret; 91 + 92 + ret = ptrace(PTRACE_CONT, child, NULL, NULL); 93 + if (ret) { 94 + perror("ptrace(PTRACE_CONT) failed"); 95 + return TEST_FAIL; 96 + } 97 + return TEST_PASS; 98 + } 99 + 100 + /* FPR */ 101 + int show_fpr(pid_t child, unsigned long *fpr) 102 + { 103 + struct fpr_regs *regs; 104 + int ret, i; 105 + 106 + regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); 107 + ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs); 108 + if (ret) { 109 + perror("ptrace(PTRACE_GETREGSET) failed"); 110 + return TEST_FAIL; 111 + } 112 + 113 + if (fpr) { 114 + for (i = 0; i < 32; i++) 115 + fpr[i] = regs->fpr[i]; 116 + } 117 + return TEST_PASS; 118 + } 119 + 120 + int write_fpr(pid_t child, unsigned long val) 121 + { 122 + struct fpr_regs *regs; 123 + int ret, i; 124 + 125 + regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); 126 + ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs); 127 + if (ret) { 128 + perror("ptrace(PTRACE_GETREGSET) failed"); 129 + return TEST_FAIL; 130 + } 131 + 132 + for (i = 0; i < 32; i++) 133 + regs->fpr[i] = val; 134 + 135 + ret = ptrace(PTRACE_SETFPREGS, child, NULL, regs); 136 + if (ret) { 137 + perror("ptrace(PTRACE_GETREGSET) failed"); 138 + return TEST_FAIL; 139 + } 140 + return TEST_PASS; 141 + } 142 + 143 + int show_ckpt_fpr(pid_t child, unsigned long *fpr) 144 + { 145 + struct fpr_regs *regs; 146 + struct iovec iov; 147 + int ret, i; 148 + 149 + regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); 150 + iov.iov_base = regs; 151 + iov.iov_len = sizeof(struct fpr_regs); 152 + 153 + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov); 154 + if (ret) { 155 + perror("ptrace(PTRACE_GETREGSET) failed"); 156 + return TEST_FAIL; 157 + } 158 + 159 + if (fpr) { 160 + for (i = 0; i < 32; i++) 161 + fpr[i] = regs->fpr[i]; 162 + } 163 + 164 + return TEST_PASS; 165 + } 166 + 167 + int write_ckpt_fpr(pid_t child, unsigned long val) 168 + { 169 + struct fpr_regs *regs; 170 + struct iovec iov; 171 + int ret, i; 172 + 173 + regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); 174 + iov.iov_base = regs; 175 + iov.iov_len = sizeof(struct fpr_regs); 176 + 177 + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov); 178 + if (ret) { 179 + perror("ptrace(PTRACE_GETREGSET) failed"); 180 + return TEST_FAIL; 181 + } 182 + 183 + for (i = 0; i < 32; i++) 184 + regs->fpr[i] = val; 185 + 186 + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CFPR, &iov); 187 + if (ret) { 188 + perror("ptrace(PTRACE_GETREGSET) failed"); 189 + return TEST_FAIL; 190 + } 191 + return TEST_PASS; 192 + } 193 + 194 + /* GPR */ 195 + int show_gpr(pid_t child, unsigned long *gpr) 196 + { 197 + struct pt_regs *regs; 198 + int ret, i; 199 + 200 + regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); 201 + if (!regs) { 202 + perror("malloc() failed"); 203 + return TEST_FAIL; 204 + } 205 + 206 + ret = ptrace(PTRACE_GETREGS, child, NULL, regs); 207 + if (ret) { 208 + perror("ptrace(PTRACE_GETREGSET) failed"); 209 + return TEST_FAIL; 210 + } 211 + 212 + if (gpr) { 213 + for (i = 14; i < 32; i++) 214 + gpr[i-14] = regs->gpr[i]; 215 + } 216 + 217 + return TEST_PASS; 218 + } 219 + 220 + int write_gpr(pid_t child, unsigned long val) 221 + { 222 + struct pt_regs *regs; 223 + int i, ret; 224 + 225 + regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); 226 + if (!regs) { 227 + perror("malloc() failed"); 228 + return TEST_FAIL; 229 + } 230 + 231 + ret = ptrace(PTRACE_GETREGS, child, NULL, regs); 232 + if (ret) { 233 + perror("ptrace(PTRACE_GETREGSET) failed"); 234 + return TEST_FAIL; 235 + } 236 + 237 + for (i = 14; i < 32; i++) 238 + regs->gpr[i] = val; 239 + 240 + ret = ptrace(PTRACE_SETREGS, child, NULL, regs); 241 + if (ret) { 242 + perror("ptrace(PTRACE_GETREGSET) failed"); 243 + return TEST_FAIL; 244 + } 245 + return TEST_PASS; 246 + } 247 + 248 + int show_ckpt_gpr(pid_t child, unsigned long *gpr) 249 + { 250 + struct pt_regs *regs; 251 + struct iovec iov; 252 + int ret, i; 253 + 254 + regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); 255 + if (!regs) { 256 + perror("malloc() failed"); 257 + return TEST_FAIL; 258 + } 259 + 260 + iov.iov_base = (u64 *) regs; 261 + iov.iov_len = sizeof(struct pt_regs); 262 + 263 + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov); 264 + if (ret) { 265 + perror("ptrace(PTRACE_GETREGSET) failed"); 266 + return TEST_FAIL; 267 + } 268 + 269 + if (gpr) { 270 + for (i = 14; i < 32; i++) 271 + gpr[i-14] = regs->gpr[i]; 272 + } 273 + 274 + return TEST_PASS; 275 + } 276 + 277 + int write_ckpt_gpr(pid_t child, unsigned long val) 278 + { 279 + struct pt_regs *regs; 280 + struct iovec iov; 281 + int ret, i; 282 + 283 + regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); 284 + if (!regs) { 285 + perror("malloc() failed\n"); 286 + return TEST_FAIL; 287 + } 288 + iov.iov_base = (u64 *) regs; 289 + iov.iov_len = sizeof(struct pt_regs); 290 + 291 + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov); 292 + if (ret) { 293 + perror("ptrace(PTRACE_GETREGSET) failed"); 294 + return TEST_FAIL; 295 + } 296 + 297 + for (i = 14; i < 32; i++) 298 + regs->gpr[i] = val; 299 + 300 + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov); 301 + if (ret) { 302 + perror("ptrace(PTRACE_GETREGSET) failed"); 303 + return TEST_FAIL; 304 + } 305 + return TEST_PASS; 306 + } 307 + 308 + /* Analyse TEXASR after TM failure */ 309 + inline unsigned long get_tfiar(void) 310 + { 311 + unsigned long ret; 312 + 313 + asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_TFIAR)); 314 + return ret; 315 + } 316 + 317 + void analyse_texasr(unsigned long texasr) 318 + { 319 + printf("TEXASR: %16lx\t", texasr); 320 + 321 + if (texasr & TEXASR_FP) 322 + printf("TEXASR_FP "); 323 + 324 + if (texasr & TEXASR_DA) 325 + printf("TEXASR_DA "); 326 + 327 + if (texasr & TEXASR_NO) 328 + printf("TEXASR_NO "); 329 + 330 + if (texasr & TEXASR_FO) 331 + printf("TEXASR_FO "); 332 + 333 + if (texasr & TEXASR_SIC) 334 + printf("TEXASR_SIC "); 335 + 336 + if (texasr & TEXASR_NTC) 337 + printf("TEXASR_NTC "); 338 + 339 + if (texasr & TEXASR_TC) 340 + printf("TEXASR_TC "); 341 + 342 + if (texasr & TEXASR_TIC) 343 + printf("TEXASR_TIC "); 344 + 345 + if (texasr & TEXASR_IC) 346 + printf("TEXASR_IC "); 347 + 348 + if (texasr & TEXASR_IFC) 349 + printf("TEXASR_IFC "); 350 + 351 + if (texasr & TEXASR_ABT) 352 + printf("TEXASR_ABT "); 353 + 354 + if (texasr & TEXASR_SPD) 355 + printf("TEXASR_SPD "); 356 + 357 + if (texasr & TEXASR_HV) 358 + printf("TEXASR_HV "); 359 + 360 + if (texasr & TEXASR_PR) 361 + printf("TEXASR_PR "); 362 + 363 + if (texasr & TEXASR_FS) 364 + printf("TEXASR_FS "); 365 + 366 + if (texasr & TEXASR_TE) 367 + printf("TEXASR_TE "); 368 + 369 + if (texasr & TEXASR_ROT) 370 + printf("TEXASR_ROT "); 371 + 372 + printf("TFIAR :%lx\n", get_tfiar()); 373 + } 374 + 375 + void store_gpr(unsigned long *addr); 376 + void store_fpr(float *addr);