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