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