XDP hardware hints discussion mail archive
 help / color / mirror / Atom feed
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


  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