bpf_loop_inline.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #define BTF_TYPES \
  2. .btf_strings = "\0int\0i\0ctx\0callback\0main\0", \
  3. .btf_types = { \
  4. /* 1: int */ BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), \
  5. /* 2: int* */ BTF_PTR_ENC(1), \
  6. /* 3: void* */ BTF_PTR_ENC(0), \
  7. /* 4: int __(void*) */ BTF_FUNC_PROTO_ENC(1, 1), \
  8. BTF_FUNC_PROTO_ARG_ENC(7, 3), \
  9. /* 5: int __(int, int*) */ BTF_FUNC_PROTO_ENC(1, 2), \
  10. BTF_FUNC_PROTO_ARG_ENC(5, 1), \
  11. BTF_FUNC_PROTO_ARG_ENC(7, 2), \
  12. /* 6: main */ BTF_FUNC_ENC(20, 4), \
  13. /* 7: callback */ BTF_FUNC_ENC(11, 5), \
  14. BTF_END_RAW \
  15. }
  16. #define MAIN_TYPE 6
  17. #define CALLBACK_TYPE 7
  18. /* can't use BPF_CALL_REL, jit_subprogs adjusts IMM & OFF
  19. * fields for pseudo calls
  20. */
  21. #define PSEUDO_CALL_INSN() \
  22. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_CALL, \
  23. INSN_OFF_MASK, INSN_IMM_MASK)
  24. /* can't use BPF_FUNC_loop constant,
  25. * do_mix_fixups adjusts the IMM field
  26. */
  27. #define HELPER_CALL_INSN() \
  28. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, INSN_OFF_MASK, INSN_IMM_MASK)
  29. {
  30. "inline simple bpf_loop call",
  31. .insns = {
  32. /* main */
  33. /* force verifier state branching to verify logic on first and
  34. * subsequent bpf_loop insn processing steps
  35. */
  36. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
  37. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 2),
  38. BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
  39. BPF_JMP_IMM(BPF_JA, 0, 0, 1),
  40. BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
  41. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),
  42. BPF_RAW_INSN(0, 0, 0, 0, 0),
  43. BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
  44. BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
  45. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
  46. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
  47. BPF_EXIT_INSN(),
  48. /* callback */
  49. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
  50. BPF_EXIT_INSN(),
  51. },
  52. .expected_insns = { PSEUDO_CALL_INSN() },
  53. .unexpected_insns = { HELPER_CALL_INSN() },
  54. .prog_type = BPF_PROG_TYPE_TRACEPOINT,
  55. .flags = F_NEEDS_JIT_ENABLED,
  56. .result = ACCEPT,
  57. .runs = 0,
  58. .func_info = { { 0, MAIN_TYPE }, { 12, CALLBACK_TYPE } },
  59. .func_info_cnt = 2,
  60. BTF_TYPES
  61. },
  62. {
  63. "don't inline bpf_loop call, flags non-zero",
  64. .insns = {
  65. /* main */
  66. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
  67. BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_0),
  68. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
  69. BPF_ALU64_REG(BPF_MOV, BPF_REG_7, BPF_REG_0),
  70. BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 9),
  71. BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
  72. BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 0),
  73. BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
  74. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 7),
  75. BPF_RAW_INSN(0, 0, 0, 0, 0),
  76. BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
  77. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
  78. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
  79. BPF_EXIT_INSN(),
  80. BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 1),
  81. BPF_JMP_IMM(BPF_JA, 0, 0, -10),
  82. /* callback */
  83. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
  84. BPF_EXIT_INSN(),
  85. },
  86. .expected_insns = { HELPER_CALL_INSN() },
  87. .unexpected_insns = { PSEUDO_CALL_INSN() },
  88. .prog_type = BPF_PROG_TYPE_TRACEPOINT,
  89. .flags = F_NEEDS_JIT_ENABLED,
  90. .result = ACCEPT,
  91. .runs = 0,
  92. .func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },
  93. .func_info_cnt = 2,
  94. BTF_TYPES
  95. },
  96. {
  97. "don't inline bpf_loop call, callback non-constant",
  98. .insns = {
  99. /* main */
  100. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
  101. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 4), /* pick a random callback */
  102. BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
  103. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 10),
  104. BPF_RAW_INSN(0, 0, 0, 0, 0),
  105. BPF_JMP_IMM(BPF_JA, 0, 0, 3),
  106. BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
  107. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),
  108. BPF_RAW_INSN(0, 0, 0, 0, 0),
  109. BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
  110. BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
  111. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
  112. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
  113. BPF_EXIT_INSN(),
  114. /* callback */
  115. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
  116. BPF_EXIT_INSN(),
  117. /* callback #2 */
  118. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
  119. BPF_EXIT_INSN(),
  120. },
  121. .expected_insns = { HELPER_CALL_INSN() },
  122. .unexpected_insns = { PSEUDO_CALL_INSN() },
  123. .prog_type = BPF_PROG_TYPE_TRACEPOINT,
  124. .flags = F_NEEDS_JIT_ENABLED,
  125. .result = ACCEPT,
  126. .runs = 0,
  127. .func_info = {
  128. { 0, MAIN_TYPE },
  129. { 14, CALLBACK_TYPE },
  130. { 16, CALLBACK_TYPE }
  131. },
  132. .func_info_cnt = 3,
  133. BTF_TYPES
  134. },
  135. {
  136. "bpf_loop_inline and a dead func",
  137. .insns = {
  138. /* main */
  139. /* A reference to callback #1 to make verifier count it as a func.
  140. * This reference is overwritten below and callback #1 is dead.
  141. */
  142. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 9),
  143. BPF_RAW_INSN(0, 0, 0, 0, 0),
  144. BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
  145. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),
  146. BPF_RAW_INSN(0, 0, 0, 0, 0),
  147. BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
  148. BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
  149. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
  150. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
  151. BPF_EXIT_INSN(),
  152. /* callback */
  153. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
  154. BPF_EXIT_INSN(),
  155. /* callback #2 */
  156. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
  157. BPF_EXIT_INSN(),
  158. },
  159. .expected_insns = { PSEUDO_CALL_INSN() },
  160. .unexpected_insns = { HELPER_CALL_INSN() },
  161. .prog_type = BPF_PROG_TYPE_TRACEPOINT,
  162. .flags = F_NEEDS_JIT_ENABLED,
  163. .result = ACCEPT,
  164. .runs = 0,
  165. .func_info = {
  166. { 0, MAIN_TYPE },
  167. { 10, CALLBACK_TYPE },
  168. { 12, CALLBACK_TYPE }
  169. },
  170. .func_info_cnt = 3,
  171. BTF_TYPES
  172. },
  173. {
  174. "bpf_loop_inline stack locations for loop vars",
  175. .insns = {
  176. /* main */
  177. BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),
  178. /* bpf_loop call #1 */
  179. BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
  180. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 22),
  181. BPF_RAW_INSN(0, 0, 0, 0, 0),
  182. BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
  183. BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
  184. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
  185. /* bpf_loop call #2 */
  186. BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
  187. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 16),
  188. BPF_RAW_INSN(0, 0, 0, 0, 0),
  189. BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
  190. BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
  191. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
  192. /* call func and exit */
  193. BPF_CALL_REL(2),
  194. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
  195. BPF_EXIT_INSN(),
  196. /* func */
  197. BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),
  198. BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
  199. BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),
  200. BPF_RAW_INSN(0, 0, 0, 0, 0),
  201. BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
  202. BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
  203. BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
  204. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
  205. BPF_EXIT_INSN(),
  206. /* callback */
  207. BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
  208. BPF_EXIT_INSN(),
  209. },
  210. .expected_insns = {
  211. BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),
  212. SKIP_INSNS(),
  213. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),
  214. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),
  215. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),
  216. SKIP_INSNS(),
  217. /* offsets are the same as in the first call */
  218. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),
  219. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),
  220. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),
  221. SKIP_INSNS(),
  222. BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),
  223. SKIP_INSNS(),
  224. /* offsets differ from main because of different offset
  225. * in BPF_ST_MEM instruction
  226. */
  227. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -56),
  228. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -48),
  229. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -40),
  230. },
  231. .unexpected_insns = { HELPER_CALL_INSN() },
  232. .prog_type = BPF_PROG_TYPE_TRACEPOINT,
  233. .flags = F_NEEDS_JIT_ENABLED,
  234. .result = ACCEPT,
  235. .func_info = {
  236. { 0, MAIN_TYPE },
  237. { 16, MAIN_TYPE },
  238. { 25, CALLBACK_TYPE },
  239. },
  240. .func_info_cnt = 3,
  241. BTF_TYPES
  242. },
  243. {
  244. "inline bpf_loop call in a big program",
  245. .insns = {},
  246. .fill_helper = bpf_fill_big_prog_with_loop_1,
  247. .expected_insns = { PSEUDO_CALL_INSN() },
  248. .unexpected_insns = { HELPER_CALL_INSN() },
  249. .result = ACCEPT,
  250. .prog_type = BPF_PROG_TYPE_TRACEPOINT,
  251. .flags = F_NEEDS_JIT_ENABLED,
  252. .func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },
  253. .func_info_cnt = 2,
  254. BTF_TYPES
  255. },
  256. #undef HELPER_CALL_INSN
  257. #undef PSEUDO_CALL_INSN
  258. #undef CALLBACK_TYPE
  259. #undef MAIN_TYPE
  260. #undef BTF_TYPES