cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

llvm.c (5649B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <stdio.h>
      3#include <stdlib.h>
      4#include <string.h>
      5#include "tests.h"
      6#include "debug.h"
      7
      8#ifdef HAVE_LIBBPF_SUPPORT
      9#include <bpf/libbpf.h>
     10#include <util/llvm-utils.h>
     11#include "llvm.h"
     12static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
     13{
     14	struct bpf_object *obj;
     15
     16	obj = bpf_object__open_mem(obj_buf, obj_buf_sz, NULL);
     17	if (libbpf_get_error(obj))
     18		return TEST_FAIL;
     19	bpf_object__close(obj);
     20	return TEST_OK;
     21}
     22
     23static struct {
     24	const char *source;
     25	const char *desc;
     26	bool should_load_fail;
     27} bpf_source_table[__LLVM_TESTCASE_MAX] = {
     28	[LLVM_TESTCASE_BASE] = {
     29		.source = test_llvm__bpf_base_prog,
     30		.desc = "Basic BPF llvm compile",
     31	},
     32	[LLVM_TESTCASE_KBUILD] = {
     33		.source = test_llvm__bpf_test_kbuild_prog,
     34		.desc = "kbuild searching",
     35	},
     36	[LLVM_TESTCASE_BPF_PROLOGUE] = {
     37		.source = test_llvm__bpf_test_prologue_prog,
     38		.desc = "Compile source for BPF prologue generation",
     39	},
     40	[LLVM_TESTCASE_BPF_RELOCATION] = {
     41		.source = test_llvm__bpf_test_relocation,
     42		.desc = "Compile source for BPF relocation",
     43		.should_load_fail = true,
     44	},
     45};
     46
     47int
     48test_llvm__fetch_bpf_obj(void **p_obj_buf,
     49			 size_t *p_obj_buf_sz,
     50			 enum test_llvm__testcase idx,
     51			 bool force,
     52			 bool *should_load_fail)
     53{
     54	const char *source;
     55	const char *desc;
     56	const char *tmpl_old, *clang_opt_old;
     57	char *tmpl_new = NULL, *clang_opt_new = NULL;
     58	int err, old_verbose, ret = TEST_FAIL;
     59
     60	if (idx >= __LLVM_TESTCASE_MAX)
     61		return TEST_FAIL;
     62
     63	source = bpf_source_table[idx].source;
     64	desc = bpf_source_table[idx].desc;
     65	if (should_load_fail)
     66		*should_load_fail = bpf_source_table[idx].should_load_fail;
     67
     68	/*
     69	 * Skip this test if user's .perfconfig doesn't set [llvm] section
     70	 * and clang is not found in $PATH
     71	 */
     72	if (!force && (!llvm_param.user_set_param &&
     73		       llvm__search_clang())) {
     74		pr_debug("No clang, skip this test\n");
     75		return TEST_SKIP;
     76	}
     77
     78	/*
     79	 * llvm is verbosity when error. Suppress all error output if
     80	 * not 'perf test -v'.
     81	 */
     82	old_verbose = verbose;
     83	if (verbose == 0)
     84		verbose = -1;
     85
     86	*p_obj_buf = NULL;
     87	*p_obj_buf_sz = 0;
     88
     89	if (!llvm_param.clang_bpf_cmd_template)
     90		goto out;
     91
     92	if (!llvm_param.clang_opt)
     93		llvm_param.clang_opt = strdup("");
     94
     95	err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
     96		       llvm_param.clang_bpf_cmd_template,
     97		       old_verbose ? "" : " 2>/dev/null");
     98	if (err < 0)
     99		goto out;
    100	err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
    101	if (err < 0)
    102		goto out;
    103
    104	tmpl_old = llvm_param.clang_bpf_cmd_template;
    105	llvm_param.clang_bpf_cmd_template = tmpl_new;
    106	clang_opt_old = llvm_param.clang_opt;
    107	llvm_param.clang_opt = clang_opt_new;
    108
    109	err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
    110
    111	llvm_param.clang_bpf_cmd_template = tmpl_old;
    112	llvm_param.clang_opt = clang_opt_old;
    113
    114	verbose = old_verbose;
    115	if (err)
    116		goto out;
    117
    118	ret = TEST_OK;
    119out:
    120	free(tmpl_new);
    121	free(clang_opt_new);
    122	if (ret != TEST_OK)
    123		pr_debug("Failed to compile test case: '%s'\n", desc);
    124	return ret;
    125}
    126
    127static int test__llvm(int subtest)
    128{
    129	int ret;
    130	void *obj_buf = NULL;
    131	size_t obj_buf_sz = 0;
    132	bool should_load_fail = false;
    133
    134	if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
    135		return TEST_FAIL;
    136
    137	ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
    138				       subtest, false, &should_load_fail);
    139
    140	if (ret == TEST_OK && !should_load_fail) {
    141		ret = test__bpf_parsing(obj_buf, obj_buf_sz);
    142		if (ret != TEST_OK) {
    143			pr_debug("Failed to parse test case '%s'\n",
    144				 bpf_source_table[subtest].desc);
    145		}
    146	}
    147	free(obj_buf);
    148
    149	return ret;
    150}
    151#endif //HAVE_LIBBPF_SUPPORT
    152
    153static int test__llvm__bpf_base_prog(struct test_suite *test __maybe_unused,
    154				     int subtest __maybe_unused)
    155{
    156#ifdef HAVE_LIBBPF_SUPPORT
    157	return test__llvm(LLVM_TESTCASE_BASE);
    158#else
    159	pr_debug("Skip LLVM test because BPF support is not compiled\n");
    160	return TEST_SKIP;
    161#endif
    162}
    163
    164static int test__llvm__bpf_test_kbuild_prog(struct test_suite *test __maybe_unused,
    165					    int subtest __maybe_unused)
    166{
    167#ifdef HAVE_LIBBPF_SUPPORT
    168	return test__llvm(LLVM_TESTCASE_KBUILD);
    169#else
    170	pr_debug("Skip LLVM test because BPF support is not compiled\n");
    171	return TEST_SKIP;
    172#endif
    173}
    174
    175static int test__llvm__bpf_test_prologue_prog(struct test_suite *test __maybe_unused,
    176					      int subtest __maybe_unused)
    177{
    178#ifdef HAVE_LIBBPF_SUPPORT
    179	return test__llvm(LLVM_TESTCASE_BPF_PROLOGUE);
    180#else
    181	pr_debug("Skip LLVM test because BPF support is not compiled\n");
    182	return TEST_SKIP;
    183#endif
    184}
    185
    186static int test__llvm__bpf_test_relocation(struct test_suite *test __maybe_unused,
    187					   int subtest __maybe_unused)
    188{
    189#ifdef HAVE_LIBBPF_SUPPORT
    190	return test__llvm(LLVM_TESTCASE_BPF_RELOCATION);
    191#else
    192	pr_debug("Skip LLVM test because BPF support is not compiled\n");
    193	return TEST_SKIP;
    194#endif
    195}
    196
    197
    198static struct test_case llvm_tests[] = {
    199#ifdef HAVE_LIBBPF_SUPPORT
    200	TEST_CASE("Basic BPF llvm compile", llvm__bpf_base_prog),
    201	TEST_CASE("kbuild searching", llvm__bpf_test_kbuild_prog),
    202	TEST_CASE("Compile source for BPF prologue generation",
    203		  llvm__bpf_test_prologue_prog),
    204	TEST_CASE("Compile source for BPF relocation", llvm__bpf_test_relocation),
    205#else
    206	TEST_CASE_REASON("Basic BPF llvm compile", llvm__bpf_base_prog, "not compiled in"),
    207	TEST_CASE_REASON("kbuild searching", llvm__bpf_test_kbuild_prog, "not compiled in"),
    208	TEST_CASE_REASON("Compile source for BPF prologue generation",
    209			llvm__bpf_test_prologue_prog, "not compiled in"),
    210	TEST_CASE_REASON("Compile source for BPF relocation",
    211			llvm__bpf_test_relocation, "not compiled in"),
    212#endif
    213	{ .name = NULL, }
    214};
    215
    216struct test_suite suite__llvm = {
    217	.desc = "LLVM search and compile",
    218	.test_cases = llvm_tests,
    219};