#define BTF_TYPES \ .btf_strings = "\0int\0i\0ctx\0callback\0main\0", \ .btf_types = { \ /* 1: int */ BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), \ /* 2: int* */ BTF_PTR_ENC(1), \ /* 3: void* */ BTF_PTR_ENC(0), \ /* 4: int __(void*) */ BTF_FUNC_PROTO_ENC(1, 1), \ BTF_FUNC_PROTO_ARG_ENC(7, 3), \ /* 5: int __(int, int*) */ BTF_FUNC_PROTO_ENC(1, 2), \ BTF_FUNC_PROTO_ARG_ENC(5, 1), \ BTF_FUNC_PROTO_ARG_ENC(7, 2), \ /* 6: main */ BTF_FUNC_ENC(20, 4), \ /* 7: callback */ BTF_FUNC_ENC(11, 5), \ BTF_END_RAW \ } #define MAIN_TYPE 6#define CALLBACK_TYPE 7 /* can't use BPF_CALL_REL, jit_subprogs adjusts IMM & OFF * fields for pseudo calls */#define PSEUDO_CALL_INSN() \ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_CALL, \ INSN_OFF_MASK, INSN_IMM_MASK) /* can't use BPF_FUNC_loop constant, * do_mix_fixups adjusts the IMM field */#define HELPER_CALL_INSN() \ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, INSN_OFF_MASK, INSN_IMM_MASK) { "inline simple bpf_loop call", .insns = { /* main */ /* force verifier state branching to verify logic on first and * subsequent bpf_loop insn processing steps */ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64), BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 2), BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), BPF_JMP_IMM(BPF_JA, 0, 0, 1), BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2), BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6), BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), BPF_EXIT_INSN(), /* callback */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), BPF_EXIT_INSN(), }, .expected_insns = { PSEUDO_CALL_INSN() }, .unexpected_insns = { HELPER_CALL_INSN() }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, .flags = F_NEEDS_JIT_ENABLED, .result = ACCEPT, .runs = 0, .func_info = { { 0, MAIN_TYPE }, { 12, CALLBACK_TYPE } }, .func_info_cnt = 2, BTF_TYPES},{ "don't inline bpf_loop call, flags non-zero", .insns = { /* main */ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64), BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64), BPF_ALU64_REG(BPF_MOV, BPF_REG_7, BPF_REG_0), BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 9), BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 7), BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), BPF_EXIT_INSN(), BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 1), BPF_JMP_IMM(BPF_JA, 0, 0, -10), /* callback */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), BPF_EXIT_INSN(), }, .expected_insns = { HELPER_CALL_INSN() }, .unexpected_insns = { PSEUDO_CALL_INSN() }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, .flags = F_NEEDS_JIT_ENABLED, .result = ACCEPT, .runs = 0, .func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } }, .func_info_cnt = 2, BTF_TYPES},{ "don't inline bpf_loop call, callback non-constant", .insns = { /* main */ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64), BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 4), /* pick a random callback */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 10), BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_JMP_IMM(BPF_JA, 0, 0, 3), BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8), BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), BPF_EXIT_INSN(), /* callback */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), BPF_EXIT_INSN(), /* callback #2 */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), BPF_EXIT_INSN(), }, .expected_insns = { HELPER_CALL_INSN() }, .unexpected_insns = { PSEUDO_CALL_INSN() }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, .flags = F_NEEDS_JIT_ENABLED, .result = ACCEPT, .runs = 0, .func_info = { { 0, MAIN_TYPE }, { 14, CALLBACK_TYPE }, { 16, CALLBACK_TYPE } }, .func_info_cnt = 3, BTF_TYPES},{ "bpf_loop_inline and a dead func", .insns = { /* main */ /* A reference to callback #1 to make verifier count it as a func. * This reference is overwritten below and callback #1 is dead. */ BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 9), BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8), BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), BPF_EXIT_INSN(), /* callback */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), BPF_EXIT_INSN(), /* callback #2 */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), BPF_EXIT_INSN(), }, .expected_insns = { PSEUDO_CALL_INSN() }, .unexpected_insns = { HELPER_CALL_INSN() }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, .flags = F_NEEDS_JIT_ENABLED, .result = ACCEPT, .runs = 0, .func_info = { { 0, MAIN_TYPE }, { 10, CALLBACK_TYPE }, { 12, CALLBACK_TYPE } }, .func_info_cnt = 3, BTF_TYPES},{ "bpf_loop_inline stack locations for loop vars", .insns = { /* main */ BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77), /* bpf_loop call #1 */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 22), BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), /* bpf_loop call #2 */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2), BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 16), BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), /* call func and exit */ BPF_CALL_REL(2), BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), BPF_EXIT_INSN(), /* func */ BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55), BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2), BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6), BPF_RAW_INSN(0, 0, 0, 0, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), BPF_EXIT_INSN(), /* callback */ BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), BPF_EXIT_INSN(), }, .expected_insns = { BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77), SKIP_INSNS(), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24), SKIP_INSNS(), /* offsets are the same as in the first call */ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24), SKIP_INSNS(), BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55), SKIP_INSNS(), /* offsets differ from main because of different offset * in BPF_ST_MEM instruction */ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -56), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -48), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -40), }, .unexpected_insns = { HELPER_CALL_INSN() }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, .flags = F_NEEDS_JIT_ENABLED, .result = ACCEPT, .func_info = { { 0, MAIN_TYPE }, { 16, MAIN_TYPE }, { 25, CALLBACK_TYPE }, }, .func_info_cnt = 3, BTF_TYPES},{ "inline bpf_loop call in a big program", .insns = {}, .fill_helper = bpf_fill_big_prog_with_loop_1, .expected_insns = { PSEUDO_CALL_INSN() }, .unexpected_insns = { HELPER_CALL_INSN() }, .result = ACCEPT, .prog_type = BPF_PROG_TYPE_TRACEPOINT, .flags = F_NEEDS_JIT_ENABLED, .func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } }, .func_info_cnt = 2, BTF_TYPES}, #undef HELPER_CALL_INSN#undef PSEUDO_CALL_INSN#undef CALLBACK_TYPE#undef MAIN_TYPE#undef BTF_TYPES
#define BTF_TYPES \
.btf_strings = "\0int\0i\0ctx\0callback\0main\0", \
.btf_types = { \
/* 1: int */ BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), \
/* 2: int* */ BTF_PTR_ENC(1), \
/* 3: void* */ BTF_PTR_ENC(0), \
/* 4: int __(void*) */ BTF_FUNC_PROTO_ENC(1, 1), \
BTF_FUNC_PROTO_ARG_ENC(7, 3), \
/* 5: int __(int, int*) */ BTF_FUNC_PROTO_ENC(1, 2), \
BTF_FUNC_PROTO_ARG_ENC(5, 1), \
BTF_FUNC_PROTO_ARG_ENC(7, 2), \
/* 6: main */ BTF_FUNC_ENC(20, 4), \
/* 7: callback */ BTF_FUNC_ENC(11, 5), \
BTF_END_RAW \
}
#define MAIN_TYPE 6
#define CALLBACK_TYPE 7
/* can't use BPF_CALL_REL, jit_subprogs adjusts IMM & OFF
* fields for pseudo calls
*/
#define PSEUDO_CALL_INSN() \
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_CALL, \
INSN_OFF_MASK, INSN_IMM_MASK)
/* can't use BPF_FUNC_loop constant,
* do_mix_fixups adjusts the IMM field
*/
#define HELPER_CALL_INSN() \
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, INSN_OFF_MASK, INSN_IMM_MASK)
{
"inline simple bpf_loop call",
.insns = {
/* main */
/* force verifier state branching to verify logic on first and
* subsequent bpf_loop insn processing steps
*/
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 2),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
BPF_JMP_IMM(BPF_JA, 0, 0, 1),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),
BPF_RAW_INSN(0, 0, 0, 0, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
BPF_EXIT_INSN(),
/* callback */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
BPF_EXIT_INSN(),
},
.expected_insns = { PSEUDO_CALL_INSN() },
.unexpected_insns = { HELPER_CALL_INSN() },
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
.flags = F_NEEDS_JIT_ENABLED,
.result = ACCEPT,
.runs = 0,
.func_info = { { 0, MAIN_TYPE }, { 12, CALLBACK_TYPE } },
.func_info_cnt = 2,
BTF_TYPES
},
{
"don't inline bpf_loop call, flags non-zero",
.insns = {
/* main */
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
BPF_ALU64_REG(BPF_MOV, BPF_REG_7, BPF_REG_0),
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 9),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 7),
BPF_RAW_INSN(0, 0, 0, 0, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
BPF_EXIT_INSN(),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 1),
BPF_JMP_IMM(BPF_JA, 0, 0, -10),
/* callback */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
BPF_EXIT_INSN(),
},
.expected_insns = { HELPER_CALL_INSN() },
.unexpected_insns = { PSEUDO_CALL_INSN() },
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
.flags = F_NEEDS_JIT_ENABLED,
.result = ACCEPT,
.runs = 0,
.func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },
.func_info_cnt = 2,
BTF_TYPES
},
{
"don't inline bpf_loop call, callback non-constant",
.insns = {
/* main */
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 4), /* pick a random callback */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 10),
BPF_RAW_INSN(0, 0, 0, 0, 0),
BPF_JMP_IMM(BPF_JA, 0, 0, 3),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),
BPF_RAW_INSN(0, 0, 0, 0, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
BPF_EXIT_INSN(),
/* callback */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
BPF_EXIT_INSN(),
/* callback #2 */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
BPF_EXIT_INSN(),
},
.expected_insns = { HELPER_CALL_INSN() },
.unexpected_insns = { PSEUDO_CALL_INSN() },
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
.flags = F_NEEDS_JIT_ENABLED,
.result = ACCEPT,
.runs = 0,
.func_info = {
{ 0, MAIN_TYPE },
{ 14, CALLBACK_TYPE },
{ 16, CALLBACK_TYPE }
},
.func_info_cnt = 3,
BTF_TYPES
},
{
"bpf_loop_inline and a dead func",
.insns = {
/* main */
/* A reference to callback #1 to make verifier count it as a func.
* This reference is overwritten below and callback #1 is dead.
*/
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 9),
BPF_RAW_INSN(0, 0, 0, 0, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),
BPF_RAW_INSN(0, 0, 0, 0, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
BPF_EXIT_INSN(),
/* callback */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
BPF_EXIT_INSN(),
/* callback #2 */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
BPF_EXIT_INSN(),
},
.expected_insns = { PSEUDO_CALL_INSN() },
.unexpected_insns = { HELPER_CALL_INSN() },
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
.flags = F_NEEDS_JIT_ENABLED,
.result = ACCEPT,
.runs = 0,
.func_info = {
{ 0, MAIN_TYPE },
{ 10, CALLBACK_TYPE },
{ 12, CALLBACK_TYPE }
},
.func_info_cnt = 3,
BTF_TYPES
},
{
"bpf_loop_inline stack locations for loop vars",
.insns = {
/* main */
BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),
/* bpf_loop call #1 */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 22),
BPF_RAW_INSN(0, 0, 0, 0, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
/* bpf_loop call #2 */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 16),
BPF_RAW_INSN(0, 0, 0, 0, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
/* call func and exit */
BPF_CALL_REL(2),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
BPF_EXIT_INSN(),
/* func */
BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),
BPF_RAW_INSN(0, 0, 0, 0, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),
BPF_EXIT_INSN(),
/* callback */
BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),
BPF_EXIT_INSN(),
},
.expected_insns = {
BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),
SKIP_INSNS(),
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),
SKIP_INSNS(),
/* offsets are the same as in the first call */
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),
SKIP_INSNS(),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),
SKIP_INSNS(),
/* offsets differ from main because of different offset
* in BPF_ST_MEM instruction
*/
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -56),
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -48),
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -40),
},
.unexpected_insns = { HELPER_CALL_INSN() },
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
.flags = F_NEEDS_JIT_ENABLED,
.result = ACCEPT,
.func_info = {
{ 0, MAIN_TYPE },
{ 16, MAIN_TYPE },
{ 25, CALLBACK_TYPE },
},
.func_info_cnt = 3,
BTF_TYPES
},
{
"inline bpf_loop call in a big program",
.insns = {},
.fill_helper = bpf_fill_big_prog_with_loop_1,
.expected_insns = { PSEUDO_CALL_INSN() },
.unexpected_insns = { HELPER_CALL_INSN() },
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
.flags = F_NEEDS_JIT_ENABLED,
.func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },
.func_info_cnt = 2,
BTF_TYPES
},
#undef HELPER_CALL_INSN
#undef PSEUDO_CALL_INSN
#undef CALLBACK_TYPE
#undef MAIN_TYPE
#undef BTF_TYPES