Skip to content

Commit

Permalink
selftests/powerpc: Add TM signal with invalid stack test
Browse files Browse the repository at this point in the history
Test the kernels signal generation code to ensure it can handle an
invalid stack pointer when transactional.

Signed-off-by: Michael Neuling <[email protected]>
Tested-by: Anshuman Khandual <[email protected]>
[mpe: Skip if we don't have TM]
Signed-off-by: Michael Ellerman <[email protected]>
  • Loading branch information
mikey authored and mpe committed Dec 14, 2015
1 parent 25007a6 commit a26f415
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 1 deletion.
1 change: 1 addition & 0 deletions tools/testing/selftests/powerpc/tm/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
tm-resched-dscr
tm-syscall
tm-signal-msr-resv
tm-signal-stack
2 changes: 1 addition & 1 deletion tools/testing/selftests/powerpc/tm/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv
TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack

all: $(TEST_PROGS)

Expand Down
76 changes: 76 additions & 0 deletions tools/testing/selftests/powerpc/tm/tm-signal-stack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2015, Michael Neuling, IBM Corp.
* Licensed under GPLv2.
*
* Test the kernel's signal delievery code to ensure that we don't
* trelaim twice in the kernel signal delivery code. This can happen
* if we trigger a signal when in a transaction and the stack pointer
* is bogus.
*
* This test case registers a SEGV handler, sets the stack pointer
* (r1) to NULL, starts a transaction and then generates a SEGV. The
* SEGV should be handled but we exit here as the stack pointer is
* invalid and hance we can't sigreturn. We only need to check that
* this flow doesn't crash the kernel.
*/

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>

#include "utils.h"
#include "tm.h"

void signal_segv(int signum)
{
/* This should never actually run since stack is foobar */
exit(1);
}

int tm_signal_stack()
{
int pid;

SKIP_IF(!have_htm());

pid = fork();
if (pid < 0)
exit(1);

if (pid) { /* Parent */
/*
* It's likely the whole machine will crash here so if
* the child ever exits, we are good.
*/
wait(NULL);
return 0;
}

/*
* The flow here is:
* 1) register a signal handler (so signal delievery occurs)
* 2) make stack pointer (r1) = NULL
* 3) start transaction
* 4) cause segv
*/
if (signal(SIGSEGV, signal_segv) == SIG_ERR)
exit(1);
asm volatile("li 1, 0 ;" /* stack ptr == NULL */
"1:"
".long 0x7C00051D ;" /* tbegin */
"beq 1b ;" /* retry forever */
".long 0x7C0005DD ; ;" /* tsuspend */
"ld 2, 0(1) ;" /* trigger segv" */
: : : "memory");

/* This should never get here due to above segv */
return 1;
}

int main(void)
{
return test_harness(tm_signal_stack, "tm_signal_stack");
}

0 comments on commit a26f415

Please sign in to comment.