linux/tools/testing/selftests/bpf/progs/syscall.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2021 Facebook */
   3#include <linux/stddef.h>
   4#include <linux/bpf.h>
   5#include <bpf/bpf_helpers.h>
   6#include <bpf/bpf_tracing.h>
   7#include <../../../tools/include/linux/filter.h>
   8#include <linux/btf.h>
   9
  10char _license[] SEC("license") = "GPL";
  11
  12struct args {
  13        __u64 log_buf;
  14        __u32 log_size;
  15        int max_entries;
  16        int map_fd;
  17        int prog_fd;
  18        int btf_fd;
  19};
  20
  21#define BTF_INFO_ENC(kind, kind_flag, vlen) \
  22        ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
  23#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
  24#define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
  25        ((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
  26#define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
  27        BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
  28        BTF_INT_ENC(encoding, bits_offset, bits)
  29
  30static int btf_load(void)
  31{
  32        struct btf_blob {
  33                struct btf_header btf_hdr;
  34                __u32 types[8];
  35                __u32 str;
  36        } raw_btf = {
  37                .btf_hdr = {
  38                        .magic = BTF_MAGIC,
  39                        .version = BTF_VERSION,
  40                        .hdr_len = sizeof(struct btf_header),
  41                        .type_len = sizeof(__u32) * 8,
  42                        .str_off = sizeof(__u32) * 8,
  43                        .str_len = sizeof(__u32),
  44                },
  45                .types = {
  46                        /* long */
  47                        BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8),  /* [1] */
  48                        /* unsigned long */
  49                        BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),  /* [2] */
  50                },
  51        };
  52        static union bpf_attr btf_load_attr = {
  53                .btf_size = sizeof(raw_btf),
  54        };
  55
  56        btf_load_attr.btf = (long)&raw_btf;
  57        return bpf_sys_bpf(BPF_BTF_LOAD, &btf_load_attr, sizeof(btf_load_attr));
  58}
  59
  60SEC("syscall")
  61int bpf_prog(struct args *ctx)
  62{
  63        static char license[] = "GPL";
  64        static struct bpf_insn insns[] = {
  65                BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  66                BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
  67                BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
  68                BPF_LD_MAP_FD(BPF_REG_1, 0),
  69                BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  70                BPF_MOV64_IMM(BPF_REG_0, 0),
  71                BPF_EXIT_INSN(),
  72        };
  73        static union bpf_attr map_create_attr = {
  74                .map_type = BPF_MAP_TYPE_HASH,
  75                .key_size = 8,
  76                .value_size = 8,
  77                .btf_key_type_id = 1,
  78                .btf_value_type_id = 2,
  79        };
  80        static union bpf_attr map_update_attr = { .map_fd = 1, };
  81        static __u64 key = 12;
  82        static __u64 value = 34;
  83        static union bpf_attr prog_load_attr = {
  84                .prog_type = BPF_PROG_TYPE_XDP,
  85                .insn_cnt = sizeof(insns) / sizeof(insns[0]),
  86        };
  87        int ret;
  88
  89        ret = btf_load();
  90        if (ret <= 0)
  91                return ret;
  92
  93        ctx->btf_fd = ret;
  94        map_create_attr.max_entries = ctx->max_entries;
  95        map_create_attr.btf_fd = ret;
  96
  97        prog_load_attr.license = (long) license;
  98        prog_load_attr.insns = (long) insns;
  99        prog_load_attr.log_buf = ctx->log_buf;
 100        prog_load_attr.log_size = ctx->log_size;
 101        prog_load_attr.log_level = 1;
 102
 103        ret = bpf_sys_bpf(BPF_MAP_CREATE, &map_create_attr, sizeof(map_create_attr));
 104        if (ret <= 0)
 105                return ret;
 106        ctx->map_fd = ret;
 107        insns[3].imm = ret;
 108
 109        map_update_attr.map_fd = ret;
 110        map_update_attr.key = (long) &key;
 111        map_update_attr.value = (long) &value;
 112        ret = bpf_sys_bpf(BPF_MAP_UPDATE_ELEM, &map_update_attr, sizeof(map_update_attr));
 113        if (ret < 0)
 114                return ret;
 115
 116        ret = bpf_sys_bpf(BPF_PROG_LOAD, &prog_load_attr, sizeof(prog_load_attr));
 117        if (ret <= 0)
 118                return ret;
 119        ctx->prog_fd = ret;
 120        return 1;
 121}
 122