162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2021 Facebook */ 362306a36Sopenharmony_ci#include <linux/stddef.h> 462306a36Sopenharmony_ci#include <linux/bpf.h> 562306a36Sopenharmony_ci#include <bpf/bpf_helpers.h> 662306a36Sopenharmony_ci#include <bpf/bpf_tracing.h> 762306a36Sopenharmony_ci#include <../../../tools/include/linux/filter.h> 862306a36Sopenharmony_ci#include <linux/btf.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cichar _license[] SEC("license") = "GPL"; 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistruct args { 1362306a36Sopenharmony_ci __u64 log_buf; 1462306a36Sopenharmony_ci __u32 log_size; 1562306a36Sopenharmony_ci int max_entries; 1662306a36Sopenharmony_ci int map_fd; 1762306a36Sopenharmony_ci int prog_fd; 1862306a36Sopenharmony_ci int btf_fd; 1962306a36Sopenharmony_ci}; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define BTF_INFO_ENC(kind, kind_flag, vlen) \ 2262306a36Sopenharmony_ci ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN)) 2362306a36Sopenharmony_ci#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type) 2462306a36Sopenharmony_ci#define BTF_INT_ENC(encoding, bits_offset, nr_bits) \ 2562306a36Sopenharmony_ci ((encoding) << 24 | (bits_offset) << 16 | (nr_bits)) 2662306a36Sopenharmony_ci#define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \ 2762306a36Sopenharmony_ci BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \ 2862306a36Sopenharmony_ci BTF_INT_ENC(encoding, bits_offset, bits) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic int btf_load(void) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci struct btf_blob { 3362306a36Sopenharmony_ci struct btf_header btf_hdr; 3462306a36Sopenharmony_ci __u32 types[8]; 3562306a36Sopenharmony_ci __u32 str; 3662306a36Sopenharmony_ci } raw_btf = { 3762306a36Sopenharmony_ci .btf_hdr = { 3862306a36Sopenharmony_ci .magic = BTF_MAGIC, 3962306a36Sopenharmony_ci .version = BTF_VERSION, 4062306a36Sopenharmony_ci .hdr_len = sizeof(struct btf_header), 4162306a36Sopenharmony_ci .type_len = sizeof(__u32) * 8, 4262306a36Sopenharmony_ci .str_off = sizeof(__u32) * 8, 4362306a36Sopenharmony_ci .str_len = sizeof(__u32), 4462306a36Sopenharmony_ci }, 4562306a36Sopenharmony_ci .types = { 4662306a36Sopenharmony_ci /* long */ 4762306a36Sopenharmony_ci BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8), /* [1] */ 4862306a36Sopenharmony_ci /* unsigned long */ 4962306a36Sopenharmony_ci BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 5062306a36Sopenharmony_ci }, 5162306a36Sopenharmony_ci }; 5262306a36Sopenharmony_ci static union bpf_attr btf_load_attr = { 5362306a36Sopenharmony_ci .btf_size = sizeof(raw_btf), 5462306a36Sopenharmony_ci }; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci btf_load_attr.btf = (long)&raw_btf; 5762306a36Sopenharmony_ci return bpf_sys_bpf(BPF_BTF_LOAD, &btf_load_attr, sizeof(btf_load_attr)); 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciSEC("syscall") 6162306a36Sopenharmony_ciint bpf_prog(struct args *ctx) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci static char license[] = "GPL"; 6462306a36Sopenharmony_ci static struct bpf_insn insns[] = { 6562306a36Sopenharmony_ci BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 6662306a36Sopenharmony_ci BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 6762306a36Sopenharmony_ci BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 6862306a36Sopenharmony_ci BPF_LD_MAP_FD(BPF_REG_1, 0), 6962306a36Sopenharmony_ci BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 7062306a36Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 7162306a36Sopenharmony_ci BPF_EXIT_INSN(), 7262306a36Sopenharmony_ci }; 7362306a36Sopenharmony_ci static union bpf_attr map_create_attr = { 7462306a36Sopenharmony_ci .map_type = BPF_MAP_TYPE_HASH, 7562306a36Sopenharmony_ci .key_size = 8, 7662306a36Sopenharmony_ci .value_size = 8, 7762306a36Sopenharmony_ci .btf_key_type_id = 1, 7862306a36Sopenharmony_ci .btf_value_type_id = 2, 7962306a36Sopenharmony_ci }; 8062306a36Sopenharmony_ci static union bpf_attr map_update_attr = { .map_fd = 1, }; 8162306a36Sopenharmony_ci static __u64 key = 12; 8262306a36Sopenharmony_ci static __u64 value = 34; 8362306a36Sopenharmony_ci static union bpf_attr prog_load_attr = { 8462306a36Sopenharmony_ci .prog_type = BPF_PROG_TYPE_XDP, 8562306a36Sopenharmony_ci .insn_cnt = sizeof(insns) / sizeof(insns[0]), 8662306a36Sopenharmony_ci }; 8762306a36Sopenharmony_ci int ret; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci ret = btf_load(); 9062306a36Sopenharmony_ci if (ret <= 0) 9162306a36Sopenharmony_ci return ret; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci ctx->btf_fd = ret; 9462306a36Sopenharmony_ci map_create_attr.max_entries = ctx->max_entries; 9562306a36Sopenharmony_ci map_create_attr.btf_fd = ret; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci prog_load_attr.license = (long) license; 9862306a36Sopenharmony_ci prog_load_attr.insns = (long) insns; 9962306a36Sopenharmony_ci prog_load_attr.log_buf = ctx->log_buf; 10062306a36Sopenharmony_ci prog_load_attr.log_size = ctx->log_size; 10162306a36Sopenharmony_ci prog_load_attr.log_level = 1; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci ret = bpf_sys_bpf(BPF_MAP_CREATE, &map_create_attr, sizeof(map_create_attr)); 10462306a36Sopenharmony_ci if (ret <= 0) 10562306a36Sopenharmony_ci return ret; 10662306a36Sopenharmony_ci ctx->map_fd = ret; 10762306a36Sopenharmony_ci insns[3].imm = ret; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci map_update_attr.map_fd = ret; 11062306a36Sopenharmony_ci map_update_attr.key = (long) &key; 11162306a36Sopenharmony_ci map_update_attr.value = (long) &value; 11262306a36Sopenharmony_ci ret = bpf_sys_bpf(BPF_MAP_UPDATE_ELEM, &map_update_attr, sizeof(map_update_attr)); 11362306a36Sopenharmony_ci if (ret < 0) 11462306a36Sopenharmony_ci return ret; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci ret = bpf_sys_bpf(BPF_PROG_LOAD, &prog_load_attr, sizeof(prog_load_attr)); 11762306a36Sopenharmony_ci if (ret <= 0) 11862306a36Sopenharmony_ci return ret; 11962306a36Sopenharmony_ci ctx->prog_fd = ret; 12062306a36Sopenharmony_ci return 1; 12162306a36Sopenharmony_ci} 122