tm-resched-dscr.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Test context switching to see if the DSCR SPR is correctly preserved
  3. * when within a transaction.
  4. *
  5. * Note: We assume that the DSCR has been left at the default value (0)
  6. * for all CPUs.
  7. *
  8. * Method:
  9. *
  10. * Set a value into the DSCR.
  11. *
  12. * Start a transaction, and suspend it (*).
  13. *
  14. * Hard loop checking to see if the transaction has become doomed.
  15. *
  16. * Now that we *may* have been preempted, record the DSCR and TEXASR SPRS.
  17. *
  18. * If the abort was because of a context switch, check the DSCR value.
  19. * Otherwise, try again.
  20. *
  21. * (*) If the transaction is not suspended we can't see the problem because
  22. * the transaction abort handler will restore the DSCR to it's checkpointed
  23. * value before we regain control.
  24. */
  25. #include <inttypes.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <assert.h>
  29. #include <asm/tm.h>
  30. #include "utils.h"
  31. #include "tm.h"
  32. #include "../pmu/lib.h"
  33. #define SPRN_DSCR 0x03
  34. int test_body(void)
  35. {
  36. uint64_t rv, dscr1 = 1, dscr2, texasr;
  37. SKIP_IF(!have_htm());
  38. printf("Check DSCR TM context switch: ");
  39. fflush(stdout);
  40. for (;;) {
  41. asm __volatile__ (
  42. /* set a known value into the DSCR */
  43. "ld 3, %[dscr1];"
  44. "mtspr %[sprn_dscr], 3;"
  45. "li %[rv], 1;"
  46. /* start and suspend a transaction */
  47. "tbegin.;"
  48. "beq 1f;"
  49. "tsuspend.;"
  50. /* hard loop until the transaction becomes doomed */
  51. "2: ;"
  52. "tcheck 0;"
  53. "bc 4, 0, 2b;"
  54. /* record DSCR and TEXASR */
  55. "mfspr 3, %[sprn_dscr];"
  56. "std 3, %[dscr2];"
  57. "mfspr 3, %[sprn_texasr];"
  58. "std 3, %[texasr];"
  59. "tresume.;"
  60. "tend.;"
  61. "li %[rv], 0;"
  62. "1: ;"
  63. : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr)
  64. : [dscr1]"m"(dscr1)
  65. , [sprn_dscr]"i"(SPRN_DSCR), [sprn_texasr]"i"(SPRN_TEXASR)
  66. : "memory", "r3"
  67. );
  68. assert(rv); /* make sure the transaction aborted */
  69. if ((texasr >> 56) != TM_CAUSE_RESCHED) {
  70. continue;
  71. }
  72. if (dscr2 != dscr1) {
  73. printf(" FAIL\n");
  74. return 1;
  75. } else {
  76. printf(" OK\n");
  77. return 0;
  78. }
  79. }
  80. }
  81. static int tm_resched_dscr(void)
  82. {
  83. return eat_cpu(test_body);
  84. }
  85. int main(int argc, const char *argv[])
  86. {
  87. return test_harness(tm_resched_dscr, "tm_resched_dscr");
  88. }