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