diff options
| -rw-r--r-- | tools/perf/MANIFEST | 1 | ||||
| -rw-r--r-- | tools/perf/tests/Build | 1 | ||||
| -rw-r--r-- | tools/perf/tests/builtin-test.c | 4 | ||||
| -rw-r--r-- | tools/perf/tests/llvm.c | 98 | ||||
| -rw-r--r-- | tools/perf/tests/tests.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/llvm-utils.c | 9 | ||||
| -rw-r--r-- | tools/perf/util/llvm-utils.h | 10 |
7 files changed, 124 insertions, 0 deletions
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index d01a0aad5a01..f31f15a5f873 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
| @@ -18,6 +18,7 @@ tools/arch/x86/include/asm/atomic.h | |||
| 18 | tools/arch/x86/include/asm/rmwcc.h | 18 | tools/arch/x86/include/asm/rmwcc.h |
| 19 | tools/lib/traceevent | 19 | tools/lib/traceevent |
| 20 | tools/lib/api | 20 | tools/lib/api |
| 21 | tools/lib/bpf | ||
| 21 | tools/lib/hweight.c | 22 | tools/lib/hweight.c |
| 22 | tools/lib/rbtree.c | 23 | tools/lib/rbtree.c |
| 23 | tools/lib/symbol/kallsyms.c | 24 | tools/lib/symbol/kallsyms.c |
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index d20d6e6ab65b..c1518bdd0f1b 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build | |||
| @@ -32,6 +32,7 @@ perf-y += sample-parsing.o | |||
| 32 | perf-y += parse-no-sample-id-all.o | 32 | perf-y += parse-no-sample-id-all.o |
| 33 | perf-y += kmod-path.o | 33 | perf-y += kmod-path.o |
| 34 | perf-y += thread-map.o | 34 | perf-y += thread-map.o |
| 35 | perf-y += llvm.o | ||
| 35 | 36 | ||
| 36 | perf-$(CONFIG_X86) += perf-time-to-tsc.o | 37 | perf-$(CONFIG_X86) += perf-time-to-tsc.o |
| 37 | 38 | ||
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index c1dde733c3a6..136cd934be66 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
| @@ -175,6 +175,10 @@ static struct test { | |||
| 175 | .func = test__thread_map, | 175 | .func = test__thread_map, |
| 176 | }, | 176 | }, |
| 177 | { | 177 | { |
| 178 | .desc = "Test LLVM searching and compiling", | ||
| 179 | .func = test__llvm, | ||
| 180 | }, | ||
| 181 | { | ||
| 178 | .func = NULL, | 182 | .func = NULL, |
| 179 | }, | 183 | }, |
| 180 | }; | 184 | }; |
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c new file mode 100644 index 000000000000..a337356fd979 --- /dev/null +++ b/tools/perf/tests/llvm.c | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <bpf/libbpf.h> | ||
| 3 | #include <util/llvm-utils.h> | ||
| 4 | #include <util/cache.h> | ||
| 5 | #include "tests.h" | ||
| 6 | #include "debug.h" | ||
| 7 | |||
| 8 | static int perf_config_cb(const char *var, const char *val, | ||
| 9 | void *arg __maybe_unused) | ||
| 10 | { | ||
| 11 | return perf_default_config(var, val, arg); | ||
| 12 | } | ||
| 13 | |||
| 14 | /* | ||
| 15 | * Randomly give it a "version" section since we don't really load it | ||
| 16 | * into kernel | ||
| 17 | */ | ||
| 18 | static const char test_bpf_prog[] = | ||
| 19 | "__attribute__((section(\"do_fork\"), used)) " | ||
| 20 | "int fork(void *ctx) {return 0;} " | ||
| 21 | "char _license[] __attribute__((section(\"license\"), used)) = \"GPL\";" | ||
| 22 | "int _version __attribute__((section(\"version\"), used)) = 0x40100;"; | ||
| 23 | |||
| 24 | #ifdef HAVE_LIBBPF_SUPPORT | ||
| 25 | static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) | ||
| 26 | { | ||
| 27 | struct bpf_object *obj; | ||
| 28 | |||
| 29 | obj = bpf_object__open_buffer(obj_buf, obj_buf_sz); | ||
| 30 | if (!obj) | ||
| 31 | return -1; | ||
| 32 | bpf_object__close(obj); | ||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | #else | ||
| 36 | static int test__bpf_parsing(void *obj_buf __maybe_unused, | ||
| 37 | size_t obj_buf_sz __maybe_unused) | ||
| 38 | { | ||
| 39 | fprintf(stderr, " (skip bpf parsing)"); | ||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | #endif | ||
| 43 | |||
| 44 | int test__llvm(void) | ||
| 45 | { | ||
| 46 | char *tmpl_new, *clang_opt_new; | ||
| 47 | void *obj_buf; | ||
| 48 | size_t obj_buf_sz; | ||
| 49 | int err, old_verbose; | ||
| 50 | |||
| 51 | perf_config(perf_config_cb, NULL); | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Skip this test if user's .perfconfig doesn't set [llvm] section | ||
| 55 | * and clang is not found in $PATH, and this is not perf test -v | ||
| 56 | */ | ||
| 57 | if (verbose == 0 && !llvm_param.user_set_param && llvm__search_clang()) { | ||
| 58 | fprintf(stderr, " (no clang, try 'perf test -v LLVM')"); | ||
| 59 | return TEST_SKIP; | ||
| 60 | } | ||
| 61 | |||
| 62 | old_verbose = verbose; | ||
| 63 | /* | ||
| 64 | * llvm is verbosity when error. Suppress all error output if | ||
| 65 | * not 'perf test -v'. | ||
| 66 | */ | ||
| 67 | if (verbose == 0) | ||
| 68 | verbose = -1; | ||
| 69 | |||
| 70 | if (!llvm_param.clang_bpf_cmd_template) | ||
| 71 | return -1; | ||
| 72 | |||
| 73 | if (!llvm_param.clang_opt) | ||
| 74 | llvm_param.clang_opt = strdup(""); | ||
| 75 | |||
| 76 | err = asprintf(&tmpl_new, "echo '%s' | %s", test_bpf_prog, | ||
| 77 | llvm_param.clang_bpf_cmd_template); | ||
| 78 | if (err < 0) | ||
| 79 | return -1; | ||
| 80 | err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt); | ||
| 81 | if (err < 0) | ||
| 82 | return -1; | ||
| 83 | |||
| 84 | llvm_param.clang_bpf_cmd_template = tmpl_new; | ||
| 85 | llvm_param.clang_opt = clang_opt_new; | ||
| 86 | err = llvm__compile_bpf("-", &obj_buf, &obj_buf_sz); | ||
| 87 | |||
| 88 | verbose = old_verbose; | ||
| 89 | if (err) { | ||
| 90 | if (!verbose) | ||
| 91 | fprintf(stderr, " (use -v to see error message)"); | ||
| 92 | return -1; | ||
| 93 | } | ||
| 94 | |||
| 95 | err = test__bpf_parsing(obj_buf, obj_buf_sz); | ||
| 96 | free(obj_buf); | ||
| 97 | return err; | ||
| 98 | } | ||
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index ebb47d96bc0b..bf113a247987 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
| @@ -62,6 +62,7 @@ int test__fdarray__filter(void); | |||
| 62 | int test__fdarray__add(void); | 62 | int test__fdarray__add(void); |
| 63 | int test__kmod_path__parse(void); | 63 | int test__kmod_path__parse(void); |
| 64 | int test__thread_map(void); | 64 | int test__thread_map(void); |
| 65 | int test__llvm(void); | ||
| 65 | 66 | ||
| 66 | #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__) | 67 | #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__) |
| 67 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 68 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c index 5887bb8c1243..4f6a4780bd5f 100644 --- a/tools/perf/util/llvm-utils.c +++ b/tools/perf/util/llvm-utils.c | |||
| @@ -22,6 +22,7 @@ struct llvm_param llvm_param = { | |||
| 22 | .clang_opt = NULL, | 22 | .clang_opt = NULL, |
| 23 | .kbuild_dir = NULL, | 23 | .kbuild_dir = NULL, |
| 24 | .kbuild_opts = NULL, | 24 | .kbuild_opts = NULL, |
| 25 | .user_set_param = false, | ||
| 25 | }; | 26 | }; |
| 26 | 27 | ||
| 27 | int perf_llvm_config(const char *var, const char *value) | 28 | int perf_llvm_config(const char *var, const char *value) |
| @@ -42,6 +43,7 @@ int perf_llvm_config(const char *var, const char *value) | |||
| 42 | llvm_param.kbuild_opts = strdup(value); | 43 | llvm_param.kbuild_opts = strdup(value); |
| 43 | else | 44 | else |
| 44 | return -1; | 45 | return -1; |
| 46 | llvm_param.user_set_param = true; | ||
| 45 | return 0; | 47 | return 0; |
| 46 | } | 48 | } |
| 47 | 49 | ||
| @@ -397,3 +399,10 @@ errout: | |||
| 397 | *p_obj_buf_sz = 0; | 399 | *p_obj_buf_sz = 0; |
| 398 | return err; | 400 | return err; |
| 399 | } | 401 | } |
| 402 | |||
| 403 | int llvm__search_clang(void) | ||
| 404 | { | ||
| 405 | char clang_path[PATH_MAX]; | ||
| 406 | |||
| 407 | return search_program(llvm_param.clang_path, "clang", clang_path); | ||
| 408 | } | ||
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h index d23adbca120b..5b3cf1c229e2 100644 --- a/tools/perf/util/llvm-utils.h +++ b/tools/perf/util/llvm-utils.h | |||
| @@ -29,6 +29,13 @@ struct llvm_param { | |||
| 29 | * compiling. Should not be used for dynamic compiling. | 29 | * compiling. Should not be used for dynamic compiling. |
| 30 | */ | 30 | */ |
| 31 | const char *kbuild_opts; | 31 | const char *kbuild_opts; |
| 32 | /* | ||
| 33 | * Default is false. If one of the above fields is set by user | ||
| 34 | * explicitly then user_set_llvm is set to true. This is used | ||
| 35 | * for perf test. If user doesn't set anything in .perfconfig | ||
| 36 | * and clang is not found, don't trigger llvm test. | ||
| 37 | */ | ||
| 38 | bool user_set_param; | ||
| 32 | }; | 39 | }; |
| 33 | 40 | ||
| 34 | extern struct llvm_param llvm_param; | 41 | extern struct llvm_param llvm_param; |
| @@ -36,4 +43,7 @@ extern int perf_llvm_config(const char *var, const char *value); | |||
| 36 | 43 | ||
| 37 | extern int llvm__compile_bpf(const char *path, void **p_obj_buf, | 44 | extern int llvm__compile_bpf(const char *path, void **p_obj_buf, |
| 38 | size_t *p_obj_buf_sz); | 45 | size_t *p_obj_buf_sz); |
| 46 | |||
| 47 | /* This function is for test__llvm() use only */ | ||
| 48 | extern int llvm__search_clang(void); | ||
| 39 | #endif | 49 | #endif |
