nfp: bpf: use the power of sparse to check we encode registers right
[linux-2.6-block.git] / drivers / net / ethernet / netronome / nfp / bpf / jit.c
1 /*
2  * Copyright (C) 2016 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  */
33
34 #define pr_fmt(fmt)     "NFP net bpf: " fmt
35
36 #include <linux/kernel.h>
37 #include <linux/bpf.h>
38 #include <linux/filter.h>
39 #include <linux/pkt_cls.h>
40 #include <linux/unistd.h>
41
42 #include "main.h"
43 #include "../nfp_asm.h"
44
45 /* --- NFP prog --- */
46 /* Foreach "multiple" entries macros provide pos and next<n> pointers.
47  * It's safe to modify the next pointers (but not pos).
48  */
49 #define nfp_for_each_insn_walk2(nfp_prog, pos, next)                    \
50         for (pos = list_first_entry(&(nfp_prog)->insns, typeof(*pos), l), \
51              next = list_next_entry(pos, l);                    \
52              &(nfp_prog)->insns != &pos->l &&                   \
53              &(nfp_prog)->insns != &next->l;                    \
54              pos = nfp_meta_next(pos),                          \
55              next = nfp_meta_next(pos))
56
57 #define nfp_for_each_insn_walk3(nfp_prog, pos, next, next2)             \
58         for (pos = list_first_entry(&(nfp_prog)->insns, typeof(*pos), l), \
59              next = list_next_entry(pos, l),                    \
60              next2 = list_next_entry(next, l);                  \
61              &(nfp_prog)->insns != &pos->l &&                   \
62              &(nfp_prog)->insns != &next->l &&                  \
63              &(nfp_prog)->insns != &next2->l;                   \
64              pos = nfp_meta_next(pos),                          \
65              next = nfp_meta_next(pos),                         \
66              next2 = nfp_meta_next(next))
67
68 static bool
69 nfp_meta_has_next(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
70 {
71         return meta->l.next != &nfp_prog->insns;
72 }
73
74 static bool
75 nfp_meta_has_prev(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
76 {
77         return meta->l.prev != &nfp_prog->insns;
78 }
79
80 static void nfp_prog_free(struct nfp_prog *nfp_prog)
81 {
82         struct nfp_insn_meta *meta, *tmp;
83
84         list_for_each_entry_safe(meta, tmp, &nfp_prog->insns, l) {
85                 list_del(&meta->l);
86                 kfree(meta);
87         }
88         kfree(nfp_prog);
89 }
90
91 static void nfp_prog_push(struct nfp_prog *nfp_prog, u64 insn)
92 {
93         if (nfp_prog->__prog_alloc_len == nfp_prog->prog_len) {
94                 nfp_prog->error = -ENOSPC;
95                 return;
96         }
97
98         nfp_prog->prog[nfp_prog->prog_len] = insn;
99         nfp_prog->prog_len++;
100 }
101
102 static unsigned int nfp_prog_current_offset(struct nfp_prog *nfp_prog)
103 {
104         return nfp_prog->start_off + nfp_prog->prog_len;
105 }
106
107 static unsigned int
108 nfp_prog_offset_to_index(struct nfp_prog *nfp_prog, unsigned int offset)
109 {
110         return offset - nfp_prog->start_off;
111 }
112
113 /* --- SW reg --- */
114 struct nfp_insn_ur_regs {
115         enum alu_dst_ab dst_ab;
116         u16 dst;
117         u16 areg, breg;
118         bool swap;
119         bool wr_both;
120 };
121
122 struct nfp_insn_re_regs {
123         enum alu_dst_ab dst_ab;
124         u8 dst;
125         u8 areg, breg;
126         bool swap;
127         bool wr_both;
128         bool i8;
129 };
130
131 static u16 nfp_swreg_to_unreg(swreg reg, bool is_dst)
132 {
133         u16 val = swreg_value(reg);
134
135         switch (swreg_type(reg)) {
136         case NN_REG_GPR_A:
137         case NN_REG_GPR_B:
138         case NN_REG_GPR_BOTH:
139                 return val;
140         case NN_REG_NNR:
141                 return UR_REG_NN | val;
142         case NN_REG_XFER:
143                 return UR_REG_XFR | val;
144         case NN_REG_IMM:
145                 if (val & ~0xff) {
146                         pr_err("immediate too large\n");
147                         return 0;
148                 }
149                 return UR_REG_IMM_encode(val);
150         case NN_REG_NONE:
151                 return is_dst ? UR_REG_NO_DST : REG_NONE;
152         }
153
154         pr_err("unrecognized reg encoding %08x\n", reg);
155         return 0;
156 }
157
158 static int
159 swreg_to_unrestricted(swreg dst, swreg lreg, swreg rreg,
160                       struct nfp_insn_ur_regs *reg)
161 {
162         memset(reg, 0, sizeof(*reg));
163
164         /* Decode destination */
165         if (swreg_type(dst) == NN_REG_IMM)
166                 return -EFAULT;
167
168         if (swreg_type(dst) == NN_REG_GPR_B)
169                 reg->dst_ab = ALU_DST_B;
170         if (swreg_type(dst) == NN_REG_GPR_BOTH)
171                 reg->wr_both = true;
172         reg->dst = nfp_swreg_to_unreg(dst, true);
173
174         /* Decode source operands */
175         if (swreg_type(lreg) == swreg_type(rreg))
176                 return -EFAULT;
177
178         if (swreg_type(lreg) == NN_REG_GPR_B ||
179             swreg_type(rreg) == NN_REG_GPR_A) {
180                 reg->areg = nfp_swreg_to_unreg(rreg, false);
181                 reg->breg = nfp_swreg_to_unreg(lreg, false);
182                 reg->swap = true;
183         } else {
184                 reg->areg = nfp_swreg_to_unreg(lreg, false);
185                 reg->breg = nfp_swreg_to_unreg(rreg, false);
186         }
187
188         return 0;
189 }
190
191 static u16 nfp_swreg_to_rereg(swreg reg, bool is_dst, bool has_imm8, bool *i8)
192 {
193         u16 val = swreg_value(reg);
194
195         switch (swreg_type(reg)) {
196         case NN_REG_GPR_A:
197         case NN_REG_GPR_B:
198         case NN_REG_GPR_BOTH:
199                 return val;
200         case NN_REG_XFER:
201                 return RE_REG_XFR | val;
202         case NN_REG_IMM:
203                 if (val & ~(0x7f | has_imm8 << 7)) {
204                         pr_err("immediate too large\n");
205                         return 0;
206                 }
207                 *i8 = val & 0x80;
208                 return RE_REG_IMM_encode(val & 0x7f);
209         case NN_REG_NONE:
210                 return is_dst ? RE_REG_NO_DST : REG_NONE;
211         case NN_REG_NNR:
212                 pr_err("NNRs used with restricted encoding\n");
213                 return 0;
214         }
215
216         pr_err("unrecognized reg encoding\n");
217         return 0;
218 }
219
220 static int
221 swreg_to_restricted(swreg dst, swreg lreg, swreg rreg,
222                     struct nfp_insn_re_regs *reg, bool has_imm8)
223 {
224         memset(reg, 0, sizeof(*reg));
225
226         /* Decode destination */
227         if (swreg_type(dst) == NN_REG_IMM)
228                 return -EFAULT;
229
230         if (swreg_type(dst) == NN_REG_GPR_B)
231                 reg->dst_ab = ALU_DST_B;
232         if (swreg_type(dst) == NN_REG_GPR_BOTH)
233                 reg->wr_both = true;
234         reg->dst = nfp_swreg_to_rereg(dst, true, false, NULL);
235
236         /* Decode source operands */
237         if (swreg_type(lreg) == swreg_type(rreg))
238                 return -EFAULT;
239
240         if (swreg_type(lreg) == NN_REG_GPR_B ||
241             swreg_type(rreg) == NN_REG_GPR_A) {
242                 reg->areg = nfp_swreg_to_rereg(rreg, false, has_imm8, &reg->i8);
243                 reg->breg = nfp_swreg_to_rereg(lreg, false, has_imm8, &reg->i8);
244                 reg->swap = true;
245         } else {
246                 reg->areg = nfp_swreg_to_rereg(lreg, false, has_imm8, &reg->i8);
247                 reg->breg = nfp_swreg_to_rereg(rreg, false, has_imm8, &reg->i8);
248         }
249
250         return 0;
251 }
252
253 /* --- Emitters --- */
254 static const struct cmd_tgt_act cmd_tgt_act[__CMD_TGT_MAP_SIZE] = {
255         [CMD_TGT_WRITE8] =              { 0x00, 0x42 },
256         [CMD_TGT_READ8] =               { 0x01, 0x43 },
257         [CMD_TGT_READ_LE] =             { 0x01, 0x40 },
258         [CMD_TGT_READ_SWAP_LE] =        { 0x03, 0x40 },
259 };
260
261 static void
262 __emit_cmd(struct nfp_prog *nfp_prog, enum cmd_tgt_map op,
263            u8 mode, u8 xfer, u8 areg, u8 breg, u8 size, bool sync)
264 {
265         enum cmd_ctx_swap ctx;
266         u64 insn;
267
268         if (sync)
269                 ctx = CMD_CTX_SWAP;
270         else
271                 ctx = CMD_CTX_NO_SWAP;
272
273         insn =  FIELD_PREP(OP_CMD_A_SRC, areg) |
274                 FIELD_PREP(OP_CMD_CTX, ctx) |
275                 FIELD_PREP(OP_CMD_B_SRC, breg) |
276                 FIELD_PREP(OP_CMD_TOKEN, cmd_tgt_act[op].token) |
277                 FIELD_PREP(OP_CMD_XFER, xfer) |
278                 FIELD_PREP(OP_CMD_CNT, size) |
279                 FIELD_PREP(OP_CMD_SIG, sync) |
280                 FIELD_PREP(OP_CMD_TGT_CMD, cmd_tgt_act[op].tgt_cmd) |
281                 FIELD_PREP(OP_CMD_MODE, mode);
282
283         nfp_prog_push(nfp_prog, insn);
284 }
285
286 static void
287 emit_cmd(struct nfp_prog *nfp_prog, enum cmd_tgt_map op,
288          u8 mode, u8 xfer, swreg lreg, swreg rreg, u8 size, bool sync)
289 {
290         struct nfp_insn_re_regs reg;
291         int err;
292
293         err = swreg_to_restricted(reg_none(), lreg, rreg, &reg, false);
294         if (err) {
295                 nfp_prog->error = err;
296                 return;
297         }
298         if (reg.swap) {
299                 pr_err("cmd can't swap arguments\n");
300                 nfp_prog->error = -EFAULT;
301                 return;
302         }
303
304         __emit_cmd(nfp_prog, op, mode, xfer, reg.areg, reg.breg, size, sync);
305 }
306
307 static void
308 __emit_br(struct nfp_prog *nfp_prog, enum br_mask mask, enum br_ev_pip ev_pip,
309           enum br_ctx_signal_state css, u16 addr, u8 defer)
310 {
311         u16 addr_lo, addr_hi;
312         u64 insn;
313
314         addr_lo = addr & (OP_BR_ADDR_LO >> __bf_shf(OP_BR_ADDR_LO));
315         addr_hi = addr != addr_lo;
316
317         insn = OP_BR_BASE |
318                 FIELD_PREP(OP_BR_MASK, mask) |
319                 FIELD_PREP(OP_BR_EV_PIP, ev_pip) |
320                 FIELD_PREP(OP_BR_CSS, css) |
321                 FIELD_PREP(OP_BR_DEFBR, defer) |
322                 FIELD_PREP(OP_BR_ADDR_LO, addr_lo) |
323                 FIELD_PREP(OP_BR_ADDR_HI, addr_hi);
324
325         nfp_prog_push(nfp_prog, insn);
326 }
327
328 static void emit_br_def(struct nfp_prog *nfp_prog, u16 addr, u8 defer)
329 {
330         if (defer > 2) {
331                 pr_err("BUG: branch defer out of bounds %d\n", defer);
332                 nfp_prog->error = -EFAULT;
333                 return;
334         }
335         __emit_br(nfp_prog, BR_UNC, BR_EV_PIP_UNCOND, BR_CSS_NONE, addr, defer);
336 }
337
338 static void
339 emit_br(struct nfp_prog *nfp_prog, enum br_mask mask, u16 addr, u8 defer)
340 {
341         __emit_br(nfp_prog, mask,
342                   mask != BR_UNC ? BR_EV_PIP_COND : BR_EV_PIP_UNCOND,
343                   BR_CSS_NONE, addr, defer);
344 }
345
346 static void
347 __emit_br_byte(struct nfp_prog *nfp_prog, u8 areg, u8 breg, bool imm8,
348                u8 byte, bool equal, u16 addr, u8 defer)
349 {
350         u16 addr_lo, addr_hi;
351         u64 insn;
352
353         addr_lo = addr & (OP_BB_ADDR_LO >> __bf_shf(OP_BB_ADDR_LO));
354         addr_hi = addr != addr_lo;
355
356         insn = OP_BBYTE_BASE |
357                 FIELD_PREP(OP_BB_A_SRC, areg) |
358                 FIELD_PREP(OP_BB_BYTE, byte) |
359                 FIELD_PREP(OP_BB_B_SRC, breg) |
360                 FIELD_PREP(OP_BB_I8, imm8) |
361                 FIELD_PREP(OP_BB_EQ, equal) |
362                 FIELD_PREP(OP_BB_DEFBR, defer) |
363                 FIELD_PREP(OP_BB_ADDR_LO, addr_lo) |
364                 FIELD_PREP(OP_BB_ADDR_HI, addr_hi);
365
366         nfp_prog_push(nfp_prog, insn);
367 }
368
369 static void
370 emit_br_byte_neq(struct nfp_prog *nfp_prog,
371                  swreg dst, u8 imm, u8 byte, u16 addr, u8 defer)
372 {
373         struct nfp_insn_re_regs reg;
374         int err;
375
376         err = swreg_to_restricted(reg_none(), dst, reg_imm(imm), &reg, true);
377         if (err) {
378                 nfp_prog->error = err;
379                 return;
380         }
381
382         __emit_br_byte(nfp_prog, reg.areg, reg.breg, reg.i8, byte, false, addr,
383                        defer);
384 }
385
386 static void
387 __emit_immed(struct nfp_prog *nfp_prog, u16 areg, u16 breg, u16 imm_hi,
388              enum immed_width width, bool invert,
389              enum immed_shift shift, bool wr_both)
390 {
391         u64 insn;
392
393         insn = OP_IMMED_BASE |
394                 FIELD_PREP(OP_IMMED_A_SRC, areg) |
395                 FIELD_PREP(OP_IMMED_B_SRC, breg) |
396                 FIELD_PREP(OP_IMMED_IMM, imm_hi) |
397                 FIELD_PREP(OP_IMMED_WIDTH, width) |
398                 FIELD_PREP(OP_IMMED_INV, invert) |
399                 FIELD_PREP(OP_IMMED_SHIFT, shift) |
400                 FIELD_PREP(OP_IMMED_WR_AB, wr_both);
401
402         nfp_prog_push(nfp_prog, insn);
403 }
404
405 static void
406 emit_immed(struct nfp_prog *nfp_prog, swreg dst, u16 imm,
407            enum immed_width width, bool invert, enum immed_shift shift)
408 {
409         struct nfp_insn_ur_regs reg;
410         int err;
411
412         if (swreg_type(dst) == NN_REG_IMM) {
413                 nfp_prog->error = -EFAULT;
414                 return;
415         }
416
417         err = swreg_to_unrestricted(dst, dst, reg_imm(imm & 0xff), &reg);
418         if (err) {
419                 nfp_prog->error = err;
420                 return;
421         }
422
423         __emit_immed(nfp_prog, reg.areg, reg.breg, imm >> 8, width,
424                      invert, shift, reg.wr_both);
425 }
426
427 static void
428 __emit_shf(struct nfp_prog *nfp_prog, u16 dst, enum alu_dst_ab dst_ab,
429            enum shf_sc sc, u8 shift,
430            u16 areg, enum shf_op op, u16 breg, bool i8, bool sw, bool wr_both)
431 {
432         u64 insn;
433
434         if (!FIELD_FIT(OP_SHF_SHIFT, shift)) {
435                 nfp_prog->error = -EFAULT;
436                 return;
437         }
438
439         if (sc == SHF_SC_L_SHF)
440                 shift = 32 - shift;
441
442         insn = OP_SHF_BASE |
443                 FIELD_PREP(OP_SHF_A_SRC, areg) |
444                 FIELD_PREP(OP_SHF_SC, sc) |
445                 FIELD_PREP(OP_SHF_B_SRC, breg) |
446                 FIELD_PREP(OP_SHF_I8, i8) |
447                 FIELD_PREP(OP_SHF_SW, sw) |
448                 FIELD_PREP(OP_SHF_DST, dst) |
449                 FIELD_PREP(OP_SHF_SHIFT, shift) |
450                 FIELD_PREP(OP_SHF_OP, op) |
451                 FIELD_PREP(OP_SHF_DST_AB, dst_ab) |
452                 FIELD_PREP(OP_SHF_WR_AB, wr_both);
453
454         nfp_prog_push(nfp_prog, insn);
455 }
456
457 static void
458 emit_shf(struct nfp_prog *nfp_prog, swreg dst,
459          swreg lreg, enum shf_op op, swreg rreg, enum shf_sc sc, u8 shift)
460 {
461         struct nfp_insn_re_regs reg;
462         int err;
463
464         err = swreg_to_restricted(dst, lreg, rreg, &reg, true);
465         if (err) {
466                 nfp_prog->error = err;
467                 return;
468         }
469
470         __emit_shf(nfp_prog, reg.dst, reg.dst_ab, sc, shift,
471                    reg.areg, op, reg.breg, reg.i8, reg.swap, reg.wr_both);
472 }
473
474 static void
475 __emit_alu(struct nfp_prog *nfp_prog, u16 dst, enum alu_dst_ab dst_ab,
476            u16 areg, enum alu_op op, u16 breg, bool swap, bool wr_both)
477 {
478         u64 insn;
479
480         insn = OP_ALU_BASE |
481                 FIELD_PREP(OP_ALU_A_SRC, areg) |
482                 FIELD_PREP(OP_ALU_B_SRC, breg) |
483                 FIELD_PREP(OP_ALU_DST, dst) |
484                 FIELD_PREP(OP_ALU_SW, swap) |
485                 FIELD_PREP(OP_ALU_OP, op) |
486                 FIELD_PREP(OP_ALU_DST_AB, dst_ab) |
487                 FIELD_PREP(OP_ALU_WR_AB, wr_both);
488
489         nfp_prog_push(nfp_prog, insn);
490 }
491
492 static void
493 emit_alu(struct nfp_prog *nfp_prog, swreg dst,
494          swreg lreg, enum alu_op op, swreg rreg)
495 {
496         struct nfp_insn_ur_regs reg;
497         int err;
498
499         err = swreg_to_unrestricted(dst, lreg, rreg, &reg);
500         if (err) {
501                 nfp_prog->error = err;
502                 return;
503         }
504
505         __emit_alu(nfp_prog, reg.dst, reg.dst_ab,
506                    reg.areg, op, reg.breg, reg.swap, reg.wr_both);
507 }
508
509 static void
510 __emit_ld_field(struct nfp_prog *nfp_prog, enum shf_sc sc,
511                 u8 areg, u8 bmask, u8 breg, u8 shift, bool imm8,
512                 bool zero, bool swap, bool wr_both)
513 {
514         u64 insn;
515
516         insn = OP_LDF_BASE |
517                 FIELD_PREP(OP_LDF_A_SRC, areg) |
518                 FIELD_PREP(OP_LDF_SC, sc) |
519                 FIELD_PREP(OP_LDF_B_SRC, breg) |
520                 FIELD_PREP(OP_LDF_I8, imm8) |
521                 FIELD_PREP(OP_LDF_SW, swap) |
522                 FIELD_PREP(OP_LDF_ZF, zero) |
523                 FIELD_PREP(OP_LDF_BMASK, bmask) |
524                 FIELD_PREP(OP_LDF_SHF, shift) |
525                 FIELD_PREP(OP_LDF_WR_AB, wr_both);
526
527         nfp_prog_push(nfp_prog, insn);
528 }
529
530 static void
531 emit_ld_field_any(struct nfp_prog *nfp_prog, enum shf_sc sc, u8 shift,
532                   swreg dst, u8 bmask, swreg src, bool zero)
533 {
534         struct nfp_insn_re_regs reg;
535         int err;
536
537         err = swreg_to_restricted(reg_none(), dst, src, &reg, true);
538         if (err) {
539                 nfp_prog->error = err;
540                 return;
541         }
542
543         __emit_ld_field(nfp_prog, sc, reg.areg, bmask, reg.breg, shift,
544                         reg.i8, zero, reg.swap, reg.wr_both);
545 }
546
547 static void
548 emit_ld_field(struct nfp_prog *nfp_prog, swreg dst, u8 bmask, swreg src,
549               enum shf_sc sc, u8 shift)
550 {
551         emit_ld_field_any(nfp_prog, sc, shift, dst, bmask, src, false);
552 }
553
554 /* --- Wrappers --- */
555 static bool pack_immed(u32 imm, u16 *val, enum immed_shift *shift)
556 {
557         if (!(imm & 0xffff0000)) {
558                 *val = imm;
559                 *shift = IMMED_SHIFT_0B;
560         } else if (!(imm & 0xff0000ff)) {
561                 *val = imm >> 8;
562                 *shift = IMMED_SHIFT_1B;
563         } else if (!(imm & 0x0000ffff)) {
564                 *val = imm >> 16;
565                 *shift = IMMED_SHIFT_2B;
566         } else {
567                 return false;
568         }
569
570         return true;
571 }
572
573 static void wrp_immed(struct nfp_prog *nfp_prog, swreg dst, u32 imm)
574 {
575         enum immed_shift shift;
576         u16 val;
577
578         if (pack_immed(imm, &val, &shift)) {
579                 emit_immed(nfp_prog, dst, val, IMMED_WIDTH_ALL, false, shift);
580         } else if (pack_immed(~imm, &val, &shift)) {
581                 emit_immed(nfp_prog, dst, val, IMMED_WIDTH_ALL, true, shift);
582         } else {
583                 emit_immed(nfp_prog, dst, imm & 0xffff, IMMED_WIDTH_ALL,
584                            false, IMMED_SHIFT_0B);
585                 emit_immed(nfp_prog, dst, imm >> 16, IMMED_WIDTH_WORD,
586                            false, IMMED_SHIFT_2B);
587         }
588 }
589
590 /* ur_load_imm_any() - encode immediate or use tmp register (unrestricted)
591  * If the @imm is small enough encode it directly in operand and return
592  * otherwise load @imm to a spare register and return its encoding.
593  */
594 static swreg ur_load_imm_any(struct nfp_prog *nfp_prog, u32 imm, swreg tmp_reg)
595 {
596         if (FIELD_FIT(UR_REG_IMM_MAX, imm))
597                 return reg_imm(imm);
598
599         wrp_immed(nfp_prog, tmp_reg, imm);
600         return tmp_reg;
601 }
602
603 /* re_load_imm_any() - encode immediate or use tmp register (restricted)
604  * If the @imm is small enough encode it directly in operand and return
605  * otherwise load @imm to a spare register and return its encoding.
606  */
607 static swreg re_load_imm_any(struct nfp_prog *nfp_prog, u32 imm, swreg tmp_reg)
608 {
609         if (FIELD_FIT(RE_REG_IMM_MAX, imm))
610                 return reg_imm(imm);
611
612         wrp_immed(nfp_prog, tmp_reg, imm);
613         return tmp_reg;
614 }
615
616 static void
617 wrp_br_special(struct nfp_prog *nfp_prog, enum br_mask mask,
618                enum br_special special)
619 {
620         emit_br(nfp_prog, mask, 0, 0);
621
622         nfp_prog->prog[nfp_prog->prog_len - 1] |=
623                 FIELD_PREP(OP_BR_SPECIAL, special);
624 }
625
626 static void wrp_reg_mov(struct nfp_prog *nfp_prog, u16 dst, u16 src)
627 {
628         emit_alu(nfp_prog, reg_both(dst), reg_none(), ALU_OP_NONE, reg_b(src));
629 }
630
631 static int
632 construct_data_ind_ld(struct nfp_prog *nfp_prog, u16 offset,
633                       u16 src, bool src_valid, u8 size)
634 {
635         unsigned int i;
636         u16 shift, sz;
637         swreg tmp_reg;
638
639         /* We load the value from the address indicated in @offset and then
640          * shift out the data we don't need.  Note: this is big endian!
641          */
642         sz = size < 4 ? 4 : size;
643         shift = size < 4 ? 4 - size : 0;
644
645         if (src_valid) {
646                 /* Calculate the true offset (src_reg + imm) */
647                 tmp_reg = ur_load_imm_any(nfp_prog, offset, imm_b(nfp_prog));
648                 emit_alu(nfp_prog, imm_both(nfp_prog),
649                          reg_a(src), ALU_OP_ADD, tmp_reg);
650                 /* Check packet length (size guaranteed to fit b/c it's u8) */
651                 emit_alu(nfp_prog, imm_a(nfp_prog),
652                          imm_a(nfp_prog), ALU_OP_ADD, reg_imm(size));
653                 emit_alu(nfp_prog, reg_none(),
654                          NFP_BPF_ABI_LEN, ALU_OP_SUB, imm_a(nfp_prog));
655                 wrp_br_special(nfp_prog, BR_BLO, OP_BR_GO_ABORT);
656                 /* Load data */
657                 emit_cmd(nfp_prog, CMD_TGT_READ8, CMD_MODE_32b, 0,
658                          pkt_reg(nfp_prog), imm_b(nfp_prog), sz - 1, true);
659         } else {
660                 /* Check packet length */
661                 tmp_reg = ur_load_imm_any(nfp_prog, offset + size,
662                                           imm_a(nfp_prog));
663                 emit_alu(nfp_prog, reg_none(),
664                          NFP_BPF_ABI_LEN, ALU_OP_SUB, tmp_reg);
665                 wrp_br_special(nfp_prog, BR_BLO, OP_BR_GO_ABORT);
666                 /* Load data */
667                 tmp_reg = re_load_imm_any(nfp_prog, offset, imm_b(nfp_prog));
668                 emit_cmd(nfp_prog, CMD_TGT_READ8, CMD_MODE_32b, 0,
669                          pkt_reg(nfp_prog), tmp_reg, sz - 1, true);
670         }
671
672         i = 0;
673         if (shift)
674                 emit_shf(nfp_prog, reg_both(0), reg_none(), SHF_OP_NONE,
675                          reg_xfer(0), SHF_SC_R_SHF, shift * 8);
676         else
677                 for (; i * 4 < size; i++)
678                         emit_alu(nfp_prog, reg_both(i),
679                                  reg_none(), ALU_OP_NONE, reg_xfer(i));
680
681         if (i < 2)
682                 wrp_immed(nfp_prog, reg_both(1), 0);
683
684         return 0;
685 }
686
687 static int construct_data_ld(struct nfp_prog *nfp_prog, u16 offset, u8 size)
688 {
689         return construct_data_ind_ld(nfp_prog, offset, 0, false, size);
690 }
691
692 static int wrp_set_mark(struct nfp_prog *nfp_prog, u8 src)
693 {
694         emit_alu(nfp_prog, NFP_BPF_ABI_MARK,
695                  reg_none(), ALU_OP_NONE, reg_b(src));
696         emit_alu(nfp_prog, NFP_BPF_ABI_FLAGS,
697                  NFP_BPF_ABI_FLAGS, ALU_OP_OR, reg_imm(NFP_BPF_ABI_FLAG_MARK));
698
699         return 0;
700 }
701
702 static void
703 wrp_alu_imm(struct nfp_prog *nfp_prog, u8 dst, enum alu_op alu_op, u32 imm)
704 {
705         swreg tmp_reg;
706
707         if (alu_op == ALU_OP_AND) {
708                 if (!imm)
709                         wrp_immed(nfp_prog, reg_both(dst), 0);
710                 if (!imm || !~imm)
711                         return;
712         }
713         if (alu_op == ALU_OP_OR) {
714                 if (!~imm)
715                         wrp_immed(nfp_prog, reg_both(dst), ~0U);
716                 if (!imm || !~imm)
717                         return;
718         }
719         if (alu_op == ALU_OP_XOR) {
720                 if (!~imm)
721                         emit_alu(nfp_prog, reg_both(dst), reg_none(),
722                                  ALU_OP_NEG, reg_b(dst));
723                 if (!imm || !~imm)
724                         return;
725         }
726
727         tmp_reg = ur_load_imm_any(nfp_prog, imm, imm_b(nfp_prog));
728         emit_alu(nfp_prog, reg_both(dst), reg_a(dst), alu_op, tmp_reg);
729 }
730
731 static int
732 wrp_alu64_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
733               enum alu_op alu_op, bool skip)
734 {
735         const struct bpf_insn *insn = &meta->insn;
736         u64 imm = insn->imm; /* sign extend */
737
738         if (skip) {
739                 meta->skip = true;
740                 return 0;
741         }
742
743         wrp_alu_imm(nfp_prog, insn->dst_reg * 2, alu_op, imm & ~0U);
744         wrp_alu_imm(nfp_prog, insn->dst_reg * 2 + 1, alu_op, imm >> 32);
745
746         return 0;
747 }
748
749 static int
750 wrp_alu64_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
751               enum alu_op alu_op)
752 {
753         u8 dst = meta->insn.dst_reg * 2, src = meta->insn.src_reg * 2;
754
755         emit_alu(nfp_prog, reg_both(dst), reg_a(dst), alu_op, reg_b(src));
756         emit_alu(nfp_prog, reg_both(dst + 1),
757                  reg_a(dst + 1), alu_op, reg_b(src + 1));
758
759         return 0;
760 }
761
762 static int
763 wrp_alu32_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
764               enum alu_op alu_op, bool skip)
765 {
766         const struct bpf_insn *insn = &meta->insn;
767
768         if (skip) {
769                 meta->skip = true;
770                 return 0;
771         }
772
773         wrp_alu_imm(nfp_prog, insn->dst_reg * 2, alu_op, insn->imm);
774         wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
775
776         return 0;
777 }
778
779 static int
780 wrp_alu32_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
781               enum alu_op alu_op)
782 {
783         u8 dst = meta->insn.dst_reg * 2, src = meta->insn.src_reg * 2;
784
785         emit_alu(nfp_prog, reg_both(dst), reg_a(dst), alu_op, reg_b(src));
786         wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0);
787
788         return 0;
789 }
790
791 static void
792 wrp_test_reg_one(struct nfp_prog *nfp_prog, u8 dst, enum alu_op alu_op, u8 src,
793                  enum br_mask br_mask, u16 off)
794 {
795         emit_alu(nfp_prog, reg_none(), reg_a(dst), alu_op, reg_b(src));
796         emit_br(nfp_prog, br_mask, off, 0);
797 }
798
799 static int
800 wrp_test_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
801              enum alu_op alu_op, enum br_mask br_mask)
802 {
803         const struct bpf_insn *insn = &meta->insn;
804
805         if (insn->off < 0) /* TODO */
806                 return -EOPNOTSUPP;
807
808         wrp_test_reg_one(nfp_prog, insn->dst_reg * 2, alu_op,
809                          insn->src_reg * 2, br_mask, insn->off);
810         wrp_test_reg_one(nfp_prog, insn->dst_reg * 2 + 1, alu_op,
811                          insn->src_reg * 2 + 1, br_mask, insn->off);
812
813         return 0;
814 }
815
816 static int
817 wrp_cmp_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
818             enum br_mask br_mask, bool swap)
819 {
820         const struct bpf_insn *insn = &meta->insn;
821         u64 imm = insn->imm; /* sign extend */
822         u8 reg = insn->dst_reg * 2;
823         swreg tmp_reg;
824
825         if (insn->off < 0) /* TODO */
826                 return -EOPNOTSUPP;
827
828         tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
829         if (!swap)
830                 emit_alu(nfp_prog, reg_none(), reg_a(reg), ALU_OP_SUB, tmp_reg);
831         else
832                 emit_alu(nfp_prog, reg_none(), tmp_reg, ALU_OP_SUB, reg_a(reg));
833
834         tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
835         if (!swap)
836                 emit_alu(nfp_prog, reg_none(),
837                          reg_a(reg + 1), ALU_OP_SUB_C, tmp_reg);
838         else
839                 emit_alu(nfp_prog, reg_none(),
840                          tmp_reg, ALU_OP_SUB_C, reg_a(reg + 1));
841
842         emit_br(nfp_prog, br_mask, insn->off, 0);
843
844         return 0;
845 }
846
847 static int
848 wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
849             enum br_mask br_mask, bool swap)
850 {
851         const struct bpf_insn *insn = &meta->insn;
852         u8 areg = insn->src_reg * 2, breg = insn->dst_reg * 2;
853
854         if (insn->off < 0) /* TODO */
855                 return -EOPNOTSUPP;
856
857         if (swap) {
858                 areg ^= breg;
859                 breg ^= areg;
860                 areg ^= breg;
861         }
862
863         emit_alu(nfp_prog, reg_none(), reg_a(areg), ALU_OP_SUB, reg_b(breg));
864         emit_alu(nfp_prog, reg_none(),
865                  reg_a(areg + 1), ALU_OP_SUB_C, reg_b(breg + 1));
866         emit_br(nfp_prog, br_mask, insn->off, 0);
867
868         return 0;
869 }
870
871 /* --- Callbacks --- */
872 static int mov_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
873 {
874         const struct bpf_insn *insn = &meta->insn;
875
876         wrp_reg_mov(nfp_prog, insn->dst_reg * 2, insn->src_reg * 2);
877         wrp_reg_mov(nfp_prog, insn->dst_reg * 2 + 1, insn->src_reg * 2 + 1);
878
879         return 0;
880 }
881
882 static int mov_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
883 {
884         u64 imm = meta->insn.imm; /* sign extend */
885
886         wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2), imm & ~0U);
887         wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), imm >> 32);
888
889         return 0;
890 }
891
892 static int xor_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
893 {
894         return wrp_alu64_reg(nfp_prog, meta, ALU_OP_XOR);
895 }
896
897 static int xor_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
898 {
899         return wrp_alu64_imm(nfp_prog, meta, ALU_OP_XOR, !meta->insn.imm);
900 }
901
902 static int and_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
903 {
904         return wrp_alu64_reg(nfp_prog, meta, ALU_OP_AND);
905 }
906
907 static int and_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
908 {
909         return wrp_alu64_imm(nfp_prog, meta, ALU_OP_AND, !~meta->insn.imm);
910 }
911
912 static int or_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
913 {
914         return wrp_alu64_reg(nfp_prog, meta, ALU_OP_OR);
915 }
916
917 static int or_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
918 {
919         return wrp_alu64_imm(nfp_prog, meta, ALU_OP_OR, !meta->insn.imm);
920 }
921
922 static int add_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
923 {
924         const struct bpf_insn *insn = &meta->insn;
925
926         emit_alu(nfp_prog, reg_both(insn->dst_reg * 2),
927                  reg_a(insn->dst_reg * 2), ALU_OP_ADD,
928                  reg_b(insn->src_reg * 2));
929         emit_alu(nfp_prog, reg_both(insn->dst_reg * 2 + 1),
930                  reg_a(insn->dst_reg * 2 + 1), ALU_OP_ADD_C,
931                  reg_b(insn->src_reg * 2 + 1));
932
933         return 0;
934 }
935
936 static int add_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
937 {
938         const struct bpf_insn *insn = &meta->insn;
939         u64 imm = insn->imm; /* sign extend */
940
941         wrp_alu_imm(nfp_prog, insn->dst_reg * 2, ALU_OP_ADD, imm & ~0U);
942         wrp_alu_imm(nfp_prog, insn->dst_reg * 2 + 1, ALU_OP_ADD_C, imm >> 32);
943
944         return 0;
945 }
946
947 static int sub_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
948 {
949         const struct bpf_insn *insn = &meta->insn;
950
951         emit_alu(nfp_prog, reg_both(insn->dst_reg * 2),
952                  reg_a(insn->dst_reg * 2), ALU_OP_SUB,
953                  reg_b(insn->src_reg * 2));
954         emit_alu(nfp_prog, reg_both(insn->dst_reg * 2 + 1),
955                  reg_a(insn->dst_reg * 2 + 1), ALU_OP_SUB_C,
956                  reg_b(insn->src_reg * 2 + 1));
957
958         return 0;
959 }
960
961 static int sub_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
962 {
963         const struct bpf_insn *insn = &meta->insn;
964         u64 imm = insn->imm; /* sign extend */
965
966         wrp_alu_imm(nfp_prog, insn->dst_reg * 2, ALU_OP_SUB, imm & ~0U);
967         wrp_alu_imm(nfp_prog, insn->dst_reg * 2 + 1, ALU_OP_SUB_C, imm >> 32);
968
969         return 0;
970 }
971
972 static int shl_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
973 {
974         const struct bpf_insn *insn = &meta->insn;
975
976         if (insn->imm != 32)
977                 return 1; /* TODO */
978
979         wrp_reg_mov(nfp_prog, insn->dst_reg * 2 + 1, insn->dst_reg * 2);
980         wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2), 0);
981
982         return 0;
983 }
984
985 static int shr_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
986 {
987         const struct bpf_insn *insn = &meta->insn;
988
989         if (insn->imm != 32)
990                 return 1; /* TODO */
991
992         wrp_reg_mov(nfp_prog, insn->dst_reg * 2, insn->dst_reg * 2 + 1);
993         wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
994
995         return 0;
996 }
997
998 static int mov_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
999 {
1000         const struct bpf_insn *insn = &meta->insn;
1001
1002         wrp_reg_mov(nfp_prog, insn->dst_reg * 2,  insn->src_reg * 2);
1003         wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
1004
1005         return 0;
1006 }
1007
1008 static int mov_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1009 {
1010         const struct bpf_insn *insn = &meta->insn;
1011
1012         wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2), insn->imm);
1013         wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
1014
1015         return 0;
1016 }
1017
1018 static int xor_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1019 {
1020         return wrp_alu32_reg(nfp_prog, meta, ALU_OP_XOR);
1021 }
1022
1023 static int xor_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1024 {
1025         return wrp_alu32_imm(nfp_prog, meta, ALU_OP_XOR, !~meta->insn.imm);
1026 }
1027
1028 static int and_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1029 {
1030         return wrp_alu32_reg(nfp_prog, meta, ALU_OP_AND);
1031 }
1032
1033 static int and_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1034 {
1035         return wrp_alu32_imm(nfp_prog, meta, ALU_OP_AND, !~meta->insn.imm);
1036 }
1037
1038 static int or_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1039 {
1040         return wrp_alu32_reg(nfp_prog, meta, ALU_OP_OR);
1041 }
1042
1043 static int or_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1044 {
1045         return wrp_alu32_imm(nfp_prog, meta, ALU_OP_OR, !meta->insn.imm);
1046 }
1047
1048 static int add_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1049 {
1050         return wrp_alu32_reg(nfp_prog, meta, ALU_OP_ADD);
1051 }
1052
1053 static int add_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1054 {
1055         return wrp_alu32_imm(nfp_prog, meta, ALU_OP_ADD, !meta->insn.imm);
1056 }
1057
1058 static int sub_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1059 {
1060         return wrp_alu32_reg(nfp_prog, meta, ALU_OP_SUB);
1061 }
1062
1063 static int sub_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1064 {
1065         return wrp_alu32_imm(nfp_prog, meta, ALU_OP_SUB, !meta->insn.imm);
1066 }
1067
1068 static int shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1069 {
1070         const struct bpf_insn *insn = &meta->insn;
1071
1072         if (!insn->imm)
1073                 return 1; /* TODO: zero shift means indirect */
1074
1075         emit_shf(nfp_prog, reg_both(insn->dst_reg * 2),
1076                  reg_none(), SHF_OP_NONE, reg_b(insn->dst_reg * 2),
1077                  SHF_SC_L_SHF, insn->imm);
1078         wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
1079
1080         return 0;
1081 }
1082
1083 static int imm_ld8_part2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1084 {
1085         wrp_immed(nfp_prog, reg_both(nfp_meta_prev(meta)->insn.dst_reg * 2 + 1),
1086                   meta->insn.imm);
1087
1088         return 0;
1089 }
1090
1091 static int imm_ld8(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1092 {
1093         const struct bpf_insn *insn = &meta->insn;
1094
1095         meta->double_cb = imm_ld8_part2;
1096         wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2), insn->imm);
1097
1098         return 0;
1099 }
1100
1101 static int data_ld1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1102 {
1103         return construct_data_ld(nfp_prog, meta->insn.imm, 1);
1104 }
1105
1106 static int data_ld2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1107 {
1108         return construct_data_ld(nfp_prog, meta->insn.imm, 2);
1109 }
1110
1111 static int data_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1112 {
1113         return construct_data_ld(nfp_prog, meta->insn.imm, 4);
1114 }
1115
1116 static int data_ind_ld1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1117 {
1118         return construct_data_ind_ld(nfp_prog, meta->insn.imm,
1119                                      meta->insn.src_reg * 2, true, 1);
1120 }
1121
1122 static int data_ind_ld2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1123 {
1124         return construct_data_ind_ld(nfp_prog, meta->insn.imm,
1125                                      meta->insn.src_reg * 2, true, 2);
1126 }
1127
1128 static int data_ind_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1129 {
1130         return construct_data_ind_ld(nfp_prog, meta->insn.imm,
1131                                      meta->insn.src_reg * 2, true, 4);
1132 }
1133
1134 static int mem_ldx4_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1135 {
1136         if (meta->insn.off == offsetof(struct sk_buff, len))
1137                 emit_alu(nfp_prog, reg_both(meta->insn.dst_reg * 2),
1138                          reg_none(), ALU_OP_NONE, NFP_BPF_ABI_LEN);
1139         else
1140                 return -EOPNOTSUPP;
1141
1142         return 0;
1143 }
1144
1145 static int mem_ldx4_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1146 {
1147         swreg dst = reg_both(meta->insn.dst_reg * 2);
1148
1149         if (meta->insn.off != offsetof(struct xdp_md, data) &&
1150             meta->insn.off != offsetof(struct xdp_md, data_end))
1151                 return -EOPNOTSUPP;
1152
1153         emit_alu(nfp_prog, dst, reg_none(), ALU_OP_NONE, NFP_BPF_ABI_PKT);
1154
1155         if (meta->insn.off == offsetof(struct xdp_md, data))
1156                 return 0;
1157
1158         emit_alu(nfp_prog, dst, dst, ALU_OP_ADD, NFP_BPF_ABI_LEN);
1159
1160         return 0;
1161 }
1162
1163 static int mem_ldx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1164 {
1165         int ret;
1166
1167         if (nfp_prog->act == NN_ACT_XDP)
1168                 ret = mem_ldx4_xdp(nfp_prog, meta);
1169         else
1170                 ret = mem_ldx4_skb(nfp_prog, meta);
1171
1172         wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0);
1173
1174         return ret;
1175 }
1176
1177 static int mem_stx4_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1178 {
1179         if (meta->insn.off == offsetof(struct sk_buff, mark))
1180                 return wrp_set_mark(nfp_prog, meta->insn.src_reg * 2);
1181
1182         return -EOPNOTSUPP;
1183 }
1184
1185 static int mem_stx4_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1186 {
1187         return -EOPNOTSUPP;
1188 }
1189
1190 static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1191 {
1192         if (nfp_prog->act == NN_ACT_XDP)
1193                 return mem_stx4_xdp(nfp_prog, meta);
1194         return mem_stx4_skb(nfp_prog, meta);
1195 }
1196
1197 static int jump(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1198 {
1199         if (meta->insn.off < 0) /* TODO */
1200                 return -EOPNOTSUPP;
1201         emit_br(nfp_prog, BR_UNC, meta->insn.off, 0);
1202
1203         return 0;
1204 }
1205
1206 static int jeq_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1207 {
1208         const struct bpf_insn *insn = &meta->insn;
1209         u64 imm = insn->imm; /* sign extend */
1210         swreg or1, or2, tmp_reg;
1211
1212         or1 = reg_a(insn->dst_reg * 2);
1213         or2 = reg_b(insn->dst_reg * 2 + 1);
1214
1215         if (insn->off < 0) /* TODO */
1216                 return -EOPNOTSUPP;
1217
1218         if (imm & ~0U) {
1219                 tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
1220                 emit_alu(nfp_prog, imm_a(nfp_prog),
1221                          reg_a(insn->dst_reg * 2), ALU_OP_XOR, tmp_reg);
1222                 or1 = imm_a(nfp_prog);
1223         }
1224
1225         if (imm >> 32) {
1226                 tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
1227                 emit_alu(nfp_prog, imm_b(nfp_prog),
1228                          reg_a(insn->dst_reg * 2 + 1), ALU_OP_XOR, tmp_reg);
1229                 or2 = imm_b(nfp_prog);
1230         }
1231
1232         emit_alu(nfp_prog, reg_none(), or1, ALU_OP_OR, or2);
1233         emit_br(nfp_prog, BR_BEQ, insn->off, 0);
1234
1235         return 0;
1236 }
1237
1238 static int jgt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1239 {
1240         return wrp_cmp_imm(nfp_prog, meta, BR_BLO, false);
1241 }
1242
1243 static int jge_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1244 {
1245         return wrp_cmp_imm(nfp_prog, meta, BR_BHS, true);
1246 }
1247
1248 static int jlt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1249 {
1250         return wrp_cmp_imm(nfp_prog, meta, BR_BHS, false);
1251 }
1252
1253 static int jle_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1254 {
1255         return wrp_cmp_imm(nfp_prog, meta, BR_BLO, true);
1256 }
1257
1258 static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1259 {
1260         const struct bpf_insn *insn = &meta->insn;
1261         u64 imm = insn->imm; /* sign extend */
1262         swreg tmp_reg;
1263
1264         if (insn->off < 0) /* TODO */
1265                 return -EOPNOTSUPP;
1266
1267         if (!imm) {
1268                 meta->skip = true;
1269                 return 0;
1270         }
1271
1272         if (imm & ~0U) {
1273                 tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
1274                 emit_alu(nfp_prog, reg_none(),
1275                          reg_a(insn->dst_reg * 2), ALU_OP_AND, tmp_reg);
1276                 emit_br(nfp_prog, BR_BNE, insn->off, 0);
1277         }
1278
1279         if (imm >> 32) {
1280                 tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
1281                 emit_alu(nfp_prog, reg_none(),
1282                          reg_a(insn->dst_reg * 2 + 1), ALU_OP_AND, tmp_reg);
1283                 emit_br(nfp_prog, BR_BNE, insn->off, 0);
1284         }
1285
1286         return 0;
1287 }
1288
1289 static int jne_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1290 {
1291         const struct bpf_insn *insn = &meta->insn;
1292         u64 imm = insn->imm; /* sign extend */
1293         swreg tmp_reg;
1294
1295         if (insn->off < 0) /* TODO */
1296                 return -EOPNOTSUPP;
1297
1298         if (!imm) {
1299                 emit_alu(nfp_prog, reg_none(), reg_a(insn->dst_reg * 2),
1300                          ALU_OP_OR, reg_b(insn->dst_reg * 2 + 1));
1301                 emit_br(nfp_prog, BR_BNE, insn->off, 0);
1302         }
1303
1304         tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
1305         emit_alu(nfp_prog, reg_none(),
1306                  reg_a(insn->dst_reg * 2), ALU_OP_XOR, tmp_reg);
1307         emit_br(nfp_prog, BR_BNE, insn->off, 0);
1308
1309         tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
1310         emit_alu(nfp_prog, reg_none(),
1311                  reg_a(insn->dst_reg * 2 + 1), ALU_OP_XOR, tmp_reg);
1312         emit_br(nfp_prog, BR_BNE, insn->off, 0);
1313
1314         return 0;
1315 }
1316
1317 static int jeq_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1318 {
1319         const struct bpf_insn *insn = &meta->insn;
1320
1321         if (insn->off < 0) /* TODO */
1322                 return -EOPNOTSUPP;
1323
1324         emit_alu(nfp_prog, imm_a(nfp_prog), reg_a(insn->dst_reg * 2),
1325                  ALU_OP_XOR, reg_b(insn->src_reg * 2));
1326         emit_alu(nfp_prog, imm_b(nfp_prog), reg_a(insn->dst_reg * 2 + 1),
1327                  ALU_OP_XOR, reg_b(insn->src_reg * 2 + 1));
1328         emit_alu(nfp_prog, reg_none(),
1329                  imm_a(nfp_prog), ALU_OP_OR, imm_b(nfp_prog));
1330         emit_br(nfp_prog, BR_BEQ, insn->off, 0);
1331
1332         return 0;
1333 }
1334
1335 static int jgt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1336 {
1337         return wrp_cmp_reg(nfp_prog, meta, BR_BLO, false);
1338 }
1339
1340 static int jge_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1341 {
1342         return wrp_cmp_reg(nfp_prog, meta, BR_BHS, true);
1343 }
1344
1345 static int jlt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1346 {
1347         return wrp_cmp_reg(nfp_prog, meta, BR_BHS, false);
1348 }
1349
1350 static int jle_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1351 {
1352         return wrp_cmp_reg(nfp_prog, meta, BR_BLO, true);
1353 }
1354
1355 static int jset_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1356 {
1357         return wrp_test_reg(nfp_prog, meta, ALU_OP_AND, BR_BNE);
1358 }
1359
1360 static int jne_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1361 {
1362         return wrp_test_reg(nfp_prog, meta, ALU_OP_XOR, BR_BNE);
1363 }
1364
1365 static int goto_out(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
1366 {
1367         wrp_br_special(nfp_prog, BR_UNC, OP_BR_GO_OUT);
1368
1369         return 0;
1370 }
1371
1372 static const instr_cb_t instr_cb[256] = {
1373         [BPF_ALU64 | BPF_MOV | BPF_X] = mov_reg64,
1374         [BPF_ALU64 | BPF_MOV | BPF_K] = mov_imm64,
1375         [BPF_ALU64 | BPF_XOR | BPF_X] = xor_reg64,
1376         [BPF_ALU64 | BPF_XOR | BPF_K] = xor_imm64,
1377         [BPF_ALU64 | BPF_AND | BPF_X] = and_reg64,
1378         [BPF_ALU64 | BPF_AND | BPF_K] = and_imm64,
1379         [BPF_ALU64 | BPF_OR | BPF_X] =  or_reg64,
1380         [BPF_ALU64 | BPF_OR | BPF_K] =  or_imm64,
1381         [BPF_ALU64 | BPF_ADD | BPF_X] = add_reg64,
1382         [BPF_ALU64 | BPF_ADD | BPF_K] = add_imm64,
1383         [BPF_ALU64 | BPF_SUB | BPF_X] = sub_reg64,
1384         [BPF_ALU64 | BPF_SUB | BPF_K] = sub_imm64,
1385         [BPF_ALU64 | BPF_LSH | BPF_K] = shl_imm64,
1386         [BPF_ALU64 | BPF_RSH | BPF_K] = shr_imm64,
1387         [BPF_ALU | BPF_MOV | BPF_X] =   mov_reg,
1388         [BPF_ALU | BPF_MOV | BPF_K] =   mov_imm,
1389         [BPF_ALU | BPF_XOR | BPF_X] =   xor_reg,
1390         [BPF_ALU | BPF_XOR | BPF_K] =   xor_imm,
1391         [BPF_ALU | BPF_AND | BPF_X] =   and_reg,
1392         [BPF_ALU | BPF_AND | BPF_K] =   and_imm,
1393         [BPF_ALU | BPF_OR | BPF_X] =    or_reg,
1394         [BPF_ALU | BPF_OR | BPF_K] =    or_imm,
1395         [BPF_ALU | BPF_ADD | BPF_X] =   add_reg,
1396         [BPF_ALU | BPF_ADD | BPF_K] =   add_imm,
1397         [BPF_ALU | BPF_SUB | BPF_X] =   sub_reg,
1398         [BPF_ALU | BPF_SUB | BPF_K] =   sub_imm,
1399         [BPF_ALU | BPF_LSH | BPF_K] =   shl_imm,
1400         [BPF_LD | BPF_IMM | BPF_DW] =   imm_ld8,
1401         [BPF_LD | BPF_ABS | BPF_B] =    data_ld1,
1402         [BPF_LD | BPF_ABS | BPF_H] =    data_ld2,
1403         [BPF_LD | BPF_ABS | BPF_W] =    data_ld4,
1404         [BPF_LD | BPF_IND | BPF_B] =    data_ind_ld1,
1405         [BPF_LD | BPF_IND | BPF_H] =    data_ind_ld2,
1406         [BPF_LD | BPF_IND | BPF_W] =    data_ind_ld4,
1407         [BPF_LDX | BPF_MEM | BPF_W] =   mem_ldx4,
1408         [BPF_STX | BPF_MEM | BPF_W] =   mem_stx4,
1409         [BPF_JMP | BPF_JA | BPF_K] =    jump,
1410         [BPF_JMP | BPF_JEQ | BPF_K] =   jeq_imm,
1411         [BPF_JMP | BPF_JGT | BPF_K] =   jgt_imm,
1412         [BPF_JMP | BPF_JGE | BPF_K] =   jge_imm,
1413         [BPF_JMP | BPF_JLT | BPF_K] =   jlt_imm,
1414         [BPF_JMP | BPF_JLE | BPF_K] =   jle_imm,
1415         [BPF_JMP | BPF_JSET | BPF_K] =  jset_imm,
1416         [BPF_JMP | BPF_JNE | BPF_K] =   jne_imm,
1417         [BPF_JMP | BPF_JEQ | BPF_X] =   jeq_reg,
1418         [BPF_JMP | BPF_JGT | BPF_X] =   jgt_reg,
1419         [BPF_JMP | BPF_JGE | BPF_X] =   jge_reg,
1420         [BPF_JMP | BPF_JLT | BPF_X] =   jlt_reg,
1421         [BPF_JMP | BPF_JLE | BPF_X] =   jle_reg,
1422         [BPF_JMP | BPF_JSET | BPF_X] =  jset_reg,
1423         [BPF_JMP | BPF_JNE | BPF_X] =   jne_reg,
1424         [BPF_JMP | BPF_EXIT] =          goto_out,
1425 };
1426
1427 /* --- Misc code --- */
1428 static void br_set_offset(u64 *instr, u16 offset)
1429 {
1430         u16 addr_lo, addr_hi;
1431
1432         addr_lo = offset & (OP_BR_ADDR_LO >> __bf_shf(OP_BR_ADDR_LO));
1433         addr_hi = offset != addr_lo;
1434         *instr &= ~(OP_BR_ADDR_HI | OP_BR_ADDR_LO);
1435         *instr |= FIELD_PREP(OP_BR_ADDR_HI, addr_hi);
1436         *instr |= FIELD_PREP(OP_BR_ADDR_LO, addr_lo);
1437 }
1438
1439 /* --- Assembler logic --- */
1440 static int nfp_fixup_branches(struct nfp_prog *nfp_prog)
1441 {
1442         struct nfp_insn_meta *meta, *next;
1443         u32 off, br_idx;
1444         u32 idx;
1445
1446         nfp_for_each_insn_walk2(nfp_prog, meta, next) {
1447                 if (meta->skip)
1448                         continue;
1449                 if (BPF_CLASS(meta->insn.code) != BPF_JMP)
1450                         continue;
1451
1452                 br_idx = nfp_prog_offset_to_index(nfp_prog, next->off) - 1;
1453                 if (!nfp_is_br(nfp_prog->prog[br_idx])) {
1454                         pr_err("Fixup found block not ending in branch %d %02x %016llx!!\n",
1455                                br_idx, meta->insn.code, nfp_prog->prog[br_idx]);
1456                         return -ELOOP;
1457                 }
1458                 /* Leave special branches for later */
1459                 if (FIELD_GET(OP_BR_SPECIAL, nfp_prog->prog[br_idx]))
1460                         continue;
1461
1462                 /* Find the target offset in assembler realm */
1463                 off = meta->insn.off;
1464                 if (!off) {
1465                         pr_err("Fixup found zero offset!!\n");
1466                         return -ELOOP;
1467                 }
1468
1469                 while (off && nfp_meta_has_next(nfp_prog, next)) {
1470                         next = nfp_meta_next(next);
1471                         off--;
1472                 }
1473                 if (off) {
1474                         pr_err("Fixup found too large jump!! %d\n", off);
1475                         return -ELOOP;
1476                 }
1477
1478                 if (next->skip) {
1479                         pr_err("Branch landing on removed instruction!!\n");
1480                         return -ELOOP;
1481                 }
1482
1483                 for (idx = nfp_prog_offset_to_index(nfp_prog, meta->off);
1484                      idx <= br_idx; idx++) {
1485                         if (!nfp_is_br(nfp_prog->prog[idx]))
1486                                 continue;
1487                         br_set_offset(&nfp_prog->prog[idx], next->off);
1488                 }
1489         }
1490
1491         /* Fixup 'goto out's separately, they can be scattered around */
1492         for (br_idx = 0; br_idx < nfp_prog->prog_len; br_idx++) {
1493                 enum br_special special;
1494
1495                 if ((nfp_prog->prog[br_idx] & OP_BR_BASE_MASK) != OP_BR_BASE)
1496                         continue;
1497
1498                 special = FIELD_GET(OP_BR_SPECIAL, nfp_prog->prog[br_idx]);
1499                 switch (special) {
1500                 case OP_BR_NORMAL:
1501                         break;
1502                 case OP_BR_GO_OUT:
1503                         br_set_offset(&nfp_prog->prog[br_idx],
1504                                       nfp_prog->tgt_out);
1505                         break;
1506                 case OP_BR_GO_ABORT:
1507                         br_set_offset(&nfp_prog->prog[br_idx],
1508                                       nfp_prog->tgt_abort);
1509                         break;
1510                 }
1511
1512                 nfp_prog->prog[br_idx] &= ~OP_BR_SPECIAL;
1513         }
1514
1515         return 0;
1516 }
1517
1518 static void nfp_intro(struct nfp_prog *nfp_prog)
1519 {
1520         emit_alu(nfp_prog, pkt_reg(nfp_prog),
1521                  reg_none(), ALU_OP_NONE, NFP_BPF_ABI_PKT);
1522 }
1523
1524 static void nfp_outro_tc_legacy(struct nfp_prog *nfp_prog)
1525 {
1526         const u8 act2code[] = {
1527                 [NN_ACT_TC_DROP]  = 0x22,
1528                 [NN_ACT_TC_REDIR] = 0x24
1529         };
1530         /* Target for aborts */
1531         nfp_prog->tgt_abort = nfp_prog_current_offset(nfp_prog);
1532         wrp_immed(nfp_prog, reg_both(0), 0);
1533
1534         /* Target for normal exits */
1535         nfp_prog->tgt_out = nfp_prog_current_offset(nfp_prog);
1536         /* Legacy TC mode:
1537          *   0        0x11 -> pass,  count as stat0
1538          *  -1  drop  0x22 -> drop,  count as stat1
1539          *     redir  0x24 -> redir, count as stat1
1540          *  ife mark  0x21 -> pass,  count as stat1
1541          *  ife + tx  0x24 -> redir, count as stat1
1542          */
1543         emit_br_byte_neq(nfp_prog, reg_b(0), 0xff, 0, nfp_prog->tgt_done, 2);
1544         emit_alu(nfp_prog, reg_a(0),
1545                  reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
1546         emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x11), SHF_SC_L_SHF, 16);
1547
1548         emit_br(nfp_prog, BR_UNC, nfp_prog->tgt_done, 1);
1549         emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(act2code[nfp_prog->act]),
1550                       SHF_SC_L_SHF, 16);
1551 }
1552
1553 static void nfp_outro_tc_da(struct nfp_prog *nfp_prog)
1554 {
1555         /* TC direct-action mode:
1556          *   0,1   ok        NOT SUPPORTED[1]
1557          *   2   drop  0x22 -> drop,  count as stat1
1558          *   4,5 nuke  0x02 -> drop
1559          *   7  redir  0x44 -> redir, count as stat2
1560          *   * unspec  0x11 -> pass,  count as stat0
1561          *
1562          * [1] We can't support OK and RECLASSIFY because we can't tell TC
1563          *     the exact decision made.  We are forced to support UNSPEC
1564          *     to handle aborts so that's the only one we handle for passing
1565          *     packets up the stack.
1566          */
1567         /* Target for aborts */
1568         nfp_prog->tgt_abort = nfp_prog_current_offset(nfp_prog);
1569
1570         emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);
1571
1572         emit_alu(nfp_prog, reg_a(0),
1573                  reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
1574         emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x11), SHF_SC_L_SHF, 16);
1575
1576         /* Target for normal exits */
1577         nfp_prog->tgt_out = nfp_prog_current_offset(nfp_prog);
1578
1579         /* if R0 > 7 jump to abort */
1580         emit_alu(nfp_prog, reg_none(), reg_imm(7), ALU_OP_SUB, reg_b(0));
1581         emit_br(nfp_prog, BR_BLO, nfp_prog->tgt_abort, 0);
1582         emit_alu(nfp_prog, reg_a(0),
1583                  reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
1584
1585         wrp_immed(nfp_prog, reg_b(2), 0x41221211);
1586         wrp_immed(nfp_prog, reg_b(3), 0x41001211);
1587
1588         emit_shf(nfp_prog, reg_a(1),
1589                  reg_none(), SHF_OP_NONE, reg_b(0), SHF_SC_L_SHF, 2);
1590
1591         emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0));
1592         emit_shf(nfp_prog, reg_a(2),
1593                  reg_imm(0xf), SHF_OP_AND, reg_b(2), SHF_SC_R_SHF, 0);
1594
1595         emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0));
1596         emit_shf(nfp_prog, reg_b(2),
1597                  reg_imm(0xf), SHF_OP_AND, reg_b(3), SHF_SC_R_SHF, 0);
1598
1599         emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);
1600
1601         emit_shf(nfp_prog, reg_b(2),
1602                  reg_a(2), SHF_OP_OR, reg_b(2), SHF_SC_L_SHF, 4);
1603         emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16);
1604 }
1605
1606 static void nfp_outro_xdp(struct nfp_prog *nfp_prog)
1607 {
1608         /* XDP return codes:
1609          *   0 aborted  0x82 -> drop,  count as stat3
1610          *   1    drop  0x22 -> drop,  count as stat1
1611          *   2    pass  0x11 -> pass,  count as stat0
1612          *   3      tx  0x44 -> redir, count as stat2
1613          *   * unknown  0x82 -> drop,  count as stat3
1614          */
1615         /* Target for aborts */
1616         nfp_prog->tgt_abort = nfp_prog_current_offset(nfp_prog);
1617
1618         emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);
1619
1620         emit_alu(nfp_prog, reg_a(0),
1621                  reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
1622         emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x82), SHF_SC_L_SHF, 16);
1623
1624         /* Target for normal exits */
1625         nfp_prog->tgt_out = nfp_prog_current_offset(nfp_prog);
1626
1627         /* if R0 > 3 jump to abort */
1628         emit_alu(nfp_prog, reg_none(), reg_imm(3), ALU_OP_SUB, reg_b(0));
1629         emit_br(nfp_prog, BR_BLO, nfp_prog->tgt_abort, 0);
1630
1631         wrp_immed(nfp_prog, reg_b(2), 0x44112282);
1632
1633         emit_shf(nfp_prog, reg_a(1),
1634                  reg_none(), SHF_OP_NONE, reg_b(0), SHF_SC_L_SHF, 3);
1635
1636         emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0));
1637         emit_shf(nfp_prog, reg_b(2),
1638                  reg_imm(0xff), SHF_OP_AND, reg_b(2), SHF_SC_R_SHF, 0);
1639
1640         emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);
1641
1642         emit_alu(nfp_prog, reg_a(0),
1643                  reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
1644         emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16);
1645 }
1646
1647 static void nfp_outro(struct nfp_prog *nfp_prog)
1648 {
1649         switch (nfp_prog->act) {
1650         case NN_ACT_DIRECT:
1651                 nfp_outro_tc_da(nfp_prog);
1652                 break;
1653         case NN_ACT_TC_DROP:
1654         case NN_ACT_TC_REDIR:
1655                 nfp_outro_tc_legacy(nfp_prog);
1656                 break;
1657         case NN_ACT_XDP:
1658                 nfp_outro_xdp(nfp_prog);
1659                 break;
1660         }
1661 }
1662
1663 static int nfp_translate(struct nfp_prog *nfp_prog)
1664 {
1665         struct nfp_insn_meta *meta;
1666         int err;
1667
1668         nfp_intro(nfp_prog);
1669         if (nfp_prog->error)
1670                 return nfp_prog->error;
1671
1672         list_for_each_entry(meta, &nfp_prog->insns, l) {
1673                 instr_cb_t cb = instr_cb[meta->insn.code];
1674
1675                 meta->off = nfp_prog_current_offset(nfp_prog);
1676
1677                 if (meta->skip) {
1678                         nfp_prog->n_translated++;
1679                         continue;
1680                 }
1681
1682                 if (nfp_meta_has_prev(nfp_prog, meta) &&
1683                     nfp_meta_prev(meta)->double_cb)
1684                         cb = nfp_meta_prev(meta)->double_cb;
1685                 if (!cb)
1686                         return -ENOENT;
1687                 err = cb(nfp_prog, meta);
1688                 if (err)
1689                         return err;
1690
1691                 nfp_prog->n_translated++;
1692         }
1693
1694         nfp_outro(nfp_prog);
1695         if (nfp_prog->error)
1696                 return nfp_prog->error;
1697
1698         return nfp_fixup_branches(nfp_prog);
1699 }
1700
1701 static int
1702 nfp_prog_prepare(struct nfp_prog *nfp_prog, const struct bpf_insn *prog,
1703                  unsigned int cnt)
1704 {
1705         unsigned int i;
1706
1707         for (i = 0; i < cnt; i++) {
1708                 struct nfp_insn_meta *meta;
1709
1710                 meta = kzalloc(sizeof(*meta), GFP_KERNEL);
1711                 if (!meta)
1712                         return -ENOMEM;
1713
1714                 meta->insn = prog[i];
1715                 meta->n = i;
1716
1717                 list_add_tail(&meta->l, &nfp_prog->insns);
1718         }
1719
1720         return 0;
1721 }
1722
1723 /* --- Optimizations --- */
1724 static void nfp_bpf_opt_reg_init(struct nfp_prog *nfp_prog)
1725 {
1726         struct nfp_insn_meta *meta;
1727
1728         list_for_each_entry(meta, &nfp_prog->insns, l) {
1729                 struct bpf_insn insn = meta->insn;
1730
1731                 /* Programs converted from cBPF start with register xoring */
1732                 if (insn.code == (BPF_ALU64 | BPF_XOR | BPF_X) &&
1733                     insn.src_reg == insn.dst_reg)
1734                         continue;
1735
1736                 /* Programs start with R6 = R1 but we ignore the skb pointer */
1737                 if (insn.code == (BPF_ALU64 | BPF_MOV | BPF_X) &&
1738                     insn.src_reg == 1 && insn.dst_reg == 6)
1739                         meta->skip = true;
1740
1741                 /* Return as soon as something doesn't match */
1742                 if (!meta->skip)
1743                         return;
1744         }
1745 }
1746
1747 /* Try to rename registers so that program uses only low ones */
1748 static int nfp_bpf_opt_reg_rename(struct nfp_prog *nfp_prog)
1749 {
1750         bool reg_used[MAX_BPF_REG] = {};
1751         u8 tgt_reg[MAX_BPF_REG] = {};
1752         struct nfp_insn_meta *meta;
1753         unsigned int i, j;
1754
1755         list_for_each_entry(meta, &nfp_prog->insns, l) {
1756                 if (meta->skip)
1757                         continue;
1758
1759                 reg_used[meta->insn.src_reg] = true;
1760                 reg_used[meta->insn.dst_reg] = true;
1761         }
1762
1763         for (i = 0, j = 0; i < ARRAY_SIZE(tgt_reg); i++) {
1764                 if (!reg_used[i])
1765                         continue;
1766
1767                 tgt_reg[i] = j++;
1768         }
1769         nfp_prog->num_regs = j;
1770
1771         list_for_each_entry(meta, &nfp_prog->insns, l) {
1772                 meta->insn.src_reg = tgt_reg[meta->insn.src_reg];
1773                 meta->insn.dst_reg = tgt_reg[meta->insn.dst_reg];
1774         }
1775
1776         return 0;
1777 }
1778
1779 /* Remove masking after load since our load guarantees this is not needed */
1780 static void nfp_bpf_opt_ld_mask(struct nfp_prog *nfp_prog)
1781 {
1782         struct nfp_insn_meta *meta1, *meta2;
1783         const s32 exp_mask[] = {
1784                 [BPF_B] = 0x000000ffU,
1785                 [BPF_H] = 0x0000ffffU,
1786                 [BPF_W] = 0xffffffffU,
1787         };
1788
1789         nfp_for_each_insn_walk2(nfp_prog, meta1, meta2) {
1790                 struct bpf_insn insn, next;
1791
1792                 insn = meta1->insn;
1793                 next = meta2->insn;
1794
1795                 if (BPF_CLASS(insn.code) != BPF_LD)
1796                         continue;
1797                 if (BPF_MODE(insn.code) != BPF_ABS &&
1798                     BPF_MODE(insn.code) != BPF_IND)
1799                         continue;
1800
1801                 if (next.code != (BPF_ALU64 | BPF_AND | BPF_K))
1802                         continue;
1803
1804                 if (!exp_mask[BPF_SIZE(insn.code)])
1805                         continue;
1806                 if (exp_mask[BPF_SIZE(insn.code)] != next.imm)
1807                         continue;
1808
1809                 if (next.src_reg || next.dst_reg)
1810                         continue;
1811
1812                 meta2->skip = true;
1813         }
1814 }
1815
1816 static void nfp_bpf_opt_ld_shift(struct nfp_prog *nfp_prog)
1817 {
1818         struct nfp_insn_meta *meta1, *meta2, *meta3;
1819
1820         nfp_for_each_insn_walk3(nfp_prog, meta1, meta2, meta3) {
1821                 struct bpf_insn insn, next1, next2;
1822
1823                 insn = meta1->insn;
1824                 next1 = meta2->insn;
1825                 next2 = meta3->insn;
1826
1827                 if (BPF_CLASS(insn.code) != BPF_LD)
1828                         continue;
1829                 if (BPF_MODE(insn.code) != BPF_ABS &&
1830                     BPF_MODE(insn.code) != BPF_IND)
1831                         continue;
1832                 if (BPF_SIZE(insn.code) != BPF_W)
1833                         continue;
1834
1835                 if (!(next1.code == (BPF_LSH | BPF_K | BPF_ALU64) &&
1836                       next2.code == (BPF_RSH | BPF_K | BPF_ALU64)) &&
1837                     !(next1.code == (BPF_RSH | BPF_K | BPF_ALU64) &&
1838                       next2.code == (BPF_LSH | BPF_K | BPF_ALU64)))
1839                         continue;
1840
1841                 if (next1.src_reg || next1.dst_reg ||
1842                     next2.src_reg || next2.dst_reg)
1843                         continue;
1844
1845                 if (next1.imm != 0x20 || next2.imm != 0x20)
1846                         continue;
1847
1848                 meta2->skip = true;
1849                 meta3->skip = true;
1850         }
1851 }
1852
1853 static int nfp_bpf_optimize(struct nfp_prog *nfp_prog)
1854 {
1855         int ret;
1856
1857         nfp_bpf_opt_reg_init(nfp_prog);
1858
1859         ret = nfp_bpf_opt_reg_rename(nfp_prog);
1860         if (ret)
1861                 return ret;
1862
1863         nfp_bpf_opt_ld_mask(nfp_prog);
1864         nfp_bpf_opt_ld_shift(nfp_prog);
1865
1866         return 0;
1867 }
1868
1869 /**
1870  * nfp_bpf_jit() - translate BPF code into NFP assembly
1871  * @filter:     kernel BPF filter struct
1872  * @prog_mem:   memory to store assembler instructions
1873  * @act:        action attached to this eBPF program
1874  * @prog_start: offset of the first instruction when loaded
1875  * @prog_done:  where to jump on exit
1876  * @prog_sz:    size of @prog_mem in instructions
1877  * @res:        achieved parameters of translation results
1878  */
1879 int
1880 nfp_bpf_jit(struct bpf_prog *filter, void *prog_mem,
1881             enum nfp_bpf_action_type act,
1882             unsigned int prog_start, unsigned int prog_done,
1883             unsigned int prog_sz, struct nfp_bpf_result *res)
1884 {
1885         struct nfp_prog *nfp_prog;
1886         int ret;
1887
1888         nfp_prog = kzalloc(sizeof(*nfp_prog), GFP_KERNEL);
1889         if (!nfp_prog)
1890                 return -ENOMEM;
1891
1892         INIT_LIST_HEAD(&nfp_prog->insns);
1893         nfp_prog->act = act;
1894         nfp_prog->start_off = prog_start;
1895         nfp_prog->tgt_done = prog_done;
1896
1897         ret = nfp_prog_prepare(nfp_prog, filter->insnsi, filter->len);
1898         if (ret)
1899                 goto out;
1900
1901         ret = nfp_prog_verify(nfp_prog, filter);
1902         if (ret)
1903                 goto out;
1904
1905         ret = nfp_bpf_optimize(nfp_prog);
1906         if (ret)
1907                 goto out;
1908
1909         if (nfp_prog->num_regs <= 7)
1910                 nfp_prog->regs_per_thread = 16;
1911         else
1912                 nfp_prog->regs_per_thread = 32;
1913
1914         nfp_prog->prog = prog_mem;
1915         nfp_prog->__prog_alloc_len = prog_sz;
1916
1917         ret = nfp_translate(nfp_prog);
1918         if (ret) {
1919                 pr_err("Translation failed with error %d (translated: %u)\n",
1920                        ret, nfp_prog->n_translated);
1921                 ret = -EINVAL;
1922         }
1923
1924         res->n_instr = nfp_prog->prog_len;
1925         res->dense_mode = nfp_prog->num_regs <= 7;
1926 out:
1927         nfp_prog_free(nfp_prog);
1928
1929         return ret;
1930 }