tm-signal-msr-resv.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /*
  2. * Copyright 2015, Michael Neuling, IBM Corp.
  3. * Licensed under GPLv2.
  4. *
  5. * Test the kernel's signal return code to ensure that it doesn't
  6. * crash when both the transactional and suspend MSR bits are set in
  7. * the signal context.
  8. *
  9. * For this test, we send ourselves a SIGUSR1. In the SIGUSR1 handler
  10. * we modify the signal context to set both MSR TM S and T bits (which
  11. * is "reserved" by the PowerISA). When we return from the signal
  12. * handler (implicit sigreturn), the kernel should detect reserved MSR
  13. * value and send us with a SIGSEGV.
  14. */
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <signal.h>
  18. #include <unistd.h>
  19. #include "utils.h"
  20. #include "tm.h"
  21. int segv_expected = 0;
  22. void signal_segv(int signum)
  23. {
  24. if (segv_expected && (signum == SIGSEGV))
  25. _exit(0);
  26. _exit(1);
  27. }
  28. void signal_usr1(int signum, siginfo_t *info, void *uc)
  29. {
  30. ucontext_t *ucp = uc;
  31. /* Link tm checkpointed context to normal context */
  32. ucp->uc_link = ucp;
  33. /* Set all TM bits so that the context is now invalid */
  34. #ifdef __powerpc64__
  35. ucp->uc_mcontext.gp_regs[PT_MSR] |= (7ULL << 32);
  36. #else
  37. ucp->uc_mcontext.uc_regs->gregs[PT_MSR] |= (7ULL);
  38. #endif
  39. /* Should segv on return becuase of invalid context */
  40. segv_expected = 1;
  41. }
  42. int tm_signal_msr_resv()
  43. {
  44. struct sigaction act;
  45. SKIP_IF(!have_htm());
  46. act.sa_sigaction = signal_usr1;
  47. sigemptyset(&act.sa_mask);
  48. act.sa_flags = SA_SIGINFO;
  49. if (sigaction(SIGUSR1, &act, NULL) < 0) {
  50. perror("sigaction sigusr1");
  51. exit(1);
  52. }
  53. if (signal(SIGSEGV, signal_segv) == SIG_ERR)
  54. exit(1);
  55. raise(SIGUSR1);
  56. /* We shouldn't get here as we exit in the segv handler */
  57. return 1;
  58. }
  59. int main(void)
  60. {
  61. return test_harness(tm_signal_msr_resv, "tm_signal_msr_resv");
  62. }