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