tm-signal-stack.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. #include <unistd.h>
  17. #include <sys/types.h>
  18. #include <sys/wait.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <signal.h>
  22. #include "utils.h"
  23. #include "tm.h"
  24. void signal_segv(int signum)
  25. {
  26. /* This should never actually run since stack is foobar */
  27. exit(1);
  28. }
  29. int tm_signal_stack()
  30. {
  31. int pid;
  32. SKIP_IF(!have_htm());
  33. pid = fork();
  34. if (pid < 0)
  35. exit(1);
  36. if (pid) { /* Parent */
  37. /*
  38. * It's likely the whole machine will crash here so if
  39. * the child ever exits, we are good.
  40. */
  41. wait(NULL);
  42. return 0;
  43. }
  44. /*
  45. * The flow here is:
  46. * 1) register a signal handler (so signal delievery occurs)
  47. * 2) make stack pointer (r1) = NULL
  48. * 3) start transaction
  49. * 4) cause segv
  50. */
  51. if (signal(SIGSEGV, signal_segv) == SIG_ERR)
  52. exit(1);
  53. asm volatile("li 1, 0 ;" /* stack ptr == NULL */
  54. "1:"
  55. "tbegin.;"
  56. "beq 1b ;" /* retry forever */
  57. "tsuspend.;"
  58. "ld 2, 0(1) ;" /* trigger segv" */
  59. : : : "memory");
  60. /* This should never get here due to above segv */
  61. return 1;
  62. }
  63. int main(void)
  64. {
  65. return test_harness(tm_signal_stack, "tm_signal_stack");
  66. }