• A
    net: filter: add "load 64-bit immediate" eBPF instruction · 02ab695b
    Alexei Starovoitov 提交于
    add BPF_LD_IMM64 instruction to load 64-bit immediate value into a register.
    All previous instructions were 8-byte. This is first 16-byte instruction.
    Two consecutive 'struct bpf_insn' blocks are interpreted as single instruction:
    insn[0].code = BPF_LD | BPF_DW | BPF_IMM
    insn[0].dst_reg = destination register
    insn[0].imm = lower 32-bit
    insn[1].code = 0
    insn[1].imm = upper 32-bit
    All unused fields must be zero.
    
    Classic BPF has similar instruction: BPF_LD | BPF_W | BPF_IMM
    which loads 32-bit immediate value into a register.
    
    x64 JITs it as single 'movabsq %rax, imm64'
    arm64 may JIT as sequence of four 'movk x0, #imm16, lsl #shift' insn
    
    Note that old eBPF programs are binary compatible with new interpreter.
    
    It helps eBPF programs load 64-bit constant into a register with one
    instruction instead of using two registers and 4 instructions:
    BPF_MOV32_IMM(R1, imm32)
    BPF_ALU64_IMM(BPF_LSH, R1, 32)
    BPF_MOV32_IMM(R2, imm32)
    BPF_ALU64_REG(BPF_OR, R1, R2)
    
    User space generated programs will use this instruction to load constants only.
    
    To tell kernel that user space needs a pointer the _pseudo_ variant of
    this instruction may be added later, which will use extra bits of encoding
    to indicate what type of pointer user space is asking kernel to provide.
    For example 'off' or 'src_reg' fields can be used for such purpose.
    src_reg = 1 could mean that user space is asking kernel to validate and
    load in-kernel map pointer.
    src_reg = 2 could mean that user space needs readonly data section pointer
    src_reg = 3 could mean that user space needs a pointer to per-cpu local data
    All such future pseudo instructions will not be carrying the actual pointer
    as part of the instruction, but rather will be treated as a request to kernel
    to provide one. The kernel will verify the request_for_a_pointer, then
    will drop _pseudo_ marking and will store actual internal pointer inside
    the instruction, so the end result is the interpreter and JITs never
    see pseudo BPF_LD_IMM64 insns and only operate on generic BPF_LD_IMM64 that
    loads 64-bit immediate into a register. User space never operates on direct
    pointers and verifier can easily recognize request_for_pointer vs other
    instructions.
    Signed-off-by: NAlexei Starovoitov <ast@plumgrid.com>
    Signed-off-by: NDavid S. Miller <davem@davemloft.net>
    02ab695b
filter.h 13.1 KB