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