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 <signal.h> 27 #include <unistd.h> 28 29 #include <altivec.h> 30 31 #include "utils.h" 32 #include "tm.h" 33 34 #define MAX_ATTEMPT 500000 35 36 #define NV_GPR_REGS 18 37 38 long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); 39 40 static sig_atomic_t fail; 41 42 static long gps[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 43 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18}; 44 45 static void signal_usr1(int signum, siginfo_t *info, void *uc) 46 { 47 int i; 48 ucontext_t *ucp = uc; 49 ucontext_t *tm_ucp = ucp->uc_link; 50 51 for (i = 0; i < NV_GPR_REGS && !fail; i++) { 52 fail = (ucp->uc_mcontext.gp_regs[i + 14] != gps[i]); 53 fail |= (tm_ucp->uc_mcontext.gp_regs[i + 14] != gps[i + NV_GPR_REGS]); 54 if (fail) 55 printf("Failed on %d GPR %lu or %lu\n", i, 56 ucp->uc_mcontext.gp_regs[i + 14], tm_ucp->uc_mcontext.gp_regs[i + 14]); 57 } 58 } 59 60 static int tm_signal_context_chk_gpr() 61 { 62 struct sigaction act; 63 int i; 64 long rc; 65 pid_t pid = getpid(); 66 67 SKIP_IF(!have_htm()); 68 69 act.sa_sigaction = signal_usr1; 70 sigemptyset(&act.sa_mask); 71 act.sa_flags = SA_SIGINFO; 72 if (sigaction(SIGUSR1, &act, NULL) < 0) { 73 perror("sigaction sigusr1"); 74 exit(1); 75 } 76 77 i = 0; 78 while (i < MAX_ATTEMPT && !fail) { 79 rc = tm_signal_self_context_load(pid, gps, NULL, NULL, NULL); 80 FAIL_IF(rc != pid); 81 i++; 82 } 83 84 return fail; 85 } 86 87 int main(void) 88 { 89 return test_harness(tm_signal_context_chk_gpr, "tm_signal_context_chk_gpr"); 90 } 91