lkml.org 
[lkml]   [2015]   [Nov]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 5/7] perf test: Enforce LLVM test: update basic BPF test program
    Date
    This patch replaces the original toy BPF program with previous introduced
    bpf-script-example.c. Dynamically embedded it into 'llvm-src-base.c'.

    The newly introduced BPF program attaches a BPF program to
    'sys_epoll_pwait()'. perf itself never use that syscall, so further test
    can verify their result with it. The program would generate 1 sample
    in every 2 calls of epoll_pwait() system call.

    Since the resuling BPF object is useful, test_llvm__fetch_bpf_obj() is
    introduced for creating BPF objects for source. llvm test is rewritten
    according to it.

    Signed-off-by: He Kuang <hekuang@huawei.com>
    Signed-off-by: Wang Nan <wangnan0@huawei.com>
    Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Zefan Li <lizefan@huawei.com>
    Cc: pi3orama@163.com
    ---
    tools/perf/tests/Build | 9 ++-
    tools/perf/tests/bpf-script-example.c | 4 ++
    tools/perf/tests/llvm.c | 131 ++++++++++++++++++++++++++--------
    tools/perf/tests/llvm.h | 16 +++++
    4 files changed, 129 insertions(+), 31 deletions(-)
    create mode 100644 tools/perf/tests/llvm.h

    diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
    index 50de225..6c095b3 100644
    --- a/tools/perf/tests/Build
    +++ b/tools/perf/tests/Build
    @@ -31,9 +31,16 @@ perf-y += sample-parsing.o
    perf-y += parse-no-sample-id-all.o
    perf-y += kmod-path.o
    perf-y += thread-map.o
    -perf-y += llvm.o
    +perf-y += llvm.o llvm-src-base.o
    perf-y += topology.o

    +$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c
    + $(call rule_mkdir)
    + $(Q)echo '#include <tests/llvm.h>' > $@
    + $(Q)echo 'const char test_llvm__bpf_base_prog[] =' >> $@
    + $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
    + $(Q)echo ';' >> $@
    +
    ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
    perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
    endif
    diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
    index 410a70b..0ec9c2c 100644
    --- a/tools/perf/tests/bpf-script-example.c
    +++ b/tools/perf/tests/bpf-script-example.c
    @@ -1,3 +1,7 @@
    +/*
    + * bpf-script-example.c
    + * Test basic LLVM building
    + */
    #ifndef LINUX_VERSION_CODE
    # error Need LINUX_VERSION_CODE
    # error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
    diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
    index 8f713f6..05683c5 100644
    --- a/tools/perf/tests/llvm.c
    +++ b/tools/perf/tests/llvm.c
    @@ -2,6 +2,7 @@
    #include <bpf/libbpf.h>
    #include <util/llvm-utils.h>
    #include <util/cache.h>
    +#include "llvm.h"
    #include "tests.h"
    #include "debug.h"

    @@ -11,16 +12,6 @@ static int perf_config_cb(const char *var, const char *val,
    return perf_default_config(var, val, arg);
    }

    -/*
    - * Randomly give it a "version" section since we don't really load it
    - * into kernel
    - */
    -static const char test_bpf_prog[] =
    - "__attribute__((section(\"do_fork\"), used)) "
    - "int fork(void *ctx) {return 0;} "
    - "char _license[] __attribute__((section(\"license\"), used)) = \"GPL\";"
    - "int _version __attribute__((section(\"version\"), used)) = 0x40100;";
    -
    #ifdef HAVE_LIBBPF_SUPPORT
    static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
    {
    @@ -28,25 +19,47 @@ static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)

    obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
    if (IS_ERR(obj))
    - return -1;
    + return TEST_FAIL;
    bpf_object__close(obj);
    - return 0;
    + return TEST_OK;
    }
    #else
    static int test__bpf_parsing(void *obj_buf __maybe_unused,
    size_t obj_buf_sz __maybe_unused)
    {
    pr_debug("Skip bpf parsing\n");
    - return 0;
    + return TEST_OK;
    }
    #endif

    -int test__llvm(void)
    +static struct {
    + const char *source;
    + const char *desc;
    +} bpf_source_table[__LLVM_TESTCASE_MAX] = {
    + [LLVM_TESTCASE_BASE] = {
    + .source = test_llvm__bpf_base_prog,
    + .desc = "Basic BPF llvm compiling test",
    + },
    +};
    +
    +
    +int
    +test_llvm__fetch_bpf_obj(void **p_obj_buf,
    + size_t *p_obj_buf_sz,
    + enum test_llvm__testcase index,
    + bool force)
    {
    - char *tmpl_new, *clang_opt_new;
    - void *obj_buf;
    - size_t obj_buf_sz;
    - int err, old_verbose;
    + const char *source;
    + const char *desc;
    + const char *tmpl_old, *clang_opt_old;
    + char *tmpl_new = NULL, *clang_opt_new = NULL;
    + int err, old_verbose, ret = TEST_FAIL;
    +
    + if (index >= __LLVM_TESTCASE_MAX)
    + return TEST_FAIL;
    +
    + source = bpf_source_table[index].source;
    + desc = bpf_source_table[index].desc;

    perf_config(perf_config_cb, NULL);

    @@ -54,42 +67,100 @@ int test__llvm(void)
    * Skip this test if user's .perfconfig doesn't set [llvm] section
    * and clang is not found in $PATH, and this is not perf test -v
    */
    - if (verbose == 0 && !llvm_param.user_set_param && llvm__search_clang()) {
    + if (!force && (verbose == 0 &&
    + !llvm_param.user_set_param &&
    + llvm__search_clang())) {
    pr_debug("No clang and no verbosive, skip this test\n");
    return TEST_SKIP;
    }

    - old_verbose = verbose;
    /*
    * llvm is verbosity when error. Suppress all error output if
    * not 'perf test -v'.
    */
    + old_verbose = verbose;
    if (verbose == 0)
    verbose = -1;

    + *p_obj_buf = NULL;
    + *p_obj_buf_sz = 0;
    +
    if (!llvm_param.clang_bpf_cmd_template)
    - return -1;
    + goto out;

    if (!llvm_param.clang_opt)
    llvm_param.clang_opt = strdup("");

    - err = asprintf(&tmpl_new, "echo '%s' | %s", test_bpf_prog,
    - llvm_param.clang_bpf_cmd_template);
    + err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
    + llvm_param.clang_bpf_cmd_template,
    + old_verbose ? "" : " 2>/dev/null");
    if (err < 0)
    - return -1;
    + goto out;
    err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
    if (err < 0)
    - return -1;
    + goto out;

    + tmpl_old = llvm_param.clang_bpf_cmd_template;
    llvm_param.clang_bpf_cmd_template = tmpl_new;
    + clang_opt_old = llvm_param.clang_opt;
    llvm_param.clang_opt = clang_opt_new;
    - err = llvm__compile_bpf("-", &obj_buf, &obj_buf_sz);
    +
    + err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
    +
    + llvm_param.clang_bpf_cmd_template = tmpl_old;
    + llvm_param.clang_opt = clang_opt_old;

    verbose = old_verbose;
    if (err)
    - return TEST_FAIL;
    + goto out;
    +
    + ret = TEST_OK;
    +out:
    + free(tmpl_new);
    + free(clang_opt_new);
    + if (ret != TEST_OK)
    + pr_debug("Failed to compile test case: '%s'\n", desc);
    + return ret;
    +}

    - err = test__bpf_parsing(obj_buf, obj_buf_sz);
    - free(obj_buf);
    - return err;
    +int test__llvm(void)
    +{
    + enum test_llvm__testcase i;
    +
    + for (i = 0; i < __LLVM_TESTCASE_MAX; i++) {
    + int ret;
    + void *obj_buf = NULL;
    + size_t obj_buf_sz = 0;
    +
    + ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
    + i, false);
    +
    + if (ret == TEST_OK) {
    + ret = test__bpf_parsing(obj_buf, obj_buf_sz);
    + if (ret != TEST_OK)
    + pr_debug("Failed to parse test case '%s'\n",
    + bpf_source_table[i].desc);
    + }
    + free(obj_buf);
    +
    + switch (ret) {
    + case TEST_SKIP:
    + return TEST_SKIP;
    + case TEST_OK:
    + break;
    + default:
    + /*
    + * Test 0 is the basic LLVM test. If test 0
    + * fail, the basic LLVM support not functional
    + * so the whole test should fail. If other test
    + * case fail, it can be fixed by adjusting
    + * config so don't report error.
    + */
    + if (i == 0)
    + return TEST_FAIL;
    + else
    + return TEST_SKIP;
    + }
    + }
    + return TEST_OK;
    }
    diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
    new file mode 100644
    index 0000000..bd63cee
    --- /dev/null
    +++ b/tools/perf/tests/llvm.h
    @@ -0,0 +1,16 @@
    +#ifndef PERF_TEST_LLVM_H
    +#define PERF_TEST_LLVM_H
    +
    +#include <stddef.h> /* for size_t */
    +#include <stdbool.h> /* for bool */
    +
    +extern const char test_llvm__bpf_base_prog[];
    +
    +enum test_llvm__testcase {
    + LLVM_TESTCASE_BASE,
    + __LLVM_TESTCASE_MAX,
    +};
    +
    +int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
    + enum test_llvm__testcase index, bool force);
    +#endif
    --
    1.8.3.4


    \
     
     \ /
      Last update: 2015-11-06 15:01    [W:5.400 / U:0.184 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site