bpf: use different interpreter depending on required stack size
authorAlexei Starovoitov <ast@fb.com>
Tue, 30 May 2017 20:31:33 +0000 (13:31 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 31 May 2017 23:29:48 +0000 (19:29 -0400)
16 __bpf_prog_run() interpreters for various stack sizes add .text
but not a lot comparing to run-time stack savings

   text    data     bss     dec     hex filename
  26350   10328     624   37302    91b6 kernel/bpf/core.o.before_split
  25777   10328     624   36729    8f79 kernel/bpf/core.o.after_split
  26970   10328     624   37922    9422 kernel/bpf/core.o.now

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
kernel/bpf/core.c

index abd410d394bc2b0d82e16863a015627a2a022b56..774069ca18a739f95d9f4ca67bce0a56261e5d3d 100644 (file)
@@ -1218,16 +1218,38 @@ load_byte:
 }
 STACK_FRAME_NON_STANDARD(___bpf_prog_run); /* jump table */
 
-static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
-{
-       u64 stack[MAX_BPF_STACK / sizeof(u64)];
-       u64 regs[MAX_BPF_REG];
-
-       FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)];
-       ARG1 = (u64) (unsigned long) ctx;
-       return ___bpf_prog_run(regs, insn, stack);
+#define PROG_NAME(stack_size) __bpf_prog_run##stack_size
+#define DEFINE_BPF_PROG_RUN(stack_size) \
+static unsigned int PROG_NAME(stack_size)(const void *ctx, const struct bpf_insn *insn) \
+{ \
+       u64 stack[stack_size / sizeof(u64)]; \
+       u64 regs[MAX_BPF_REG]; \
+\
+       FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \
+       ARG1 = (u64) (unsigned long) ctx; \
+       return ___bpf_prog_run(regs, insn, stack); \
 }
 
+#define EVAL1(FN, X) FN(X)
+#define EVAL2(FN, X, Y...) FN(X) EVAL1(FN, Y)
+#define EVAL3(FN, X, Y...) FN(X) EVAL2(FN, Y)
+#define EVAL4(FN, X, Y...) FN(X) EVAL3(FN, Y)
+#define EVAL5(FN, X, Y...) FN(X) EVAL4(FN, Y)
+#define EVAL6(FN, X, Y...) FN(X) EVAL5(FN, Y)
+
+EVAL6(DEFINE_BPF_PROG_RUN, 32, 64, 96, 128, 160, 192);
+EVAL6(DEFINE_BPF_PROG_RUN, 224, 256, 288, 320, 352, 384);
+EVAL4(DEFINE_BPF_PROG_RUN, 416, 448, 480, 512);
+
+#define PROG_NAME_LIST(stack_size) PROG_NAME(stack_size),
+
+static unsigned int (*interpreters[])(const void *ctx,
+                                     const struct bpf_insn *insn) = {
+EVAL6(PROG_NAME_LIST, 32, 64, 96, 128, 160, 192)
+EVAL6(PROG_NAME_LIST, 224, 256, 288, 320, 352, 384)
+EVAL4(PROG_NAME_LIST, 416, 448, 480, 512)
+};
+
 bool bpf_prog_array_compatible(struct bpf_array *array,
                               const struct bpf_prog *fp)
 {
@@ -1275,7 +1297,7 @@ static int bpf_check_tail_call(const struct bpf_prog *fp)
  */
 struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
 {
-       fp->bpf_func = (void *) __bpf_prog_run;
+       fp->bpf_func = interpreters[round_down(fp->aux->stack_depth, 32) / 32];
 
        /* eBPF JITs can rewrite the program in case constant
         * blinding is active. However, in case of error during