From: Leon Hwang <leon.hwang@linux.dev>
To: bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Martin KaFai Lau <martin.lau@linux.dev>,
Eduard Zingerman <eddyz87@gmail.com>, Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
John Fastabend <john.fastabend@gmail.com>,
KP Singh <kpsingh@kernel.org>,
Stanislav Fomichev <sdf@fomichev.me>, Hao Luo <haoluo@google.com>,
Jiri Olsa <jolsa@kernel.org>,
Puranjay Mohan <puranjay@kernel.org>,
Xu Kuohai <xukuohai@huaweicloud.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>, Thomas Gleixner <tglx@kernel.org>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H . Peter Anvin" <hpa@zytor.com>,
Shuah Khan <shuah@kernel.org>, Leon Hwang <leon.hwang@linux.dev>,
Peilin Ye <yepeilin@google.com>,
Luis Gerhorst <luis.gerhorst@fau.de>,
Viktor Malik <vmalik@redhat.com>,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com
Subject: [PATCH bpf-next v2 5/6] selftests/bpf: Add __cpu_feature annotation for CPU-feature-gated tests
Date: Thu, 19 Feb 2026 22:29:27 +0800 [thread overview]
Message-ID: <20260219142933.13904-6-leon.hwang@linux.dev> (raw)
In-Reply-To: <20260219142933.13904-1-leon.hwang@linux.dev>
Add a new __cpu_feature("...") test annotation and parse it in
selftests/bpf test_loader.
Behavior:
- Annotation value is matched against CPU feature tokens from
/proc/cpuinfo (case-insensitive).
- Multiple __cpu_feature annotations can be specified for one test; all
required features must be present.
- If any required feature is missing, the test is skipped.
Limitation:
- __cpu_feature is evaluated per test function and is not scoped per
__arch_* block. A single test that combines multiple architectures
cannot express different per-arch feature requirements.
This lets JIT/disassembly-sensitive tests declare explicit CPU feature
requirements and avoid false failures on unsupported systems.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
tools/testing/selftests/bpf/progs/bpf_misc.h | 7 +
tools/testing/selftests/bpf/test_loader.c | 150 +++++++++++++++++++
2 files changed, 157 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index c9bfbe1bafc1..75e66373a64d 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -126,6 +126,12 @@
* Several __arch_* annotations could be specified at once.
* When test case is not run on current arch it is marked as skipped.
* __caps_unpriv Specify the capabilities that should be set when running the test.
+ * __cpu_feature Specify required CPU feature for test execution.
+ * Multiple __cpu_feature annotations could be specified.
+ * Value must match a CPU feature token exposed by
+ * /proc/cpuinfo (case-insensitive).
+ * Can't be used together with multiple __arch_* tags.
+ * If any required feature is not present, test case is skipped.
*
* __linear_size Specify the size of the linear area of non-linear skbs, or
* 0 for linear skbs.
@@ -156,6 +162,7 @@
#define __arch_riscv64 __arch("RISCV64")
#define __arch_s390x __arch("s390x")
#define __caps_unpriv(caps) __attribute__((btf_decl_tag("comment:test_caps_unpriv=" EXPAND_QUOTE(caps))))
+#define __cpu_feature(feat) __attribute__((btf_decl_tag("comment:test_cpu_feature=" feat)))
#define __load_if_JITed() __attribute__((btf_decl_tag("comment:load_mode=jited")))
#define __load_if_no_JITed() __attribute__((btf_decl_tag("comment:load_mode=no_jited")))
#define __stderr(msg) __attribute__((btf_decl_tag("comment:test_expect_stderr=" XSTR(__COUNTER__) "=" msg)))
diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c
index 338c035c3688..3729d1572589 100644
--- a/tools/testing/selftests/bpf/test_loader.c
+++ b/tools/testing/selftests/bpf/test_loader.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <test_progs.h>
#include <bpf/btf.h>
+#include <ctype.h>
#include "autoconf_helper.h"
#include "disasm_helpers.h"
@@ -44,6 +45,7 @@
#define TEST_TAG_EXPECT_STDOUT_PFX "comment:test_expect_stdout="
#define TEST_TAG_EXPECT_STDOUT_PFX_UNPRIV "comment:test_expect_stdout_unpriv="
#define TEST_TAG_LINEAR_SIZE "comment:test_linear_size="
+#define TEST_TAG_CPU_FEATURE_PFX "comment:test_cpu_feature="
/* Warning: duplicated in bpf_misc.h */
#define POINTER_VALUE 0xbadcafe
@@ -67,6 +69,11 @@ enum load_mode {
NO_JITED = 1 << 1,
};
+struct cpu_feature_set {
+ char **names;
+ size_t cnt;
+};
+
struct test_subspec {
char *name;
bool expect_failure;
@@ -93,6 +100,7 @@ struct test_spec {
int linear_sz;
bool auxiliary;
bool valid;
+ struct cpu_feature_set cpu_features;
};
static int tester_init(struct test_loader *tester)
@@ -145,6 +153,16 @@ static void free_test_spec(struct test_spec *spec)
free(spec->unpriv.name);
spec->priv.name = NULL;
spec->unpriv.name = NULL;
+
+ if (spec->cpu_features.names) {
+ size_t i;
+
+ for (i = 0; i < spec->cpu_features.cnt; i++)
+ free(spec->cpu_features.names[i]);
+ free(spec->cpu_features.names);
+ spec->cpu_features.names = NULL;
+ spec->cpu_features.cnt = 0;
+ }
}
/* Compiles regular expression matching pattern.
@@ -394,6 +412,122 @@ static int get_current_arch(void)
return ARCH_UNKNOWN;
}
+static int cpu_feature_set_add(struct cpu_feature_set *set, const char *name)
+{
+ char **tmp, *norm;
+ size_t i, len;
+
+ if (!name || !name[0]) {
+ PRINT_FAIL("bad cpu feature spec: empty string");
+ return -EINVAL;
+ }
+
+ len = strlen(name);
+ norm = malloc(len + 1);
+ if (!norm)
+ return -ENOMEM;
+
+ for (i = 0; i < len; i++) {
+ if (isspace(name[i])) {
+ free(norm);
+ PRINT_FAIL("bad cpu feature spec: whitespace is not allowed in '%s'", name);
+ return -EINVAL;
+ }
+ norm[i] = tolower((unsigned char)name[i]);
+ }
+ norm[len] = '\0';
+
+ for (i = 0; i < set->cnt; i++) {
+ if (strcmp(set->names[i], norm) == 0) {
+ free(norm);
+ return 0;
+ }
+ }
+
+ tmp = realloc(set->names, (set->cnt + 1) * sizeof(*set->names));
+ if (!tmp) {
+ free(norm);
+ return -ENOMEM;
+ }
+ set->names = tmp;
+ set->names[set->cnt++] = norm;
+ return 0;
+}
+
+static bool cpu_feature_set_has(const struct cpu_feature_set *set, const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < set->cnt; i++) {
+ if (strcmp(set->names[i], name) == 0)
+ return true;
+ }
+ return false;
+}
+
+static bool cpu_feature_set_includes(const struct cpu_feature_set *have,
+ const struct cpu_feature_set *need)
+{
+ size_t i;
+
+ for (i = 0; i < need->cnt; i++) {
+ if (!cpu_feature_set_has(have, need->names[i]))
+ return false;
+ }
+ return true;
+}
+
+static const struct cpu_feature_set *get_current_cpu_features(void)
+{
+ static struct cpu_feature_set set;
+ static bool initialized;
+ char *line = NULL;
+ size_t len = 0;
+ FILE *fp;
+ int err;
+
+ if (initialized)
+ return &set;
+
+ initialized = true;
+ fp = fopen("/proc/cpuinfo", "r");
+ if (!fp)
+ return &set;
+
+ while (getline(&line, &len, fp) != -1) {
+ char *p = line, *colon, *tok;
+
+ while (*p && isspace(*p))
+ p++;
+ if (!str_has_pfx(p, "flags") &&
+ !str_has_pfx(p, "Features") &&
+ !str_has_pfx(p, "features"))
+ continue;
+
+ colon = strchr(p, ':');
+ if (!colon)
+ continue;
+
+ for (tok = strtok(colon + 1, " \t\n"); tok; tok = strtok(NULL, " \t\n")) {
+ err = cpu_feature_set_add(&set, tok);
+ if (err) {
+ PRINT_FAIL("failed to parse cpu feature from '/proc/cpuinfo': '%s'",
+ tok);
+ break;
+ }
+ }
+ }
+
+ free(line);
+ fclose(fp);
+ return &set;
+}
+
+static int parse_cpu_feature(const char *name, struct cpu_feature_set *set)
+{
+ return cpu_feature_set_add(set, name);
+}
+
/* Uses btf_decl_tag attributes to describe the expected test
* behavior, see bpf_misc.h for detailed description of each attribute
* and attribute combinations.
@@ -650,9 +784,20 @@ static int parse_test_spec(struct test_loader *tester,
err = -EINVAL;
goto cleanup;
}
+ } else if (str_has_pfx(s, TEST_TAG_CPU_FEATURE_PFX)) {
+ val = s + sizeof(TEST_TAG_CPU_FEATURE_PFX) - 1;
+ err = parse_cpu_feature(val, &spec->cpu_features);
+ if (err)
+ goto cleanup;
}
}
+ if (spec->cpu_features.cnt && __builtin_popcount(arch_mask) != 1) {
+ PRINT_FAIL("__cpu_feature requires exactly one __arch_* tag");
+ err = -EINVAL;
+ goto cleanup;
+ }
+
spec->arch_mask = arch_mask ?: -1;
spec->load_mask = load_mask ?: (JITED | NO_JITED);
@@ -1161,6 +1306,11 @@ void run_subtest(struct test_loader *tester,
return;
}
+ if (!cpu_feature_set_includes(get_current_cpu_features(), &spec->cpu_features)) {
+ test__skip();
+ return;
+ }
+
if (unpriv) {
if (!can_execute_unpriv(tester, spec)) {
test__skip();
--
2.52.0
next prev parent reply other threads:[~2026-02-19 14:31 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-19 14:29 [PATCH bpf-next v2 0/6] bpf: Introduce 64-bit bitops kfuncs Leon Hwang
2026-02-19 14:29 ` [PATCH bpf-next v2 1/6] " Leon Hwang
2026-02-19 17:50 ` Alexei Starovoitov
2026-02-20 15:34 ` Leon Hwang
2026-02-19 14:29 ` [PATCH bpf-next v2 2/6] bpf, x86: Add 64-bit bitops kfuncs support for x86_64 Leon Hwang
2026-02-19 17:47 ` Alexei Starovoitov
2026-02-20 15:54 ` Leon Hwang
2026-02-20 17:50 ` Alexei Starovoitov
2026-02-21 12:45 ` Leon Hwang
2026-02-21 16:51 ` Alexei Starovoitov
2026-02-23 16:35 ` Leon Hwang
2026-02-19 14:29 ` [PATCH bpf-next v2 3/6] bpf, arm64: Add 64-bit bitops kfuncs support Leon Hwang
2026-02-19 15:10 ` Puranjay Mohan
2026-02-19 15:20 ` Puranjay Mohan
2026-02-19 15:25 ` Puranjay Mohan
2026-02-19 15:36 ` Leon Hwang
2026-02-19 14:29 ` [PATCH bpf-next v2 4/6] selftests/bpf: Add tests for 64-bit bitops kfuncs Leon Hwang
2026-02-19 14:29 ` Leon Hwang [this message]
2026-02-19 14:29 ` [PATCH bpf-next v2 6/6] selftests/bpf: Add JIT disassembly " Leon Hwang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260219142933.13904-6-leon.hwang@linux.dev \
--to=leon.hwang@linux.dev \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bp@alien8.de \
--cc=bpf@vger.kernel.org \
--cc=catalin.marinas@arm.com \
--cc=daniel@iogearbox.net \
--cc=dave.hansen@linux.intel.com \
--cc=eddyz87@gmail.com \
--cc=haoluo@google.com \
--cc=hpa@zytor.com \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kernel-patches-bot@fb.com \
--cc=kpsingh@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=luis.gerhorst@fau.de \
--cc=martin.lau@linux.dev \
--cc=mingo@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=puranjay@kernel.org \
--cc=sdf@fomichev.me \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=tglx@kernel.org \
--cc=vmalik@redhat.com \
--cc=will@kernel.org \
--cc=x86@kernel.org \
--cc=xukuohai@huaweicloud.com \
--cc=yepeilin@google.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox