xref: /dpdk/lib/bpf/bpf_exec.c (revision 0e21c7c07d623719d61cc7e2e85613e8c71d9a57)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2018 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include <stdio.h>
699a2dd95SBruce Richardson #include <stdint.h>
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson #include <rte_common.h>
999a2dd95SBruce Richardson #include <rte_log.h>
1099a2dd95SBruce Richardson #include <rte_debug.h>
1199a2dd95SBruce Richardson #include <rte_byteorder.h>
1299a2dd95SBruce Richardson 
1399a2dd95SBruce Richardson #include "bpf_impl.h"
1499a2dd95SBruce Richardson 
1599a2dd95SBruce Richardson #define BPF_JMP_UNC(ins)	((ins) += (ins)->off)
1699a2dd95SBruce Richardson 
1799a2dd95SBruce Richardson #define BPF_JMP_CND_REG(reg, ins, op, type)	\
1899a2dd95SBruce Richardson 	((ins) += \
1999a2dd95SBruce Richardson 		((type)(reg)[(ins)->dst_reg] op (type)(reg)[(ins)->src_reg]) ? \
2099a2dd95SBruce Richardson 		(ins)->off : 0)
2199a2dd95SBruce Richardson 
2299a2dd95SBruce Richardson #define BPF_JMP_CND_IMM(reg, ins, op, type)	\
2399a2dd95SBruce Richardson 	((ins) += \
2499a2dd95SBruce Richardson 		((type)(reg)[(ins)->dst_reg] op (type)(ins)->imm) ? \
2599a2dd95SBruce Richardson 		(ins)->off : 0)
2699a2dd95SBruce Richardson 
2799a2dd95SBruce Richardson #define BPF_NEG_ALU(reg, ins, type)	\
2899a2dd95SBruce Richardson 	((reg)[(ins)->dst_reg] = (type)(-(reg)[(ins)->dst_reg]))
2999a2dd95SBruce Richardson 
3099a2dd95SBruce Richardson #define EBPF_MOV_ALU_REG(reg, ins, type)	\
3199a2dd95SBruce Richardson 	((reg)[(ins)->dst_reg] = (type)(reg)[(ins)->src_reg])
3299a2dd95SBruce Richardson 
3399a2dd95SBruce Richardson #define BPF_OP_ALU_REG(reg, ins, op, type)	\
3499a2dd95SBruce Richardson 	((reg)[(ins)->dst_reg] = \
3599a2dd95SBruce Richardson 		(type)(reg)[(ins)->dst_reg] op (type)(reg)[(ins)->src_reg])
3699a2dd95SBruce Richardson 
3799a2dd95SBruce Richardson #define EBPF_MOV_ALU_IMM(reg, ins, type)	\
3899a2dd95SBruce Richardson 	((reg)[(ins)->dst_reg] = (type)(ins)->imm)
3999a2dd95SBruce Richardson 
4099a2dd95SBruce Richardson #define BPF_OP_ALU_IMM(reg, ins, op, type)	\
4199a2dd95SBruce Richardson 	((reg)[(ins)->dst_reg] = \
4299a2dd95SBruce Richardson 		(type)(reg)[(ins)->dst_reg] op (type)(ins)->imm)
4399a2dd95SBruce Richardson 
4499a2dd95SBruce Richardson #define BPF_DIV_ZERO_CHECK(bpf, reg, ins, type) do { \
4599a2dd95SBruce Richardson 	if ((type)(reg)[(ins)->src_reg] == 0) { \
46*0e21c7c0SDavid Marchand 		RTE_BPF_LOG_LINE(ERR, \
47*0e21c7c0SDavid Marchand 			"%s(%p): division by 0 at pc: %#zx;", \
4899a2dd95SBruce Richardson 			__func__, bpf, \
4999a2dd95SBruce Richardson 			(uintptr_t)(ins) - (uintptr_t)(bpf)->prm.ins); \
5099a2dd95SBruce Richardson 		return 0; \
5199a2dd95SBruce Richardson 	} \
5299a2dd95SBruce Richardson } while (0)
5399a2dd95SBruce Richardson 
5499a2dd95SBruce Richardson #define BPF_LD_REG(reg, ins, type)	\
5599a2dd95SBruce Richardson 	((reg)[(ins)->dst_reg] = \
5699a2dd95SBruce Richardson 		*(type *)(uintptr_t)((reg)[(ins)->src_reg] + (ins)->off))
5799a2dd95SBruce Richardson 
5899a2dd95SBruce Richardson #define BPF_ST_IMM(reg, ins, type)	\
5999a2dd95SBruce Richardson 	(*(type *)(uintptr_t)((reg)[(ins)->dst_reg] + (ins)->off) = \
6099a2dd95SBruce Richardson 		(type)(ins)->imm)
6199a2dd95SBruce Richardson 
6299a2dd95SBruce Richardson #define BPF_ST_REG(reg, ins, type)	\
6399a2dd95SBruce Richardson 	(*(type *)(uintptr_t)((reg)[(ins)->dst_reg] + (ins)->off) = \
6499a2dd95SBruce Richardson 		(type)(reg)[(ins)->src_reg])
6599a2dd95SBruce Richardson 
6699a2dd95SBruce Richardson #define BPF_ST_XADD_REG(reg, ins, tp)	\
6799a2dd95SBruce Richardson 	(rte_atomic##tp##_add((rte_atomic##tp##_t *) \
6899a2dd95SBruce Richardson 		(uintptr_t)((reg)[(ins)->dst_reg] + (ins)->off), \
6999a2dd95SBruce Richardson 		reg[ins->src_reg]))
7099a2dd95SBruce Richardson 
7199a2dd95SBruce Richardson /* BPF_LD | BPF_ABS/BPF_IND */
7299a2dd95SBruce Richardson 
7399a2dd95SBruce Richardson #define	NOP(x)	(x)
7499a2dd95SBruce Richardson 
7599a2dd95SBruce Richardson #define BPF_LD_ABS(bpf, reg, ins, type, op) do { \
7699a2dd95SBruce Richardson 	const type *p = bpf_ld_mbuf(bpf, reg, ins, (ins)->imm, sizeof(type)); \
7799a2dd95SBruce Richardson 	if (p == NULL)  \
7899a2dd95SBruce Richardson 		return 0; \
7999a2dd95SBruce Richardson 	reg[EBPF_REG_0] = op(p[0]); \
8099a2dd95SBruce Richardson } while (0)
8199a2dd95SBruce Richardson 
8299a2dd95SBruce Richardson #define BPF_LD_IND(bpf, reg, ins, type, op) do { \
8399a2dd95SBruce Richardson 	uint32_t ofs = reg[ins->src_reg] + (ins)->imm; \
8499a2dd95SBruce Richardson 	const type *p = bpf_ld_mbuf(bpf, reg, ins, ofs, sizeof(type)); \
8599a2dd95SBruce Richardson 	if (p == NULL)  \
8699a2dd95SBruce Richardson 		return 0; \
8799a2dd95SBruce Richardson 	reg[EBPF_REG_0] = op(p[0]); \
8899a2dd95SBruce Richardson } while (0)
8999a2dd95SBruce Richardson 
9099a2dd95SBruce Richardson 
9199a2dd95SBruce Richardson static inline void
bpf_alu_be(uint64_t reg[EBPF_REG_NUM],const struct ebpf_insn * ins)9299a2dd95SBruce Richardson bpf_alu_be(uint64_t reg[EBPF_REG_NUM], const struct ebpf_insn *ins)
9399a2dd95SBruce Richardson {
9499a2dd95SBruce Richardson 	uint64_t *v;
9599a2dd95SBruce Richardson 
9699a2dd95SBruce Richardson 	v = reg + ins->dst_reg;
9799a2dd95SBruce Richardson 	switch (ins->imm) {
9899a2dd95SBruce Richardson 	case 16:
9999a2dd95SBruce Richardson 		*v = rte_cpu_to_be_16(*v);
10099a2dd95SBruce Richardson 		break;
10199a2dd95SBruce Richardson 	case 32:
10299a2dd95SBruce Richardson 		*v = rte_cpu_to_be_32(*v);
10399a2dd95SBruce Richardson 		break;
10499a2dd95SBruce Richardson 	case 64:
10599a2dd95SBruce Richardson 		*v = rte_cpu_to_be_64(*v);
10699a2dd95SBruce Richardson 		break;
10799a2dd95SBruce Richardson 	}
10899a2dd95SBruce Richardson }
10999a2dd95SBruce Richardson 
11099a2dd95SBruce Richardson static inline void
bpf_alu_le(uint64_t reg[EBPF_REG_NUM],const struct ebpf_insn * ins)11199a2dd95SBruce Richardson bpf_alu_le(uint64_t reg[EBPF_REG_NUM], const struct ebpf_insn *ins)
11299a2dd95SBruce Richardson {
11399a2dd95SBruce Richardson 	uint64_t *v;
11499a2dd95SBruce Richardson 
11599a2dd95SBruce Richardson 	v = reg + ins->dst_reg;
11699a2dd95SBruce Richardson 	switch (ins->imm) {
11799a2dd95SBruce Richardson 	case 16:
11899a2dd95SBruce Richardson 		*v = rte_cpu_to_le_16(*v);
11999a2dd95SBruce Richardson 		break;
12099a2dd95SBruce Richardson 	case 32:
12199a2dd95SBruce Richardson 		*v = rte_cpu_to_le_32(*v);
12299a2dd95SBruce Richardson 		break;
12399a2dd95SBruce Richardson 	case 64:
12499a2dd95SBruce Richardson 		*v = rte_cpu_to_le_64(*v);
12599a2dd95SBruce Richardson 		break;
12699a2dd95SBruce Richardson 	}
12799a2dd95SBruce Richardson }
12899a2dd95SBruce Richardson 
12999a2dd95SBruce Richardson static inline const void *
bpf_ld_mbuf(const struct rte_bpf * bpf,uint64_t reg[EBPF_REG_NUM],const struct ebpf_insn * ins,uint32_t off,uint32_t len)13099a2dd95SBruce Richardson bpf_ld_mbuf(const struct rte_bpf *bpf, uint64_t reg[EBPF_REG_NUM],
13199a2dd95SBruce Richardson 	const struct ebpf_insn *ins, uint32_t off, uint32_t len)
13299a2dd95SBruce Richardson {
13399a2dd95SBruce Richardson 	const struct rte_mbuf *mb;
13499a2dd95SBruce Richardson 	const void *p;
13599a2dd95SBruce Richardson 
13699a2dd95SBruce Richardson 	mb = (const struct rte_mbuf *)(uintptr_t)reg[EBPF_REG_6];
13799a2dd95SBruce Richardson 	p = rte_pktmbuf_read(mb, off, len, reg + EBPF_REG_0);
13899a2dd95SBruce Richardson 	if (p == NULL)
139*0e21c7c0SDavid Marchand 		RTE_BPF_LOG_LINE(DEBUG, "%s(bpf=%p, mbuf=%p, ofs=%u, len=%u): "
140*0e21c7c0SDavid Marchand 			"load beyond packet boundary at pc: %#zx;",
14199a2dd95SBruce Richardson 			__func__, bpf, mb, off, len,
14299a2dd95SBruce Richardson 			(uintptr_t)(ins) - (uintptr_t)(bpf)->prm.ins);
14399a2dd95SBruce Richardson 	return p;
14499a2dd95SBruce Richardson }
14599a2dd95SBruce Richardson 
14699a2dd95SBruce Richardson static inline uint64_t
bpf_exec(const struct rte_bpf * bpf,uint64_t reg[EBPF_REG_NUM])14799a2dd95SBruce Richardson bpf_exec(const struct rte_bpf *bpf, uint64_t reg[EBPF_REG_NUM])
14899a2dd95SBruce Richardson {
14999a2dd95SBruce Richardson 	const struct ebpf_insn *ins;
15099a2dd95SBruce Richardson 
15199a2dd95SBruce Richardson 	for (ins = bpf->prm.ins; ; ins++) {
15299a2dd95SBruce Richardson 		switch (ins->code) {
15399a2dd95SBruce Richardson 		/* 32 bit ALU IMM operations */
15499a2dd95SBruce Richardson 		case (BPF_ALU | BPF_ADD | BPF_K):
15599a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, +, uint32_t);
15699a2dd95SBruce Richardson 			break;
15799a2dd95SBruce Richardson 		case (BPF_ALU | BPF_SUB | BPF_K):
15899a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, -, uint32_t);
15999a2dd95SBruce Richardson 			break;
16099a2dd95SBruce Richardson 		case (BPF_ALU | BPF_AND | BPF_K):
16199a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, &, uint32_t);
16299a2dd95SBruce Richardson 			break;
16399a2dd95SBruce Richardson 		case (BPF_ALU | BPF_OR | BPF_K):
16499a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, |, uint32_t);
16599a2dd95SBruce Richardson 			break;
16699a2dd95SBruce Richardson 		case (BPF_ALU | BPF_LSH | BPF_K):
16799a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, <<, uint32_t);
16899a2dd95SBruce Richardson 			break;
16999a2dd95SBruce Richardson 		case (BPF_ALU | BPF_RSH | BPF_K):
17099a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, >>, uint32_t);
17199a2dd95SBruce Richardson 			break;
17299a2dd95SBruce Richardson 		case (BPF_ALU | BPF_XOR | BPF_K):
17399a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, ^, uint32_t);
17499a2dd95SBruce Richardson 			break;
17599a2dd95SBruce Richardson 		case (BPF_ALU | BPF_MUL | BPF_K):
17699a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, *, uint32_t);
17799a2dd95SBruce Richardson 			break;
17899a2dd95SBruce Richardson 		case (BPF_ALU | BPF_DIV | BPF_K):
17999a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, /, uint32_t);
18099a2dd95SBruce Richardson 			break;
18199a2dd95SBruce Richardson 		case (BPF_ALU | BPF_MOD | BPF_K):
18299a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, %, uint32_t);
18399a2dd95SBruce Richardson 			break;
18499a2dd95SBruce Richardson 		case (BPF_ALU | EBPF_MOV | BPF_K):
18599a2dd95SBruce Richardson 			EBPF_MOV_ALU_IMM(reg, ins, uint32_t);
18699a2dd95SBruce Richardson 			break;
18799a2dd95SBruce Richardson 		/* 32 bit ALU REG operations */
18899a2dd95SBruce Richardson 		case (BPF_ALU | BPF_ADD | BPF_X):
18999a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, +, uint32_t);
19099a2dd95SBruce Richardson 			break;
19199a2dd95SBruce Richardson 		case (BPF_ALU | BPF_SUB | BPF_X):
19299a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, -, uint32_t);
19399a2dd95SBruce Richardson 			break;
19499a2dd95SBruce Richardson 		case (BPF_ALU | BPF_AND | BPF_X):
19599a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, &, uint32_t);
19699a2dd95SBruce Richardson 			break;
19799a2dd95SBruce Richardson 		case (BPF_ALU | BPF_OR | BPF_X):
19899a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, |, uint32_t);
19999a2dd95SBruce Richardson 			break;
20099a2dd95SBruce Richardson 		case (BPF_ALU | BPF_LSH | BPF_X):
20199a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, <<, uint32_t);
20299a2dd95SBruce Richardson 			break;
20399a2dd95SBruce Richardson 		case (BPF_ALU | BPF_RSH | BPF_X):
20499a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, >>, uint32_t);
20599a2dd95SBruce Richardson 			break;
20699a2dd95SBruce Richardson 		case (BPF_ALU | BPF_XOR | BPF_X):
20799a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, ^, uint32_t);
20899a2dd95SBruce Richardson 			break;
20999a2dd95SBruce Richardson 		case (BPF_ALU | BPF_MUL | BPF_X):
21099a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, *, uint32_t);
21199a2dd95SBruce Richardson 			break;
21299a2dd95SBruce Richardson 		case (BPF_ALU | BPF_DIV | BPF_X):
21399a2dd95SBruce Richardson 			BPF_DIV_ZERO_CHECK(bpf, reg, ins, uint32_t);
21499a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, /, uint32_t);
21599a2dd95SBruce Richardson 			break;
21699a2dd95SBruce Richardson 		case (BPF_ALU | BPF_MOD | BPF_X):
21799a2dd95SBruce Richardson 			BPF_DIV_ZERO_CHECK(bpf, reg, ins, uint32_t);
21899a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, %, uint32_t);
21999a2dd95SBruce Richardson 			break;
22099a2dd95SBruce Richardson 		case (BPF_ALU | EBPF_MOV | BPF_X):
22199a2dd95SBruce Richardson 			EBPF_MOV_ALU_REG(reg, ins, uint32_t);
22299a2dd95SBruce Richardson 			break;
22399a2dd95SBruce Richardson 		case (BPF_ALU | BPF_NEG):
22499a2dd95SBruce Richardson 			BPF_NEG_ALU(reg, ins, uint32_t);
22599a2dd95SBruce Richardson 			break;
22699a2dd95SBruce Richardson 		case (BPF_ALU | EBPF_END | EBPF_TO_BE):
22799a2dd95SBruce Richardson 			bpf_alu_be(reg, ins);
22899a2dd95SBruce Richardson 			break;
22999a2dd95SBruce Richardson 		case (BPF_ALU | EBPF_END | EBPF_TO_LE):
23099a2dd95SBruce Richardson 			bpf_alu_le(reg, ins);
23199a2dd95SBruce Richardson 			break;
23299a2dd95SBruce Richardson 		/* 64 bit ALU IMM operations */
23399a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_ADD | BPF_K):
23499a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, +, uint64_t);
23599a2dd95SBruce Richardson 			break;
23699a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_SUB | BPF_K):
23799a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, -, uint64_t);
23899a2dd95SBruce Richardson 			break;
23999a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_AND | BPF_K):
24099a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, &, uint64_t);
24199a2dd95SBruce Richardson 			break;
24299a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_OR | BPF_K):
24399a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, |, uint64_t);
24499a2dd95SBruce Richardson 			break;
24599a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_LSH | BPF_K):
24699a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, <<, uint64_t);
24799a2dd95SBruce Richardson 			break;
24899a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_RSH | BPF_K):
24999a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, >>, uint64_t);
25099a2dd95SBruce Richardson 			break;
25199a2dd95SBruce Richardson 		case (EBPF_ALU64 | EBPF_ARSH | BPF_K):
25299a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, >>, int64_t);
25399a2dd95SBruce Richardson 			break;
25499a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_XOR | BPF_K):
25599a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, ^, uint64_t);
25699a2dd95SBruce Richardson 			break;
25799a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_MUL | BPF_K):
25899a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, *, uint64_t);
25999a2dd95SBruce Richardson 			break;
26099a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_DIV | BPF_K):
26199a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, /, uint64_t);
26299a2dd95SBruce Richardson 			break;
26399a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_MOD | BPF_K):
26499a2dd95SBruce Richardson 			BPF_OP_ALU_IMM(reg, ins, %, uint64_t);
26599a2dd95SBruce Richardson 			break;
26699a2dd95SBruce Richardson 		case (EBPF_ALU64 | EBPF_MOV | BPF_K):
26799a2dd95SBruce Richardson 			EBPF_MOV_ALU_IMM(reg, ins, uint64_t);
26899a2dd95SBruce Richardson 			break;
26999a2dd95SBruce Richardson 		/* 64 bit ALU REG operations */
27099a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_ADD | BPF_X):
27199a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, +, uint64_t);
27299a2dd95SBruce Richardson 			break;
27399a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_SUB | BPF_X):
27499a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, -, uint64_t);
27599a2dd95SBruce Richardson 			break;
27699a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_AND | BPF_X):
27799a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, &, uint64_t);
27899a2dd95SBruce Richardson 			break;
27999a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_OR | BPF_X):
28099a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, |, uint64_t);
28199a2dd95SBruce Richardson 			break;
28299a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_LSH | BPF_X):
28399a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, <<, uint64_t);
28499a2dd95SBruce Richardson 			break;
28599a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_RSH | BPF_X):
28699a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, >>, uint64_t);
28799a2dd95SBruce Richardson 			break;
28899a2dd95SBruce Richardson 		case (EBPF_ALU64 | EBPF_ARSH | BPF_X):
28999a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, >>, int64_t);
29099a2dd95SBruce Richardson 			break;
29199a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_XOR | BPF_X):
29299a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, ^, uint64_t);
29399a2dd95SBruce Richardson 			break;
29499a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_MUL | BPF_X):
29599a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, *, uint64_t);
29699a2dd95SBruce Richardson 			break;
29799a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_DIV | BPF_X):
29899a2dd95SBruce Richardson 			BPF_DIV_ZERO_CHECK(bpf, reg, ins, uint64_t);
29999a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, /, uint64_t);
30099a2dd95SBruce Richardson 			break;
30199a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_MOD | BPF_X):
30299a2dd95SBruce Richardson 			BPF_DIV_ZERO_CHECK(bpf, reg, ins, uint64_t);
30399a2dd95SBruce Richardson 			BPF_OP_ALU_REG(reg, ins, %, uint64_t);
30499a2dd95SBruce Richardson 			break;
30599a2dd95SBruce Richardson 		case (EBPF_ALU64 | EBPF_MOV | BPF_X):
30699a2dd95SBruce Richardson 			EBPF_MOV_ALU_REG(reg, ins, uint64_t);
30799a2dd95SBruce Richardson 			break;
30899a2dd95SBruce Richardson 		case (EBPF_ALU64 | BPF_NEG):
30999a2dd95SBruce Richardson 			BPF_NEG_ALU(reg, ins, uint64_t);
31099a2dd95SBruce Richardson 			break;
31199a2dd95SBruce Richardson 		/* load instructions */
31299a2dd95SBruce Richardson 		case (BPF_LDX | BPF_MEM | BPF_B):
31399a2dd95SBruce Richardson 			BPF_LD_REG(reg, ins, uint8_t);
31499a2dd95SBruce Richardson 			break;
31599a2dd95SBruce Richardson 		case (BPF_LDX | BPF_MEM | BPF_H):
31699a2dd95SBruce Richardson 			BPF_LD_REG(reg, ins, uint16_t);
31799a2dd95SBruce Richardson 			break;
31899a2dd95SBruce Richardson 		case (BPF_LDX | BPF_MEM | BPF_W):
31999a2dd95SBruce Richardson 			BPF_LD_REG(reg, ins, uint32_t);
32099a2dd95SBruce Richardson 			break;
32199a2dd95SBruce Richardson 		case (BPF_LDX | BPF_MEM | EBPF_DW):
32299a2dd95SBruce Richardson 			BPF_LD_REG(reg, ins, uint64_t);
32399a2dd95SBruce Richardson 			break;
32499a2dd95SBruce Richardson 		/* load 64 bit immediate value */
32599a2dd95SBruce Richardson 		case (BPF_LD | BPF_IMM | EBPF_DW):
32699a2dd95SBruce Richardson 			reg[ins->dst_reg] = (uint32_t)ins[0].imm |
32799a2dd95SBruce Richardson 				(uint64_t)(uint32_t)ins[1].imm << 32;
32899a2dd95SBruce Richardson 			ins++;
32999a2dd95SBruce Richardson 			break;
33099a2dd95SBruce Richardson 		/* load absolute instructions */
33199a2dd95SBruce Richardson 		case (BPF_LD | BPF_ABS | BPF_B):
33299a2dd95SBruce Richardson 			BPF_LD_ABS(bpf, reg, ins, uint8_t, NOP);
33399a2dd95SBruce Richardson 			break;
33499a2dd95SBruce Richardson 		case (BPF_LD | BPF_ABS | BPF_H):
33599a2dd95SBruce Richardson 			BPF_LD_ABS(bpf, reg, ins, uint16_t, rte_be_to_cpu_16);
33699a2dd95SBruce Richardson 			break;
33799a2dd95SBruce Richardson 		case (BPF_LD | BPF_ABS | BPF_W):
33899a2dd95SBruce Richardson 			BPF_LD_ABS(bpf, reg, ins, uint32_t, rte_be_to_cpu_32);
33999a2dd95SBruce Richardson 			break;
34099a2dd95SBruce Richardson 		/* load indirect instructions */
34199a2dd95SBruce Richardson 		case (BPF_LD | BPF_IND | BPF_B):
34299a2dd95SBruce Richardson 			BPF_LD_IND(bpf, reg, ins, uint8_t, NOP);
34399a2dd95SBruce Richardson 			break;
34499a2dd95SBruce Richardson 		case (BPF_LD | BPF_IND | BPF_H):
34599a2dd95SBruce Richardson 			BPF_LD_IND(bpf, reg, ins, uint16_t, rte_be_to_cpu_16);
34699a2dd95SBruce Richardson 			break;
34799a2dd95SBruce Richardson 		case (BPF_LD | BPF_IND | BPF_W):
34899a2dd95SBruce Richardson 			BPF_LD_IND(bpf, reg, ins, uint32_t, rte_be_to_cpu_32);
34999a2dd95SBruce Richardson 			break;
35099a2dd95SBruce Richardson 		/* store instructions */
35199a2dd95SBruce Richardson 		case (BPF_STX | BPF_MEM | BPF_B):
35299a2dd95SBruce Richardson 			BPF_ST_REG(reg, ins, uint8_t);
35399a2dd95SBruce Richardson 			break;
35499a2dd95SBruce Richardson 		case (BPF_STX | BPF_MEM | BPF_H):
35599a2dd95SBruce Richardson 			BPF_ST_REG(reg, ins, uint16_t);
35699a2dd95SBruce Richardson 			break;
35799a2dd95SBruce Richardson 		case (BPF_STX | BPF_MEM | BPF_W):
35899a2dd95SBruce Richardson 			BPF_ST_REG(reg, ins, uint32_t);
35999a2dd95SBruce Richardson 			break;
36099a2dd95SBruce Richardson 		case (BPF_STX | BPF_MEM | EBPF_DW):
36199a2dd95SBruce Richardson 			BPF_ST_REG(reg, ins, uint64_t);
36299a2dd95SBruce Richardson 			break;
36399a2dd95SBruce Richardson 		case (BPF_ST | BPF_MEM | BPF_B):
36499a2dd95SBruce Richardson 			BPF_ST_IMM(reg, ins, uint8_t);
36599a2dd95SBruce Richardson 			break;
36699a2dd95SBruce Richardson 		case (BPF_ST | BPF_MEM | BPF_H):
36799a2dd95SBruce Richardson 			BPF_ST_IMM(reg, ins, uint16_t);
36899a2dd95SBruce Richardson 			break;
36999a2dd95SBruce Richardson 		case (BPF_ST | BPF_MEM | BPF_W):
37099a2dd95SBruce Richardson 			BPF_ST_IMM(reg, ins, uint32_t);
37199a2dd95SBruce Richardson 			break;
37299a2dd95SBruce Richardson 		case (BPF_ST | BPF_MEM | EBPF_DW):
37399a2dd95SBruce Richardson 			BPF_ST_IMM(reg, ins, uint64_t);
37499a2dd95SBruce Richardson 			break;
37599a2dd95SBruce Richardson 		/* atomic add instructions */
37699a2dd95SBruce Richardson 		case (BPF_STX | EBPF_XADD | BPF_W):
37799a2dd95SBruce Richardson 			BPF_ST_XADD_REG(reg, ins, 32);
37899a2dd95SBruce Richardson 			break;
37999a2dd95SBruce Richardson 		case (BPF_STX | EBPF_XADD | EBPF_DW):
38099a2dd95SBruce Richardson 			BPF_ST_XADD_REG(reg, ins, 64);
38199a2dd95SBruce Richardson 			break;
38299a2dd95SBruce Richardson 		/* jump instructions */
38399a2dd95SBruce Richardson 		case (BPF_JMP | BPF_JA):
38499a2dd95SBruce Richardson 			BPF_JMP_UNC(ins);
38599a2dd95SBruce Richardson 			break;
38699a2dd95SBruce Richardson 		/* jump IMM instructions */
38799a2dd95SBruce Richardson 		case (BPF_JMP | BPF_JEQ | BPF_K):
38899a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, ==, uint64_t);
38999a2dd95SBruce Richardson 			break;
39099a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JNE | BPF_K):
39199a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, !=, uint64_t);
39299a2dd95SBruce Richardson 			break;
39399a2dd95SBruce Richardson 		case (BPF_JMP | BPF_JGT | BPF_K):
39499a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, >, uint64_t);
39599a2dd95SBruce Richardson 			break;
39699a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JLT | BPF_K):
39799a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, <, uint64_t);
39899a2dd95SBruce Richardson 			break;
39999a2dd95SBruce Richardson 		case (BPF_JMP | BPF_JGE | BPF_K):
40099a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, >=, uint64_t);
40199a2dd95SBruce Richardson 			break;
40299a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JLE | BPF_K):
40399a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, <=, uint64_t);
40499a2dd95SBruce Richardson 			break;
40599a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JSGT | BPF_K):
40699a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, >, int64_t);
40799a2dd95SBruce Richardson 			break;
40899a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JSLT | BPF_K):
40999a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, <, int64_t);
41099a2dd95SBruce Richardson 			break;
41199a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JSGE | BPF_K):
41299a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, >=, int64_t);
41399a2dd95SBruce Richardson 			break;
41499a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JSLE | BPF_K):
41599a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, <=, int64_t);
41699a2dd95SBruce Richardson 			break;
41799a2dd95SBruce Richardson 		case (BPF_JMP | BPF_JSET | BPF_K):
41899a2dd95SBruce Richardson 			BPF_JMP_CND_IMM(reg, ins, &, uint64_t);
41999a2dd95SBruce Richardson 			break;
42099a2dd95SBruce Richardson 		/* jump REG instructions */
42199a2dd95SBruce Richardson 		case (BPF_JMP | BPF_JEQ | BPF_X):
42299a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, ==, uint64_t);
42399a2dd95SBruce Richardson 			break;
42499a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JNE | BPF_X):
42599a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, !=, uint64_t);
42699a2dd95SBruce Richardson 			break;
42799a2dd95SBruce Richardson 		case (BPF_JMP | BPF_JGT | BPF_X):
42899a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, >, uint64_t);
42999a2dd95SBruce Richardson 			break;
43099a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JLT | BPF_X):
43199a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, <, uint64_t);
43299a2dd95SBruce Richardson 			break;
43399a2dd95SBruce Richardson 		case (BPF_JMP | BPF_JGE | BPF_X):
43499a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, >=, uint64_t);
43599a2dd95SBruce Richardson 			break;
43699a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JLE | BPF_X):
43799a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, <=, uint64_t);
43899a2dd95SBruce Richardson 			break;
43999a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JSGT | BPF_X):
44099a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, >, int64_t);
44199a2dd95SBruce Richardson 			break;
44299a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JSLT | BPF_X):
44399a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, <, int64_t);
44499a2dd95SBruce Richardson 			break;
44599a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JSGE | BPF_X):
44699a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, >=, int64_t);
44799a2dd95SBruce Richardson 			break;
44899a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_JSLE | BPF_X):
44999a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, <=, int64_t);
45099a2dd95SBruce Richardson 			break;
45199a2dd95SBruce Richardson 		case (BPF_JMP | BPF_JSET | BPF_X):
45299a2dd95SBruce Richardson 			BPF_JMP_CND_REG(reg, ins, &, uint64_t);
45399a2dd95SBruce Richardson 			break;
45499a2dd95SBruce Richardson 		/* call instructions */
45599a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_CALL):
45699a2dd95SBruce Richardson 			reg[EBPF_REG_0] = bpf->prm.xsym[ins->imm].func.val(
45799a2dd95SBruce Richardson 				reg[EBPF_REG_1], reg[EBPF_REG_2],
45899a2dd95SBruce Richardson 				reg[EBPF_REG_3], reg[EBPF_REG_4],
45999a2dd95SBruce Richardson 				reg[EBPF_REG_5]);
46099a2dd95SBruce Richardson 			break;
46199a2dd95SBruce Richardson 		/* return instruction */
46299a2dd95SBruce Richardson 		case (BPF_JMP | EBPF_EXIT):
46399a2dd95SBruce Richardson 			return reg[EBPF_REG_0];
46499a2dd95SBruce Richardson 		default:
465*0e21c7c0SDavid Marchand 			RTE_BPF_LOG_LINE(ERR,
466*0e21c7c0SDavid Marchand 				"%s(%p): invalid opcode %#x at pc: %#zx;",
46799a2dd95SBruce Richardson 				__func__, bpf, ins->code,
46899a2dd95SBruce Richardson 				(uintptr_t)ins - (uintptr_t)bpf->prm.ins);
46999a2dd95SBruce Richardson 			return 0;
47099a2dd95SBruce Richardson 		}
47199a2dd95SBruce Richardson 	}
47299a2dd95SBruce Richardson 
47399a2dd95SBruce Richardson 	/* should never be reached */
47499a2dd95SBruce Richardson 	RTE_VERIFY(0);
47599a2dd95SBruce Richardson 	return 0;
47699a2dd95SBruce Richardson }
47799a2dd95SBruce Richardson 
47899a2dd95SBruce Richardson uint32_t
rte_bpf_exec_burst(const struct rte_bpf * bpf,void * ctx[],uint64_t rc[],uint32_t num)47999a2dd95SBruce Richardson rte_bpf_exec_burst(const struct rte_bpf *bpf, void *ctx[], uint64_t rc[],
48099a2dd95SBruce Richardson 	uint32_t num)
48199a2dd95SBruce Richardson {
48299a2dd95SBruce Richardson 	uint32_t i;
48399a2dd95SBruce Richardson 	uint64_t reg[EBPF_REG_NUM];
48499a2dd95SBruce Richardson 	uint64_t stack[MAX_BPF_STACK_SIZE / sizeof(uint64_t)];
48599a2dd95SBruce Richardson 
48699a2dd95SBruce Richardson 	for (i = 0; i != num; i++) {
48799a2dd95SBruce Richardson 
48899a2dd95SBruce Richardson 		reg[EBPF_REG_1] = (uintptr_t)ctx[i];
48999a2dd95SBruce Richardson 		reg[EBPF_REG_10] = (uintptr_t)(stack + RTE_DIM(stack));
49099a2dd95SBruce Richardson 
49199a2dd95SBruce Richardson 		rc[i] = bpf_exec(bpf, reg);
49299a2dd95SBruce Richardson 	}
49399a2dd95SBruce Richardson 
49499a2dd95SBruce Richardson 	return i;
49599a2dd95SBruce Richardson }
49699a2dd95SBruce Richardson 
49799a2dd95SBruce Richardson uint64_t
rte_bpf_exec(const struct rte_bpf * bpf,void * ctx)49899a2dd95SBruce Richardson rte_bpf_exec(const struct rte_bpf *bpf, void *ctx)
49999a2dd95SBruce Richardson {
50099a2dd95SBruce Richardson 	uint64_t rc;
50199a2dd95SBruce Richardson 
50299a2dd95SBruce Richardson 	rte_bpf_exec_burst(bpf, &ctx, &rc, 1);
50399a2dd95SBruce Richardson 	return rc;
50499a2dd95SBruce Richardson }
505