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_FPU_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 /* Be sure there are 2x as many as there are NV FPU regs (2x18) */ 41 static double fps[] = { 42 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 46 static sig_atomic_t fail; 47 48 static void signal_usr1(int signum, siginfo_t *info, void *uc) 49 { 50 int i; 51 ucontext_t *ucp = uc; 52 ucontext_t *tm_ucp = ucp->uc_link; 53 54 for (i = 0; i < NV_FPU_REGS && !fail; i++) { 55 fail = (ucp->uc_mcontext.fp_regs[i + 14] != fps[i]); 56 fail |= (tm_ucp->uc_mcontext.fp_regs[i + 14] != fps[i + NV_FPU_REGS]); 57 if (fail) 58 printf("Failed on %d FP %g or %g\n", i, ucp->uc_mcontext.fp_regs[i + 14], tm_ucp->uc_mcontext.fp_regs[i + 14]); 59 } 60 } 61 62 static int tm_signal_context_chk_fpu() 63 { 64 struct sigaction act; 65 int i; 66 long rc; 67 pid_t pid = getpid(); 68 69 SKIP_IF(!have_htm()); 70 71 act.sa_sigaction = signal_usr1; 72 sigemptyset(&act.sa_mask); 73 act.sa_flags = SA_SIGINFO; 74 if (sigaction(SIGUSR1, &act, NULL) < 0) { 75 perror("sigaction sigusr1"); 76 exit(1); 77 } 78 79 i = 0; 80 while (i < MAX_ATTEMPT && !fail) { 81 rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL); 82 FAIL_IF(rc != pid); 83 i++; 84 } 85 86 return fail; 87 } 88 89 int main(void) 90 { 91 return test_harness(tm_signal_context_chk_fpu, "tm_signal_context_chk_fpu"); 92 } 93