Skip to content

Commit

Permalink
selftests/bpf: __arch_* macro to limit test cases to specific archs
Browse files Browse the repository at this point in the history
Add annotations __arch_x86_64, __arch_arm64, __arch_riscv64
to specify on which architecture the test case should be tested.
Several __arch_* annotations could be specified at once.
When test case is not run on current arch it is marked as skipped.

For example, the following would be tested only on arm64 and riscv64:

  SEC("raw_tp")
  __arch_arm64
  __arch_riscv64
  __xlated("1: *(u64 *)(r10 - 16) = r1")
  __xlated("2: call")
  __xlated("3: r1 = *(u64 *)(r10 - 16);")
  __success
  __naked void canary_arm64_riscv64(void)
  {
  	asm volatile (
  	"r1 = 1;"
  	"*(u64 *)(r10 - 16) = r1;"
  	"call %[bpf_get_smp_processor_id];"
  	"r1 = *(u64 *)(r10 - 16);"
  	"exit;"
  	:
  	: __imm(bpf_get_smp_processor_id)
  	: __clobber_all);
  }

On x86 it would be skipped:

  torvalds#467/2   verifier_nocsr/canary_arm64_riscv64:SKIP

Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20240722233844.1406874-10-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
  • Loading branch information
eddyz87 authored and Alexei Starovoitov committed Jul 24, 2024
1 parent 69c9922 commit c64d2f7
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
8 changes: 8 additions & 0 deletions tools/testing/selftests/bpf/progs/bpf_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
* __auxiliary Annotated program is not a separate test, but used as auxiliary
* for some other test cases and should always be loaded.
* __auxiliary_unpriv Same, but load program in unprivileged mode.
*
* __arch_* Specify on which architecture the test case should be tested.
* Several __arch_* annotations could be specified at once.
* When test case is not run on current arch it is marked as skipped.
*/
#define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" msg)))
#define __regex(regex) __attribute__((btf_decl_tag("comment:test_expect_regex=" regex)))
Expand All @@ -82,6 +86,10 @@
#define __auxiliary __attribute__((btf_decl_tag("comment:test_auxiliary")))
#define __auxiliary_unpriv __attribute__((btf_decl_tag("comment:test_auxiliary_unpriv")))
#define __btf_path(path) __attribute__((btf_decl_tag("comment:test_btf_path=" path)))
#define __arch(arch) __attribute__((btf_decl_tag("comment:test_arch=" arch)))
#define __arch_x86_64 __arch("X86_64")
#define __arch_arm64 __arch("ARM64")
#define __arch_riscv64 __arch("RISCV64")

/* Convenience macro for use with 'asm volatile' blocks */
#define __naked __attribute__((naked))
Expand Down
43 changes: 43 additions & 0 deletions tools/testing/selftests/bpf/test_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define TEST_TAG_AUXILIARY "comment:test_auxiliary"
#define TEST_TAG_AUXILIARY_UNPRIV "comment:test_auxiliary_unpriv"
#define TEST_BTF_PATH "comment:test_btf_path="
#define TEST_TAG_ARCH "comment:test_arch="

/* Warning: duplicated in bpf_misc.h */
#define POINTER_VALUE 0xcafe4all
Expand Down Expand Up @@ -80,6 +81,7 @@ struct test_spec {
int log_level;
int prog_flags;
int mode_mask;
int arch_mask;
bool auxiliary;
bool valid;
};
Expand Down Expand Up @@ -213,6 +215,12 @@ static void update_flags(int *flags, int flag, bool clear)
*flags |= flag;
}

enum arch {
ARCH_X86_64 = 0x1,
ARCH_ARM64 = 0x2,
ARCH_RISCV64 = 0x4,
};

/* Uses btf_decl_tag attributes to describe the expected test
* behavior, see bpf_misc.h for detailed description of each attribute
* and attribute combinations.
Expand All @@ -226,6 +234,7 @@ static int parse_test_spec(struct test_loader *tester,
bool has_unpriv_result = false;
bool has_unpriv_retval = false;
int func_id, i, err = 0;
u32 arch_mask = 0;
struct btf *btf;

memset(spec, 0, sizeof(*spec));
Expand Down Expand Up @@ -364,11 +373,26 @@ static int parse_test_spec(struct test_loader *tester,
goto cleanup;
update_flags(&spec->prog_flags, flags, clear);
}
} else if (str_has_pfx(s, TEST_TAG_ARCH)) {
val = s + sizeof(TEST_TAG_ARCH) - 1;
if (strcmp(val, "X86_64") == 0) {
arch_mask |= ARCH_X86_64;
} else if (strcmp(val, "ARM64") == 0) {
arch_mask |= ARCH_ARM64;
} else if (strcmp(val, "RISCV64") == 0) {
arch_mask |= ARCH_RISCV64;
} else {
PRINT_FAIL("bad arch spec: '%s'", val);
err = -EINVAL;
goto cleanup;
}
} else if (str_has_pfx(s, TEST_BTF_PATH)) {
spec->btf_custom_path = s + sizeof(TEST_BTF_PATH) - 1;
}
}

spec->arch_mask = arch_mask;

if (spec->mode_mask == 0)
spec->mode_mask = PRIV;

Expand Down Expand Up @@ -677,6 +701,20 @@ static int get_xlated_program_text(int prog_fd, char *text, size_t text_sz)
return err;
}

static bool run_on_current_arch(int arch_mask)
{
if (arch_mask == 0)
return true;
#if defined(__x86_64__)
return arch_mask & ARCH_X86_64;
#elif defined(__aarch64__)
return arch_mask & ARCH_ARM64;
#elif defined(__riscv) && __riscv_xlen == 64
return arch_mask & ARCH_RISCV64;
#endif
return false;
}

/* this function is forced noinline and has short generic name to look better
* in test_progs output (in case of a failure)
*/
Expand All @@ -701,6 +739,11 @@ void run_subtest(struct test_loader *tester,
if (!test__start_subtest(subspec->name))
return;

if (!run_on_current_arch(spec->arch_mask)) {
test__skip();
return;
}

if (unpriv) {
if (!can_execute_unpriv(tester, spec)) {
test__skip();
Expand Down

0 comments on commit c64d2f7

Please sign in to comment.