]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/bpf: __arch_* macro to limit test cases to specific archs
authorEduard Zingerman <eddyz87@gmail.com>
Mon, 22 Jul 2024 23:38:43 +0000 (16:38 -0700)
committerAndrii Nakryiko <andrii@kernel.org>
Mon, 29 Jul 2024 22:05:06 +0000 (15:05 -0700)
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:

  #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>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
tools/testing/selftests/bpf/progs/bpf_misc.h
tools/testing/selftests/bpf/test_loader.c

index a70939c7bc26ba5fc50c4d1ec494d3c7223b577d..a225cd87897c417ad9838fd82e28617f827e918c 100644 (file)
  * __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)))
 #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))
index b44b6a2fc82ce9252a47a7420b4d67d38b88eb30..12b0c41e8d64c304cbd6c0d33c78b9436a3c2dd7 100644 (file)
@@ -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
@@ -80,6 +81,7 @@ struct test_spec {
        int log_level;
        int prog_flags;
        int mode_mask;
+       int arch_mask;
        bool auxiliary;
        bool valid;
 };
@@ -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.
@@ -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));
@@ -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;
 
@@ -677,6 +701,20 @@ out:
        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)
  */
@@ -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();