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