Module Name: src Committed By: alnsn Date: Tue Jul 1 16:18:55 UTC 2014
Modified Files: src/sys/net: bpfjit.c Log Message: Move the main loop in bpfjit_generate_code() to a new function and make few small changes. To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 src/sys/net/bpfjit.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/bpfjit.c diff -u src/sys/net/bpfjit.c:1.18 src/sys/net/bpfjit.c:1.19 --- src/sys/net/bpfjit.c:1.18 Wed Jun 25 13:53:40 2014 +++ src/sys/net/bpfjit.c Tue Jul 1 16:18:55 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: bpfjit.c,v 1.18 2014/06/25 13:53:40 alnsn Exp $ */ +/* $NetBSD: bpfjit.c,v 1.19 2014/07/01 16:18:55 alnsn Exp $ */ /*- * Copyright (c) 2011-2014 Alexander Nasonov. @@ -31,9 +31,9 @@ #include <sys/cdefs.h> #ifdef _KERNEL -__KERNEL_RCSID(0, "$NetBSD: bpfjit.c,v 1.18 2014/06/25 13:53:40 alnsn Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bpfjit.c,v 1.19 2014/07/01 16:18:55 alnsn Exp $"); #else -__RCSID("$NetBSD: bpfjit.c,v 1.18 2014/06/25 13:53:40 alnsn Exp $"); +__RCSID("$NetBSD: bpfjit.c,v 1.19 2014/07/01 16:18:55 alnsn Exp $"); #endif #include <sys/types.h> @@ -114,6 +114,12 @@ __RCSID("$NetBSD: bpfjit.c,v 1.18 2014/0 #define BJ_INIT_XBIT BJ_INIT_MBIT(MAX_MEMWORDS + 1) /* + * Get a number of memwords and external memwords from a bpf_ctx object. + */ +#define GET_EXTWORDS(bc) ((bc) ? (bc)->extwords : 0) +#define GET_MEMWORDS(bc) (GET_EXTWORDS(bc) ? GET_EXTWORDS(bc) : BPF_MEMWORDS) + +/* * Datatype for Array Bounds Check Elimination (ABC) pass. */ typedef uint64_t bpfjit_abc_length_t; @@ -307,7 +313,7 @@ append_jump(struct sljit_jump *jump, str * Generate code for BPF_LD+BPF_B+BPF_ABS A <- P[k:1]. */ static int -emit_read8(struct sljit_compiler* compiler, uint32_t k) +emit_read8(struct sljit_compiler *compiler, uint32_t k) { return sljit_emit_op1(compiler, @@ -320,7 +326,7 @@ emit_read8(struct sljit_compiler* compil * Generate code for BPF_LD+BPF_H+BPF_ABS A <- P[k:2]. */ static int -emit_read16(struct sljit_compiler* compiler, uint32_t k) +emit_read16(struct sljit_compiler *compiler, uint32_t k) { int status; @@ -362,7 +368,7 @@ emit_read16(struct sljit_compiler* compi * Generate code for BPF_LD+BPF_W+BPF_ABS A <- P[k:4]. */ static int -emit_read32(struct sljit_compiler* compiler, uint32_t k) +emit_read32(struct sljit_compiler *compiler, uint32_t k) { int status; @@ -471,7 +477,7 @@ emit_read32(struct sljit_compiler* compi * code for BPF_MSH instruction. */ static int -emit_xcall(struct sljit_compiler* compiler, const struct bpf_insn *pc, +emit_xcall(struct sljit_compiler *compiler, const struct bpf_insn *pc, int dst, sljit_sw dstw, struct sljit_jump **ret0_jump, uint32_t (*fn)(const struct mbuf *, uint32_t, int *)) { @@ -578,7 +584,7 @@ emit_xcall(struct sljit_compiler* compil * Emit code for BPF_COP and BPF_COPX instructions. */ static int -emit_cop(struct sljit_compiler* compiler, const bpf_ctx_t *bc, +emit_cop(struct sljit_compiler *compiler, const bpf_ctx_t *bc, const struct bpf_insn *pc, struct sljit_jump **ret0_jump) { #if BJ_XREG == SLJIT_RETURN_REG || \ @@ -698,7 +704,7 @@ emit_cop(struct sljit_compiler* compiler * BPF_LD+BPF_B+BPF_IND A <- P[X+k:1] */ static int -emit_pkt_read(struct sljit_compiler* compiler, +emit_pkt_read(struct sljit_compiler *compiler, const struct bpf_insn *pc, struct sljit_jump *to_mchain_jump, struct sljit_jump ***ret0, size_t *ret0_size, size_t *ret0_maxsize) { @@ -832,7 +838,7 @@ emit_pkt_read(struct sljit_compiler* com } static int -emit_memload(struct sljit_compiler* compiler, +emit_memload(struct sljit_compiler *compiler, sljit_si dst, uint32_t k, size_t extwords) { int status; @@ -860,7 +866,7 @@ emit_memload(struct sljit_compiler* comp } static int -emit_memstore(struct sljit_compiler* compiler, +emit_memstore(struct sljit_compiler *compiler, sljit_si src, uint32_t k, size_t extwords) { int status; @@ -891,7 +897,7 @@ emit_memstore(struct sljit_compiler* com * Generate code for BPF_LDX+BPF_B+BPF_MSH X <- 4*(P[k:1]&0xf). */ static int -emit_msh(struct sljit_compiler* compiler, +emit_msh(struct sljit_compiler *compiler, const struct bpf_insn *pc, struct sljit_jump *to_mchain_jump, struct sljit_jump ***ret0, size_t *ret0_size, size_t *ret0_maxsize) { @@ -999,7 +1005,7 @@ emit_msh(struct sljit_compiler* compiler } static int -emit_pow2_division(struct sljit_compiler* compiler, uint32_t k) +emit_pow2_division(struct sljit_compiler *compiler, uint32_t k) { int shift = 0; int status = SLJIT_SUCCESS; @@ -1036,7 +1042,7 @@ divide(sljit_uw x, sljit_uw y) * divt,divw are either SLJIT_IMM,pc->k or BJ_XREG,0. */ static int -emit_division(struct sljit_compiler* compiler, int divt, sljit_sw divw) +emit_division(struct sljit_compiler *compiler, int divt, sljit_sw divw) { int status; @@ -1155,8 +1161,8 @@ optimize_init(struct bpfjit_insn_data *i * for any valid kernel filter program. */ static bool -optimize_pass1(const struct bpf_insn *insns, - struct bpfjit_insn_data *insn_dat, size_t insn_count, size_t extwords, +optimize_pass1(const bpf_ctx_t *bc, const struct bpf_insn *insns, + struct bpfjit_insn_data *insn_dat, size_t insn_count, bpf_memword_init_t *initmask, int *nscratches, int *ncopfuncs) { struct bpfjit_jump *jtf; @@ -1166,7 +1172,7 @@ optimize_pass1(const struct bpf_insn *in bpf_memword_init_t invalid; /* borrowed from bpf_filter() */ bool unreachable; - const size_t memwords = (extwords != 0) ? extwords : BPF_MEMWORDS; + const size_t memwords = GET_MEMWORDS(bc); *ncopfuncs = 0; *nscratches = 2; @@ -1364,8 +1370,8 @@ optimize_pass1(const struct bpf_insn *in * Array Bounds Check Elimination (ABC) pass. */ static void -optimize_pass2(const struct bpf_insn *insns, - struct bpfjit_insn_data *insn_dat, size_t insn_count, size_t extwords) +optimize_pass2(const bpf_ctx_t *bc, const struct bpf_insn *insns, + struct bpfjit_insn_data *insn_dat, size_t insn_count) { struct bpfjit_jump *jmp; const struct bpf_insn *pc; @@ -1373,6 +1379,8 @@ optimize_pass2(const struct bpf_insn *in size_t i; bpfjit_abc_length_t length, abc_length = 0; + const size_t extwords = GET_EXTWORDS(bc); + for (i = insn_count; i != 0; i--) { pc = &insns[i-1]; pd = &insn_dat[i-1]; @@ -1473,20 +1481,19 @@ optimize_pass3(const struct bpf_insn *in } static bool -optimize(const struct bpf_insn *insns, +optimize(const bpf_ctx_t *bc, const struct bpf_insn *insns, struct bpfjit_insn_data *insn_dat, size_t insn_count, - size_t extwords, bpf_memword_init_t *initmask, int *nscratches, int *ncopfuncs) { optimize_init(insn_dat, insn_count); - if (!optimize_pass1(insns, insn_dat, insn_count, - extwords, initmask, nscratches, ncopfuncs)) { + if (!optimize_pass1(bc, insns, insn_dat, insn_count, + initmask, nscratches, ncopfuncs)) { return false; } - optimize_pass2(insns, insn_dat, insn_count, extwords); + optimize_pass2(bc, insns, insn_dat, insn_count); optimize_pass3(insns, insn_dat, insn_count); return true; @@ -1578,66 +1585,35 @@ kx_to_reg_arg(const struct bpf_insn *pc) } } -bpfjit_func_t -bpfjit_generate_code(const bpf_ctx_t *bc, - const struct bpf_insn *insns, size_t insn_count) +static bool +generate_insn_code(struct sljit_compiler *compiler, const bpf_ctx_t *bc, + const struct bpf_insn *insns, struct bpfjit_insn_data *insn_dat, + size_t insn_count) { - void *rv; - struct sljit_compiler *compiler; - - size_t i; - int status; - int branching, negate; - unsigned int rval, mode, src; - - /* optimization related */ - bpf_memword_init_t initmask; - int nscratches, ncopfuncs; - - /* memory store location for initial zero initialization */ - sljit_si mem_reg; - sljit_sw mem_off; - /* a list of jumps to out-of-bound return from a generated function */ struct sljit_jump **ret0; size_t ret0_size, ret0_maxsize; - const struct bpf_insn *pc; - struct bpfjit_insn_data *insn_dat; - - /* for local use */ - struct sljit_label *label; struct sljit_jump *jump; + struct sljit_label *label; + const struct bpf_insn *pc; struct bpfjit_jump *bjump, *jtf; - struct sljit_jump *to_mchain_jump; - bool unconditional_ret; + size_t i; + int status; + int branching, negate; + unsigned int rval, mode, src; uint32_t jt, jf; - const size_t extwords = bc ? bc->extwords : 0; - const size_t memwords = extwords ? extwords : BPF_MEMWORDS; - const bpf_memword_init_t preinited = extwords ? bc->preinited : 0; - - rv = NULL; - ret0 = NULL; - compiler = NULL; - insn_dat = NULL; - - if (memwords > MAX_MEMWORDS) - goto fail; - - if (insn_count == 0 || insn_count > SIZE_MAX / sizeof(insn_dat[0])) - goto fail; + bool unconditional_ret; + bool rv; - insn_dat = BJ_ALLOC(insn_count * sizeof(insn_dat[0])); - if (insn_dat == NULL) - goto fail; + const size_t extwords = GET_EXTWORDS(bc); + const size_t memwords = GET_MEMWORDS(bc); - if (!optimize(insns, insn_dat, insn_count, - extwords, &initmask, &nscratches, &ncopfuncs)) { - goto fail; - } + ret0 = NULL; + rv = false; ret0_size = 0; ret0_maxsize = 64; @@ -1645,101 +1621,6 @@ bpfjit_generate_code(const bpf_ctx_t *bc if (ret0 == NULL) goto fail; - compiler = sljit_create_compiler(); - if (compiler == NULL) - goto fail; - -#if !defined(_KERNEL) && defined(SLJIT_VERBOSE) && SLJIT_VERBOSE - sljit_compiler_verbose(compiler, stderr); -#endif - - status = sljit_emit_enter(compiler, - 2, nscratches, 3, sizeof(struct bpfjit_stack)); - if (status != SLJIT_SUCCESS) - goto fail; - - if (ncopfuncs > 0) { - /* save ctx argument */ - status = sljit_emit_op1(compiler, - SLJIT_MOV_P, - SLJIT_MEM1(SLJIT_LOCALS_REG), - offsetof(struct bpfjit_stack, ctx), - BJ_CTX_ARG, 0); - if (status != SLJIT_SUCCESS) - goto fail; - } - - if (extwords == 0) { - mem_reg = SLJIT_MEM1(SLJIT_LOCALS_REG); - mem_off = offsetof(struct bpfjit_stack, mem); - } else { - /* copy "mem" argument from bpf_args to bpfjit_stack */ - status = sljit_emit_op1(compiler, - SLJIT_MOV_P, - BJ_TMP1REG, 0, - SLJIT_MEM1(BJ_ARGS), offsetof(struct bpf_args, mem)); - if (status != SLJIT_SUCCESS) - goto fail; - - status = sljit_emit_op1(compiler, - SLJIT_MOV_P, - SLJIT_MEM1(SLJIT_LOCALS_REG), - offsetof(struct bpfjit_stack, extmem), - BJ_TMP1REG, 0); - if (status != SLJIT_SUCCESS) - goto fail; - - mem_reg = SLJIT_MEM1(BJ_TMP1REG); - mem_off = 0; - } - - /* - * Exclude pre-initialised external memory words but keep - * initialization statuses of A and X registers in case - * bc->preinited wrongly sets those two bits. - */ - initmask &= ~preinited | BJ_INIT_ABIT | BJ_INIT_XBIT; - -#if defined(_KERNEL) - /* bpf_filter() checks initialization of memwords. */ - BJ_ASSERT((initmask & (BJ_INIT_MBIT(memwords) - 1)) == 0); -#endif - for (i = 0; i < memwords; i++) { - if (initmask & BJ_INIT_MBIT(i)) { - /* M[i] = 0; */ - status = sljit_emit_op1(compiler, - SLJIT_MOV_UI, - mem_reg, mem_off + i * sizeof(uint32_t), - SLJIT_IMM, 0); - if (status != SLJIT_SUCCESS) - goto fail; - } - } - - if (initmask & BJ_INIT_ABIT) { - /* A = 0; */ - status = sljit_emit_op1(compiler, - SLJIT_MOV, - BJ_AREG, 0, - SLJIT_IMM, 0); - if (status != SLJIT_SUCCESS) - goto fail; - } - - if (initmask & BJ_INIT_XBIT) { - /* X = 0; */ - status = sljit_emit_op1(compiler, - SLJIT_MOV, - BJ_XREG, 0, - SLJIT_IMM, 0); - if (status != SLJIT_SUCCESS) - goto fail; - } - - status = load_buf_buflen(compiler); - if (status != SLJIT_SUCCESS) - goto fail; - for (i = 0; i < insn_count; i++) { if (insn_dat[i].unreachable) continue; @@ -2135,6 +2016,156 @@ bpfjit_generate_code(const bpf_ctx_t *bc sljit_set_label(ret0[i], label); } + rv = true; + +fail: + if (ret0 != NULL) + BJ_FREE(ret0, ret0_maxsize * sizeof(ret0[0])); + + return rv; +} + +bpfjit_func_t +bpfjit_generate_code(const bpf_ctx_t *bc, + const struct bpf_insn *insns, size_t insn_count) +{ + void *rv; + struct sljit_compiler *compiler; + + size_t i; + int status; + + /* optimization related */ + bpf_memword_init_t initmask; + int nscratches, ncopfuncs; + + /* memory store location for initial zero initialization */ + sljit_si mem_reg; + sljit_sw mem_off; + + struct bpfjit_insn_data *insn_dat; + + const size_t extwords = GET_EXTWORDS(bc); + const size_t memwords = GET_MEMWORDS(bc); + const bpf_memword_init_t preinited = extwords ? bc->preinited : 0; + + rv = NULL; + compiler = NULL; + insn_dat = NULL; + + if (memwords > MAX_MEMWORDS) + goto fail; + + if (insn_count == 0 || insn_count > SIZE_MAX / sizeof(insn_dat[0])) + goto fail; + + insn_dat = BJ_ALLOC(insn_count * sizeof(insn_dat[0])); + if (insn_dat == NULL) + goto fail; + + if (!optimize(bc, insns, insn_dat, insn_count, + &initmask, &nscratches, &ncopfuncs)) { + goto fail; + } + + compiler = sljit_create_compiler(); + if (compiler == NULL) + goto fail; + +#if !defined(_KERNEL) && defined(SLJIT_VERBOSE) && SLJIT_VERBOSE + sljit_compiler_verbose(compiler, stderr); +#endif + + status = sljit_emit_enter(compiler, + 2, nscratches, 3, sizeof(struct bpfjit_stack)); + if (status != SLJIT_SUCCESS) + goto fail; + + if (ncopfuncs > 0) { + /* save ctx argument */ + status = sljit_emit_op1(compiler, + SLJIT_MOV_P, + SLJIT_MEM1(SLJIT_LOCALS_REG), + offsetof(struct bpfjit_stack, ctx), + BJ_CTX_ARG, 0); + if (status != SLJIT_SUCCESS) + goto fail; + } + + if (extwords == 0) { + mem_reg = SLJIT_MEM1(SLJIT_LOCALS_REG); + mem_off = offsetof(struct bpfjit_stack, mem); + } else { + /* copy "mem" argument from bpf_args to bpfjit_stack */ + status = sljit_emit_op1(compiler, + SLJIT_MOV_P, + BJ_TMP1REG, 0, + SLJIT_MEM1(BJ_ARGS), offsetof(struct bpf_args, mem)); + if (status != SLJIT_SUCCESS) + goto fail; + + status = sljit_emit_op1(compiler, + SLJIT_MOV_P, + SLJIT_MEM1(SLJIT_LOCALS_REG), + offsetof(struct bpfjit_stack, extmem), + BJ_TMP1REG, 0); + if (status != SLJIT_SUCCESS) + goto fail; + + mem_reg = SLJIT_MEM1(BJ_TMP1REG); + mem_off = 0; + } + + /* + * Exclude pre-initialised external memory words but keep + * initialization statuses of A and X registers in case + * bc->preinited wrongly sets those two bits. + */ + initmask &= ~preinited | BJ_INIT_ABIT | BJ_INIT_XBIT; + +#if defined(_KERNEL) + /* bpf_filter() checks initialization of memwords. */ + BJ_ASSERT((initmask & (BJ_INIT_MBIT(memwords) - 1)) == 0); +#endif + for (i = 0; i < memwords; i++) { + if (initmask & BJ_INIT_MBIT(i)) { + /* M[i] = 0; */ + status = sljit_emit_op1(compiler, + SLJIT_MOV_UI, + mem_reg, mem_off + i * sizeof(uint32_t), + SLJIT_IMM, 0); + if (status != SLJIT_SUCCESS) + goto fail; + } + } + + if (initmask & BJ_INIT_ABIT) { + /* A = 0; */ + status = sljit_emit_op1(compiler, + SLJIT_MOV, + BJ_AREG, 0, + SLJIT_IMM, 0); + if (status != SLJIT_SUCCESS) + goto fail; + } + + if (initmask & BJ_INIT_XBIT) { + /* X = 0; */ + status = sljit_emit_op1(compiler, + SLJIT_MOV, + BJ_XREG, 0, + SLJIT_IMM, 0); + if (status != SLJIT_SUCCESS) + goto fail; + } + + status = load_buf_buflen(compiler); + if (status != SLJIT_SUCCESS) + goto fail; + + if (!generate_insn_code(compiler, bc, insns, insn_dat, insn_count)) + goto fail; + status = sljit_emit_return(compiler, SLJIT_MOV_UI, SLJIT_IMM, 0); @@ -2150,9 +2181,6 @@ fail: if (insn_dat != NULL) BJ_FREE(insn_dat, insn_count * sizeof(insn_dat[0])); - if (ret0 != NULL) - BJ_FREE(ret0, ret0_maxsize * sizeof(ret0[0])); - return (bpfjit_func_t)rv; }