Module Name:    src
Committed By:   alnsn
Date:           Sun Jul 13 21:54:46 UTC 2014

Modified Files:
        src/sys/net: bpfjit.c

Log Message:
Refactor BPF_COPX code. New version doesn't load buf and buflen after copx call.


To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 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.27 src/sys/net/bpfjit.c:1.28
--- src/sys/net/bpfjit.c:1.27	Sun Jul 13 18:48:27 2014
+++ src/sys/net/bpfjit.c	Sun Jul 13 21:54:46 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: bpfjit.c,v 1.27 2014/07/13 18:48:27 alnsn Exp $	*/
+/*	$NetBSD: bpfjit.c,v 1.28 2014/07/13 21:54:46 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.27 2014/07/13 18:48:27 alnsn Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bpfjit.c,v 1.28 2014/07/13 21:54:46 alnsn Exp $");
 #else
-__RCSID("$NetBSD: bpfjit.c,v 1.27 2014/07/13 18:48:27 alnsn Exp $");
+__RCSID("$NetBSD: bpfjit.c,v 1.28 2014/07/13 21:54:46 alnsn Exp $");
 #endif
 
 #include <sys/types.h>
@@ -95,13 +95,6 @@ __RCSID("$NetBSD: bpfjit.c,v 1.27 2014/0
 #define BJ_XREG		SLJIT_TEMPORARY_EREG1
 #define BJ_TMP3REG	SLJIT_TEMPORARY_EREG2
 
-/*
- * EREG registers can't be used for indirect calls, reuse BJ_BUF and
- * BJ_BUFLEN registers. They can be easily restored from BJ_ARGS.
- */
-#define BJ_COPF_PTR	SLJIT_SAVED_REG1
-#define BJ_COPF_IDX	SLJIT_SAVED_REG3
-
 #ifdef _KERNEL
 #define MAX_MEMWORDS BPF_MAX_MEMWORDS
 #else
@@ -123,11 +116,12 @@ __RCSID("$NetBSD: bpfjit.c,v 1.27 2014/0
  * Optimization hints.
  */
 typedef unsigned int bpfjit_hint_t;
-#define BJ_HINT_ABS  0x01 /* packet read at absolute offset  */
-#define BJ_HINT_IND  0x02 /* packet read at variable offset  */
-#define BJ_HINT_COP  0x04 /* BPF_COP or BPF_COPX instruction */
-#define BJ_HINT_XREG 0x08 /* BJ_XREG is needed   */
-#define BJ_HINT_LDX  0x10 /* BPF_LDX instruction */
+#define BJ_HINT_ABS  0x01 /* packet read at absolute offset   */
+#define BJ_HINT_IND  0x02 /* packet read at variable offset   */
+#define BJ_HINT_COP  0x04 /* BPF_COP or BPF_COPX instruction  */
+#define BJ_HINT_COPX 0x08 /* BPF_COPX instruction             */
+#define BJ_HINT_XREG 0x10 /* BJ_XREG is needed                */
+#define BJ_HINT_LDX  0x20 /* BPF_LDX instruction              */
 #define BJ_HINT_PKT  (BJ_HINT_ABS|BJ_HINT_IND) /* packet read */
 
 /*
@@ -271,6 +265,9 @@ nscratches(bpfjit_hint_t hints)
 		rv = 5; /* uses BJ_TMP3REG */
 #endif
 
+	if (hints & BJ_HINT_COPX)
+		rv = 5; /* uses BJ_TMP3REG */
+
 	return rv;
 }
 
@@ -649,26 +646,31 @@ 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,
-    const struct bpf_insn *pc, struct sljit_jump **ret0_jump)
+emit_cop(struct sljit_compiler *compiler,
+    const bpf_ctx_t *bc, const struct bpf_insn *pc,
+    struct sljit_jump ***ret0, size_t *ret0_size, size_t *ret0_maxsize)
 {
-#if BJ_XREG == SLJIT_RETURN_REG   || \
-    BJ_XREG == SLJIT_SCRATCH_REG1 || \
-    BJ_XREG == SLJIT_SCRATCH_REG2 || \
-    BJ_XREG == SLJIT_SCRATCH_REG3 || \
-    BJ_COPF_PTR == BJ_ARGS        || \
-    BJ_COPF_IDX	== BJ_ARGS
+#if BJ_XREG    == SLJIT_RETURN_REG   || \
+    BJ_XREG    == SLJIT_SCRATCH_REG1 || \
+    BJ_XREG    == SLJIT_SCRATCH_REG2 || \
+    BJ_XREG    == SLJIT_SCRATCH_REG3 || \
+    BJ_TMP3REG == SLJIT_SCRATCH_REG1 || \
+    BJ_TMP3REG == SLJIT_SCRATCH_REG2 || \
+    BJ_TMP3REG == SLJIT_SCRATCH_REG3
 #error "Not supported assignment of registers."
 #endif
 
 	struct sljit_jump *jump;
+	sljit_si call_reg;
+	sljit_sw call_off;
 	int status;
 
-	jump = NULL;
-
 	BJ_ASSERT(bc != NULL && bc->copfuncs != NULL);
 
-	if (BPF_MISCOP(pc->code) == BPF_COPX) {
+	if (BPF_MISCOP(pc->code) == BPF_COP) {
+		call_reg = SLJIT_IMM;
+		call_off = SLJIT_FUNC_OFFSET(bc->copfuncs[pc->k]);
+	} else {
 		/* if (X >= bc->nfuncs) return 0; */
 		jump = sljit_emit_cmp(compiler,
 		    SLJIT_C_GREATER_EQUAL,
@@ -676,10 +678,46 @@ emit_cop(struct sljit_compiler *compiler
 		    SLJIT_IMM, bc->nfuncs);
 		if (jump == NULL)
 			return SLJIT_ERR_ALLOC_FAILED;
-	}
+		if (!append_jump(jump, ret0, ret0_size, ret0_maxsize))
+			return SLJIT_ERR_ALLOC_FAILED;
+
+		/* tmp1 = ctx; */
+		status = sljit_emit_op1(compiler,
+		    SLJIT_MOV_P,
+		    BJ_TMP1REG, 0,
+		    SLJIT_MEM1(SLJIT_LOCALS_REG),
+		    offsetof(struct bpfjit_stack, ctx));
+		if (status != SLJIT_SUCCESS)
+			return status;
+
+		/* tmp1 = ctx->copfuncs; */
+		status = sljit_emit_op1(compiler,
+		    SLJIT_MOV_P,
+		    BJ_TMP1REG, 0,
+		    SLJIT_MEM1(BJ_TMP1REG),
+		    offsetof(struct bpf_ctx, copfuncs));
+		if (status != SLJIT_SUCCESS)
+			return status;
+
+		/* tmp2 = X; */
+		status = sljit_emit_op1(compiler,
+		    SLJIT_MOV,
+		    BJ_TMP2REG, 0,
+		    BJ_XREG, 0);
+		if (status != SLJIT_SUCCESS)
+			return status;
 
-	if (jump != NULL)
-		*ret0_jump = jump;
+		/* tmp3 = ctx->copfuncs[tmp2]; */
+		call_reg = BJ_TMP3REG;
+		call_off = 0;
+		status = sljit_emit_op1(compiler,
+		    SLJIT_MOV_P,
+		    call_reg, call_off,
+		    SLJIT_MEM2(BJ_TMP1REG, BJ_TMP2REG),
+		    SLJIT_WORD_SHIFT);
+		if (status != SLJIT_SUCCESS)
+			return status;
+	}
 
 	/*
 	 * Copy bpf_copfunc_t arguments to registers.
@@ -708,44 +746,10 @@ emit_cop(struct sljit_compiler *compiler
 	if (status != SLJIT_SUCCESS)
 		return status;
 
-	if (BPF_MISCOP(pc->code) == BPF_COP) {
-		status = sljit_emit_ijump(compiler,
-		    SLJIT_CALL3,
-		    SLJIT_IMM, SLJIT_FUNC_OFFSET(bc->copfuncs[pc->k]));
-		if (status != SLJIT_SUCCESS)
-			return status;
-	} else if (BPF_MISCOP(pc->code) == BPF_COPX) {
-		/* load ctx->copfuncs */
-		status = sljit_emit_op1(compiler,
-		    SLJIT_MOV_P,
-		    BJ_COPF_PTR, 0,
-		    SLJIT_MEM1(SLJIT_SCRATCH_REG1),
-		    offsetof(struct bpf_ctx, copfuncs));
-		if (status != SLJIT_SUCCESS)
-			return status;
-
-		/*
-		 * Load X to a register that can be used for
-		 * memory addressing.
-		 */
-		status = sljit_emit_op1(compiler,
-		    SLJIT_MOV,
-		    BJ_COPF_IDX, 0,
-		    BJ_XREG, 0);
-		if (status != SLJIT_SUCCESS)
-			return status;
-
-		status = sljit_emit_ijump(compiler,
-		    SLJIT_CALL3,
-		    SLJIT_MEM2(BJ_COPF_PTR, BJ_COPF_IDX),
-		    SLJIT_WORD_SHIFT);
-		if (status != SLJIT_SUCCESS)
-			return status;
-
-		status = load_buf_buflen(compiler);
-		if (status != SLJIT_SUCCESS)
-			return status;
-	}
+	status = sljit_emit_ijump(compiler,
+	    SLJIT_CALL3, call_reg, call_off);
+	if (status != SLJIT_SUCCESS)
+		return status;
 
 #if BJ_AREG != SLJIT_RETURN_REG
 	status = sljit_emit_op1(compiler,
@@ -1328,7 +1332,7 @@ optimize_pass1(const bpf_ctx_t *bc, cons
 				continue;
 
 			case BPF_COPX:
-				*hints |= BJ_HINT_XREG;
+				*hints |= BJ_HINT_XREG | BJ_HINT_COPX;
 				/* FALLTHROUGH */
 
 			case BPF_COP:
@@ -2019,15 +2023,11 @@ generate_insn_code(struct sljit_compiler
 					goto fail;
 				}
 
-				jump = NULL;
-				status = emit_cop(compiler, bc, pc, &jump);
+				status = emit_cop(compiler, bc, pc,
+				    &ret0, &ret0_size, &ret0_maxsize);
 				if (status != SLJIT_SUCCESS)
 					goto fail;
 
-				if (jump != NULL && !append_jump(jump,
-				    &ret0, &ret0_size, &ret0_maxsize))
-					goto fail;
-
 				continue;
 			}
 

Reply via email to