diff --git a/tools/testing/selftests/bpf/prog_tests/struct_ops_epilogue.c b/tools/testing/selftests/bpf/prog_tests/struct_ops_epilogue.c new file mode 100644 index 000000000000..02825d9107ac --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/struct_ops_epilogue.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include "struct_ops_epilogue.skel.h" + +void test_struct_ops_epilogue(void) +{ + RUN_TESTS(struct_ops_epilogue); +} diff --git a/tools/testing/selftests/bpf/progs/struct_ops_epilogue.c b/tools/testing/selftests/bpf/progs/struct_ops_epilogue.c new file mode 100644 index 000000000000..8702c9375023 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/struct_ops_epilogue.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include "bpf_misc.h" + +char _license[] SEC("license") = "GPL"; + +struct st_ops_args { + int a; +}; + +struct bpf_testmod_st_ops { + int (*test_prologue)(struct st_ops_args *args); + int (*test_epilogue)(struct st_ops_args *args); + int (*test_pro_epilogue)(struct st_ops_args *args); + struct module *owner; +}; + +__success +__xlated("0: *(u64 *)(r10 -8) = r1") +__xlated("1: r0 = 0") +__xlated("2: r1 = *(u64 *)(r10 -8)") +__xlated("3: r1 = *(u64 *)(r1 +0)") +__xlated("4: r6 = *(u32 *)(r1 +0)") +__xlated("5: w6 += 10000") +__xlated("6: *(u32 *)(r1 +0) = r6") +__xlated("7: r6 = r1") +__xlated("8: call kernel-function") +__xlated("9: r1 = r6") +__xlated("10: call kernel-function") +__xlated("11: w0 *= 2") +__xlated("12: exit") +SEC("struct_ops/test_epilogue") +__naked int test_epilogue(void) +{ + asm volatile ( + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +__success +__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") +__xlated("10: r0 = 0") +__xlated("11: exit") +SEC("struct_ops/test_prologue") +__naked int test_prologue(void) +{ + asm volatile ( + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC(".struct_ops.link") +struct bpf_testmod_st_ops st_ops = { + .test_epilogue = (void *)test_epilogue, + .test_prologue = (void *)test_prologue, +};