Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
sudo: required
language: bash
dist: bionic
services:
- docker

env:
global:
- PROJECT_NAME='libbpf'
- AUTHOR_EMAIL="$(git log -1 --pretty=\"%aE\")"
- REPO_ROOT="$TRAVIS_BUILD_DIR"
- CI_ROOT="$REPO_ROOT/travis-ci"
- VMTEST_ROOT="$CI_ROOT/vmtest"

addons:
apt:
packages:
- qemu-kvm
- zstd
- binutils-dev
- elfutils
- libcap-dev
- libelf-dev
- libdw-dev
- python3-docutils

jobs:
include:
- stage: Builds & Tests
name: Kernel LATEST + selftests
language: bash
env: KERNEL=LATEST
script: $CI_ROOT/vmtest/run_vmtest.sh || travis_terminate 1
4 changes: 2 additions & 2 deletions Documentation/bpf/btf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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::

Expand All @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion include/uapi/linux/btf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
54 changes: 45 additions & 9 deletions kernel/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down
40 changes: 40 additions & 0 deletions tools/bpf/bpftool/btf_dumper.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,41 @@ static void btf_int128_print(json_writer_t *jw, const void *data,
}
}

static void btf_bigint_print(json_writer_t *jw, const void *data, int nr_bits,
bool is_plain_text)
{
char buf[nr_bits / 4 + 1];
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);
}
}

if (is_plain_text)
jsonw_printf(jw, "0x%s", buf);
else
jsonw_printf(jw, "\"0x%s\"", buf);
}

static void btf_int128_shift(__u64 *print_num, __u16 left_shift_bits,
__u16 right_shift_bits)
{
Expand Down Expand Up @@ -373,6 +408,11 @@ static int btf_dumper_int(const struct btf_type *t, __u8 bit_offset,
return 0;
}

if (nr_bits > 128) {
btf_bigint_print(jw, data, nr_bits, is_plain_text);
return 0;
}

if (nr_bits == 128) {
btf_int128_print(jw, data, is_plain_text);
return 0;
Expand Down
2 changes: 1 addition & 1 deletion tools/include/uapi/linux/btf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion tools/lib/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1722,7 +1722,7 @@ int btf__add_int(struct btf *btf, const char *name, size_t byte_sz, int encoding
if (!name || !name[0])
return -EINVAL;
/* byte_sz must be power of 2 */
if (!byte_sz || (byte_sz & (byte_sz - 1)) || byte_sz > 16)
if (!byte_sz || (byte_sz & (byte_sz - 1)) || byte_sz > 64)
return -EINVAL;
if (encoding & ~(BTF_INT_SIGNED | BTF_INT_CHAR | BTF_INT_BOOL))
return -EINVAL;
Expand Down
3 changes: 2 additions & 1 deletion tools/testing/selftests/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ TEST_PROGS := test_kmod.sh \
test_bpftool_build.sh \
test_bpftool.sh \
test_bpftool_metadata.sh \
test_xsk.sh
test_xsk.sh \
test_extint.py

TEST_PROGS_EXTENDED := with_addr.sh \
with_tunnels.sh \
Expand Down
3 changes: 2 additions & 1 deletion tools/testing/selftests/bpf/prog_tests/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -4073,6 +4073,7 @@ struct btf_file_test {
static struct btf_file_test file_tests[] = {
{ .file = "test_btf_haskv.o", },
{ .file = "test_btf_newkv.o", },
{ .file = "test_btf_extint.o", },
{ .file = "test_btf_nokv.o", .btf_kv_notfound = true, },
};

Expand Down Expand Up @@ -4414,7 +4415,7 @@ static struct btf_raw_test pprint_test_template[] = {
* will have both int and enum types.
*/
.raw_types = {
/* unsighed char */ /* [1] */
/* unsigned char */ /* [1] */
BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 8, 1),
/* unsigned short */ /* [2] */
BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 16, 2),
Expand Down
50 changes: 50 additions & 0 deletions tools/testing/selftests/bpf/progs/test_btf_extint.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include "bpf_legacy.h"

struct extint {
_ExtInt(256) v256;
_ExtInt(512) v512;
};

struct bpf_map_def SEC("maps") btf_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(struct extint),
.max_entries = 1,
};

BPF_ANNOTATE_KV_PAIR(btf_map, int, struct extint);

__attribute__((noinline))
int test_long_fname_2(void)
{
struct extint *bi;
int key = 0;

bi = bpf_map_lookup_elem(&btf_map, &key);
if (!bi)
return 0;

bi->v256 <<= 64;
bi->v256 += (_ExtInt(256))0xcafedead;
bi->v512 <<= 128;
bi->v512 += (_ExtInt(512))0xff00ff00ff00ffull;

return 0;
}

__attribute__((noinline))
int test_long_fname_1(void)
{
return test_long_fname_2();
}

SEC("dummy_tracepoint")
int _dummy_tracepoint(void *arg)
{
return test_long_fname_1();
}

char _license[] SEC("license") = "GPL";
Loading