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