mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-31 16:38:12 +00:00
03d4d13fab
The main purpose of the profiler test to check different llvm generation patterns to make sure the verifier can load these large programs. Note that profiler.inc.h test doesn't follow strict kernel coding style. The code was formatted in the kernel style, but variable declarations are kept as-is to preserve original llvm IR pattern. profiler1.c should pass with older and newer llvm profiler[23].c may fail on older llvm that don't have: https://reviews.llvm.org/D85570 because llvm may do speculative code motion optimization that will generate code like this: // r9 is a pointer to map_value // r7 is a scalar 17: bf 96 00 00 00 00 00 00 r6 = r9 18: 0f 76 00 00 00 00 00 00 r6 += r7 19: a5 07 01 00 01 01 00 00 if r7 < 257 goto +1 20: bf 96 00 00 00 00 00 00 r6 = r9 // r6 is used here The verifier will reject such code with the error: "math between map_value pointer and register with unbounded min value is not allowed" At insn 18 the r7 is indeed unbounded. The later insn 19 checks the bounds and the insn 20 undoes map_value addition. It is currently impossible for the verifier to understand such speculative pointer arithmetic. Hence llvm D85570 addresses it on the compiler side. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20201009011240.48506-4-alexei.starovoitov@gmail.com
72 lines
2.1 KiB
C
72 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright (c) 2020 Facebook */
|
|
#include <test_progs.h>
|
|
#include "progs/profiler.h"
|
|
#include "profiler1.skel.h"
|
|
#include "profiler2.skel.h"
|
|
#include "profiler3.skel.h"
|
|
|
|
static int sanity_run(struct bpf_program *prog)
|
|
{
|
|
struct bpf_prog_test_run_attr test_attr = {};
|
|
__u64 args[] = {1, 2, 3};
|
|
__u32 duration = 0;
|
|
int err, prog_fd;
|
|
|
|
prog_fd = bpf_program__fd(prog);
|
|
test_attr.prog_fd = prog_fd;
|
|
test_attr.ctx_in = args;
|
|
test_attr.ctx_size_in = sizeof(args);
|
|
err = bpf_prog_test_run_xattr(&test_attr);
|
|
if (CHECK(err || test_attr.retval, "test_run",
|
|
"err %d errno %d retval %d duration %d\n",
|
|
err, errno, test_attr.retval, duration))
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
void test_test_profiler(void)
|
|
{
|
|
struct profiler1 *profiler1_skel = NULL;
|
|
struct profiler2 *profiler2_skel = NULL;
|
|
struct profiler3 *profiler3_skel = NULL;
|
|
__u32 duration = 0;
|
|
int err;
|
|
|
|
profiler1_skel = profiler1__open_and_load();
|
|
if (CHECK(!profiler1_skel, "profiler1_skel_load", "profiler1 skeleton failed\n"))
|
|
goto cleanup;
|
|
|
|
err = profiler1__attach(profiler1_skel);
|
|
if (CHECK(err, "profiler1_attach", "profiler1 attach failed: %d\n", err))
|
|
goto cleanup;
|
|
|
|
if (sanity_run(profiler1_skel->progs.raw_tracepoint__sched_process_exec))
|
|
goto cleanup;
|
|
|
|
profiler2_skel = profiler2__open_and_load();
|
|
if (CHECK(!profiler2_skel, "profiler2_skel_load", "profiler2 skeleton failed\n"))
|
|
goto cleanup;
|
|
|
|
err = profiler2__attach(profiler2_skel);
|
|
if (CHECK(err, "profiler2_attach", "profiler2 attach failed: %d\n", err))
|
|
goto cleanup;
|
|
|
|
if (sanity_run(profiler2_skel->progs.raw_tracepoint__sched_process_exec))
|
|
goto cleanup;
|
|
|
|
profiler3_skel = profiler3__open_and_load();
|
|
if (CHECK(!profiler3_skel, "profiler3_skel_load", "profiler3 skeleton failed\n"))
|
|
goto cleanup;
|
|
|
|
err = profiler3__attach(profiler3_skel);
|
|
if (CHECK(err, "profiler3_attach", "profiler3 attach failed: %d\n", err))
|
|
goto cleanup;
|
|
|
|
if (sanity_run(profiler3_skel->progs.raw_tracepoint__sched_process_exec))
|
|
goto cleanup;
|
|
cleanup:
|
|
profiler1__destroy(profiler1_skel);
|
|
profiler2__destroy(profiler2_skel);
|
|
profiler3__destroy(profiler3_skel);
|
|
}
|