asm-extable.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. #ifndef __ASM_ASM_EXTABLE_H
  3. #define __ASM_ASM_EXTABLE_H
  4. #include <linux/bits.h>
  5. #include <asm/gpr-num.h>
  6. #define EX_TYPE_NONE 0
  7. #define EX_TYPE_BPF 1
  8. #define EX_TYPE_UACCESS_ERR_ZERO 2
  9. #define EX_TYPE_KACCESS_ERR_ZERO 3
  10. #define EX_TYPE_UACCESS_CPY 4
  11. #define EX_TYPE_LOAD_UNALIGNED_ZEROPAD 5
  12. /* Data fields for EX_TYPE_UACCESS_ERR_ZERO */
  13. #define EX_DATA_REG_ERR_SHIFT 0
  14. #define EX_DATA_REG_ERR GENMASK(4, 0)
  15. #define EX_DATA_REG_ZERO_SHIFT 5
  16. #define EX_DATA_REG_ZERO GENMASK(9, 5)
  17. /* Data fields for EX_TYPE_LOAD_UNALIGNED_ZEROPAD */
  18. #define EX_DATA_REG_DATA_SHIFT 0
  19. #define EX_DATA_REG_DATA GENMASK(4, 0)
  20. #define EX_DATA_REG_ADDR_SHIFT 5
  21. #define EX_DATA_REG_ADDR GENMASK(9, 5)
  22. /* Data fields for EX_TYPE_UACCESS_CPY */
  23. #define EX_DATA_UACCESS_WRITE BIT(0)
  24. #ifdef __ASSEMBLER__
  25. #define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
  26. .pushsection __ex_table, "a"; \
  27. .align 2; \
  28. .long ((insn) - .); \
  29. .long ((fixup) - .); \
  30. .short (type); \
  31. .short (data); \
  32. .popsection;
  33. #define EX_DATA_REG(reg, gpr) \
  34. (.L__gpr_num_##gpr << EX_DATA_REG_##reg##_SHIFT)
  35. #define _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero) \
  36. __ASM_EXTABLE_RAW(insn, fixup, \
  37. EX_TYPE_UACCESS_ERR_ZERO, \
  38. ( \
  39. EX_DATA_REG(ERR, err) | \
  40. EX_DATA_REG(ZERO, zero) \
  41. ))
  42. #define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) \
  43. _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, wzr)
  44. #define _ASM_EXTABLE_UACCESS(insn, fixup) \
  45. _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, wzr, wzr)
  46. /*
  47. * Create an exception table entry for uaccess `insn`, which will branch to `fixup`
  48. * when an unhandled fault is taken.
  49. */
  50. .macro _asm_extable_uaccess, insn, fixup
  51. _ASM_EXTABLE_UACCESS(\insn, \fixup)
  52. .endm
  53. /*
  54. * Create an exception table entry for `insn` if `fixup` is provided. Otherwise
  55. * do nothing.
  56. */
  57. .macro _cond_uaccess_extable, insn, fixup
  58. .ifnc \fixup,
  59. _asm_extable_uaccess \insn, \fixup
  60. .endif
  61. .endm
  62. .macro _asm_extable_uaccess_cpy, insn, fixup, uaccess_is_write
  63. __ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_UACCESS_CPY, \uaccess_is_write)
  64. .endm
  65. #else /* __ASSEMBLER__ */
  66. #include <linux/stringify.h>
  67. #define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
  68. ".pushsection __ex_table, \"a\"\n" \
  69. ".align 2\n" \
  70. ".long ((" insn ") - .)\n" \
  71. ".long ((" fixup ") - .)\n" \
  72. ".short (" type ")\n" \
  73. ".short (" data ")\n" \
  74. ".popsection\n"
  75. #define EX_DATA_REG(reg, gpr) \
  76. "((.L__gpr_num_" #gpr ") << " __stringify(EX_DATA_REG_##reg##_SHIFT) ")"
  77. #define _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero) \
  78. __DEFINE_ASM_GPR_NUMS \
  79. __ASM_EXTABLE_RAW(#insn, #fixup, \
  80. __stringify(EX_TYPE_UACCESS_ERR_ZERO), \
  81. "(" \
  82. EX_DATA_REG(ERR, err) " | " \
  83. EX_DATA_REG(ZERO, zero) \
  84. ")")
  85. #define _ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, err, zero) \
  86. __DEFINE_ASM_GPR_NUMS \
  87. __ASM_EXTABLE_RAW(#insn, #fixup, \
  88. __stringify(EX_TYPE_KACCESS_ERR_ZERO), \
  89. "(" \
  90. EX_DATA_REG(ERR, err) " | " \
  91. EX_DATA_REG(ZERO, zero) \
  92. ")")
  93. #define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) \
  94. _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, wzr)
  95. #define _ASM_EXTABLE_UACCESS(insn, fixup) \
  96. _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, wzr, wzr)
  97. #define _ASM_EXTABLE_KACCESS_ERR(insn, fixup, err) \
  98. _ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, err, wzr)
  99. #define _ASM_EXTABLE_KACCESS(insn, fixup) \
  100. _ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, wzr, wzr)
  101. #define _ASM_EXTABLE_LOAD_UNALIGNED_ZEROPAD(insn, fixup, data, addr) \
  102. __DEFINE_ASM_GPR_NUMS \
  103. __ASM_EXTABLE_RAW(#insn, #fixup, \
  104. __stringify(EX_TYPE_LOAD_UNALIGNED_ZEROPAD), \
  105. "(" \
  106. EX_DATA_REG(DATA, data) " | " \
  107. EX_DATA_REG(ADDR, addr) \
  108. ")")
  109. #endif /* __ASSEMBLER__ */
  110. #endif /* __ASM_ASM_EXTABLE_H */