1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright 2015, Michael Neuling, IBM Corp. 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Test the kernel's signal delievery code to ensure that we don't 6*4882a593Smuzhiyun * trelaim twice in the kernel signal delivery code. This can happen 7*4882a593Smuzhiyun * if we trigger a signal when in a transaction and the stack pointer 8*4882a593Smuzhiyun * is bogus. 9*4882a593Smuzhiyun * 10*4882a593Smuzhiyun * This test case registers a SEGV handler, sets the stack pointer 11*4882a593Smuzhiyun * (r1) to NULL, starts a transaction and then generates a SEGV. The 12*4882a593Smuzhiyun * SEGV should be handled but we exit here as the stack pointer is 13*4882a593Smuzhiyun * invalid and hance we can't sigreturn. We only need to check that 14*4882a593Smuzhiyun * this flow doesn't crash the kernel. 15*4882a593Smuzhiyun */ 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #include <unistd.h> 18*4882a593Smuzhiyun #include <sys/types.h> 19*4882a593Smuzhiyun #include <sys/wait.h> 20*4882a593Smuzhiyun #include <stdlib.h> 21*4882a593Smuzhiyun #include <stdio.h> 22*4882a593Smuzhiyun #include <signal.h> 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun #include "utils.h" 25*4882a593Smuzhiyun #include "tm.h" 26*4882a593Smuzhiyun signal_segv(int signum)27*4882a593Smuzhiyunvoid signal_segv(int signum) 28*4882a593Smuzhiyun { 29*4882a593Smuzhiyun /* This should never actually run since stack is foobar */ 30*4882a593Smuzhiyun exit(1); 31*4882a593Smuzhiyun } 32*4882a593Smuzhiyun tm_signal_stack()33*4882a593Smuzhiyunint tm_signal_stack() 34*4882a593Smuzhiyun { 35*4882a593Smuzhiyun int pid; 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun SKIP_IF(!have_htm()); 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun pid = fork(); 40*4882a593Smuzhiyun if (pid < 0) 41*4882a593Smuzhiyun exit(1); 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun if (pid) { /* Parent */ 44*4882a593Smuzhiyun /* 45*4882a593Smuzhiyun * It's likely the whole machine will crash here so if 46*4882a593Smuzhiyun * the child ever exits, we are good. 47*4882a593Smuzhiyun */ 48*4882a593Smuzhiyun wait(NULL); 49*4882a593Smuzhiyun return 0; 50*4882a593Smuzhiyun } 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun /* 53*4882a593Smuzhiyun * The flow here is: 54*4882a593Smuzhiyun * 1) register a signal handler (so signal delievery occurs) 55*4882a593Smuzhiyun * 2) make stack pointer (r1) = NULL 56*4882a593Smuzhiyun * 3) start transaction 57*4882a593Smuzhiyun * 4) cause segv 58*4882a593Smuzhiyun */ 59*4882a593Smuzhiyun if (signal(SIGSEGV, signal_segv) == SIG_ERR) 60*4882a593Smuzhiyun exit(1); 61*4882a593Smuzhiyun asm volatile("li 1, 0 ;" /* stack ptr == NULL */ 62*4882a593Smuzhiyun "1:" 63*4882a593Smuzhiyun "tbegin.;" 64*4882a593Smuzhiyun "beq 1b ;" /* retry forever */ 65*4882a593Smuzhiyun "tsuspend.;" 66*4882a593Smuzhiyun "ld 2, 0(1) ;" /* trigger segv" */ 67*4882a593Smuzhiyun : : : "memory"); 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun /* This should never get here due to above segv */ 70*4882a593Smuzhiyun return 1; 71*4882a593Smuzhiyun } 72*4882a593Smuzhiyun main(void)73*4882a593Smuzhiyunint main(void) 74*4882a593Smuzhiyun { 75*4882a593Smuzhiyun return test_harness(tm_signal_stack, "tm_signal_stack"); 76*4882a593Smuzhiyun } 77