Home | History | Annotate | Download | only in tm
      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