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