162306a36Sopenharmony_ci/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
262306a36Sopenharmony_ci/* Copyright (C) 2016-2018 Netronome Systems, Inc. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#ifndef __NFP_BPF_H__
562306a36Sopenharmony_ci#define __NFP_BPF_H__ 1
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/bitfield.h>
862306a36Sopenharmony_ci#include <linux/bpf.h>
962306a36Sopenharmony_ci#include <linux/bpf_verifier.h>
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/list.h>
1262306a36Sopenharmony_ci#include <linux/rhashtable.h>
1362306a36Sopenharmony_ci#include <linux/skbuff.h>
1462306a36Sopenharmony_ci#include <linux/types.h>
1562306a36Sopenharmony_ci#include <linux/wait.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "../ccm.h"
1862306a36Sopenharmony_ci#include "../nfp_asm.h"
1962306a36Sopenharmony_ci#include "fw.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define cmsg_warn(bpf, msg...)	nn_dp_warn(&(bpf)->app->ctrl->dp, msg)
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* For relocation logic use up-most byte of branch instruction as scratch
2462306a36Sopenharmony_ci * area.  Remember to clear this before sending instructions to HW!
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci#define OP_RELO_TYPE	0xff00000000000000ULL
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cienum nfp_relo_type {
2962306a36Sopenharmony_ci	RELO_NONE = 0,
3062306a36Sopenharmony_ci	/* standard internal jumps */
3162306a36Sopenharmony_ci	RELO_BR_REL,
3262306a36Sopenharmony_ci	/* internal jumps to parts of the outro */
3362306a36Sopenharmony_ci	RELO_BR_GO_OUT,
3462306a36Sopenharmony_ci	RELO_BR_GO_ABORT,
3562306a36Sopenharmony_ci	RELO_BR_GO_CALL_PUSH_REGS,
3662306a36Sopenharmony_ci	RELO_BR_GO_CALL_POP_REGS,
3762306a36Sopenharmony_ci	/* external jumps to fixed addresses */
3862306a36Sopenharmony_ci	RELO_BR_NEXT_PKT,
3962306a36Sopenharmony_ci	RELO_BR_HELPER,
4062306a36Sopenharmony_ci	/* immediate relocation against load address */
4162306a36Sopenharmony_ci	RELO_IMMED_REL,
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/* To make absolute relocated branches (branches other than RELO_BR_REL)
4562306a36Sopenharmony_ci * distinguishable in user space dumps from normal jumps, add a large offset
4662306a36Sopenharmony_ci * to them.
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_ci#define BR_OFF_RELO		15000
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cienum static_regs {
5162306a36Sopenharmony_ci	STATIC_REG_IMMA		= 20, /* Bank AB */
5262306a36Sopenharmony_ci	STATIC_REG_IMM		= 21, /* Bank AB */
5362306a36Sopenharmony_ci	STATIC_REG_STACK	= 22, /* Bank A */
5462306a36Sopenharmony_ci	STATIC_REG_PKT_LEN	= 22, /* Bank B */
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cienum pkt_vec {
5862306a36Sopenharmony_ci	PKT_VEC_PKT_LEN		= 0,
5962306a36Sopenharmony_ci	PKT_VEC_PKT_PTR		= 2,
6062306a36Sopenharmony_ci	PKT_VEC_QSEL_SET	= 4,
6162306a36Sopenharmony_ci	PKT_VEC_QSEL_VAL	= 6,
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci#define PKT_VEL_QSEL_SET_BIT	4
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#define pv_len(np)	reg_lm(1, PKT_VEC_PKT_LEN)
6762306a36Sopenharmony_ci#define pv_ctm_ptr(np)	reg_lm(1, PKT_VEC_PKT_PTR)
6862306a36Sopenharmony_ci#define pv_qsel_set(np)	reg_lm(1, PKT_VEC_QSEL_SET)
6962306a36Sopenharmony_ci#define pv_qsel_val(np)	reg_lm(1, PKT_VEC_QSEL_VAL)
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci#define stack_reg(np)	reg_a(STATIC_REG_STACK)
7262306a36Sopenharmony_ci#define stack_imm(np)	imm_b(np)
7362306a36Sopenharmony_ci#define plen_reg(np)	reg_b(STATIC_REG_PKT_LEN)
7462306a36Sopenharmony_ci#define pptr_reg(np)	pv_ctm_ptr(np)
7562306a36Sopenharmony_ci#define imm_a(np)	reg_a(STATIC_REG_IMM)
7662306a36Sopenharmony_ci#define imm_b(np)	reg_b(STATIC_REG_IMM)
7762306a36Sopenharmony_ci#define imma_a(np)	reg_a(STATIC_REG_IMMA)
7862306a36Sopenharmony_ci#define imma_b(np)	reg_b(STATIC_REG_IMMA)
7962306a36Sopenharmony_ci#define imm_both(np)	reg_both(STATIC_REG_IMM)
8062306a36Sopenharmony_ci#define ret_reg(np)	imm_a(np)
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci#define NFP_BPF_ABI_FLAGS	reg_imm(0)
8362306a36Sopenharmony_ci#define   NFP_BPF_ABI_FLAG_MARK	1
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci/**
8662306a36Sopenharmony_ci * struct nfp_app_bpf - bpf app priv structure
8762306a36Sopenharmony_ci * @app:		backpointer to the app
8862306a36Sopenharmony_ci * @ccm:		common control message handler data
8962306a36Sopenharmony_ci *
9062306a36Sopenharmony_ci * @bpf_dev:		BPF offload device handle
9162306a36Sopenharmony_ci *
9262306a36Sopenharmony_ci * @cmsg_key_sz:	size of key in cmsg element array
9362306a36Sopenharmony_ci * @cmsg_val_sz:	size of value in cmsg element array
9462306a36Sopenharmony_ci *
9562306a36Sopenharmony_ci * @map_list:		list of offloaded maps
9662306a36Sopenharmony_ci * @maps_in_use:	number of currently offloaded maps
9762306a36Sopenharmony_ci * @map_elems_in_use:	number of elements allocated to offloaded maps
9862306a36Sopenharmony_ci *
9962306a36Sopenharmony_ci * @maps_neutral:	hash table of offload-neutral maps (on pointer)
10062306a36Sopenharmony_ci *
10162306a36Sopenharmony_ci * @abi_version:	global BPF ABI version
10262306a36Sopenharmony_ci * @cmsg_cache_cnt:	number of entries to read for caching
10362306a36Sopenharmony_ci *
10462306a36Sopenharmony_ci * @adjust_head:	adjust head capability
10562306a36Sopenharmony_ci * @adjust_head.flags:		extra flags for adjust head
10662306a36Sopenharmony_ci * @adjust_head.off_min:	minimal packet offset within buffer required
10762306a36Sopenharmony_ci * @adjust_head.off_max:	maximum packet offset within buffer required
10862306a36Sopenharmony_ci * @adjust_head.guaranteed_sub:	negative adjustment guaranteed possible
10962306a36Sopenharmony_ci * @adjust_head.guaranteed_add:	positive adjustment guaranteed possible
11062306a36Sopenharmony_ci *
11162306a36Sopenharmony_ci * @maps:		map capability
11262306a36Sopenharmony_ci * @maps.types:			supported map types
11362306a36Sopenharmony_ci * @maps.max_maps:		max number of maps supported
11462306a36Sopenharmony_ci * @maps.max_elems:		max number of entries in each map
11562306a36Sopenharmony_ci * @maps.max_key_sz:		max size of map key
11662306a36Sopenharmony_ci * @maps.max_val_sz:		max size of map value
11762306a36Sopenharmony_ci * @maps.max_elem_sz:		max size of map entry (key + value)
11862306a36Sopenharmony_ci *
11962306a36Sopenharmony_ci * @helpers:		helper addressess for various calls
12062306a36Sopenharmony_ci * @helpers.map_lookup:		map lookup helper address
12162306a36Sopenharmony_ci * @helpers.map_update:		map update helper address
12262306a36Sopenharmony_ci * @helpers.map_delete:		map delete helper address
12362306a36Sopenharmony_ci * @helpers.perf_event_output:	output perf event to a ring buffer
12462306a36Sopenharmony_ci *
12562306a36Sopenharmony_ci * @pseudo_random:	FW initialized the pseudo-random machinery (CSRs)
12662306a36Sopenharmony_ci * @queue_select:	BPF can set the RX queue ID in packet vector
12762306a36Sopenharmony_ci * @adjust_tail:	BPF can simply trunc packet size for adjust tail
12862306a36Sopenharmony_ci * @cmsg_multi_ent:	FW can pack multiple map entries in a single cmsg
12962306a36Sopenharmony_ci */
13062306a36Sopenharmony_cistruct nfp_app_bpf {
13162306a36Sopenharmony_ci	struct nfp_app *app;
13262306a36Sopenharmony_ci	struct nfp_ccm ccm;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	struct bpf_offload_dev *bpf_dev;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	unsigned int cmsg_key_sz;
13762306a36Sopenharmony_ci	unsigned int cmsg_val_sz;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	unsigned int cmsg_cache_cnt;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	struct list_head map_list;
14262306a36Sopenharmony_ci	unsigned int maps_in_use;
14362306a36Sopenharmony_ci	unsigned int map_elems_in_use;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	struct rhashtable maps_neutral;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	u32 abi_version;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	struct nfp_bpf_cap_adjust_head {
15062306a36Sopenharmony_ci		u32 flags;
15162306a36Sopenharmony_ci		int off_min;
15262306a36Sopenharmony_ci		int off_max;
15362306a36Sopenharmony_ci		int guaranteed_sub;
15462306a36Sopenharmony_ci		int guaranteed_add;
15562306a36Sopenharmony_ci	} adjust_head;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	struct {
15862306a36Sopenharmony_ci		u32 types;
15962306a36Sopenharmony_ci		u32 max_maps;
16062306a36Sopenharmony_ci		u32 max_elems;
16162306a36Sopenharmony_ci		u32 max_key_sz;
16262306a36Sopenharmony_ci		u32 max_val_sz;
16362306a36Sopenharmony_ci		u32 max_elem_sz;
16462306a36Sopenharmony_ci	} maps;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	struct {
16762306a36Sopenharmony_ci		u32 map_lookup;
16862306a36Sopenharmony_ci		u32 map_update;
16962306a36Sopenharmony_ci		u32 map_delete;
17062306a36Sopenharmony_ci		u32 perf_event_output;
17162306a36Sopenharmony_ci	} helpers;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	bool pseudo_random;
17462306a36Sopenharmony_ci	bool queue_select;
17562306a36Sopenharmony_ci	bool adjust_tail;
17662306a36Sopenharmony_ci	bool cmsg_multi_ent;
17762306a36Sopenharmony_ci};
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_cienum nfp_bpf_map_use {
18062306a36Sopenharmony_ci	NFP_MAP_UNUSED = 0,
18162306a36Sopenharmony_ci	NFP_MAP_USE_READ,
18262306a36Sopenharmony_ci	NFP_MAP_USE_WRITE,
18362306a36Sopenharmony_ci	NFP_MAP_USE_ATOMIC_CNT,
18462306a36Sopenharmony_ci};
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistruct nfp_bpf_map_word {
18762306a36Sopenharmony_ci	unsigned char type		:4;
18862306a36Sopenharmony_ci	unsigned char non_zero_update	:1;
18962306a36Sopenharmony_ci};
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci#define NFP_BPF_MAP_CACHE_CNT		4U
19262306a36Sopenharmony_ci#define NFP_BPF_MAP_CACHE_TIME_NS	(250 * 1000)
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci/**
19562306a36Sopenharmony_ci * struct nfp_bpf_map - private per-map data attached to BPF maps for offload
19662306a36Sopenharmony_ci * @offmap:	pointer to the offloaded BPF map
19762306a36Sopenharmony_ci * @bpf:	back pointer to bpf app private structure
19862306a36Sopenharmony_ci * @tid:	table id identifying map on datapath
19962306a36Sopenharmony_ci *
20062306a36Sopenharmony_ci * @cache_lock:	protects @cache_blockers, @cache_to, @cache
20162306a36Sopenharmony_ci * @cache_blockers:	number of ops in flight which block caching
20262306a36Sopenharmony_ci * @cache_gen:	counter incremented by every blocker on exit
20362306a36Sopenharmony_ci * @cache_to:	time when cache will no longer be valid (ns)
20462306a36Sopenharmony_ci * @cache:	skb with cached response
20562306a36Sopenharmony_ci *
20662306a36Sopenharmony_ci * @l:		link on the nfp_app_bpf->map_list list
20762306a36Sopenharmony_ci * @use_map:	map of how the value is used (in 4B chunks)
20862306a36Sopenharmony_ci */
20962306a36Sopenharmony_cistruct nfp_bpf_map {
21062306a36Sopenharmony_ci	struct bpf_offloaded_map *offmap;
21162306a36Sopenharmony_ci	struct nfp_app_bpf *bpf;
21262306a36Sopenharmony_ci	u32 tid;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	spinlock_t cache_lock;
21562306a36Sopenharmony_ci	u32 cache_blockers;
21662306a36Sopenharmony_ci	u32 cache_gen;
21762306a36Sopenharmony_ci	u64 cache_to;
21862306a36Sopenharmony_ci	struct sk_buff *cache;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	struct list_head l;
22162306a36Sopenharmony_ci	struct nfp_bpf_map_word use_map[];
22262306a36Sopenharmony_ci};
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistruct nfp_bpf_neutral_map {
22562306a36Sopenharmony_ci	struct rhash_head l;
22662306a36Sopenharmony_ci	struct bpf_map *ptr;
22762306a36Sopenharmony_ci	u32 map_id;
22862306a36Sopenharmony_ci	u32 count;
22962306a36Sopenharmony_ci};
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ciextern const struct rhashtable_params nfp_bpf_maps_neutral_params;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cistruct nfp_prog;
23462306a36Sopenharmony_cistruct nfp_insn_meta;
23562306a36Sopenharmony_citypedef int (*instr_cb_t)(struct nfp_prog *, struct nfp_insn_meta *);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci#define nfp_prog_first_meta(nfp_prog)					\
23862306a36Sopenharmony_ci	list_first_entry(&(nfp_prog)->insns, struct nfp_insn_meta, l)
23962306a36Sopenharmony_ci#define nfp_prog_last_meta(nfp_prog)					\
24062306a36Sopenharmony_ci	list_last_entry(&(nfp_prog)->insns, struct nfp_insn_meta, l)
24162306a36Sopenharmony_ci#define nfp_meta_next(meta)	list_next_entry(meta, l)
24262306a36Sopenharmony_ci#define nfp_meta_prev(meta)	list_prev_entry(meta, l)
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci/**
24562306a36Sopenharmony_ci * struct nfp_bpf_reg_state - register state for calls
24662306a36Sopenharmony_ci * @reg: BPF register state from latest path
24762306a36Sopenharmony_ci * @var_off: for stack arg - changes stack offset on different paths
24862306a36Sopenharmony_ci */
24962306a36Sopenharmony_cistruct nfp_bpf_reg_state {
25062306a36Sopenharmony_ci	struct bpf_reg_state reg;
25162306a36Sopenharmony_ci	bool var_off;
25262306a36Sopenharmony_ci};
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci#define FLAG_INSN_IS_JUMP_DST			BIT(0)
25562306a36Sopenharmony_ci#define FLAG_INSN_IS_SUBPROG_START		BIT(1)
25662306a36Sopenharmony_ci#define FLAG_INSN_PTR_CALLER_STACK_FRAME	BIT(2)
25762306a36Sopenharmony_ci/* Instruction is pointless, noop even on its own */
25862306a36Sopenharmony_ci#define FLAG_INSN_SKIP_NOOP			BIT(3)
25962306a36Sopenharmony_ci/* Instruction is optimized out based on preceding instructions */
26062306a36Sopenharmony_ci#define FLAG_INSN_SKIP_PREC_DEPENDENT		BIT(4)
26162306a36Sopenharmony_ci/* Instruction is optimized by the verifier */
26262306a36Sopenharmony_ci#define FLAG_INSN_SKIP_VERIFIER_OPT		BIT(5)
26362306a36Sopenharmony_ci/* Instruction needs to zero extend to high 32-bit */
26462306a36Sopenharmony_ci#define FLAG_INSN_DO_ZEXT			BIT(6)
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci#define FLAG_INSN_SKIP_MASK		(FLAG_INSN_SKIP_NOOP | \
26762306a36Sopenharmony_ci					 FLAG_INSN_SKIP_PREC_DEPENDENT | \
26862306a36Sopenharmony_ci					 FLAG_INSN_SKIP_VERIFIER_OPT)
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci/**
27162306a36Sopenharmony_ci * struct nfp_insn_meta - BPF instruction wrapper
27262306a36Sopenharmony_ci * @insn: BPF instruction
27362306a36Sopenharmony_ci * @ptr: pointer type for memory operations
27462306a36Sopenharmony_ci * @ldst_gather_len: memcpy length gathered from load/store sequence
27562306a36Sopenharmony_ci * @paired_st: the paired store insn at the head of the sequence
27662306a36Sopenharmony_ci * @ptr_not_const: pointer is not always constant
27762306a36Sopenharmony_ci * @pkt_cache: packet data cache information
27862306a36Sopenharmony_ci * @pkt_cache.range_start: start offset for associated packet data cache
27962306a36Sopenharmony_ci * @pkt_cache.range_end: end offset for associated packet data cache
28062306a36Sopenharmony_ci * @pkt_cache.do_init: this read needs to initialize packet data cache
28162306a36Sopenharmony_ci * @xadd_over_16bit: 16bit immediate is not guaranteed
28262306a36Sopenharmony_ci * @xadd_maybe_16bit: 16bit immediate is possible
28362306a36Sopenharmony_ci * @jmp_dst: destination info for jump instructions
28462306a36Sopenharmony_ci * @jump_neg_op: jump instruction has inverted immediate, use ADD instead of SUB
28562306a36Sopenharmony_ci * @num_insns_after_br: number of insns following a branch jump, used for fixup
28662306a36Sopenharmony_ci * @func_id: function id for call instructions
28762306a36Sopenharmony_ci * @arg1: arg1 for call instructions
28862306a36Sopenharmony_ci * @arg2: arg2 for call instructions
28962306a36Sopenharmony_ci * @umin_src: copy of core verifier umin_value for src opearnd.
29062306a36Sopenharmony_ci * @umax_src: copy of core verifier umax_value for src operand.
29162306a36Sopenharmony_ci * @umin_dst: copy of core verifier umin_value for dst opearnd.
29262306a36Sopenharmony_ci * @umax_dst: copy of core verifier umax_value for dst operand.
29362306a36Sopenharmony_ci * @off: index of first generated machine instruction (in nfp_prog.prog)
29462306a36Sopenharmony_ci * @n: eBPF instruction number
29562306a36Sopenharmony_ci * @flags: eBPF instruction extra optimization flags
29662306a36Sopenharmony_ci * @subprog_idx: index of subprogram to which the instruction belongs
29762306a36Sopenharmony_ci * @double_cb: callback for second part of the instruction
29862306a36Sopenharmony_ci * @l: link on nfp_prog->insns list
29962306a36Sopenharmony_ci */
30062306a36Sopenharmony_cistruct nfp_insn_meta {
30162306a36Sopenharmony_ci	struct bpf_insn insn;
30262306a36Sopenharmony_ci	union {
30362306a36Sopenharmony_ci		/* pointer ops (ld/st/xadd) */
30462306a36Sopenharmony_ci		struct {
30562306a36Sopenharmony_ci			struct bpf_reg_state ptr;
30662306a36Sopenharmony_ci			struct bpf_insn *paired_st;
30762306a36Sopenharmony_ci			s16 ldst_gather_len;
30862306a36Sopenharmony_ci			bool ptr_not_const;
30962306a36Sopenharmony_ci			struct {
31062306a36Sopenharmony_ci				s16 range_start;
31162306a36Sopenharmony_ci				s16 range_end;
31262306a36Sopenharmony_ci				bool do_init;
31362306a36Sopenharmony_ci			} pkt_cache;
31462306a36Sopenharmony_ci			bool xadd_over_16bit;
31562306a36Sopenharmony_ci			bool xadd_maybe_16bit;
31662306a36Sopenharmony_ci		};
31762306a36Sopenharmony_ci		/* jump */
31862306a36Sopenharmony_ci		struct {
31962306a36Sopenharmony_ci			struct nfp_insn_meta *jmp_dst;
32062306a36Sopenharmony_ci			bool jump_neg_op;
32162306a36Sopenharmony_ci			u32 num_insns_after_br; /* only for BPF-to-BPF calls */
32262306a36Sopenharmony_ci		};
32362306a36Sopenharmony_ci		/* function calls */
32462306a36Sopenharmony_ci		struct {
32562306a36Sopenharmony_ci			u32 func_id;
32662306a36Sopenharmony_ci			struct bpf_reg_state arg1;
32762306a36Sopenharmony_ci			struct nfp_bpf_reg_state arg2;
32862306a36Sopenharmony_ci		};
32962306a36Sopenharmony_ci		/* We are interested in range info for operands of ALU
33062306a36Sopenharmony_ci		 * operations. For example, shift amount, multiplicand and
33162306a36Sopenharmony_ci		 * multiplier etc.
33262306a36Sopenharmony_ci		 */
33362306a36Sopenharmony_ci		struct {
33462306a36Sopenharmony_ci			u64 umin_src;
33562306a36Sopenharmony_ci			u64 umax_src;
33662306a36Sopenharmony_ci			u64 umin_dst;
33762306a36Sopenharmony_ci			u64 umax_dst;
33862306a36Sopenharmony_ci		};
33962306a36Sopenharmony_ci	};
34062306a36Sopenharmony_ci	unsigned int off;
34162306a36Sopenharmony_ci	unsigned short n;
34262306a36Sopenharmony_ci	unsigned short flags;
34362306a36Sopenharmony_ci	unsigned short subprog_idx;
34462306a36Sopenharmony_ci	instr_cb_t double_cb;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	struct list_head l;
34762306a36Sopenharmony_ci};
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci#define BPF_SIZE_MASK	0x18
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_cistatic inline u8 mbpf_class(const struct nfp_insn_meta *meta)
35262306a36Sopenharmony_ci{
35362306a36Sopenharmony_ci	return BPF_CLASS(meta->insn.code);
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_cistatic inline u8 mbpf_src(const struct nfp_insn_meta *meta)
35762306a36Sopenharmony_ci{
35862306a36Sopenharmony_ci	return BPF_SRC(meta->insn.code);
35962306a36Sopenharmony_ci}
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_cistatic inline u8 mbpf_op(const struct nfp_insn_meta *meta)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	return BPF_OP(meta->insn.code);
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_cistatic inline u8 mbpf_mode(const struct nfp_insn_meta *meta)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	return BPF_MODE(meta->insn.code);
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_cistatic inline bool is_mbpf_alu(const struct nfp_insn_meta *meta)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	return mbpf_class(meta) == BPF_ALU64 || mbpf_class(meta) == BPF_ALU;
37462306a36Sopenharmony_ci}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_cistatic inline bool is_mbpf_load(const struct nfp_insn_meta *meta)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	return (meta->insn.code & ~BPF_SIZE_MASK) == (BPF_LDX | BPF_MEM);
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_cistatic inline bool is_mbpf_jmp32(const struct nfp_insn_meta *meta)
38262306a36Sopenharmony_ci{
38362306a36Sopenharmony_ci	return mbpf_class(meta) == BPF_JMP32;
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic inline bool is_mbpf_jmp64(const struct nfp_insn_meta *meta)
38762306a36Sopenharmony_ci{
38862306a36Sopenharmony_ci	return mbpf_class(meta) == BPF_JMP;
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_cistatic inline bool is_mbpf_jmp(const struct nfp_insn_meta *meta)
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci	return is_mbpf_jmp32(meta) || is_mbpf_jmp64(meta);
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_cistatic inline bool is_mbpf_store(const struct nfp_insn_meta *meta)
39762306a36Sopenharmony_ci{
39862306a36Sopenharmony_ci	return (meta->insn.code & ~BPF_SIZE_MASK) == (BPF_STX | BPF_MEM);
39962306a36Sopenharmony_ci}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic inline bool is_mbpf_load_pkt(const struct nfp_insn_meta *meta)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	return is_mbpf_load(meta) && meta->ptr.type == PTR_TO_PACKET;
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cistatic inline bool is_mbpf_store_pkt(const struct nfp_insn_meta *meta)
40762306a36Sopenharmony_ci{
40862306a36Sopenharmony_ci	return is_mbpf_store(meta) && meta->ptr.type == PTR_TO_PACKET;
40962306a36Sopenharmony_ci}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_cistatic inline bool is_mbpf_classic_load(const struct nfp_insn_meta *meta)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	u8 code = meta->insn.code;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	return BPF_CLASS(code) == BPF_LD &&
41662306a36Sopenharmony_ci	       (BPF_MODE(code) == BPF_ABS || BPF_MODE(code) == BPF_IND);
41762306a36Sopenharmony_ci}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_cistatic inline bool is_mbpf_classic_store(const struct nfp_insn_meta *meta)
42062306a36Sopenharmony_ci{
42162306a36Sopenharmony_ci	u8 code = meta->insn.code;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	return BPF_CLASS(code) == BPF_ST && BPF_MODE(code) == BPF_MEM;
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic inline bool is_mbpf_classic_store_pkt(const struct nfp_insn_meta *meta)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	return is_mbpf_classic_store(meta) && meta->ptr.type == PTR_TO_PACKET;
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cistatic inline bool is_mbpf_atomic(const struct nfp_insn_meta *meta)
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	return (meta->insn.code & ~BPF_SIZE_MASK) == (BPF_STX | BPF_ATOMIC);
43462306a36Sopenharmony_ci}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_cistatic inline bool is_mbpf_mul(const struct nfp_insn_meta *meta)
43762306a36Sopenharmony_ci{
43862306a36Sopenharmony_ci	return is_mbpf_alu(meta) && mbpf_op(meta) == BPF_MUL;
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_cistatic inline bool is_mbpf_div(const struct nfp_insn_meta *meta)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	return is_mbpf_alu(meta) && mbpf_op(meta) == BPF_DIV;
44462306a36Sopenharmony_ci}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_cistatic inline bool is_mbpf_cond_jump(const struct nfp_insn_meta *meta)
44762306a36Sopenharmony_ci{
44862306a36Sopenharmony_ci	u8 op;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	if (is_mbpf_jmp32(meta))
45162306a36Sopenharmony_ci		return true;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	if (!is_mbpf_jmp64(meta))
45462306a36Sopenharmony_ci		return false;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	op = mbpf_op(meta);
45762306a36Sopenharmony_ci	return op != BPF_JA && op != BPF_EXIT && op != BPF_CALL;
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_cistatic inline bool is_mbpf_helper_call(const struct nfp_insn_meta *meta)
46162306a36Sopenharmony_ci{
46262306a36Sopenharmony_ci	struct bpf_insn insn = meta->insn;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	return insn.code == (BPF_JMP | BPF_CALL) &&
46562306a36Sopenharmony_ci		insn.src_reg != BPF_PSEUDO_CALL;
46662306a36Sopenharmony_ci}
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_cistatic inline bool is_mbpf_pseudo_call(const struct nfp_insn_meta *meta)
46962306a36Sopenharmony_ci{
47062306a36Sopenharmony_ci	struct bpf_insn insn = meta->insn;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	return insn.code == (BPF_JMP | BPF_CALL) &&
47362306a36Sopenharmony_ci		insn.src_reg == BPF_PSEUDO_CALL;
47462306a36Sopenharmony_ci}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci#define STACK_FRAME_ALIGN 64
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci/**
47962306a36Sopenharmony_ci * struct nfp_bpf_subprog_info - nfp BPF sub-program (a.k.a. function) info
48062306a36Sopenharmony_ci * @stack_depth:	maximum stack depth used by this sub-program
48162306a36Sopenharmony_ci * @needs_reg_push:	whether sub-program uses callee-saved registers
48262306a36Sopenharmony_ci */
48362306a36Sopenharmony_cistruct nfp_bpf_subprog_info {
48462306a36Sopenharmony_ci	u16 stack_depth;
48562306a36Sopenharmony_ci	u8 needs_reg_push : 1;
48662306a36Sopenharmony_ci};
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci/**
48962306a36Sopenharmony_ci * struct nfp_prog - nfp BPF program
49062306a36Sopenharmony_ci * @bpf: backpointer to the bpf app priv structure
49162306a36Sopenharmony_ci * @prog: machine code
49262306a36Sopenharmony_ci * @prog_len: number of valid instructions in @prog array
49362306a36Sopenharmony_ci * @__prog_alloc_len: alloc size of @prog array
49462306a36Sopenharmony_ci * @stack_size: total amount of stack used
49562306a36Sopenharmony_ci * @verifier_meta: temporary storage for verifier's insn meta
49662306a36Sopenharmony_ci * @type: BPF program type
49762306a36Sopenharmony_ci * @last_bpf_off: address of the last instruction translated from BPF
49862306a36Sopenharmony_ci * @tgt_out: jump target for normal exit
49962306a36Sopenharmony_ci * @tgt_abort: jump target for abort (e.g. access outside of packet buffer)
50062306a36Sopenharmony_ci * @tgt_call_push_regs: jump target for subroutine for saving R6~R9 to stack
50162306a36Sopenharmony_ci * @tgt_call_pop_regs: jump target for subroutine used for restoring R6~R9
50262306a36Sopenharmony_ci * @n_translated: number of successfully translated instructions (for errors)
50362306a36Sopenharmony_ci * @error: error code if something went wrong
50462306a36Sopenharmony_ci * @stack_frame_depth: max stack depth for current frame
50562306a36Sopenharmony_ci * @adjust_head_location: if program has single adjust head call - the insn no.
50662306a36Sopenharmony_ci * @map_records_cnt: the number of map pointers recorded for this prog
50762306a36Sopenharmony_ci * @subprog_cnt: number of sub-programs, including main function
50862306a36Sopenharmony_ci * @map_records: the map record pointers from bpf->maps_neutral
50962306a36Sopenharmony_ci * @subprog: pointer to an array of objects holding info about sub-programs
51062306a36Sopenharmony_ci * @n_insns: number of instructions on @insns list
51162306a36Sopenharmony_ci * @insns: list of BPF instruction wrappers (struct nfp_insn_meta)
51262306a36Sopenharmony_ci */
51362306a36Sopenharmony_cistruct nfp_prog {
51462306a36Sopenharmony_ci	struct nfp_app_bpf *bpf;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	u64 *prog;
51762306a36Sopenharmony_ci	unsigned int prog_len;
51862306a36Sopenharmony_ci	unsigned int __prog_alloc_len;
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	unsigned int stack_size;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	struct nfp_insn_meta *verifier_meta;
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	enum bpf_prog_type type;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	unsigned int last_bpf_off;
52762306a36Sopenharmony_ci	unsigned int tgt_out;
52862306a36Sopenharmony_ci	unsigned int tgt_abort;
52962306a36Sopenharmony_ci	unsigned int tgt_call_push_regs;
53062306a36Sopenharmony_ci	unsigned int tgt_call_pop_regs;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	unsigned int n_translated;
53362306a36Sopenharmony_ci	int error;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	unsigned int stack_frame_depth;
53662306a36Sopenharmony_ci	unsigned int adjust_head_location;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	unsigned int map_records_cnt;
53962306a36Sopenharmony_ci	unsigned int subprog_cnt;
54062306a36Sopenharmony_ci	struct nfp_bpf_neutral_map **map_records;
54162306a36Sopenharmony_ci	struct nfp_bpf_subprog_info *subprog;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	unsigned int n_insns;
54462306a36Sopenharmony_ci	struct list_head insns;
54562306a36Sopenharmony_ci};
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci/**
54862306a36Sopenharmony_ci * struct nfp_bpf_vnic - per-vNIC BPF priv structure
54962306a36Sopenharmony_ci * @tc_prog:	currently loaded cls_bpf program
55062306a36Sopenharmony_ci * @start_off:	address of the first instruction in the memory
55162306a36Sopenharmony_ci * @tgt_done:	jump target to get the next packet
55262306a36Sopenharmony_ci */
55362306a36Sopenharmony_cistruct nfp_bpf_vnic {
55462306a36Sopenharmony_ci	struct bpf_prog *tc_prog;
55562306a36Sopenharmony_ci	unsigned int start_off;
55662306a36Sopenharmony_ci	unsigned int tgt_done;
55762306a36Sopenharmony_ci};
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_cibool nfp_is_subprog_start(struct nfp_insn_meta *meta);
56062306a36Sopenharmony_civoid nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog);
56162306a36Sopenharmony_ciint nfp_bpf_jit(struct nfp_prog *prog);
56262306a36Sopenharmony_cibool nfp_bpf_supported_opcode(u8 code);
56362306a36Sopenharmony_cibool nfp_bpf_offload_check_mtu(struct nfp_net *nn, struct bpf_prog *prog,
56462306a36Sopenharmony_ci			       unsigned int mtu);
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ciint nfp_verify_insn(struct bpf_verifier_env *env, int insn_idx,
56762306a36Sopenharmony_ci		    int prev_insn_idx);
56862306a36Sopenharmony_ciint nfp_bpf_finalize(struct bpf_verifier_env *env);
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ciint nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off,
57162306a36Sopenharmony_ci			     struct bpf_insn *insn);
57262306a36Sopenharmony_ciint nfp_bpf_opt_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt);
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ciextern const struct bpf_prog_offload_ops nfp_bpf_dev_ops;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_cistruct netdev_bpf;
57762306a36Sopenharmony_cistruct nfp_app;
57862306a36Sopenharmony_cistruct nfp_net;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ciint nfp_ndo_bpf(struct nfp_app *app, struct nfp_net *nn,
58162306a36Sopenharmony_ci		struct netdev_bpf *bpf);
58262306a36Sopenharmony_ciint nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
58362306a36Sopenharmony_ci			bool old_prog, struct netlink_ext_ack *extack);
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_cistruct nfp_insn_meta *
58662306a36Sopenharmony_cinfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
58762306a36Sopenharmony_ci		  unsigned int insn_idx);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_civoid *nfp_bpf_relo_for_vnic(struct nfp_prog *nfp_prog, struct nfp_bpf_vnic *bv);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ciunsigned int nfp_bpf_ctrl_cmsg_min_mtu(struct nfp_app_bpf *bpf);
59262306a36Sopenharmony_ciunsigned int nfp_bpf_ctrl_cmsg_mtu(struct nfp_app_bpf *bpf);
59362306a36Sopenharmony_ciunsigned int nfp_bpf_ctrl_cmsg_cache_cnt(struct nfp_app_bpf *bpf);
59462306a36Sopenharmony_cilong long int
59562306a36Sopenharmony_cinfp_bpf_ctrl_alloc_map(struct nfp_app_bpf *bpf, struct bpf_map *map);
59662306a36Sopenharmony_civoid
59762306a36Sopenharmony_cinfp_bpf_ctrl_free_map(struct nfp_app_bpf *bpf, struct nfp_bpf_map *nfp_map);
59862306a36Sopenharmony_ciint nfp_bpf_ctrl_getfirst_entry(struct bpf_offloaded_map *offmap,
59962306a36Sopenharmony_ci				void *next_key);
60062306a36Sopenharmony_ciint nfp_bpf_ctrl_update_entry(struct bpf_offloaded_map *offmap,
60162306a36Sopenharmony_ci			      void *key, void *value, u64 flags);
60262306a36Sopenharmony_ciint nfp_bpf_ctrl_del_entry(struct bpf_offloaded_map *offmap, void *key);
60362306a36Sopenharmony_ciint nfp_bpf_ctrl_lookup_entry(struct bpf_offloaded_map *offmap,
60462306a36Sopenharmony_ci			      void *key, void *value);
60562306a36Sopenharmony_ciint nfp_bpf_ctrl_getnext_entry(struct bpf_offloaded_map *offmap,
60662306a36Sopenharmony_ci			       void *key, void *next_key);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ciint nfp_bpf_event_output(struct nfp_app_bpf *bpf, const void *data,
60962306a36Sopenharmony_ci			 unsigned int len);
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_civoid nfp_bpf_ctrl_msg_rx(struct nfp_app *app, struct sk_buff *skb);
61262306a36Sopenharmony_civoid
61362306a36Sopenharmony_cinfp_bpf_ctrl_msg_rx_raw(struct nfp_app *app, const void *data,
61462306a36Sopenharmony_ci			unsigned int len);
61562306a36Sopenharmony_ci#endif
616