inst.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. #ifndef _ASM_POWERPC_INST_H
  3. #define _ASM_POWERPC_INST_H
  4. #include <asm/ppc-opcode.h>
  5. #include <asm/reg.h>
  6. #include <asm/disassemble.h>
  7. #include <asm/uaccess.h>
  8. #define ___get_user_instr(gu_op, dest, ptr) \
  9. ({ \
  10. long __gui_ret; \
  11. u32 __user *__gui_ptr = (u32 __user *)ptr; \
  12. ppc_inst_t __gui_inst; \
  13. unsigned int __prefix, __suffix; \
  14. \
  15. __chk_user_ptr(ptr); \
  16. __gui_ret = gu_op(__prefix, __gui_ptr); \
  17. if (__gui_ret == 0) { \
  18. if (IS_ENABLED(CONFIG_PPC64) && (__prefix >> 26) == OP_PREFIX) { \
  19. __gui_ret = gu_op(__suffix, __gui_ptr + 1); \
  20. __gui_inst = ppc_inst_prefix(__prefix, __suffix); \
  21. } else { \
  22. __gui_inst = ppc_inst(__prefix); \
  23. } \
  24. if (__gui_ret == 0) \
  25. (dest) = __gui_inst; \
  26. } \
  27. __gui_ret; \
  28. })
  29. #define get_user_instr(x, ptr) ___get_user_instr(get_user, x, ptr)
  30. #define __get_user_instr(x, ptr) ___get_user_instr(__get_user, x, ptr)
  31. /*
  32. * Instruction data type for POWER
  33. */
  34. #if defined(CONFIG_PPC64) || defined(__CHECKER__)
  35. static inline u32 ppc_inst_val(ppc_inst_t x)
  36. {
  37. return x.val;
  38. }
  39. #define ppc_inst(x) ((ppc_inst_t){ .val = (x) })
  40. #else
  41. static inline u32 ppc_inst_val(ppc_inst_t x)
  42. {
  43. return x;
  44. }
  45. #define ppc_inst(x) (x)
  46. #endif
  47. static inline int ppc_inst_primary_opcode(ppc_inst_t x)
  48. {
  49. return ppc_inst_val(x) >> 26;
  50. }
  51. #ifdef CONFIG_PPC64
  52. #define ppc_inst_prefix(x, y) ((ppc_inst_t){ .val = (x), .suffix = (y) })
  53. static inline u32 ppc_inst_suffix(ppc_inst_t x)
  54. {
  55. return x.suffix;
  56. }
  57. #else
  58. #define ppc_inst_prefix(x, y) ((void)y, ppc_inst(x))
  59. static inline u32 ppc_inst_suffix(ppc_inst_t x)
  60. {
  61. return 0;
  62. }
  63. #endif /* CONFIG_PPC64 */
  64. static inline ppc_inst_t ppc_inst_read(const u32 *ptr)
  65. {
  66. if (IS_ENABLED(CONFIG_PPC64) && (*ptr >> 26) == OP_PREFIX)
  67. return ppc_inst_prefix(*ptr, *(ptr + 1));
  68. else
  69. return ppc_inst(*ptr);
  70. }
  71. static inline bool ppc_inst_prefixed(ppc_inst_t x)
  72. {
  73. return IS_ENABLED(CONFIG_PPC64) && ppc_inst_primary_opcode(x) == OP_PREFIX;
  74. }
  75. static inline ppc_inst_t ppc_inst_swab(ppc_inst_t x)
  76. {
  77. return ppc_inst_prefix(swab32(ppc_inst_val(x)), swab32(ppc_inst_suffix(x)));
  78. }
  79. static inline bool ppc_inst_equal(ppc_inst_t x, ppc_inst_t y)
  80. {
  81. if (ppc_inst_val(x) != ppc_inst_val(y))
  82. return false;
  83. if (!ppc_inst_prefixed(x))
  84. return true;
  85. return ppc_inst_suffix(x) == ppc_inst_suffix(y);
  86. }
  87. static inline int ppc_inst_len(ppc_inst_t x)
  88. {
  89. return ppc_inst_prefixed(x) ? 8 : 4;
  90. }
  91. /*
  92. * Return the address of the next instruction, if the instruction @value was
  93. * located at @location.
  94. */
  95. static inline u32 *ppc_inst_next(u32 *location, u32 *value)
  96. {
  97. ppc_inst_t tmp;
  98. tmp = ppc_inst_read(value);
  99. return (void *)location + ppc_inst_len(tmp);
  100. }
  101. static inline unsigned long ppc_inst_as_ulong(ppc_inst_t x)
  102. {
  103. if (IS_ENABLED(CONFIG_PPC32))
  104. return ppc_inst_val(x);
  105. else if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
  106. return (u64)ppc_inst_suffix(x) << 32 | ppc_inst_val(x);
  107. else
  108. return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x);
  109. }
  110. static inline void ppc_inst_write(u32 *ptr, ppc_inst_t x)
  111. {
  112. if (!ppc_inst_prefixed(x))
  113. *ptr = ppc_inst_val(x);
  114. else
  115. *(u64 *)ptr = ppc_inst_as_ulong(x);
  116. }
  117. static inline int __copy_inst_from_kernel_nofault(ppc_inst_t *inst, u32 *src)
  118. {
  119. unsigned int val, suffix;
  120. /* See https://github.com/ClangBuiltLinux/linux/issues/1521 */
  121. #if defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 140000
  122. val = suffix = 0;
  123. #endif
  124. __get_kernel_nofault(&val, src, u32, Efault);
  125. if (IS_ENABLED(CONFIG_PPC64) && get_op(val) == OP_PREFIX) {
  126. __get_kernel_nofault(&suffix, src + 1, u32, Efault);
  127. *inst = ppc_inst_prefix(val, suffix);
  128. } else {
  129. *inst = ppc_inst(val);
  130. }
  131. return 0;
  132. Efault:
  133. return -EFAULT;
  134. }
  135. static inline int copy_inst_from_kernel_nofault(ppc_inst_t *inst, u32 *src)
  136. {
  137. if (unlikely(!is_kernel_addr((unsigned long)src)))
  138. return -ERANGE;
  139. return __copy_inst_from_kernel_nofault(inst, src);
  140. }
  141. #endif /* _ASM_POWERPC_INST_H */