ptrace-tm-spr.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Ptrace test TM SPR registers
  4. *
  5. * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
  6. */
  7. #include "ptrace.h"
  8. #include "tm.h"
  9. /* Tracee and tracer shared data */
  10. struct shared {
  11. int flag;
  12. struct tm_spr_regs regs;
  13. };
  14. unsigned long tfhar;
  15. int shm_id;
  16. struct shared *cptr, *pptr;
  17. int shm_id1;
  18. int *cptr1, *pptr1;
  19. #define TM_KVM_SCHED 0xe0000001ac000001
  20. int validate_tm_spr(struct tm_spr_regs *regs)
  21. {
  22. FAIL_IF(regs->tm_tfhar != tfhar);
  23. FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0));
  24. return TEST_PASS;
  25. }
  26. void tm_spr(void)
  27. {
  28. unsigned long result, texasr;
  29. int ret;
  30. cptr = (struct shared *)shmat(shm_id, NULL, 0);
  31. cptr1 = (int *)shmat(shm_id1, NULL, 0);
  32. trans:
  33. cptr1[0] = 0;
  34. asm __volatile__(
  35. "1: ;"
  36. /* TM failover handler should follow "tbegin.;" */
  37. "mflr 31;"
  38. "bl 4f;" /* $ = TFHAR - 12 */
  39. "4: ;"
  40. "mflr %[tfhar];"
  41. "mtlr 31;"
  42. "tbegin.;"
  43. "beq 2f;"
  44. "tsuspend.;"
  45. "li 8, 1;"
  46. "sth 8, 0(%[cptr1]);"
  47. "tresume.;"
  48. "b .;"
  49. "tend.;"
  50. "li 0, 0;"
  51. "ori %[res], 0, 0;"
  52. "b 3f;"
  53. "2: ;"
  54. "li 0, 1;"
  55. "ori %[res], 0, 0;"
  56. "mfspr %[texasr], %[sprn_texasr];"
  57. "3: ;"
  58. : [tfhar] "=r" (tfhar), [res] "=r" (result),
  59. [texasr] "=r" (texasr), [cptr1] "=b" (cptr1)
  60. : [sprn_texasr] "i" (SPRN_TEXASR)
  61. : "memory", "r0", "r8", "r31"
  62. );
  63. /* There are 2 32bit instructions before tbegin. */
  64. tfhar += 12;
  65. if (result) {
  66. if (!cptr->flag)
  67. goto trans;
  68. ret = validate_tm_spr((struct tm_spr_regs *)&cptr->regs);
  69. shmdt((void *)cptr);
  70. shmdt((void *)cptr1);
  71. if (ret)
  72. exit(1);
  73. exit(0);
  74. }
  75. shmdt((void *)cptr);
  76. shmdt((void *)cptr1);
  77. exit(1);
  78. }
  79. int trace_tm_spr(pid_t child)
  80. {
  81. FAIL_IF(start_trace(child));
  82. FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs));
  83. printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar,
  84. pptr->regs.tm_texasr, pptr->regs.tm_tfiar);
  85. pptr->flag = 1;
  86. FAIL_IF(stop_trace(child));
  87. return TEST_PASS;
  88. }
  89. int ptrace_tm_spr(void)
  90. {
  91. pid_t pid;
  92. int ret, status;
  93. SKIP_IF(!have_htm());
  94. SKIP_IF(htm_is_synthetic());
  95. shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
  96. shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
  97. pid = fork();
  98. if (pid < 0) {
  99. perror("fork() failed");
  100. return TEST_FAIL;
  101. }
  102. if (pid == 0)
  103. tm_spr();
  104. if (pid) {
  105. pptr = (struct shared *)shmat(shm_id, NULL, 0);
  106. pptr1 = (int *)shmat(shm_id1, NULL, 0);
  107. while (!pptr1[0])
  108. asm volatile("" : : : "memory");
  109. ret = trace_tm_spr(pid);
  110. if (ret) {
  111. kill(pid, SIGKILL);
  112. shmdt((void *)pptr);
  113. shmdt((void *)pptr1);
  114. shmctl(shm_id, IPC_RMID, NULL);
  115. shmctl(shm_id1, IPC_RMID, NULL);
  116. return TEST_FAIL;
  117. }
  118. shmdt((void *)pptr);
  119. shmdt((void *)pptr1);
  120. ret = wait(&status);
  121. shmctl(shm_id, IPC_RMID, NULL);
  122. shmctl(shm_id1, IPC_RMID, NULL);
  123. if (ret != pid) {
  124. printf("Child's exit status not captured\n");
  125. return TEST_FAIL;
  126. }
  127. return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
  128. TEST_PASS;
  129. }
  130. return TEST_PASS;
  131. }
  132. int main(int argc, char *argv[])
  133. {
  134. return test_harness(ptrace_tm_spr, "ptrace_tm_spr");
  135. }