1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Ptrace test for TAR, PPR, DSCR registers in the TM Suspend context 4 * 5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. 6 */ 7 #include "ptrace.h" 8 #include "tm.h" 9 #include "ptrace-tar.h" 10 11 int shm_id; 12 int *cptr, *pptr; 13 14 __attribute__((used)) void wait_parent(void) 15 { 16 cptr[2] = 1; 17 while (!cptr[1]) 18 asm volatile("" : : : "memory"); 19 } 20 21 void tm_spd_tar(void) 22 { 23 unsigned long result, texasr; 24 unsigned long regs[3]; 25 int ret; 26 27 cptr = (int *)shmat(shm_id, NULL, 0); 28 29 trans: 30 cptr[2] = 0; 31 asm __volatile__( 32 "li 4, %[tar_1];" 33 "mtspr %[sprn_tar], 4;" /* TAR_1 */ 34 "li 4, %[dscr_1];" 35 "mtspr %[sprn_dscr], 4;" /* DSCR_1 */ 36 "or 31,31,31;" /* PPR_1*/ 37 38 "1: ;" 39 "tbegin.;" 40 "beq 2f;" 41 42 "li 4, %[tar_2];" 43 "mtspr %[sprn_tar], 4;" /* TAR_2 */ 44 "li 4, %[dscr_2];" 45 "mtspr %[sprn_dscr], 4;" /* DSCR_2 */ 46 "or 1,1,1;" /* PPR_2 */ 47 48 "tsuspend.;" 49 "li 4, %[tar_3];" 50 "mtspr %[sprn_tar], 4;" /* TAR_3 */ 51 "li 4, %[dscr_3];" 52 "mtspr %[sprn_dscr], 4;" /* DSCR_3 */ 53 "or 6,6,6;" /* PPR_3 */ 54 "bl wait_parent;" 55 "tresume.;" 56 57 "tend.;" 58 "li 0, 0;" 59 "ori %[res], 0, 0;" 60 "b 3f;" 61 62 /* Transaction abort handler */ 63 "2: ;" 64 "li 0, 1;" 65 "ori %[res], 0, 0;" 66 "mfspr %[texasr], %[sprn_texasr];" 67 68 "3: ;" 69 70 : [res] "=r" (result), [texasr] "=r" (texasr) 71 : [sprn_dscr]"i"(SPRN_DSCR), 72 [sprn_tar]"i"(SPRN_TAR), [sprn_ppr]"i"(SPRN_PPR), 73 [sprn_texasr]"i"(SPRN_TEXASR), [tar_1]"i"(TAR_1), 74 [dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2), [dscr_2]"i"(DSCR_2), 75 [tar_3]"i"(TAR_3), [dscr_3]"i"(DSCR_3) 76 : "memory", "r0", "r3", "r4", "r5", "r6", "lr" 77 ); 78 79 /* TM failed, analyse */ 80 if (result) { 81 if (!cptr[0]) 82 goto trans; 83 84 regs[0] = mfspr(SPRN_TAR); 85 regs[1] = mfspr(SPRN_PPR); 86 regs[2] = mfspr(SPRN_DSCR); 87 88 shmdt(&cptr); 89 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", 90 user_read, regs[0], regs[1], regs[2]); 91 92 ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4); 93 if (ret) 94 exit(1); 95 exit(0); 96 } 97 shmdt(&cptr); 98 exit(1); 99 } 100 101 int trace_tm_spd_tar(pid_t child) 102 { 103 unsigned long regs[3]; 104 105 FAIL_IF(start_trace(child)); 106 FAIL_IF(show_tar_registers(child, regs)); 107 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", 108 ptrace_read_running, regs[0], regs[1], regs[2]); 109 110 FAIL_IF(validate_tar_registers(regs, TAR_3, PPR_3, DSCR_3)); 111 FAIL_IF(show_tm_checkpointed_state(child, regs)); 112 printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", 113 ptrace_read_ckpt, regs[0], regs[1], regs[2]); 114 115 FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1)); 116 FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4)); 117 printf("%-30s TAR: %u PPR: %lx DSCR: %u\n", 118 ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4); 119 120 pptr[0] = 1; 121 pptr[1] = 1; 122 FAIL_IF(stop_trace(child)); 123 return TEST_PASS; 124 } 125 126 int ptrace_tm_spd_tar(void) 127 { 128 pid_t pid; 129 int ret, status; 130 131 SKIP_IF(!have_htm()); 132 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); 133 pid = fork(); 134 if (pid == 0) 135 tm_spd_tar(); 136 137 pptr = (int *)shmat(shm_id, NULL, 0); 138 pptr[0] = 0; 139 pptr[1] = 0; 140 141 if (pid) { 142 while (!pptr[2]) 143 asm volatile("" : : : "memory"); 144 ret = trace_tm_spd_tar(pid); 145 if (ret) { 146 kill(pid, SIGTERM); 147 shmdt(&pptr); 148 shmctl(shm_id, IPC_RMID, NULL); 149 return TEST_FAIL; 150 } 151 152 shmdt(&pptr); 153 154 ret = wait(&status); 155 shmctl(shm_id, IPC_RMID, NULL); 156 if (ret != pid) { 157 printf("Child's exit status not captured\n"); 158 return TEST_FAIL; 159 } 160 161 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : 162 TEST_PASS; 163 } 164 return TEST_PASS; 165 } 166 167 int main(int argc, char *argv[]) 168 { 169 return test_harness(ptrace_tm_spd_tar, "ptrace_tm_spd_tar"); 170 } 171