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 24int segv_expected = 0; 25 26void signal_segv(int signum) 27{ 28 if (segv_expected && (signum == SIGSEGV)) 29 _exit(0); 30 _exit(1); 31} 32 33void 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 49int 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 71int main(void) 72{ 73 return test_harness(tm_signal_msr_resv, "tm_signal_msr_resv"); 74} 75