mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +00:00
Merge branch 'ebpf'
Alexei Starovoitov says: ==================== load imm64 insn and uapi/linux/bpf.h V9->V10 - no changes, added Daniel's ack Note they're on top of Hannes's patch in the same area [1] V8 thread with 'why' reasoning and end goal [2] Original set [3] of ~28 patches I'm planning to present in 4 stages: I. this 2 patches to fork off llvm upstreaming II. bpf syscall with manpage and map implementation III. bpf program load/unload with verifier testsuite (1st user of instruction macros from bpf.h and 1st user of load imm64 insn) IV. tracing, etc [1] http://patchwork.ozlabs.org/patch/385266/ [2] https://lkml.org/lkml/2014/8/27/628 [3] https://lkml.org/lkml/2014/8/26/859 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
afddacc3cc
@ -951,7 +951,7 @@ Size modifier is one of ...
|
||||
|
||||
Mode modifier is one of:
|
||||
|
||||
BPF_IMM 0x00 /* classic BPF only, reserved in eBPF */
|
||||
BPF_IMM 0x00 /* used for 32-bit mov in classic BPF and 64-bit in eBPF */
|
||||
BPF_ABS 0x20
|
||||
BPF_IND 0x40
|
||||
BPF_MEM 0x60
|
||||
@ -995,6 +995,12 @@ BPF_XADD | BPF_DW | BPF_STX: lock xadd *(u64 *)(dst_reg + off16) += src_reg
|
||||
Where size is one of: BPF_B or BPF_H or BPF_W or BPF_DW. Note that 1 and
|
||||
2 byte atomic increments are not supported.
|
||||
|
||||
eBPF has one 16-byte instruction: BPF_LD | BPF_DW | BPF_IMM which consists
|
||||
of two consecutive 'struct bpf_insn' 8-byte blocks and interpreted as single
|
||||
instruction that loads 64-bit immediate value into a dst_reg.
|
||||
Classic BPF has similar instruction: BPF_LD | BPF_W | BPF_IMM which loads
|
||||
32-bit immediate value into a register.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
|
@ -393,6 +393,23 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
||||
EMIT1_off32(add_1reg(0xB8, dst_reg), imm32);
|
||||
break;
|
||||
|
||||
case BPF_LD | BPF_IMM | BPF_DW:
|
||||
if (insn[1].code != 0 || insn[1].src_reg != 0 ||
|
||||
insn[1].dst_reg != 0 || insn[1].off != 0) {
|
||||
/* verifier must catch invalid insns */
|
||||
pr_err("invalid BPF_LD_IMM64 insn\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* movabsq %rax, imm64 */
|
||||
EMIT2(add_1mod(0x48, dst_reg), add_1reg(0xB8, dst_reg));
|
||||
EMIT(insn[0].imm, 4);
|
||||
EMIT(insn[1].imm, 4);
|
||||
|
||||
insn++;
|
||||
i++;
|
||||
break;
|
||||
|
||||
/* dst %= src, dst /= src, dst %= imm32, dst /= imm32 */
|
||||
case BPF_ALU | BPF_MOD | BPF_X:
|
||||
case BPF_ALU | BPF_DIV | BPF_X:
|
||||
|
@ -10,58 +10,12 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <uapi/linux/filter.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
|
||||
struct sk_buff;
|
||||
struct sock;
|
||||
struct seccomp_data;
|
||||
|
||||
/* Internally used and optimized filter representation with extended
|
||||
* instruction set based on top of classic BPF.
|
||||
*/
|
||||
|
||||
/* instruction classes */
|
||||
#define BPF_ALU64 0x07 /* alu mode in double word width */
|
||||
|
||||
/* ld/ldx fields */
|
||||
#define BPF_DW 0x18 /* double word */
|
||||
#define BPF_XADD 0xc0 /* exclusive add */
|
||||
|
||||
/* alu/jmp fields */
|
||||
#define BPF_MOV 0xb0 /* mov reg to reg */
|
||||
#define BPF_ARSH 0xc0 /* sign extending arithmetic shift right */
|
||||
|
||||
/* change endianness of a register */
|
||||
#define BPF_END 0xd0 /* flags for endianness conversion: */
|
||||
#define BPF_TO_LE 0x00 /* convert to little-endian */
|
||||
#define BPF_TO_BE 0x08 /* convert to big-endian */
|
||||
#define BPF_FROM_LE BPF_TO_LE
|
||||
#define BPF_FROM_BE BPF_TO_BE
|
||||
|
||||
#define BPF_JNE 0x50 /* jump != */
|
||||
#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
|
||||
#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
|
||||
#define BPF_CALL 0x80 /* function call */
|
||||
#define BPF_EXIT 0x90 /* function return */
|
||||
|
||||
/* Register numbers */
|
||||
enum {
|
||||
BPF_REG_0 = 0,
|
||||
BPF_REG_1,
|
||||
BPF_REG_2,
|
||||
BPF_REG_3,
|
||||
BPF_REG_4,
|
||||
BPF_REG_5,
|
||||
BPF_REG_6,
|
||||
BPF_REG_7,
|
||||
BPF_REG_8,
|
||||
BPF_REG_9,
|
||||
BPF_REG_10,
|
||||
__MAX_BPF_REG,
|
||||
};
|
||||
|
||||
/* BPF has 10 general purpose 64-bit registers and stack frame. */
|
||||
#define MAX_BPF_REG __MAX_BPF_REG
|
||||
|
||||
/* ArgX, context and stack frame pointer register positions. Note,
|
||||
* Arg1, Arg2, Arg3, etc are used as argument mappings of function
|
||||
* calls in BPF_CALL instruction.
|
||||
@ -166,6 +120,24 @@ enum {
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */
|
||||
#define BPF_LD_IMM64(DST, IMM) \
|
||||
BPF_LD_IMM64_RAW(DST, 0, IMM)
|
||||
|
||||
#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_LD | BPF_DW | BPF_IMM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = 0, \
|
||||
.imm = (__u32) (IMM) }), \
|
||||
((struct bpf_insn) { \
|
||||
.code = 0, /* zero is reserved opcode */ \
|
||||
.dst_reg = 0, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = ((__u64) (IMM)) >> 32 })
|
||||
|
||||
/* Short form of mov based on type, BPF_X: dst_reg = src_reg, BPF_K: dst_reg = imm32 */
|
||||
|
||||
#define BPF_MOV64_RAW(TYPE, DST, SRC, IMM) \
|
||||
@ -304,14 +276,6 @@ enum {
|
||||
#define SK_RUN_FILTER(filter, ctx) \
|
||||
(*filter->prog->bpf_func)(ctx, filter->prog->insnsi)
|
||||
|
||||
struct bpf_insn {
|
||||
__u8 code; /* opcode */
|
||||
__u8 dst_reg:4; /* dest register */
|
||||
__u8 src_reg:4; /* source register */
|
||||
__s16 off; /* signed offset */
|
||||
__s32 imm; /* signed immediate constant */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
/* A struct sock_filter is architecture independent. */
|
||||
struct compat_sock_fprog {
|
||||
|
@ -67,6 +67,7 @@ header-y += bfs_fs.h
|
||||
header-y += binfmts.h
|
||||
header-y += blkpg.h
|
||||
header-y += blktrace_api.h
|
||||
header-y += bpf.h
|
||||
header-y += bpqether.h
|
||||
header-y += bsg.h
|
||||
header-y += btrfs.h
|
||||
|
65
include/uapi/linux/bpf.h
Normal file
65
include/uapi/linux/bpf.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef _UAPI__LINUX_BPF_H__
|
||||
#define _UAPI__LINUX_BPF_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Extended instruction set based on top of classic BPF */
|
||||
|
||||
/* instruction classes */
|
||||
#define BPF_ALU64 0x07 /* alu mode in double word width */
|
||||
|
||||
/* ld/ldx fields */
|
||||
#define BPF_DW 0x18 /* double word */
|
||||
#define BPF_XADD 0xc0 /* exclusive add */
|
||||
|
||||
/* alu/jmp fields */
|
||||
#define BPF_MOV 0xb0 /* mov reg to reg */
|
||||
#define BPF_ARSH 0xc0 /* sign extending arithmetic shift right */
|
||||
|
||||
/* change endianness of a register */
|
||||
#define BPF_END 0xd0 /* flags for endianness conversion: */
|
||||
#define BPF_TO_LE 0x00 /* convert to little-endian */
|
||||
#define BPF_TO_BE 0x08 /* convert to big-endian */
|
||||
#define BPF_FROM_LE BPF_TO_LE
|
||||
#define BPF_FROM_BE BPF_TO_BE
|
||||
|
||||
#define BPF_JNE 0x50 /* jump != */
|
||||
#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
|
||||
#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
|
||||
#define BPF_CALL 0x80 /* function call */
|
||||
#define BPF_EXIT 0x90 /* function return */
|
||||
|
||||
/* Register numbers */
|
||||
enum {
|
||||
BPF_REG_0 = 0,
|
||||
BPF_REG_1,
|
||||
BPF_REG_2,
|
||||
BPF_REG_3,
|
||||
BPF_REG_4,
|
||||
BPF_REG_5,
|
||||
BPF_REG_6,
|
||||
BPF_REG_7,
|
||||
BPF_REG_8,
|
||||
BPF_REG_9,
|
||||
BPF_REG_10,
|
||||
__MAX_BPF_REG,
|
||||
};
|
||||
|
||||
/* BPF has 10 general purpose 64-bit registers and stack frame. */
|
||||
#define MAX_BPF_REG __MAX_BPF_REG
|
||||
|
||||
struct bpf_insn {
|
||||
__u8 code; /* opcode */
|
||||
__u8 dst_reg:4; /* dest register */
|
||||
__u8 src_reg:4; /* source register */
|
||||
__s16 off; /* signed offset */
|
||||
__s32 imm; /* signed immediate constant */
|
||||
};
|
||||
|
||||
#endif /* _UAPI__LINUX_BPF_H__ */
|
@ -242,6 +242,7 @@ static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
|
||||
[BPF_LD | BPF_IND | BPF_W] = &&LD_IND_W,
|
||||
[BPF_LD | BPF_IND | BPF_H] = &&LD_IND_H,
|
||||
[BPF_LD | BPF_IND | BPF_B] = &&LD_IND_B,
|
||||
[BPF_LD | BPF_IMM | BPF_DW] = &&LD_IMM_DW,
|
||||
};
|
||||
void *ptr;
|
||||
int off;
|
||||
@ -301,6 +302,10 @@ select_insn:
|
||||
ALU64_MOV_K:
|
||||
DST = IMM;
|
||||
CONT;
|
||||
LD_IMM_DW:
|
||||
DST = (u64) (u32) insn[0].imm | ((u64) (u32) insn[1].imm) << 32;
|
||||
insn++;
|
||||
CONT;
|
||||
ALU64_ARSH_X:
|
||||
(*(s64 *) &DST) >>= SRC;
|
||||
CONT;
|
||||
|
@ -1735,6 +1735,27 @@ static struct bpf_test tests[] = {
|
||||
{ },
|
||||
{ { 1, 0 } },
|
||||
},
|
||||
{
|
||||
"load 64-bit immediate",
|
||||
.u.insns_int = {
|
||||
BPF_LD_IMM64(R1, 0x567800001234L),
|
||||
BPF_MOV64_REG(R2, R1),
|
||||
BPF_MOV64_REG(R3, R2),
|
||||
BPF_ALU64_IMM(BPF_RSH, R2, 32),
|
||||
BPF_ALU64_IMM(BPF_LSH, R3, 32),
|
||||
BPF_ALU64_IMM(BPF_RSH, R3, 32),
|
||||
BPF_ALU64_IMM(BPF_MOV, R0, 0),
|
||||
BPF_JMP_IMM(BPF_JEQ, R2, 0x5678, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
BPF_JMP_IMM(BPF_JEQ, R3, 0x1234, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
BPF_ALU64_IMM(BPF_MOV, R0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
INTERNAL,
|
||||
{ },
|
||||
{ { 0, 1 } }
|
||||
},
|
||||
};
|
||||
|
||||
static struct net_device dev;
|
||||
|
Loading…
Reference in New Issue
Block a user