#include <linux/netdevice.h>
#include <linux/filter.h>
#include <linux/if_vlan.h>
#include <linux/bpf.h>
#include <linux/memory.h>
#include <linux/sort.h>
#include <asm/extable.h>
#include <asm/ftrace.h>
#include <asm/set_memory.h>
#include <asm/nospec-branch.h>
#include <asm/text-patching.h>
#include <asm/unwind.h>
#include <asm/cfi.h>
static bool all_callee_regs_used[4] = …;
static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
{ … }
#define EMIT(bytes, len) …
#define EMIT1(b1) …
#define EMIT2(b1, b2) …
#define EMIT3(b1, b2, b3) …
#define EMIT4(b1, b2, b3, b4) …
#define EMIT1_off32(b1, off) …
#define EMIT2_off32(b1, b2, off) …
#define EMIT3_off32(b1, b2, b3, off) …
#define EMIT4_off32(b1, b2, b3, b4, off) …
#ifdef CONFIG_X86_KERNEL_IBT
#define EMIT_ENDBR() …
#define EMIT_ENDBR_POISON() …
#else
#define EMIT_ENDBR …
#define EMIT_ENDBR_POISON …
#endif
static bool is_imm8(int value)
{ … }
static bool is_imm8_jmp_offset(int value)
{ … }
static bool is_simm32(s64 value)
{ … }
static bool is_uimm32(u64 value)
{ … }
#define EMIT_mov(DST, SRC) …
static int bpf_size_to_x86_bytes(int bpf_size)
{ … }
#define X86_JB …
#define X86_JAE …
#define X86_JE …
#define X86_JNE …
#define X86_JBE …
#define X86_JA …
#define X86_JL …
#define X86_JGE …
#define X86_JLE …
#define X86_JG …
#define AUX_REG …
#define X86_REG_R9 …
#define X86_REG_R12 …
static const int reg2hex[] = …;
static const int reg2pt_regs[] = …;
static bool is_ereg(u32 reg)
{ … }
static bool is_ereg_8l(u32 reg)
{ … }
static bool is_axreg(u32 reg)
{ … }
static u8 add_1mod(u8 byte, u32 reg)
{ … }
static u8 add_2mod(u8 byte, u32 r1, u32 r2)
{ … }
static u8 add_3mod(u8 byte, u32 r1, u32 r2, u32 index)
{ … }
static u8 add_1reg(u8 byte, u32 dst_reg)
{ … }
static u8 add_2reg(u8 byte, u32 dst_reg, u32 src_reg)
{ … }
static u8 simple_alu_opcodes[] = …;
static void jit_fill_hole(void *area, unsigned int size)
{ … }
int bpf_arch_text_invalidate(void *dst, size_t len)
{ … }
struct jit_context { … };
#define BPF_MAX_INSN_SIZE …
#define BPF_INSN_SAFETY …
#define X86_PATCH_SIZE …
#define X86_TAIL_CALL_OFFSET …
static void push_r12(u8 **pprog)
{ … }
static void push_callee_regs(u8 **pprog, bool *callee_regs_used)
{ … }
static void pop_r12(u8 **pprog)
{ … }
static void pop_callee_regs(u8 **pprog, bool *callee_regs_used)
{ … }
static void emit_nops(u8 **pprog, int len)
{ … }
static void emit_fineibt(u8 **pprog, u32 hash)
{ … }
static void emit_kcfi(u8 **pprog, u32 hash)
{ … }
static void emit_cfi(u8 **pprog, u32 hash)
{ … }
static void emit_prologue_tail_call(u8 **pprog, bool is_subprog)
{ … }
static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf,
bool tail_call_reachable, bool is_subprog,
bool is_exception_cb)
{ … }
static int emit_patch(u8 **pprog, void *func, void *ip, u8 opcode)
{ … }
static int emit_call(u8 **pprog, void *func, void *ip)
{ … }
static int emit_rsb_call(u8 **pprog, void *func, void *ip)
{ … }
static int emit_jump(u8 **pprog, void *func, void *ip)
{ … }
static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
void *old_addr, void *new_addr)
{ … }
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
void *old_addr, void *new_addr)
{ … }
#define EMIT_LFENCE() …
static void emit_indirect_jump(u8 **pprog, int reg, u8 *ip)
{ … }
static void emit_return(u8 **pprog, u8 *ip)
{ … }
#define BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack) …
static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog,
u8 **pprog, bool *callee_regs_used,
u32 stack_depth, u8 *ip,
struct jit_context *ctx)
{ … }
static void emit_bpf_tail_call_direct(struct bpf_prog *bpf_prog,
struct bpf_jit_poke_descriptor *poke,
u8 **pprog, u8 *ip,
bool *callee_regs_used, u32 stack_depth,
struct jit_context *ctx)
{ … }
static void bpf_tail_call_direct_fixup(struct bpf_prog *prog)
{ … }
static void emit_mov_imm32(u8 **pprog, bool sign_propagate,
u32 dst_reg, const u32 imm32)
{ … }
static void emit_mov_imm64(u8 **pprog, u32 dst_reg,
const u32 imm32_hi, const u32 imm32_lo)
{ … }
static void emit_mov_reg(u8 **pprog, bool is64, u32 dst_reg, u32 src_reg)
{ … }
static void emit_movsx_reg(u8 **pprog, int num_bits, bool is64, u32 dst_reg,
u32 src_reg)
{ … }
static void emit_insn_suffix(u8 **pprog, u32 ptr_reg, u32 val_reg, int off)
{ … }
static void emit_insn_suffix_SIB(u8 **pprog, u32 ptr_reg, u32 val_reg, u32 index_reg, int off)
{ … }
static void maybe_emit_mod(u8 **pprog, u32 dst_reg, u32 src_reg, bool is64)
{ … }
static void maybe_emit_1mod(u8 **pprog, u32 reg, bool is64)
{ … }
static void emit_ldx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
{ … }
static void emit_ldsx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
{ … }
static void emit_ldx_index(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, u32 index_reg, int off)
{ … }
static void emit_ldx_r12(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
{ … }
static void emit_stx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
{ … }
static void emit_stx_index(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, u32 index_reg, int off)
{ … }
static void emit_stx_r12(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
{ … }
static void emit_st_index(u8 **pprog, u32 size, u32 dst_reg, u32 index_reg, int off, int imm)
{ … }
static void emit_st_r12(u8 **pprog, u32 size, u32 dst_reg, int off, int imm)
{ … }
static int emit_atomic(u8 **pprog, u8 atomic_op,
u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
{ … }
static int emit_atomic_index(u8 **pprog, u8 atomic_op, u32 size,
u32 dst_reg, u32 src_reg, u32 index_reg, int off)
{ … }
#define DONT_CLEAR …
bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs)
{ … }
static void detect_reg_usage(struct bpf_insn *insn, int insn_cnt,
bool *regs_used)
{ … }
static void emit_3vex(u8 **pprog, bool r, bool x, bool b, u8 m,
bool w, u8 src_reg2, bool l, u8 pp)
{ … }
static void emit_shiftx(u8 **pprog, u32 dst_reg, u8 src_reg, bool is64, u8 op)
{ … }
#define INSN_SZ_DIFF …
#define __LOAD_TCC_PTR(off) …
#define LOAD_TAIL_CALL_CNT_PTR(stack) …
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
int oldproglen, struct jit_context *ctx, bool jmp_padding)
{ … }
static void clean_stack_garbage(const struct btf_func_model *m,
u8 **pprog, int nr_stack_slots,
int stack_size)
{ … }
static int get_nr_used_regs(const struct btf_func_model *m)
{ … }
static void save_args(const struct btf_func_model *m, u8 **prog,
int stack_size, bool for_call_origin)
{ … }
static void restore_regs(const struct btf_func_model *m, u8 **prog,
int stack_size)
{ … }
static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
struct bpf_tramp_link *l, int stack_size,
int run_ctx_off, bool save_ret,
void *image, void *rw_image)
{ … }
static void emit_align(u8 **pprog, u32 align)
{ … }
static int emit_cond_near_jump(u8 **pprog, void *func, void *ip, u8 jmp_cond)
{ … }
static int invoke_bpf(const struct btf_func_model *m, u8 **pprog,
struct bpf_tramp_links *tl, int stack_size,
int run_ctx_off, bool save_ret,
void *image, void *rw_image)
{ … }
static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog,
struct bpf_tramp_links *tl, int stack_size,
int run_ctx_off, u8 **branches,
void *image, void *rw_image)
{ … }
#define LOAD_TRAMP_TAIL_CALL_CNT_PTR(stack) …
static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_image,
void *rw_image_end, void *image,
const struct btf_func_model *m, u32 flags,
struct bpf_tramp_links *tlinks,
void *func_addr)
{ … }
void *arch_alloc_bpf_trampoline(unsigned int size)
{ … }
void arch_free_bpf_trampoline(void *image, unsigned int size)
{ … }
int arch_protect_bpf_trampoline(void *image, unsigned int size)
{ … }
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,
const struct btf_func_model *m, u32 flags,
struct bpf_tramp_links *tlinks,
void *func_addr)
{ … }
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
struct bpf_tramp_links *tlinks, void *func_addr)
{ … }
static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs, u8 *image, u8 *buf)
{ … }
static int cmp_ips(const void *a, const void *b)
{ … }
int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_funcs)
{ … }
struct x64_jit_data { … };
#define MAX_PASSES …
#define PADDING_PASSES …
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
{ … }
bool bpf_jit_supports_kfunc_call(void)
{ … }
void *bpf_arch_text_copy(void *dst, void *src, size_t len)
{ … }
bool bpf_jit_supports_subprog_tailcalls(void)
{ … }
bool bpf_jit_supports_percpu_insn(void)
{ … }
void bpf_jit_free(struct bpf_prog *prog)
{ … }
bool bpf_jit_supports_exceptions(void)
{ … }
void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie)
{ … }
void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
struct bpf_prog *new, struct bpf_prog *old)
{ … }
bool bpf_jit_supports_arena(void)
{ … }
bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
{ … }
bool bpf_jit_supports_ptr_xchg(void)
{ … }
u64 bpf_arch_uaddress_limit(void)
{ … }