1a26f415bSMichael Neuling /* 2a26f415bSMichael Neuling * Copyright 2015, Michael Neuling, IBM Corp. 3a26f415bSMichael Neuling * Licensed under GPLv2. 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 27a26f415bSMichael Neuling void 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 33a26f415bSMichael Neuling int tm_signal_stack() 34a26f415bSMichael Neuling { 35a26f415bSMichael Neuling int pid; 36a26f415bSMichael Neuling 37a26f415bSMichael Neuling SKIP_IF(!have_htm()); 38a26f415bSMichael Neuling 39a26f415bSMichael Neuling pid = fork(); 40a26f415bSMichael Neuling if (pid < 0) 41a26f415bSMichael Neuling exit(1); 42a26f415bSMichael Neuling 43a26f415bSMichael Neuling if (pid) { /* Parent */ 44a26f415bSMichael Neuling /* 45a26f415bSMichael Neuling * It's likely the whole machine will crash here so if 46a26f415bSMichael Neuling * the child ever exits, we are good. 47a26f415bSMichael Neuling */ 48a26f415bSMichael Neuling wait(NULL); 49a26f415bSMichael Neuling return 0; 50a26f415bSMichael Neuling } 51a26f415bSMichael Neuling 52a26f415bSMichael Neuling /* 53a26f415bSMichael Neuling * The flow here is: 54a26f415bSMichael Neuling * 1) register a signal handler (so signal delievery occurs) 55a26f415bSMichael Neuling * 2) make stack pointer (r1) = NULL 56a26f415bSMichael Neuling * 3) start transaction 57a26f415bSMichael Neuling * 4) cause segv 58a26f415bSMichael Neuling */ 59a26f415bSMichael Neuling if (signal(SIGSEGV, signal_segv) == SIG_ERR) 60a26f415bSMichael Neuling exit(1); 61a26f415bSMichael Neuling asm volatile("li 1, 0 ;" /* stack ptr == NULL */ 62a26f415bSMichael Neuling "1:" 63a26f415bSMichael Neuling ".long 0x7C00051D ;" /* tbegin */ 64a26f415bSMichael Neuling "beq 1b ;" /* retry forever */ 65a26f415bSMichael Neuling ".long 0x7C0005DD ; ;" /* tsuspend */ 66a26f415bSMichael Neuling "ld 2, 0(1) ;" /* trigger segv" */ 67a26f415bSMichael Neuling : : : "memory"); 68a26f415bSMichael Neuling 69a26f415bSMichael Neuling /* This should never get here due to above segv */ 70a26f415bSMichael Neuling return 1; 71a26f415bSMichael Neuling } 72a26f415bSMichael Neuling 73a26f415bSMichael Neuling int main(void) 74a26f415bSMichael Neuling { 75a26f415bSMichael Neuling return test_harness(tm_signal_stack, "tm_signal_stack"); 76a26f415bSMichael Neuling } 77