Home | History | Annotate | Download | only in tm
      1 /*
      2  * Copyright 2015, Michael Neuling, IBM Corp.
      3  * Licensed under GPLv2.
      4  *
      5  * Test the kernel's signal return code to ensure that it doesn't
      6  * crash when both the transactional and suspend MSR bits are set in
      7  * the signal context.
      8  *
      9  * For this test, we send ourselves a SIGUSR1.  In the SIGUSR1 handler
     10  * we modify the signal context to set both MSR TM S and T bits (which
     11  * is "reserved" by the PowerISA). When we return from the signal
     12  * handler (implicit sigreturn), the kernel should detect reserved MSR
     13  * value and send us with a SIGSEGV.
     14  */
     15 
     16 #include <stdlib.h>
     17 #include <stdio.h>
     18 #include <signal.h>
     19 #include <unistd.h>
     20 
     21 #include "utils.h"
     22 #include "tm.h"
     23 
     24 int segv_expected = 0;
     25 
     26 void signal_segv(int signum)
     27 {
     28 	if (segv_expected && (signum == SIGSEGV))
     29 		_exit(0);
     30 	_exit(1);
     31 }
     32 
     33 void signal_usr1(int signum, siginfo_t *info, void *uc)
     34 {
     35 	ucontext_t *ucp = uc;
     36 
     37 	/* Link tm checkpointed context to normal context */
     38 	ucp->uc_link = ucp;
     39 	/* Set all TM bits so that the context is now invalid */
     40 #ifdef __powerpc64__
     41 	ucp->uc_mcontext.gp_regs[PT_MSR] |= (7ULL << 32);
     42 #else
     43 	ucp->uc_mcontext.uc_regs->gregs[PT_MSR] |= (7ULL);
     44 #endif
     45 	/* Should segv on return becuase of invalid context */
     46 	segv_expected = 1;
     47 }
     48 
     49 int tm_signal_msr_resv()
     50 {
     51 	struct sigaction act;
     52 
     53 	SKIP_IF(!have_htm());
     54 
     55 	act.sa_sigaction = signal_usr1;
     56 	sigemptyset(&act.sa_mask);
     57 	act.sa_flags = SA_SIGINFO;
     58 	if (sigaction(SIGUSR1, &act, NULL) < 0) {
     59 		perror("sigaction sigusr1");
     60 		exit(1);
     61 	}
     62 	if (signal(SIGSEGV, signal_segv) == SIG_ERR)
     63 		exit(1);
     64 
     65 	raise(SIGUSR1);
     66 
     67 	/* We shouldn't get here as we exit in the segv handler */
     68 	return 1;
     69 }
     70 
     71 int main(void)
     72 {
     73 	return test_harness(tm_signal_msr_resv, "tm_signal_msr_resv");
     74 }
     75