[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <13cfab3593e0ea960ca732c259bfa60bf3c16b3b.1609855479.git.sean@mess.org>
Date: Tue, 5 Jan 2021 14:45:31 +0000
From: Sean Young <sean@...s.org>
To: Yonghong Song <yhs@...com>, Alexei Starovoitov <ast@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Andrii Nakryiko <andrii@...nel.org>,
Martin KaFai Lau <kafai@...com>,
Song Liu <songliubraving@...com>,
John Fastabend <john.fastabend@...il.com>,
KP Singh <kpsingh@...nel.org>,
Nathan Chancellor <natechancellor@...il.com>,
Nick Desaulniers <ndesaulniers@...gle.com>,
Quentin Monnet <quentin@...valent.com>,
Toke Høiland-Jørgensen <toke@...hat.com>,
linux-doc@...r.kernel.org, netdev@...r.kernel.org,
bpf@...r.kernel.org, linux-kernel@...r.kernel.org,
clang-built-linux@...glegroups.com
Subject: [PATCH v3 1/4] btf: add support for ints larger than 128 bits
clang supports arbitrary length ints using the _ExtInt extension. This
can be useful to hold very large values, e.g. 256 bit or 512 bit types.
Larger types (e.g. 1024 bits) are possible but I am unaware of a use
case for these.
This requires the _ExtInt extension enabled in clang, which is under
review.
Link: https://clang.llvm.org/docs/LanguageExtensions.html#extended-integer-types
Link: https://reviews.llvm.org/D93103
Signed-off-by: Sean Young <sean@...s.org>
---
Documentation/bpf/btf.rst | 4 +--
include/uapi/linux/btf.h | 2 +-
kernel/bpf/btf.c | 54 ++++++++++++++++++++++++++++------
tools/include/uapi/linux/btf.h | 2 +-
4 files changed, 49 insertions(+), 13 deletions(-)
diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst
index 44dc789de2b4..784f1743dbc7 100644
--- a/Documentation/bpf/btf.rst
+++ b/Documentation/bpf/btf.rst
@@ -132,7 +132,7 @@ The following sections detail encoding of each kind.
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
#define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
- #define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
+ #define BTF_INT_BITS(VAL) ((VAL) & 0x000003ff)
The ``BTF_INT_ENCODING`` has the following attributes::
@@ -147,7 +147,7 @@ pretty print. At most one encoding can be specified for the int type.
The ``BTF_INT_BITS()`` specifies the number of actual bits held by this int
type. For example, a 4-bit bitfield encodes ``BTF_INT_BITS()`` equals to 4.
The ``btf_type.size * 8`` must be equal to or greater than ``BTF_INT_BITS()``
-for the type. The maximum value of ``BTF_INT_BITS()`` is 128.
+for the type. The maximum value of ``BTF_INT_BITS()`` is 512.
The ``BTF_INT_OFFSET()`` specifies the starting bit offset to calculate values
for this int. For example, a bitfield struct member has:
diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h
index 5a667107ad2c..1696fd02b302 100644
--- a/include/uapi/linux/btf.h
+++ b/include/uapi/linux/btf.h
@@ -84,7 +84,7 @@ struct btf_type {
*/
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
#define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
-#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
+#define BTF_INT_BITS(VAL) ((VAL) & 0x000003ff)
/* Attributes stored in the BTF_INT_ENCODING */
#define BTF_INT_SIGNED (1 << 0)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 8d6bdb4f4d61..44bc17207e9b 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -166,7 +166,8 @@
*
*/
-#define BITS_PER_U128 (sizeof(u64) * BITS_PER_BYTE * 2)
+#define BITS_PER_U128 128
+#define BITS_PER_U512 512
#define BITS_PER_BYTE_MASK (BITS_PER_BYTE - 1)
#define BITS_PER_BYTE_MASKED(bits) ((bits) & BITS_PER_BYTE_MASK)
#define BITS_ROUNDDOWN_BYTES(bits) ((bits) >> 3)
@@ -1907,9 +1908,9 @@ static int btf_int_check_member(struct btf_verifier_env *env,
nr_copy_bits = BTF_INT_BITS(int_data) +
BITS_PER_BYTE_MASKED(struct_bits_off);
- if (nr_copy_bits > BITS_PER_U128) {
+ if (nr_copy_bits > BITS_PER_U512) {
btf_verifier_log_member(env, struct_type, member,
- "nr_copy_bits exceeds 128");
+ "nr_copy_bits exceeds 512");
return -EINVAL;
}
@@ -1963,9 +1964,9 @@ static int btf_int_check_kflag_member(struct btf_verifier_env *env,
bytes_offset = BITS_ROUNDDOWN_BYTES(struct_bits_off);
nr_copy_bits = nr_bits + BITS_PER_BYTE_MASKED(struct_bits_off);
- if (nr_copy_bits > BITS_PER_U128) {
+ if (nr_copy_bits > BITS_PER_U512) {
btf_verifier_log_member(env, struct_type, member,
- "nr_copy_bits exceeds 128");
+ "nr_copy_bits exceeds 512");
return -EINVAL;
}
@@ -2012,9 +2013,9 @@ static s32 btf_int_check_meta(struct btf_verifier_env *env,
nr_bits = BTF_INT_BITS(int_data) + BTF_INT_OFFSET(int_data);
- if (nr_bits > BITS_PER_U128) {
- btf_verifier_log_type(env, t, "nr_bits exceeds %zu",
- BITS_PER_U128);
+ if (nr_bits > BITS_PER_U512) {
+ btf_verifier_log_type(env, t, "nr_bits exceeds %u",
+ BITS_PER_U512);
return -EINVAL;
}
@@ -2080,6 +2081,37 @@ static void btf_int128_print(struct btf_show *show, void *data)
lower_num);
}
+static void btf_bigint_print(struct btf_show *show, void *data, u16 nr_bits)
+{
+ /* data points to 256 or 512 bit int type */
+ char buf[129];
+ int last_u64 = nr_bits / 64 - 1;
+ bool seen_nonzero = false;
+ int i;
+
+ for (i = 0; i <= last_u64; i++) {
+#ifdef __BIG_ENDIAN_BITFIELD
+ u64 v = ((u64 *)data)[i];
+#else
+ u64 v = ((u64 *)data)[last_u64 - i];
+#endif
+ if (!seen_nonzero) {
+ if (!v && i != last_u64)
+ continue;
+
+ snprintf(buf, sizeof(buf), "%llx", v);
+
+ seen_nonzero = true;
+ } else {
+ size_t off = strlen(buf);
+
+ snprintf(buf + off, sizeof(buf) - off, "%016llx", v);
+ }
+ }
+
+ btf_show_type_value(show, "0x%s", buf);
+}
+
static void btf_int128_shift(u64 *print_num, u16 left_shift_bits,
u16 right_shift_bits)
{
@@ -2172,7 +2204,7 @@ static void btf_int_show(const struct btf *btf, const struct btf_type *t,
u32 int_data = btf_type_int(t);
u8 encoding = BTF_INT_ENCODING(int_data);
bool sign = encoding & BTF_INT_SIGNED;
- u8 nr_bits = BTF_INT_BITS(int_data);
+ u16 nr_bits = BTF_INT_BITS(int_data);
void *safe_data;
safe_data = btf_show_start_type(show, t, type_id, data);
@@ -2186,6 +2218,10 @@ static void btf_int_show(const struct btf *btf, const struct btf_type *t,
}
switch (nr_bits) {
+ case 512:
+ case 256:
+ btf_bigint_print(show, safe_data, nr_bits);
+ break;
case 128:
btf_int128_print(show, safe_data);
break;
diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h
index 5a667107ad2c..1696fd02b302 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -84,7 +84,7 @@ struct btf_type {
*/
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
#define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
-#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
+#define BTF_INT_BITS(VAL) ((VAL) & 0x000003ff)
/* Attributes stored in the BTF_INT_ENCODING */
#define BTF_INT_SIGNED (1 << 0)
--
2.29.2
Powered by blists - more mailing lists