From: Ederson de Souza <ederson.desouza@intel.com>
To: xdp-hints@xdp-project.net
Cc: bpf@vger.kernel.org, Saeed Mahameed <saeedm@mellanox.com>
Subject: [[RFC xdp-hints] 01/16] bpf: add btf register/unregister API
Date: Mon, 2 Aug 2021 18:03:16 -0700 [thread overview]
Message-ID: <20210803010331.39453-2-ederson.desouza@intel.com> (raw)
In-Reply-To: <20210803010331.39453-1-ederson.desouza@intel.com>
From: Saeed Mahameed <saeedm@mellanox.com>
A device driver can register own BTF format buffers into the kernel.
Will be used in downstream patches by mlx5 XDP driver to advertise and
populated XDP meta data.
Issue: 2114293
Change-Id: I37cc1b18dadd7cf22aa67d2f14d811deae7525b4
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
include/linux/btf.h | 9 +++
kernel/bpf/btf.c | 155 +++++++++++++++++++++++++++++++++++---------
2 files changed, 135 insertions(+), 29 deletions(-)
diff --git a/include/linux/btf.h b/include/linux/btf.h
index 214fde93214b..d48e6fcf46dc 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -225,6 +225,8 @@ const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
const char *btf_name_by_offset(const struct btf *btf, u32 offset);
struct btf *btf_parse_vmlinux(void);
struct btf *bpf_prog_get_target_btf(const struct bpf_prog *prog);
+struct btf *btf_register(void *data, u32 data_size);
+void btf_unregister(struct btf *btf);
#else
static inline const struct btf_type *btf_type_by_id(const struct btf *btf,
u32 type_id)
@@ -236,6 +238,13 @@ static inline const char *btf_name_by_offset(const struct btf *btf,
{
return NULL;
}
+
+static inline struct btf *btf_register(void *data, u32 data_size)
+{
+ return NULL;
+}
+
+static inline void btf_unregister(struct btf *btf) { }
#endif
#endif
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 7780131f710e..88d8cd02d282 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -1509,11 +1509,31 @@ static void btf_free_id(struct btf *btf)
spin_unlock_irqrestore(&btf_idr_lock, flags);
}
+static struct btf *btf_alloc(u32 data_size)
+{
+ struct btf *btf;
+
+ btf = kzalloc(sizeof(*btf), GFP_KERNEL | __GFP_NOWARN);
+ if (!btf)
+ return NULL;
+
+ btf->data = kvmalloc(data_size, GFP_KERNEL | __GFP_NOWARN);
+ if (!btf->data) {
+ kfree(btf);
+ return NULL;
+ }
+
+ btf->data_size = data_size;
+ return btf;
+}
+
static void btf_free(struct btf *btf)
{
kvfree(btf->types);
kvfree(btf->resolved_sizes);
kvfree(btf->resolved_ids);
+
+ /* stuff allocated via btf_alloc */
kvfree(btf->data);
kfree(btf);
}
@@ -1574,6 +1594,13 @@ static int env_resolve_init(struct btf_verifier_env *env)
return -ENOMEM;
}
+static struct btf_verifier_env *btf_verifier_env_alloc(void)
+{
+ gfp_t flags = GFP_KERNEL | __GFP_NOWARN;
+
+ return kzalloc(sizeof(struct btf_verifier_env), flags);
+}
+
static void btf_verifier_env_free(struct btf_verifier_env *env)
{
kvfree(env->visit_states);
@@ -4306,19 +4333,37 @@ static int btf_parse_hdr(struct btf_verifier_env *env)
return 0;
}
-static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size,
- u32 log_level, char __user *log_ubuf, u32 log_size)
+static int btf_parse(struct btf_verifier_env *env)
+{
+ struct btf *btf = env->btf;
+ int err;
+
+ err = btf_parse_hdr(env);
+ if (err)
+ return err;
+
+ btf->nohdr_data = btf->data + btf->hdr.hdr_len;
+
+ err = btf_parse_str_sec(env);
+ if (err)
+ return err;
+
+ return btf_parse_type_sec(env);
+}
+
+static struct btf *
+btf_parse_user(bpfptr_t btf_data, u32 btf_data_size,
+ u32 log_level, char __user *log_ubuf, u32 log_size)
{
struct btf_verifier_env *env = NULL;
struct bpf_verifier_log *log;
struct btf *btf = NULL;
- u8 *data;
int err;
if (btf_data_size > BTF_MAX_SIZE)
return ERR_PTR(-E2BIG);
- env = kzalloc(sizeof(*env), GFP_KERNEL | __GFP_NOWARN);
+ env = btf_verifier_env_alloc();
if (!env)
return ERR_PTR(-ENOMEM);
@@ -4339,45 +4384,66 @@ static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size,
}
}
- btf = kzalloc(sizeof(*btf), GFP_KERNEL | __GFP_NOWARN);
+ btf = btf_alloc(btf_data_size);
if (!btf) {
err = -ENOMEM;
goto errout;
}
- env->btf = btf;
- data = kvmalloc(btf_data_size, GFP_KERNEL | __GFP_NOWARN);
- if (!data) {
- err = -ENOMEM;
+ if (copy_from_bpfptr(btf->data, btf_data, btf_data_size)) {
+ err = -EFAULT;
goto errout;
}
- btf->data = data;
- btf->data_size = btf_data_size;
+ env->btf = btf;
+ err = btf_parse(env);
+ if (err)
+ goto errout;
- if (copy_from_bpfptr(data, btf_data, btf_data_size)) {
- err = -EFAULT;
+ if (log->level && bpf_verifier_log_full(log)) {
+ err = -ENOSPC;
goto errout;
}
- err = btf_parse_hdr(env);
- if (err)
- goto errout;
+ btf_verifier_env_free(env);
+ refcount_set(&btf->refcnt, 1);
+ return btf;
- btf->nohdr_data = btf->data + btf->hdr.hdr_len;
+errout:
+ btf_verifier_env_free(env);
+ if (btf)
+ btf_free(btf);
+ return ERR_PTR(err);
+}
- err = btf_parse_str_sec(env);
- if (err)
- goto errout;
+static struct btf *btf_parse_raw(void *btf_data, u32 btf_data_size)
+{
+ struct btf_verifier_env *env = NULL;
+ struct btf *btf = NULL;
+ int err;
- err = btf_parse_type_sec(env);
- if (err)
- goto errout;
+ if (btf_data_size > BTF_MAX_SIZE)
+ return ERR_PTR(-E2BIG);
- if (log->level && bpf_verifier_log_full(log)) {
- err = -ENOSPC;
+ env = btf_verifier_env_alloc();
+ if (!env)
+ return ERR_PTR(-ENOMEM);
+
+ /* force log to go to kernel trace buffer */
+ env->log.level = BPF_LOG_KERNEL;
+
+ btf = btf_alloc(btf_data_size);
+ if (!btf) {
+ err = -ENOMEM;
goto errout;
}
+ memcpy(btf->data, btf_data, btf_data_size);
+
+ env->btf = btf;
+
+ err = btf_parse(env);
+ if (err)
+ goto errout;
btf_verifier_env_free(env);
refcount_set(&btf->refcnt, 1);
@@ -4388,6 +4454,7 @@ static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size,
if (btf)
btf_free(btf);
return ERR_PTR(err);
+
}
extern char __weak __start_BTF[];
@@ -5846,10 +5913,10 @@ int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr)
struct btf *btf;
int ret;
- btf = btf_parse(make_bpfptr(attr->btf, uattr.is_kernel),
- attr->btf_size, attr->btf_log_level,
- u64_to_user_ptr(attr->btf_log_buf),
- attr->btf_log_size);
+ btf = btf_parse_user(make_bpfptr(attr->btf, uattr.is_kernel),
+ attr->btf_size, attr->btf_log_level,
+ u64_to_user_ptr(attr->btf_log_buf),
+ attr->btf_log_size);
if (IS_ERR(btf))
return PTR_ERR(btf);
@@ -5872,6 +5939,35 @@ int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr)
return ret;
}
+struct btf *btf_register(void *data, u32 data_size)
+{
+ struct btf *btf;
+ int ret;
+
+ btf = btf_parse_raw(data, data_size);
+ if (IS_ERR(btf))
+ return btf;
+
+ ret = btf_alloc_id(btf);
+ if (ret) {
+ btf_free(btf);
+ return ERR_PTR(ret);
+ }
+
+ return btf;
+}
+EXPORT_SYMBOL(btf_register);
+
+void btf_unregister(struct btf *btf)
+{
+ if (IS_ERR(btf))
+ return;
+
+ /* btf_put since btf might be held by user */
+ btf_put(btf);
+}
+EXPORT_SYMBOL(btf_unregister);
+
struct btf *btf_get_by_fd(int fd)
{
struct btf *btf;
@@ -5979,6 +6075,7 @@ u32 btf_obj_id(const struct btf *btf)
{
return btf->id;
}
+EXPORT_SYMBOL(btf_obj_id);
bool btf_is_kernel(const struct btf *btf)
{
--
2.32.0
next prev parent reply other threads:[~2021-08-03 1:03 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-03 1:03 [[RFC xdp-hints] 00/16] XDP hints and AF_XDP support Ederson de Souza
2021-08-03 1:03 ` Ederson de Souza [this message]
2021-08-03 1:03 ` [[RFC xdp-hints] 02/16] net/core: XDP metadata BTF netlink API Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 03/16] tools/bpf: Query XDP metadata BTF ID Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 04/16] tools/bpf: Add xdp set command for md btf Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 05/16] igc: Fix race condition in PTP Tx code Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 06/16] igc: Retrieve the TX timestamp directly (instead of in a interrupt) Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 07/16] igc: Add support for multiple in-flight TX timestamps Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 08/16] igc: Use irq safe locks for timestamping Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 09/16] net/xdp: Support for generic XDP hints Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 10/16] igc: XDP packet RX timestamp Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 11/16] igc: XDP packet TX timestamp Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 12/16] ethtool,igc: Add "xdp_headroom" driver info Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 13/16] libbpf: Helpers to access XDP frame metadata Ederson de Souza
2021-08-06 22:59 ` Andrii Nakryiko
2021-08-19 11:47 ` Toke Høiland-Jørgensen
2021-08-03 1:03 ` [[RFC xdp-hints] 14/16] libbpf: Helpers to access XDP hints based on BTF definitions Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 15/16] samples/bpf: XDP hints AF_XDP example Ederson de Souza
2021-08-03 1:03 ` [[RFC xdp-hints] 16/16] samples/bpf: Show XDP hints usage Ederson de Souza
2021-08-06 23:14 ` Andrii Nakryiko
2021-08-03 9:12 ` [[RFC xdp-hints] 00/16] XDP hints and AF_XDP support Alexander Lobakin
2021-08-03 15:23 ` John Fastabend
2021-08-04 15:15 ` Alexander Lobakin
2021-08-04 23:45 ` John Fastabend
2021-08-13 22:04 ` Desouza, Ederson
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
List information: https://lists.xdp-project.net/postorius/lists/xdp-hints.xdp-project.net/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210803010331.39453-2-ederson.desouza@intel.com \
--to=ederson.desouza@intel.com \
--cc=bpf@vger.kernel.org \
--cc=saeedm@mellanox.com \
--cc=xdp-hints@xdp-project.net \
/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