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