]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/perf/tests/llvm.c
Merge remote-tracking branch 'edac-amd/for-next'
[karo-tx-linux.git] / tools / perf / tests / llvm.c
1 #include <stdio.h>
2 #include <bpf/libbpf.h>
3 #include <util/llvm-utils.h>
4 #include <util/cache.h>
5 #include "llvm.h"
6 #include "tests.h"
7 #include "debug.h"
8
9 static int perf_config_cb(const char *var, const char *val,
10                           void *arg __maybe_unused)
11 {
12         return perf_default_config(var, val, arg);
13 }
14
15 #ifdef HAVE_LIBBPF_SUPPORT
16 static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
17 {
18         struct bpf_object *obj;
19
20         obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
21         if (IS_ERR(obj))
22                 return TEST_FAIL;
23         bpf_object__close(obj);
24         return TEST_OK;
25 }
26 #else
27 static int test__bpf_parsing(void *obj_buf __maybe_unused,
28                              size_t obj_buf_sz __maybe_unused)
29 {
30         pr_debug("Skip bpf parsing\n");
31         return TEST_OK;
32 }
33 #endif
34
35 static struct {
36         const char *source;
37         const char *desc;
38         bool should_load_fail;
39 } bpf_source_table[__LLVM_TESTCASE_MAX] = {
40         [LLVM_TESTCASE_BASE] = {
41                 .source = test_llvm__bpf_base_prog,
42                 .desc = "Basic BPF llvm compiling test",
43         },
44         [LLVM_TESTCASE_KBUILD] = {
45                 .source = test_llvm__bpf_test_kbuild_prog,
46                 .desc = "Test kbuild searching",
47         },
48         [LLVM_TESTCASE_BPF_PROLOGUE] = {
49                 .source = test_llvm__bpf_test_prologue_prog,
50                 .desc = "Compile source for BPF prologue generation test",
51         },
52         [LLVM_TESTCASE_BPF_RELOCATION] = {
53                 .source = test_llvm__bpf_test_relocation,
54                 .desc = "Compile source for BPF relocation test",
55                 .should_load_fail = true,
56         },
57 };
58
59 int
60 test_llvm__fetch_bpf_obj(void **p_obj_buf,
61                          size_t *p_obj_buf_sz,
62                          enum test_llvm__testcase idx,
63                          bool force,
64                          bool *should_load_fail)
65 {
66         const char *source;
67         const char *desc;
68         const char *tmpl_old, *clang_opt_old;
69         char *tmpl_new = NULL, *clang_opt_new = NULL;
70         int err, old_verbose, ret = TEST_FAIL;
71
72         if (idx >= __LLVM_TESTCASE_MAX)
73                 return TEST_FAIL;
74
75         source = bpf_source_table[idx].source;
76         desc = bpf_source_table[idx].desc;
77         if (should_load_fail)
78                 *should_load_fail = bpf_source_table[idx].should_load_fail;
79
80         perf_config(perf_config_cb, NULL);
81
82         /*
83          * Skip this test if user's .perfconfig doesn't set [llvm] section
84          * and clang is not found in $PATH, and this is not perf test -v
85          */
86         if (!force && (verbose == 0 &&
87                        !llvm_param.user_set_param &&
88                        llvm__search_clang())) {
89                 pr_debug("No clang and no verbosive, skip this test\n");
90                 return TEST_SKIP;
91         }
92
93         /*
94          * llvm is verbosity when error. Suppress all error output if
95          * not 'perf test -v'.
96          */
97         old_verbose = verbose;
98         if (verbose == 0)
99                 verbose = -1;
100
101         *p_obj_buf = NULL;
102         *p_obj_buf_sz = 0;
103
104         if (!llvm_param.clang_bpf_cmd_template)
105                 goto out;
106
107         if (!llvm_param.clang_opt)
108                 llvm_param.clang_opt = strdup("");
109
110         err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
111                        llvm_param.clang_bpf_cmd_template,
112                        old_verbose ? "" : " 2>/dev/null");
113         if (err < 0)
114                 goto out;
115         err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
116         if (err < 0)
117                 goto out;
118
119         tmpl_old = llvm_param.clang_bpf_cmd_template;
120         llvm_param.clang_bpf_cmd_template = tmpl_new;
121         clang_opt_old = llvm_param.clang_opt;
122         llvm_param.clang_opt = clang_opt_new;
123
124         err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
125
126         llvm_param.clang_bpf_cmd_template = tmpl_old;
127         llvm_param.clang_opt = clang_opt_old;
128
129         verbose = old_verbose;
130         if (err)
131                 goto out;
132
133         ret = TEST_OK;
134 out:
135         free(tmpl_new);
136         free(clang_opt_new);
137         if (ret != TEST_OK)
138                 pr_debug("Failed to compile test case: '%s'\n", desc);
139         return ret;
140 }
141
142 int test__llvm(int subtest)
143 {
144         int ret;
145         void *obj_buf = NULL;
146         size_t obj_buf_sz = 0;
147         bool should_load_fail = false;
148
149         if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
150                 return TEST_FAIL;
151
152         ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
153                                        subtest, false, &should_load_fail);
154
155         if (ret == TEST_OK && !should_load_fail) {
156                 ret = test__bpf_parsing(obj_buf, obj_buf_sz);
157                 if (ret != TEST_OK) {
158                         pr_debug("Failed to parse test case '%s'\n",
159                                  bpf_source_table[subtest].desc);
160                 }
161         }
162         free(obj_buf);
163
164         return ret;
165 }
166
167 int test__llvm_subtest_get_nr(void)
168 {
169         return __LLVM_TESTCASE_MAX;
170 }
171
172 const char *test__llvm_subtest_get_desc(int subtest)
173 {
174         if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
175                 return NULL;
176
177         return bpf_source_table[subtest].desc;
178 }