The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/amd64/amd64/bpf_jit_machdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
    3  * Copyright (C) 2005-2008 Jung-uk Kim <jkim@FreeBSD.org>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  *
   10  * 1. Redistributions of source code must retain the above copyright
   11  * notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  * notice, this list of conditions and the following disclaimer in the
   14  * documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the Politecnico di Torino nor the names of its
   16  * contributors may be used to endorse or promote products derived from
   17  * this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #ifdef _KERNEL
   36 #include "opt_bpf.h"
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/socket.h>
   41 #include <sys/malloc.h>
   42 #include <net/if.h>
   43 #else
   44 #include <stdlib.h>
   45 #endif
   46 
   47 #include <sys/types.h>
   48 
   49 #include <net/bpf.h>
   50 #include <net/bpf_jitter.h>
   51 
   52 #include <amd64/amd64/bpf_jit_machdep.h>
   53 
   54 bpf_filter_func bpf_jit_compile(struct bpf_insn *, u_int, int *);
   55 
   56 /*
   57  * emit routine to update the jump table
   58  */
   59 static void
   60 emit_length(bpf_bin_stream *stream, __unused u_int value, u_int len)
   61 {
   62 
   63         (stream->refs)[stream->bpf_pc] += len;
   64         stream->cur_ip += len;
   65 }
   66 
   67 /*
   68  * emit routine to output the actual binary code
   69  */
   70 static void
   71 emit_code(bpf_bin_stream *stream, u_int value, u_int len)
   72 {
   73 
   74         switch (len) {
   75         case 1:
   76                 stream->ibuf[stream->cur_ip] = (u_char)value;
   77                 stream->cur_ip++;
   78                 break;
   79 
   80         case 2:
   81                 *((u_short *)(stream->ibuf + stream->cur_ip)) = (u_short)value;
   82                 stream->cur_ip += 2;
   83                 break;
   84 
   85         case 4:
   86                 *((u_int *)(stream->ibuf + stream->cur_ip)) = value;
   87                 stream->cur_ip += 4;
   88                 break;
   89         }
   90 
   91         return;
   92 }
   93 
   94 /*
   95  * Function that does the real stuff
   96  */
   97 bpf_filter_func
   98 bpf_jit_compile(struct bpf_insn *prog, u_int nins, int *mem)
   99 {
  100         struct bpf_insn *ins;
  101         u_int i, pass;
  102         bpf_bin_stream stream;
  103 
  104         /*
  105          * NOTE: do not modify the name of this variable, as it's used by
  106          * the macros to emit code.
  107          */
  108         emit_func emitm;
  109 
  110         /* Allocate the reference table for the jumps */
  111 #ifdef _KERNEL
  112         stream.refs = (u_int *)malloc((nins + 1) * sizeof(u_int),
  113             M_BPFJIT, M_NOWAIT);
  114 #else
  115         stream.refs = (u_int *)malloc((nins + 1) * sizeof(u_int));
  116 #endif
  117         if (stream.refs == NULL)
  118                 return (NULL);
  119 
  120         /* Reset the reference table */
  121         for (i = 0; i < nins + 1; i++)
  122                 stream.refs[i] = 0;
  123 
  124         stream.cur_ip = 0;
  125         stream.bpf_pc = 0;
  126 
  127         /*
  128          * the first pass will emit the lengths of the instructions
  129          * to create the reference table
  130          */
  131         emitm = emit_length;
  132 
  133         pass = 0;
  134         for (;;) {
  135                 ins = prog;
  136 
  137                 /* create the procedure header */
  138                 MOVrq2(RBX, R8);
  139                 MOVrq(RDI, RBX);
  140                 MOVrd2(ESI, R9D);
  141                 MOVrd(EDX, EDI);
  142 
  143                 for (i = 0; i < nins; i++) {
  144                         stream.bpf_pc++;
  145 
  146                         switch (ins->code) {
  147                         default:
  148 #ifdef _KERNEL
  149                                 return (NULL);
  150 #else
  151                                 abort();
  152 #endif
  153 
  154                         case BPF_RET|BPF_K:
  155                                 MOVid(ins->k, EAX);
  156                                 MOVrq3(R8, RBX);
  157                                 RET();
  158                                 break;
  159 
  160                         case BPF_RET|BPF_A:
  161                                 MOVrq3(R8, RBX);
  162                                 RET();
  163                                 break;
  164 
  165                         case BPF_LD|BPF_W|BPF_ABS:
  166                                 MOVid(ins->k, ESI);
  167                                 CMPrd(EDI, ESI);
  168                                 JAb(12);
  169                                 MOVrd(EDI, ECX);
  170                                 SUBrd(ESI, ECX);
  171                                 CMPid(sizeof(int32_t), ECX);
  172                                 JAEb(6);
  173                                 ZEROrd(EAX);
  174                                 MOVrq3(R8, RBX);
  175                                 RET();
  176                                 MOVobd(RBX, RSI, EAX);
  177                                 BSWAP(EAX);
  178                                 break;
  179 
  180                         case BPF_LD|BPF_H|BPF_ABS:
  181                                 ZEROrd(EAX);
  182                                 MOVid(ins->k, ESI);
  183                                 CMPrd(EDI, ESI);
  184                                 JAb(12);
  185                                 MOVrd(EDI, ECX);
  186                                 SUBrd(ESI, ECX);
  187                                 CMPid(sizeof(int16_t), ECX);
  188                                 JAEb(4);
  189                                 MOVrq3(R8, RBX);
  190                                 RET();
  191                                 MOVobw(RBX, RSI, AX);
  192                                 SWAP_AX();
  193                                 break;
  194 
  195                         case BPF_LD|BPF_B|BPF_ABS:
  196                                 ZEROrd(EAX);
  197                                 MOVid(ins->k, ESI);
  198                                 CMPrd(EDI, ESI);
  199                                 JBb(4);
  200                                 MOVrq3(R8, RBX);
  201                                 RET();
  202                                 MOVobb(RBX, RSI, AL);
  203                                 break;
  204 
  205                         case BPF_LD|BPF_W|BPF_LEN:
  206                                 MOVrd3(R9D, EAX);
  207                                 break;
  208 
  209                         case BPF_LDX|BPF_W|BPF_LEN:
  210                                 MOVrd3(R9D, EDX);
  211                                 break;
  212 
  213                         case BPF_LD|BPF_W|BPF_IND:
  214                                 CMPrd(EDI, EDX);
  215                                 JAb(27);
  216                                 MOVid(ins->k, ESI);
  217                                 MOVrd(EDI, ECX);
  218                                 SUBrd(EDX, ECX);
  219                                 CMPrd(ESI, ECX);
  220                                 JBb(14);
  221                                 ADDrd(EDX, ESI);
  222                                 MOVrd(EDI, ECX);
  223                                 SUBrd(ESI, ECX);
  224                                 CMPid(sizeof(int32_t), ECX);
  225                                 JAEb(6);
  226                                 ZEROrd(EAX);
  227                                 MOVrq3(R8, RBX);
  228                                 RET();
  229                                 MOVobd(RBX, RSI, EAX);
  230                                 BSWAP(EAX);
  231                                 break;
  232 
  233                         case BPF_LD|BPF_H|BPF_IND:
  234                                 ZEROrd(EAX);
  235                                 CMPrd(EDI, EDX);
  236                                 JAb(27);
  237                                 MOVid(ins->k, ESI);
  238                                 MOVrd(EDI, ECX);
  239                                 SUBrd(EDX, ECX);
  240                                 CMPrd(ESI, ECX);
  241                                 JBb(14);
  242                                 ADDrd(EDX, ESI);
  243                                 MOVrd(EDI, ECX);
  244                                 SUBrd(ESI, ECX);
  245                                 CMPid(sizeof(int16_t), ECX);
  246                                 JAEb(4);
  247                                 MOVrq3(R8, RBX);
  248                                 RET();
  249                                 MOVobw(RBX, RSI, AX);
  250                                 SWAP_AX();
  251                                 break;
  252 
  253                         case BPF_LD|BPF_B|BPF_IND:
  254                                 ZEROrd(EAX);
  255                                 CMPrd(EDI, EDX);
  256                                 JAEb(13);
  257                                 MOVid(ins->k, ESI);
  258                                 MOVrd(EDI, ECX);
  259                                 SUBrd(EDX, ECX);
  260                                 CMPrd(ESI, ECX);
  261                                 JAb(4);
  262                                 MOVrq3(R8, RBX);
  263                                 RET();
  264                                 ADDrd(EDX, ESI);
  265                                 MOVobb(RBX, RSI, AL);
  266                                 break;
  267 
  268                         case BPF_LDX|BPF_MSH|BPF_B:
  269                                 MOVid(ins->k, ESI);
  270                                 CMPrd(EDI, ESI);
  271                                 JBb(6);
  272                                 ZEROrd(EAX);
  273                                 MOVrq3(R8, RBX);
  274                                 RET();
  275                                 ZEROrd(EDX);
  276                                 MOVobb(RBX, RSI, DL);
  277                                 ANDib(0x0f, DL);
  278                                 SHLib(2, EDX);
  279                                 break;
  280 
  281                         case BPF_LD|BPF_IMM:
  282                                 MOVid(ins->k, EAX);
  283                                 break;
  284 
  285                         case BPF_LDX|BPF_IMM:
  286                                 MOVid(ins->k, EDX);
  287                                 break;
  288 
  289                         case BPF_LD|BPF_MEM:
  290                                 MOViq((uintptr_t)mem, RCX);
  291                                 MOVid(ins->k * 4, ESI);
  292                                 MOVobd(RCX, RSI, EAX);
  293                                 break;
  294 
  295                         case BPF_LDX|BPF_MEM:
  296                                 MOViq((uintptr_t)mem, RCX);
  297                                 MOVid(ins->k * 4, ESI);
  298                                 MOVobd(RCX, RSI, EDX);
  299                                 break;
  300 
  301                         case BPF_ST:
  302                                 /*
  303                                  * XXX this command and the following could
  304                                  * be optimized if the previous instruction
  305                                  * was already of this type
  306                                  */
  307                                 MOViq((uintptr_t)mem, RCX);
  308                                 MOVid(ins->k * 4, ESI);
  309                                 MOVomd(EAX, RCX, RSI);
  310                                 break;
  311 
  312                         case BPF_STX:
  313                                 MOViq((uintptr_t)mem, RCX);
  314                                 MOVid(ins->k * 4, ESI);
  315                                 MOVomd(EDX, RCX, RSI);
  316                                 break;
  317 
  318                         case BPF_JMP|BPF_JA:
  319                                 JMP(stream.refs[stream.bpf_pc + ins->k] -
  320                                     stream.refs[stream.bpf_pc]);
  321                                 break;
  322 
  323                         case BPF_JMP|BPF_JGT|BPF_K:
  324                                 if (ins->jt == 0 && ins->jf == 0)
  325                                         break;
  326                                 CMPid(ins->k, EAX);
  327                                 JCC(JA, JBE);
  328                                 break;
  329 
  330                         case BPF_JMP|BPF_JGE|BPF_K:
  331                                 if (ins->jt == 0 && ins->jf == 0)
  332                                         break;
  333                                 CMPid(ins->k, EAX);
  334                                 JCC(JAE, JB);
  335                                 break;
  336 
  337                         case BPF_JMP|BPF_JEQ|BPF_K:
  338                                 if (ins->jt == 0 && ins->jf == 0)
  339                                         break;
  340                                 CMPid(ins->k, EAX);
  341                                 JCC(JE, JNE);
  342                                 break;
  343 
  344                         case BPF_JMP|BPF_JSET|BPF_K:
  345                                 if (ins->jt == 0 && ins->jf == 0)
  346                                         break;
  347                                 TESTid(ins->k, EAX);
  348                                 JCC(JNE, JE);
  349                                 break;
  350 
  351                         case BPF_JMP|BPF_JGT|BPF_X:
  352                                 if (ins->jt == 0 && ins->jf == 0)
  353                                         break;
  354                                 CMPrd(EDX, EAX);
  355                                 JCC(JA, JBE);
  356                                 break;
  357 
  358                         case BPF_JMP|BPF_JGE|BPF_X:
  359                                 if (ins->jt == 0 && ins->jf == 0)
  360                                         break;
  361                                 CMPrd(EDX, EAX);
  362                                 JCC(JAE, JB);
  363                                 break;
  364 
  365                         case BPF_JMP|BPF_JEQ|BPF_X:
  366                                 if (ins->jt == 0 && ins->jf == 0)
  367                                         break;
  368                                 CMPrd(EDX, EAX);
  369                                 JCC(JE, JNE);
  370                                 break;
  371 
  372                         case BPF_JMP|BPF_JSET|BPF_X:
  373                                 if (ins->jt == 0 && ins->jf == 0)
  374                                         break;
  375                                 TESTrd(EDX, EAX);
  376                                 JCC(JNE, JE);
  377                                 break;
  378 
  379                         case BPF_ALU|BPF_ADD|BPF_X:
  380                                 ADDrd(EDX, EAX);
  381                                 break;
  382 
  383                         case BPF_ALU|BPF_SUB|BPF_X:
  384                                 SUBrd(EDX, EAX);
  385                                 break;
  386 
  387                         case BPF_ALU|BPF_MUL|BPF_X:
  388                                 MOVrd(EDX, ECX);
  389                                 MULrd(EDX);
  390                                 MOVrd(ECX, EDX);
  391                                 break;
  392 
  393                         case BPF_ALU|BPF_DIV|BPF_X:
  394                                 TESTrd(EDX, EDX);
  395                                 JNEb(6);
  396                                 ZEROrd(EAX);
  397                                 MOVrq3(R8, RBX);
  398                                 RET();
  399                                 MOVrd(EDX, ECX);
  400                                 ZEROrd(EDX);
  401                                 DIVrd(ECX);
  402                                 MOVrd(ECX, EDX);
  403                                 break;
  404 
  405                         case BPF_ALU|BPF_AND|BPF_X:
  406                                 ANDrd(EDX, EAX);
  407                                 break;
  408 
  409                         case BPF_ALU|BPF_OR|BPF_X:
  410                                 ORrd(EDX, EAX);
  411                                 break;
  412 
  413                         case BPF_ALU|BPF_LSH|BPF_X:
  414                                 MOVrd(EDX, ECX);
  415                                 SHL_CLrb(EAX);
  416                                 break;
  417 
  418                         case BPF_ALU|BPF_RSH|BPF_X:
  419                                 MOVrd(EDX, ECX);
  420                                 SHR_CLrb(EAX);
  421                                 break;
  422 
  423                         case BPF_ALU|BPF_ADD|BPF_K:
  424                                 ADD_EAXi(ins->k);
  425                                 break;
  426 
  427                         case BPF_ALU|BPF_SUB|BPF_K:
  428                                 SUB_EAXi(ins->k);
  429                                 break;
  430 
  431                         case BPF_ALU|BPF_MUL|BPF_K:
  432                                 MOVrd(EDX, ECX);
  433                                 MOVid(ins->k, EDX);
  434                                 MULrd(EDX);
  435                                 MOVrd(ECX, EDX);
  436                                 break;
  437 
  438                         case BPF_ALU|BPF_DIV|BPF_K:
  439                                 MOVrd(EDX, ECX);
  440                                 ZEROrd(EDX);
  441                                 MOVid(ins->k, ESI);
  442                                 DIVrd(ESI);
  443                                 MOVrd(ECX, EDX);
  444                                 break;
  445 
  446                         case BPF_ALU|BPF_AND|BPF_K:
  447                                 ANDid(ins->k, EAX);
  448                                 break;
  449 
  450                         case BPF_ALU|BPF_OR|BPF_K:
  451                                 ORid(ins->k, EAX);
  452                                 break;
  453 
  454                         case BPF_ALU|BPF_LSH|BPF_K:
  455                                 SHLib((ins->k) & 0xff, EAX);
  456                                 break;
  457 
  458                         case BPF_ALU|BPF_RSH|BPF_K:
  459                                 SHRib((ins->k) & 0xff, EAX);
  460                                 break;
  461 
  462                         case BPF_ALU|BPF_NEG:
  463                                 NEGd(EAX);
  464                                 break;
  465 
  466                         case BPF_MISC|BPF_TAX:
  467                                 MOVrd(EAX, EDX);
  468                                 break;
  469 
  470                         case BPF_MISC|BPF_TXA:
  471                                 MOVrd(EDX, EAX);
  472                                 break;
  473                         }
  474                         ins++;
  475                 }
  476 
  477                 pass++;
  478                 if (pass == 2)
  479                         break;
  480 
  481 #ifdef _KERNEL
  482                 stream.ibuf = (char *)malloc(stream.cur_ip, M_BPFJIT, M_NOWAIT);
  483                 if (stream.ibuf == NULL) {
  484                         free(stream.refs, M_BPFJIT);
  485                         return (NULL);
  486                 }
  487 #else
  488                 stream.ibuf = (char *)malloc(stream.cur_ip);
  489                 if (stream.ibuf == NULL) {
  490                         free(stream.refs);
  491                         return (NULL);
  492                 }
  493 #endif
  494 
  495                 /*
  496                  * modify the reference table to contain the offsets and
  497                  * not the lengths of the instructions
  498                  */
  499                 for (i = 1; i < nins + 1; i++)
  500                         stream.refs[i] += stream.refs[i - 1];
  501 
  502                 /* Reset the counters */
  503                 stream.cur_ip = 0;
  504                 stream.bpf_pc = 0;
  505 
  506                 /* the second pass creates the actual code */
  507                 emitm = emit_code;
  508         }
  509 
  510         /*
  511          * the reference table is needed only during compilation,
  512          * now we can free it
  513          */
  514 #ifdef _KERNEL
  515         free(stream.refs, M_BPFJIT);
  516 #else
  517         free(stream.refs);
  518 #endif
  519 
  520         return ((bpf_filter_func)stream.ibuf);
  521 }

Cache object: 65725640eb39497c72cefc2d09138d66


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.