tm-tmspr.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright 2015, Michael Neuling, IBM Corp.
  4. *
  5. * Original: Michael Neuling 3/4/2014
  6. * Modified: Rashmica Gupta 8/12/2015
  7. *
  8. * Check if any of the Transaction Memory SPRs get corrupted.
  9. * - TFIAR - stores address of location of transaction failure
  10. * - TFHAR - stores address of software failure handler (if transaction
  11. * fails)
  12. * - TEXASR - lots of info about the transacion(s)
  13. *
  14. * (1) create more threads than cpus
  15. * (2) in each thread:
  16. * (a) set TFIAR and TFHAR a unique value
  17. * (b) loop for awhile, continually checking to see if
  18. * either register has been corrupted.
  19. *
  20. * (3) Loop:
  21. * (a) begin transaction
  22. * (b) abort transaction
  23. * (c) check TEXASR to see if FS has been corrupted
  24. */
  25. #define _GNU_SOURCE
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <pthread.h>
  30. #include <string.h>
  31. #include "utils.h"
  32. #include "tm.h"
  33. int num_loops = 1000000;
  34. int passed = 1;
  35. void tfiar_tfhar(void *in)
  36. {
  37. unsigned long tfhar, tfhar_rd, tfiar, tfiar_rd;
  38. int i;
  39. /* TFIAR: Last bit has to be high so userspace can read register */
  40. tfiar = ((unsigned long)in) + 1;
  41. tfiar += 2;
  42. mtspr(SPRN_TFIAR, tfiar);
  43. /* TFHAR: Last two bits are reserved */
  44. tfhar = ((unsigned long)in);
  45. tfhar &= ~0x3UL;
  46. tfhar += 4;
  47. mtspr(SPRN_TFHAR, tfhar);
  48. for (i = 0; i < num_loops; i++) {
  49. tfhar_rd = mfspr(SPRN_TFHAR);
  50. tfiar_rd = mfspr(SPRN_TFIAR);
  51. if ( (tfhar != tfhar_rd) || (tfiar != tfiar_rd) ) {
  52. passed = 0;
  53. return;
  54. }
  55. }
  56. return;
  57. }
  58. void texasr(void *in)
  59. {
  60. unsigned long i;
  61. uint64_t result = 0;
  62. for (i = 0; i < num_loops; i++) {
  63. asm __volatile__(
  64. "tbegin.;"
  65. "beq 3f ;"
  66. "tabort. 0 ;"
  67. "tend.;"
  68. /* Abort handler */
  69. "3: ;"
  70. ::: "memory");
  71. /* Check the TEXASR */
  72. result = mfspr(SPRN_TEXASR);
  73. if ((result & TEXASR_FS) == 0) {
  74. passed = 0;
  75. return;
  76. }
  77. }
  78. return;
  79. }
  80. int test_tmspr()
  81. {
  82. pthread_t *thread;
  83. int thread_num;
  84. unsigned long i;
  85. SKIP_IF(!have_htm());
  86. SKIP_IF(htm_is_synthetic());
  87. /* To cause some context switching */
  88. thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN);
  89. thread = malloc(thread_num * sizeof(pthread_t));
  90. if (thread == NULL)
  91. return EXIT_FAILURE;
  92. /* Test TFIAR and TFHAR */
  93. for (i = 0; i < thread_num; i += 2) {
  94. if (pthread_create(&thread[i], NULL, (void *)tfiar_tfhar,
  95. (void *)i))
  96. return EXIT_FAILURE;
  97. }
  98. /* Test TEXASR */
  99. for (i = 1; i < thread_num; i += 2) {
  100. if (pthread_create(&thread[i], NULL, (void *)texasr, (void *)i))
  101. return EXIT_FAILURE;
  102. }
  103. for (i = 0; i < thread_num; i++) {
  104. if (pthread_join(thread[i], NULL) != 0)
  105. return EXIT_FAILURE;
  106. }
  107. free(thread);
  108. if (passed)
  109. return 0;
  110. else
  111. return 1;
  112. }
  113. int main(int argc, char *argv[])
  114. {
  115. if (argc > 1) {
  116. if (strcmp(argv[1], "-h") == 0) {
  117. printf("Syntax:\t [<num loops>]\n");
  118. return 0;
  119. } else {
  120. num_loops = atoi(argv[1]);
  121. }
  122. }
  123. return test_harness(test_tmspr, "tm_tmspr");
  124. }