diff mbox

[21/31] perf test: Enforce LLVM test, add kbuild test

Message ID 1444826502-49291-22-git-send-email-wangnan0@huawei.com
State New
Headers show

Commit Message

Wang Nan Oct. 14, 2015, 12:41 p.m. UTC
This patch enforces existing LLVM test, makes it compile more than one
BPF source file. The compiled results are stored, can be used for other
testcases. Except the first testcase (named LLVM_TESTCASE_BASE), failures
of other test cases are not considered as failure of the whole test.

Adds a kbuild testcase to check whether kernel headers can be correctly
found.

For example:

 # perf test LLVM

   38: Test LLVM searching and compiling                        : (llvm.kbuild-dir can be fixed) Ok

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/n/ebpf-6yw9eg0ej3l4jnqhinngkw86@git.kernel.org
---
 tools/perf/tests/Build                    |  11 ++-
 tools/perf/tests/bpf-script-example.c     |   4 +
 tools/perf/tests/bpf-script-test-kbuild.c |  21 ++++
 tools/perf/tests/bpf.c                    |   3 +-
 tools/perf/tests/llvm.c                   | 154 ++++++++++++++++++++++--------
 tools/perf/tests/llvm.h                   |  10 +-
 6 files changed, 156 insertions(+), 47 deletions(-)
 create mode 100644 tools/perf/tests/bpf-script-test-kbuild.c

Comments

Namhyung Kim Oct. 19, 2015, 2:42 p.m. UTC | #1
Hi,

On Wed, Oct 14, 2015 at 12:41:32PM +0000, Wang Nan wrote:
> This patch enforces existing LLVM test, makes it compile more than one
> BPF source file. The compiled results are stored, can be used for other
> testcases. Except the first testcase (named LLVM_TESTCASE_BASE), failures
> of other test cases are not considered as failure of the whole test.
> 
> Adds a kbuild testcase to check whether kernel headers can be correctly
> found.
> 
> For example:
> 
>  # perf test LLVM
> 
>    38: Test LLVM searching and compiling                        : (llvm.kbuild-dir can be fixed) Ok

IMHO it'd be better to keep the test result simply as either "Ok" or
"FAILED" and provide details with -v option.

Anyway I found the tracepoint error message is annoying in the current
perf test output.  Will send a fix soon.

Thanks,
Namhyung
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Arnaldo Carvalho de Melo Oct. 19, 2015, 2:53 p.m. UTC | #2
Em Mon, Oct 19, 2015 at 11:42:31PM +0900, Namhyung Kim escreveu:
> Hi,
> 
> On Wed, Oct 14, 2015 at 12:41:32PM +0000, Wang Nan wrote:
> > This patch enforces existing LLVM test, makes it compile more than one
> > BPF source file. The compiled results are stored, can be used for other
> > testcases. Except the first testcase (named LLVM_TESTCASE_BASE), failures
> > of other test cases are not considered as failure of the whole test.
> > 
> > Adds a kbuild testcase to check whether kernel headers can be correctly
> > found.
> > 
> > For example:
> > 
> >  # perf test LLVM
> > 
> >    38: Test LLVM searching and compiling                        : (llvm.kbuild-dir can be fixed) Ok
> 
> IMHO it'd be better to keep the test result simply as either "Ok" or
> "FAILED" and provide details with -v option.

"Skipped" looks more natural here, with the reason for it skipping being shown
only with -v.

Ingo made some comments about 'perf test' output recently, have you read that?

> Anyway I found the tracepoint error message is annoying in the current

You mean all these warnings:

[root@zoo ~]# perf test "parse event" 
 5: parse events tests                                       :  Warning: [sunrpc:xprt_lookup_rqst] function __builtin_constant_p not defined
  Warning: [sunrpc:xprt_transmit] function __builtin_constant_p not defined
  Warning: [sunrpc:xprt_complete_rqst] function __builtin_constant_p not defined
<SNIP>
  Warning: [xen:xen_mmu_set_pud] function sizeof not defined
  Warning: [xen:xen_mmu_set_pgd] function sizeof not defined
  Warning: [xen:xen_mmu_ptep_modify_prot_start] function sizeof not defined
  Warning: [xen:xen_mmu_ptep_modify_prot_commit] function sizeof not defined
 Ok
[root@zoo ~]# 

i.e. making those warnings appear only under 'perf test -v'? Cool!

> perf test output.  Will send a fix soon.
> 
> Thanks,
> Namhyung
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Namhyung Kim Oct. 19, 2015, 3:21 p.m. UTC | #3
Hi Arnaldo,

On Mon, Oct 19, 2015 at 12:53:12PM -0200, Arnaldo Carvalho de Melo wrote:
> Em Mon, Oct 19, 2015 at 11:42:31PM +0900, Namhyung Kim escreveu:
> > Hi,
> > 
> > On Wed, Oct 14, 2015 at 12:41:32PM +0000, Wang Nan wrote:
> > > This patch enforces existing LLVM test, makes it compile more than one
> > > BPF source file. The compiled results are stored, can be used for other
> > > testcases. Except the first testcase (named LLVM_TESTCASE_BASE), failures
> > > of other test cases are not considered as failure of the whole test.
> > > 
> > > Adds a kbuild testcase to check whether kernel headers can be correctly
> > > found.
> > > 
> > > For example:
> > > 
> > >  # perf test LLVM
> > > 
> > >    38: Test LLVM searching and compiling                        : (llvm.kbuild-dir can be fixed) Ok
> > 
> > IMHO it'd be better to keep the test result simply as either "Ok" or
> > "FAILED" and provide details with -v option.
> 
> "Skipped" looks more natural here, with the reason for it skipping being shown
> only with -v.

Agreed.

> 
> Ingo made some comments about 'perf test' output recently, have you read that?

Nop, sorry.  I'll check it (and it'd be great it you could give me the
link :)


> 
> > Anyway I found the tracepoint error message is annoying in the current
> 
> You mean all these warnings:
> 
> [root@zoo ~]# perf test "parse event" 
>  5: parse events tests                                       :  Warning: [sunrpc:xprt_lookup_rqst] function __builtin_constant_p not defined
>   Warning: [sunrpc:xprt_transmit] function __builtin_constant_p not defined
>   Warning: [sunrpc:xprt_complete_rqst] function __builtin_constant_p not defined
> <SNIP>
>   Warning: [xen:xen_mmu_set_pud] function sizeof not defined
>   Warning: [xen:xen_mmu_set_pgd] function sizeof not defined
>   Warning: [xen:xen_mmu_ptep_modify_prot_start] function sizeof not defined
>   Warning: [xen:xen_mmu_ptep_modify_prot_commit] function sizeof not defined
>  Ok
> [root@zoo ~]# 
> 
> i.e. making those warnings appear only under 'perf test -v'? Cool!

Will send the fix soon!

Thanks,
Namhyung
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Wang Nan Oct. 20, 2015, 10:36 a.m. UTC | #4
On 2015/10/19 22:53, Arnaldo Carvalho de Melo wrote:
> Em Mon, Oct 19, 2015 at 11:42:31PM +0900, Namhyung Kim escreveu:
>> Hi,
>>
>> On Wed, Oct 14, 2015 at 12:41:32PM +0000, Wang Nan wrote:
>>> This patch enforces existing LLVM test, makes it compile more than one
>>> BPF source file. The compiled results are stored, can be used for other
>>> testcases. Except the first testcase (named LLVM_TESTCASE_BASE), failures
>>> of other test cases are not considered as failure of the whole test.
>>>
>>> Adds a kbuild testcase to check whether kernel headers can be correctly
>>> found.
>>>
>>> For example:
>>>
>>>   # perf test LLVM
>>>
>>>     38: Test LLVM searching and compiling                        : (llvm.kbuild-dir can be fixed) Ok
>> IMHO it'd be better to keep the test result simply as either "Ok" or
>> "FAILED" and provide details with -v option.

I have to say I'm not the first one to output things like this:

  #perf test dummy attr
  14: struct perf_event_attr setup                             : 
(omitted) Ok
  23: Test using a dummy software event to keep tracking       : (not 
supported) Ok

Do you think they also need to be fixed?

> "Skipped" looks more natural here, with the reason for it skipping being shown
> only with -v.

For this specific case, I will change the logic:

  1. When basic test failed (no clang, compiling error...), report failure;

  2. When basic test passed but kbuild test or later test cases failed, 
report
     Skip.

  3. Don't output any other information.

Thank you.

> Ingo made some comments about 'perf test' output recently, have you read that?
>
>> Anyway I found the tracepoint error message is annoying in the current
> You mean all these warnings:
>
> [root@zoo ~]# perf test "parse event"
>   5: parse events tests                                       :  Warning: [sunrpc:xprt_lookup_rqst] function __builtin_constant_p not defined
>    Warning: [sunrpc:xprt_transmit] function __builtin_constant_p not defined
>    Warning: [sunrpc:xprt_complete_rqst] function __builtin_constant_p not defined
> <SNIP>
>    Warning: [xen:xen_mmu_set_pud] function sizeof not defined
>    Warning: [xen:xen_mmu_set_pgd] function sizeof not defined
>    Warning: [xen:xen_mmu_ptep_modify_prot_start] function sizeof not defined
>    Warning: [xen:xen_mmu_ptep_modify_prot_commit] function sizeof not defined
>   Ok
> [root@zoo ~]#
>
> i.e. making those warnings appear only under 'perf test -v'? Cool!
>
>> perf test output.  Will send a fix soon.
>>
>> Thanks,
>> Namhyung


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Arnaldo Carvalho de Melo Oct. 20, 2015, 1:42 p.m. UTC | #5
Em Tue, Oct 20, 2015 at 06:36:33PM +0800, Wangnan (F) escreveu:
> On 2015/10/19 22:53, Arnaldo Carvalho de Melo wrote:
> >Em Mon, Oct 19, 2015 at 11:42:31PM +0900, Namhyung Kim escreveu:
> >>On Wed, Oct 14, 2015 at 12:41:32PM +0000, Wang Nan wrote:
> >>>This patch enforces existing LLVM test, makes it compile more than one
> >>>BPF source file. The compiled results are stored, can be used for other
> >>>testcases. Except the first testcase (named LLVM_TESTCASE_BASE), failures
> >>>of other test cases are not considered as failure of the whole test.

> >>>Adds a kbuild testcase to check whether kernel headers can be correctly
> >>>found.

> >>>For example:
> >>>  # perf test LLVM
> >>>    38: Test LLVM searching and compiling                        : (llvm.kbuild-dir can be fixed) Ok

> >>IMHO it'd be better to keep the test result simply as either "Ok" or
> >>"FAILED" and provide details with -v option.
> 
> I have to say I'm not the first one to output things like this:
> 
>  #perf test dummy attr
>  14: struct perf_event_attr setup                             :
> (omitted) Ok
>  23: Test using a dummy software event to keep tracking       : (not
> supported) Ok
> 
> Do you think they also need to be fixed?

yes
 
> >"Skipped" looks more natural here, with the reason for it skipping being shown
> >only with -v.
> 
> For this specific case, I will change the logic:
> 
>  1. When basic test failed (no clang, compiling error...), report failure;
> 
>  2. When basic test passed but kbuild test or later test cases
> failed, report
>     Skip.
> 
>  3. Don't output any other information.
> 
> Thank you.
> 
> >Ingo made some comments about 'perf test' output recently, have you read that?
> >
> >>Anyway I found the tracepoint error message is annoying in the current
> >You mean all these warnings:
> >
> >[root@zoo ~]# perf test "parse event"
> >  5: parse events tests                                       :  Warning: [sunrpc:xprt_lookup_rqst] function __builtin_constant_p not defined
> >   Warning: [sunrpc:xprt_transmit] function __builtin_constant_p not defined
> >   Warning: [sunrpc:xprt_complete_rqst] function __builtin_constant_p not defined
> ><SNIP>
> >   Warning: [xen:xen_mmu_set_pud] function sizeof not defined
> >   Warning: [xen:xen_mmu_set_pgd] function sizeof not defined
> >   Warning: [xen:xen_mmu_ptep_modify_prot_start] function sizeof not defined
> >   Warning: [xen:xen_mmu_ptep_modify_prot_commit] function sizeof not defined
> >  Ok
> >[root@zoo ~]#
> >
> >i.e. making those warnings appear only under 'perf test -v'? Cool!
> >
> >>perf test output.  Will send a fix soon.
> >>
> >>Thanks,
> >>Namhyung
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
diff mbox

Patch

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index d0278a9..23e2201 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -31,17 +31,24 @@  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 llvm-src.o
+perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o
 perf-y += bpf.o
 perf-y += topology.o
 
-$(OUTPUT)tests/llvm-src.c: tests/bpf-script-example.c
+$(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_prog[] =' >> $@
 	$(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
 	$(Q)echo ';' >> $@
 
+$(OUTPUT)tests/llvm-src-kbuild.c: tests/bpf-script-test-kbuild.c
+	$(call rule_mkdir)
+	$(Q)echo '#include <tests/llvm.h>' > $@
+	$(Q)echo 'const char test_llvm__bpf_test_kbuild_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/bpf-script-test-kbuild.c b/tools/perf/tests/bpf-script-test-kbuild.c
new file mode 100644
index 0000000..a11f589
--- /dev/null
+++ b/tools/perf/tests/bpf-script-test-kbuild.c
@@ -0,0 +1,21 @@ 
+/*
+ * bpf-script-test-kbuild.c
+ * Test include from kernel header
+ */
+#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'
+#endif
+#define SEC(NAME) __attribute__((section(NAME), used))
+
+#include <uapi/linux/fs.h>
+#include <uapi/asm/ptrace.h>
+
+SEC("func=vfs_llseek")
+int bpf_func__vfs_llseek(struct pt_regs *ctx)
+{
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index d7cdc84..4dd701b 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -140,7 +140,8 @@  int test__bpf(void)
 		return TEST_SKIP;
 	}
 
-	test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz);
+	test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz, LLVM_TESTCASE_BASE);
+
 	if (!obj_buf || !obj_buf_sz) {
 		if (verbose == 0)
 			fprintf(stderr, " (fix 'perf test LLVM' first)");
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index fd5fdb0..75cd99f 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -9,6 +9,22 @@ 
 #include "debug.h"
 #include "llvm.h"
 
+#define SHARED_BUF_INIT_SIZE	(1 << 20)
+struct llvm_testcase {
+	const char *source;
+	const char *errmsg;
+	struct test_llvm__bpf_result *result;
+	bool tried;
+} llvm_testcases[NR_LLVM_TESTCASES + 1] = {
+	[LLVM_TESTCASE_BASE]	= {.source = test_llvm__bpf_prog,
+				   .errmsg = "Basic LLVM compiling failed",
+				   .tried = false},
+	[LLVM_TESTCASE_KBUILD]	= {.source = test_llvm__bpf_test_kbuild_prog,
+				   .errmsg = "llvm.kbuild-dir can be fixed",
+				   .tried = false},
+	{.source = NULL}
+};
+
 static int perf_config_cb(const char *var, const char *val,
 			  void *arg __maybe_unused)
 {
@@ -36,7 +52,7 @@  static int test__bpf_parsing(void *obj_buf __maybe_unused,
 #endif
 
 static char *
-compose_source(void)
+compose_source(const char *raw_source)
 {
 	struct utsname utsname;
 	int version, patchlevel, sublevel, err;
@@ -56,25 +72,27 @@  compose_source(void)
 
 	version_code = (version << 16) + (patchlevel << 8) + sublevel;
 	err = asprintf(&code, "#define LINUX_VERSION_CODE 0x%08lx;\n%s",
-		       version_code, test_llvm__bpf_prog);
+		       version_code, raw_source);
 	if (err < 0)
 		return NULL;
 
 	return code;
 }
 
-#define SHARED_BUF_INIT_SIZE	(1 << 20)
-struct test_llvm__bpf_result *p_test_llvm__bpf_result;
 
-int test__llvm(void)
+static int __test__llvm(int i)
 {
-	char *tmpl_new, *clang_opt_new;
 	void *obj_buf;
 	size_t obj_buf_sz;
 	int err, old_verbose;
-	char *source;
+	const char *tmpl_old, *clang_opt_old;
+	char *tmpl_new, *clang_opt_new, *source;
+	const char *raw_source = llvm_testcases[i].source;
+	struct test_llvm__bpf_result *result = llvm_testcases[i].result;
 
 	perf_config(perf_config_cb, NULL);
+	clang_opt_old = llvm_param.clang_opt;
+	tmpl_old = llvm_param.clang_bpf_cmd_template;
 
 	/*
 	 * Skip this test if user's .perfconfig doesn't set [llvm] section
@@ -99,15 +117,17 @@  int test__llvm(void)
 	if (!llvm_param.clang_opt)
 		llvm_param.clang_opt = strdup("");
 
-	source = compose_source();
+	source = compose_source(raw_source);
 	if (!source) {
 		pr_err("Failed to compose source code\n");
 		return -1;
 	}
 
 	/* Quote __EOF__ so strings in source won't be expanded by shell */
-	err = asprintf(&tmpl_new, "cat << '__EOF__' | %s\n%s\n__EOF__\n",
-		       llvm_param.clang_bpf_cmd_template, source);
+	err = asprintf(&tmpl_new, "cat << '__EOF__' | %s %s \n%s\n__EOF__\n",
+		       llvm_param.clang_bpf_cmd_template,
+		       !old_verbose ? "2>/dev/null" : "",
+		       source);
 	free(source);
 	source = NULL;
 	if (err < 0) {
@@ -123,73 +143,123 @@  int test__llvm(void)
 	llvm_param.clang_opt = clang_opt_new;
 	err = llvm__compile_bpf("-", &obj_buf, &obj_buf_sz);
 
+	free((void *)llvm_param.clang_bpf_cmd_template);
+	free((void *)llvm_param.clang_opt);
+	llvm_param.clang_bpf_cmd_template = tmpl_old;
+	llvm_param.clang_opt = clang_opt_old;
+
 	verbose = old_verbose;
-	if (err) {
-		if (!verbose)
-			fprintf(stderr, " (use -v to see error message)");
+	if (err)
 		return -1;
-	}
 
 	err = test__bpf_parsing(obj_buf, obj_buf_sz);
-	if (!err && p_test_llvm__bpf_result) {
+	if (!err && result) {
 		if (obj_buf_sz > SHARED_BUF_INIT_SIZE) {
 			pr_err("Resulting object too large\n");
 		} else {
-			p_test_llvm__bpf_result->size = obj_buf_sz;
-			memcpy(p_test_llvm__bpf_result->object,
-			       obj_buf, obj_buf_sz);
+			result->size = obj_buf_sz;
+			memcpy(result->object, obj_buf, obj_buf_sz);
 		}
 	}
 	free(obj_buf);
 	return err;
 }
 
+int test__llvm(void)
+{
+	int i, ret;
+
+	for (i = 0; llvm_testcases[i].source; i++) {
+		ret = __test__llvm(i);
+		if (i == 0 && ret) {
+			/*
+			 * First testcase tests basic LLVM compiling. If it
+			 * fails, no need to check others.
+			 */
+			if (!verbose)
+				fprintf(stderr, " (use -v to see error message)");
+			return ret;
+		} else if (ret) {
+			if (!verbose && llvm_testcases[i].errmsg)
+				fprintf(stderr, " (%s)", llvm_testcases[i].errmsg);
+			return 0;
+		}
+	}
+	return 0;
+}
+
 void test__llvm_prepare(void)
 {
-	p_test_llvm__bpf_result = mmap(NULL, SHARED_BUF_INIT_SIZE,
-				       PROT_READ | PROT_WRITE,
-				       MAP_SHARED | MAP_ANONYMOUS, -1, 0);
-	if (!p_test_llvm__bpf_result)
-		return;
-	memset((void *)p_test_llvm__bpf_result, '\0', SHARED_BUF_INIT_SIZE);
+	int i;
+
+	for (i = 0; llvm_testcases[i].source; i++) {
+		struct test_llvm__bpf_result *result;
+
+		result = mmap(NULL, SHARED_BUF_INIT_SIZE,
+			      PROT_READ | PROT_WRITE,
+			      MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+		if (!result)
+			return;
+		memset((void *)result, '\0', SHARED_BUF_INIT_SIZE);
+
+		llvm_testcases[i].result = result;
+	}
 }
 
 void test__llvm_cleanup(void)
 {
-	unsigned long boundary, buf_end;
+	int i;
 
-	if (!p_test_llvm__bpf_result)
-		return;
-	if (p_test_llvm__bpf_result->size == 0) {
-		munmap((void *)p_test_llvm__bpf_result, SHARED_BUF_INIT_SIZE);
-		p_test_llvm__bpf_result = NULL;
-		return;
-	}
+	for (i = 0; llvm_testcases[i].source; i++) {
+		struct test_llvm__bpf_result *result;
+		unsigned long boundary, buf_end;
 
-	buf_end = (unsigned long)p_test_llvm__bpf_result + SHARED_BUF_INIT_SIZE;
+		result = llvm_testcases[i].result;
+		llvm_testcases[i].tried = true;
 
-	boundary = (unsigned long)(p_test_llvm__bpf_result);
-	boundary += p_test_llvm__bpf_result->size;
-	boundary = (boundary + (page_size - 1)) &
+		if (!result)
+			continue;
+
+		if (result->size == 0) {
+			munmap((void *)result, SHARED_BUF_INIT_SIZE);
+			result = NULL;
+			llvm_testcases[i].result = NULL;
+			continue;
+		}
+
+		buf_end = (unsigned long)result + SHARED_BUF_INIT_SIZE;
+
+		boundary = (unsigned long)(result);
+		boundary += result->size;
+		boundary = (boundary + (page_size - 1)) &
 			(~((unsigned long)page_size - 1));
-	munmap((void *)boundary, buf_end - boundary);
+		munmap((void *)boundary, buf_end - boundary);
+	}
 }
 
 void
-test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz)
+test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz, int index)
 {
+	struct test_llvm__bpf_result *result;
+
 	*p_obj_buf = NULL;
 	*p_obj_buf_sz = 0;
 
-	if (!p_test_llvm__bpf_result) {
+	if (index > NR_LLVM_TESTCASES)
+		return;
+
+	result = llvm_testcases[index].result;
+
+	if (!result && !llvm_testcases[index].tried) {
 		test__llvm_prepare();
 		test__llvm();
 		test__llvm_cleanup();
 	}
 
-	if (!p_test_llvm__bpf_result)
+	result = llvm_testcases[index].result;
+	if (!result)
 		return;
 
-	*p_obj_buf = p_test_llvm__bpf_result->object;
-	*p_obj_buf_sz = p_test_llvm__bpf_result->size;
+	*p_obj_buf = result->object;
+	*p_obj_buf_sz = result->size;
 }
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 2fd7ed6..78ec01d 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -8,8 +8,14 @@  struct test_llvm__bpf_result {
 	char object[];
 };
 
-extern struct test_llvm__bpf_result *p_test_llvm__bpf_result;
 extern const char test_llvm__bpf_prog[];
-void test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz);
+extern const char test_llvm__bpf_test_kbuild_prog[];
+
+enum test_llvm__testcase {
+	LLVM_TESTCASE_BASE,
+	LLVM_TESTCASE_KBUILD,
+	NR_LLVM_TESTCASES,
+};
+void test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz, int index);
 
 #endif