.. | .. |
---|
1 | | -/* |
---|
2 | | - * Copyright (C) 2016-2018 Netronome Systems, Inc. |
---|
3 | | - * |
---|
4 | | - * This software is dual licensed under the GNU General License Version 2, |
---|
5 | | - * June 1991 as shown in the file COPYING in the top-level directory of this |
---|
6 | | - * source tree or the BSD 2-Clause License provided below. You have the |
---|
7 | | - * option to license this software under the complete terms of either license. |
---|
8 | | - * |
---|
9 | | - * The BSD 2-Clause License: |
---|
10 | | - * |
---|
11 | | - * Redistribution and use in source and binary forms, with or |
---|
12 | | - * without modification, are permitted provided that the following |
---|
13 | | - * conditions are met: |
---|
14 | | - * |
---|
15 | | - * 1. Redistributions of source code must retain the above |
---|
16 | | - * copyright notice, this list of conditions and the following |
---|
17 | | - * disclaimer. |
---|
18 | | - * |
---|
19 | | - * 2. Redistributions in binary form must reproduce the above |
---|
20 | | - * copyright notice, this list of conditions and the following |
---|
21 | | - * disclaimer in the documentation and/or other materials |
---|
22 | | - * provided with the distribution. |
---|
23 | | - * |
---|
24 | | - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
---|
25 | | - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
---|
26 | | - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
---|
27 | | - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
---|
28 | | - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
---|
29 | | - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
---|
30 | | - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
---|
31 | | - * SOFTWARE. |
---|
32 | | - */ |
---|
| 1 | +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ |
---|
| 2 | +/* Copyright (C) 2016-2018 Netronome Systems, Inc. */ |
---|
33 | 3 | |
---|
34 | 4 | #ifndef __NFP_BPF_H__ |
---|
35 | 5 | #define __NFP_BPF_H__ 1 |
---|
.. | .. |
---|
44 | 14 | #include <linux/types.h> |
---|
45 | 15 | #include <linux/wait.h> |
---|
46 | 16 | |
---|
| 17 | +#include "../ccm.h" |
---|
47 | 18 | #include "../nfp_asm.h" |
---|
48 | 19 | #include "fw.h" |
---|
49 | 20 | |
---|
.. | .. |
---|
61 | 32 | /* internal jumps to parts of the outro */ |
---|
62 | 33 | RELO_BR_GO_OUT, |
---|
63 | 34 | RELO_BR_GO_ABORT, |
---|
| 35 | + RELO_BR_GO_CALL_PUSH_REGS, |
---|
| 36 | + RELO_BR_GO_CALL_POP_REGS, |
---|
64 | 37 | /* external jumps to fixed addresses */ |
---|
65 | 38 | RELO_BR_NEXT_PKT, |
---|
66 | 39 | RELO_BR_HELPER, |
---|
.. | .. |
---|
104 | 77 | #define imma_a(np) reg_a(STATIC_REG_IMMA) |
---|
105 | 78 | #define imma_b(np) reg_b(STATIC_REG_IMMA) |
---|
106 | 79 | #define imm_both(np) reg_both(STATIC_REG_IMM) |
---|
| 80 | +#define ret_reg(np) imm_a(np) |
---|
107 | 81 | |
---|
108 | 82 | #define NFP_BPF_ABI_FLAGS reg_imm(0) |
---|
109 | 83 | #define NFP_BPF_ABI_FLAG_MARK 1 |
---|
.. | .. |
---|
111 | 85 | /** |
---|
112 | 86 | * struct nfp_app_bpf - bpf app priv structure |
---|
113 | 87 | * @app: backpointer to the app |
---|
| 88 | + * @ccm: common control message handler data |
---|
114 | 89 | * |
---|
115 | 90 | * @bpf_dev: BPF offload device handle |
---|
116 | 91 | * |
---|
117 | | - * @tag_allocator: bitmap of control message tags in use |
---|
118 | | - * @tag_alloc_next: next tag bit to allocate |
---|
119 | | - * @tag_alloc_last: next tag bit to be freed |
---|
120 | | - * |
---|
121 | | - * @cmsg_replies: received cmsg replies waiting to be consumed |
---|
122 | | - * @cmsg_wq: work queue for waiting for cmsg replies |
---|
| 92 | + * @cmsg_key_sz: size of key in cmsg element array |
---|
| 93 | + * @cmsg_val_sz: size of value in cmsg element array |
---|
123 | 94 | * |
---|
124 | 95 | * @map_list: list of offloaded maps |
---|
125 | 96 | * @maps_in_use: number of currently offloaded maps |
---|
126 | 97 | * @map_elems_in_use: number of elements allocated to offloaded maps |
---|
127 | 98 | * |
---|
128 | 99 | * @maps_neutral: hash table of offload-neutral maps (on pointer) |
---|
| 100 | + * |
---|
| 101 | + * @abi_version: global BPF ABI version |
---|
| 102 | + * @cmsg_cache_cnt: number of entries to read for caching |
---|
129 | 103 | * |
---|
130 | 104 | * @adjust_head: adjust head capability |
---|
131 | 105 | * @adjust_head.flags: extra flags for adjust head |
---|
.. | .. |
---|
151 | 125 | * @pseudo_random: FW initialized the pseudo-random machinery (CSRs) |
---|
152 | 126 | * @queue_select: BPF can set the RX queue ID in packet vector |
---|
153 | 127 | * @adjust_tail: BPF can simply trunc packet size for adjust tail |
---|
| 128 | + * @cmsg_multi_ent: FW can pack multiple map entries in a single cmsg |
---|
154 | 129 | */ |
---|
155 | 130 | struct nfp_app_bpf { |
---|
156 | 131 | struct nfp_app *app; |
---|
| 132 | + struct nfp_ccm ccm; |
---|
157 | 133 | |
---|
158 | 134 | struct bpf_offload_dev *bpf_dev; |
---|
159 | 135 | |
---|
160 | | - DECLARE_BITMAP(tag_allocator, U16_MAX + 1); |
---|
161 | | - u16 tag_alloc_next; |
---|
162 | | - u16 tag_alloc_last; |
---|
| 136 | + unsigned int cmsg_key_sz; |
---|
| 137 | + unsigned int cmsg_val_sz; |
---|
163 | 138 | |
---|
164 | | - struct sk_buff_head cmsg_replies; |
---|
165 | | - struct wait_queue_head cmsg_wq; |
---|
| 139 | + unsigned int cmsg_cache_cnt; |
---|
166 | 140 | |
---|
167 | 141 | struct list_head map_list; |
---|
168 | 142 | unsigned int maps_in_use; |
---|
169 | 143 | unsigned int map_elems_in_use; |
---|
170 | 144 | |
---|
171 | 145 | struct rhashtable maps_neutral; |
---|
| 146 | + |
---|
| 147 | + u32 abi_version; |
---|
172 | 148 | |
---|
173 | 149 | struct nfp_bpf_cap_adjust_head { |
---|
174 | 150 | u32 flags; |
---|
.. | .. |
---|
197 | 173 | bool pseudo_random; |
---|
198 | 174 | bool queue_select; |
---|
199 | 175 | bool adjust_tail; |
---|
| 176 | + bool cmsg_multi_ent; |
---|
200 | 177 | }; |
---|
201 | 178 | |
---|
202 | 179 | enum nfp_bpf_map_use { |
---|
.. | .. |
---|
211 | 188 | unsigned char non_zero_update :1; |
---|
212 | 189 | }; |
---|
213 | 190 | |
---|
| 191 | +#define NFP_BPF_MAP_CACHE_CNT 4U |
---|
| 192 | +#define NFP_BPF_MAP_CACHE_TIME_NS (250 * 1000) |
---|
| 193 | + |
---|
214 | 194 | /** |
---|
215 | 195 | * struct nfp_bpf_map - private per-map data attached to BPF maps for offload |
---|
216 | 196 | * @offmap: pointer to the offloaded BPF map |
---|
217 | 197 | * @bpf: back pointer to bpf app private structure |
---|
218 | 198 | * @tid: table id identifying map on datapath |
---|
| 199 | + * |
---|
| 200 | + * @cache_lock: protects @cache_blockers, @cache_to, @cache |
---|
| 201 | + * @cache_blockers: number of ops in flight which block caching |
---|
| 202 | + * @cache_gen: counter incremented by every blocker on exit |
---|
| 203 | + * @cache_to: time when cache will no longer be valid (ns) |
---|
| 204 | + * @cache: skb with cached response |
---|
| 205 | + * |
---|
219 | 206 | * @l: link on the nfp_app_bpf->map_list list |
---|
220 | 207 | * @use_map: map of how the value is used (in 4B chunks) |
---|
221 | 208 | */ |
---|
.. | .. |
---|
223 | 210 | struct bpf_offloaded_map *offmap; |
---|
224 | 211 | struct nfp_app_bpf *bpf; |
---|
225 | 212 | u32 tid; |
---|
| 213 | + |
---|
| 214 | + spinlock_t cache_lock; |
---|
| 215 | + u32 cache_blockers; |
---|
| 216 | + u32 cache_gen; |
---|
| 217 | + u64 cache_to; |
---|
| 218 | + struct sk_buff *cache; |
---|
| 219 | + |
---|
226 | 220 | struct list_head l; |
---|
227 | 221 | struct nfp_bpf_map_word use_map[]; |
---|
228 | 222 | }; |
---|
.. | .. |
---|
257 | 251 | bool var_off; |
---|
258 | 252 | }; |
---|
259 | 253 | |
---|
260 | | -#define FLAG_INSN_IS_JUMP_DST BIT(0) |
---|
| 254 | +#define FLAG_INSN_IS_JUMP_DST BIT(0) |
---|
| 255 | +#define FLAG_INSN_IS_SUBPROG_START BIT(1) |
---|
| 256 | +#define FLAG_INSN_PTR_CALLER_STACK_FRAME BIT(2) |
---|
| 257 | +/* Instruction is pointless, noop even on its own */ |
---|
| 258 | +#define FLAG_INSN_SKIP_NOOP BIT(3) |
---|
| 259 | +/* Instruction is optimized out based on preceding instructions */ |
---|
| 260 | +#define FLAG_INSN_SKIP_PREC_DEPENDENT BIT(4) |
---|
| 261 | +/* Instruction is optimized by the verifier */ |
---|
| 262 | +#define FLAG_INSN_SKIP_VERIFIER_OPT BIT(5) |
---|
| 263 | +/* Instruction needs to zero extend to high 32-bit */ |
---|
| 264 | +#define FLAG_INSN_DO_ZEXT BIT(6) |
---|
| 265 | + |
---|
| 266 | +#define FLAG_INSN_SKIP_MASK (FLAG_INSN_SKIP_NOOP | \ |
---|
| 267 | + FLAG_INSN_SKIP_PREC_DEPENDENT | \ |
---|
| 268 | + FLAG_INSN_SKIP_VERIFIER_OPT) |
---|
261 | 269 | |
---|
262 | 270 | /** |
---|
263 | 271 | * struct nfp_insn_meta - BPF instruction wrapper |
---|
.. | .. |
---|
274 | 282 | * @xadd_maybe_16bit: 16bit immediate is possible |
---|
275 | 283 | * @jmp_dst: destination info for jump instructions |
---|
276 | 284 | * @jump_neg_op: jump instruction has inverted immediate, use ADD instead of SUB |
---|
| 285 | + * @num_insns_after_br: number of insns following a branch jump, used for fixup |
---|
277 | 286 | * @func_id: function id for call instructions |
---|
278 | 287 | * @arg1: arg1 for call instructions |
---|
279 | 288 | * @arg2: arg2 for call instructions |
---|
.. | .. |
---|
284 | 293 | * @off: index of first generated machine instruction (in nfp_prog.prog) |
---|
285 | 294 | * @n: eBPF instruction number |
---|
286 | 295 | * @flags: eBPF instruction extra optimization flags |
---|
287 | | - * @skip: skip this instruction (optimized out) |
---|
| 296 | + * @subprog_idx: index of subprogram to which the instruction belongs |
---|
288 | 297 | * @double_cb: callback for second part of the instruction |
---|
289 | 298 | * @l: link on nfp_prog->insns list |
---|
290 | 299 | */ |
---|
.. | .. |
---|
309 | 318 | struct { |
---|
310 | 319 | struct nfp_insn_meta *jmp_dst; |
---|
311 | 320 | bool jump_neg_op; |
---|
| 321 | + u32 num_insns_after_br; /* only for BPF-to-BPF calls */ |
---|
312 | 322 | }; |
---|
313 | 323 | /* function calls */ |
---|
314 | 324 | struct { |
---|
.. | .. |
---|
330 | 340 | unsigned int off; |
---|
331 | 341 | unsigned short n; |
---|
332 | 342 | unsigned short flags; |
---|
333 | | - bool skip; |
---|
| 343 | + unsigned short subprog_idx; |
---|
334 | 344 | instr_cb_t double_cb; |
---|
335 | 345 | |
---|
336 | 346 | struct list_head l; |
---|
.. | .. |
---|
366 | 376 | static inline bool is_mbpf_load(const struct nfp_insn_meta *meta) |
---|
367 | 377 | { |
---|
368 | 378 | return (meta->insn.code & ~BPF_SIZE_MASK) == (BPF_LDX | BPF_MEM); |
---|
| 379 | +} |
---|
| 380 | + |
---|
| 381 | +static inline bool is_mbpf_jmp32(const struct nfp_insn_meta *meta) |
---|
| 382 | +{ |
---|
| 383 | + return mbpf_class(meta) == BPF_JMP32; |
---|
| 384 | +} |
---|
| 385 | + |
---|
| 386 | +static inline bool is_mbpf_jmp64(const struct nfp_insn_meta *meta) |
---|
| 387 | +{ |
---|
| 388 | + return mbpf_class(meta) == BPF_JMP; |
---|
| 389 | +} |
---|
| 390 | + |
---|
| 391 | +static inline bool is_mbpf_jmp(const struct nfp_insn_meta *meta) |
---|
| 392 | +{ |
---|
| 393 | + return is_mbpf_jmp32(meta) || is_mbpf_jmp64(meta); |
---|
369 | 394 | } |
---|
370 | 395 | |
---|
371 | 396 | static inline bool is_mbpf_store(const struct nfp_insn_meta *meta) |
---|
.. | .. |
---|
418 | 443 | return is_mbpf_alu(meta) && mbpf_op(meta) == BPF_DIV; |
---|
419 | 444 | } |
---|
420 | 445 | |
---|
| 446 | +static inline bool is_mbpf_cond_jump(const struct nfp_insn_meta *meta) |
---|
| 447 | +{ |
---|
| 448 | + u8 op; |
---|
| 449 | + |
---|
| 450 | + if (is_mbpf_jmp32(meta)) |
---|
| 451 | + return true; |
---|
| 452 | + |
---|
| 453 | + if (!is_mbpf_jmp64(meta)) |
---|
| 454 | + return false; |
---|
| 455 | + |
---|
| 456 | + op = mbpf_op(meta); |
---|
| 457 | + return op != BPF_JA && op != BPF_EXIT && op != BPF_CALL; |
---|
| 458 | +} |
---|
| 459 | + |
---|
| 460 | +static inline bool is_mbpf_helper_call(const struct nfp_insn_meta *meta) |
---|
| 461 | +{ |
---|
| 462 | + struct bpf_insn insn = meta->insn; |
---|
| 463 | + |
---|
| 464 | + return insn.code == (BPF_JMP | BPF_CALL) && |
---|
| 465 | + insn.src_reg != BPF_PSEUDO_CALL; |
---|
| 466 | +} |
---|
| 467 | + |
---|
| 468 | +static inline bool is_mbpf_pseudo_call(const struct nfp_insn_meta *meta) |
---|
| 469 | +{ |
---|
| 470 | + struct bpf_insn insn = meta->insn; |
---|
| 471 | + |
---|
| 472 | + return insn.code == (BPF_JMP | BPF_CALL) && |
---|
| 473 | + insn.src_reg == BPF_PSEUDO_CALL; |
---|
| 474 | +} |
---|
| 475 | + |
---|
| 476 | +#define STACK_FRAME_ALIGN 64 |
---|
| 477 | + |
---|
| 478 | +/** |
---|
| 479 | + * struct nfp_bpf_subprog_info - nfp BPF sub-program (a.k.a. function) info |
---|
| 480 | + * @stack_depth: maximum stack depth used by this sub-program |
---|
| 481 | + * @needs_reg_push: whether sub-program uses callee-saved registers |
---|
| 482 | + */ |
---|
| 483 | +struct nfp_bpf_subprog_info { |
---|
| 484 | + u16 stack_depth; |
---|
| 485 | + u8 needs_reg_push : 1; |
---|
| 486 | +}; |
---|
| 487 | + |
---|
421 | 488 | /** |
---|
422 | 489 | * struct nfp_prog - nfp BPF program |
---|
423 | 490 | * @bpf: backpointer to the bpf app priv structure |
---|
424 | 491 | * @prog: machine code |
---|
425 | 492 | * @prog_len: number of valid instructions in @prog array |
---|
426 | 493 | * @__prog_alloc_len: alloc size of @prog array |
---|
| 494 | + * @stack_size: total amount of stack used |
---|
427 | 495 | * @verifier_meta: temporary storage for verifier's insn meta |
---|
428 | 496 | * @type: BPF program type |
---|
429 | 497 | * @last_bpf_off: address of the last instruction translated from BPF |
---|
430 | 498 | * @tgt_out: jump target for normal exit |
---|
431 | 499 | * @tgt_abort: jump target for abort (e.g. access outside of packet buffer) |
---|
| 500 | + * @tgt_call_push_regs: jump target for subroutine for saving R6~R9 to stack |
---|
| 501 | + * @tgt_call_pop_regs: jump target for subroutine used for restoring R6~R9 |
---|
432 | 502 | * @n_translated: number of successfully translated instructions (for errors) |
---|
433 | 503 | * @error: error code if something went wrong |
---|
434 | | - * @stack_depth: max stack depth from the verifier |
---|
| 504 | + * @stack_frame_depth: max stack depth for current frame |
---|
435 | 505 | * @adjust_head_location: if program has single adjust head call - the insn no. |
---|
436 | 506 | * @map_records_cnt: the number of map pointers recorded for this prog |
---|
| 507 | + * @subprog_cnt: number of sub-programs, including main function |
---|
437 | 508 | * @map_records: the map record pointers from bpf->maps_neutral |
---|
| 509 | + * @subprog: pointer to an array of objects holding info about sub-programs |
---|
| 510 | + * @n_insns: number of instructions on @insns list |
---|
438 | 511 | * @insns: list of BPF instruction wrappers (struct nfp_insn_meta) |
---|
439 | 512 | */ |
---|
440 | 513 | struct nfp_prog { |
---|
.. | .. |
---|
444 | 517 | unsigned int prog_len; |
---|
445 | 518 | unsigned int __prog_alloc_len; |
---|
446 | 519 | |
---|
| 520 | + unsigned int stack_size; |
---|
| 521 | + |
---|
447 | 522 | struct nfp_insn_meta *verifier_meta; |
---|
448 | 523 | |
---|
449 | 524 | enum bpf_prog_type type; |
---|
.. | .. |
---|
451 | 526 | unsigned int last_bpf_off; |
---|
452 | 527 | unsigned int tgt_out; |
---|
453 | 528 | unsigned int tgt_abort; |
---|
| 529 | + unsigned int tgt_call_push_regs; |
---|
| 530 | + unsigned int tgt_call_pop_regs; |
---|
454 | 531 | |
---|
455 | 532 | unsigned int n_translated; |
---|
456 | 533 | int error; |
---|
457 | 534 | |
---|
458 | | - unsigned int stack_depth; |
---|
| 535 | + unsigned int stack_frame_depth; |
---|
459 | 536 | unsigned int adjust_head_location; |
---|
460 | 537 | |
---|
461 | 538 | unsigned int map_records_cnt; |
---|
| 539 | + unsigned int subprog_cnt; |
---|
462 | 540 | struct nfp_bpf_neutral_map **map_records; |
---|
| 541 | + struct nfp_bpf_subprog_info *subprog; |
---|
463 | 542 | |
---|
| 543 | + unsigned int n_insns; |
---|
464 | 544 | struct list_head insns; |
---|
465 | 545 | }; |
---|
466 | 546 | |
---|
.. | .. |
---|
476 | 556 | unsigned int tgt_done; |
---|
477 | 557 | }; |
---|
478 | 558 | |
---|
479 | | -void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog, unsigned int cnt); |
---|
| 559 | +bool nfp_is_subprog_start(struct nfp_insn_meta *meta); |
---|
| 560 | +void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog); |
---|
480 | 561 | int nfp_bpf_jit(struct nfp_prog *prog); |
---|
481 | 562 | bool nfp_bpf_supported_opcode(u8 code); |
---|
| 563 | +bool nfp_bpf_offload_check_mtu(struct nfp_net *nn, struct bpf_prog *prog, |
---|
| 564 | + unsigned int mtu); |
---|
482 | 565 | |
---|
483 | | -extern const struct bpf_prog_offload_ops nfp_bpf_analyzer_ops; |
---|
| 566 | +int nfp_verify_insn(struct bpf_verifier_env *env, int insn_idx, |
---|
| 567 | + int prev_insn_idx); |
---|
| 568 | +int nfp_bpf_finalize(struct bpf_verifier_env *env); |
---|
| 569 | + |
---|
| 570 | +int nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off, |
---|
| 571 | + struct bpf_insn *insn); |
---|
| 572 | +int nfp_bpf_opt_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt); |
---|
| 573 | + |
---|
| 574 | +extern const struct bpf_prog_offload_ops nfp_bpf_dev_ops; |
---|
484 | 575 | |
---|
485 | 576 | struct netdev_bpf; |
---|
486 | 577 | struct nfp_app; |
---|
.. | .. |
---|
493 | 584 | |
---|
494 | 585 | struct nfp_insn_meta * |
---|
495 | 586 | nfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, |
---|
496 | | - unsigned int insn_idx, unsigned int n_insns); |
---|
| 587 | + unsigned int insn_idx); |
---|
497 | 588 | |
---|
498 | 589 | void *nfp_bpf_relo_for_vnic(struct nfp_prog *nfp_prog, struct nfp_bpf_vnic *bv); |
---|
499 | 590 | |
---|
| 591 | +unsigned int nfp_bpf_ctrl_cmsg_min_mtu(struct nfp_app_bpf *bpf); |
---|
| 592 | +unsigned int nfp_bpf_ctrl_cmsg_mtu(struct nfp_app_bpf *bpf); |
---|
| 593 | +unsigned int nfp_bpf_ctrl_cmsg_cache_cnt(struct nfp_app_bpf *bpf); |
---|
500 | 594 | long long int |
---|
501 | 595 | nfp_bpf_ctrl_alloc_map(struct nfp_app_bpf *bpf, struct bpf_map *map); |
---|
502 | 596 | void |
---|