1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2016, Cyril Bur, IBM Corp. 4 * 5 * Test the kernel's signal frame code. 6 * 7 * The kernel sets up two sets of ucontexts if the signal was to be 8 * delivered while the thread was in a transaction. 9 * Expected behaviour is that the checkpointed state is in the user 10 * context passed to the signal handler. The speculated state can be 11 * accessed with the uc_link pointer. 12 * 13 * The rationale for this is that if TM unaware code (which linked 14 * against TM libs) installs a signal handler it will not know of the 15 * speculative nature of the 'live' registers and may infer the wrong 16 * thing. 17 */ 18 19 #include <stdlib.h> 20 #include <stdio.h> 21 #include <string.h> 22 #include <signal.h> 23 #include <unistd.h> 24 25 #include <altivec.h> 26 27 #include "utils.h" 28 #include "tm.h" 29 30 #define MAX_ATTEMPT 500000 31 32 #define NV_VSX_REGS 12 33 34 long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); 35 36 static sig_atomic_t fail; 37 38 vector int vss[] = { 39 {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12}, 40 {13,14,15,16},{17,18,19,20},{21,22,23,24}, 41 {25,26,27,28},{29,30,31,32},{33,34,35,36}, 42 {37,38,39,40},{41,42,43,44},{45,46,47,48}, 43 {-1, -2, -3, -4 },{-5, -6, -7, -8 },{-9, -10,-11,-12}, 44 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24}, 45 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36}, 46 {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48} 47 }; 48 49 static void signal_usr1(int signum, siginfo_t *info, void *uc) 50 { 51 int i; 52 uint8_t vsc[sizeof(vector int)]; 53 uint8_t vst[sizeof(vector int)]; 54 ucontext_t *ucp = uc; 55 ucontext_t *tm_ucp = ucp->uc_link; 56 57 /* 58 * The other half of the VSX regs will be after v_regs. 59 * 60 * In short, vmx_reserve array holds everything. v_regs is a 16 61 * byte aligned pointer at the start of vmx_reserve (vmx_reserve 62 * may or may not be 16 aligned) where the v_regs structure exists. 63 * (half of) The VSX regsters are directly after v_regs so the 64 * easiest way to find them below. 65 */ 66 long *vsx_ptr = (long *)(ucp->uc_mcontext.v_regs + 1); 67 long *tm_vsx_ptr = (long *)(tm_ucp->uc_mcontext.v_regs + 1); 68 for (i = 0; i < NV_VSX_REGS && !fail; i++) { 69 memcpy(vsc, &ucp->uc_mcontext.fp_regs[i + 20], 8); 70 memcpy(vsc + 8, &vsx_ptr[20 + i], 8); 71 fail = memcmp(vsc, &vss[i], sizeof(vector int)); 72 memcpy(vst, &tm_ucp->uc_mcontext.fp_regs[i + 20], 8); 73 memcpy(vst + 8, &tm_vsx_ptr[20 + i], 8); 74 fail |= memcmp(vst, &vss[i + NV_VSX_REGS], sizeof(vector int)); 75 76 if (fail) { 77 int j; 78 79 fprintf(stderr, "Failed on %d vsx 0x", i); 80 for (j = 0; j < 16; j++) 81 fprintf(stderr, "%02x", vsc[j]); 82 fprintf(stderr, " vs 0x"); 83 for (j = 0; j < 16; j++) 84 fprintf(stderr, "%02x", vst[j]); 85 fprintf(stderr, "\n"); 86 } 87 } 88 } 89 90 static int tm_signal_context_chk() 91 { 92 struct sigaction act; 93 int i; 94 long rc; 95 pid_t pid = getpid(); 96 97 SKIP_IF(!have_htm()); 98 99 act.sa_sigaction = signal_usr1; 100 sigemptyset(&act.sa_mask); 101 act.sa_flags = SA_SIGINFO; 102 if (sigaction(SIGUSR1, &act, NULL) < 0) { 103 perror("sigaction sigusr1"); 104 exit(1); 105 } 106 107 i = 0; 108 while (i < MAX_ATTEMPT && !fail) { 109 rc = tm_signal_self_context_load(pid, NULL, NULL, NULL, vss); 110 FAIL_IF(rc != pid); 111 i++; 112 } 113 114 return fail; 115 } 116 117 int main(void) 118 { 119 return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vsx"); 120 } 121