LCOV - code coverage report
Current view: top level - lib/bpf - bpf_jit_x86.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 446 454 98.2 %
Date: 2025-03-01 20:23:48 Functions: 39 39 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 426 448 95.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <errno.h>
       6                 :            : #include <stdint.h>
       7                 :            : 
       8                 :            : #include <rte_common.h>
       9                 :            : #include <rte_log.h>
      10                 :            : #include <rte_debug.h>
      11                 :            : 
      12                 :            : #include "bpf_impl.h"
      13                 :            : 
      14                 :            : #define GET_BPF_OP(op)  (BPF_OP(op) >> 4)
      15                 :            : 
      16                 :            : enum {
      17                 :            :         RAX = 0,  /* scratch, return value */
      18                 :            :         RCX = 1,  /* scratch, 4th arg */
      19                 :            :         RDX = 2,  /* scratch, 3rd arg */
      20                 :            :         RBX = 3,  /* callee saved */
      21                 :            :         RSP = 4,  /* stack pointer */
      22                 :            :         RBP = 5,  /* frame pointer, callee saved */
      23                 :            :         RSI = 6,  /* scratch, 2nd arg */
      24                 :            :         RDI = 7,  /* scratch, 1st arg */
      25                 :            :         R8  = 8,  /* scratch, 5th arg */
      26                 :            :         R9  = 9,  /* scratch, 6th arg */
      27                 :            :         R10 = 10, /* scratch */
      28                 :            :         R11 = 11, /* scratch */
      29                 :            :         R12 = 12, /* callee saved */
      30                 :            :         R13 = 13, /* callee saved */
      31                 :            :         R14 = 14, /* callee saved */
      32                 :            :         R15 = 15, /* callee saved */
      33                 :            : };
      34                 :            : 
      35                 :            : #define IS_EXT_REG(r)   ((r) >= R8)
      36                 :            : 
      37                 :            : enum {
      38                 :            :         REX_PREFIX = 0x40, /* fixed value 0100 */
      39                 :            :         REX_W = 0x8,       /* 64bit operand size */
      40                 :            :         REX_R = 0x4,       /* extension of the ModRM.reg field */
      41                 :            :         REX_X = 0x2,       /* extension of the SIB.index field */
      42                 :            :         REX_B = 0x1,       /* extension of the ModRM.rm field */
      43                 :            : };
      44                 :            : 
      45                 :            : enum {
      46                 :            :         MOD_INDIRECT = 0,
      47                 :            :         MOD_IDISP8 = 1,
      48                 :            :         MOD_IDISP32 = 2,
      49                 :            :         MOD_DIRECT = 3,
      50                 :            : };
      51                 :            : 
      52                 :            : enum {
      53                 :            :         SIB_SCALE_1 = 0,
      54                 :            :         SIB_SCALE_2 = 1,
      55                 :            :         SIB_SCALE_4 = 2,
      56                 :            :         SIB_SCALE_8 = 3,
      57                 :            : };
      58                 :            : 
      59                 :            : /*
      60                 :            :  * eBPF to x86_64 register mappings.
      61                 :            :  */
      62                 :            : static const uint32_t ebpf2x86[] = {
      63                 :            :         [EBPF_REG_0] = RAX,
      64                 :            :         [EBPF_REG_1] = RDI,
      65                 :            :         [EBPF_REG_2] = RSI,
      66                 :            :         [EBPF_REG_3] = RDX,
      67                 :            :         [EBPF_REG_4] = RCX,
      68                 :            :         [EBPF_REG_5] = R8,
      69                 :            :         [EBPF_REG_6] = RBX,
      70                 :            :         [EBPF_REG_7] = R13,
      71                 :            :         [EBPF_REG_8] = R14,
      72                 :            :         [EBPF_REG_9] = R15,
      73                 :            :         [EBPF_REG_10] = RBP,
      74                 :            : };
      75                 :            : 
      76                 :            : /*
      77                 :            :  * r10 and r11 are used as a scratch temporary registers.
      78                 :            :  */
      79                 :            : enum {
      80                 :            :         REG_DIV_IMM = R9,
      81                 :            :         REG_TMP0 = R11,
      82                 :            :         REG_TMP1 = R10,
      83                 :            : };
      84                 :            : 
      85                 :            : /* LD_ABS/LD_IMM offsets */
      86                 :            : enum {
      87                 :            :         LDMB_FSP_OFS, /* fast-path */
      88                 :            :         LDMB_SLP_OFS, /* slow-path */
      89                 :            :         LDMB_FIN_OFS, /* final part */
      90                 :            :         LDMB_OFS_NUM
      91                 :            : };
      92                 :            : 
      93                 :            : /*
      94                 :            :  * callee saved registers list.
      95                 :            :  * keep RBP as the last one.
      96                 :            :  */
      97                 :            : static const uint32_t save_regs[] = {RBX, R12, R13, R14, R15, RBP};
      98                 :            : 
      99                 :            : struct bpf_jit_state {
     100                 :            :         uint32_t idx;
     101                 :            :         size_t sz;
     102                 :            :         struct {
     103                 :            :                 uint32_t num;
     104                 :            :                 int32_t off;
     105                 :            :         } exit;
     106                 :            :         struct {
     107                 :            :                 uint32_t stack_ofs;
     108                 :            :         } ldmb;
     109                 :            :         uint32_t reguse;
     110                 :            :         int32_t *off;
     111                 :            :         uint8_t *ins;
     112                 :            : };
     113                 :            : 
     114                 :            : #define INUSE(v, r)     (((v) >> (r)) & 1)
     115                 :            : #define USED(v, r)      ((v) |= 1 << (r))
     116                 :            : 
     117                 :            : union bpf_jit_imm {
     118                 :            :         uint32_t u32;
     119                 :            :         uint8_t u8[4];
     120                 :            : };
     121                 :            : 
     122                 :            : /*
     123                 :            :  * In many cases for imm8 we can produce shorter code.
     124                 :            :  */
     125                 :            : static size_t
     126                 :            : imm_size(int32_t v)
     127                 :            : {
     128   [ +  +  +  -  :      21356 :         if (v == (int8_t)v)
             +  -  +  - ]
     129                 :      28985 :                 return sizeof(int8_t);
     130                 :            :         return sizeof(int32_t);
     131                 :            : }
     132                 :            : 
     133                 :            : static void
     134                 :            : emit_bytes(struct bpf_jit_state *st, const uint8_t ins[], uint32_t sz)
     135                 :            : {
     136                 :            :         uint32_t i;
     137                 :            : 
     138   [ +  +  +  +  :      38441 :         if (st->ins != NULL) {
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  + ]
     139   [ +  +  +  +  :      66958 :                 for (i = 0; i != sz; i++)
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                +  +  + ]
     140                 :      49212 :                         st->ins[st->sz + i] = ins[i];
     141                 :            :         }
     142   [ +  +  +  +  :       8226 :         st->sz += sz;
             +  +  +  - ]
     143                 :      50527 : }
     144                 :            : 
     145                 :            : static void
     146                 :            : emit_imm(struct bpf_jit_state *st, const uint32_t imm, uint32_t sz)
     147                 :            : {
     148                 :            :         union bpf_jit_imm v;
     149                 :            : 
     150   [ +  +  +  +  :      16568 :         v.u32 = imm;
          +  +  +  +  +  
                      + ]
     151                 :            :         emit_bytes(st, v.u8, sz);
     152                 :       2467 : }
     153                 :            : 
     154                 :            : /*
     155                 :            :  * emit REX byte
     156                 :            :  */
     157                 :            : static void
     158                 :      44413 : emit_rex(struct bpf_jit_state *st, uint32_t op, uint32_t reg, uint32_t rm)
     159                 :            : {
     160                 :            :         uint8_t rex;
     161                 :            : 
     162                 :            :         /* mark operand registers as used*/
     163                 :      44413 :         USED(st->reguse, reg);
     164                 :      44413 :         USED(st->reguse, rm);
     165                 :            : 
     166                 :      44413 :         rex = 0;
     167         [ +  + ]:      44413 :         if (BPF_CLASS(op) == EBPF_ALU64 ||
     168         [ +  + ]:      14388 :                         op == (BPF_ST | BPF_MEM | EBPF_DW) ||
     169                 :            :                         op == (BPF_STX | BPF_MEM | EBPF_DW) ||
     170                 :      13872 :                         op == (BPF_STX | EBPF_XADD | EBPF_DW) ||
     171         [ +  + ]:      13872 :                         op == (BPF_LD | BPF_IMM | EBPF_DW) ||
     172         [ +  + ]:      13844 :                         (BPF_CLASS(op) == BPF_LDX &&
     173                 :      10322 :                         BPF_MODE(op) == BPF_MEM &&
     174         [ +  + ]:      10322 :                         BPF_SIZE(op) != BPF_W))
     175                 :      39399 :                 rex |= REX_W;
     176                 :            : 
     177         [ +  + ]:      44413 :         if (IS_EXT_REG(reg))
     178                 :       1126 :                 rex |= REX_R;
     179                 :            : 
     180         [ +  + ]:      44413 :         if (IS_EXT_REG(rm))
     181                 :        642 :                 rex |= REX_B;
     182                 :            : 
     183                 :            :         /* store using SIL, DIL */
     184   [ +  +  +  + ]:      44413 :         if (op == (BPF_STX | BPF_MEM | BPF_B) && (reg == RDI || reg == RSI))
     185                 :          3 :                 rex |= REX_PREFIX;
     186                 :            : 
     187         [ +  + ]:      44413 :         if (rex != 0) {
     188         [ +  + ]:      39613 :                 rex |= REX_PREFIX;
     189                 :            :                 emit_bytes(st, &rex, sizeof(rex));
     190                 :            :         }
     191                 :      44413 : }
     192                 :            : 
     193                 :            : /*
     194                 :            :  * emit MODRegRM byte
     195                 :            :  */
     196                 :            : static void
     197                 :            : emit_modregrm(struct bpf_jit_state *st, uint32_t mod, uint32_t reg, uint32_t rm)
     198                 :            : {
     199                 :            :         uint8_t v;
     200                 :            : 
     201   [ +  +  +  +  :      41938 :         v = mod << 6 | (reg & 7) << 3 | (rm & 7);
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  + ]
     202                 :            :         emit_bytes(st, &v, sizeof(v));
     203                 :       5736 : }
     204                 :            : 
     205                 :            : /*
     206                 :            :  * emit SIB byte
     207                 :            :  */
     208                 :            : static void
     209                 :            : emit_sib(struct bpf_jit_state *st, uint32_t scale, uint32_t idx, uint32_t base)
     210                 :            : {
     211                 :            :         uint8_t v;
     212                 :            : 
     213   [ +  +  +  + ]:        962 :         v = scale << 6 | (idx & 7) << 3 | (base & 7);
     214                 :            :         emit_bytes(st, &v, sizeof(v));
     215                 :        962 : }
     216                 :            : 
     217                 :            : /*
     218                 :            :  * emit OPCODE+REGIDX byte
     219                 :            :  */
     220                 :            : static void
     221                 :            : emit_opcode(struct bpf_jit_state *st, uint8_t ops, uint32_t reg)
     222                 :            : {
     223                 :            :         uint8_t v;
     224                 :            : 
     225         [ +  + ]:       2443 :         v = ops | (reg & 7);
     226                 :            :         emit_bytes(st, &v, sizeof(v));
     227                 :            : }
     228                 :            : 
     229                 :            : 
     230                 :            : /*
     231                 :            :  * emit xchg %<sreg>, %<dreg>
     232                 :            :  */
     233                 :            : static void
     234                 :         12 : emit_xchg_reg(struct bpf_jit_state *st, uint32_t sreg, uint32_t dreg)
     235                 :            : {
     236                 :         12 :         const uint8_t ops = 0x87;
     237                 :            : 
     238                 :         12 :         emit_rex(st, EBPF_ALU64, sreg, dreg);
     239                 :            :         emit_bytes(st, &ops, sizeof(ops));
     240                 :            :         emit_modregrm(st, MOD_DIRECT, sreg, dreg);
     241                 :         12 : }
     242                 :            : 
     243                 :            : /*
     244                 :            :  * emit neg %<dreg>
     245                 :            :  */
     246                 :            : static void
     247                 :          6 : emit_neg(struct bpf_jit_state *st, uint32_t op, uint32_t dreg)
     248                 :            : {
     249                 :          6 :         const uint8_t ops = 0xF7;
     250                 :            :         const uint8_t mods = 3;
     251                 :            : 
     252                 :          6 :         emit_rex(st, op, 0, dreg);
     253                 :            :         emit_bytes(st, &ops, sizeof(ops));
     254                 :            :         emit_modregrm(st, MOD_DIRECT, mods, dreg);
     255                 :          6 : }
     256                 :            : 
     257                 :            : /*
     258                 :            :  * emit mov %<sreg>, %<dreg>
     259                 :            :  */
     260                 :            : static void
     261                 :       5763 : emit_mov_reg(struct bpf_jit_state *st, uint32_t op, uint32_t sreg,
     262                 :            :         uint32_t dreg)
     263                 :            : {
     264                 :       5763 :         const uint8_t ops = 0x89;
     265                 :            : 
     266                 :            :         /* if operands are 32-bit, then it can be used to clear upper 32-bit */
     267   [ +  +  +  + ]:       5763 :         if (sreg != dreg || BPF_CLASS(op) == BPF_ALU) {
     268                 :       5736 :                 emit_rex(st, op, sreg, dreg);
     269                 :            :                 emit_bytes(st, &ops, sizeof(ops));
     270                 :            :                 emit_modregrm(st, MOD_DIRECT, sreg, dreg);
     271                 :            :         }
     272                 :       5763 : }
     273                 :            : 
     274                 :            : /*
     275                 :            :  * emit movzwl %<sreg>, %<dreg>
     276                 :            :  */
     277                 :            : static void
     278                 :        578 : emit_movzwl(struct bpf_jit_state *st, uint32_t sreg, uint32_t dreg)
     279                 :            : {
     280                 :            :         static const uint8_t ops[] = {0x0F, 0xB7};
     281                 :            : 
     282                 :        578 :         emit_rex(st, BPF_ALU, sreg, dreg);
     283                 :            :         emit_bytes(st, ops, sizeof(ops));
     284                 :            :         emit_modregrm(st, MOD_DIRECT, sreg, dreg);
     285                 :        578 : }
     286                 :            : 
     287                 :            : /*
     288                 :            :  * emit ror <imm8>, %<dreg>
     289                 :            :  */
     290                 :            : static void
     291                 :        575 : emit_ror_imm(struct bpf_jit_state *st, uint32_t dreg, uint32_t imm)
     292                 :            : {
     293                 :        575 :         const uint8_t prfx = 0x66;
     294         [ +  + ]:        575 :         const uint8_t ops = 0xC1;
     295                 :            :         const uint8_t mods = 1;
     296                 :            : 
     297                 :            :         emit_bytes(st, &prfx, sizeof(prfx));
     298                 :        575 :         emit_rex(st, BPF_ALU, 0, dreg);
     299                 :            :         emit_bytes(st, &ops, sizeof(ops));
     300                 :            :         emit_modregrm(st, MOD_DIRECT, mods, dreg);
     301         [ +  + ]:        575 :         emit_imm(st, imm, imm_size(imm));
     302                 :        575 : }
     303                 :            : 
     304                 :            : /*
     305                 :            :  * emit bswap %<dreg>
     306                 :            :  */
     307                 :            : static void
     308                 :       1418 : emit_be2le_48(struct bpf_jit_state *st, uint32_t dreg, uint32_t imm)
     309                 :            : {
     310                 :            :         uint32_t rop;
     311                 :            : 
     312                 :       1418 :         const uint8_t ops = 0x0F;
     313                 :            :         const uint8_t mods = 1;
     314                 :            : 
     315         [ +  + ]:       1418 :         rop = (imm == 64) ? EBPF_ALU64 : BPF_ALU;
     316                 :       1418 :         emit_rex(st, rop, 0, dreg);
     317                 :            :         emit_bytes(st, &ops, sizeof(ops));
     318                 :            :         emit_modregrm(st, MOD_DIRECT, mods, dreg);
     319                 :       1418 : }
     320                 :            : 
     321                 :            : static void
     322                 :       1993 : emit_be2le(struct bpf_jit_state *st, uint32_t dreg, uint32_t imm)
     323                 :            : {
     324         [ +  + ]:       1993 :         if (imm == 16) {
     325                 :        575 :                 emit_ror_imm(st, dreg, 8);
     326                 :        575 :                 emit_movzwl(st, dreg, dreg);
     327                 :            :         } else
     328                 :       1418 :                 emit_be2le_48(st, dreg, imm);
     329                 :       1993 : }
     330                 :            : 
     331                 :            : /*
     332                 :            :  * In general it is NOP for x86.
     333                 :            :  * Just clear the upper bits.
     334                 :            :  */
     335                 :            : static void
     336                 :          9 : emit_le2be(struct bpf_jit_state *st, uint32_t dreg, uint32_t imm)
     337                 :            : {
     338         [ +  + ]:          9 :         if (imm == 16)
     339                 :          3 :                 emit_movzwl(st, dreg, dreg);
     340         [ +  + ]:          6 :         else if (imm == 32)
     341                 :          3 :                 emit_mov_reg(st, BPF_ALU | EBPF_MOV | BPF_X, dreg, dreg);
     342                 :          9 : }
     343                 :            : 
     344                 :            : /*
     345                 :            :  * emit one of:
     346                 :            :  *   add <imm>, %<dreg>
     347                 :            :  *   and <imm>, %<dreg>
     348                 :            :  *   or  <imm>, %<dreg>
     349                 :            :  *   sub <imm>, %<dreg>
     350                 :            :  *   xor <imm>, %<dreg>
     351                 :            :  */
     352                 :            : static void
     353                 :       3073 : emit_alu_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg, uint32_t imm)
     354                 :            : {
     355                 :            :         uint8_t mod, opcode;
     356                 :            :         uint32_t bop, imsz;
     357                 :            : 
     358                 :            :         const uint8_t op8 = 0x83;
     359                 :            :         const uint8_t op32 = 0x81;
     360                 :            :         static const uint8_t mods[] = {
     361                 :            :                 [GET_BPF_OP(BPF_ADD)] = 0,
     362                 :            :                 [GET_BPF_OP(BPF_AND)] = 4,
     363                 :            :                 [GET_BPF_OP(BPF_OR)] =  1,
     364                 :            :                 [GET_BPF_OP(BPF_SUB)] = 5,
     365                 :            :                 [GET_BPF_OP(BPF_XOR)] = 6,
     366                 :            :         };
     367                 :            : 
     368                 :       3073 :         bop = GET_BPF_OP(op);
     369         [ +  + ]:       3073 :         mod = mods[bop];
     370                 :            : 
     371                 :       3073 :         imsz = imm_size(imm);
     372         [ +  + ]:       3073 :         opcode = (imsz == 1) ? op8 : op32;
     373                 :            : 
     374                 :       3073 :         emit_rex(st, op, 0, dreg);
     375                 :            :         emit_bytes(st, &opcode, sizeof(opcode));
     376                 :            :         emit_modregrm(st, MOD_DIRECT, mod, dreg);
     377                 :            :         emit_imm(st, imm, imsz);
     378                 :       3073 : }
     379                 :            : 
     380                 :            : /*
     381                 :            :  * emit one of:
     382                 :            :  *   add %<sreg>, %<dreg>
     383                 :            :  *   and %<sreg>, %<dreg>
     384                 :            :  *   or  %<sreg>, %<dreg>
     385                 :            :  *   sub %<sreg>, %<dreg>
     386                 :            :  *   xor %<sreg>, %<dreg>
     387                 :            :  */
     388                 :            : static void
     389                 :       8125 : emit_alu_reg(struct bpf_jit_state *st, uint32_t op, uint32_t sreg,
     390                 :            :         uint32_t dreg)
     391                 :            : {
     392                 :            :         uint32_t bop;
     393                 :            : 
     394                 :            :         static const uint8_t ops[] = {
     395                 :            :                 [GET_BPF_OP(BPF_ADD)] = 0x01,
     396                 :            :                 [GET_BPF_OP(BPF_AND)] = 0x21,
     397                 :            :                 [GET_BPF_OP(BPF_OR)] =  0x09,
     398                 :            :                 [GET_BPF_OP(BPF_SUB)] = 0x29,
     399                 :            :                 [GET_BPF_OP(BPF_XOR)] = 0x31,
     400                 :            :         };
     401                 :            : 
     402                 :       8125 :         bop = GET_BPF_OP(op);
     403                 :            : 
     404                 :       8125 :         emit_rex(st, op, sreg, dreg);
     405         [ +  + ]:       8125 :         emit_bytes(st, &ops[bop], sizeof(ops[bop]));
     406                 :            :         emit_modregrm(st, MOD_DIRECT, sreg, dreg);
     407                 :       8125 : }
     408                 :            : 
     409                 :            : static void
     410                 :        138 : emit_shift(struct bpf_jit_state *st, uint32_t op, uint32_t dreg)
     411                 :            : {
     412                 :            :         uint8_t mod;
     413                 :            :         uint32_t bop, opx;
     414                 :            : 
     415                 :            :         static const uint8_t ops[] = {0xC1, 0xD3};
     416                 :            :         static const uint8_t mods[] = {
     417                 :            :                 [GET_BPF_OP(BPF_LSH)] = 4,
     418                 :            :                 [GET_BPF_OP(BPF_RSH)] = 5,
     419                 :            :                 [GET_BPF_OP(EBPF_ARSH)] = 7,
     420                 :            :         };
     421                 :            : 
     422                 :        138 :         bop = GET_BPF_OP(op);
     423                 :        138 :         mod = mods[bop];
     424                 :        138 :         opx = (BPF_SRC(op) == BPF_X);
     425                 :            : 
     426                 :        138 :         emit_rex(st, op, 0, dreg);
     427         [ +  + ]:        138 :         emit_bytes(st, &ops[opx], sizeof(ops[opx]));
     428                 :            :         emit_modregrm(st, MOD_DIRECT, mod, dreg);
     429                 :        138 : }
     430                 :            : 
     431                 :            : /*
     432                 :            :  * emit one of:
     433                 :            :  *   shl <imm>, %<dreg>
     434                 :            :  *   shr <imm>, %<dreg>
     435                 :            :  *   sar <imm>, %<dreg>
     436                 :            :  */
     437                 :            : static void
     438                 :        126 : emit_shift_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg,
     439                 :            :         uint32_t imm)
     440                 :            : {
     441                 :        126 :         emit_shift(st, op, dreg);
     442         [ +  + ]:        126 :         emit_imm(st, imm, imm_size(imm));
     443                 :        126 : }
     444                 :            : 
     445                 :            : /*
     446                 :            :  * emit one of:
     447                 :            :  *   shl %<dreg>
     448                 :            :  *   shr %<dreg>
     449                 :            :  *   sar %<dreg>
     450                 :            :  * note that rcx is implicitly used as a source register, so few extra
     451                 :            :  * instructions for register spillage might be necessary.
     452                 :            :  */
     453                 :            : static void
     454                 :         12 : emit_shift_reg(struct bpf_jit_state *st, uint32_t op, uint32_t sreg,
     455                 :            :         uint32_t dreg)
     456                 :            : {
     457         [ +  + ]:         12 :         if (sreg != RCX)
     458                 :          6 :                 emit_xchg_reg(st, RCX, sreg);
     459                 :            : 
     460         [ +  + ]:         21 :         emit_shift(st, op, (dreg == RCX) ? sreg : dreg);
     461                 :            : 
     462         [ +  + ]:         12 :         if (sreg != RCX)
     463                 :          6 :                 emit_xchg_reg(st, RCX, sreg);
     464                 :         12 : }
     465                 :            : 
     466                 :            : /*
     467                 :            :  * emit mov <imm>, %<dreg>
     468                 :            :  */
     469                 :            : static void
     470                 :       5344 : emit_mov_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg, uint32_t imm)
     471                 :            : {
     472                 :       5344 :         const uint8_t ops = 0xC7;
     473                 :            : 
     474         [ +  + ]:       5344 :         if (imm == 0) {
     475                 :            :                 /* replace 'mov 0, %<dst>' with 'xor %<dst>, %<dst>' */
     476                 :        220 :                 op = BPF_CLASS(op) | BPF_XOR | BPF_X;
     477                 :        240 :                 emit_alu_reg(st, op, dreg, dreg);
     478                 :        220 :                 return;
     479                 :            :         }
     480                 :            : 
     481                 :       5124 :         emit_rex(st, op, 0, dreg);
     482                 :            :         emit_bytes(st, &ops, sizeof(ops));
     483                 :            :         emit_modregrm(st, MOD_DIRECT, 0, dreg);
     484                 :            :         emit_imm(st, imm, sizeof(imm));
     485                 :            : }
     486                 :            : 
     487                 :            : /*
     488                 :            :  * emit mov <imm64>, %<dreg>
     489                 :            :  */
     490                 :            : static void
     491                 :       2443 : emit_ld_imm64(struct bpf_jit_state *st, uint32_t dreg, uint32_t imm0,
     492                 :            :         uint32_t imm1)
     493                 :            : {
     494                 :            :         uint32_t op;
     495                 :            : 
     496                 :            :         const uint8_t ops = 0xB8;
     497                 :            : 
     498         [ +  + ]:       2443 :         op = (imm1 == 0) ? BPF_ALU : EBPF_ALU64;
     499                 :            : 
     500                 :       2443 :         emit_rex(st, op, 0, dreg);
     501                 :            :         emit_opcode(st, ops, dreg);
     502                 :            : 
     503                 :            :         emit_imm(st, imm0, sizeof(imm0));
     504         [ +  + ]:       2443 :         if (imm1 != 0)
     505                 :            :                 emit_imm(st, imm1, sizeof(imm1));
     506                 :       2443 : }
     507                 :            : 
     508                 :            : /*
     509                 :            :  * note that rax:rdx are implicitly used as source/destination registers,
     510                 :            :  * so some reg spillage is necessary.
     511                 :            :  * emit:
     512                 :            :  * mov %rax, %r11
     513                 :            :  * mov %rdx, %r10
     514                 :            :  * mov %<dreg>, %rax
     515                 :            :  * either:
     516                 :            :  *   mov %<sreg>, %rdx
     517                 :            :  * OR
     518                 :            :  *   mov <imm>, %rdx
     519                 :            :  * mul %rdx
     520                 :            :  * mov %r10, %rdx
     521                 :            :  * mov %rax, %<dreg>
     522                 :            :  * mov %r11, %rax
     523                 :            :  */
     524                 :            : static void
     525                 :         32 : emit_mul(struct bpf_jit_state *st, uint32_t op, uint32_t sreg, uint32_t dreg,
     526                 :            :         uint32_t imm)
     527                 :            : {
     528                 :         32 :         const uint8_t ops = 0xF7;
     529                 :            :         const uint8_t mods = 4;
     530                 :            : 
     531                 :            :         /* save rax & rdx */
     532                 :         32 :         emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, RAX, REG_TMP0);
     533                 :         32 :         emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, RDX, REG_TMP1);
     534                 :            : 
     535                 :            :         /* rax = dreg */
     536                 :         32 :         emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, dreg, RAX);
     537                 :            : 
     538         [ +  + ]:         32 :         if (BPF_SRC(op) == BPF_X)
     539                 :            :                 /* rdx = sreg */
     540         [ -  + ]:         14 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X,
     541                 :            :                         sreg == RAX ? REG_TMP0 : sreg, RDX);
     542                 :            :         else
     543                 :            :                 /* rdx = imm */
     544                 :         18 :                 emit_mov_imm(st, EBPF_ALU64 | EBPF_MOV | BPF_K, RDX, imm);
     545                 :            : 
     546                 :         32 :         emit_rex(st, op, RAX, RDX);
     547                 :            :         emit_bytes(st, &ops, sizeof(ops));
     548                 :            :         emit_modregrm(st, MOD_DIRECT, mods, RDX);
     549                 :            : 
     550         [ +  + ]:         32 :         if (dreg != RDX)
     551                 :            :                 /* restore rdx */
     552                 :         29 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, REG_TMP1, RDX);
     553                 :            : 
     554         [ +  + ]:         32 :         if (dreg != RAX) {
     555                 :            :                 /* dreg = rax */
     556                 :         12 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, RAX, dreg);
     557                 :            :                 /* restore rax */
     558                 :         12 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, REG_TMP0, RAX);
     559                 :            :         }
     560                 :         32 : }
     561                 :            : 
     562                 :            : /*
     563                 :            :  * emit mov <ofs>(%<sreg>), %<dreg>
     564                 :            :  * note that for non 64-bit ops, higher bits have to be cleared.
     565                 :            :  */
     566                 :            : static void
     567                 :      10322 : emit_ld_reg(struct bpf_jit_state *st, uint32_t op, uint32_t sreg, uint32_t dreg,
     568                 :            :         int32_t ofs)
     569                 :            : {
     570                 :            :         uint32_t mods, opsz;
     571                 :      10322 :         const uint8_t op32 = 0x8B;
     572                 :      10322 :         const uint8_t op16[] = {0x0F, 0xB7};
     573                 :      10322 :         const uint8_t op8[] = {0x0F, 0xB6};
     574                 :            : 
     575                 :      10322 :         emit_rex(st, op, dreg, sreg);
     576                 :            : 
     577                 :      10322 :         opsz = BPF_SIZE(op);
     578         [ +  + ]:      10322 :         if (opsz == BPF_B)
     579                 :            :                 emit_bytes(st, op8, sizeof(op8));
     580         [ +  + ]:       9872 :         else if (opsz == BPF_H)
     581                 :            :                 emit_bytes(st, op16, sizeof(op16));
     582                 :            :         else
     583                 :            :                 emit_bytes(st, &op32, sizeof(op32));
     584                 :            : 
     585                 :            :         mods = (imm_size(ofs) == 1) ? MOD_IDISP8 : MOD_IDISP32;
     586                 :            : 
     587                 :            :         emit_modregrm(st, mods, dreg, sreg);
     588         [ +  + ]:      10322 :         if (sreg == RSP || sreg == R12)
     589                 :            :                 emit_sib(st, SIB_SCALE_1, sreg, sreg);
     590         [ +  + ]:      10322 :         emit_imm(st, ofs, imm_size(ofs));
     591                 :      10322 : }
     592                 :            : 
     593                 :            : /*
     594                 :            :  * emit one of:
     595                 :            :  *   mov %<sreg>, <ofs>(%<dreg>)
     596                 :            :  *   mov <imm>, <ofs>(%<dreg>)
     597                 :            :  */
     598                 :            : static void
     599                 :        586 : emit_st_common(struct bpf_jit_state *st, uint32_t op, uint32_t sreg,
     600                 :            :         uint32_t dreg, uint32_t imm, int32_t ofs)
     601                 :            : {
     602                 :            :         uint32_t mods, imsz, opsz, opx;
     603                 :        586 :         const uint8_t prfx16 = 0x66;
     604                 :            : 
     605                 :            :         /* 8 bit instruction opcodes */
     606                 :            :         static const uint8_t op8[] = {0xC6, 0x88};
     607                 :            : 
     608                 :            :         /* 16/32/64 bit instruction opcodes */
     609                 :            :         static const uint8_t ops[] = {0xC7, 0x89};
     610                 :            : 
     611                 :            :         /* is the instruction has immediate value or src reg? */
     612                 :        586 :         opx = (BPF_CLASS(op) == BPF_STX);
     613                 :            : 
     614                 :        586 :         opsz = BPF_SIZE(op);
     615         [ +  + ]:        586 :         if (opsz == BPF_H)
     616                 :            :                 emit_bytes(st, &prfx16, sizeof(prfx16));
     617                 :            : 
     618                 :        586 :         emit_rex(st, op, sreg, dreg);
     619                 :            : 
     620         [ +  + ]:        586 :         if (opsz == BPF_B)
     621         [ +  + ]:         30 :                 emit_bytes(st, &op8[opx], sizeof(op8[opx]));
     622                 :            :         else
     623         [ +  + ]:        556 :                 emit_bytes(st, &ops[opx], sizeof(ops[opx]));
     624                 :            : 
     625                 :        586 :         imsz = imm_size(ofs);
     626         [ +  + ]:        586 :         mods = (imsz == 1) ? MOD_IDISP8 : MOD_IDISP32;
     627                 :            : 
     628                 :            :         emit_modregrm(st, mods, sreg, dreg);
     629                 :            : 
     630         [ +  + ]:        586 :         if (dreg == RSP || dreg == R12)
     631                 :            :                 emit_sib(st, SIB_SCALE_1, dreg, dreg);
     632                 :            : 
     633         [ +  + ]:        586 :         emit_imm(st, ofs, imsz);
     634                 :            : 
     635         [ +  + ]:        586 :         if (opx == 0) {
     636         [ +  + ]:         28 :                 imsz = RTE_MIN(bpf_size(opsz), sizeof(imm));
     637                 :            :                 emit_imm(st, imm, imsz);
     638                 :            :         }
     639                 :        586 : }
     640                 :            : 
     641                 :            : static void
     642                 :            : emit_st_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg, uint32_t imm,
     643                 :            :         int32_t ofs)
     644                 :            : {
     645                 :         28 :         emit_st_common(st, op, 0, dreg, imm, ofs);
     646                 :         28 : }
     647                 :            : 
     648                 :            : static void
     649                 :            : emit_st_reg(struct bpf_jit_state *st, uint32_t op, uint32_t sreg, uint32_t dreg,
     650                 :            :         int32_t ofs)
     651                 :            : {
     652                 :        421 :         emit_st_common(st, op, sreg, dreg, 0, ofs);
     653                 :        137 : }
     654                 :            : 
     655                 :            : /*
     656                 :            :  * emit lock add %<sreg>, <ofs>(%<dreg>)
     657                 :            :  */
     658                 :            : static void
     659                 :         56 : emit_st_xadd(struct bpf_jit_state *st, uint32_t op, uint32_t sreg,
     660                 :            :         uint32_t dreg, int32_t ofs)
     661                 :            : {
     662                 :            :         uint32_t imsz, mods;
     663                 :            : 
     664                 :         56 :         const uint8_t lck = 0xF0; /* lock prefix */
     665         [ +  - ]:         56 :         const uint8_t ops = 0x01; /* add opcode */
     666                 :            : 
     667                 :         56 :         imsz = imm_size(ofs);
     668         [ -  + ]:         56 :         mods = (imsz == 1) ? MOD_IDISP8 : MOD_IDISP32;
     669                 :            : 
     670                 :            :         emit_bytes(st, &lck, sizeof(lck));
     671                 :         56 :         emit_rex(st, op, sreg, dreg);
     672                 :            :         emit_bytes(st, &ops, sizeof(ops));
     673                 :            :         emit_modregrm(st, mods, sreg, dreg);
     674         [ +  + ]:         56 :         emit_imm(st, ofs, imsz);
     675                 :         56 : }
     676                 :            : 
     677                 :            : /*
     678                 :            :  * emit:
     679                 :            :  *    mov <imm64>, (%rax)
     680                 :            :  *    call *%rax
     681                 :            :  */
     682                 :            : static void
     683                 :       2423 : emit_call(struct bpf_jit_state *st, uintptr_t trg)
     684                 :            : {
     685                 :       2423 :         const uint8_t ops = 0xFF;
     686                 :            :         const uint8_t mods = 2;
     687                 :            : 
     688                 :       2423 :         emit_ld_imm64(st, RAX, trg, trg >> 32);
     689                 :            :         emit_bytes(st, &ops, sizeof(ops));
     690                 :            :         emit_modregrm(st, MOD_DIRECT, mods, RAX);
     691                 :       2423 : }
     692                 :            : 
     693                 :            : /*
     694                 :            :  * emit jmp <ofs>
     695                 :            :  * where 'ofs' is the target offset for the native code.
     696                 :            :  */
     697                 :            : static void
     698                 :       2651 : emit_abs_jmp(struct bpf_jit_state *st, int32_t ofs)
     699                 :            : {
     700                 :            :         int32_t joff;
     701                 :            :         uint32_t imsz;
     702                 :            : 
     703                 :       2651 :         const uint8_t op8 = 0xEB;
     704                 :       2651 :         const uint8_t op32 = 0xE9;
     705                 :            : 
     706                 :            :         const int32_t sz8 = sizeof(op8) + sizeof(uint8_t);
     707                 :            :         const int32_t sz32 = sizeof(op32) + sizeof(uint32_t);
     708                 :            : 
     709                 :            :         /* max possible jmp instruction size */
     710                 :            :         const int32_t iszm = RTE_MAX(sz8, sz32);
     711                 :            : 
     712         [ +  + ]:       2651 :         joff = ofs - st->sz;
     713         [ +  + ]:       2651 :         imsz = RTE_MAX(imm_size(joff), imm_size(joff + iszm));
     714                 :            : 
     715         [ +  + ]:       2651 :         if (imsz == 1) {
     716                 :            :                 emit_bytes(st, &op8, sizeof(op8));
     717                 :       2573 :                 joff -= sz8;
     718                 :            :         } else {
     719                 :            :                 emit_bytes(st, &op32, sizeof(op32));
     720                 :         78 :                 joff -= sz32;
     721                 :            :         }
     722                 :            : 
     723         [ +  + ]:       2651 :         emit_imm(st, joff, imsz);
     724                 :       2651 : }
     725                 :            : 
     726                 :            : /*
     727                 :            :  * emit jmp <ofs>
     728                 :            :  * where 'ofs' is the target offset for the BPF bytecode.
     729                 :            :  */
     730                 :            : static void
     731                 :            : emit_jmp(struct bpf_jit_state *st, int32_t ofs)
     732                 :            : {
     733                 :        119 :         emit_abs_jmp(st, st->off[st->idx + ofs]);
     734                 :        119 : }
     735                 :            : 
     736                 :            : /*
     737                 :            :  * emit one of:
     738                 :            :  *    cmovz %<sreg>, <%dreg>
     739                 :            :  *    cmovne %<sreg>, <%dreg>
     740                 :            :  *    cmova %<sreg>, <%dreg>
     741                 :            :  *    cmovb %<sreg>, <%dreg>
     742                 :            :  *    cmovae %<sreg>, <%dreg>
     743                 :            :  *    cmovbe %<sreg>, <%dreg>
     744                 :            :  *    cmovg %<sreg>, <%dreg>
     745                 :            :  *    cmovl %<sreg>, <%dreg>
     746                 :            :  *    cmovge %<sreg>, <%dreg>
     747                 :            :  *    cmovle %<sreg>, <%dreg>
     748                 :            :  */
     749                 :            : static void
     750                 :         12 : emit_movcc_reg(struct bpf_jit_state *st, uint32_t op, uint32_t sreg,
     751                 :            :         uint32_t dreg)
     752                 :            : {
     753                 :            :         uint32_t bop;
     754                 :            : 
     755                 :            :         static const uint8_t ops[][2] = {
     756                 :            :                 [GET_BPF_OP(BPF_JEQ)] = {0x0F, 0x44},  /* CMOVZ */
     757                 :            :                 [GET_BPF_OP(EBPF_JNE)] = {0x0F, 0x45},  /* CMOVNE */
     758                 :            :                 [GET_BPF_OP(BPF_JGT)] = {0x0F, 0x47},  /* CMOVA */
     759                 :            :                 [GET_BPF_OP(EBPF_JLT)] = {0x0F, 0x42},  /* CMOVB */
     760                 :            :                 [GET_BPF_OP(BPF_JGE)] = {0x0F, 0x43},  /* CMOVAE */
     761                 :            :                 [GET_BPF_OP(EBPF_JLE)] = {0x0F, 0x46},  /* CMOVBE */
     762                 :            :                 [GET_BPF_OP(EBPF_JSGT)] = {0x0F, 0x4F}, /* CMOVG */
     763                 :            :                 [GET_BPF_OP(EBPF_JSLT)] = {0x0F, 0x4C}, /* CMOVL */
     764                 :            :                 [GET_BPF_OP(EBPF_JSGE)] = {0x0F, 0x4D}, /* CMOVGE */
     765                 :            :                 [GET_BPF_OP(EBPF_JSLE)] = {0x0F, 0x4E}, /* CMOVLE */
     766                 :            :                 [GET_BPF_OP(BPF_JSET)] = {0x0F, 0x45}, /* CMOVNE */
     767                 :            :         };
     768                 :            : 
     769                 :         12 :         bop = GET_BPF_OP(op);
     770                 :            : 
     771                 :         12 :         emit_rex(st, op, dreg, sreg);
     772         [ +  + ]:         12 :         emit_bytes(st, ops[bop], sizeof(ops[bop]));
     773                 :            :         emit_modregrm(st, MOD_DIRECT, dreg, sreg);
     774                 :         12 : }
     775                 :            : 
     776                 :            : /*
     777                 :            :  * emit one of:
     778                 :            :  * je <ofs>
     779                 :            :  * jne <ofs>
     780                 :            :  * ja <ofs>
     781                 :            :  * jb <ofs>
     782                 :            :  * jae <ofs>
     783                 :            :  * jbe <ofs>
     784                 :            :  * jg <ofs>
     785                 :            :  * jl <ofs>
     786                 :            :  * jge <ofs>
     787                 :            :  * jle <ofs>
     788                 :            :  * where 'ofs' is the target offset for the native code.
     789                 :            :  */
     790                 :            : static void
     791                 :       6157 : emit_abs_jcc(struct bpf_jit_state *st, uint32_t op, int32_t ofs)
     792                 :            : {
     793                 :            :         uint32_t bop, imsz;
     794                 :            :         int32_t joff;
     795                 :            : 
     796                 :            :         static const uint8_t op8[] = {
     797                 :            :                 [GET_BPF_OP(BPF_JEQ)] = 0x74,  /* JE */
     798                 :            :                 [GET_BPF_OP(EBPF_JNE)] = 0x75,  /* JNE */
     799                 :            :                 [GET_BPF_OP(BPF_JGT)] = 0x77,  /* JA */
     800                 :            :                 [GET_BPF_OP(EBPF_JLT)] = 0x72,  /* JB */
     801                 :            :                 [GET_BPF_OP(BPF_JGE)] = 0x73,  /* JAE */
     802                 :            :                 [GET_BPF_OP(EBPF_JLE)] = 0x76,  /* JBE */
     803                 :            :                 [GET_BPF_OP(EBPF_JSGT)] = 0x7F, /* JG */
     804                 :            :                 [GET_BPF_OP(EBPF_JSLT)] = 0x7C, /* JL */
     805                 :            :                 [GET_BPF_OP(EBPF_JSGE)] = 0x7D, /*JGE */
     806                 :            :                 [GET_BPF_OP(EBPF_JSLE)] = 0x7E, /* JLE */
     807                 :            :                 [GET_BPF_OP(BPF_JSET)] = 0x75, /*JNE */
     808                 :            :         };
     809                 :            : 
     810                 :            :         static const uint8_t op32[][2] = {
     811                 :            :                 [GET_BPF_OP(BPF_JEQ)] = {0x0F, 0x84},  /* JE */
     812                 :            :                 [GET_BPF_OP(EBPF_JNE)] = {0x0F, 0x85},  /* JNE */
     813                 :            :                 [GET_BPF_OP(BPF_JGT)] = {0x0F, 0x87},  /* JA */
     814                 :            :                 [GET_BPF_OP(EBPF_JLT)] = {0x0F, 0x82},  /* JB */
     815                 :            :                 [GET_BPF_OP(BPF_JGE)] = {0x0F, 0x83},  /* JAE */
     816                 :            :                 [GET_BPF_OP(EBPF_JLE)] = {0x0F, 0x86},  /* JBE */
     817                 :            :                 [GET_BPF_OP(EBPF_JSGT)] = {0x0F, 0x8F}, /* JG */
     818                 :            :                 [GET_BPF_OP(EBPF_JSLT)] = {0x0F, 0x8C}, /* JL */
     819                 :            :                 [GET_BPF_OP(EBPF_JSGE)] = {0x0F, 0x8D}, /*JGE */
     820                 :            :                 [GET_BPF_OP(EBPF_JSLE)] = {0x0F, 0x8E}, /* JLE */
     821                 :            :                 [GET_BPF_OP(BPF_JSET)] = {0x0F, 0x85}, /*JNE */
     822                 :            :         };
     823                 :            : 
     824                 :            :         const int32_t sz8 = sizeof(op8[0]) + sizeof(uint8_t);
     825                 :            :         const int32_t sz32 = sizeof(op32[0]) + sizeof(uint32_t);
     826                 :            : 
     827                 :            :         /* max possible jcc instruction size */
     828                 :            :         const int32_t iszm = RTE_MAX(sz8, sz32);
     829                 :            : 
     830         [ +  + ]:       6157 :         joff = ofs - st->sz;
     831         [ +  + ]:       6157 :         imsz = RTE_MAX(imm_size(joff), imm_size(joff + iszm));
     832                 :            : 
     833                 :       6157 :         bop = GET_BPF_OP(op);
     834                 :            : 
     835         [ +  + ]:       6157 :         if (imsz == 1) {
     836         [ +  + ]:       3118 :                 emit_bytes(st, &op8[bop], sizeof(op8[bop]));
     837                 :       3118 :                 joff -= sz8;
     838                 :            :         } else {
     839         [ +  + ]:       3039 :                 emit_bytes(st, op32[bop], sizeof(op32[bop]));
     840                 :       3039 :                 joff -= sz32;
     841                 :            :         }
     842                 :            : 
     843         [ +  + ]:       6157 :         emit_imm(st, joff, imsz);
     844                 :       6157 : }
     845                 :            : 
     846                 :            : /*
     847                 :            :  * emit one of:
     848                 :            :  * je <ofs>
     849                 :            :  * jne <ofs>
     850                 :            :  * ja <ofs>
     851                 :            :  * jb <ofs>
     852                 :            :  * jae <ofs>
     853                 :            :  * jbe <ofs>
     854                 :            :  * jg <ofs>
     855                 :            :  * jl <ofs>
     856                 :            :  * jge <ofs>
     857                 :            :  * jle <ofs>
     858                 :            :  * where 'ofs' is the target offset for the BPF bytecode.
     859                 :            :  */
     860                 :            : static void
     861                 :            : emit_jcc(struct bpf_jit_state *st, uint32_t op, int32_t ofs)
     862                 :            : {
     863                 :       1353 :         emit_abs_jcc(st, op, st->off[st->idx + ofs]);
     864                 :            : }
     865                 :            : 
     866                 :            : 
     867                 :            : /*
     868                 :            :  * emit cmp <imm>, %<dreg>
     869                 :            :  */
     870                 :            : static void
     871         [ +  + ]:       3489 : emit_cmp_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg, uint32_t imm)
     872                 :            : {
     873                 :            :         uint8_t ops;
     874                 :            :         uint32_t imsz;
     875                 :            : 
     876                 :            :         const uint8_t op8 = 0x83;
     877                 :            :         const uint8_t op32 = 0x81;
     878                 :            :         const uint8_t mods = 7;
     879                 :            : 
     880                 :       3489 :         imsz = imm_size(imm);
     881         [ +  + ]:       3489 :         ops = (imsz == 1) ? op8 : op32;
     882                 :            : 
     883                 :       3489 :         emit_rex(st, op, 0, dreg);
     884                 :            :         emit_bytes(st, &ops, sizeof(ops));
     885                 :            :         emit_modregrm(st, MOD_DIRECT, mods, dreg);
     886                 :            :         emit_imm(st, imm, imsz);
     887                 :       3489 : }
     888                 :            : 
     889                 :            : /*
     890                 :            :  * emit test <imm>, %<dreg>
     891                 :            :  */
     892                 :            : static void
     893                 :         72 : emit_tst_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg, uint32_t imm)
     894                 :            : {
     895                 :         72 :         const uint8_t ops = 0xF7;
     896                 :            :         const uint8_t mods = 0;
     897                 :            : 
     898                 :         72 :         emit_rex(st, op, 0, dreg);
     899                 :            :         emit_bytes(st, &ops, sizeof(ops));
     900                 :            :         emit_modregrm(st, MOD_DIRECT, mods, dreg);
     901         [ +  + ]:         72 :         emit_imm(st, imm, imm_size(imm));
     902                 :         72 : }
     903                 :            : 
     904                 :            : static void
     905                 :       1165 : emit_jcc_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg,
     906                 :            :         uint32_t imm, int32_t ofs)
     907                 :            : {
     908         [ +  + ]:       1165 :         if (BPF_OP(op) == BPF_JSET)
     909                 :         72 :                 emit_tst_imm(st, EBPF_ALU64, dreg, imm);
     910                 :            :         else
     911                 :       1093 :                 emit_cmp_imm(st, EBPF_ALU64, dreg, imm);
     912                 :            : 
     913                 :            :         emit_jcc(st, op, ofs);
     914                 :       1165 : }
     915                 :            : 
     916                 :            : /*
     917                 :            :  * emit test %<sreg>, %<dreg>
     918                 :            :  */
     919                 :            : static void
     920                 :       2412 : emit_tst_reg(struct bpf_jit_state *st, uint32_t op, uint32_t sreg,
     921                 :            :         uint32_t dreg)
     922                 :            : {
     923                 :       2412 :         const uint8_t ops = 0x85;
     924                 :            : 
     925                 :       2412 :         emit_rex(st, op, sreg, dreg);
     926                 :            :         emit_bytes(st, &ops, sizeof(ops));
     927                 :            :         emit_modregrm(st, MOD_DIRECT, sreg, dreg);
     928                 :       2412 : }
     929                 :            : 
     930                 :            : /*
     931                 :            :  * emit cmp %<sreg>, %<dreg>
     932                 :            :  */
     933                 :            : static void
     934                 :        184 : emit_cmp_reg(struct bpf_jit_state *st, uint32_t op, uint32_t sreg,
     935                 :            :         uint32_t dreg)
     936                 :            : {
     937                 :        184 :         const uint8_t ops = 0x39;
     938                 :            : 
     939                 :        184 :         emit_rex(st, op, sreg, dreg);
     940                 :            :         emit_bytes(st, &ops, sizeof(ops));
     941                 :            :         emit_modregrm(st, MOD_DIRECT, sreg, dreg);
     942                 :            : 
     943                 :        184 : }
     944                 :            : 
     945                 :            : static void
     946                 :        188 : emit_jcc_reg(struct bpf_jit_state *st, uint32_t op, uint32_t sreg,
     947                 :            :         uint32_t dreg, int32_t ofs)
     948                 :            : {
     949         [ +  + ]:        188 :         if (BPF_OP(op) == BPF_JSET)
     950                 :          4 :                 emit_tst_reg(st, EBPF_ALU64, sreg, dreg);
     951                 :            :         else
     952                 :        184 :                 emit_cmp_reg(st, EBPF_ALU64, sreg, dreg);
     953                 :            : 
     954                 :            :         emit_jcc(st, op, ofs);
     955                 :        188 : }
     956                 :            : 
     957                 :            : /*
     958                 :            :  * note that rax:rdx are implicitly used as source/destination registers,
     959                 :            :  * so some reg spillage is necessary.
     960                 :            :  * emit:
     961                 :            :  * mov %rax, %r11
     962                 :            :  * mov %rdx, %r10
     963                 :            :  * mov %<dreg>, %rax
     964                 :            :  * xor %rdx, %rdx
     965                 :            :  * for divisor as immediate value:
     966                 :            :  *   mov <imm>, %r9
     967                 :            :  * div %<divisor_reg>
     968                 :            :  * mov %r10, %rdx
     969                 :            :  * mov %rax, %<dreg>
     970                 :            :  * mov %r11, %rax
     971                 :            :  * either:
     972                 :            :  *   mov %rax, %<dreg>
     973                 :            :  * OR
     974                 :            :  *   mov %rdx, %<dreg>
     975                 :            :  * mov %r11, %rax
     976                 :            :  * mov %r10, %rdx
     977                 :            :  */
     978                 :            : static void
     979                 :         20 : emit_div(struct bpf_jit_state *st, uint32_t op, uint32_t sreg, uint32_t dreg,
     980                 :            :         uint32_t imm)
     981                 :            : {
     982                 :            :         uint32_t sr;
     983                 :            : 
     984                 :         20 :         const uint8_t ops = 0xF7;
     985                 :            :         const uint8_t mods = 6;
     986                 :            : 
     987         [ +  + ]:         20 :         if (BPF_SRC(op) == BPF_X) {
     988                 :            : 
     989                 :            :                 /* check that src divisor is not zero */
     990                 :         12 :                 emit_tst_reg(st, BPF_CLASS(op), sreg, sreg);
     991                 :            : 
     992                 :            :                 /* exit with return value zero */
     993                 :         12 :                 emit_movcc_reg(st, BPF_CLASS(op) | BPF_JEQ | BPF_X, sreg, RAX);
     994                 :         12 :                 emit_abs_jcc(st, BPF_JMP | BPF_JEQ | BPF_K, st->exit.off);
     995                 :            :         }
     996                 :            : 
     997                 :            :         /* save rax & rdx */
     998         [ +  - ]:         20 :         if (dreg != RAX)
     999                 :         20 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, RAX, REG_TMP0);
    1000         [ +  + ]:         20 :         if (dreg != RDX)
    1001                 :         16 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, RDX, REG_TMP1);
    1002                 :            : 
    1003                 :            :         /* fill rax & rdx */
    1004                 :         20 :         emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, dreg, RAX);
    1005                 :            :         emit_mov_imm(st, EBPF_ALU64 | EBPF_MOV | BPF_K, RDX, 0);
    1006                 :            : 
    1007         [ +  + ]:         20 :         if (BPF_SRC(op) == BPF_X) {
    1008                 :            :                 sr = sreg;
    1009         [ +  - ]:         12 :                 if (sr == RAX)
    1010                 :            :                         sr = REG_TMP0;
    1011         [ +  + ]:         12 :                 else if (sr == RDX)
    1012                 :            :                         sr = REG_TMP1;
    1013                 :            :         } else {
    1014                 :            :                 sr = REG_DIV_IMM;
    1015                 :          8 :                 emit_mov_imm(st, EBPF_ALU64 | EBPF_MOV | BPF_K, sr, imm);
    1016                 :            :         }
    1017                 :            : 
    1018                 :         20 :         emit_rex(st, op, 0, sr);
    1019                 :            :         emit_bytes(st, &ops, sizeof(ops));
    1020                 :            :         emit_modregrm(st, MOD_DIRECT, mods, sr);
    1021                 :            : 
    1022         [ +  + ]:         20 :         if (BPF_OP(op) == BPF_DIV)
    1023                 :         12 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, RAX, dreg);
    1024                 :            :         else
    1025                 :          8 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, RDX, dreg);
    1026                 :            : 
    1027         [ +  - ]:         20 :         if (dreg != RAX)
    1028                 :         20 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, REG_TMP0, RAX);
    1029         [ +  + ]:         20 :         if (dreg != RDX)
    1030                 :         16 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, REG_TMP1, RDX);
    1031                 :         20 : }
    1032                 :            : 
    1033                 :            : /*
    1034                 :            :  * helper function, used by emit_ld_mbuf().
    1035                 :            :  * generates code for 'fast_path':
    1036                 :            :  * calculate load offset and check is it inside first packet segment.
    1037                 :            :  */
    1038                 :            : static void
    1039                 :       2396 : emit_ldmb_fast_path(struct bpf_jit_state *st, const uint32_t rg[EBPF_REG_7],
    1040                 :            :         uint32_t sreg, uint32_t mode, uint32_t sz, uint32_t imm,
    1041                 :            :         const int32_t ofs[LDMB_OFS_NUM])
    1042                 :            : {
    1043                 :            :         /* make R2 contain *off* value */
    1044                 :            : 
    1045         [ +  - ]:       2396 :         if (sreg != rg[EBPF_REG_2]) {
    1046                 :       2396 :                 emit_mov_imm(st, EBPF_ALU64 | EBPF_MOV | BPF_K,
    1047                 :            :                         rg[EBPF_REG_2], imm);
    1048         [ +  + ]:       2396 :                 if (mode == BPF_IND)
    1049                 :        300 :                         emit_alu_reg(st, EBPF_ALU64 | BPF_ADD | BPF_X,
    1050                 :            :                                 sreg, rg[EBPF_REG_2]);
    1051                 :            :         } else
    1052                 :            :                 /* BPF_IND with sreg == R2 */
    1053                 :          0 :                 emit_alu_imm(st, EBPF_ALU64 | BPF_ADD | BPF_K,
    1054                 :            :                         rg[EBPF_REG_2], imm);
    1055                 :            : 
    1056                 :            :         /* R3 = mbuf->data_len */
    1057                 :       2396 :         emit_ld_reg(st, BPF_LDX | BPF_MEM | BPF_H,
    1058                 :            :                 rg[EBPF_REG_6], rg[EBPF_REG_3],
    1059                 :            :                 offsetof(struct rte_mbuf, data_len));
    1060                 :            : 
    1061                 :            :         /* R3 = R3 - R2 */
    1062                 :       2396 :         emit_alu_reg(st, EBPF_ALU64 | BPF_SUB | BPF_X,
    1063                 :            :                 rg[EBPF_REG_2], rg[EBPF_REG_3]);
    1064                 :            : 
    1065                 :            :         /* JSLT R3, <sz> <slow_path> */
    1066                 :       2396 :         emit_cmp_imm(st, EBPF_ALU64, rg[EBPF_REG_3], sz);
    1067                 :       2396 :         emit_abs_jcc(st, BPF_JMP | EBPF_JSLT | BPF_K, ofs[LDMB_SLP_OFS]);
    1068                 :            : 
    1069                 :            :         /* R3 = mbuf->data_off */
    1070                 :       2396 :         emit_ld_reg(st, BPF_LDX | BPF_MEM | BPF_H,
    1071                 :            :                 rg[EBPF_REG_6], rg[EBPF_REG_3],
    1072                 :            :                 offsetof(struct rte_mbuf, data_off));
    1073                 :            : 
    1074                 :            :         /* R0 = mbuf->buf_addr */
    1075                 :       2396 :         emit_ld_reg(st, BPF_LDX | BPF_MEM | EBPF_DW,
    1076                 :            :                 rg[EBPF_REG_6], rg[EBPF_REG_0],
    1077                 :            :                 offsetof(struct rte_mbuf, buf_addr));
    1078                 :            : 
    1079                 :            :         /* R0 = R0 + R3 */
    1080                 :       2396 :         emit_alu_reg(st, EBPF_ALU64 | BPF_ADD | BPF_X,
    1081                 :            :                 rg[EBPF_REG_3], rg[EBPF_REG_0]);
    1082                 :            : 
    1083                 :            :         /* R0 = R0 + R2 */
    1084                 :       2396 :         emit_alu_reg(st, EBPF_ALU64 | BPF_ADD | BPF_X,
    1085                 :            :                 rg[EBPF_REG_2], rg[EBPF_REG_0]);
    1086                 :            : 
    1087                 :            :         /* JMP <fin_part> */
    1088                 :       2396 :         emit_abs_jmp(st, ofs[LDMB_FIN_OFS]);
    1089                 :       2396 : }
    1090                 :            : 
    1091                 :            : /*
    1092                 :            :  * helper function, used by emit_ld_mbuf().
    1093                 :            :  * generates code for 'slow_path':
    1094                 :            :  * call __rte_pktmbuf_read() and check return value.
    1095                 :            :  */
    1096                 :            : static void
    1097                 :       2396 : emit_ldmb_slow_path(struct bpf_jit_state *st, const uint32_t rg[EBPF_REG_7],
    1098                 :            :         uint32_t sz)
    1099                 :            : {
    1100                 :            :         /* make R3 contain *len* value (1/2/4) */
    1101                 :            : 
    1102                 :       2396 :         emit_mov_imm(st, EBPF_ALU64 | EBPF_MOV | BPF_K, rg[EBPF_REG_3], sz);
    1103                 :            : 
    1104                 :            :         /* make R4 contain (RBP - ldmb.stack_ofs) */
    1105                 :            : 
    1106                 :       2396 :         emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, RBP, rg[EBPF_REG_4]);
    1107                 :       2396 :         emit_alu_imm(st, EBPF_ALU64 | BPF_SUB | BPF_K, rg[EBPF_REG_4],
    1108                 :            :                 st->ldmb.stack_ofs);
    1109                 :            : 
    1110                 :            :         /* make R1 contain mbuf ptr */
    1111                 :            : 
    1112                 :       2396 :         emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X,
    1113                 :            :                 rg[EBPF_REG_6], rg[EBPF_REG_1]);
    1114                 :            : 
    1115                 :            :         /* call rte_pktmbuf_read */
    1116                 :       2396 :         emit_call(st, (uintptr_t)__rte_pktmbuf_read);
    1117                 :            : 
    1118                 :            :         /* check that return value (R0) is not zero */
    1119                 :       2396 :         emit_tst_reg(st, EBPF_ALU64, rg[EBPF_REG_0], rg[EBPF_REG_0]);
    1120                 :       2396 :         emit_abs_jcc(st, BPF_JMP | BPF_JEQ | BPF_K, st->exit.off);
    1121                 :       2396 : }
    1122                 :            : 
    1123                 :            : /*
    1124                 :            :  * helper function, used by emit_ld_mbuf().
    1125                 :            :  * generates final part of code for BPF_ABS/BPF_IND load:
    1126                 :            :  * perform data load and endianness conversion.
    1127                 :            :  * expects dreg to contain valid data pointer.
    1128                 :            :  */
    1129                 :            : static void
    1130                 :       2396 : emit_ldmb_fin(struct bpf_jit_state *st, uint32_t dreg, uint32_t opsz,
    1131                 :            :         uint32_t sz)
    1132                 :            : {
    1133                 :       2396 :         emit_ld_reg(st, BPF_LDX | BPF_MEM | opsz, dreg, dreg, 0);
    1134         [ +  + ]:       2396 :         if (sz != sizeof(uint8_t))
    1135                 :       1976 :                 emit_be2le(st, dreg, sz * CHAR_BIT);
    1136                 :       2396 : }
    1137                 :            : 
    1138                 :            : /*
    1139                 :            :  * emit code for BPF_ABS/BPF_IND load.
    1140                 :            :  * generates the following construction:
    1141                 :            :  * fast_path:
    1142                 :            :  *   off = ins->sreg + ins->imm
    1143                 :            :  *   if (mbuf->data_len - off < ins->opsz)
    1144                 :            :  *      goto slow_path;
    1145                 :            :  *   ptr = mbuf->buf_addr + mbuf->data_off + off;
    1146                 :            :  *   goto fin_part;
    1147                 :            :  * slow_path:
    1148                 :            :  *   typeof(ins->opsz) buf; //allocate space on the stack
    1149                 :            :  *   ptr = __rte_pktmbuf_read(mbuf, off, ins->opsz, &buf);
    1150                 :            :  *   if (ptr == NULL)
    1151                 :            :  *      goto exit_label;
    1152                 :            :  * fin_part:
    1153                 :            :  *   res = *(typeof(ins->opsz))ptr;
    1154                 :            :  *   res = bswap(res);
    1155                 :            :  */
    1156                 :            : static void
    1157                 :       1198 : emit_ld_mbuf(struct bpf_jit_state *st, uint32_t op, uint32_t sreg, uint32_t imm)
    1158                 :            : {
    1159                 :            :         uint32_t i, mode, opsz, sz;
    1160                 :            :         uint32_t rg[EBPF_REG_7];
    1161                 :            :         int32_t ofs[LDMB_OFS_NUM];
    1162                 :            : 
    1163                 :       1198 :         mode = BPF_MODE(op);
    1164         [ +  + ]:       1198 :         opsz = BPF_SIZE(op);
    1165                 :       1198 :         sz = bpf_size(opsz);
    1166                 :            : 
    1167         [ +  + ]:       9584 :         for (i = 0; i != RTE_DIM(rg); i++)
    1168                 :       8386 :                 rg[i] = ebpf2x86[i];
    1169                 :            : 
    1170                 :            :         /* fill with fake offsets */
    1171         [ +  + ]:       4792 :         for (i = 0; i != RTE_DIM(ofs); i++)
    1172                 :       3594 :                 ofs[i] = st->sz + INT8_MAX;
    1173                 :            : 
    1174                 :            :         /* dry run first to calculate jump offsets */
    1175                 :            : 
    1176                 :       1198 :         ofs[LDMB_FSP_OFS] = st->sz;
    1177                 :       1198 :         emit_ldmb_fast_path(st, rg, sreg, mode, sz, imm, ofs);
    1178                 :       1198 :         ofs[LDMB_SLP_OFS] = st->sz;
    1179                 :       1198 :         emit_ldmb_slow_path(st, rg, sz);
    1180                 :       1198 :         ofs[LDMB_FIN_OFS] = st->sz;
    1181                 :       1198 :         emit_ldmb_fin(st, rg[EBPF_REG_0], opsz, sz);
    1182                 :            : 
    1183         [ -  + ]:       1198 :         RTE_VERIFY(ofs[LDMB_FIN_OFS] - ofs[LDMB_FSP_OFS] <= INT8_MAX);
    1184                 :            : 
    1185                 :            :         /* reset dry-run code and do a proper run */
    1186                 :            : 
    1187                 :       1198 :         st->sz = ofs[LDMB_FSP_OFS];
    1188                 :       1198 :         emit_ldmb_fast_path(st, rg, sreg, mode, sz, imm, ofs);
    1189                 :       1198 :         emit_ldmb_slow_path(st, rg, sz);
    1190                 :       1198 :         emit_ldmb_fin(st, rg[EBPF_REG_0], opsz, sz);
    1191                 :       1198 : }
    1192                 :            : 
    1193                 :            : static void
    1194                 :        196 : emit_prolog(struct bpf_jit_state *st, int32_t stack_size)
    1195                 :            : {
    1196                 :            :         uint32_t i;
    1197                 :            :         int32_t spil, ofs;
    1198                 :            : 
    1199                 :            :         spil = 0;
    1200         [ +  + ]:       1372 :         for (i = 0; i != RTE_DIM(save_regs); i++)
    1201                 :       1176 :                 spil += INUSE(st->reguse, save_regs[i]);
    1202                 :            : 
    1203                 :            :         /* we can avoid touching the stack at all */
    1204         [ +  + ]:        196 :         if (spil == 0)
    1205                 :            :                 return;
    1206                 :            : 
    1207                 :            : 
    1208                 :        123 :         emit_alu_imm(st, EBPF_ALU64 | BPF_SUB | BPF_K, RSP,
    1209                 :            :                 spil * sizeof(uint64_t));
    1210                 :            : 
    1211                 :            :         ofs = 0;
    1212         [ +  + ]:        861 :         for (i = 0; i != RTE_DIM(save_regs); i++) {
    1213         [ +  + ]:        738 :                 if (INUSE(st->reguse, save_regs[i]) != 0) {
    1214                 :            :                         emit_st_reg(st, BPF_STX | BPF_MEM | EBPF_DW,
    1215                 :            :                                 save_regs[i], RSP, ofs);
    1216                 :        421 :                         ofs += sizeof(uint64_t);
    1217                 :            :                 }
    1218                 :            :         }
    1219                 :            : 
    1220         [ +  + ]:        123 :         if (INUSE(st->reguse, RBP) != 0) {
    1221                 :        114 :                 emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X, RSP, RBP);
    1222                 :        114 :                 emit_alu_imm(st, EBPF_ALU64 | BPF_SUB | BPF_K, RSP, stack_size);
    1223                 :            :         }
    1224                 :            : }
    1225                 :            : 
    1226                 :            : /*
    1227                 :            :  * emit ret
    1228                 :            :  */
    1229                 :            : static void
    1230                 :            : emit_ret(struct bpf_jit_state *st)
    1231                 :            : {
    1232                 :            :         const uint8_t ops = 0xC3;
    1233                 :            : 
    1234                 :            :         emit_bytes(st, &ops, sizeof(ops));
    1235                 :        196 : }
    1236                 :            : 
    1237                 :            : static void
    1238                 :        332 : emit_epilog(struct bpf_jit_state *st)
    1239                 :            : {
    1240                 :            :         uint32_t i;
    1241                 :            :         int32_t spil, ofs;
    1242                 :            : 
    1243                 :            :         /* if we already have an epilog generate a jump to it */
    1244         [ +  + ]:        332 :         if (st->exit.num++ != 0) {
    1245                 :        136 :                 emit_abs_jmp(st, st->exit.off);
    1246                 :        136 :                 return;
    1247                 :            :         }
    1248                 :            : 
    1249                 :            :         /* store offset of epilog block */
    1250                 :        196 :         st->exit.off = st->sz;
    1251                 :            : 
    1252                 :            :         spil = 0;
    1253         [ +  + ]:       1372 :         for (i = 0; i != RTE_DIM(save_regs); i++)
    1254                 :       1176 :                 spil += INUSE(st->reguse, save_regs[i]);
    1255                 :            : 
    1256         [ +  + ]:        196 :         if (spil != 0) {
    1257                 :            : 
    1258         [ +  + ]:        160 :                 if (INUSE(st->reguse, RBP) != 0)
    1259                 :        148 :                         emit_mov_reg(st, EBPF_ALU64 | EBPF_MOV | BPF_X,
    1260                 :            :                                 RBP, RSP);
    1261                 :            : 
    1262                 :            :                 ofs = 0;
    1263         [ +  + ]:       1120 :                 for (i = 0; i != RTE_DIM(save_regs); i++) {
    1264         [ +  + ]:        960 :                         if (INUSE(st->reguse, save_regs[i]) != 0) {
    1265                 :        541 :                                 emit_ld_reg(st, BPF_LDX | BPF_MEM | EBPF_DW,
    1266                 :            :                                         RSP, save_regs[i], ofs);
    1267                 :        541 :                                 ofs += sizeof(uint64_t);
    1268                 :            :                         }
    1269                 :            :                 }
    1270                 :            : 
    1271                 :        160 :                 emit_alu_imm(st, EBPF_ALU64 | BPF_ADD | BPF_K, RSP,
    1272                 :            :                         spil * sizeof(uint64_t));
    1273                 :            :         }
    1274                 :            : 
    1275                 :            :         emit_ret(st);
    1276                 :            : }
    1277                 :            : 
    1278                 :            : /*
    1279                 :            :  * walk through bpf code and translate them x86_64 one.
    1280                 :            :  */
    1281                 :            : static int
    1282                 :        196 : emit(struct bpf_jit_state *st, const struct rte_bpf *bpf)
    1283                 :            : {
    1284                 :            :         uint32_t i, dr, op, sr;
    1285                 :            :         const struct ebpf_insn *ins;
    1286                 :            : 
    1287                 :            :         /* reset state fields */
    1288                 :        196 :         st->sz = 0;
    1289                 :        196 :         st->exit.num = 0;
    1290                 :        196 :         st->ldmb.stack_ofs = bpf->stack_sz;
    1291                 :            : 
    1292                 :        196 :         emit_prolog(st, bpf->stack_sz);
    1293                 :            : 
    1294         [ +  + ]:       5519 :         for (i = 0; i != bpf->prm.nb_ins; i++) {
    1295                 :            : 
    1296                 :       5323 :                 st->idx = i;
    1297                 :       5323 :                 st->off[i] = st->sz;
    1298                 :            : 
    1299                 :       5323 :                 ins = bpf->prm.ins + i;
    1300                 :            : 
    1301                 :       5323 :                 dr = ebpf2x86[ins->dst_reg];
    1302                 :       5323 :                 sr = ebpf2x86[ins->src_reg];
    1303                 :       5323 :                 op = ins->code;
    1304                 :            : 
    1305   [ +  +  +  +  :       5323 :                 switch (op) {
          +  -  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                      - ]
    1306                 :            :                 /* 32 bit ALU IMM operations */
    1307                 :        198 :                 case (BPF_ALU | BPF_ADD | BPF_K):
    1308                 :            :                 case (BPF_ALU | BPF_SUB | BPF_K):
    1309                 :            :                 case (BPF_ALU | BPF_AND | BPF_K):
    1310                 :            :                 case (BPF_ALU | BPF_OR | BPF_K):
    1311                 :            :                 case (BPF_ALU | BPF_XOR | BPF_K):
    1312                 :        198 :                         emit_alu_imm(st, op, dr, ins->imm);
    1313                 :        198 :                         break;
    1314                 :         95 :                 case (BPF_ALU | BPF_LSH | BPF_K):
    1315                 :            :                 case (BPF_ALU | BPF_RSH | BPF_K):
    1316                 :         95 :                         emit_shift_imm(st, op, dr, ins->imm);
    1317                 :         95 :                         break;
    1318                 :        459 :                 case (BPF_ALU | EBPF_MOV | BPF_K):
    1319                 :        459 :                         emit_mov_imm(st, op, dr, ins->imm);
    1320                 :        459 :                         break;
    1321                 :            :                 /* 32 bit ALU REG operations */
    1322                 :         34 :                 case (BPF_ALU | BPF_ADD | BPF_X):
    1323                 :            :                 case (BPF_ALU | BPF_SUB | BPF_X):
    1324                 :            :                 case (BPF_ALU | BPF_AND | BPF_X):
    1325                 :            :                 case (BPF_ALU | BPF_OR | BPF_X):
    1326                 :            :                 case (BPF_ALU | BPF_XOR | BPF_X):
    1327                 :         34 :                         emit_alu_reg(st, op, sr, dr);
    1328                 :         34 :                         break;
    1329                 :          6 :                 case (BPF_ALU | BPF_LSH | BPF_X):
    1330                 :            :                 case (BPF_ALU | BPF_RSH | BPF_X):
    1331                 :          6 :                         emit_shift_reg(st, op, sr, dr);
    1332                 :          6 :                         break;
    1333                 :          0 :                 case (BPF_ALU | EBPF_MOV | BPF_X):
    1334                 :          0 :                         emit_mov_reg(st, op, sr, dr);
    1335                 :          0 :                         break;
    1336                 :          3 :                 case (BPF_ALU | BPF_NEG):
    1337                 :          3 :                         emit_neg(st, op, dr);
    1338                 :          3 :                         break;
    1339                 :         17 :                 case (BPF_ALU | EBPF_END | EBPF_TO_BE):
    1340                 :         17 :                         emit_be2le(st, dr, ins->imm);
    1341                 :         17 :                         break;
    1342                 :          9 :                 case (BPF_ALU | EBPF_END | EBPF_TO_LE):
    1343                 :          9 :                         emit_le2be(st, dr, ins->imm);
    1344                 :          9 :                         break;
    1345                 :            :                 /* 64 bit ALU IMM operations */
    1346                 :         82 :                 case (EBPF_ALU64 | BPF_ADD | BPF_K):
    1347                 :            :                 case (EBPF_ALU64 | BPF_SUB | BPF_K):
    1348                 :            :                 case (EBPF_ALU64 | BPF_AND | BPF_K):
    1349                 :            :                 case (EBPF_ALU64 | BPF_OR | BPF_K):
    1350                 :            :                 case (EBPF_ALU64 | BPF_XOR | BPF_K):
    1351                 :         82 :                         emit_alu_imm(st, op, dr, ins->imm);
    1352                 :         82 :                         break;
    1353                 :         31 :                 case (EBPF_ALU64 | BPF_LSH | BPF_K):
    1354                 :            :                 case (EBPF_ALU64 | BPF_RSH | BPF_K):
    1355                 :            :                 case (EBPF_ALU64 | EBPF_ARSH | BPF_K):
    1356                 :         31 :                         emit_shift_imm(st, op, dr, ins->imm);
    1357                 :         31 :                         break;
    1358                 :         67 :                 case (EBPF_ALU64 | EBPF_MOV | BPF_K):
    1359                 :         67 :                         emit_mov_imm(st, op, dr, ins->imm);
    1360                 :         67 :                         break;
    1361                 :            :                 /* 64 bit ALU REG operations */
    1362                 :        363 :                 case (EBPF_ALU64 | BPF_ADD | BPF_X):
    1363                 :            :                 case (EBPF_ALU64 | BPF_SUB | BPF_X):
    1364                 :            :                 case (EBPF_ALU64 | BPF_AND | BPF_X):
    1365                 :            :                 case (EBPF_ALU64 | BPF_OR | BPF_X):
    1366                 :            :                 case (EBPF_ALU64 | BPF_XOR | BPF_X):
    1367                 :        363 :                         emit_alu_reg(st, op, sr, dr);
    1368                 :        363 :                         break;
    1369                 :          6 :                 case (EBPF_ALU64 | BPF_LSH | BPF_X):
    1370                 :            :                 case (EBPF_ALU64 | BPF_RSH | BPF_X):
    1371                 :            :                 case (EBPF_ALU64 | EBPF_ARSH | BPF_X):
    1372                 :          6 :                         emit_shift_reg(st, op, sr, dr);
    1373                 :          6 :                         break;
    1374                 :        431 :                 case (EBPF_ALU64 | EBPF_MOV | BPF_X):
    1375                 :        431 :                         emit_mov_reg(st, op, sr, dr);
    1376                 :        431 :                         break;
    1377                 :          3 :                 case (EBPF_ALU64 | BPF_NEG):
    1378                 :          3 :                         emit_neg(st, op, dr);
    1379                 :          3 :                         break;
    1380                 :            :                 /* multiply instructions */
    1381                 :         32 :                 case (BPF_ALU | BPF_MUL | BPF_K):
    1382                 :            :                 case (BPF_ALU | BPF_MUL | BPF_X):
    1383                 :            :                 case (EBPF_ALU64 | BPF_MUL | BPF_K):
    1384                 :            :                 case (EBPF_ALU64 | BPF_MUL | BPF_X):
    1385                 :         32 :                         emit_mul(st, op, sr, dr, ins->imm);
    1386                 :         32 :                         break;
    1387                 :            :                 /* divide instructions */
    1388                 :         20 :                 case (BPF_ALU | BPF_DIV | BPF_K):
    1389                 :            :                 case (BPF_ALU | BPF_MOD | BPF_K):
    1390                 :            :                 case (BPF_ALU | BPF_DIV | BPF_X):
    1391                 :            :                 case (BPF_ALU | BPF_MOD | BPF_X):
    1392                 :            :                 case (EBPF_ALU64 | BPF_DIV | BPF_K):
    1393                 :            :                 case (EBPF_ALU64 | BPF_MOD | BPF_K):
    1394                 :            :                 case (EBPF_ALU64 | BPF_DIV | BPF_X):
    1395                 :            :                 case (EBPF_ALU64 | BPF_MOD | BPF_X):
    1396                 :         20 :                         emit_div(st, op, sr, dr, ins->imm);
    1397                 :         20 :                         break;
    1398                 :            :                 /* load instructions */
    1399                 :        197 :                 case (BPF_LDX | BPF_MEM | BPF_B):
    1400                 :            :                 case (BPF_LDX | BPF_MEM | BPF_H):
    1401                 :            :                 case (BPF_LDX | BPF_MEM | BPF_W):
    1402                 :            :                 case (BPF_LDX | BPF_MEM | EBPF_DW):
    1403                 :        197 :                         emit_ld_reg(st, op, sr, dr, ins->off);
    1404                 :        197 :                         break;
    1405                 :            :                 /* load 64 bit immediate value */
    1406                 :         20 :                 case (BPF_LD | BPF_IMM | EBPF_DW):
    1407                 :         20 :                         emit_ld_imm64(st, dr, ins[0].imm, ins[1].imm);
    1408                 :         20 :                         i++;
    1409                 :         20 :                         break;
    1410                 :            :                 /* load absolute/indirect instructions */
    1411                 :       1198 :                 case (BPF_LD | BPF_ABS | BPF_B):
    1412                 :            :                 case (BPF_LD | BPF_ABS | BPF_H):
    1413                 :            :                 case (BPF_LD | BPF_ABS | BPF_W):
    1414                 :            :                 case (BPF_LD | BPF_IND | BPF_B):
    1415                 :            :                 case (BPF_LD | BPF_IND | BPF_H):
    1416                 :            :                 case (BPF_LD | BPF_IND | BPF_W):
    1417                 :       1198 :                         emit_ld_mbuf(st, op, sr, ins->imm);
    1418                 :       1198 :                         break;
    1419                 :            :                 /* store instructions */
    1420                 :        137 :                 case (BPF_STX | BPF_MEM | BPF_B):
    1421                 :            :                 case (BPF_STX | BPF_MEM | BPF_H):
    1422                 :            :                 case (BPF_STX | BPF_MEM | BPF_W):
    1423                 :            :                 case (BPF_STX | BPF_MEM | EBPF_DW):
    1424                 :        137 :                         emit_st_reg(st, op, sr, dr, ins->off);
    1425                 :            :                         break;
    1426                 :         28 :                 case (BPF_ST | BPF_MEM | BPF_B):
    1427                 :            :                 case (BPF_ST | BPF_MEM | BPF_H):
    1428                 :            :                 case (BPF_ST | BPF_MEM | BPF_W):
    1429                 :            :                 case (BPF_ST | BPF_MEM | EBPF_DW):
    1430                 :         28 :                         emit_st_imm(st, op, dr, ins->imm, ins->off);
    1431                 :            :                         break;
    1432                 :            :                 /* atomic add instructions */
    1433                 :         56 :                 case (BPF_STX | EBPF_XADD | BPF_W):
    1434                 :            :                 case (BPF_STX | EBPF_XADD | EBPF_DW):
    1435                 :         56 :                         emit_st_xadd(st, op, sr, dr, ins->off);
    1436                 :         56 :                         break;
    1437                 :            :                 /* jump instructions */
    1438                 :        119 :                 case (BPF_JMP | BPF_JA):
    1439                 :        119 :                         emit_jmp(st, ins->off + 1);
    1440                 :            :                         break;
    1441                 :            :                 /* jump IMM instructions */
    1442                 :       1165 :                 case (BPF_JMP | BPF_JEQ | BPF_K):
    1443                 :            :                 case (BPF_JMP | EBPF_JNE | BPF_K):
    1444                 :            :                 case (BPF_JMP | BPF_JGT | BPF_K):
    1445                 :            :                 case (BPF_JMP | EBPF_JLT | BPF_K):
    1446                 :            :                 case (BPF_JMP | BPF_JGE | BPF_K):
    1447                 :            :                 case (BPF_JMP | EBPF_JLE | BPF_K):
    1448                 :            :                 case (BPF_JMP | EBPF_JSGT | BPF_K):
    1449                 :            :                 case (BPF_JMP | EBPF_JSLT | BPF_K):
    1450                 :            :                 case (BPF_JMP | EBPF_JSGE | BPF_K):
    1451                 :            :                 case (BPF_JMP | EBPF_JSLE | BPF_K):
    1452                 :            :                 case (BPF_JMP | BPF_JSET | BPF_K):
    1453                 :       1165 :                         emit_jcc_imm(st, op, dr, ins->imm, ins->off + 1);
    1454                 :       1165 :                         break;
    1455                 :            :                 /* jump REG instructions */
    1456                 :        188 :                 case (BPF_JMP | BPF_JEQ | BPF_X):
    1457                 :            :                 case (BPF_JMP | EBPF_JNE | BPF_X):
    1458                 :            :                 case (BPF_JMP | BPF_JGT | BPF_X):
    1459                 :            :                 case (BPF_JMP | EBPF_JLT | BPF_X):
    1460                 :            :                 case (BPF_JMP | BPF_JGE | BPF_X):
    1461                 :            :                 case (BPF_JMP | EBPF_JLE | BPF_X):
    1462                 :            :                 case (BPF_JMP | EBPF_JSGT | BPF_X):
    1463                 :            :                 case (BPF_JMP | EBPF_JSLT | BPF_X):
    1464                 :            :                 case (BPF_JMP | EBPF_JSGE | BPF_X):
    1465                 :            :                 case (BPF_JMP | EBPF_JSLE | BPF_X):
    1466                 :            :                 case (BPF_JMP | BPF_JSET | BPF_X):
    1467                 :        188 :                         emit_jcc_reg(st, op, sr, dr, ins->off + 1);
    1468                 :        188 :                         break;
    1469                 :            :                 /* call instructions */
    1470                 :         27 :                 case (BPF_JMP | EBPF_CALL):
    1471                 :         27 :                         emit_call(st,
    1472                 :         27 :                                 (uintptr_t)bpf->prm.xsym[ins->imm].func.val);
    1473                 :         27 :                         break;
    1474                 :            :                 /* return instruction */
    1475                 :        332 :                 case (BPF_JMP | EBPF_EXIT):
    1476                 :        332 :                         emit_epilog(st);
    1477                 :        332 :                         break;
    1478                 :          0 :                 default:
    1479                 :          0 :                         RTE_BPF_LOG_LINE(ERR,
    1480                 :            :                                 "%s(%p): invalid opcode %#x at pc: %u;",
    1481                 :            :                                 __func__, bpf, ins->code, i);
    1482                 :          0 :                         return -EINVAL;
    1483                 :            :                 }
    1484                 :            :         }
    1485                 :            : 
    1486                 :            :         return 0;
    1487                 :            : }
    1488                 :            : 
    1489                 :            : /*
    1490                 :            :  * produce a native ISA version of the given BPF code.
    1491                 :            :  */
    1492                 :            : int
    1493         [ +  - ]:         48 : __rte_bpf_jit_x86(struct rte_bpf *bpf)
    1494                 :            : {
    1495                 :            :         int32_t rc;
    1496                 :            :         uint32_t i;
    1497                 :            :         size_t sz;
    1498                 :            :         struct bpf_jit_state st;
    1499                 :            : 
    1500                 :            :         /* init state */
    1501                 :            :         memset(&st, 0, sizeof(st));
    1502                 :         48 :         st.off = malloc(bpf->prm.nb_ins * sizeof(st.off[0]));
    1503         [ +  - ]:         48 :         if (st.off == NULL)
    1504                 :            :                 return -ENOMEM;
    1505                 :            : 
    1506                 :            :         /* fill with fake offsets */
    1507                 :         48 :         st.exit.off = INT32_MAX;
    1508         [ +  + ]:       1277 :         for (i = 0; i != bpf->prm.nb_ins; i++)
    1509                 :       1229 :                 st.off[i] = INT32_MAX;
    1510                 :            : 
    1511                 :            :         /*
    1512                 :            :          * dry runs, used to calculate total code size and valid jump offsets.
    1513                 :            :          * stop when we get minimal possible size
    1514                 :            :          */
    1515                 :            :         do {
    1516                 :        148 :                 sz = st.sz;
    1517                 :        148 :                 rc = emit(&st, bpf);
    1518   [ +  -  +  + ]:        148 :         } while (rc == 0 && sz != st.sz);
    1519                 :            : 
    1520         [ +  - ]:         48 :         if (rc == 0) {
    1521                 :            : 
    1522                 :            :                 /* allocate memory needed */
    1523                 :         48 :                 st.ins = mmap(NULL, st.sz, PROT_READ | PROT_WRITE,
    1524                 :            :                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    1525         [ +  - ]:         48 :                 if (st.ins == MAP_FAILED)
    1526                 :            :                         rc = -ENOMEM;
    1527                 :            :                 else
    1528                 :            :                         /* generate code */
    1529                 :         48 :                         rc = emit(&st, bpf);
    1530                 :            :         }
    1531                 :            : 
    1532   [ +  -  +  - ]:         48 :         if (rc == 0 && mprotect(st.ins, st.sz, PROT_READ | PROT_EXEC) != 0)
    1533                 :            :                 rc = -ENOMEM;
    1534                 :            : 
    1535         [ -  + ]:         48 :         if (rc != 0)
    1536                 :          0 :                 munmap(st.ins, st.sz);
    1537                 :            :         else {
    1538                 :         48 :                 bpf->jit.func = (void *)st.ins;
    1539                 :         48 :                 bpf->jit.sz = st.sz;
    1540                 :            :         }
    1541                 :            : 
    1542                 :         48 :         free(st.off);
    1543                 :         48 :         return rc;
    1544                 :            : }

Generated by: LCOV version 1.14