root/tools/testing/selftests/powerpc/tm/tm-signal-stack.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. signal_segv
  2. tm_signal_stack
  3. main

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

/* [<][>][^][v][top][bottom][index][help] */