1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Ptrace test for VMX/VSX 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-vsx.h" 10 11 int shm_id; 12 unsigned long *cptr, *pptr; 13 14 unsigned long fp_load[VEC_MAX]; 15 unsigned long fp_store[VEC_MAX]; 16 unsigned long fp_load_ckpt[VEC_MAX]; 17 unsigned long fp_load_ckpt_new[VEC_MAX]; 18 19 __attribute__((used)) void load_vsx(void) 20 { 21 loadvsx(fp_load, 0); 22 } 23 24 __attribute__((used)) void load_vsx_ckpt(void) 25 { 26 loadvsx(fp_load_ckpt, 0); 27 } 28 29 void tm_vsx(void) 30 { 31 unsigned long result, texasr; 32 int ret; 33 34 cptr = (unsigned long *)shmat(shm_id, NULL, 0); 35 36 trans: 37 cptr[1] = 0; 38 asm __volatile__( 39 "bl load_vsx_ckpt;" 40 41 "1: ;" 42 "tbegin.;" 43 "beq 2f;" 44 45 "bl load_vsx;" 46 "tsuspend.;" 47 "li 7, 1;" 48 "stw 7, 0(%[cptr1]);" 49 "tresume.;" 50 "b .;" 51 52 "tend.;" 53 "li 0, 0;" 54 "ori %[res], 0, 0;" 55 "b 3f;" 56 57 "2: ;" 58 "li 0, 1;" 59 "ori %[res], 0, 0;" 60 "mfspr %[texasr], %[sprn_texasr];" 61 62 "3: ;" 63 : [res] "=r" (result), [texasr] "=r" (texasr) 64 : [sprn_texasr] "i" (SPRN_TEXASR), [cptr1] "b" (&cptr[1]) 65 : "memory", "r0", "r3", "r4", 66 "r7", "r8", "r9", "r10", "r11", "lr" 67 ); 68 69 if (result) { 70 if (!cptr[0]) 71 goto trans; 72 73 shmdt((void *)cptr); 74 storevsx(fp_store, 0); 75 ret = compare_vsx_vmx(fp_store, fp_load_ckpt_new); 76 if (ret) 77 exit(1); 78 exit(0); 79 } 80 shmdt((void *)cptr); 81 exit(1); 82 } 83 84 int trace_tm_vsx(pid_t child) 85 { 86 unsigned long vsx[VSX_MAX]; 87 unsigned long vmx[VMX_MAX + 2][2]; 88 89 FAIL_IF(start_trace(child)); 90 FAIL_IF(show_vsx(child, vsx)); 91 FAIL_IF(validate_vsx(vsx, fp_load)); 92 FAIL_IF(show_vmx(child, vmx)); 93 FAIL_IF(validate_vmx(vmx, fp_load)); 94 FAIL_IF(show_vsx_ckpt(child, vsx)); 95 FAIL_IF(validate_vsx(vsx, fp_load_ckpt)); 96 FAIL_IF(show_vmx_ckpt(child, vmx)); 97 FAIL_IF(validate_vmx(vmx, fp_load_ckpt)); 98 memset(vsx, 0, sizeof(vsx)); 99 memset(vmx, 0, sizeof(vmx)); 100 101 load_vsx_vmx(fp_load_ckpt_new, vsx, vmx); 102 103 FAIL_IF(write_vsx_ckpt(child, vsx)); 104 FAIL_IF(write_vmx_ckpt(child, vmx)); 105 pptr[0] = 1; 106 FAIL_IF(stop_trace(child)); 107 return TEST_PASS; 108 } 109 110 int ptrace_tm_vsx(void) 111 { 112 pid_t pid; 113 int ret, status, i; 114 115 SKIP_IF(!have_htm()); 116 shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); 117 118 for (i = 0; i < 128; i++) { 119 fp_load[i] = 1 + rand(); 120 fp_load_ckpt[i] = 1 + 2 * rand(); 121 fp_load_ckpt_new[i] = 1 + 3 * rand(); 122 } 123 124 pid = fork(); 125 if (pid < 0) { 126 perror("fork() failed"); 127 return TEST_FAIL; 128 } 129 130 if (pid == 0) 131 tm_vsx(); 132 133 if (pid) { 134 pptr = (unsigned long *)shmat(shm_id, NULL, 0); 135 while (!pptr[1]) 136 asm volatile("" : : : "memory"); 137 138 ret = trace_tm_vsx(pid); 139 if (ret) { 140 kill(pid, SIGKILL); 141 shmdt((void *)pptr); 142 shmctl(shm_id, IPC_RMID, NULL); 143 return TEST_FAIL; 144 } 145 146 shmdt((void *)pptr); 147 ret = wait(&status); 148 shmctl(shm_id, IPC_RMID, NULL); 149 if (ret != pid) { 150 printf("Child's exit status not captured\n"); 151 return TEST_FAIL; 152 } 153 154 return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : 155 TEST_PASS; 156 } 157 return TEST_PASS; 158 } 159 160 int main(int argc, char *argv[]) 161 { 162 return test_harness(ptrace_tm_vsx, "ptrace_tm_vsx"); 163 } 164