probes.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Common helper functions for kprobes and uprobes
  4. *
  5. * Copyright IBM Corp. 2014
  6. */
  7. #include <linux/errno.h>
  8. #include <asm/kprobes.h>
  9. #include <asm/dis.h>
  10. int probe_is_prohibited_opcode(u16 *insn)
  11. {
  12. if (!is_known_insn((unsigned char *)insn))
  13. return -EINVAL;
  14. switch (insn[0] >> 8) {
  15. case 0x0c: /* bassm */
  16. case 0x0b: /* bsm */
  17. case 0x83: /* diag */
  18. case 0x44: /* ex */
  19. case 0xac: /* stnsm */
  20. case 0xad: /* stosm */
  21. return -EINVAL;
  22. case 0xc6:
  23. switch (insn[0] & 0x0f) {
  24. case 0x00: /* exrl */
  25. return -EINVAL;
  26. }
  27. }
  28. switch (insn[0]) {
  29. case 0x0101: /* pr */
  30. case 0xb25a: /* bsa */
  31. case 0xb240: /* bakr */
  32. case 0xb258: /* bsg */
  33. case 0xb218: /* pc */
  34. case 0xb228: /* pt */
  35. case 0xb98d: /* epsw */
  36. case 0xe560: /* tbegin */
  37. case 0xe561: /* tbeginc */
  38. case 0xb2f8: /* tend */
  39. return -EINVAL;
  40. }
  41. return 0;
  42. }
  43. int probe_get_fixup_type(u16 *insn)
  44. {
  45. /* default fixup method */
  46. int fixup = FIXUP_PSW_NORMAL;
  47. switch (insn[0] >> 8) {
  48. case 0x05: /* balr */
  49. case 0x0d: /* basr */
  50. fixup = FIXUP_RETURN_REGISTER;
  51. /* if r2 = 0, no branch will be taken */
  52. if ((insn[0] & 0x0f) == 0)
  53. fixup |= FIXUP_BRANCH_NOT_TAKEN;
  54. break;
  55. case 0x06: /* bctr */
  56. case 0x07: /* bcr */
  57. fixup = FIXUP_BRANCH_NOT_TAKEN;
  58. break;
  59. case 0x45: /* bal */
  60. case 0x4d: /* bas */
  61. fixup = FIXUP_RETURN_REGISTER;
  62. break;
  63. case 0x47: /* bc */
  64. case 0x46: /* bct */
  65. case 0x86: /* bxh */
  66. case 0x87: /* bxle */
  67. fixup = FIXUP_BRANCH_NOT_TAKEN;
  68. break;
  69. case 0x82: /* lpsw */
  70. fixup = FIXUP_NOT_REQUIRED;
  71. break;
  72. case 0xb2: /* lpswe */
  73. if ((insn[0] & 0xff) == 0xb2)
  74. fixup = FIXUP_NOT_REQUIRED;
  75. break;
  76. case 0xa7: /* bras */
  77. if ((insn[0] & 0x0f) == 0x05)
  78. fixup |= FIXUP_RETURN_REGISTER;
  79. break;
  80. case 0xc0:
  81. if ((insn[0] & 0x0f) == 0x05) /* brasl */
  82. fixup |= FIXUP_RETURN_REGISTER;
  83. break;
  84. case 0xeb:
  85. switch (insn[2] & 0xff) {
  86. case 0x44: /* bxhg */
  87. case 0x45: /* bxleg */
  88. fixup = FIXUP_BRANCH_NOT_TAKEN;
  89. break;
  90. }
  91. break;
  92. case 0xe3: /* bctg */
  93. if ((insn[2] & 0xff) == 0x46)
  94. fixup = FIXUP_BRANCH_NOT_TAKEN;
  95. break;
  96. case 0xec:
  97. switch (insn[2] & 0xff) {
  98. case 0xe5: /* clgrb */
  99. case 0xe6: /* cgrb */
  100. case 0xf6: /* crb */
  101. case 0xf7: /* clrb */
  102. case 0xfc: /* cgib */
  103. case 0xfd: /* cglib */
  104. case 0xfe: /* cib */
  105. case 0xff: /* clib */
  106. fixup = FIXUP_BRANCH_NOT_TAKEN;
  107. break;
  108. }
  109. break;
  110. }
  111. return fixup;
  112. }
  113. int probe_is_insn_relative_long(u16 *insn)
  114. {
  115. /* Check if we have a RIL-b or RIL-c format instruction which
  116. * we need to modify in order to avoid instruction emulation. */
  117. switch (insn[0] >> 8) {
  118. case 0xc0:
  119. if ((insn[0] & 0x0f) == 0x00) /* larl */
  120. return true;
  121. break;
  122. case 0xc4:
  123. switch (insn[0] & 0x0f) {
  124. case 0x02: /* llhrl */
  125. case 0x04: /* lghrl */
  126. case 0x05: /* lhrl */
  127. case 0x06: /* llghrl */
  128. case 0x07: /* sthrl */
  129. case 0x08: /* lgrl */
  130. case 0x0b: /* stgrl */
  131. case 0x0c: /* lgfrl */
  132. case 0x0d: /* lrl */
  133. case 0x0e: /* llgfrl */
  134. case 0x0f: /* strl */
  135. return true;
  136. }
  137. break;
  138. case 0xc6:
  139. switch (insn[0] & 0x0f) {
  140. case 0x02: /* pfdrl */
  141. case 0x04: /* cghrl */
  142. case 0x05: /* chrl */
  143. case 0x06: /* clghrl */
  144. case 0x07: /* clhrl */
  145. case 0x08: /* cgrl */
  146. case 0x0a: /* clgrl */
  147. case 0x0c: /* cgfrl */
  148. case 0x0d: /* crl */
  149. case 0x0e: /* clgfrl */
  150. case 0x0f: /* clrl */
  151. return true;
  152. }
  153. break;
  154. }
  155. return false;
  156. }