From: Dave Marchevsky <davemarchevsky@fb.com>
To: <bpf@vger.kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Rik van Riel <riel@surriel.com>,
Ilya Leoshkevich <iii@linux.ibm.com>, Yonghong Song <yhs@fb.com>,
<kernel-team@fb.com>, Dave Marchevsky <davemarchevsky@fb.com>
Subject: [RFC PATCH bpf-next 5/5] selftests/bpf: get_reg_val test exercising fxsave fetch
Date: Thu, 12 May 2022 00:43:21 -0700 [thread overview]
Message-ID: <20220512074321.2090073-6-davemarchevsky@fb.com> (raw)
In-Reply-To: <20220512074321.2090073-1-davemarchevsky@fb.com>
Add a test which calls bpf_get_reg_val with an xmm reg after forcing fpu
state save. The test program writes to %xmm10, then calls a BPF program
which forces fpu save and calls bpf_get_reg_val. This guarantees that
!fpregs_state_valid check will succeed, forcing bpf_get_reg_val to fetch
%xmm10's value from task's fpu state.
A bpf_testmod_save_fpregs kfunc helper is added to bpf_testmod to enable
'force fpu save'. Existing bpf_dummy_ops test infra is extended to
support calling the kfunc.
unload_bpf_testmod would often fail with -EAGAIN when running the test
added in this patch, so a single retry w/ 20ms sleep is added.
Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
---
include/linux/bpf.h | 1 +
kernel/trace/bpf_trace.c | 2 +-
net/bpf/bpf_dummy_struct_ops.c | 13 ++++++
.../selftests/bpf/bpf_testmod/bpf_testmod.c | 13 ++++++
tools/testing/selftests/bpf/prog_tests/usdt.c | 42 +++++++++++++++++++
.../selftests/bpf/progs/test_urandom_usdt.c | 24 +++++++++++
tools/testing/selftests/bpf/test_progs.c | 7 ++++
7 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index be94833d390a..e642e4b8a726 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2223,6 +2223,7 @@ extern const struct bpf_func_proto bpf_find_vma_proto;
extern const struct bpf_func_proto bpf_loop_proto;
extern const struct bpf_func_proto bpf_strncmp_proto;
extern const struct bpf_func_proto bpf_copy_from_user_task_proto;
+extern const struct bpf_func_proto bpf_get_reg_val_proto;
const struct bpf_func_proto *tracing_prog_func_proto(
enum bpf_func_id func_id, const struct bpf_prog *prog);
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 0de7d6b3af5b..cb81142a751a 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1300,7 +1300,7 @@ BPF_CALL_5(get_reg_val, void *, dst, u32, size,
BTF_ID_LIST(bpf_get_reg_val_ids)
BTF_ID(struct, pt_regs)
-static const struct bpf_func_proto bpf_get_reg_val_proto = {
+const struct bpf_func_proto bpf_get_reg_val_proto = {
.func = get_reg_val,
.ret_type = RET_INTEGER,
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
diff --git a/net/bpf/bpf_dummy_struct_ops.c b/net/bpf/bpf_dummy_struct_ops.c
index d0e54e30658a..1f3933cd8aa6 100644
--- a/net/bpf/bpf_dummy_struct_ops.c
+++ b/net/bpf/bpf_dummy_struct_ops.c
@@ -171,7 +171,20 @@ static int bpf_dummy_ops_btf_struct_access(struct bpf_verifier_log *log,
return atype == BPF_READ ? err : NOT_INIT;
}
+static const struct bpf_func_proto *
+bpf_dummy_ops_get_func_proto(enum bpf_func_id func_id,
+ const struct bpf_prog *prog)
+{
+ switch (func_id) {
+ case BPF_FUNC_get_reg_val:
+ return &bpf_get_reg_val_proto;
+ default:
+ return bpf_base_func_proto(func_id);
+ }
+}
+
static const struct bpf_verifier_ops bpf_dummy_verifier_ops = {
+ .get_func_proto = bpf_dummy_ops_get_func_proto,
.is_valid_access = bpf_dummy_ops_is_valid_access,
.btf_struct_access = bpf_dummy_ops_btf_struct_access,
};
diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
index e585e1cefc77..b2b35138b097 100644
--- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
+++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020 Facebook */
+#include <asm/fpu/api.h>
#include <linux/btf.h>
#include <linux/btf_ids.h>
#include <linux/error-injection.h>
@@ -25,6 +26,13 @@ bpf_testmod_test_mod_kfunc(int i)
*(int *)this_cpu_ptr(&bpf_testmod_ksym_percpu) = i;
}
+noinline void
+bpf_testmod_save_fpregs(void)
+{
+ kernel_fpu_begin();
+ kernel_fpu_end();
+}
+
struct bpf_testmod_btf_type_tag_1 {
int a;
};
@@ -150,6 +158,7 @@ static struct bin_attribute bin_attr_bpf_testmod_file __ro_after_init = {
BTF_SET_START(bpf_testmod_check_kfunc_ids)
BTF_ID(func, bpf_testmod_test_mod_kfunc)
+BTF_ID(func, bpf_testmod_save_fpregs)
BTF_SET_END(bpf_testmod_check_kfunc_ids)
static const struct btf_kfunc_id_set bpf_testmod_kfunc_set = {
@@ -166,6 +175,10 @@ static int bpf_testmod_init(void)
ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, &bpf_testmod_kfunc_set);
if (ret < 0)
return ret;
+ ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &bpf_testmod_kfunc_set);
+ if (ret < 0)
+ return ret;
+
if (bpf_fentry_test1(0) < 0)
return -EINVAL;
return sysfs_create_bin_file(kernel_kobj, &bin_attr_bpf_testmod_file);
diff --git a/tools/testing/selftests/bpf/prog_tests/usdt.c b/tools/testing/selftests/bpf/prog_tests/usdt.c
index f98749ac74a7..3866cb004b22 100644
--- a/tools/testing/selftests/bpf/prog_tests/usdt.c
+++ b/tools/testing/selftests/bpf/prog_tests/usdt.c
@@ -8,6 +8,11 @@
#include "test_usdt.skel.h"
#include "test_urandom_usdt.skel.h"
+/* Need to keep consistent with definition in include/linux/bpf.h */
+struct bpf_dummy_ops_state {
+ int val;
+};
+
int lets_test_this(int);
static volatile int idx = 2;
@@ -415,6 +420,41 @@ static void subtest_urandom_usdt(bool auto_attach)
test_urandom_usdt__destroy(skel);
}
+static void subtest_reg_val_fpustate(void)
+{
+ struct bpf_dummy_ops_state in_state;
+ struct test_urandom_usdt__bss *bss;
+ struct test_urandom_usdt *skel;
+ u64 in_args[1];
+ u64 regval[2];
+ int err, fd;
+
+ in_state.val = 0; /* unused */
+ in_args[0] = (unsigned long)&in_state;
+
+ LIBBPF_OPTS(bpf_test_run_opts, attr,
+ .ctx_in = in_args,
+ .ctx_size_in = sizeof(in_args),
+ );
+
+ skel = test_urandom_usdt__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "skel_open"))
+ return;
+ bss = skel->bss;
+
+ fd = bpf_program__fd(skel->progs.save_fpregs_and_read);
+ regval[0] = 42;
+ regval[1] = 0;
+ asm("movdqa %0, %%xmm10" : "=m"(*(char *)regval));
+
+ err = bpf_prog_test_run_opts(fd, &attr);
+ ASSERT_OK(err, "save_fpregs_and_read");
+ ASSERT_EQ(bss->fpregs_dummy_opts_xmm_val, 42, "fpregs_dummy_opts_xmm_val");
+
+ close(fd);
+ test_urandom_usdt__destroy(skel);
+}
+
void test_usdt(void)
{
if (test__start_subtest("basic"))
@@ -425,4 +465,6 @@ void test_usdt(void)
subtest_urandom_usdt(true /* auto_attach */);
if (test__start_subtest("urand_pid_attach"))
subtest_urandom_usdt(false /* auto_attach */);
+ if (test__start_subtest("bpf_get_reg_val_fpustate"))
+ subtest_reg_val_fpustate();
}
diff --git a/tools/testing/selftests/bpf/progs/test_urandom_usdt.c b/tools/testing/selftests/bpf/progs/test_urandom_usdt.c
index 575761863eb6..2c8b6709606a 100644
--- a/tools/testing/selftests/bpf/progs/test_urandom_usdt.c
+++ b/tools/testing/selftests/bpf/progs/test_urandom_usdt.c
@@ -67,6 +67,30 @@ int BPF_USDT(urandlib_read_with_sema, int iter_num, int iter_cnt, int buf_sz)
return 0;
}
+extern void bpf_testmod_save_fpregs(void) __ksym;
+
+u64 fpregs_dummy_opts_xmm_val;
+
+SEC("struct_ops/save_fpregs_and_read")
+int BPF_PROG(save_fpregs_and_read, struct bpf_dummy_ops_state *unused)
+{
+ struct task_struct *tsk;
+ u64 val[2];
+
+ bpf_testmod_save_fpregs();
+ tsk = bpf_get_current_task_btf();
+
+ bpf_get_reg_val(&val[0], 16, (u64)BPF_GETREG_X86_XMM10 << 32, NULL, tsk);
+ __sync_fetch_and_add(&fpregs_dummy_opts_xmm_val, val[0]);
+
+ return 0;
+}
+
+SEC(".struct_ops")
+struct bpf_dummy_ops dummy_ops = {
+ .test_1 = (void *)save_fpregs_and_read,
+};
+
int urandlib_xmm_reg_read_buf_sz_sum;
SEC("usdt/./liburandom_read_xmm.so:urandlib:xmm_reg_read")
int BPF_USDT(urandlib_xmm_reg_read, int *f1, int *f2, int *f3, int a, int b,
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index a07da648af3b..27a3e8cb9c36 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -620,6 +620,9 @@ int kern_sync_rcu(void)
static void unload_bpf_testmod(void)
{
+ bool tried_again = false;
+
+again:
if (kern_sync_rcu())
fprintf(env.stderr, "Failed to trigger kernel-side RCU sync!\n");
if (delete_module("bpf_testmod", 0)) {
@@ -627,6 +630,10 @@ static void unload_bpf_testmod(void)
if (verbose())
fprintf(stdout, "bpf_testmod.ko is already unloaded.\n");
return;
+ } else if (errno == EAGAIN && !tried_again) {
+ tried_again = true;
+ usleep(20 * 1000);
+ goto again;
}
fprintf(env.stderr, "Failed to unload bpf_testmod.ko from kernel: %d\n", -errno);
return;
--
2.30.2
next prev parent reply other threads:[~2022-05-12 7:43 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-12 7:43 [RFC PATCH bpf-next 0/5] bpf: add get_reg_val helper Dave Marchevsky
2022-05-12 7:43 ` [RFC PATCH bpf-next 1/5] x86/fpu: Move context.h to include/asm Dave Marchevsky
2022-05-12 13:56 ` David Vernet
2022-05-14 0:44 ` Alexei Starovoitov
2022-05-12 7:43 ` [RFC PATCH bpf-next 2/5] bpf: add get_reg_val helper Dave Marchevsky
2022-05-12 15:29 ` David Vernet
2022-05-18 8:07 ` Dave Marchevsky
2022-05-14 0:41 ` Alexei Starovoitov
2022-05-18 7:35 ` Dave Marchevsky
2022-05-12 7:43 ` [RFC PATCH bpf-next 3/5] libbpf: usdt lib wiring of xmm reads Dave Marchevsky
2022-05-14 0:43 ` Alexei Starovoitov
2022-05-16 23:26 ` Andrii Nakryiko
2022-05-18 8:20 ` Dave Marchevsky
2022-05-12 7:43 ` [RFC PATCH bpf-next 4/5] selftests/bpf: Add test for USDT parse of xmm reg Dave Marchevsky
2022-05-16 23:31 ` Andrii Nakryiko
2022-05-17 1:17 ` Alexei Starovoitov
2022-05-18 23:56 ` Andrii Nakryiko
2022-05-12 7:43 ` Dave Marchevsky [this message]
2022-05-12 17:47 ` [RFC PATCH bpf-next 5/5] selftests/bpf: get_reg_val test exercising fxsave fetch Dave Marchevsky
2022-05-16 23:28 ` Andrii Nakryiko
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=20220512074321.2090073-6-davemarchevsky@fb.com \
--to=davemarchevsky@fb.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=iii@linux.ibm.com \
--cc=kernel-team@fb.com \
--cc=riel@surriel.com \
--cc=yhs@fb.com \
/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