linux/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
<<
>>
Prefs
   1/*
   2 * Copyright 2015, Michael Neuling, IBM Corp.
   3 * Licensed under GPLv2.
   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
  27void signal_segv(int signum)
  28{
  29        /* This should never actually run since stack is foobar */
  30        exit(1);
  31}
  32
  33int 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
  73int main(void)
  74{
  75        return test_harness(tm_signal_stack, "tm_signal_stack");
  76}
  77