Remove bpf_jit which was ported from FreeBSD recently.

It will soon be replaced with the new bpfjit kernel module.
This commit is contained in:
alnsn 2012-09-27 18:28:53 +00:00
parent 275a51d69d
commit 5c5a76d566
17 changed files with 20 additions and 2556 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1781 2012/09/18 15:14:41 skrll Exp $
# $NetBSD: mi,v 1.1782 2012/09/27 18:28:53 alnsn Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -1805,7 +1805,7 @@
./usr/include/net/agr/if_agrioctl.h comp-c-include
./usr/include/net/bpf.h comp-c-include
./usr/include/net/bpfdesc.h comp-c-include
./usr/include/net/bpf_jit.h comp-c-include
./usr/include/net/bpf_jit.h comp-c-include obsolete
./usr/include/net/dlt.h comp-c-include
./usr/include/net/ethertypes.h comp-c-include
./usr/include/net/if.h comp-c-include

View File

@ -1,657 +0,0 @@
/* $NetBSD: bpf_jit_machdep.c,v 1.1 2012/08/01 23:24:28 rmind Exp $ */
/*-
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/amd64/amd64/bpf_jit_machdep.c,
* v 1.22 2010/04/22 23:47:19 jkim Exp $
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bpf_jit_machdep.c,v 1.1 2012/08/01 23:24:28 rmind Exp $");
#ifdef _KERNEL
#if defined(_KERNEL_OPT)
#include "opt_bpf.h"
#endif
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/malloc.h>
#include <net/if.h>
#else
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/param.h>
#endif
#include <sys/types.h>
#include <net/bpf.h>
#include <net/bpf_jit.h>
#include <amd64/amd64/bpf_jit_machdep.h>
bpf_filter_func bpf_jit_compile(struct bpf_insn *, u_int, size_t *);
/*
* Emit routine to update the jump table.
*/
static void
emit_length(bpf_bin_stream *stream, __unused u_int value, u_int len)
{
if (stream->refs != NULL)
(stream->refs)[stream->bpf_pc] += len;
stream->cur_ip += len;
}
/*
* Emit routine to output the actual binary code.
*/
static void
emit_code(bpf_bin_stream *stream, u_int value, u_int len)
{
switch (len) {
case 1:
stream->ibuf[stream->cur_ip] = (u_char)value;
stream->cur_ip++;
break;
case 2:
*((u_short *)(stream->ibuf + stream->cur_ip)) = (u_short)value;
stream->cur_ip += 2;
break;
case 4:
*((u_int *)(stream->ibuf + stream->cur_ip)) = value;
stream->cur_ip += 4;
break;
}
}
/*
* Scan the filter program and find possible optimization.
*/
static int
bpf_jit_optimize(struct bpf_insn *prog, u_int nins)
{
int flags;
u_int i;
/* Do we return immediately? */
if (BPF_CLASS(prog[0].code) == BPF_RET)
return (BPF_JIT_FRET);
for (flags = 0, i = 0; i < nins; i++) {
switch (prog[i].code) {
case BPF_LD|BPF_W|BPF_ABS:
case BPF_LD|BPF_H|BPF_ABS:
case BPF_LD|BPF_B|BPF_ABS:
case BPF_LD|BPF_W|BPF_IND:
case BPF_LD|BPF_H|BPF_IND:
case BPF_LD|BPF_B|BPF_IND:
case BPF_LDX|BPF_MSH|BPF_B:
flags |= BPF_JIT_FPKT;
break;
case BPF_LD|BPF_MEM:
case BPF_LDX|BPF_MEM:
case BPF_ST:
case BPF_STX:
flags |= BPF_JIT_FMEM;
break;
case BPF_LD|BPF_W|BPF_LEN:
case BPF_LDX|BPF_W|BPF_LEN:
flags |= BPF_JIT_FLEN;
break;
case BPF_JMP|BPF_JA:
case BPF_JMP|BPF_JGT|BPF_K:
case BPF_JMP|BPF_JGE|BPF_K:
case BPF_JMP|BPF_JEQ|BPF_K:
case BPF_JMP|BPF_JSET|BPF_K:
case BPF_JMP|BPF_JGT|BPF_X:
case BPF_JMP|BPF_JGE|BPF_X:
case BPF_JMP|BPF_JEQ|BPF_X:
case BPF_JMP|BPF_JSET|BPF_X:
flags |= BPF_JIT_FJMP;
break;
}
if (flags == BPF_JIT_FLAG_ALL)
break;
}
return (flags);
}
/*
* Function that does the real stuff.
*/
bpf_filter_func
bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
{
bpf_bin_stream stream;
struct bpf_insn *ins;
int flags, fret, fpkt, fmem, fjmp, flen;
u_int i, pass;
/*
* NOTE: Do not modify the name of this variable, as it's used by
* the macros to emit code.
*/
emit_func emitm;
flags = bpf_jit_optimize(prog, nins);
fret = (flags & BPF_JIT_FRET) != 0;
fpkt = (flags & BPF_JIT_FPKT) != 0;
fmem = (flags & BPF_JIT_FMEM) != 0;
fjmp = (flags & BPF_JIT_FJMP) != 0;
flen = (flags & BPF_JIT_FLEN) != 0;
if (fret)
nins = 1;
memset(&stream, 0, sizeof(stream));
/* Allocate the reference table for the jumps. */
if (fjmp) {
#ifdef _KERNEL
stream.refs = malloc((nins + 1) * sizeof(u_int), M_TEMP,
M_NOWAIT | M_ZERO);
#else
stream.refs = calloc(nins + 1, sizeof(u_int));
#endif
if (stream.refs == NULL)
return (NULL);
}
/*
* The first pass will emit the lengths of the instructions
* to create the reference table.
*/
emitm = emit_length;
for (pass = 0; pass < 2; pass++) {
ins = prog;
/* Create the procedure header. */
if (fmem) {
PUSH(RBP);
MOVrq(RSP, RBP);
SUBib(BPF_MEMWORDS * sizeof(uint32_t), RSP);
}
if (flen)
MOVrd2(ESI, R9D);
if (fpkt) {
MOVrq2(RDI, R8);
MOVrd(EDX, EDI);
}
for (i = 0; i < nins; i++) {
stream.bpf_pc++;
switch (ins->code) {
default:
#ifdef _KERNEL
return (NULL);
#else
abort();
#endif
case BPF_RET|BPF_K:
MOVid(ins->k, EAX);
if (fmem)
LEAVE();
RET();
break;
case BPF_RET|BPF_A:
if (fmem)
LEAVE();
RET();
break;
case BPF_LD|BPF_W|BPF_ABS:
MOVid(ins->k, ESI);
CMPrd(EDI, ESI);
JAb(12);
MOVrd(EDI, ECX);
SUBrd(ESI, ECX);
CMPid(sizeof(int32_t), ECX);
if (fmem) {
JAEb(4);
ZEROrd(EAX);
LEAVE();
} else {
JAEb(3);
ZEROrd(EAX);
}
RET();
MOVrq3(R8, RCX);
MOVobd(RCX, RSI, EAX);
BSWAP(EAX);
break;
case BPF_LD|BPF_H|BPF_ABS:
ZEROrd(EAX);
MOVid(ins->k, ESI);
CMPrd(EDI, ESI);
JAb(12);
MOVrd(EDI, ECX);
SUBrd(ESI, ECX);
CMPid(sizeof(int16_t), ECX);
if (fmem) {
JAEb(2);
LEAVE();
} else
JAEb(1);
RET();
MOVrq3(R8, RCX);
MOVobw(RCX, RSI, AX);
SWAP_AX();
break;
case BPF_LD|BPF_B|BPF_ABS:
ZEROrd(EAX);
MOVid(ins->k, ESI);
CMPrd(EDI, ESI);
if (fmem) {
JBb(2);
LEAVE();
} else
JBb(1);
RET();
MOVrq3(R8, RCX);
MOVobb(RCX, RSI, AL);
break;
case BPF_LD|BPF_W|BPF_LEN:
MOVrd3(R9D, EAX);
break;
case BPF_LDX|BPF_W|BPF_LEN:
MOVrd3(R9D, EDX);
break;
case BPF_LD|BPF_W|BPF_IND:
CMPrd(EDI, EDX);
JAb(27);
MOVid(ins->k, ESI);
MOVrd(EDI, ECX);
SUBrd(EDX, ECX);
CMPrd(ESI, ECX);
JBb(14);
ADDrd(EDX, ESI);
MOVrd(EDI, ECX);
SUBrd(ESI, ECX);
CMPid(sizeof(int32_t), ECX);
if (fmem) {
JAEb(4);
ZEROrd(EAX);
LEAVE();
} else {
JAEb(3);
ZEROrd(EAX);
}
RET();
MOVrq3(R8, RCX);
MOVobd(RCX, RSI, EAX);
BSWAP(EAX);
break;
case BPF_LD|BPF_H|BPF_IND:
ZEROrd(EAX);
CMPrd(EDI, EDX);
JAb(27);
MOVid(ins->k, ESI);
MOVrd(EDI, ECX);
SUBrd(EDX, ECX);
CMPrd(ESI, ECX);
JBb(14);
ADDrd(EDX, ESI);
MOVrd(EDI, ECX);
SUBrd(ESI, ECX);
CMPid(sizeof(int16_t), ECX);
if (fmem) {
JAEb(2);
LEAVE();
} else
JAEb(1);
RET();
MOVrq3(R8, RCX);
MOVobw(RCX, RSI, AX);
SWAP_AX();
break;
case BPF_LD|BPF_B|BPF_IND:
ZEROrd(EAX);
CMPrd(EDI, EDX);
JAEb(13);
MOVid(ins->k, ESI);
MOVrd(EDI, ECX);
SUBrd(EDX, ECX);
CMPrd(ESI, ECX);
if (fmem) {
JAb(2);
LEAVE();
} else
JAb(1);
RET();
MOVrq3(R8, RCX);
ADDrd(EDX, ESI);
MOVobb(RCX, RSI, AL);
break;
case BPF_LDX|BPF_MSH|BPF_B:
MOVid(ins->k, ESI);
CMPrd(EDI, ESI);
if (fmem) {
JBb(4);
ZEROrd(EAX);
LEAVE();
} else {
JBb(3);
ZEROrd(EAX);
}
RET();
ZEROrd(EDX);
MOVrq3(R8, RCX);
MOVobb(RCX, RSI, DL);
ANDib(0x0f, DL);
SHLib(2, EDX);
break;
case BPF_LD|BPF_IMM:
MOVid(ins->k, EAX);
break;
case BPF_LDX|BPF_IMM:
MOVid(ins->k, EDX);
break;
case BPF_LD|BPF_MEM:
MOVid(ins->k * sizeof(uint32_t), ESI);
MOVobd(RSP, RSI, EAX);
break;
case BPF_LDX|BPF_MEM:
MOVid(ins->k * sizeof(uint32_t), ESI);
MOVobd(RSP, RSI, EDX);
break;
case BPF_ST:
/*
* XXX this command and the following could
* be optimized if the previous instruction
* was already of this type
*/
MOVid(ins->k * sizeof(uint32_t), ESI);
MOVomd(EAX, RSP, RSI);
break;
case BPF_STX:
MOVid(ins->k * sizeof(uint32_t), ESI);
MOVomd(EDX, RSP, RSI);
break;
case BPF_JMP|BPF_JA:
JUMP(ins->k);
break;
case BPF_JMP|BPF_JGT|BPF_K:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPid(ins->k, EAX);
JCC(JA, JBE);
break;
case BPF_JMP|BPF_JGE|BPF_K:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPid(ins->k, EAX);
JCC(JAE, JB);
break;
case BPF_JMP|BPF_JEQ|BPF_K:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPid(ins->k, EAX);
JCC(JE, JNE);
break;
case BPF_JMP|BPF_JSET|BPF_K:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
TESTid(ins->k, EAX);
JCC(JNE, JE);
break;
case BPF_JMP|BPF_JGT|BPF_X:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPrd(EDX, EAX);
JCC(JA, JBE);
break;
case BPF_JMP|BPF_JGE|BPF_X:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPrd(EDX, EAX);
JCC(JAE, JB);
break;
case BPF_JMP|BPF_JEQ|BPF_X:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPrd(EDX, EAX);
JCC(JE, JNE);
break;
case BPF_JMP|BPF_JSET|BPF_X:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
TESTrd(EDX, EAX);
JCC(JNE, JE);
break;
case BPF_ALU|BPF_ADD|BPF_X:
ADDrd(EDX, EAX);
break;
case BPF_ALU|BPF_SUB|BPF_X:
SUBrd(EDX, EAX);
break;
case BPF_ALU|BPF_MUL|BPF_X:
MOVrd(EDX, ECX);
MULrd(EDX);
MOVrd(ECX, EDX);
break;
case BPF_ALU|BPF_DIV|BPF_X:
TESTrd(EDX, EDX);
if (fmem) {
JNEb(4);
ZEROrd(EAX);
LEAVE();
} else {
JNEb(3);
ZEROrd(EAX);
}
RET();
MOVrd(EDX, ECX);
ZEROrd(EDX);
DIVrd(ECX);
MOVrd(ECX, EDX);
break;
case BPF_ALU|BPF_AND|BPF_X:
ANDrd(EDX, EAX);
break;
case BPF_ALU|BPF_OR|BPF_X:
ORrd(EDX, EAX);
break;
case BPF_ALU|BPF_LSH|BPF_X:
MOVrd(EDX, ECX);
SHL_CLrb(EAX);
break;
case BPF_ALU|BPF_RSH|BPF_X:
MOVrd(EDX, ECX);
SHR_CLrb(EAX);
break;
case BPF_ALU|BPF_ADD|BPF_K:
ADD_EAXi(ins->k);
break;
case BPF_ALU|BPF_SUB|BPF_K:
SUB_EAXi(ins->k);
break;
case BPF_ALU|BPF_MUL|BPF_K:
MOVrd(EDX, ECX);
MOVid(ins->k, EDX);
MULrd(EDX);
MOVrd(ECX, EDX);
break;
case BPF_ALU|BPF_DIV|BPF_K:
MOVrd(EDX, ECX);
ZEROrd(EDX);
MOVid(ins->k, ESI);
DIVrd(ESI);
MOVrd(ECX, EDX);
break;
case BPF_ALU|BPF_AND|BPF_K:
ANDid(ins->k, EAX);
break;
case BPF_ALU|BPF_OR|BPF_K:
ORid(ins->k, EAX);
break;
case BPF_ALU|BPF_LSH|BPF_K:
SHLib((ins->k) & 0xff, EAX);
break;
case BPF_ALU|BPF_RSH|BPF_K:
SHRib((ins->k) & 0xff, EAX);
break;
case BPF_ALU|BPF_NEG:
NEGd(EAX);
break;
case BPF_MISC|BPF_TAX:
MOVrd(EAX, EDX);
break;
case BPF_MISC|BPF_TXA:
MOVrd(EDX, EAX);
break;
}
ins++;
}
if (pass > 0)
continue;
*size = stream.cur_ip;
#ifdef _KERNEL
stream.ibuf = malloc(*size, M_TEMP, M_NOWAIT);
if (stream.ibuf == NULL)
break;
#else
stream.ibuf = mmap(NULL, *size, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
if (stream.ibuf == MAP_FAILED) {
stream.ibuf = NULL;
break;
}
#endif
/*
* Modify the reference table to contain the offsets and
* not the lengths of the instructions.
*/
if (fjmp)
for (i = 1; i < nins + 1; i++)
stream.refs[i] += stream.refs[i - 1];
/* Reset the counters. */
stream.cur_ip = 0;
stream.bpf_pc = 0;
/* The second pass creates the actual code. */
emitm = emit_code;
}
/*
* The reference table is needed only during compilation,
* now we can free it.
*/
if (fjmp)
#ifdef _KERNEL
free(stream.refs, M_TEMP);
#else
free(stream.refs);
#endif
#ifndef _KERNEL
if (stream.ibuf != NULL &&
mprotect(stream.ibuf, *size, PROT_READ | PROT_EXEC) != 0) {
munmap(stream.ibuf, *size);
stream.ibuf = NULL;
}
#endif
return ((bpf_filter_func)stream.ibuf);
}

View File

@ -1,485 +0,0 @@
/* $NetBSD: bpf_jit_machdep.h,v 1.1 2012/08/01 23:24:28 rmind Exp $ */
/*-
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/amd64/amd64/bpf_jit_machdep.h,
* v 1.15 2010/04/22 23:47:19 jkim Exp $
*/
#ifndef _BPF_JIT_MACHDEP_H_
#define _BPF_JIT_MACHDEP_H_
/*
* Registers
*/
#define RAX 0
#define RCX 1
#define RDX 2
#define RBX 3
#define RSP 4
#define RBP 5
#define RSI 6
#define RDI 7
#define R8 0
#define R9 1
#define R10 2
#define R11 3
#define R12 4
#define R13 5
#define R14 6
#define R15 7
#define EAX 0
#define ECX 1
#define EDX 2
#define EBX 3
#define ESP 4
#define EBP 5
#define ESI 6
#define EDI 7
#define R8D 0
#define R9D 1
#define R10D 2
#define R11D 3
#define R12D 4
#define R13D 5
#define R14D 6
#define R15D 7
#define AX 0
#define CX 1
#define DX 2
#define BX 3
#define SP 4
#define BP 5
#define SI 6
#define DI 7
#define AL 0
#define CL 1
#define DL 2
#define BL 3
/* Optimization flags */
#define BPF_JIT_FRET 0x01
#define BPF_JIT_FPKT 0x02
#define BPF_JIT_FMEM 0x04
#define BPF_JIT_FJMP 0x08
#define BPF_JIT_FLEN 0x10
#define BPF_JIT_FLAG_ALL \
(BPF_JIT_FPKT | BPF_JIT_FMEM | BPF_JIT_FJMP | BPF_JIT_FLEN)
/* A stream of native binary code */
typedef struct bpf_bin_stream {
/* Current native instruction pointer. */
int cur_ip;
/*
* Current BPF instruction pointer, i.e. position in
* the BPF program reached by the jitter.
*/
int bpf_pc;
/* Instruction buffer, contains the generated native code. */
char *ibuf;
/* Jumps reference table. */
u_int *refs;
} bpf_bin_stream;
/*
* Prototype of the emit functions.
*
* Different emit functions are used to create the reference table and
* to generate the actual filtering code. This allows to have simpler
* instruction macros.
* The first parameter is the stream that will receive the data.
* The second one is a variable containing the data.
* The third one is the length, that can be 1, 2, or 4 since it is possible
* to emit a byte, a short, or a word at a time.
*/
typedef void (*emit_func)(bpf_bin_stream *, u_int, u_int);
/*
* Native instruction macros
*/
/* movl i32,r32 */
#define MOVid(i32, r32) do { \
emitm(&stream, (11 << 4) | (1 << 3) | (r32 & 0x7), 1); \
emitm(&stream, i32, 4); \
} while (0)
/* movq i64,r64 */
#define MOViq(i64, r64) do { \
emitm(&stream, 0x48, 1); \
emitm(&stream, (11 << 4) | (1 << 3) | (r64 & 0x7), 1); \
emitm(&stream, i64, 4); \
emitm(&stream, (i64 >> 32), 4); \
} while (0)
/* movl sr32,dr32 */
#define MOVrd(sr32, dr32) do { \
emitm(&stream, 0x89, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* movl sr32,dr32 (dr32 = %r8-15d) */
#define MOVrd2(sr32, dr32) do { \
emitm(&stream, 0x8941, 2); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* movl sr32,dr32 (sr32 = %r8-15d) */
#define MOVrd3(sr32, dr32) do { \
emitm(&stream, 0x8944, 2); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* movq sr64,dr64 */
#define MOVrq(sr64, dr64) do { \
emitm(&stream, 0x8948, 2); \
emitm(&stream, \
(3 << 6) | ((sr64 & 0x7) << 3) | (dr64 & 0x7), 1); \
} while (0)
/* movq sr64,dr64 (dr64 = %r8-15) */
#define MOVrq2(sr64, dr64) do { \
emitm(&stream, 0x8949, 2); \
emitm(&stream, \
(3 << 6) | ((sr64 & 0x7) << 3) | (dr64 & 0x7), 1); \
} while (0)
/* movq sr64,dr64 (sr64 = %r8-15) */
#define MOVrq3(sr64, dr64) do { \
emitm(&stream, 0x894c, 2); \
emitm(&stream, \
(3 << 6) | ((sr64 & 0x7) << 3) | (dr64 & 0x7), 1); \
} while (0)
/* movl (sr64,or64,1),dr32 */
#define MOVobd(sr64, or64, dr32) do { \
emitm(&stream, 0x8b, 1); \
emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \
emitm(&stream, ((or64 & 0x7) << 3) | (sr64 & 0x7), 1); \
} while (0)
/* movw (sr64,or64,1),dr16 */
#define MOVobw(sr64, or64, dr16) do { \
emitm(&stream, 0x8b66, 2); \
emitm(&stream, ((dr16 & 0x7) << 3) | 4, 1); \
emitm(&stream, ((or64 & 0x7) << 3) | (sr64 & 0x7), 1); \
} while (0)
/* movb (sr64,or64,1),dr8 */
#define MOVobb(sr64, or64, dr8) do { \
emitm(&stream, 0x8a, 1); \
emitm(&stream, ((dr8 & 0x7) << 3) | 4, 1); \
emitm(&stream, ((or64 & 0x7) << 3) | (sr64 & 0x7), 1); \
} while (0)
/* movl sr32,(dr64,or64,1) */
#define MOVomd(sr32, dr64, or64) do { \
emitm(&stream, 0x89, 1); \
emitm(&stream, ((sr32 & 0x7) << 3) | 4, 1); \
emitm(&stream, ((or64 & 0x7) << 3) | (dr64 & 0x7), 1); \
} while (0)
/* bswapl dr32 */
#define BSWAP(dr32) do { \
emitm(&stream, 0xf, 1); \
emitm(&stream, (0x19 << 3) | dr32, 1); \
} while (0)
/* xchgb %al,%ah */
#define SWAP_AX() do { \
emitm(&stream, 0xc486, 2); \
} while (0)
/* pushq r64 */
#define PUSH(r64) do { \
emitm(&stream, (5 << 4) | (0 << 3) | (r64 & 0x7), 1); \
} while (0)
/* leaveq */
#define LEAVE() do { \
emitm(&stream, 0xc9, 1); \
} while (0)
/* retq */
#define RET() do { \
emitm(&stream, 0xc3, 1); \
} while (0)
/* addl sr32,dr32 */
#define ADDrd(sr32, dr32) do { \
emitm(&stream, 0x01, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* addl i32,%eax */
#define ADD_EAXi(i32) do { \
emitm(&stream, 0x05, 1); \
emitm(&stream, i32, 4); \
} while (0)
/* addl i8,r32 */
#define ADDib(i8, r32) do { \
emitm(&stream, 0x83, 1); \
emitm(&stream, (24 << 3) | r32, 1); \
emitm(&stream, i8, 1); \
} while (0)
/* subl sr32,dr32 */
#define SUBrd(sr32, dr32) do { \
emitm(&stream, 0x29, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* subl i32,%eax */
#define SUB_EAXi(i32) do { \
emitm(&stream, 0x2d, 1); \
emitm(&stream, i32, 4); \
} while (0)
/* subq i8,r64 */
#define SUBib(i8, r64) do { \
emitm(&stream, 0x8348, 2); \
emitm(&stream, (29 << 3) | (r64 & 0x7), 1); \
emitm(&stream, i8, 1); \
} while (0)
/* mull r32 */
#define MULrd(r32) do { \
emitm(&stream, 0xf7, 1); \
emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
} while (0)
/* divl r32 */
#define DIVrd(r32) do { \
emitm(&stream, 0xf7, 1); \
emitm(&stream, (15 << 4) | (r32 & 0x7), 1); \
} while (0)
/* andb i8,r8 */
#define ANDib(i8, r8) do { \
if (r8 == AL) { \
emitm(&stream, 0x24, 1); \
} else { \
emitm(&stream, 0x80, 1); \
emitm(&stream, (7 << 5) | r8, 1); \
} \
emitm(&stream, i8, 1); \
} while (0)
/* andl i32,r32 */
#define ANDid(i32, r32) do { \
if (r32 == EAX) { \
emitm(&stream, 0x25, 1); \
} else { \
emitm(&stream, 0x81, 1); \
emitm(&stream, (7 << 5) | r32, 1); \
} \
emitm(&stream, i32, 4); \
} while (0)
/* andl sr32,dr32 */
#define ANDrd(sr32, dr32) do { \
emitm(&stream, 0x21, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* testl i32,r32 */
#define TESTid(i32, r32) do { \
if (r32 == EAX) { \
emitm(&stream, 0xa9, 1); \
} else { \
emitm(&stream, 0xf7, 1); \
emitm(&stream, (3 << 6) | r32, 1); \
} \
emitm(&stream, i32, 4); \
} while (0)
/* testl sr32,dr32 */
#define TESTrd(sr32, dr32) do { \
emitm(&stream, 0x85, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* orl sr32,dr32 */
#define ORrd(sr32, dr32) do { \
emitm(&stream, 0x09, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* orl i32,r32 */
#define ORid(i32, r32) do { \
if (r32 == EAX) { \
emitm(&stream, 0x0d, 1); \
} else { \
emitm(&stream, 0x81, 1); \
emitm(&stream, (25 << 3) | r32, 1); \
} \
emitm(&stream, i32, 4); \
} while (0)
/* shll i8,r32 */
#define SHLib(i8, r32) do { \
emitm(&stream, 0xc1, 1); \
emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
emitm(&stream, i8, 1); \
} while (0)
/* shll %cl,dr32 */
#define SHL_CLrb(dr32) do { \
emitm(&stream, 0xd3, 1); \
emitm(&stream, (7 << 5) | (dr32 & 0x7), 1); \
} while (0)
/* shrl i8,r32 */
#define SHRib(i8, r32) do { \
emitm(&stream, 0xc1, 1); \
emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \
emitm(&stream, i8, 1); \
} while (0)
/* shrl %cl,dr32 */
#define SHR_CLrb(dr32) do { \
emitm(&stream, 0xd3, 1); \
emitm(&stream, (29 << 3) | (dr32 & 0x7), 1); \
} while (0)
/* negl r32 */
#define NEGd(r32) do { \
emitm(&stream, 0xf7, 1); \
emitm(&stream, (27 << 3) | (r32 & 0x7), 1); \
} while (0)
/* cmpl sr32,dr32 */
#define CMPrd(sr32, dr32) do { \
emitm(&stream, 0x39, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* cmpl i32,dr32 */
#define CMPid(i32, dr32) do { \
if (dr32 == EAX){ \
emitm(&stream, 0x3d, 1); \
emitm(&stream, i32, 4); \
} else { \
emitm(&stream, 0x81, 1); \
emitm(&stream, (0x1f << 3) | (dr32 & 0x7), 1); \
emitm(&stream, i32, 4); \
} \
} while (0)
/* jb off8 */
#define JBb(off8) do { \
emitm(&stream, 0x72, 1); \
emitm(&stream, off8, 1); \
} while (0)
/* jae off8 */
#define JAEb(off8) do { \
emitm(&stream, 0x73, 1); \
emitm(&stream, off8, 1); \
} while (0)
/* jne off8 */
#define JNEb(off8) do { \
emitm(&stream, 0x75, 1); \
emitm(&stream, off8, 1); \
} while (0)
/* ja off8 */
#define JAb(off8) do { \
emitm(&stream, 0x77, 1); \
emitm(&stream, off8, 1); \
} while (0)
/* jmp off32 */
#define JMP(off32) do { \
emitm(&stream, 0xe9, 1); \
emitm(&stream, off32, 4); \
} while (0)
/* xorl r32,r32 */
#define ZEROrd(r32) do { \
emitm(&stream, 0x31, 1); \
emitm(&stream, (3 << 6) | ((r32 & 0x7) << 3) | (r32 & 0x7), 1); \
} while (0)
/*
* Conditional long jumps
*/
#define JB 0x82
#define JAE 0x83
#define JE 0x84
#define JNE 0x85
#define JBE 0x86
#define JA 0x87
#define JCC(t, f) do { \
if (ins->jt != 0 && ins->jf != 0) { \
/* 5 is the size of the following jmp */ \
emitm(&stream, ((t) << 8) | 0x0f, 2); \
emitm(&stream, stream.refs[stream.bpf_pc + ins->jt] - \
stream.refs[stream.bpf_pc] + 5, 4); \
JMP(stream.refs[stream.bpf_pc + ins->jf] - \
stream.refs[stream.bpf_pc]); \
} else if (ins->jt != 0) { \
emitm(&stream, ((t) << 8) | 0x0f, 2); \
emitm(&stream, stream.refs[stream.bpf_pc + ins->jt] - \
stream.refs[stream.bpf_pc], 4); \
} else { \
emitm(&stream, ((f) << 8) | 0x0f, 2); \
emitm(&stream, stream.refs[stream.bpf_pc + ins->jf] - \
stream.refs[stream.bpf_pc], 4); \
} \
} while (0)
#define JUMP(off) do { \
if ((off) != 0) \
JMP(stream.refs[stream.bpf_pc + (off)] - \
stream.refs[stream.bpf_pc]); \
} while (0)
#endif /* _BPF_JIT_MACHDEP_H_ */

View File

@ -1,4 +1,4 @@
# $NetBSD: files.amd64,v 1.76 2012/08/01 23:24:29 rmind Exp $
# $NetBSD: files.amd64,v 1.77 2012/09/27 18:28:55 alnsn Exp $
#
# new style config file for amd64 architecture
#
@ -31,7 +31,6 @@ defflag eisa.h EISA
file arch/amd64/amd64/amd64func.S
file arch/amd64/amd64/autoconf.c
file arch/amd64/amd64/busfunc.S
file arch/amd64/amd64/bpf_jit_machdep.c bpf_filter
file arch/amd64/amd64/cpu_in_cksum.S (inet | inet6) & cpu_in_cksum
file arch/amd64/amd64/cpufunc.S
file arch/amd64/amd64/db_disasm.c ddb

View File

@ -1,11 +1,10 @@
# $NetBSD: std.amd64,v 1.8 2012/08/01 23:24:29 rmind Exp $
# $NetBSD: std.amd64,v 1.9 2012/09/27 18:28:55 alnsn Exp $
#
# standard, required NetBSD/amd64 'options'
machine amd64 x86
include "conf/std" # MI standard options
options BPF_JIT
options CPU_IN_CKSUM
options EXEC_ELF64 # exec ELF binaries
options EXEC_SCRIPT # exec #! scripts

View File

@ -1,4 +1,4 @@
# $NetBSD: files.i386,v 1.364 2012/08/01 23:24:29 rmind Exp $
# $NetBSD: files.i386,v 1.365 2012/09/27 18:28:55 alnsn Exp $
#
# new style config file for i386 architecture
#
@ -61,7 +61,6 @@ file arch/i386/i386/multiboot.c multiboot
file arch/i386/i386/autoconf.c
file arch/i386/i386/aout_machdep.c exec_aout
file arch/i386/i386/bpf_jit_machdep.c bpf_filter
file arch/i386/i386/busfunc.S
file arch/i386/i386/cpufunc.S
file arch/i386/i386/cpu_in_cksum.S (inet | inet6) & cpu_in_cksum

View File

@ -1,11 +1,10 @@
# $NetBSD: std.i386,v 1.32 2012/08/01 23:24:29 rmind Exp $
# $NetBSD: std.i386,v 1.33 2012/09/27 18:28:55 alnsn Exp $
#
# standard, required NetBSD/i386 'options'
machine i386 x86
include "conf/std" # MI standard options
options BPF_JIT
options CPU_IN_CKSUM
options EXEC_AOUT # exec a.out binaries
options EXEC_ELF32 # exec ELF binaries

View File

@ -1,686 +0,0 @@
/* $NetBSD: bpf_jit_machdep.c,v 1.1 2012/08/01 23:24:28 rmind Exp $ */
/*-
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/i386/i386/bpf_jit_machdep.c,
* v 1.22 2010/04/22 23:47:19 jkim Exp $
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bpf_jit_machdep.c,v 1.1 2012/08/01 23:24:28 rmind Exp $");
#ifdef _KERNEL
#if defined(_KERNEL_OPT)
#include "opt_bpf.h"
#endif
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/malloc.h>
#include <net/if.h>
#else
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/param.h>
#endif
#include <sys/types.h>
#include <net/bpf.h>
#include <net/bpf_jit.h>
#include <i386/i386/bpf_jit_machdep.h>
bpf_filter_func bpf_jit_compile(struct bpf_insn *, u_int, size_t *);
/*
* Emit routine to update the jump table.
*/
static void
emit_length(bpf_bin_stream *stream, __unused u_int value, u_int len)
{
if (stream->refs != NULL)
(stream->refs)[stream->bpf_pc] += len;
stream->cur_ip += len;
}
/*
* Emit routine to output the actual binary code.
*/
static void
emit_code(bpf_bin_stream *stream, u_int value, u_int len)
{
switch (len) {
case 1:
stream->ibuf[stream->cur_ip] = (u_char)value;
stream->cur_ip++;
break;
case 2:
*((u_short *)(stream->ibuf + stream->cur_ip)) = (u_short)value;
stream->cur_ip += 2;
break;
case 4:
*((u_int *)(stream->ibuf + stream->cur_ip)) = value;
stream->cur_ip += 4;
break;
}
}
/*
* Scan the filter program and find possible optimization.
*/
static int
bpf_jit_optimize(struct bpf_insn *prog, u_int nins)
{
int flags;
u_int i;
/* Do we return immediately? */
if (BPF_CLASS(prog[0].code) == BPF_RET)
return (BPF_JIT_FRET);
for (flags = 0, i = 0; i < nins; i++) {
switch (prog[i].code) {
case BPF_LD|BPF_W|BPF_ABS:
case BPF_LD|BPF_H|BPF_ABS:
case BPF_LD|BPF_B|BPF_ABS:
case BPF_LD|BPF_W|BPF_IND:
case BPF_LD|BPF_H|BPF_IND:
case BPF_LD|BPF_B|BPF_IND:
case BPF_LDX|BPF_MSH|BPF_B:
flags |= BPF_JIT_FPKT;
break;
case BPF_LD|BPF_MEM:
case BPF_LDX|BPF_MEM:
case BPF_ST:
case BPF_STX:
flags |= BPF_JIT_FMEM;
break;
case BPF_JMP|BPF_JA:
case BPF_JMP|BPF_JGT|BPF_K:
case BPF_JMP|BPF_JGE|BPF_K:
case BPF_JMP|BPF_JEQ|BPF_K:
case BPF_JMP|BPF_JSET|BPF_K:
case BPF_JMP|BPF_JGT|BPF_X:
case BPF_JMP|BPF_JGE|BPF_X:
case BPF_JMP|BPF_JEQ|BPF_X:
case BPF_JMP|BPF_JSET|BPF_X:
flags |= BPF_JIT_FJMP;
break;
case BPF_ALU|BPF_DIV|BPF_K:
flags |= BPF_JIT_FADK;
break;
}
if (flags == BPF_JIT_FLAG_ALL)
break;
}
return (flags);
}
/*
* Function that does the real stuff.
*/
bpf_filter_func
bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
{
bpf_bin_stream stream;
struct bpf_insn *ins;
int flags, fret, fpkt, fmem, fjmp, fadk;
int save_esp;
u_int i, pass;
/*
* NOTE: Do not modify the name of this variable, as it's used by
* the macros to emit code.
*/
emit_func emitm;
flags = bpf_jit_optimize(prog, nins);
fret = (flags & BPF_JIT_FRET) != 0;
fpkt = (flags & BPF_JIT_FPKT) != 0;
fmem = (flags & BPF_JIT_FMEM) != 0;
fjmp = (flags & BPF_JIT_FJMP) != 0;
fadk = (flags & BPF_JIT_FADK) != 0;
save_esp = (fpkt || fmem || fadk); /* Stack is used. */
if (fret)
nins = 1;
memset(&stream, 0, sizeof(stream));
/* Allocate the reference table for the jumps. */
if (fjmp) {
#ifdef _KERNEL
stream.refs = malloc((nins + 1) * sizeof(u_int), M_TEMP,
M_NOWAIT | M_ZERO);
#else
stream.refs = calloc(nins + 1, sizeof(u_int));
#endif
if (stream.refs == NULL)
return (NULL);
}
/*
* The first pass will emit the lengths of the instructions
* to create the reference table.
*/
emitm = emit_length;
for (pass = 0; pass < 2; pass++) {
ins = prog;
/* Create the procedure header. */
if (save_esp) {
PUSH(EBP);
MOVrd(ESP, EBP);
}
if (fmem)
SUBib(BPF_MEMWORDS * sizeof(uint32_t), ESP);
if (save_esp)
PUSH(ESI);
if (fpkt) {
PUSH(EDI);
PUSH(EBX);
MOVodd(8, EBP, EBX);
MOVodd(16, EBP, EDI);
}
for (i = 0; i < nins; i++) {
stream.bpf_pc++;
switch (ins->code) {
default:
#ifdef _KERNEL
return (NULL);
#else
abort();
#endif
case BPF_RET|BPF_K:
MOVid(ins->k, EAX);
if (save_esp) {
if (fpkt) {
POP(EBX);
POP(EDI);
}
POP(ESI);
LEAVE();
}
RET();
break;
case BPF_RET|BPF_A:
if (save_esp) {
if (fpkt) {
POP(EBX);
POP(EDI);
}
POP(ESI);
LEAVE();
}
RET();
break;
case BPF_LD|BPF_W|BPF_ABS:
MOVid(ins->k, ESI);
CMPrd(EDI, ESI);
JAb(12);
MOVrd(EDI, ECX);
SUBrd(ESI, ECX);
CMPid(sizeof(int32_t), ECX);
JAEb(7);
ZEROrd(EAX);
POP(EBX);
POP(EDI);
POP(ESI);
LEAVE();
RET();
MOVobd(EBX, ESI, EAX);
BSWAP(EAX);
break;
case BPF_LD|BPF_H|BPF_ABS:
ZEROrd(EAX);
MOVid(ins->k, ESI);
CMPrd(EDI, ESI);
JAb(12);
MOVrd(EDI, ECX);
SUBrd(ESI, ECX);
CMPid(sizeof(int16_t), ECX);
JAEb(5);
POP(EBX);
POP(EDI);
POP(ESI);
LEAVE();
RET();
MOVobw(EBX, ESI, AX);
SWAP_AX();
break;
case BPF_LD|BPF_B|BPF_ABS:
ZEROrd(EAX);
MOVid(ins->k, ESI);
CMPrd(EDI, ESI);
JBb(5);
POP(EBX);
POP(EDI);
POP(ESI);
LEAVE();
RET();
MOVobb(EBX, ESI, AL);
break;
case BPF_LD|BPF_W|BPF_LEN:
if (save_esp)
MOVodd(12, EBP, EAX);
else {
MOVrd(ESP, ECX);
MOVodd(12, ECX, EAX);
}
break;
case BPF_LDX|BPF_W|BPF_LEN:
if (save_esp)
MOVodd(12, EBP, EDX);
else {
MOVrd(ESP, ECX);
MOVodd(12, ECX, EDX);
}
break;
case BPF_LD|BPF_W|BPF_IND:
CMPrd(EDI, EDX);
JAb(27);
MOVid(ins->k, ESI);
MOVrd(EDI, ECX);
SUBrd(EDX, ECX);
CMPrd(ESI, ECX);
JBb(14);
ADDrd(EDX, ESI);
MOVrd(EDI, ECX);
SUBrd(ESI, ECX);
CMPid(sizeof(int32_t), ECX);
JAEb(7);
ZEROrd(EAX);
POP(EBX);
POP(EDI);
POP(ESI);
LEAVE();
RET();
MOVobd(EBX, ESI, EAX);
BSWAP(EAX);
break;
case BPF_LD|BPF_H|BPF_IND:
ZEROrd(EAX);
CMPrd(EDI, EDX);
JAb(27);
MOVid(ins->k, ESI);
MOVrd(EDI, ECX);
SUBrd(EDX, ECX);
CMPrd(ESI, ECX);
JBb(14);
ADDrd(EDX, ESI);
MOVrd(EDI, ECX);
SUBrd(ESI, ECX);
CMPid(sizeof(int16_t), ECX);
JAEb(5);
POP(EBX);
POP(EDI);
POP(ESI);
LEAVE();
RET();
MOVobw(EBX, ESI, AX);
SWAP_AX();
break;
case BPF_LD|BPF_B|BPF_IND:
ZEROrd(EAX);
CMPrd(EDI, EDX);
JAEb(13);
MOVid(ins->k, ESI);
MOVrd(EDI, ECX);
SUBrd(EDX, ECX);
CMPrd(ESI, ECX);
JAb(5);
POP(EBX);
POP(EDI);
POP(ESI);
LEAVE();
RET();
ADDrd(EDX, ESI);
MOVobb(EBX, ESI, AL);
break;
case BPF_LDX|BPF_MSH|BPF_B:
MOVid(ins->k, ESI);
CMPrd(EDI, ESI);
JBb(7);
ZEROrd(EAX);
POP(EBX);
POP(EDI);
POP(ESI);
LEAVE();
RET();
ZEROrd(EDX);
MOVobb(EBX, ESI, DL);
ANDib(0x0f, DL);
SHLib(2, EDX);
break;
case BPF_LD|BPF_IMM:
MOVid(ins->k, EAX);
break;
case BPF_LDX|BPF_IMM:
MOVid(ins->k, EDX);
break;
case BPF_LD|BPF_MEM:
MOVrd(EBP, ECX);
MOVid(((int)ins->k - BPF_MEMWORDS) *
sizeof(uint32_t), ESI);
MOVobd(ECX, ESI, EAX);
break;
case BPF_LDX|BPF_MEM:
MOVrd(EBP, ECX);
MOVid(((int)ins->k - BPF_MEMWORDS) *
sizeof(uint32_t), ESI);
MOVobd(ECX, ESI, EDX);
break;
case BPF_ST:
/*
* XXX this command and the following could
* be optimized if the previous instruction
* was already of this type
*/
MOVrd(EBP, ECX);
MOVid(((int)ins->k - BPF_MEMWORDS) *
sizeof(uint32_t), ESI);
MOVomd(EAX, ECX, ESI);
break;
case BPF_STX:
MOVrd(EBP, ECX);
MOVid(((int)ins->k - BPF_MEMWORDS) *
sizeof(uint32_t), ESI);
MOVomd(EDX, ECX, ESI);
break;
case BPF_JMP|BPF_JA:
JUMP(ins->k);
break;
case BPF_JMP|BPF_JGT|BPF_K:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPid(ins->k, EAX);
JCC(JA, JBE);
break;
case BPF_JMP|BPF_JGE|BPF_K:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPid(ins->k, EAX);
JCC(JAE, JB);
break;
case BPF_JMP|BPF_JEQ|BPF_K:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPid(ins->k, EAX);
JCC(JE, JNE);
break;
case BPF_JMP|BPF_JSET|BPF_K:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
TESTid(ins->k, EAX);
JCC(JNE, JE);
break;
case BPF_JMP|BPF_JGT|BPF_X:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPrd(EDX, EAX);
JCC(JA, JBE);
break;
case BPF_JMP|BPF_JGE|BPF_X:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPrd(EDX, EAX);
JCC(JAE, JB);
break;
case BPF_JMP|BPF_JEQ|BPF_X:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
CMPrd(EDX, EAX);
JCC(JE, JNE);
break;
case BPF_JMP|BPF_JSET|BPF_X:
if (ins->jt == ins->jf) {
JUMP(ins->jt);
break;
}
TESTrd(EDX, EAX);
JCC(JNE, JE);
break;
case BPF_ALU|BPF_ADD|BPF_X:
ADDrd(EDX, EAX);
break;
case BPF_ALU|BPF_SUB|BPF_X:
SUBrd(EDX, EAX);
break;
case BPF_ALU|BPF_MUL|BPF_X:
MOVrd(EDX, ECX);
MULrd(EDX);
MOVrd(ECX, EDX);
break;
case BPF_ALU|BPF_DIV|BPF_X:
TESTrd(EDX, EDX);
if (save_esp) {
if (fpkt) {
JNEb(7);
ZEROrd(EAX);
POP(EBX);
POP(EDI);
} else {
JNEb(5);
ZEROrd(EAX);
}
POP(ESI);
LEAVE();
} else {
JNEb(3);
ZEROrd(EAX);
}
RET();
MOVrd(EDX, ECX);
ZEROrd(EDX);
DIVrd(ECX);
MOVrd(ECX, EDX);
break;
case BPF_ALU|BPF_AND|BPF_X:
ANDrd(EDX, EAX);
break;
case BPF_ALU|BPF_OR|BPF_X:
ORrd(EDX, EAX);
break;
case BPF_ALU|BPF_LSH|BPF_X:
MOVrd(EDX, ECX);
SHL_CLrb(EAX);
break;
case BPF_ALU|BPF_RSH|BPF_X:
MOVrd(EDX, ECX);
SHR_CLrb(EAX);
break;
case BPF_ALU|BPF_ADD|BPF_K:
ADD_EAXi(ins->k);
break;
case BPF_ALU|BPF_SUB|BPF_K:
SUB_EAXi(ins->k);
break;
case BPF_ALU|BPF_MUL|BPF_K:
MOVrd(EDX, ECX);
MOVid(ins->k, EDX);
MULrd(EDX);
MOVrd(ECX, EDX);
break;
case BPF_ALU|BPF_DIV|BPF_K:
MOVrd(EDX, ECX);
ZEROrd(EDX);
MOVid(ins->k, ESI);
DIVrd(ESI);
MOVrd(ECX, EDX);
break;
case BPF_ALU|BPF_AND|BPF_K:
ANDid(ins->k, EAX);
break;
case BPF_ALU|BPF_OR|BPF_K:
ORid(ins->k, EAX);
break;
case BPF_ALU|BPF_LSH|BPF_K:
SHLib((ins->k) & 0xff, EAX);
break;
case BPF_ALU|BPF_RSH|BPF_K:
SHRib((ins->k) & 0xff, EAX);
break;
case BPF_ALU|BPF_NEG:
NEGd(EAX);
break;
case BPF_MISC|BPF_TAX:
MOVrd(EAX, EDX);
break;
case BPF_MISC|BPF_TXA:
MOVrd(EDX, EAX);
break;
}
ins++;
}
if (pass > 0)
continue;
*size = stream.cur_ip;
#ifdef _KERNEL
stream.ibuf = malloc(*size, M_TEMP, M_NOWAIT);
if (stream.ibuf == NULL)
break;
#else
stream.ibuf = mmap(NULL, *size, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
if (stream.ibuf == MAP_FAILED) {
stream.ibuf = NULL;
break;
}
#endif
/*
* Modify the reference table to contain the offsets and
* not the lengths of the instructions.
*/
if (fjmp)
for (i = 1; i < nins + 1; i++)
stream.refs[i] += stream.refs[i - 1];
/* Reset the counters. */
stream.cur_ip = 0;
stream.bpf_pc = 0;
/* The second pass creates the actual code. */
emitm = emit_code;
}
/*
* The reference table is needed only during compilation,
* now we can free it.
*/
if (fjmp)
#ifdef _KERNEL
free(stream.refs, M_TEMP);
#else
free(stream.refs);
#endif
#ifndef _KERNEL
if (stream.ibuf != NULL &&
mprotect(stream.ibuf, *size, PROT_READ | PROT_EXEC) != 0) {
munmap(stream.ibuf, *size);
stream.ibuf = NULL;
}
#endif
return ((bpf_filter_func)stream.ibuf);
}

View File

@ -1,430 +0,0 @@
/* $NetBSD: bpf_jit_machdep.h,v 1.1 2012/08/01 23:24:28 rmind Exp $ */
/*-
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/i386/i386/bpf_jit_machdep.h,
* v 1.15 2010/04/22 23:47:19 jkim Exp $
*/
#ifndef _BPF_JIT_MACHDEP_H_
#define _BPF_JIT_MACHDEP_H_
/*
* Registers
*/
#define EAX 0
#define ECX 1
#define EDX 2
#define EBX 3
#define ESP 4
#define EBP 5
#define ESI 6
#define EDI 7
#define AX 0
#define CX 1
#define DX 2
#define BX 3
#define SP 4
#define BP 5
#define SI 6
#define DI 7
#define AL 0
#define CL 1
#define DL 2
#define BL 3
/* Optimization flags */
#define BPF_JIT_FRET 0x01
#define BPF_JIT_FPKT 0x02
#define BPF_JIT_FMEM 0x04
#define BPF_JIT_FJMP 0x08
#define BPF_JIT_FADK 0x10
#define BPF_JIT_FLAG_ALL \
(BPF_JIT_FPKT | BPF_JIT_FMEM | BPF_JIT_FJMP | BPF_JIT_FADK)
/* A stream of native binary code */
typedef struct bpf_bin_stream {
/* Current native instruction pointer. */
int cur_ip;
/*
* Current BPF instruction pointer, i.e. position in
* the BPF program reached by the jitter.
*/
int bpf_pc;
/* Instruction buffer, contains the generated native code. */
char *ibuf;
/* Jumps reference table. */
u_int *refs;
} bpf_bin_stream;
/*
* Prototype of the emit functions.
*
* Different emit functions are used to create the reference table and
* to generate the actual filtering code. This allows to have simpler
* instruction macros.
* The first parameter is the stream that will receive the data.
* The second one is a variable containing the data.
* The third one is the length, that can be 1, 2, or 4 since it is possible
* to emit a byte, a short, or a word at a time.
*/
typedef void (*emit_func)(bpf_bin_stream *, u_int, u_int);
/*
* Native instruction macros
*/
/* movl i32,r32 */
#define MOVid(i32, r32) do { \
emitm(&stream, (11 << 4) | (1 << 3) | (r32 & 0x7), 1); \
emitm(&stream, i32, 4); \
} while (0)
/* movl sr32,dr32 */
#define MOVrd(sr32, dr32) do { \
emitm(&stream, 0x89, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* movl off(sr32),dr32 */
#define MOVodd(off, sr32, dr32) do { \
emitm(&stream, 0x8b, 1); \
emitm(&stream, \
(1 << 6) | ((dr32 & 0x7) << 3) | (sr32 & 0x7), 1); \
emitm(&stream, off, 1); \
} while (0)
/* movl (sr32,or32,1),dr32 */
#define MOVobd(sr32, or32, dr32) do { \
emitm(&stream, 0x8b, 1); \
emitm(&stream, ((dr32 & 0x7) << 3) | 4, 1); \
emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \
} while (0)
/* movw (sr32,or32,1),dr16 */
#define MOVobw(sr32, or32, dr16) do { \
emitm(&stream, 0x8b66, 2); \
emitm(&stream, ((dr16 & 0x7) << 3) | 4, 1); \
emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \
} while (0)
/* movb (sr32,or32,1),dr8 */
#define MOVobb(sr32, or32, dr8) do { \
emitm(&stream, 0x8a, 1); \
emitm(&stream, ((dr8 & 0x7) << 3) | 4, 1); \
emitm(&stream, ((or32 & 0x7) << 3) | (sr32 & 0x7), 1); \
} while (0)
/* movl sr32,(dr32,or32,1) */
#define MOVomd(sr32, dr32, or32) do { \
emitm(&stream, 0x89, 1); \
emitm(&stream, ((sr32 & 0x7) << 3) | 4, 1); \
emitm(&stream, ((or32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* bswapl dr32 */
#define BSWAP(dr32) do { \
emitm(&stream, 0xf, 1); \
emitm(&stream, (0x19 << 3) | dr32, 1); \
} while (0)
/* xchgb %al,%ah */
#define SWAP_AX() do { \
emitm(&stream, 0xc486, 2); \
} while (0)
/* pushl r32 */
#define PUSH(r32) do { \
emitm(&stream, (5 << 4) | (0 << 3) | (r32 & 0x7), 1); \
} while (0)
/* popl r32 */
#define POP(r32) do { \
emitm(&stream, (5 << 4) | (1 << 3) | (r32 & 0x7), 1); \
} while (0)
/* leave */
#define LEAVE() do { \
emitm(&stream, 0xc9, 1); \
} while (0)
/* ret */
#define RET() do { \
emitm(&stream, 0xc3, 1); \
} while (0)
/* addl sr32,dr32 */
#define ADDrd(sr32, dr32) do { \
emitm(&stream, 0x01, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* addl i32,%eax */
#define ADD_EAXi(i32) do { \
emitm(&stream, 0x05, 1); \
emitm(&stream, i32, 4); \
} while (0)
/* addl i8,r32 */
#define ADDib(i8, r32) do { \
emitm(&stream, 0x83, 1); \
emitm(&stream, (24 << 3) | r32, 1); \
emitm(&stream, i8, 1); \
} while (0)
/* subl sr32,dr32 */
#define SUBrd(sr32, dr32) do { \
emitm(&stream, 0x29, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* subl i32,%eax */
#define SUB_EAXi(i32) do { \
emitm(&stream, 0x2d, 1); \
emitm(&stream, i32, 4); \
} while (0)
/* subl i8,r32 */
#define SUBib(i8, r32) do { \
emitm(&stream, 0x83, 1); \
emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \
emitm(&stream, i8, 1); \
} while (0)
/* mull r32 */
#define MULrd(r32) do { \
emitm(&stream, 0xf7, 1); \
emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
} while (0)
/* divl r32 */
#define DIVrd(r32) do { \
emitm(&stream, 0xf7, 1); \
emitm(&stream, (15 << 4) | (r32 & 0x7), 1); \
} while (0)
/* andb i8,r8 */
#define ANDib(i8, r8) do { \
if (r8 == AL) { \
emitm(&stream, 0x24, 1); \
} else { \
emitm(&stream, 0x80, 1); \
emitm(&stream, (7 << 5) | r8, 1); \
} \
emitm(&stream, i8, 1); \
} while (0)
/* andl i32,r32 */
#define ANDid(i32, r32) do { \
if (r32 == EAX) { \
emitm(&stream, 0x25, 1); \
} else { \
emitm(&stream, 0x81, 1); \
emitm(&stream, (7 << 5) | r32, 1); \
} \
emitm(&stream, i32, 4); \
} while (0)
/* andl sr32,dr32 */
#define ANDrd(sr32, dr32) do { \
emitm(&stream, 0x21, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* testl i32,r32 */
#define TESTid(i32, r32) do { \
if (r32 == EAX) { \
emitm(&stream, 0xa9, 1); \
} else { \
emitm(&stream, 0xf7, 1); \
emitm(&stream, (3 << 6) | r32, 1); \
} \
emitm(&stream, i32, 4); \
} while (0)
/* testl sr32,dr32 */
#define TESTrd(sr32, dr32) do { \
emitm(&stream, 0x85, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* orl sr32,dr32 */
#define ORrd(sr32, dr32) do { \
emitm(&stream, 0x09, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* orl i32,r32 */
#define ORid(i32, r32) do { \
if (r32 == EAX) { \
emitm(&stream, 0x0d, 1); \
} else { \
emitm(&stream, 0x81, 1); \
emitm(&stream, (25 << 3) | r32, 1); \
} \
emitm(&stream, i32, 4); \
} while (0)
/* shll i8,r32 */
#define SHLib(i8, r32) do { \
emitm(&stream, 0xc1, 1); \
emitm(&stream, (7 << 5) | (r32 & 0x7), 1); \
emitm(&stream, i8, 1); \
} while (0)
/* shll %cl,dr32 */
#define SHL_CLrb(dr32) do { \
emitm(&stream, 0xd3, 1); \
emitm(&stream, (7 << 5) | (dr32 & 0x7), 1); \
} while (0)
/* shrl i8,r32 */
#define SHRib(i8, r32) do { \
emitm(&stream, 0xc1, 1); \
emitm(&stream, (29 << 3) | (r32 & 0x7), 1); \
emitm(&stream, i8, 1); \
} while (0)
/* shrl %cl,dr32 */
#define SHR_CLrb(dr32) do { \
emitm(&stream, 0xd3, 1); \
emitm(&stream, (29 << 3) | (dr32 & 0x7), 1); \
} while (0)
/* negl r32 */
#define NEGd(r32) do { \
emitm(&stream, 0xf7, 1); \
emitm(&stream, (27 << 3) | (r32 & 0x7), 1); \
} while (0)
/* cmpl sr32,dr32 */
#define CMPrd(sr32, dr32) do { \
emitm(&stream, 0x39, 1); \
emitm(&stream, \
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
} while (0)
/* cmpl i32,dr32 */
#define CMPid(i32, dr32) do { \
if (dr32 == EAX){ \
emitm(&stream, 0x3d, 1); \
emitm(&stream, i32, 4); \
} else { \
emitm(&stream, 0x81, 1); \
emitm(&stream, (0x1f << 3) | (dr32 & 0x7), 1); \
emitm(&stream, i32, 4); \
} \
} while (0)
/* jb off8 */
#define JBb(off8) do { \
emitm(&stream, 0x72, 1); \
emitm(&stream, off8, 1); \
} while (0)
/* jae off8 */
#define JAEb(off8) do { \
emitm(&stream, 0x73, 1); \
emitm(&stream, off8, 1); \
} while (0)
/* jne off8 */
#define JNEb(off8) do { \
emitm(&stream, 0x75, 1); \
emitm(&stream, off8, 1); \
} while (0)
/* ja off8 */
#define JAb(off8) do { \
emitm(&stream, 0x77, 1); \
emitm(&stream, off8, 1); \
} while (0)
/* jmp off32 */
#define JMP(off32) do { \
emitm(&stream, 0xe9, 1); \
emitm(&stream, off32, 4); \
} while (0)
/* xorl r32,r32 */
#define ZEROrd(r32) do { \
emitm(&stream, 0x31, 1); \
emitm(&stream, (3 << 6) | ((r32 & 0x7) << 3) | (r32 & 0x7), 1); \
} while (0)
/*
* Conditional long jumps
*/
#define JB 0x82
#define JAE 0x83
#define JE 0x84
#define JNE 0x85
#define JBE 0x86
#define JA 0x87
#define JCC(t, f) do { \
if (ins->jt != 0 && ins->jf != 0) { \
/* 5 is the size of the following jmp */ \
emitm(&stream, ((t) << 8) | 0x0f, 2); \
emitm(&stream, stream.refs[stream.bpf_pc + ins->jt] - \
stream.refs[stream.bpf_pc] + 5, 4); \
JMP(stream.refs[stream.bpf_pc + ins->jf] - \
stream.refs[stream.bpf_pc]); \
} else if (ins->jt != 0) { \
emitm(&stream, ((t) << 8) | 0x0f, 2); \
emitm(&stream, stream.refs[stream.bpf_pc + ins->jt] - \
stream.refs[stream.bpf_pc], 4); \
} else { \
emitm(&stream, ((f) << 8) | 0x0f, 2); \
emitm(&stream, stream.refs[stream.bpf_pc + ins->jf] - \
stream.refs[stream.bpf_pc], 4); \
} \
} while (0)
#define JUMP(off) do { \
if ((off) != 0) \
JMP(stream.refs[stream.bpf_pc + (off)] - \
stream.refs[stream.bpf_pc]); \
} while (0)
#endif /* _BPF_JIT_MACHDEP_H_ */

View File

@ -1,4 +1,4 @@
# $NetBSD: files,v 1.1057 2012/09/01 11:21:22 matt Exp $
# $NetBSD: files,v 1.1058 2012/09/27 18:28:56 alnsn Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
version 20100430
@ -184,7 +184,6 @@ include "dev/sysmon/files.sysmon"
#
define bpf_filter
defparam opt_bpf.h BPF_BUFSIZE
defflag opt_bpf.h BPF_JIT
include "net80211/files.net80211"
include "netatalk/files.netatalk"
@ -1648,7 +1647,6 @@ file miscfs/syncfs/sync_vnops.c
file net/bpf.c bpfilter
file net/bpf_filter.c bpf_filter
file net/bpf_jit.c bpf_filter & bpf_jit
file net/bpf_stub.c
file net/bsd-comp.c ppp & ppp_bsdcomp
file net/if.c

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.3 2012/08/02 00:22:32 matt Exp $
# $NetBSD: Makefile,v 1.4 2012/09/27 18:28:56 alnsn Exp $
#
.include "../Makefile.inc"
@ -10,16 +10,4 @@ KMOD= bpf
# inseparable from bpfilter?)
SRCS= bpf.c bpf_filter.c
.PATH: ${S}/arch/${MACHINE}/${MACHINE}
.PATH: ${S}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
.PATH: ${S}/arch/${MACHINE_CPU}/${MACHINE_CPU}
.if (exists(${S}/arch/${MACHINE}/${MACHINE}/bpf_jit_machdep.c)) || \
(exists(${S}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}/bpf_jit_machdep.c)) || \
(exists(${S}/arch/${MACHINE_CPU}/${MACHINE_CPU}/bpf_jit_machdep.c))
SRCS+= bpf_jit.c
SRCS+= bpf_jit_machdep.c
CPPFLAGS+= -DBPF_JIT
.endif
.include <bsd.kmodule.mk>

View File

@ -1,8 +1,8 @@
# $NetBSD: Makefile,v 1.30 2012/08/02 01:16:36 matt Exp $
# $NetBSD: Makefile,v 1.31 2012/09/27 18:28:56 alnsn Exp $
INCSDIR= /usr/include/net
INCS= bpf.h bpfdesc.h bpf_jit.h dlt.h ethertypes.h if.h if_arc.h if_arp.h \
INCS= bpf.h bpfdesc.h dlt.h ethertypes.h if.h if_arc.h if_arp.h \
if_atm.h if_bridgevar.h if_dl.h if_ether.h if_etherip.h if_fddi.h if_gif.h \
if_gre.h if_hippi.h if_ieee1394.h if_llc.h if_media.h if_mpls.h \
if_pflog.h if_ppp.h if_pppoe.h if_sppp.h if_srt.h if_stf.h \

View File

@ -1,4 +1,4 @@
/* $NetBSD: bpf.c,v 1.171 2012/08/15 20:59:51 alnsn Exp $ */
/* $NetBSD: bpf.c,v 1.172 2012/09/27 18:28:56 alnsn Exp $ */
/*
* Copyright (c) 1990, 1991, 1993
@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.171 2012/08/15 20:59:51 alnsn Exp $");
__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.172 2012/09/27 18:28:56 alnsn Exp $");
#if defined(_KERNEL_OPT)
#include "opt_bpf.h"
@ -79,7 +79,6 @@ __KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.171 2012/08/15 20:59:51 alnsn Exp $");
#include <net/slip.h>
#include <net/bpf.h>
#include <net/bpf_jit.h>
#include <net/bpfdesc.h>
#include <net/if_arc.h>
@ -120,14 +119,6 @@ struct bpf_stat bpf_gstats;
*/
static kmutex_t bpf_mtx;
/* BPF JIT compilation. */
static bool bpf_jit_enable __read_mostly = false;
#ifndef BPF_JIT
#define bpf_jit(x, y) NULL
#define bpf_destroy_jit_filter(x) (void)x
#endif
/*
* bpf_iflist is the list of interfaces; each corresponds to an ifnet
* bpf_dtab holds the descriptors, indexed by minor device #
@ -1063,7 +1054,6 @@ int
bpf_setf(struct bpf_d *d, struct bpf_program *fp)
{
struct bpf_insn *fcode, *old;
bpf_jit_filter *jfunc, *ofunc;
size_t flen, size;
int s;
@ -1085,28 +1075,20 @@ bpf_setf(struct bpf_d *d, struct bpf_program *fp)
free(fcode, M_DEVBUF);
return EINVAL;
}
/* Perform JIT compilation. */
jfunc = bpf_jit(fcode, flen);
} else {
fcode = NULL;
jfunc = NULL;
}
s = splnet();
old = d->bd_filter;
ofunc = d->bd_bfilter;
d->bd_filter = fcode;
d->bd_bfilter = jfunc;
reset_d(d);
splx(s);
if (old) {
free(old, M_DEVBUF);
}
if (ofunc) {
bpf_destroy_jit_filter(ofunc);
}
return 0;
}
@ -1368,7 +1350,6 @@ bpf_deliver(struct bpf_if *bp, void *(*cpfn)(void *, const void *, size_t),
* interfaces shared any data. This is not the case.
*/
for (d = bp->bif_dlist; d != NULL; d = d->bd_next) {
bpf_jit_filter *bf;
u_int slen;
if (!d->bd_seesent && !rcv) {
@ -1377,17 +1358,7 @@ bpf_deliver(struct bpf_if *bp, void *(*cpfn)(void *, const void *, size_t),
d->bd_rcount++;
bpf_gstats.bs_recv++;
bf = bpf_jit_enable ? d->bd_bfilter : NULL;
if (bf) {
/*
* XXX THIS is totally broken when pkt
* points to mbuf. FreeBSD does a runtime
* check, we don't.
*/
slen = (*(bf->func))(pkt, pktlen, pktlen);
} else {
slen = bpf_filter(d->bd_filter, pkt, pktlen, buflen);
}
slen = bpf_filter(d->bd_filter, pkt, pktlen, buflen);
if (!slen) {
continue;
}
@ -1716,8 +1687,6 @@ bpf_freed(struct bpf_d *d)
}
if (d->bd_filter)
free(d->bd_filter, M_DEVBUF);
if (d->bd_bfilter)
bpf_destroy_jit_filter(d->bd_bfilter);
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: bpf_filter.c,v 1.53 2012/08/15 21:31:39 alnsn Exp $ */
/* $NetBSD: bpf_filter.c,v 1.54 2012/09/27 18:28:56 alnsn Exp $ */
/*-
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bpf_filter.c,v 1.53 2012/08/15 21:31:39 alnsn Exp $");
__KERNEL_RCSID(0, "$NetBSD: bpf_filter.c,v 1.54 2012/09/27 18:28:56 alnsn Exp $");
#if 0
#if !(defined(lint) || defined(KERNEL))
@ -86,10 +86,8 @@ m_xword(const struct mbuf *m, uint32_t k, int *err)
return EXTRACT_LONG(cp);
}
m0 = m->m_next;
if (m0 == 0 || m0->m_len + len - k < 4) {
*err = 1;
if (m0 == 0 || m0->m_len + len - k < 4)
return 0;
}
*err = 0;
np = mtod(m0, u_char *);
@ -118,16 +116,13 @@ m_xhalf(const struct mbuf *m, uint32_t k, int *err)
return EXTRACT_SHORT(cp);
}
m0 = m->m_next;
if (m0 == 0) {
*err = 1;
if (m0 == 0)
return 0;
}
*err = 0;
return (cp[0] << 8) | mtod(m0, u_char *)[0];
}
#else /* _KERNEL */
#include <stdlib.h>
#include <string.h>
#endif /* !_KERNEL */
#include <net/bpf.h>

View File

@ -1,142 +0,0 @@
/* $NetBSD: bpf_jit.c,v 1.1 2012/08/01 23:24:29 rmind Exp $ */
/*-
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/net/bpf_jitter.c,v 1.11 2009/11/20 18:49:20 jkim Exp $
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bpf_jit.c,v 1.1 2012/08/01 23:24:29 rmind Exp $");
#ifdef _KERNEL
#if defined(_KERNEL_OPT)
#include "opt_bpf.h"
#endif
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/sysctl.h>
#else
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/types.h>
#endif
#include <net/bpf.h>
#include <net/bpf_jit.h>
bpf_filter_func bpf_jit_compile(struct bpf_insn *, u_int, size_t *);
static u_int bpf_jit_accept_all(u_char *, u_int, u_int);
#ifdef _KERNEL
bpf_jit_filter *
bpf_jit(struct bpf_insn *fp, int nins)
{
bpf_jit_filter *filter;
/* Allocate the filter structure */
filter = malloc(sizeof(*filter), M_TEMP, M_NOWAIT);
if (filter == NULL)
return (NULL);
/* No filter means accept all */
if (fp == NULL || nins == 0) {
filter->func = bpf_jit_accept_all;
return (filter);
}
/* Create the binary */
if ((filter->func = bpf_jit_compile(fp, nins, &filter->size)) == NULL) {
free(filter, M_TEMP);
return (NULL);
}
return (filter);
}
void
bpf_destroy_jit_filter(bpf_jit_filter *filter)
{
if (filter->func != bpf_jit_accept_all)
free(filter->func, M_TEMP);
free(filter, M_TEMP);
}
#else
bpf_jit_filter *
bpf_jit(struct bpf_insn *fp, int nins)
{
bpf_jit_filter *filter;
/* Allocate the filter structure */
filter = (struct bpf_jit_filter *)malloc(sizeof(*filter));
if (filter == NULL)
return (NULL);
/* No filter means accept all */
if (fp == NULL || nins == 0) {
filter->func = bpf_jit_accept_all;
return (filter);
}
/* Create the binary */
if ((filter->func = bpf_jit_compile(fp, nins, &filter->size)) == NULL) {
free(filter);
return (NULL);
}
return (filter);
}
void
bpf_destroy_jit_filter(bpf_jit_filter *filter)
{
if (filter->func != bpf_jit_accept_all)
munmap(filter->func, filter->size);
free(filter);
}
#endif
static u_int
bpf_jit_accept_all(__unused u_char *p, __unused u_int wirelen,
__unused u_int buflen)
{
return ((u_int)-1);
}

View File

@ -1,81 +0,0 @@
/* $NetBSD: bpf_jit.h,v 1.2 2012/08/02 01:05:05 rmind Exp $ */
/*-
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/net/bpf_jitter.h,v 1.8 2009/11/20 18:49:20 jkim Exp $
*/
#ifndef _NET_BPF_JIT_H_
#define _NET_BPF_JIT_H_
struct bpf_insn;
/*
* Prototype of a filtering function created by the JIT compiler.
*
* The syntax and the meaning of the parameters is analogous to the one of
* bpf_filter(). Notice that the filter is not among the parameters because
* it is hardwired in the function.
*/
typedef u_int (*bpf_filter_func)(u_char *, u_int, u_int);
/* Structure describing a native filtering program by the JIT compiler. */
typedef struct bpf_jit_filter {
/* The native filtering binary, in the form of a bpf_filter_func. */
bpf_filter_func func;
size_t size;
} bpf_jit_filter;
/*
* BPF JIT compiler, builds a machine function from a BPF program.
*
* param fp The BPF pseudo-assembly filter that will be translated
* into native code.
* param nins Number of instructions of the input filter.
* return The bpf_jit_filter structure containing the native filtering
* binary.
*
* bpf_jit allocates the buffers for the new native filter and
* then translates the program pointed by fp calling bpf_jit_compile().
*/
bpf_jit_filter *bpf_jit(struct bpf_insn *, int);
/*
* Deletes a filtering function that was previously created by bpf_jit().
*
* param filter The filter to destroy.
*
* This function frees the variuos buffers (code, memory, etc.) associated
* with a filtering function.
*/
void bpf_destroy_jit_filter(bpf_jit_filter *);
#endif /* _NET_BPF_JIT_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: bpfdesc.h,v 1.34 2012/08/01 23:24:29 rmind Exp $ */
/* $NetBSD: bpfdesc.h,v 1.35 2012/09/27 18:28:56 alnsn Exp $ */
/*
* Copyright (c) 1990, 1991, 1993
@ -44,7 +44,6 @@
#include <sys/callout.h>
#include <sys/selinfo.h> /* for struct selinfo */
#include <net/if.h> /* for IFNAMSIZ */
#include <net/bpf_jit.h>
/*
* Descriptor associated with each open bpf file.
@ -71,7 +70,6 @@ struct bpf_d {
struct bpf_if * bd_bif; /* interface descriptor */
u_long bd_rtout; /* Read timeout in 'ticks' */
struct bpf_insn *bd_filter; /* filter code */
bpf_jit_filter *bd_bfilter; /* binary filter code */
u_long bd_rcount; /* number of packets received */
u_long bd_dcount; /* number of packets dropped */
u_long bd_ccount; /* number of packets captured */
@ -102,6 +100,7 @@ struct bpf_d {
#ifdef _LP64
int bd_compat32; /* 32-bit stream on LP64 system */
#endif
void *bd_dummy; /* to be replaced shortly with bd_jitcode */
};