From: Martin KaFai Lau <martin.lau@xxxxxxxxxx> This patch changes the .gen_pro/epilogue of the bpf_testmod_st_ops to call kfunc. It will call the inc10 and inc100 kfunc. The __xlated instructions have been adjusted accordinly. The same goes for the __retval. The inc100 kfunc is newly added in this patch which does args->a += 100. Note that it is not in the register_btf_kfunc_id_set(), so no need to declare in the bpf_testmod_kfunc.h. It is enclosed with __bpf_kfunc_{start,end}_defs to avoid the compiler warning. Signed-off-by: Martin KaFai Lau <martin.lau@xxxxxxxxxx> --- .../selftests/bpf/bpf_testmod/bpf_testmod.c | 42 +++++++++++- .../selftests/bpf/prog_tests/pro_epilogue.c | 4 +- .../selftests/bpf/progs/pro_epilogue_kfunc.c | 68 ++++++++++++------- .../bpf/progs/pro_epilogue_subprog.c | 58 ++++++++++------ 4 files changed, 123 insertions(+), 49 deletions(-) diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c index 4c75346376d9..6f745d29e124 100644 --- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c @@ -966,6 +966,16 @@ __bpf_kfunc int bpf_kfunc_st_ops_inc10(struct st_ops_args *args) return args->a; } +__bpf_kfunc_start_defs(); + +__bpf_kfunc int bpf_kfunc_st_ops_inc100(struct st_ops_args *args) +{ + args->a += 100; + return args->a; +} + +__bpf_kfunc_end_defs(); + BTF_KFUNCS_START(bpf_testmod_check_kfunc_ids) BTF_ID_FLAGS(func, bpf_testmod_test_mod_kfunc) BTF_ID_FLAGS(func, bpf_kfunc_call_test1) @@ -1140,6 +1150,10 @@ static int bpf_test_mod_st_ops__test_pro_epilogue(struct st_ops_args *args) return 0; } +BTF_ID_LIST(st_ops_epilogue_kfunc_list) +BTF_ID(func, bpf_kfunc_st_ops_inc10) +BTF_ID(func, bpf_kfunc_st_ops_inc100) + static int st_ops_gen_prologue(struct bpf_insn *insn_buf, bool direct_write, const struct bpf_prog *prog, struct module **module) { @@ -1153,13 +1167,28 @@ static int st_ops_gen_prologue(struct bpf_insn *insn_buf, bool direct_write, * r7 = r6->a; * r7 += 1000; * r6->a = r7; + * r7 = r1; + * r1 = r6; + * bpf_kfunc_st_ops_in10(r1) + * r1 = r6; + * bpf_kfunc_st_ops_in100(r1) + * r1 = r7; */ *insn++ = BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0); *insn++ = BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, offsetof(struct st_ops_args, a)); *insn++ = BPF_ALU32_IMM(BPF_ADD, BPF_REG_7, 1000); *insn++ = BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, offsetof(struct st_ops_args, a)); + *insn++ = BPF_MOV64_REG(BPF_REG_7, BPF_REG_1); + *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_6); + *insn++ = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, + st_ops_epilogue_kfunc_list[0]); + *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_6); + *insn++ = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, + st_ops_epilogue_kfunc_list[1]); + *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_7); *insn++ = prog->insnsi[0]; + *module = THIS_MODULE; return insn - insn_buf; } @@ -1177,7 +1206,10 @@ static int st_ops_gen_epilogue(struct bpf_insn *insn_buf, const struct bpf_prog * r6 = r1->a; * r6 += 10000; * r1->a = r6; - * r0 = r6; + * r6 = r1; + * bpf_kfunc_st_ops_in10(r1) + * r1 = r6; + * bpf_kfunc_st_ops_in100(r1) * r0 *= 2; * BPF_EXIT; */ @@ -1186,10 +1218,16 @@ static int st_ops_gen_epilogue(struct bpf_insn *insn_buf, const struct bpf_prog *insn++ = BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, offsetof(struct st_ops_args, a)); *insn++ = BPF_ALU32_IMM(BPF_ADD, BPF_REG_6, 10000); *insn++ = BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offsetof(struct st_ops_args, a)); - *insn++ = BPF_MOV32_REG(BPF_REG_0, BPF_REG_6); + *insn++ = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1); + *insn++ = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, + st_ops_epilogue_kfunc_list[0]); + *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_6); + *insn++ = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, + st_ops_epilogue_kfunc_list[1]); *insn++ = BPF_ALU32_IMM(BPF_MUL, BPF_REG_0, 2); *insn++ = BPF_EXIT_INSN(); + *module = THIS_MODULE; return insn - insn_buf; } diff --git a/tools/testing/selftests/bpf/prog_tests/pro_epilogue.c b/tools/testing/selftests/bpf/prog_tests/pro_epilogue.c index 98de677c55a9..db6e98096335 100644 --- a/tools/testing/selftests/bpf/prog_tests/pro_epilogue.c +++ b/tools/testing/selftests/bpf/prog_tests/pro_epilogue.c @@ -34,8 +34,8 @@ static void test_tailcall(void) prog_fd = bpf_program__fd(skel->progs.syscall_epilogue_tailcall); err = bpf_prog_test_run_opts(prog_fd, &topts); ASSERT_OK(err, "bpf_prog_test_run_opts"); - ASSERT_EQ(args.a, 10001, "args.a"); - ASSERT_EQ(topts.retval, 10001 * 2, "topts.retval"); + ASSERT_EQ(args.a, 10111, "args.a"); + ASSERT_EQ(topts.retval, 10111 * 2, "topts.retval"); done: epilogue_tailcall__destroy(skel); diff --git a/tools/testing/selftests/bpf/progs/pro_epilogue_kfunc.c b/tools/testing/selftests/bpf/progs/pro_epilogue_kfunc.c index 7d1124cf4942..2bd306f16610 100644 --- a/tools/testing/selftests/bpf/progs/pro_epilogue_kfunc.c +++ b/tools/testing/selftests/bpf/progs/pro_epilogue_kfunc.c @@ -28,13 +28,19 @@ __xlated("0: r6 = *(u64 *)(r1 +0)") __xlated("1: r7 = *(u32 *)(r6 +0)") __xlated("2: w7 += 1000") __xlated("3: *(u32 *)(r6 +0) = r7") -/* main prog */ -__xlated("4: r1 = *(u64 *)(r1 +0)") -__xlated("5: r6 = r1") +__xlated("4: r7 = r1") +__xlated("5: r1 = r6") __xlated("6: call kernel-function") __xlated("7: r1 = r6") -__xlated("8: call pc+1") -__xlated("9: exit") +__xlated("8: call kernel-function") +__xlated("9: r1 = r7") +/* main prog */ +__xlated("10: r1 = *(u64 *)(r1 +0)") +__xlated("11: r6 = r1") +__xlated("12: call kernel-function") +__xlated("13: r1 = r6") +__xlated("14: call pc+1") +__xlated("15: exit") SEC("struct_ops/test_prologue_kfunc") __naked int test_prologue_kfunc(void) { @@ -65,9 +71,12 @@ __xlated("7: r1 = *(u64 *)(r1 +0)") __xlated("8: r6 = *(u32 *)(r1 +0)") __xlated("9: w6 += 10000") __xlated("10: *(u32 *)(r1 +0) = r6") -__xlated("11: w0 = w6") -__xlated("12: w0 *= 2") -__xlated("13: exit") +__xlated("11: r6 = r1") +__xlated("12: call kernel-function") +__xlated("13: r1 = r6") +__xlated("14: call kernel-function") +__xlated("15: w0 *= 2") +__xlated("16: exit") SEC("struct_ops/test_epilogue_kfunc") __naked int test_epilogue_kfunc(void) { @@ -89,23 +98,32 @@ __xlated("0: r6 = *(u64 *)(r1 +0)") __xlated("1: r7 = *(u32 *)(r6 +0)") __xlated("2: w7 += 1000") __xlated("3: *(u32 *)(r6 +0) = r7") +__xlated("4: r7 = r1") +__xlated("5: r1 = r6") +__xlated("6: call kernel-function") +__xlated("7: r1 = r6") +__xlated("8: call kernel-function") +__xlated("9: r1 = r7") /* save __u64 *ctx to stack */ -__xlated("4: *(u64 *)(r10 -8) = r1") +__xlated("10: *(u64 *)(r10 -8) = r1") /* main prog */ -__xlated("5: r1 = *(u64 *)(r1 +0)") -__xlated("6: r6 = r1") -__xlated("7: call kernel-function") -__xlated("8: r1 = r6") -__xlated("9: call pc+") -/* epilogue */ -__xlated("10: r1 = *(u64 *)(r10 -8)") __xlated("11: r1 = *(u64 *)(r1 +0)") -__xlated("12: r6 = *(u32 *)(r1 +0)") -__xlated("13: w6 += 10000") -__xlated("14: *(u32 *)(r1 +0) = r6") -__xlated("15: w0 = w6") -__xlated("16: w0 *= 2") -__xlated("17: exit") +__xlated("12: r6 = r1") +__xlated("13: call kernel-function") +__xlated("14: r1 = r6") +__xlated("15: call pc+") +/* epilogue */ +__xlated("16: r1 = *(u64 *)(r10 -8)") +__xlated("17: r1 = *(u64 *)(r1 +0)") +__xlated("18: r6 = *(u32 *)(r1 +0)") +__xlated("19: w6 += 10000") +__xlated("20: *(u32 *)(r1 +0) = r6") +__xlated("21: r6 = r1") +__xlated("22: call kernel-function") +__xlated("23: r1 = r6") +__xlated("24: call kernel-function") +__xlated("25: w0 *= 2") +__xlated("26: exit") SEC("struct_ops/test_pro_epilogue_kfunc") __naked int test_pro_epilogue_kfunc(void) { @@ -122,7 +140,7 @@ __naked int test_pro_epilogue_kfunc(void) } SEC("syscall") -__retval(1011) /* PROLOGUE_A [1000] + KFUNC_INC10 + SUBPROG_A [1] */ +__retval(1121) /* PROLOGUE_A [1110] + KFUNC_INC10 + SUBPROG_A [1] */ int syscall_prologue_kfunc(void *ctx) { struct st_ops_args args = {}; @@ -131,7 +149,7 @@ int syscall_prologue_kfunc(void *ctx) } SEC("syscall") -__retval(20022) /* (KFUNC_INC10 + SUBPROG_A [1] + EPILOGUE_A [10000]) * 2 */ +__retval(20242) /* (KFUNC_INC10 + SUBPROG_A [1] + EPILOGUE_A [10110]) * 2 */ int syscall_epilogue_kfunc(void *ctx) { struct st_ops_args args = {}; @@ -140,7 +158,7 @@ int syscall_epilogue_kfunc(void *ctx) } SEC("syscall") -__retval(22022) /* (PROLOGUE_A [1000] + KFUNC_INC10 + SUBPROG_A [1] + EPILOGUE_A [10000]) * 2 */ +__retval(22462) /* (PROLOGUE_A [1110] + KFUNC_INC10 + SUBPROG_A [1] + EPILOGUE_A [10110]) * 2 */ int syscall_pro_epilogue_kfunc(void *ctx) { struct st_ops_args args = {}; diff --git a/tools/testing/selftests/bpf/progs/pro_epilogue_subprog.c b/tools/testing/selftests/bpf/progs/pro_epilogue_subprog.c index c91b1bf30e37..3d9cc25c024b 100644 --- a/tools/testing/selftests/bpf/progs/pro_epilogue_subprog.c +++ b/tools/testing/selftests/bpf/progs/pro_epilogue_subprog.c @@ -21,10 +21,16 @@ __xlated("0: r6 = *(u64 *)(r1 +0)") __xlated("1: r7 = *(u32 *)(r6 +0)") __xlated("2: w7 += 1000") __xlated("3: *(u32 *)(r6 +0) = r7") +__xlated("4: r7 = r1") +__xlated("5: r1 = r6") +__xlated("6: call kernel-function") +__xlated("7: r1 = r6") +__xlated("8: call kernel-function") +__xlated("9: r1 = r7") /* main prog */ -__xlated("4: r1 = *(u64 *)(r1 +0)") -__xlated("5: call pc+1") -__xlated("6: exit") +__xlated("10: r1 = *(u64 *)(r1 +0)") +__xlated("11: call pc+1") +__xlated("12: exit") SEC("struct_ops/test_prologue_subprog") __naked int test_prologue_subprog(void) { @@ -47,9 +53,12 @@ __xlated("4: r1 = *(u64 *)(r1 +0)") __xlated("5: r6 = *(u32 *)(r1 +0)") __xlated("6: w6 += 10000") __xlated("7: *(u32 *)(r1 +0) = r6") -__xlated("8: w0 = w6") -__xlated("9: w0 *= 2") -__xlated("10: exit") +__xlated("8: r6 = r1") +__xlated("9: call kernel-function") +__xlated("10: r1 = r6") +__xlated("11: call kernel-function") +__xlated("12: w0 *= 2") +__xlated("13: exit") SEC("struct_ops/test_epilogue_subprog") __naked int test_epilogue_subprog(void) { @@ -66,20 +75,29 @@ __xlated("0: r6 = *(u64 *)(r1 +0)") __xlated("1: r7 = *(u32 *)(r6 +0)") __xlated("2: w7 += 1000") __xlated("3: *(u32 *)(r6 +0) = r7") +__xlated("4: r7 = r1") +__xlated("5: r1 = r6") +__xlated("6: call kernel-function") +__xlated("7: r1 = r6") +__xlated("8: call kernel-function") +__xlated("9: r1 = r7") /* save __u64 *ctx to stack */ -__xlated("4: *(u64 *)(r10 -8) = r1") +__xlated("10: *(u64 *)(r10 -8) = r1") /* main prog */ -__xlated("5: r1 = *(u64 *)(r1 +0)") -__xlated("6: call pc+") +__xlated("11: r1 = *(u64 *)(r1 +0)") +__xlated("12: call pc+") /* epilogue */ -__xlated("7: r1 = *(u64 *)(r10 -8)") -__xlated("8: r1 = *(u64 *)(r1 +0)") -__xlated("9: r6 = *(u32 *)(r1 +0)") -__xlated("10: w6 += 10000") -__xlated("11: *(u32 *)(r1 +0) = r6") -__xlated("12: w0 = w6") -__xlated("13: w0 *= 2") -__xlated("14: exit") +__xlated("13: r1 = *(u64 *)(r10 -8)") +__xlated("14: r1 = *(u64 *)(r1 +0)") +__xlated("15: r6 = *(u32 *)(r1 +0)") +__xlated("16: w6 += 10000") +__xlated("17: *(u32 *)(r1 +0) = r6") +__xlated("18: r6 = r1") +__xlated("19: call kernel-function") +__xlated("20: r1 = r6") +__xlated("21: call kernel-function") +__xlated("22: w0 *= 2") +__xlated("23: exit") SEC("struct_ops/test_pro_epilogue_subprog") __naked int test_pro_epilogue_subprog(void) { @@ -91,7 +109,7 @@ __naked int test_pro_epilogue_subprog(void) } SEC("syscall") -__retval(1001) /* PROLOGUE_A [1000] + SUBPROG_A [1] */ +__retval(1111) /* PROLOGUE_A [1110] + SUBPROG_A [1] */ int syscall_prologue_subprog(void *ctx) { struct st_ops_args args = {}; @@ -100,7 +118,7 @@ int syscall_prologue_subprog(void *ctx) } SEC("syscall") -__retval(20002) /* (SUBPROG_A [1] + EPILOGUE_A [10000]) * 2 */ +__retval(20222) /* (SUBPROG_A [1] + EPILOGUE_A [10110]) * 2 */ int syscall_epilogue_subprog(void *ctx) { struct st_ops_args args = {}; @@ -109,7 +127,7 @@ int syscall_epilogue_subprog(void *ctx) } SEC("syscall") -__retval(22002) /* (PROLOGUE_A [1000] + SUBPROG_A [1] + EPILOGUE_A [10000]) * 2 */ +__retval(22442) /* (PROLOGUE_A [1110] + SUBPROG_A [1] + EPILOGUE_A [10110]) * 2 */ int syscall_pro_epilogue_subprog(void *ctx) { struct st_ops_args args = {}; -- 2.43.5