Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Intel Corporation
3 : : */
4 : :
5 : : #include <stdio.h>
6 : : #include <stdint.h>
7 : :
8 : : #include <eal_export.h>
9 : : #include <rte_common.h>
10 : : #include <rte_log.h>
11 : : #include <rte_debug.h>
12 : : #include <rte_byteorder.h>
13 : :
14 : : #include "bpf_impl.h"
15 : :
16 : : #define BPF_JMP_UNC(ins) ((ins) += (ins)->off)
17 : :
18 : : #define BPF_JMP_CND_REG(reg, ins, op, type) \
19 : : ((ins) += \
20 : : ((type)(reg)[(ins)->dst_reg] op (type)(reg)[(ins)->src_reg]) ? \
21 : : (ins)->off : 0)
22 : :
23 : : #define BPF_JMP_CND_IMM(reg, ins, op, type) \
24 : : ((ins) += \
25 : : ((type)(reg)[(ins)->dst_reg] op (type)(ins)->imm) ? \
26 : : (ins)->off : 0)
27 : :
28 : : #define BPF_NEG_ALU(reg, ins, type) \
29 : : ((reg)[(ins)->dst_reg] = (type)(-(reg)[(ins)->dst_reg]))
30 : :
31 : : #define EBPF_MOV_ALU_REG(reg, ins, type) \
32 : : ((reg)[(ins)->dst_reg] = (type)(reg)[(ins)->src_reg])
33 : :
34 : : #define BPF_OP_ALU_REG(reg, ins, op, type) \
35 : : ((reg)[(ins)->dst_reg] = \
36 : : (type)(reg)[(ins)->dst_reg] op (type)(reg)[(ins)->src_reg])
37 : :
38 : : #define EBPF_MOV_ALU_IMM(reg, ins, type) \
39 : : ((reg)[(ins)->dst_reg] = (type)(ins)->imm)
40 : :
41 : : #define BPF_OP_ALU_IMM(reg, ins, op, type) \
42 : : ((reg)[(ins)->dst_reg] = \
43 : : (type)(reg)[(ins)->dst_reg] op (type)(ins)->imm)
44 : :
45 : : #define BPF_DIV_ZERO_CHECK(bpf, reg, ins, type) do { \
46 : : if ((type)(reg)[(ins)->src_reg] == 0) { \
47 : : RTE_BPF_LOG_LINE(ERR, \
48 : : "%s(%p): division by 0 at pc: %#zx;", \
49 : : __func__, bpf, \
50 : : (uintptr_t)(ins) - (uintptr_t)(bpf)->prm.ins); \
51 : : return 0; \
52 : : } \
53 : : } while (0)
54 : :
55 : : #define BPF_LD_REG(reg, ins, type) \
56 : : ((reg)[(ins)->dst_reg] = \
57 : : *(type *)(uintptr_t)((reg)[(ins)->src_reg] + (ins)->off))
58 : :
59 : : #define BPF_ST_IMM(reg, ins, type) \
60 : : (*(type *)(uintptr_t)((reg)[(ins)->dst_reg] + (ins)->off) = \
61 : : (type)(ins)->imm)
62 : :
63 : : #define BPF_ST_REG(reg, ins, type) \
64 : : (*(type *)(uintptr_t)((reg)[(ins)->dst_reg] + (ins)->off) = \
65 : : (type)(reg)[(ins)->src_reg])
66 : :
67 : : #define BPF_ST_XADD_REG(reg, ins, tp) \
68 : : (rte_atomic##tp##_add((rte_atomic##tp##_t *) \
69 : : (uintptr_t)((reg)[(ins)->dst_reg] + (ins)->off), \
70 : : reg[ins->src_reg]))
71 : :
72 : : /* BPF_LD | BPF_ABS/BPF_IND */
73 : :
74 : : #define NOP(x) (x)
75 : :
76 : : #define BPF_LD_ABS(bpf, reg, ins, type, op) do { \
77 : : const type *p = bpf_ld_mbuf(bpf, reg, ins, (ins)->imm, sizeof(type)); \
78 : : if (p == NULL) \
79 : : return 0; \
80 : : reg[EBPF_REG_0] = op(p[0]); \
81 : : } while (0)
82 : :
83 : : #define BPF_LD_IND(bpf, reg, ins, type, op) do { \
84 : : uint32_t ofs = reg[ins->src_reg] + (ins)->imm; \
85 : : const type *p = bpf_ld_mbuf(bpf, reg, ins, ofs, sizeof(type)); \
86 : : if (p == NULL) \
87 : : return 0; \
88 : : reg[EBPF_REG_0] = op(p[0]); \
89 : : } while (0)
90 : :
91 : :
92 : : static inline void
93 : 5 : bpf_alu_be(uint64_t reg[EBPF_REG_NUM], const struct ebpf_insn *ins)
94 : : {
95 : : uint64_t *v;
96 : :
97 : 5 : v = reg + ins->dst_reg;
98 [ + + + - ]: 5 : switch (ins->imm) {
99 : 1 : case 16:
100 [ - + ]: 1 : *v = rte_cpu_to_be_16(*v);
101 : 1 : break;
102 : 3 : case 32:
103 [ - + ]: 3 : *v = rte_cpu_to_be_32(*v);
104 : 3 : break;
105 : 1 : case 64:
106 [ - + ]: 1 : *v = rte_cpu_to_be_64(*v);
107 : 1 : break;
108 : : }
109 : 5 : }
110 : :
111 : : static inline void
112 : : bpf_alu_le(uint64_t reg[EBPF_REG_NUM], const struct ebpf_insn *ins)
113 : : {
114 : : uint64_t *v;
115 : :
116 : : v = reg + ins->dst_reg;
117 : : switch (ins->imm) {
118 : : case 16:
119 : : *v = rte_cpu_to_le_16(*v);
120 : : break;
121 : : case 32:
122 : : *v = rte_cpu_to_le_32(*v);
123 : : break;
124 : : case 64:
125 : : *v = rte_cpu_to_le_64(*v);
126 : : break;
127 : : }
128 : : }
129 : :
130 : : static inline const void *
131 : 19 : bpf_ld_mbuf(const struct rte_bpf *bpf, uint64_t reg[EBPF_REG_NUM],
132 : : const struct ebpf_insn *ins, uint32_t off, uint32_t len)
133 : : {
134 : : const struct rte_mbuf *mb;
135 : : const void *p;
136 : :
137 [ + + ]: 19 : mb = (const struct rte_mbuf *)(uintptr_t)reg[EBPF_REG_6];
138 : : p = rte_pktmbuf_read(mb, off, len, reg + EBPF_REG_0);
139 [ + + ]: 19 : if (p == NULL)
140 : 1 : RTE_BPF_LOG_LINE(DEBUG, "%s(bpf=%p, mbuf=%p, ofs=%u, len=%u): "
141 : : "load beyond packet boundary at pc: %#zx;",
142 : : __func__, bpf, mb, off, len,
143 : : (uintptr_t)(ins) - (uintptr_t)(bpf)->prm.ins);
144 : 19 : return p;
145 : : }
146 : :
147 : : static inline uint64_t
148 : 22 : bpf_exec(const struct rte_bpf *bpf, uint64_t reg[EBPF_REG_NUM])
149 : : {
150 : : const struct ebpf_insn *ins;
151 : :
152 : 341 : for (ins = bpf->prm.ins; ; ins++) {
153 [ - - + - : 341 : switch (ins->code) {
+ - + + +
- + - + +
+ + + - +
+ + - + +
+ + + + +
+ + + + -
+ + + + +
- + - + +
+ + - + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
- - - - -
- + + + +
- - - + +
- - - + +
+ - + ]
154 : : /* 32 bit ALU IMM operations */
155 : 0 : case (BPF_ALU | BPF_ADD | BPF_K):
156 : 0 : BPF_OP_ALU_IMM(reg, ins, +, uint32_t);
157 : 0 : break;
158 : 0 : case (BPF_ALU | BPF_SUB | BPF_K):
159 : 0 : BPF_OP_ALU_IMM(reg, ins, -, uint32_t);
160 : 0 : break;
161 : 11 : case (BPF_ALU | BPF_AND | BPF_K):
162 : 11 : BPF_OP_ALU_IMM(reg, ins, &, uint32_t);
163 : 11 : break;
164 : 0 : case (BPF_ALU | BPF_OR | BPF_K):
165 : 0 : BPF_OP_ALU_IMM(reg, ins, |, uint32_t);
166 : 0 : break;
167 : 4 : case (BPF_ALU | BPF_LSH | BPF_K):
168 : 4 : BPF_OP_ALU_IMM(reg, ins, <<, uint32_t);
169 : 4 : break;
170 : 0 : case (BPF_ALU | BPF_RSH | BPF_K):
171 : 0 : BPF_OP_ALU_IMM(reg, ins, >>, uint32_t);
172 : 0 : break;
173 : 1 : case (BPF_ALU | BPF_XOR | BPF_K):
174 : 1 : BPF_OP_ALU_IMM(reg, ins, ^, uint32_t);
175 : 1 : break;
176 : 1 : case (BPF_ALU | BPF_MUL | BPF_K):
177 : 1 : BPF_OP_ALU_IMM(reg, ins, *, uint32_t);
178 : 1 : break;
179 : 1 : case (BPF_ALU | BPF_DIV | BPF_K):
180 : 1 : BPF_OP_ALU_IMM(reg, ins, /, uint32_t);
181 : 1 : break;
182 : 0 : case (BPF_ALU | BPF_MOD | BPF_K):
183 : 0 : BPF_OP_ALU_IMM(reg, ins, %, uint32_t);
184 : 0 : break;
185 : 12 : case (BPF_ALU | EBPF_MOV | BPF_K):
186 : 12 : EBPF_MOV_ALU_IMM(reg, ins, uint32_t);
187 : 12 : break;
188 : : /* 32 bit ALU REG operations */
189 : 0 : case (BPF_ALU | BPF_ADD | BPF_X):
190 : 0 : BPF_OP_ALU_REG(reg, ins, +, uint32_t);
191 : 0 : break;
192 : 1 : case (BPF_ALU | BPF_SUB | BPF_X):
193 : 1 : BPF_OP_ALU_REG(reg, ins, -, uint32_t);
194 : 1 : break;
195 : 1 : case (BPF_ALU | BPF_AND | BPF_X):
196 : 1 : BPF_OP_ALU_REG(reg, ins, &, uint32_t);
197 : 1 : break;
198 : 1 : case (BPF_ALU | BPF_OR | BPF_X):
199 : 1 : BPF_OP_ALU_REG(reg, ins, |, uint32_t);
200 : 1 : break;
201 : 1 : case (BPF_ALU | BPF_LSH | BPF_X):
202 : 1 : BPF_OP_ALU_REG(reg, ins, <<, uint32_t);
203 : 1 : break;
204 : 1 : case (BPF_ALU | BPF_RSH | BPF_X):
205 : 1 : BPF_OP_ALU_REG(reg, ins, >>, uint32_t);
206 : 1 : break;
207 : 0 : case (BPF_ALU | BPF_XOR | BPF_X):
208 : 0 : BPF_OP_ALU_REG(reg, ins, ^, uint32_t);
209 : 0 : break;
210 : 1 : case (BPF_ALU | BPF_MUL | BPF_X):
211 : 1 : BPF_OP_ALU_REG(reg, ins, *, uint32_t);
212 : 1 : break;
213 : 1 : case (BPF_ALU | BPF_DIV | BPF_X):
214 [ + - ]: 1 : BPF_DIV_ZERO_CHECK(bpf, reg, ins, uint32_t);
215 : 0 : BPF_OP_ALU_REG(reg, ins, /, uint32_t);
216 : 0 : break;
217 : 1 : case (BPF_ALU | BPF_MOD | BPF_X):
218 [ - + ]: 1 : BPF_DIV_ZERO_CHECK(bpf, reg, ins, uint32_t);
219 : 1 : BPF_OP_ALU_REG(reg, ins, %, uint32_t);
220 : 1 : break;
221 : 0 : case (BPF_ALU | EBPF_MOV | BPF_X):
222 : 0 : EBPF_MOV_ALU_REG(reg, ins, uint32_t);
223 : 0 : break;
224 : 1 : case (BPF_ALU | BPF_NEG):
225 : 1 : BPF_NEG_ALU(reg, ins, uint32_t);
226 : 1 : break;
227 : 5 : case (BPF_ALU | EBPF_END | EBPF_TO_BE):
228 : 5 : bpf_alu_be(reg, ins);
229 : 5 : break;
230 : : case (BPF_ALU | EBPF_END | EBPF_TO_LE):
231 : : bpf_alu_le(reg, ins);
232 : : break;
233 : : /* 64 bit ALU IMM operations */
234 : 6 : case (EBPF_ALU64 | BPF_ADD | BPF_K):
235 : 6 : BPF_OP_ALU_IMM(reg, ins, +, uint64_t);
236 : 6 : break;
237 : 2 : case (EBPF_ALU64 | BPF_SUB | BPF_K):
238 : 2 : BPF_OP_ALU_IMM(reg, ins, -, uint64_t);
239 : 2 : break;
240 : 1 : case (EBPF_ALU64 | BPF_AND | BPF_K):
241 : 1 : BPF_OP_ALU_IMM(reg, ins, &, uint64_t);
242 : 1 : break;
243 : 9 : case (EBPF_ALU64 | BPF_OR | BPF_K):
244 : 9 : BPF_OP_ALU_IMM(reg, ins, |, uint64_t);
245 : 9 : break;
246 : 2 : case (EBPF_ALU64 | BPF_LSH | BPF_K):
247 : 2 : BPF_OP_ALU_IMM(reg, ins, <<, uint64_t);
248 : 2 : break;
249 : 4 : case (EBPF_ALU64 | BPF_RSH | BPF_K):
250 : 4 : BPF_OP_ALU_IMM(reg, ins, >>, uint64_t);
251 : 4 : break;
252 : 1 : case (EBPF_ALU64 | EBPF_ARSH | BPF_K):
253 : 1 : BPF_OP_ALU_IMM(reg, ins, >>, int64_t);
254 : 1 : break;
255 : 1 : case (EBPF_ALU64 | BPF_XOR | BPF_K):
256 : 1 : BPF_OP_ALU_IMM(reg, ins, ^, uint64_t);
257 : 1 : break;
258 : 1 : case (EBPF_ALU64 | BPF_MUL | BPF_K):
259 : 1 : BPF_OP_ALU_IMM(reg, ins, *, uint64_t);
260 : 1 : break;
261 : 0 : case (EBPF_ALU64 | BPF_DIV | BPF_K):
262 : 0 : BPF_OP_ALU_IMM(reg, ins, /, uint64_t);
263 : 0 : break;
264 : 1 : case (EBPF_ALU64 | BPF_MOD | BPF_K):
265 : 1 : BPF_OP_ALU_IMM(reg, ins, %, uint64_t);
266 : 1 : break;
267 : 16 : case (EBPF_ALU64 | EBPF_MOV | BPF_K):
268 : 16 : EBPF_MOV_ALU_IMM(reg, ins, uint64_t);
269 : 16 : break;
270 : : /* 64 bit ALU REG operations */
271 : 23 : case (EBPF_ALU64 | BPF_ADD | BPF_X):
272 : 23 : BPF_OP_ALU_REG(reg, ins, +, uint64_t);
273 : 23 : break;
274 : 1 : case (EBPF_ALU64 | BPF_SUB | BPF_X):
275 : 1 : BPF_OP_ALU_REG(reg, ins, -, uint64_t);
276 : 1 : break;
277 : 1 : case (EBPF_ALU64 | BPF_AND | BPF_X):
278 : 1 : BPF_OP_ALU_REG(reg, ins, &, uint64_t);
279 : 1 : break;
280 : 0 : case (EBPF_ALU64 | BPF_OR | BPF_X):
281 : 0 : BPF_OP_ALU_REG(reg, ins, |, uint64_t);
282 : 0 : break;
283 : 1 : case (EBPF_ALU64 | BPF_LSH | BPF_X):
284 : 1 : BPF_OP_ALU_REG(reg, ins, <<, uint64_t);
285 : 1 : break;
286 : 0 : case (EBPF_ALU64 | BPF_RSH | BPF_X):
287 : 0 : BPF_OP_ALU_REG(reg, ins, >>, uint64_t);
288 : 0 : break;
289 : 1 : case (EBPF_ALU64 | EBPF_ARSH | BPF_X):
290 : 1 : BPF_OP_ALU_REG(reg, ins, >>, int64_t);
291 : 1 : break;
292 : 5 : case (EBPF_ALU64 | BPF_XOR | BPF_X):
293 : 5 : BPF_OP_ALU_REG(reg, ins, ^, uint64_t);
294 : 5 : break;
295 : 1 : case (EBPF_ALU64 | BPF_MUL | BPF_X):
296 : 1 : BPF_OP_ALU_REG(reg, ins, *, uint64_t);
297 : 1 : break;
298 : 1 : case (EBPF_ALU64 | BPF_DIV | BPF_X):
299 [ - + ]: 1 : BPF_DIV_ZERO_CHECK(bpf, reg, ins, uint64_t);
300 : 1 : BPF_OP_ALU_REG(reg, ins, /, uint64_t);
301 : 1 : break;
302 : 0 : case (EBPF_ALU64 | BPF_MOD | BPF_X):
303 [ # # ]: 0 : BPF_DIV_ZERO_CHECK(bpf, reg, ins, uint64_t);
304 : 0 : BPF_OP_ALU_REG(reg, ins, %, uint64_t);
305 : 0 : break;
306 : 26 : case (EBPF_ALU64 | EBPF_MOV | BPF_X):
307 : 26 : EBPF_MOV_ALU_REG(reg, ins, uint64_t);
308 : 26 : break;
309 : 1 : case (EBPF_ALU64 | BPF_NEG):
310 : 1 : BPF_NEG_ALU(reg, ins, uint64_t);
311 : 1 : break;
312 : : /* load instructions */
313 : 8 : case (BPF_LDX | BPF_MEM | BPF_B):
314 : 8 : BPF_LD_REG(reg, ins, uint8_t);
315 : 8 : break;
316 : 7 : case (BPF_LDX | BPF_MEM | BPF_H):
317 : 7 : BPF_LD_REG(reg, ins, uint16_t);
318 : 7 : break;
319 : 22 : case (BPF_LDX | BPF_MEM | BPF_W):
320 : 22 : BPF_LD_REG(reg, ins, uint32_t);
321 : 22 : break;
322 : 16 : case (BPF_LDX | BPF_MEM | EBPF_DW):
323 : 16 : BPF_LD_REG(reg, ins, uint64_t);
324 : 16 : break;
325 : : /* load 64 bit immediate value */
326 : 5 : case (BPF_LD | BPF_IMM | EBPF_DW):
327 : 5 : reg[ins->dst_reg] = (uint32_t)ins[0].imm |
328 : 5 : (uint64_t)(uint32_t)ins[1].imm << 32;
329 : 5 : ins++;
330 : 5 : break;
331 : : /* load absolute instructions */
332 : 3 : case (BPF_LD | BPF_ABS | BPF_B):
333 [ + - ]: 3 : BPF_LD_ABS(bpf, reg, ins, uint8_t, NOP);
334 : 3 : break;
335 : 5 : case (BPF_LD | BPF_ABS | BPF_H):
336 [ + - - + ]: 10 : BPF_LD_ABS(bpf, reg, ins, uint16_t, rte_be_to_cpu_16);
337 : 5 : break;
338 : 3 : case (BPF_LD | BPF_ABS | BPF_W):
339 [ + - - + ]: 6 : BPF_LD_ABS(bpf, reg, ins, uint32_t, rte_be_to_cpu_32);
340 : 3 : break;
341 : : /* load indirect instructions */
342 : 3 : case (BPF_LD | BPF_IND | BPF_B):
343 [ + - ]: 3 : BPF_LD_IND(bpf, reg, ins, uint8_t, NOP);
344 : 3 : break;
345 : 2 : case (BPF_LD | BPF_IND | BPF_H):
346 [ + - - + ]: 4 : BPF_LD_IND(bpf, reg, ins, uint16_t, rte_be_to_cpu_16);
347 : 2 : break;
348 : 3 : case (BPF_LD | BPF_IND | BPF_W):
349 [ + + - + ]: 5 : BPF_LD_IND(bpf, reg, ins, uint32_t, rte_be_to_cpu_32);
350 : 2 : break;
351 : : /* store instructions */
352 : 3 : case (BPF_STX | BPF_MEM | BPF_B):
353 : 3 : BPF_ST_REG(reg, ins, uint8_t);
354 : 3 : break;
355 : 1 : case (BPF_STX | BPF_MEM | BPF_H):
356 : 1 : BPF_ST_REG(reg, ins, uint16_t);
357 : 1 : break;
358 : 6 : case (BPF_STX | BPF_MEM | BPF_W):
359 : 6 : BPF_ST_REG(reg, ins, uint32_t);
360 : 6 : break;
361 : 29 : case (BPF_STX | BPF_MEM | EBPF_DW):
362 : 29 : BPF_ST_REG(reg, ins, uint64_t);
363 : 29 : break;
364 : 5 : case (BPF_ST | BPF_MEM | BPF_B):
365 : 5 : BPF_ST_IMM(reg, ins, uint8_t);
366 : 5 : break;
367 : 1 : case (BPF_ST | BPF_MEM | BPF_H):
368 : 1 : BPF_ST_IMM(reg, ins, uint16_t);
369 : 1 : break;
370 : 1 : case (BPF_ST | BPF_MEM | BPF_W):
371 : 1 : BPF_ST_IMM(reg, ins, uint32_t);
372 : 1 : break;
373 : 1 : case (BPF_ST | BPF_MEM | EBPF_DW):
374 : 1 : BPF_ST_IMM(reg, ins, uint64_t);
375 : 1 : break;
376 : : /* atomic add instructions */
377 : 7 : case (BPF_STX | EBPF_XADD | BPF_W):
378 : 7 : BPF_ST_XADD_REG(reg, ins, 32);
379 : : break;
380 : 7 : case (BPF_STX | EBPF_XADD | EBPF_DW):
381 : 7 : BPF_ST_XADD_REG(reg, ins, 64);
382 : : break;
383 : : /* jump instructions */
384 : 6 : case (BPF_JMP | BPF_JA):
385 : 6 : BPF_JMP_UNC(ins);
386 : 6 : break;
387 : : /* jump IMM instructions */
388 : 4 : case (BPF_JMP | BPF_JEQ | BPF_K):
389 [ + + ]: 4 : BPF_JMP_CND_IMM(reg, ins, ==, uint64_t);
390 : 4 : break;
391 : 5 : case (BPF_JMP | EBPF_JNE | BPF_K):
392 [ - + ]: 5 : BPF_JMP_CND_IMM(reg, ins, !=, uint64_t);
393 : 5 : break;
394 : 1 : case (BPF_JMP | BPF_JGT | BPF_K):
395 [ + - ]: 1 : BPF_JMP_CND_IMM(reg, ins, >, uint64_t);
396 : 1 : break;
397 : 0 : case (BPF_JMP | EBPF_JLT | BPF_K):
398 [ # # ]: 0 : BPF_JMP_CND_IMM(reg, ins, <, uint64_t);
399 : 0 : break;
400 : 0 : case (BPF_JMP | BPF_JGE | BPF_K):
401 [ # # ]: 0 : BPF_JMP_CND_IMM(reg, ins, >=, uint64_t);
402 : 0 : break;
403 : 0 : case (BPF_JMP | EBPF_JLE | BPF_K):
404 [ # # ]: 0 : BPF_JMP_CND_IMM(reg, ins, <=, uint64_t);
405 : 0 : break;
406 : 0 : case (BPF_JMP | EBPF_JSGT | BPF_K):
407 [ # # ]: 0 : BPF_JMP_CND_IMM(reg, ins, >, int64_t);
408 : 0 : break;
409 : 0 : case (BPF_JMP | EBPF_JSLT | BPF_K):
410 [ # # ]: 0 : BPF_JMP_CND_IMM(reg, ins, <, int64_t);
411 : 0 : break;
412 : 0 : case (BPF_JMP | EBPF_JSGE | BPF_K):
413 [ # # ]: 0 : BPF_JMP_CND_IMM(reg, ins, >=, int64_t);
414 : 0 : break;
415 : 1 : case (BPF_JMP | EBPF_JSLE | BPF_K):
416 [ + - ]: 1 : BPF_JMP_CND_IMM(reg, ins, <=, int64_t);
417 : 1 : break;
418 : 1 : case (BPF_JMP | BPF_JSET | BPF_K):
419 [ + - ]: 1 : BPF_JMP_CND_IMM(reg, ins, &, uint64_t);
420 : 1 : break;
421 : : /* jump REG instructions */
422 : 2 : case (BPF_JMP | BPF_JEQ | BPF_X):
423 [ + + ]: 2 : BPF_JMP_CND_REG(reg, ins, ==, uint64_t);
424 : 2 : break;
425 : 1 : case (BPF_JMP | EBPF_JNE | BPF_X):
426 [ + - ]: 1 : BPF_JMP_CND_REG(reg, ins, !=, uint64_t);
427 : 1 : break;
428 : 0 : case (BPF_JMP | BPF_JGT | BPF_X):
429 [ # # ]: 0 : BPF_JMP_CND_REG(reg, ins, >, uint64_t);
430 : 0 : break;
431 : 0 : case (BPF_JMP | EBPF_JLT | BPF_X):
432 [ # # ]: 0 : BPF_JMP_CND_REG(reg, ins, <, uint64_t);
433 : 0 : break;
434 : 0 : case (BPF_JMP | BPF_JGE | BPF_X):
435 [ # # ]: 0 : BPF_JMP_CND_REG(reg, ins, >=, uint64_t);
436 : 0 : break;
437 : 1 : case (BPF_JMP | EBPF_JLE | BPF_X):
438 [ + - ]: 1 : BPF_JMP_CND_REG(reg, ins, <=, uint64_t);
439 : 1 : break;
440 : 1 : case (BPF_JMP | EBPF_JSGT | BPF_X):
441 [ - + ]: 1 : BPF_JMP_CND_REG(reg, ins, >, int64_t);
442 : 1 : break;
443 : 0 : case (BPF_JMP | EBPF_JSLT | BPF_X):
444 [ # # ]: 0 : BPF_JMP_CND_REG(reg, ins, <, int64_t);
445 : 0 : break;
446 : 0 : case (BPF_JMP | EBPF_JSGE | BPF_X):
447 [ # # ]: 0 : BPF_JMP_CND_REG(reg, ins, >=, int64_t);
448 : 0 : break;
449 : 0 : case (BPF_JMP | EBPF_JSLE | BPF_X):
450 [ # # ]: 0 : BPF_JMP_CND_REG(reg, ins, <=, int64_t);
451 : 0 : break;
452 : 1 : case (BPF_JMP | BPF_JSET | BPF_X):
453 [ + - ]: 1 : BPF_JMP_CND_REG(reg, ins, &, uint64_t);
454 : 1 : break;
455 : : /* call instructions */
456 : 7 : case (BPF_JMP | EBPF_CALL):
457 : 7 : reg[EBPF_REG_0] = bpf->prm.xsym[ins->imm].func.val(
458 : : reg[EBPF_REG_1], reg[EBPF_REG_2],
459 : : reg[EBPF_REG_3], reg[EBPF_REG_4],
460 : : reg[EBPF_REG_5]);
461 : 7 : break;
462 : : /* return instruction */
463 : 20 : case (BPF_JMP | EBPF_EXIT):
464 : 20 : return reg[EBPF_REG_0];
465 : 0 : default:
466 : 0 : RTE_BPF_LOG_LINE(ERR,
467 : : "%s(%p): invalid opcode %#x at pc: %#zx;",
468 : : __func__, bpf, ins->code,
469 : : (uintptr_t)ins - (uintptr_t)bpf->prm.ins);
470 : 0 : return 0;
471 : : }
472 : : }
473 : :
474 : : /* should never be reached */
475 : : RTE_VERIFY(0);
476 : : return 0;
477 : : }
478 : :
479 : : RTE_EXPORT_SYMBOL(rte_bpf_exec_burst)
480 : : uint32_t
481 : 22 : rte_bpf_exec_burst(const struct rte_bpf *bpf, void *ctx[], uint64_t rc[],
482 : : uint32_t num)
483 : : {
484 : : uint32_t i;
485 : : uint64_t reg[EBPF_REG_NUM];
486 : : uint64_t stack[MAX_BPF_STACK_SIZE / sizeof(uint64_t)];
487 : :
488 [ + + ]: 44 : for (i = 0; i != num; i++) {
489 : :
490 : 22 : reg[EBPF_REG_1] = (uintptr_t)ctx[i];
491 : 22 : reg[EBPF_REG_10] = (uintptr_t)(stack + RTE_DIM(stack));
492 : :
493 : 22 : rc[i] = bpf_exec(bpf, reg);
494 : : }
495 : :
496 : 22 : return i;
497 : : }
498 : :
499 : : RTE_EXPORT_SYMBOL(rte_bpf_exec)
500 : : uint64_t
501 : 22 : rte_bpf_exec(const struct rte_bpf *bpf, void *ctx)
502 : : {
503 : : uint64_t rc;
504 : :
505 : 22 : rte_bpf_exec_burst(bpf, &ctx, &rc, 1);
506 : 22 : return rc;
507 : : }
|