1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Ptrace test for GPR/FPR registers in TM Suspend context 4 * 5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. 6 */ 7 #include "ptrace.h" 8 #include "ptrace-gpr.h" 9 #include "tm.h" 10 11 /* Tracer and Tracee Shared Data */ 12 int shm_id; 13 int *cptr, *pptr; 14 15 double a = FPR_1; 16 double b = FPR_2; 17 double c = FPR_3; 18 double d = FPR_4; 19 20 __attribute__((used)) void wait_parent(void) 21 { 22 cptr[2] = 1; 23 while (!cptr[1]) 24 asm volatile("" : : : "memory"); 25 } 26 27 void tm_spd_gpr(void) 28 { 29 unsigned long gpr_buf[18]; 30 unsigned long result, texasr; 31 double fpr_buf[32]; 32 33 cptr = (int *)shmat(shm_id, NULL, 0); 34 35 trans: 36 cptr[2] = 0; 37 asm __volatile__( 38 ASM_LOAD_GPR_IMMED(gpr_1) 39 ASM_LOAD_FPR(flt_1) 40 41 "1: ;" 42 "tbegin.;" 43 "beq 2f;" 44 45 ASM_LOAD_GPR_IMMED(gpr_2) 46 "tsuspend.;" 47 ASM_LOAD_GPR_IMMED(gpr_4) 48 ASM_LOAD_FPR(flt_4) 49 50 "bl wait_parent;" 51 "tresume.;" 52 "tend.;" 53 "li 0, 0;" 54 "ori %[res], 0, 0;" 55 "b 3f;" 56 57 /* Transaction abort handler */ 58 "2: ;" 59 "li 0, 1;" 60 "ori %[res], 0, 0;" 61 "mfspr %[texasr], %[sprn_texasr];" 62 63 "3: ;" 64 : [res] "=r" (result), [texasr] "=r" (texasr) 65 : [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2), [gpr_4]"i"(GPR_4), 66 [sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "b" (&a), 67 [flt_4] "b" (&d) 68 : "memory", "r0", "r5", "r6", "r7", 69 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 70 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 71 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" 72 ); 73 74 if (result) { 75 if (!cptr[0]) 76 goto trans; 77 78 shmdt((void *)cptr); 79 store_gpr(gpr_buf); 80 store_fpr(fpr_buf); 81 82 if (validate_gpr(gpr_buf, GPR_3)) 83 exit(1); 84 85 if (validate_fpr_double(fpr_buf, c)) 86 exit(1); 87 exit(0); 88 } 89 shmdt((void *)cptr); 90 exit(1); 91 } 92 93 int trace_tm_spd_gpr(pid_t child) 94 { 95 unsigned long gpr[18]; 96 __u64 fpr[32]; 97 98 FAIL_IF(start_trace(child)); 99 FAIL_IF(show_gpr(child, gpr)); 100 FAIL_IF(validate_gpr(gpr, GPR_4)); 101 FAIL_IF(show_fpr(child, fpr)); 102 FAIL_IF(validate_fpr(fpr, FPR_4_REP)); 103 FAIL_IF(show_ckpt_fpr(child, fpr)); 104 FAIL_IF(validate_fpr(fpr, FPR_1_REP)); 105 FAIL_IF(show_ckpt_gpr(child, gpr)); 106 FAIL_IF(validate_gpr(gpr, GPR_1)); 107 FAIL_IF(write_ckpt_gpr(child, GPR_3)); 108 FAIL_IF(write_ckpt_fpr(child, FPR_3_REP)); 109 110 pptr[0] = 1; 111 pptr[1] = 1; 112 FAIL_IF(stop_trace(child)); 113 return TEST_PASS; 114 } 115 116 int ptrace_tm_spd_gpr(void) 117 { 118 pid_t pid; 119 int ret, status; 120 121 SKIP_IF(!have_htm()); 122 SKIP_IF(htm_is_synthetic()); 123 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); 124 pid = fork(); 125 if (pid < 0) { 126 perror("fork() failed"); 127 return TEST_FAIL; 128 } 129 130 if (pid == 0) 131 tm_spd_gpr(); 132 133 if (pid) { 134 pptr = (int *)shmat(shm_id, NULL, 0); 135 pptr[0] = 0; 136 pptr[1] = 0; 137 138 while (!pptr[2]) 139 asm volatile("" : : : "memory"); 140 ret = trace_tm_spd_gpr(pid); 141 if (ret) { 142 kill(pid, SIGTERM); 143 shmdt((void *)pptr); 144 shmctl(shm_id, IPC_RMID, NULL); 145 return TEST_FAIL; 146 } 147 148 shmdt((void *)pptr); 149 150 ret = wait(&status); 151 shmctl(shm_id, IPC_RMID, NULL); 152 if (ret != pid) { 153 printf("Child's exit status not captured\n"); 154 return TEST_FAIL; 155 } 156 157 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : 158 TEST_PASS; 159 } 160 return TEST_PASS; 161 } 162 163 int main(int argc, char *argv[]) 164 { 165 return test_harness(ptrace_tm_spd_gpr, "ptrace_tm_spd_gpr"); 166 } 167