aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-09-09 13:27:22 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-09 13:27:22 -0400
commitafddacc3ccd048c49c7f4f0ad0b6a40730c74715 (patch)
treef990840a7b9e6afe48ea73a5fdafe1cdc50f936d
parent5b4c314575ea6edd57c547c2123083d88d8ff4e6 (diff)
parentdaedfb22451dd02b35c0549566cbb7cc06bdd53b (diff)
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>
-rw-r--r--Documentation/networking/filter.txt8
-rw-r--r--arch/x86/net/bpf_jit_comp.c17
-rw-r--r--include/linux/filter.h74
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/bpf.h65
-rw-r--r--kernel/bpf/core.c5
-rw-r--r--lib/test_bpf.c21
7 files changed, 135 insertions, 56 deletions
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt
index c48a9704bda8..81916ab5d96f 100644
--- a/Documentation/networking/filter.txt
+++ b/Documentation/networking/filter.txt
@@ -951,7 +951,7 @@ Size modifier is one of ...
951 951
952Mode modifier is one of: 952Mode modifier is one of:
953 953
954 BPF_IMM 0x00 /* classic BPF only, reserved in eBPF */ 954 BPF_IMM 0x00 /* used for 32-bit mov in classic BPF and 64-bit in eBPF */
955 BPF_ABS 0x20 955 BPF_ABS 0x20
956 BPF_IND 0x40 956 BPF_IND 0x40
957 BPF_MEM 0x60 957 BPF_MEM 0x60
@@ -995,6 +995,12 @@ BPF_XADD | BPF_DW | BPF_STX: lock xadd *(u64 *)(dst_reg + off16) += src_reg
995Where size is one of: BPF_B or BPF_H or BPF_W or BPF_DW. Note that 1 and 995Where size is one of: BPF_B or BPF_H or BPF_W or BPF_DW. Note that 1 and
9962 byte atomic increments are not supported. 9962 byte atomic increments are not supported.
997 997
998eBPF has one 16-byte instruction: BPF_LD | BPF_DW | BPF_IMM which consists
999of two consecutive 'struct bpf_insn' 8-byte blocks and interpreted as single
1000instruction that loads 64-bit immediate value into a dst_reg.
1001Classic BPF has similar instruction: BPF_LD | BPF_W | BPF_IMM which loads
100232-bit immediate value into a register.
1003
998Testing 1004Testing
999------- 1005-------
1000 1006
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 39ccfbb4a723..06f8c17f5484 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -393,6 +393,23 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
393 EMIT1_off32(add_1reg(0xB8, dst_reg), imm32); 393 EMIT1_off32(add_1reg(0xB8, dst_reg), imm32);
394 break; 394 break;
395 395
396 case BPF_LD | BPF_IMM | BPF_DW:
397 if (insn[1].code != 0 || insn[1].src_reg != 0 ||
398 insn[1].dst_reg != 0 || insn[1].off != 0) {
399 /* verifier must catch invalid insns */
400 pr_err("invalid BPF_LD_IMM64 insn\n");
401 return -EINVAL;
402 }
403
404 /* movabsq %rax, imm64 */
405 EMIT2(add_1mod(0x48, dst_reg), add_1reg(0xB8, dst_reg));
406 EMIT(insn[0].imm, 4);
407 EMIT(insn[1].imm, 4);
408
409 insn++;
410 i++;
411 break;
412
396 /* dst %= src, dst /= src, dst %= imm32, dst /= imm32 */ 413 /* dst %= src, dst /= src, dst %= imm32, dst /= imm32 */
397 case BPF_ALU | BPF_MOD | BPF_X: 414 case BPF_ALU | BPF_MOD | BPF_X:
398 case BPF_ALU | BPF_DIV | BPF_X: 415 case BPF_ALU | BPF_DIV | BPF_X:
diff --git a/include/linux/filter.h b/include/linux/filter.h
index c78994593355..8f82ef3f1cdd 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -10,58 +10,12 @@
10#include <linux/workqueue.h> 10#include <linux/workqueue.h>
11#include <uapi/linux/filter.h> 11#include <uapi/linux/filter.h>
12#include <asm/cacheflush.h> 12#include <asm/cacheflush.h>
13#include <uapi/linux/bpf.h>
13 14
14struct sk_buff; 15struct sk_buff;
15struct sock; 16struct sock;
16struct seccomp_data; 17struct seccomp_data;
17 18
18/* Internally used and optimized filter representation with extended
19 * instruction set based on top of classic BPF.
20 */
21
22/* instruction classes */
23#define BPF_ALU64 0x07 /* alu mode in double word width */
24
25/* ld/ldx fields */
26#define BPF_DW 0x18 /* double word */
27#define BPF_XADD 0xc0 /* exclusive add */
28
29/* alu/jmp fields */
30#define BPF_MOV 0xb0 /* mov reg to reg */
31#define BPF_ARSH 0xc0 /* sign extending arithmetic shift right */
32
33/* change endianness of a register */
34#define BPF_END 0xd0 /* flags for endianness conversion: */
35#define BPF_TO_LE 0x00 /* convert to little-endian */
36#define BPF_TO_BE 0x08 /* convert to big-endian */
37#define BPF_FROM_LE BPF_TO_LE
38#define BPF_FROM_BE BPF_TO_BE
39
40#define BPF_JNE 0x50 /* jump != */
41#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
42#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
43#define BPF_CALL 0x80 /* function call */
44#define BPF_EXIT 0x90 /* function return */
45
46/* Register numbers */
47enum {
48 BPF_REG_0 = 0,
49 BPF_REG_1,
50 BPF_REG_2,
51 BPF_REG_3,
52 BPF_REG_4,
53 BPF_REG_5,
54 BPF_REG_6,
55 BPF_REG_7,
56 BPF_REG_8,
57 BPF_REG_9,
58 BPF_REG_10,
59 __MAX_BPF_REG,
60};
61
62/* BPF has 10 general purpose 64-bit registers and stack frame. */
63#define MAX_BPF_REG __MAX_BPF_REG
64
65/* ArgX, context and stack frame pointer register positions. Note, 19/* ArgX, context and stack frame pointer register positions. Note,
66 * Arg1, Arg2, Arg3, etc are used as argument mappings of function 20 * Arg1, Arg2, Arg3, etc are used as argument mappings of function
67 * calls in BPF_CALL instruction. 21 * calls in BPF_CALL instruction.
@@ -166,6 +120,24 @@ enum {
166 .off = 0, \ 120 .off = 0, \
167 .imm = IMM }) 121 .imm = IMM })
168 122
123/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */
124#define BPF_LD_IMM64(DST, IMM) \
125 BPF_LD_IMM64_RAW(DST, 0, IMM)
126
127#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \
128 ((struct bpf_insn) { \
129 .code = BPF_LD | BPF_DW | BPF_IMM, \
130 .dst_reg = DST, \
131 .src_reg = SRC, \
132 .off = 0, \
133 .imm = (__u32) (IMM) }), \
134 ((struct bpf_insn) { \
135 .code = 0, /* zero is reserved opcode */ \
136 .dst_reg = 0, \
137 .src_reg = 0, \
138 .off = 0, \
139 .imm = ((__u64) (IMM)) >> 32 })
140
169/* Short form of mov based on type, BPF_X: dst_reg = src_reg, BPF_K: dst_reg = imm32 */ 141/* Short form of mov based on type, BPF_X: dst_reg = src_reg, BPF_K: dst_reg = imm32 */
170 142
171#define BPF_MOV64_RAW(TYPE, DST, SRC, IMM) \ 143#define BPF_MOV64_RAW(TYPE, DST, SRC, IMM) \
@@ -304,14 +276,6 @@ enum {
304#define SK_RUN_FILTER(filter, ctx) \ 276#define SK_RUN_FILTER(filter, ctx) \
305 (*filter->prog->bpf_func)(ctx, filter->prog->insnsi) 277 (*filter->prog->bpf_func)(ctx, filter->prog->insnsi)
306 278
307struct bpf_insn {
308 __u8 code; /* opcode */
309 __u8 dst_reg:4; /* dest register */
310 __u8 src_reg:4; /* source register */
311 __s16 off; /* signed offset */
312 __s32 imm; /* signed immediate constant */
313};
314
315#ifdef CONFIG_COMPAT 279#ifdef CONFIG_COMPAT
316/* A struct sock_filter is architecture independent. */ 280/* A struct sock_filter is architecture independent. */
317struct compat_sock_fprog { 281struct compat_sock_fprog {
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 24e9033f8b3f..fb3f7b675229 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -67,6 +67,7 @@ header-y += bfs_fs.h
67header-y += binfmts.h 67header-y += binfmts.h
68header-y += blkpg.h 68header-y += blkpg.h
69header-y += blktrace_api.h 69header-y += blktrace_api.h
70header-y += bpf.h
70header-y += bpqether.h 71header-y += bpqether.h
71header-y += bsg.h 72header-y += bsg.h
72header-y += btrfs.h 73header-y += btrfs.h
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
new file mode 100644
index 000000000000..479ed0b6be16
--- /dev/null
+++ b/include/uapi/linux/bpf.h
@@ -0,0 +1,65 @@
1/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#ifndef _UAPI__LINUX_BPF_H__
8#define _UAPI__LINUX_BPF_H__
9
10#include <linux/types.h>
11
12/* Extended instruction set based on top of classic BPF */
13
14/* instruction classes */
15#define BPF_ALU64 0x07 /* alu mode in double word width */
16
17/* ld/ldx fields */
18#define BPF_DW 0x18 /* double word */
19#define BPF_XADD 0xc0 /* exclusive add */
20
21/* alu/jmp fields */
22#define BPF_MOV 0xb0 /* mov reg to reg */
23#define BPF_ARSH 0xc0 /* sign extending arithmetic shift right */
24
25/* change endianness of a register */
26#define BPF_END 0xd0 /* flags for endianness conversion: */
27#define BPF_TO_LE 0x00 /* convert to little-endian */
28#define BPF_TO_BE 0x08 /* convert to big-endian */
29#define BPF_FROM_LE BPF_TO_LE
30#define BPF_FROM_BE BPF_TO_BE
31
32#define BPF_JNE 0x50 /* jump != */
33#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
34#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
35#define BPF_CALL 0x80 /* function call */
36#define BPF_EXIT 0x90 /* function return */
37
38/* Register numbers */
39enum {
40 BPF_REG_0 = 0,
41 BPF_REG_1,
42 BPF_REG_2,
43 BPF_REG_3,
44 BPF_REG_4,
45 BPF_REG_5,
46 BPF_REG_6,
47 BPF_REG_7,
48 BPF_REG_8,
49 BPF_REG_9,
50 BPF_REG_10,
51 __MAX_BPF_REG,
52};
53
54/* BPF has 10 general purpose 64-bit registers and stack frame. */
55#define MAX_BPF_REG __MAX_BPF_REG
56
57struct bpf_insn {
58 __u8 code; /* opcode */
59 __u8 dst_reg:4; /* dest register */
60 __u8 src_reg:4; /* source register */
61 __s16 off; /* signed offset */
62 __s32 imm; /* signed immediate constant */
63};
64
65#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index b54bb2c2e494..2c2bfaacce66 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -242,6 +242,7 @@ static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
242 [BPF_LD | BPF_IND | BPF_W] = &&LD_IND_W, 242 [BPF_LD | BPF_IND | BPF_W] = &&LD_IND_W,
243 [BPF_LD | BPF_IND | BPF_H] = &&LD_IND_H, 243 [BPF_LD | BPF_IND | BPF_H] = &&LD_IND_H,
244 [BPF_LD | BPF_IND | BPF_B] = &&LD_IND_B, 244 [BPF_LD | BPF_IND | BPF_B] = &&LD_IND_B,
245 [BPF_LD | BPF_IMM | BPF_DW] = &&LD_IMM_DW,
245 }; 246 };
246 void *ptr; 247 void *ptr;
247 int off; 248 int off;
@@ -301,6 +302,10 @@ select_insn:
301 ALU64_MOV_K: 302 ALU64_MOV_K:
302 DST = IMM; 303 DST = IMM;
303 CONT; 304 CONT;
305 LD_IMM_DW:
306 DST = (u64) (u32) insn[0].imm | ((u64) (u32) insn[1].imm) << 32;
307 insn++;
308 CONT;
304 ALU64_ARSH_X: 309 ALU64_ARSH_X:
305 (*(s64 *) &DST) >>= SRC; 310 (*(s64 *) &DST) >>= SRC;
306 CONT; 311 CONT;
diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 9a67456ba29a..413890815d3e 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -1735,6 +1735,27 @@ static struct bpf_test tests[] = {
1735 { }, 1735 { },
1736 { { 1, 0 } }, 1736 { { 1, 0 } },
1737 }, 1737 },
1738 {
1739 "load 64-bit immediate",
1740 .u.insns_int = {
1741 BPF_LD_IMM64(R1, 0x567800001234L),
1742 BPF_MOV64_REG(R2, R1),
1743 BPF_MOV64_REG(R3, R2),
1744 BPF_ALU64_IMM(BPF_RSH, R2, 32),
1745 BPF_ALU64_IMM(BPF_LSH, R3, 32),
1746 BPF_ALU64_IMM(BPF_RSH, R3, 32),
1747 BPF_ALU64_IMM(BPF_MOV, R0, 0),
1748 BPF_JMP_IMM(BPF_JEQ, R2, 0x5678, 1),
1749 BPF_EXIT_INSN(),
1750 BPF_JMP_IMM(BPF_JEQ, R3, 0x1234, 1),
1751 BPF_EXIT_INSN(),
1752 BPF_ALU64_IMM(BPF_MOV, R0, 1),
1753 BPF_EXIT_INSN(),
1754 },
1755 INTERNAL,
1756 { },
1757 { { 0, 1 } }
1758 },
1738}; 1759};
1739 1760
1740static struct net_device dev; 1761static struct net_device dev;