tm-syscall.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright 2015, Sam Bobroff, IBM Corp.
  4. *
  5. * Test the kernel's system call code to ensure that a system call
  6. * made from within an active HTM transaction is aborted with the
  7. * correct failure code.
  8. * Conversely, ensure that a system call made from within a
  9. * suspended transaction can succeed.
  10. */
  11. #include <stdio.h>
  12. #include <unistd.h>
  13. #include <sys/syscall.h>
  14. #include <asm/tm.h>
  15. #include <sys/time.h>
  16. #include <stdlib.h>
  17. #include "utils.h"
  18. #include "tm.h"
  19. #ifndef PPC_FEATURE2_SCV
  20. #define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */
  21. #endif
  22. extern int getppid_tm_active(void);
  23. extern int getppid_tm_suspended(void);
  24. extern int getppid_scv_tm_active(void);
  25. extern int getppid_scv_tm_suspended(void);
  26. unsigned retries = 0;
  27. #define TEST_DURATION 10 /* seconds */
  28. pid_t getppid_tm(bool scv, bool suspend)
  29. {
  30. int i;
  31. pid_t pid;
  32. for (i = 0; i < TM_RETRIES; i++) {
  33. if (suspend) {
  34. if (scv)
  35. pid = getppid_scv_tm_suspended();
  36. else
  37. pid = getppid_tm_suspended();
  38. } else {
  39. if (scv)
  40. pid = getppid_scv_tm_active();
  41. else
  42. pid = getppid_tm_active();
  43. }
  44. if (pid >= 0)
  45. return pid;
  46. if (failure_is_persistent()) {
  47. if (failure_is_syscall())
  48. return -1;
  49. printf("Unexpected persistent transaction failure.\n");
  50. printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
  51. __builtin_get_texasr(), __builtin_get_tfiar());
  52. exit(-1);
  53. }
  54. retries++;
  55. }
  56. printf("Exceeded limit of %d temporary transaction failures.\n", TM_RETRIES);
  57. printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
  58. __builtin_get_texasr(), __builtin_get_tfiar());
  59. exit(-1);
  60. }
  61. int tm_syscall(void)
  62. {
  63. unsigned count = 0;
  64. struct timeval end, now;
  65. SKIP_IF(!have_htm_nosc());
  66. SKIP_IF(htm_is_synthetic());
  67. setbuf(stdout, NULL);
  68. printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION);
  69. gettimeofday(&end, NULL);
  70. now.tv_sec = TEST_DURATION;
  71. now.tv_usec = 0;
  72. timeradd(&end, &now, &end);
  73. for (count = 0; timercmp(&now, &end, <); count++) {
  74. /*
  75. * Test a syscall within a suspended transaction and verify
  76. * that it succeeds.
  77. */
  78. FAIL_IF(getppid_tm(false, true) == -1); /* Should succeed. */
  79. /*
  80. * Test a syscall within an active transaction and verify that
  81. * it fails with the correct failure code.
  82. */
  83. FAIL_IF(getppid_tm(false, false) != -1); /* Should fail... */
  84. FAIL_IF(!failure_is_persistent()); /* ...persistently... */
  85. FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
  86. /* Now do it all again with scv if it is available. */
  87. if (have_hwcap2(PPC_FEATURE2_SCV)) {
  88. FAIL_IF(getppid_tm(true, true) == -1); /* Should succeed. */
  89. FAIL_IF(getppid_tm(true, false) != -1); /* Should fail... */
  90. FAIL_IF(!failure_is_persistent()); /* ...persistently... */
  91. FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
  92. }
  93. gettimeofday(&now, 0);
  94. }
  95. printf("%d active and suspended transactions behaved correctly.\n", count);
  96. printf("(There were %d transaction retries.)\n", retries);
  97. return 0;
  98. }
  99. int main(void)
  100. {
  101. return test_harness(tm_syscall, "tm_syscall");
  102. }