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