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_VMX_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 vms[] = { 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 ucontext_t *ucp = uc; 58 ucontext_t *tm_ucp = ucp->uc_link; 59 60 for (i = 0; i < NV_VMX_REGS && !fail; i++) { 61 fail = memcmp(ucp->uc_mcontext.v_regs->vrregs[i + 20], 62 &vms[i], sizeof(vector int)); 63 fail |= memcmp(tm_ucp->uc_mcontext.v_regs->vrregs[i + 20], 64 &vms[i + NV_VMX_REGS], sizeof (vector int)); 65 66 if (fail) { 67 int j; 68 69 fprintf(stderr, "Failed on %d vmx 0x", i); 70 for (j = 0; j < 4; j++) 71 fprintf(stderr, "%04x", ucp->uc_mcontext.v_regs->vrregs[i + 20][j]); 72 fprintf(stderr, " vs 0x"); 73 for (j = 0 ; j < 4; j++) 74 fprintf(stderr, "%04x", tm_ucp->uc_mcontext.v_regs->vrregs[i + 20][j]); 75 fprintf(stderr, "\n"); 76 } 77 } 78 } 79 80 static int tm_signal_context_chk() 81 { 82 struct sigaction act; 83 int i; 84 long rc; 85 pid_t pid = getpid(); 86 87 SKIP_IF(!have_htm()); 88 89 act.sa_sigaction = signal_usr1; 90 sigemptyset(&act.sa_mask); 91 act.sa_flags = SA_SIGINFO; 92 if (sigaction(SIGUSR1, &act, NULL) < 0) { 93 perror("sigaction sigusr1"); 94 exit(1); 95 } 96 97 i = 0; 98 while (i < MAX_ATTEMPT && !fail) { 99 rc = tm_signal_self_context_load(pid, NULL, NULL, vms, NULL); 100 FAIL_IF(rc != pid); 101 i++; 102 } 103 104 return fail; 105 } 106 107 int main(void) 108 { 109 return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vmx"); 110 } 111