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_push(struct nfp_prog *nfp_prog, u64 insn) 81 { 82 if (nfp_prog->__prog_alloc_len == nfp_prog->prog_len) { 83 nfp_prog->error = -ENOSPC; 84 return; 85 } 86 87 nfp_prog->prog[nfp_prog->prog_len] = insn; 88 nfp_prog->prog_len++; 89 } 90 91 static unsigned int nfp_prog_current_offset(struct nfp_prog *nfp_prog) 92 { 93 return nfp_prog->start_off + nfp_prog->prog_len; 94 } 95 96 static unsigned int 97 nfp_prog_offset_to_index(struct nfp_prog *nfp_prog, unsigned int offset) 98 { 99 return offset - nfp_prog->start_off; 100 } 101 102 /* --- Emitters --- */ 103 static void 104 __emit_cmd(struct nfp_prog *nfp_prog, enum cmd_tgt_map op, 105 u8 mode, u8 xfer, u8 areg, u8 breg, u8 size, bool sync) 106 { 107 enum cmd_ctx_swap ctx; 108 u64 insn; 109 110 if (sync) 111 ctx = CMD_CTX_SWAP; 112 else 113 ctx = CMD_CTX_NO_SWAP; 114 115 insn = FIELD_PREP(OP_CMD_A_SRC, areg) | 116 FIELD_PREP(OP_CMD_CTX, ctx) | 117 FIELD_PREP(OP_CMD_B_SRC, breg) | 118 FIELD_PREP(OP_CMD_TOKEN, cmd_tgt_act[op].token) | 119 FIELD_PREP(OP_CMD_XFER, xfer) | 120 FIELD_PREP(OP_CMD_CNT, size) | 121 FIELD_PREP(OP_CMD_SIG, sync) | 122 FIELD_PREP(OP_CMD_TGT_CMD, cmd_tgt_act[op].tgt_cmd) | 123 FIELD_PREP(OP_CMD_MODE, mode); 124 125 nfp_prog_push(nfp_prog, insn); 126 } 127 128 static void 129 emit_cmd(struct nfp_prog *nfp_prog, enum cmd_tgt_map op, 130 u8 mode, u8 xfer, swreg lreg, swreg rreg, u8 size, bool sync) 131 { 132 struct nfp_insn_re_regs reg; 133 int err; 134 135 err = swreg_to_restricted(reg_none(), lreg, rreg, ®, false); 136 if (err) { 137 nfp_prog->error = err; 138 return; 139 } 140 if (reg.swap) { 141 pr_err("cmd can't swap arguments\n"); 142 nfp_prog->error = -EFAULT; 143 return; 144 } 145 if (reg.dst_lmextn || reg.src_lmextn) { 146 pr_err("cmd can't use LMextn\n"); 147 nfp_prog->error = -EFAULT; 148 return; 149 } 150 151 __emit_cmd(nfp_prog, op, mode, xfer, reg.areg, reg.breg, size, sync); 152 } 153 154 static void 155 __emit_br(struct nfp_prog *nfp_prog, enum br_mask mask, enum br_ev_pip ev_pip, 156 enum br_ctx_signal_state css, u16 addr, u8 defer) 157 { 158 u16 addr_lo, addr_hi; 159 u64 insn; 160 161 addr_lo = addr & (OP_BR_ADDR_LO >> __bf_shf(OP_BR_ADDR_LO)); 162 addr_hi = addr != addr_lo; 163 164 insn = OP_BR_BASE | 165 FIELD_PREP(OP_BR_MASK, mask) | 166 FIELD_PREP(OP_BR_EV_PIP, ev_pip) | 167 FIELD_PREP(OP_BR_CSS, css) | 168 FIELD_PREP(OP_BR_DEFBR, defer) | 169 FIELD_PREP(OP_BR_ADDR_LO, addr_lo) | 170 FIELD_PREP(OP_BR_ADDR_HI, addr_hi); 171 172 nfp_prog_push(nfp_prog, insn); 173 } 174 175 static void emit_br_def(struct nfp_prog *nfp_prog, u16 addr, u8 defer) 176 { 177 if (defer > 2) { 178 pr_err("BUG: branch defer out of bounds %d\n", defer); 179 nfp_prog->error = -EFAULT; 180 return; 181 } 182 __emit_br(nfp_prog, BR_UNC, BR_EV_PIP_UNCOND, BR_CSS_NONE, addr, defer); 183 } 184 185 static void 186 emit_br(struct nfp_prog *nfp_prog, enum br_mask mask, u16 addr, u8 defer) 187 { 188 __emit_br(nfp_prog, mask, 189 mask != BR_UNC ? BR_EV_PIP_COND : BR_EV_PIP_UNCOND, 190 BR_CSS_NONE, addr, defer); 191 } 192 193 static void 194 __emit_immed(struct nfp_prog *nfp_prog, u16 areg, u16 breg, u16 imm_hi, 195 enum immed_width width, bool invert, 196 enum immed_shift shift, bool wr_both, 197 bool dst_lmextn, bool src_lmextn) 198 { 199 u64 insn; 200 201 insn = OP_IMMED_BASE | 202 FIELD_PREP(OP_IMMED_A_SRC, areg) | 203 FIELD_PREP(OP_IMMED_B_SRC, breg) | 204 FIELD_PREP(OP_IMMED_IMM, imm_hi) | 205 FIELD_PREP(OP_IMMED_WIDTH, width) | 206 FIELD_PREP(OP_IMMED_INV, invert) | 207 FIELD_PREP(OP_IMMED_SHIFT, shift) | 208 FIELD_PREP(OP_IMMED_WR_AB, wr_both) | 209 FIELD_PREP(OP_IMMED_SRC_LMEXTN, src_lmextn) | 210 FIELD_PREP(OP_IMMED_DST_LMEXTN, dst_lmextn); 211 212 nfp_prog_push(nfp_prog, insn); 213 } 214 215 static void 216 emit_immed(struct nfp_prog *nfp_prog, swreg dst, u16 imm, 217 enum immed_width width, bool invert, enum immed_shift shift) 218 { 219 struct nfp_insn_ur_regs reg; 220 int err; 221 222 if (swreg_type(dst) == NN_REG_IMM) { 223 nfp_prog->error = -EFAULT; 224 return; 225 } 226 227 err = swreg_to_unrestricted(dst, dst, reg_imm(imm & 0xff), ®); 228 if (err) { 229 nfp_prog->error = err; 230 return; 231 } 232 233 __emit_immed(nfp_prog, reg.areg, reg.breg, imm >> 8, width, 234 invert, shift, reg.wr_both, 235 reg.dst_lmextn, reg.src_lmextn); 236 } 237 238 static void 239 __emit_shf(struct nfp_prog *nfp_prog, u16 dst, enum alu_dst_ab dst_ab, 240 enum shf_sc sc, u8 shift, 241 u16 areg, enum shf_op op, u16 breg, bool i8, bool sw, bool wr_both, 242 bool dst_lmextn, bool src_lmextn) 243 { 244 u64 insn; 245 246 if (!FIELD_FIT(OP_SHF_SHIFT, shift)) { 247 nfp_prog->error = -EFAULT; 248 return; 249 } 250 251 if (sc == SHF_SC_L_SHF) 252 shift = 32 - shift; 253 254 insn = OP_SHF_BASE | 255 FIELD_PREP(OP_SHF_A_SRC, areg) | 256 FIELD_PREP(OP_SHF_SC, sc) | 257 FIELD_PREP(OP_SHF_B_SRC, breg) | 258 FIELD_PREP(OP_SHF_I8, i8) | 259 FIELD_PREP(OP_SHF_SW, sw) | 260 FIELD_PREP(OP_SHF_DST, dst) | 261 FIELD_PREP(OP_SHF_SHIFT, shift) | 262 FIELD_PREP(OP_SHF_OP, op) | 263 FIELD_PREP(OP_SHF_DST_AB, dst_ab) | 264 FIELD_PREP(OP_SHF_WR_AB, wr_both) | 265 FIELD_PREP(OP_SHF_SRC_LMEXTN, src_lmextn) | 266 FIELD_PREP(OP_SHF_DST_LMEXTN, dst_lmextn); 267 268 nfp_prog_push(nfp_prog, insn); 269 } 270 271 static void 272 emit_shf(struct nfp_prog *nfp_prog, swreg dst, 273 swreg lreg, enum shf_op op, swreg rreg, enum shf_sc sc, u8 shift) 274 { 275 struct nfp_insn_re_regs reg; 276 int err; 277 278 err = swreg_to_restricted(dst, lreg, rreg, ®, true); 279 if (err) { 280 nfp_prog->error = err; 281 return; 282 } 283 284 __emit_shf(nfp_prog, reg.dst, reg.dst_ab, sc, shift, 285 reg.areg, op, reg.breg, reg.i8, reg.swap, reg.wr_both, 286 reg.dst_lmextn, reg.src_lmextn); 287 } 288 289 static void 290 __emit_alu(struct nfp_prog *nfp_prog, u16 dst, enum alu_dst_ab dst_ab, 291 u16 areg, enum alu_op op, u16 breg, bool swap, bool wr_both, 292 bool dst_lmextn, bool src_lmextn) 293 { 294 u64 insn; 295 296 insn = OP_ALU_BASE | 297 FIELD_PREP(OP_ALU_A_SRC, areg) | 298 FIELD_PREP(OP_ALU_B_SRC, breg) | 299 FIELD_PREP(OP_ALU_DST, dst) | 300 FIELD_PREP(OP_ALU_SW, swap) | 301 FIELD_PREP(OP_ALU_OP, op) | 302 FIELD_PREP(OP_ALU_DST_AB, dst_ab) | 303 FIELD_PREP(OP_ALU_WR_AB, wr_both) | 304 FIELD_PREP(OP_ALU_SRC_LMEXTN, src_lmextn) | 305 FIELD_PREP(OP_ALU_DST_LMEXTN, dst_lmextn); 306 307 nfp_prog_push(nfp_prog, insn); 308 } 309 310 static void 311 emit_alu(struct nfp_prog *nfp_prog, swreg dst, 312 swreg lreg, enum alu_op op, swreg rreg) 313 { 314 struct nfp_insn_ur_regs reg; 315 int err; 316 317 err = swreg_to_unrestricted(dst, lreg, rreg, ®); 318 if (err) { 319 nfp_prog->error = err; 320 return; 321 } 322 323 __emit_alu(nfp_prog, reg.dst, reg.dst_ab, 324 reg.areg, op, reg.breg, reg.swap, reg.wr_both, 325 reg.dst_lmextn, reg.src_lmextn); 326 } 327 328 static void 329 __emit_ld_field(struct nfp_prog *nfp_prog, enum shf_sc sc, 330 u8 areg, u8 bmask, u8 breg, u8 shift, bool imm8, 331 bool zero, bool swap, bool wr_both, 332 bool dst_lmextn, bool src_lmextn) 333 { 334 u64 insn; 335 336 insn = OP_LDF_BASE | 337 FIELD_PREP(OP_LDF_A_SRC, areg) | 338 FIELD_PREP(OP_LDF_SC, sc) | 339 FIELD_PREP(OP_LDF_B_SRC, breg) | 340 FIELD_PREP(OP_LDF_I8, imm8) | 341 FIELD_PREP(OP_LDF_SW, swap) | 342 FIELD_PREP(OP_LDF_ZF, zero) | 343 FIELD_PREP(OP_LDF_BMASK, bmask) | 344 FIELD_PREP(OP_LDF_SHF, shift) | 345 FIELD_PREP(OP_LDF_WR_AB, wr_both) | 346 FIELD_PREP(OP_LDF_SRC_LMEXTN, src_lmextn) | 347 FIELD_PREP(OP_LDF_DST_LMEXTN, dst_lmextn); 348 349 nfp_prog_push(nfp_prog, insn); 350 } 351 352 static void 353 emit_ld_field_any(struct nfp_prog *nfp_prog, swreg dst, u8 bmask, swreg src, 354 enum shf_sc sc, u8 shift, bool zero) 355 { 356 struct nfp_insn_re_regs reg; 357 int err; 358 359 /* Note: ld_field is special as it uses one of the src regs as dst */ 360 err = swreg_to_restricted(dst, dst, src, ®, true); 361 if (err) { 362 nfp_prog->error = err; 363 return; 364 } 365 366 __emit_ld_field(nfp_prog, sc, reg.areg, bmask, reg.breg, shift, 367 reg.i8, zero, reg.swap, reg.wr_both, 368 reg.dst_lmextn, reg.src_lmextn); 369 } 370 371 static void 372 emit_ld_field(struct nfp_prog *nfp_prog, swreg dst, u8 bmask, swreg src, 373 enum shf_sc sc, u8 shift) 374 { 375 emit_ld_field_any(nfp_prog, dst, bmask, src, sc, shift, false); 376 } 377 378 static void 379 __emit_lcsr(struct nfp_prog *nfp_prog, u16 areg, u16 breg, bool wr, u16 addr, 380 bool dst_lmextn, bool src_lmextn) 381 { 382 u64 insn; 383 384 insn = OP_LCSR_BASE | 385 FIELD_PREP(OP_LCSR_A_SRC, areg) | 386 FIELD_PREP(OP_LCSR_B_SRC, breg) | 387 FIELD_PREP(OP_LCSR_WRITE, wr) | 388 FIELD_PREP(OP_LCSR_ADDR, addr) | 389 FIELD_PREP(OP_LCSR_SRC_LMEXTN, src_lmextn) | 390 FIELD_PREP(OP_LCSR_DST_LMEXTN, dst_lmextn); 391 392 nfp_prog_push(nfp_prog, insn); 393 } 394 395 static void emit_csr_wr(struct nfp_prog *nfp_prog, swreg src, u16 addr) 396 { 397 struct nfp_insn_ur_regs reg; 398 int err; 399 400 /* This instruction takes immeds instead of reg_none() for the ignored 401 * operand, but we can't encode 2 immeds in one instr with our normal 402 * swreg infra so if param is an immed, we encode as reg_none() and 403 * copy the immed to both operands. 404 */ 405 if (swreg_type(src) == NN_REG_IMM) { 406 err = swreg_to_unrestricted(reg_none(), src, reg_none(), ®); 407 reg.breg = reg.areg; 408 } else { 409 err = swreg_to_unrestricted(reg_none(), src, reg_imm(0), ®); 410 } 411 if (err) { 412 nfp_prog->error = err; 413 return; 414 } 415 416 __emit_lcsr(nfp_prog, reg.areg, reg.breg, true, addr / 4, 417 false, reg.src_lmextn); 418 } 419 420 static void emit_nop(struct nfp_prog *nfp_prog) 421 { 422 __emit_immed(nfp_prog, UR_REG_IMM, UR_REG_IMM, 0, 0, 0, 0, 0, 0, 0); 423 } 424 425 /* --- Wrappers --- */ 426 static bool pack_immed(u32 imm, u16 *val, enum immed_shift *shift) 427 { 428 if (!(imm & 0xffff0000)) { 429 *val = imm; 430 *shift = IMMED_SHIFT_0B; 431 } else if (!(imm & 0xff0000ff)) { 432 *val = imm >> 8; 433 *shift = IMMED_SHIFT_1B; 434 } else if (!(imm & 0x0000ffff)) { 435 *val = imm >> 16; 436 *shift = IMMED_SHIFT_2B; 437 } else { 438 return false; 439 } 440 441 return true; 442 } 443 444 static void wrp_immed(struct nfp_prog *nfp_prog, swreg dst, u32 imm) 445 { 446 enum immed_shift shift; 447 u16 val; 448 449 if (pack_immed(imm, &val, &shift)) { 450 emit_immed(nfp_prog, dst, val, IMMED_WIDTH_ALL, false, shift); 451 } else if (pack_immed(~imm, &val, &shift)) { 452 emit_immed(nfp_prog, dst, val, IMMED_WIDTH_ALL, true, shift); 453 } else { 454 emit_immed(nfp_prog, dst, imm & 0xffff, IMMED_WIDTH_ALL, 455 false, IMMED_SHIFT_0B); 456 emit_immed(nfp_prog, dst, imm >> 16, IMMED_WIDTH_WORD, 457 false, IMMED_SHIFT_2B); 458 } 459 } 460 461 /* ur_load_imm_any() - encode immediate or use tmp register (unrestricted) 462 * If the @imm is small enough encode it directly in operand and return 463 * otherwise load @imm to a spare register and return its encoding. 464 */ 465 static swreg ur_load_imm_any(struct nfp_prog *nfp_prog, u32 imm, swreg tmp_reg) 466 { 467 if (FIELD_FIT(UR_REG_IMM_MAX, imm)) 468 return reg_imm(imm); 469 470 wrp_immed(nfp_prog, tmp_reg, imm); 471 return tmp_reg; 472 } 473 474 /* re_load_imm_any() - encode immediate or use tmp register (restricted) 475 * If the @imm is small enough encode it directly in operand and return 476 * otherwise load @imm to a spare register and return its encoding. 477 */ 478 static swreg re_load_imm_any(struct nfp_prog *nfp_prog, u32 imm, swreg tmp_reg) 479 { 480 if (FIELD_FIT(RE_REG_IMM_MAX, imm)) 481 return reg_imm(imm); 482 483 wrp_immed(nfp_prog, tmp_reg, imm); 484 return tmp_reg; 485 } 486 487 static void wrp_nops(struct nfp_prog *nfp_prog, unsigned int count) 488 { 489 while (count--) 490 emit_nop(nfp_prog); 491 } 492 493 static void 494 wrp_br_special(struct nfp_prog *nfp_prog, enum br_mask mask, 495 enum br_special special) 496 { 497 emit_br(nfp_prog, mask, 0, 0); 498 499 nfp_prog->prog[nfp_prog->prog_len - 1] |= 500 FIELD_PREP(OP_BR_SPECIAL, special); 501 } 502 503 static void wrp_mov(struct nfp_prog *nfp_prog, swreg dst, swreg src) 504 { 505 emit_alu(nfp_prog, dst, reg_none(), ALU_OP_NONE, src); 506 } 507 508 static void wrp_reg_mov(struct nfp_prog *nfp_prog, u16 dst, u16 src) 509 { 510 wrp_mov(nfp_prog, reg_both(dst), reg_b(src)); 511 } 512 513 static int 514 data_ld(struct nfp_prog *nfp_prog, swreg offset, u8 dst_gpr, int size) 515 { 516 unsigned int i; 517 u16 shift, sz; 518 519 /* We load the value from the address indicated in @offset and then 520 * shift out the data we don't need. Note: this is big endian! 521 */ 522 sz = max(size, 4); 523 shift = size < 4 ? 4 - size : 0; 524 525 emit_cmd(nfp_prog, CMD_TGT_READ8, CMD_MODE_32b, 0, 526 pptr_reg(nfp_prog), offset, sz - 1, true); 527 528 i = 0; 529 if (shift) 530 emit_shf(nfp_prog, reg_both(dst_gpr), reg_none(), SHF_OP_NONE, 531 reg_xfer(0), SHF_SC_R_SHF, shift * 8); 532 else 533 for (; i * 4 < size; i++) 534 wrp_mov(nfp_prog, reg_both(dst_gpr + i), reg_xfer(i)); 535 536 if (i < 2) 537 wrp_immed(nfp_prog, reg_both(dst_gpr + 1), 0); 538 539 return 0; 540 } 541 542 static int 543 data_ld_host_order(struct nfp_prog *nfp_prog, u8 src_gpr, swreg offset, 544 u8 dst_gpr, int size) 545 { 546 unsigned int i; 547 u8 mask, sz; 548 549 /* We load the value from the address indicated in @offset and then 550 * mask out the data we don't need. Note: this is little endian! 551 */ 552 sz = max(size, 4); 553 mask = size < 4 ? GENMASK(size - 1, 0) : 0; 554 555 emit_cmd(nfp_prog, CMD_TGT_READ32_SWAP, CMD_MODE_32b, 0, 556 reg_a(src_gpr), offset, sz / 4 - 1, true); 557 558 i = 0; 559 if (mask) 560 emit_ld_field_any(nfp_prog, reg_both(dst_gpr), mask, 561 reg_xfer(0), SHF_SC_NONE, 0, true); 562 else 563 for (; i * 4 < size; i++) 564 wrp_mov(nfp_prog, reg_both(dst_gpr + i), reg_xfer(i)); 565 566 if (i < 2) 567 wrp_immed(nfp_prog, reg_both(dst_gpr + 1), 0); 568 569 return 0; 570 } 571 572 static int 573 construct_data_ind_ld(struct nfp_prog *nfp_prog, u16 offset, u16 src, u8 size) 574 { 575 swreg tmp_reg; 576 577 /* Calculate the true offset (src_reg + imm) */ 578 tmp_reg = ur_load_imm_any(nfp_prog, offset, imm_b(nfp_prog)); 579 emit_alu(nfp_prog, imm_both(nfp_prog), reg_a(src), ALU_OP_ADD, tmp_reg); 580 581 /* Check packet length (size guaranteed to fit b/c it's u8) */ 582 emit_alu(nfp_prog, imm_a(nfp_prog), 583 imm_a(nfp_prog), ALU_OP_ADD, reg_imm(size)); 584 emit_alu(nfp_prog, reg_none(), 585 plen_reg(nfp_prog), ALU_OP_SUB, imm_a(nfp_prog)); 586 wrp_br_special(nfp_prog, BR_BLO, OP_BR_GO_ABORT); 587 588 /* Load data */ 589 return data_ld(nfp_prog, imm_b(nfp_prog), 0, size); 590 } 591 592 static int construct_data_ld(struct nfp_prog *nfp_prog, u16 offset, u8 size) 593 { 594 swreg tmp_reg; 595 596 /* Check packet length */ 597 tmp_reg = ur_load_imm_any(nfp_prog, offset + size, imm_a(nfp_prog)); 598 emit_alu(nfp_prog, reg_none(), plen_reg(nfp_prog), ALU_OP_SUB, tmp_reg); 599 wrp_br_special(nfp_prog, BR_BLO, OP_BR_GO_ABORT); 600 601 /* Load data */ 602 tmp_reg = re_load_imm_any(nfp_prog, offset, imm_b(nfp_prog)); 603 return data_ld(nfp_prog, tmp_reg, 0, size); 604 } 605 606 static int 607 data_stx_host_order(struct nfp_prog *nfp_prog, u8 dst_gpr, swreg offset, 608 u8 src_gpr, u8 size) 609 { 610 unsigned int i; 611 612 for (i = 0; i * 4 < size; i++) 613 wrp_mov(nfp_prog, reg_xfer(i), reg_a(src_gpr + i)); 614 615 emit_cmd(nfp_prog, CMD_TGT_WRITE8_SWAP, CMD_MODE_32b, 0, 616 reg_a(dst_gpr), offset, size - 1, true); 617 618 return 0; 619 } 620 621 static int 622 data_st_host_order(struct nfp_prog *nfp_prog, u8 dst_gpr, swreg offset, 623 u64 imm, u8 size) 624 { 625 wrp_immed(nfp_prog, reg_xfer(0), imm); 626 if (size == 8) 627 wrp_immed(nfp_prog, reg_xfer(1), imm >> 32); 628 629 emit_cmd(nfp_prog, CMD_TGT_WRITE8_SWAP, CMD_MODE_32b, 0, 630 reg_a(dst_gpr), offset, size - 1, true); 631 632 return 0; 633 } 634 635 typedef int 636 (*lmem_step)(struct nfp_prog *nfp_prog, u8 gpr, u8 gpr_byte, s32 off, 637 unsigned int size, bool first, bool new_gpr, bool last, bool lm3, 638 bool needs_inc); 639 640 static int 641 wrp_lmem_load(struct nfp_prog *nfp_prog, u8 dst, u8 dst_byte, s32 off, 642 unsigned int size, bool first, bool new_gpr, bool last, bool lm3, 643 bool needs_inc) 644 { 645 bool should_inc = needs_inc && new_gpr && !last; 646 u32 idx, src_byte; 647 enum shf_sc sc; 648 swreg reg; 649 int shf; 650 u8 mask; 651 652 if (WARN_ON_ONCE(dst_byte + size > 4 || off % 4 + size > 4)) 653 return -EOPNOTSUPP; 654 655 idx = off / 4; 656 657 /* Move the entire word */ 658 if (size == 4) { 659 wrp_mov(nfp_prog, reg_both(dst), 660 should_inc ? reg_lm_inc(3) : reg_lm(lm3 ? 3 : 0, idx)); 661 return 0; 662 } 663 664 if (WARN_ON_ONCE(lm3 && idx > RE_REG_LM_IDX_MAX)) 665 return -EOPNOTSUPP; 666 667 src_byte = off % 4; 668 669 mask = (1 << size) - 1; 670 mask <<= dst_byte; 671 672 if (WARN_ON_ONCE(mask > 0xf)) 673 return -EOPNOTSUPP; 674 675 shf = abs(src_byte - dst_byte) * 8; 676 if (src_byte == dst_byte) { 677 sc = SHF_SC_NONE; 678 } else if (src_byte < dst_byte) { 679 shf = 32 - shf; 680 sc = SHF_SC_L_SHF; 681 } else { 682 sc = SHF_SC_R_SHF; 683 } 684 685 /* ld_field can address fewer indexes, if offset too large do RMW. 686 * Because we RMV twice we waste 2 cycles on unaligned 8 byte writes. 687 */ 688 if (idx <= RE_REG_LM_IDX_MAX) { 689 reg = reg_lm(lm3 ? 3 : 0, idx); 690 } else { 691 reg = imm_a(nfp_prog); 692 /* If it's not the first part of the load and we start a new GPR 693 * that means we are loading a second part of the LMEM word into 694 * a new GPR. IOW we've already looked that LMEM word and 695 * therefore it has been loaded into imm_a(). 696 */ 697 if (first || !new_gpr) 698 wrp_mov(nfp_prog, reg, reg_lm(0, idx)); 699 } 700 701 emit_ld_field_any(nfp_prog, reg_both(dst), mask, reg, sc, shf, new_gpr); 702 703 if (should_inc) 704 wrp_mov(nfp_prog, reg_none(), reg_lm_inc(3)); 705 706 return 0; 707 } 708 709 static int 710 wrp_lmem_store(struct nfp_prog *nfp_prog, u8 src, u8 src_byte, s32 off, 711 unsigned int size, bool first, bool new_gpr, bool last, bool lm3, 712 bool needs_inc) 713 { 714 bool should_inc = needs_inc && new_gpr && !last; 715 u32 idx, dst_byte; 716 enum shf_sc sc; 717 swreg reg; 718 int shf; 719 u8 mask; 720 721 if (WARN_ON_ONCE(src_byte + size > 4 || off % 4 + size > 4)) 722 return -EOPNOTSUPP; 723 724 idx = off / 4; 725 726 /* Move the entire word */ 727 if (size == 4) { 728 wrp_mov(nfp_prog, 729 should_inc ? reg_lm_inc(3) : reg_lm(lm3 ? 3 : 0, idx), 730 reg_b(src)); 731 return 0; 732 } 733 734 if (WARN_ON_ONCE(lm3 && idx > RE_REG_LM_IDX_MAX)) 735 return -EOPNOTSUPP; 736 737 dst_byte = off % 4; 738 739 mask = (1 << size) - 1; 740 mask <<= dst_byte; 741 742 if (WARN_ON_ONCE(mask > 0xf)) 743 return -EOPNOTSUPP; 744 745 shf = abs(src_byte - dst_byte) * 8; 746 if (src_byte == dst_byte) { 747 sc = SHF_SC_NONE; 748 } else if (src_byte < dst_byte) { 749 shf = 32 - shf; 750 sc = SHF_SC_L_SHF; 751 } else { 752 sc = SHF_SC_R_SHF; 753 } 754 755 /* ld_field can address fewer indexes, if offset too large do RMW. 756 * Because we RMV twice we waste 2 cycles on unaligned 8 byte writes. 757 */ 758 if (idx <= RE_REG_LM_IDX_MAX) { 759 reg = reg_lm(lm3 ? 3 : 0, idx); 760 } else { 761 reg = imm_a(nfp_prog); 762 /* Only first and last LMEM locations are going to need RMW, 763 * the middle location will be overwritten fully. 764 */ 765 if (first || last) 766 wrp_mov(nfp_prog, reg, reg_lm(0, idx)); 767 } 768 769 emit_ld_field(nfp_prog, reg, mask, reg_b(src), sc, shf); 770 771 if (new_gpr || last) { 772 if (idx > RE_REG_LM_IDX_MAX) 773 wrp_mov(nfp_prog, reg_lm(0, idx), reg); 774 if (should_inc) 775 wrp_mov(nfp_prog, reg_none(), reg_lm_inc(3)); 776 } 777 778 return 0; 779 } 780 781 static int 782 mem_op_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 783 unsigned int size, unsigned int ptr_off, u8 gpr, u8 ptr_gpr, 784 bool clr_gpr, lmem_step step) 785 { 786 s32 off = nfp_prog->stack_depth + meta->insn.off + ptr_off; 787 bool first = true, last; 788 bool needs_inc = false; 789 swreg stack_off_reg; 790 u8 prev_gpr = 255; 791 u32 gpr_byte = 0; 792 bool lm3 = true; 793 int ret; 794 795 if (meta->ptr_not_const) { 796 /* Use of the last encountered ptr_off is OK, they all have 797 * the same alignment. Depend on low bits of value being 798 * discarded when written to LMaddr register. 799 */ 800 stack_off_reg = ur_load_imm_any(nfp_prog, meta->insn.off, 801 stack_imm(nfp_prog)); 802 803 emit_alu(nfp_prog, imm_b(nfp_prog), 804 reg_a(ptr_gpr), ALU_OP_ADD, stack_off_reg); 805 806 needs_inc = true; 807 } else if (off + size <= 64) { 808 /* We can reach bottom 64B with LMaddr0 */ 809 lm3 = false; 810 } else if (round_down(off, 32) == round_down(off + size - 1, 32)) { 811 /* We have to set up a new pointer. If we know the offset 812 * and the entire access falls into a single 32 byte aligned 813 * window we won't have to increment the LM pointer. 814 * The 32 byte alignment is imporant because offset is ORed in 815 * not added when doing *l$indexN[off]. 816 */ 817 stack_off_reg = ur_load_imm_any(nfp_prog, round_down(off, 32), 818 stack_imm(nfp_prog)); 819 emit_alu(nfp_prog, imm_b(nfp_prog), 820 stack_reg(nfp_prog), ALU_OP_ADD, stack_off_reg); 821 822 off %= 32; 823 } else { 824 stack_off_reg = ur_load_imm_any(nfp_prog, round_down(off, 4), 825 stack_imm(nfp_prog)); 826 827 emit_alu(nfp_prog, imm_b(nfp_prog), 828 stack_reg(nfp_prog), ALU_OP_ADD, stack_off_reg); 829 830 needs_inc = true; 831 } 832 if (lm3) { 833 emit_csr_wr(nfp_prog, imm_b(nfp_prog), NFP_CSR_ACT_LM_ADDR3); 834 /* For size < 4 one slot will be filled by zeroing of upper. */ 835 wrp_nops(nfp_prog, clr_gpr && size < 8 ? 2 : 3); 836 } 837 838 if (clr_gpr && size < 8) 839 wrp_immed(nfp_prog, reg_both(gpr + 1), 0); 840 841 while (size) { 842 u32 slice_end; 843 u8 slice_size; 844 845 slice_size = min(size, 4 - gpr_byte); 846 slice_end = min(off + slice_size, round_up(off + 1, 4)); 847 slice_size = slice_end - off; 848 849 last = slice_size == size; 850 851 if (needs_inc) 852 off %= 4; 853 854 ret = step(nfp_prog, gpr, gpr_byte, off, slice_size, 855 first, gpr != prev_gpr, last, lm3, needs_inc); 856 if (ret) 857 return ret; 858 859 prev_gpr = gpr; 860 first = false; 861 862 gpr_byte += slice_size; 863 if (gpr_byte >= 4) { 864 gpr_byte -= 4; 865 gpr++; 866 } 867 868 size -= slice_size; 869 off += slice_size; 870 } 871 872 return 0; 873 } 874 875 static void 876 wrp_alu_imm(struct nfp_prog *nfp_prog, u8 dst, enum alu_op alu_op, u32 imm) 877 { 878 swreg tmp_reg; 879 880 if (alu_op == ALU_OP_AND) { 881 if (!imm) 882 wrp_immed(nfp_prog, reg_both(dst), 0); 883 if (!imm || !~imm) 884 return; 885 } 886 if (alu_op == ALU_OP_OR) { 887 if (!~imm) 888 wrp_immed(nfp_prog, reg_both(dst), ~0U); 889 if (!imm || !~imm) 890 return; 891 } 892 if (alu_op == ALU_OP_XOR) { 893 if (!~imm) 894 emit_alu(nfp_prog, reg_both(dst), reg_none(), 895 ALU_OP_NOT, reg_b(dst)); 896 if (!imm || !~imm) 897 return; 898 } 899 900 tmp_reg = ur_load_imm_any(nfp_prog, imm, imm_b(nfp_prog)); 901 emit_alu(nfp_prog, reg_both(dst), reg_a(dst), alu_op, tmp_reg); 902 } 903 904 static int 905 wrp_alu64_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 906 enum alu_op alu_op, bool skip) 907 { 908 const struct bpf_insn *insn = &meta->insn; 909 u64 imm = insn->imm; /* sign extend */ 910 911 if (skip) { 912 meta->skip = true; 913 return 0; 914 } 915 916 wrp_alu_imm(nfp_prog, insn->dst_reg * 2, alu_op, imm & ~0U); 917 wrp_alu_imm(nfp_prog, insn->dst_reg * 2 + 1, alu_op, imm >> 32); 918 919 return 0; 920 } 921 922 static int 923 wrp_alu64_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 924 enum alu_op alu_op) 925 { 926 u8 dst = meta->insn.dst_reg * 2, src = meta->insn.src_reg * 2; 927 928 emit_alu(nfp_prog, reg_both(dst), reg_a(dst), alu_op, reg_b(src)); 929 emit_alu(nfp_prog, reg_both(dst + 1), 930 reg_a(dst + 1), alu_op, reg_b(src + 1)); 931 932 return 0; 933 } 934 935 static int 936 wrp_alu32_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 937 enum alu_op alu_op, bool skip) 938 { 939 const struct bpf_insn *insn = &meta->insn; 940 941 if (skip) { 942 meta->skip = true; 943 return 0; 944 } 945 946 wrp_alu_imm(nfp_prog, insn->dst_reg * 2, alu_op, insn->imm); 947 wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0); 948 949 return 0; 950 } 951 952 static int 953 wrp_alu32_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 954 enum alu_op alu_op) 955 { 956 u8 dst = meta->insn.dst_reg * 2, src = meta->insn.src_reg * 2; 957 958 emit_alu(nfp_prog, reg_both(dst), reg_a(dst), alu_op, reg_b(src)); 959 wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0); 960 961 return 0; 962 } 963 964 static void 965 wrp_test_reg_one(struct nfp_prog *nfp_prog, u8 dst, enum alu_op alu_op, u8 src, 966 enum br_mask br_mask, u16 off) 967 { 968 emit_alu(nfp_prog, reg_none(), reg_a(dst), alu_op, reg_b(src)); 969 emit_br(nfp_prog, br_mask, off, 0); 970 } 971 972 static int 973 wrp_test_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 974 enum alu_op alu_op, enum br_mask br_mask) 975 { 976 const struct bpf_insn *insn = &meta->insn; 977 978 if (insn->off < 0) /* TODO */ 979 return -EOPNOTSUPP; 980 981 wrp_test_reg_one(nfp_prog, insn->dst_reg * 2, alu_op, 982 insn->src_reg * 2, br_mask, insn->off); 983 wrp_test_reg_one(nfp_prog, insn->dst_reg * 2 + 1, alu_op, 984 insn->src_reg * 2 + 1, br_mask, insn->off); 985 986 return 0; 987 } 988 989 static int 990 wrp_cmp_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 991 enum br_mask br_mask, bool swap) 992 { 993 const struct bpf_insn *insn = &meta->insn; 994 u64 imm = insn->imm; /* sign extend */ 995 u8 reg = insn->dst_reg * 2; 996 swreg tmp_reg; 997 998 if (insn->off < 0) /* TODO */ 999 return -EOPNOTSUPP; 1000 1001 tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog)); 1002 if (!swap) 1003 emit_alu(nfp_prog, reg_none(), reg_a(reg), ALU_OP_SUB, tmp_reg); 1004 else 1005 emit_alu(nfp_prog, reg_none(), tmp_reg, ALU_OP_SUB, reg_a(reg)); 1006 1007 tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog)); 1008 if (!swap) 1009 emit_alu(nfp_prog, reg_none(), 1010 reg_a(reg + 1), ALU_OP_SUB_C, tmp_reg); 1011 else 1012 emit_alu(nfp_prog, reg_none(), 1013 tmp_reg, ALU_OP_SUB_C, reg_a(reg + 1)); 1014 1015 emit_br(nfp_prog, br_mask, insn->off, 0); 1016 1017 return 0; 1018 } 1019 1020 static int 1021 wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1022 enum br_mask br_mask, bool swap) 1023 { 1024 const struct bpf_insn *insn = &meta->insn; 1025 u8 areg, breg; 1026 1027 areg = insn->dst_reg * 2; 1028 breg = insn->src_reg * 2; 1029 1030 if (insn->off < 0) /* TODO */ 1031 return -EOPNOTSUPP; 1032 1033 if (swap) { 1034 areg ^= breg; 1035 breg ^= areg; 1036 areg ^= breg; 1037 } 1038 1039 emit_alu(nfp_prog, reg_none(), reg_a(areg), ALU_OP_SUB, reg_b(breg)); 1040 emit_alu(nfp_prog, reg_none(), 1041 reg_a(areg + 1), ALU_OP_SUB_C, reg_b(breg + 1)); 1042 emit_br(nfp_prog, br_mask, insn->off, 0); 1043 1044 return 0; 1045 } 1046 1047 static void wrp_end32(struct nfp_prog *nfp_prog, swreg reg_in, u8 gpr_out) 1048 { 1049 emit_ld_field(nfp_prog, reg_both(gpr_out), 0xf, reg_in, 1050 SHF_SC_R_ROT, 8); 1051 emit_ld_field(nfp_prog, reg_both(gpr_out), 0x5, reg_a(gpr_out), 1052 SHF_SC_R_ROT, 16); 1053 } 1054 1055 /* --- Callbacks --- */ 1056 static int mov_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1057 { 1058 const struct bpf_insn *insn = &meta->insn; 1059 u8 dst = insn->dst_reg * 2; 1060 u8 src = insn->src_reg * 2; 1061 1062 if (insn->src_reg == BPF_REG_10) { 1063 swreg stack_depth_reg; 1064 1065 stack_depth_reg = ur_load_imm_any(nfp_prog, 1066 nfp_prog->stack_depth, 1067 stack_imm(nfp_prog)); 1068 emit_alu(nfp_prog, reg_both(dst), 1069 stack_reg(nfp_prog), ALU_OP_ADD, stack_depth_reg); 1070 wrp_immed(nfp_prog, reg_both(dst + 1), 0); 1071 } else { 1072 wrp_reg_mov(nfp_prog, dst, src); 1073 wrp_reg_mov(nfp_prog, dst + 1, src + 1); 1074 } 1075 1076 return 0; 1077 } 1078 1079 static int mov_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1080 { 1081 u64 imm = meta->insn.imm; /* sign extend */ 1082 1083 wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2), imm & ~0U); 1084 wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), imm >> 32); 1085 1086 return 0; 1087 } 1088 1089 static int xor_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1090 { 1091 return wrp_alu64_reg(nfp_prog, meta, ALU_OP_XOR); 1092 } 1093 1094 static int xor_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1095 { 1096 return wrp_alu64_imm(nfp_prog, meta, ALU_OP_XOR, !meta->insn.imm); 1097 } 1098 1099 static int and_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1100 { 1101 return wrp_alu64_reg(nfp_prog, meta, ALU_OP_AND); 1102 } 1103 1104 static int and_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1105 { 1106 return wrp_alu64_imm(nfp_prog, meta, ALU_OP_AND, !~meta->insn.imm); 1107 } 1108 1109 static int or_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1110 { 1111 return wrp_alu64_reg(nfp_prog, meta, ALU_OP_OR); 1112 } 1113 1114 static int or_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1115 { 1116 return wrp_alu64_imm(nfp_prog, meta, ALU_OP_OR, !meta->insn.imm); 1117 } 1118 1119 static int add_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1120 { 1121 const struct bpf_insn *insn = &meta->insn; 1122 1123 emit_alu(nfp_prog, reg_both(insn->dst_reg * 2), 1124 reg_a(insn->dst_reg * 2), ALU_OP_ADD, 1125 reg_b(insn->src_reg * 2)); 1126 emit_alu(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 1127 reg_a(insn->dst_reg * 2 + 1), ALU_OP_ADD_C, 1128 reg_b(insn->src_reg * 2 + 1)); 1129 1130 return 0; 1131 } 1132 1133 static int add_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1134 { 1135 const struct bpf_insn *insn = &meta->insn; 1136 u64 imm = insn->imm; /* sign extend */ 1137 1138 wrp_alu_imm(nfp_prog, insn->dst_reg * 2, ALU_OP_ADD, imm & ~0U); 1139 wrp_alu_imm(nfp_prog, insn->dst_reg * 2 + 1, ALU_OP_ADD_C, imm >> 32); 1140 1141 return 0; 1142 } 1143 1144 static int sub_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1145 { 1146 const struct bpf_insn *insn = &meta->insn; 1147 1148 emit_alu(nfp_prog, reg_both(insn->dst_reg * 2), 1149 reg_a(insn->dst_reg * 2), ALU_OP_SUB, 1150 reg_b(insn->src_reg * 2)); 1151 emit_alu(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 1152 reg_a(insn->dst_reg * 2 + 1), ALU_OP_SUB_C, 1153 reg_b(insn->src_reg * 2 + 1)); 1154 1155 return 0; 1156 } 1157 1158 static int sub_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1159 { 1160 const struct bpf_insn *insn = &meta->insn; 1161 u64 imm = insn->imm; /* sign extend */ 1162 1163 wrp_alu_imm(nfp_prog, insn->dst_reg * 2, ALU_OP_SUB, imm & ~0U); 1164 wrp_alu_imm(nfp_prog, insn->dst_reg * 2 + 1, ALU_OP_SUB_C, imm >> 32); 1165 1166 return 0; 1167 } 1168 1169 static int neg_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1170 { 1171 const struct bpf_insn *insn = &meta->insn; 1172 1173 emit_alu(nfp_prog, reg_both(insn->dst_reg * 2), reg_imm(0), 1174 ALU_OP_SUB, reg_b(insn->dst_reg * 2)); 1175 emit_alu(nfp_prog, reg_both(insn->dst_reg * 2 + 1), reg_imm(0), 1176 ALU_OP_SUB_C, reg_b(insn->dst_reg * 2 + 1)); 1177 1178 return 0; 1179 } 1180 1181 static int shl_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1182 { 1183 const struct bpf_insn *insn = &meta->insn; 1184 u8 dst = insn->dst_reg * 2; 1185 1186 if (insn->imm < 32) { 1187 emit_shf(nfp_prog, reg_both(dst + 1), 1188 reg_a(dst + 1), SHF_OP_NONE, reg_b(dst), 1189 SHF_SC_R_DSHF, 32 - insn->imm); 1190 emit_shf(nfp_prog, reg_both(dst), 1191 reg_none(), SHF_OP_NONE, reg_b(dst), 1192 SHF_SC_L_SHF, insn->imm); 1193 } else if (insn->imm == 32) { 1194 wrp_reg_mov(nfp_prog, dst + 1, dst); 1195 wrp_immed(nfp_prog, reg_both(dst), 0); 1196 } else if (insn->imm > 32) { 1197 emit_shf(nfp_prog, reg_both(dst + 1), 1198 reg_none(), SHF_OP_NONE, reg_b(dst), 1199 SHF_SC_L_SHF, insn->imm - 32); 1200 wrp_immed(nfp_prog, reg_both(dst), 0); 1201 } 1202 1203 return 0; 1204 } 1205 1206 static int shr_imm64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1207 { 1208 const struct bpf_insn *insn = &meta->insn; 1209 u8 dst = insn->dst_reg * 2; 1210 1211 if (insn->imm < 32) { 1212 emit_shf(nfp_prog, reg_both(dst), 1213 reg_a(dst + 1), SHF_OP_NONE, reg_b(dst), 1214 SHF_SC_R_DSHF, insn->imm); 1215 emit_shf(nfp_prog, reg_both(dst + 1), 1216 reg_none(), SHF_OP_NONE, reg_b(dst + 1), 1217 SHF_SC_R_SHF, insn->imm); 1218 } else if (insn->imm == 32) { 1219 wrp_reg_mov(nfp_prog, dst, dst + 1); 1220 wrp_immed(nfp_prog, reg_both(dst + 1), 0); 1221 } else if (insn->imm > 32) { 1222 emit_shf(nfp_prog, reg_both(dst), 1223 reg_none(), SHF_OP_NONE, reg_b(dst + 1), 1224 SHF_SC_R_SHF, insn->imm - 32); 1225 wrp_immed(nfp_prog, reg_both(dst + 1), 0); 1226 } 1227 1228 return 0; 1229 } 1230 1231 static int mov_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1232 { 1233 const struct bpf_insn *insn = &meta->insn; 1234 1235 wrp_reg_mov(nfp_prog, insn->dst_reg * 2, insn->src_reg * 2); 1236 wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0); 1237 1238 return 0; 1239 } 1240 1241 static int mov_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1242 { 1243 const struct bpf_insn *insn = &meta->insn; 1244 1245 wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2), insn->imm); 1246 wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0); 1247 1248 return 0; 1249 } 1250 1251 static int xor_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1252 { 1253 return wrp_alu32_reg(nfp_prog, meta, ALU_OP_XOR); 1254 } 1255 1256 static int xor_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1257 { 1258 return wrp_alu32_imm(nfp_prog, meta, ALU_OP_XOR, !~meta->insn.imm); 1259 } 1260 1261 static int and_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1262 { 1263 return wrp_alu32_reg(nfp_prog, meta, ALU_OP_AND); 1264 } 1265 1266 static int and_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1267 { 1268 return wrp_alu32_imm(nfp_prog, meta, ALU_OP_AND, !~meta->insn.imm); 1269 } 1270 1271 static int or_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1272 { 1273 return wrp_alu32_reg(nfp_prog, meta, ALU_OP_OR); 1274 } 1275 1276 static int or_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1277 { 1278 return wrp_alu32_imm(nfp_prog, meta, ALU_OP_OR, !meta->insn.imm); 1279 } 1280 1281 static int add_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1282 { 1283 return wrp_alu32_reg(nfp_prog, meta, ALU_OP_ADD); 1284 } 1285 1286 static int add_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1287 { 1288 return wrp_alu32_imm(nfp_prog, meta, ALU_OP_ADD, !meta->insn.imm); 1289 } 1290 1291 static int sub_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1292 { 1293 return wrp_alu32_reg(nfp_prog, meta, ALU_OP_SUB); 1294 } 1295 1296 static int sub_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1297 { 1298 return wrp_alu32_imm(nfp_prog, meta, ALU_OP_SUB, !meta->insn.imm); 1299 } 1300 1301 static int neg_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1302 { 1303 u8 dst = meta->insn.dst_reg * 2; 1304 1305 emit_alu(nfp_prog, reg_both(dst), reg_imm(0), ALU_OP_SUB, reg_b(dst)); 1306 wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0); 1307 1308 return 0; 1309 } 1310 1311 static int shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1312 { 1313 const struct bpf_insn *insn = &meta->insn; 1314 1315 if (!insn->imm) 1316 return 1; /* TODO: zero shift means indirect */ 1317 1318 emit_shf(nfp_prog, reg_both(insn->dst_reg * 2), 1319 reg_none(), SHF_OP_NONE, reg_b(insn->dst_reg * 2), 1320 SHF_SC_L_SHF, insn->imm); 1321 wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0); 1322 1323 return 0; 1324 } 1325 1326 static int end_reg32(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1327 { 1328 const struct bpf_insn *insn = &meta->insn; 1329 u8 gpr = insn->dst_reg * 2; 1330 1331 switch (insn->imm) { 1332 case 16: 1333 emit_ld_field(nfp_prog, reg_both(gpr), 0x9, reg_b(gpr), 1334 SHF_SC_R_ROT, 8); 1335 emit_ld_field(nfp_prog, reg_both(gpr), 0xe, reg_a(gpr), 1336 SHF_SC_R_SHF, 16); 1337 1338 wrp_immed(nfp_prog, reg_both(gpr + 1), 0); 1339 break; 1340 case 32: 1341 wrp_end32(nfp_prog, reg_a(gpr), gpr); 1342 wrp_immed(nfp_prog, reg_both(gpr + 1), 0); 1343 break; 1344 case 64: 1345 wrp_mov(nfp_prog, imm_a(nfp_prog), reg_b(gpr + 1)); 1346 1347 wrp_end32(nfp_prog, reg_a(gpr), gpr + 1); 1348 wrp_end32(nfp_prog, imm_a(nfp_prog), gpr); 1349 break; 1350 } 1351 1352 return 0; 1353 } 1354 1355 static int imm_ld8_part2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1356 { 1357 struct nfp_insn_meta *prev = nfp_meta_prev(meta); 1358 u32 imm_lo, imm_hi; 1359 u8 dst; 1360 1361 dst = prev->insn.dst_reg * 2; 1362 imm_lo = prev->insn.imm; 1363 imm_hi = meta->insn.imm; 1364 1365 wrp_immed(nfp_prog, reg_both(dst), imm_lo); 1366 1367 /* mov is always 1 insn, load imm may be two, so try to use mov */ 1368 if (imm_hi == imm_lo) 1369 wrp_mov(nfp_prog, reg_both(dst + 1), reg_a(dst)); 1370 else 1371 wrp_immed(nfp_prog, reg_both(dst + 1), imm_hi); 1372 1373 return 0; 1374 } 1375 1376 static int imm_ld8(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1377 { 1378 meta->double_cb = imm_ld8_part2; 1379 return 0; 1380 } 1381 1382 static int data_ld1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1383 { 1384 return construct_data_ld(nfp_prog, meta->insn.imm, 1); 1385 } 1386 1387 static int data_ld2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1388 { 1389 return construct_data_ld(nfp_prog, meta->insn.imm, 2); 1390 } 1391 1392 static int data_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1393 { 1394 return construct_data_ld(nfp_prog, meta->insn.imm, 4); 1395 } 1396 1397 static int data_ind_ld1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1398 { 1399 return construct_data_ind_ld(nfp_prog, meta->insn.imm, 1400 meta->insn.src_reg * 2, 1); 1401 } 1402 1403 static int data_ind_ld2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1404 { 1405 return construct_data_ind_ld(nfp_prog, meta->insn.imm, 1406 meta->insn.src_reg * 2, 2); 1407 } 1408 1409 static int data_ind_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1410 { 1411 return construct_data_ind_ld(nfp_prog, meta->insn.imm, 1412 meta->insn.src_reg * 2, 4); 1413 } 1414 1415 static int 1416 mem_ldx_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1417 unsigned int size, unsigned int ptr_off) 1418 { 1419 return mem_op_stack(nfp_prog, meta, size, ptr_off, 1420 meta->insn.dst_reg * 2, meta->insn.src_reg * 2, 1421 true, wrp_lmem_load); 1422 } 1423 1424 static int mem_ldx_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1425 u8 size) 1426 { 1427 swreg dst = reg_both(meta->insn.dst_reg * 2); 1428 1429 switch (meta->insn.off) { 1430 case offsetof(struct __sk_buff, len): 1431 if (size != FIELD_SIZEOF(struct __sk_buff, len)) 1432 return -EOPNOTSUPP; 1433 wrp_mov(nfp_prog, dst, plen_reg(nfp_prog)); 1434 break; 1435 case offsetof(struct __sk_buff, data): 1436 if (size != FIELD_SIZEOF(struct __sk_buff, data)) 1437 return -EOPNOTSUPP; 1438 wrp_mov(nfp_prog, dst, pptr_reg(nfp_prog)); 1439 break; 1440 case offsetof(struct __sk_buff, data_end): 1441 if (size != FIELD_SIZEOF(struct __sk_buff, data_end)) 1442 return -EOPNOTSUPP; 1443 emit_alu(nfp_prog, dst, 1444 plen_reg(nfp_prog), ALU_OP_ADD, pptr_reg(nfp_prog)); 1445 break; 1446 default: 1447 return -EOPNOTSUPP; 1448 } 1449 1450 wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0); 1451 1452 return 0; 1453 } 1454 1455 static int mem_ldx_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1456 u8 size) 1457 { 1458 swreg dst = reg_both(meta->insn.dst_reg * 2); 1459 1460 switch (meta->insn.off) { 1461 case offsetof(struct xdp_md, data): 1462 if (size != FIELD_SIZEOF(struct xdp_md, data)) 1463 return -EOPNOTSUPP; 1464 wrp_mov(nfp_prog, dst, pptr_reg(nfp_prog)); 1465 break; 1466 case offsetof(struct xdp_md, data_end): 1467 if (size != FIELD_SIZEOF(struct xdp_md, data_end)) 1468 return -EOPNOTSUPP; 1469 emit_alu(nfp_prog, dst, 1470 plen_reg(nfp_prog), ALU_OP_ADD, pptr_reg(nfp_prog)); 1471 break; 1472 default: 1473 return -EOPNOTSUPP; 1474 } 1475 1476 wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0); 1477 1478 return 0; 1479 } 1480 1481 static int 1482 mem_ldx_data(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1483 unsigned int size) 1484 { 1485 swreg tmp_reg; 1486 1487 tmp_reg = re_load_imm_any(nfp_prog, meta->insn.off, imm_b(nfp_prog)); 1488 1489 return data_ld_host_order(nfp_prog, meta->insn.src_reg * 2, tmp_reg, 1490 meta->insn.dst_reg * 2, size); 1491 } 1492 1493 static int 1494 mem_ldx(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1495 unsigned int size) 1496 { 1497 if (meta->ptr.type == PTR_TO_CTX) { 1498 if (nfp_prog->type == BPF_PROG_TYPE_XDP) 1499 return mem_ldx_xdp(nfp_prog, meta, size); 1500 else 1501 return mem_ldx_skb(nfp_prog, meta, size); 1502 } 1503 1504 if (meta->ptr.type == PTR_TO_PACKET) 1505 return mem_ldx_data(nfp_prog, meta, size); 1506 1507 if (meta->ptr.type == PTR_TO_STACK) 1508 return mem_ldx_stack(nfp_prog, meta, size, 1509 meta->ptr.off + meta->ptr.var_off.value); 1510 1511 return -EOPNOTSUPP; 1512 } 1513 1514 static int mem_ldx1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1515 { 1516 return mem_ldx(nfp_prog, meta, 1); 1517 } 1518 1519 static int mem_ldx2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1520 { 1521 return mem_ldx(nfp_prog, meta, 2); 1522 } 1523 1524 static int mem_ldx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1525 { 1526 return mem_ldx(nfp_prog, meta, 4); 1527 } 1528 1529 static int mem_ldx8(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1530 { 1531 return mem_ldx(nfp_prog, meta, 8); 1532 } 1533 1534 static int 1535 mem_st_data(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1536 unsigned int size) 1537 { 1538 u64 imm = meta->insn.imm; /* sign extend */ 1539 swreg off_reg; 1540 1541 off_reg = re_load_imm_any(nfp_prog, meta->insn.off, imm_b(nfp_prog)); 1542 1543 return data_st_host_order(nfp_prog, meta->insn.dst_reg * 2, off_reg, 1544 imm, size); 1545 } 1546 1547 static int mem_st(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1548 unsigned int size) 1549 { 1550 if (meta->ptr.type == PTR_TO_PACKET) 1551 return mem_st_data(nfp_prog, meta, size); 1552 1553 return -EOPNOTSUPP; 1554 } 1555 1556 static int mem_st1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1557 { 1558 return mem_st(nfp_prog, meta, 1); 1559 } 1560 1561 static int mem_st2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1562 { 1563 return mem_st(nfp_prog, meta, 2); 1564 } 1565 1566 static int mem_st4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1567 { 1568 return mem_st(nfp_prog, meta, 4); 1569 } 1570 1571 static int mem_st8(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1572 { 1573 return mem_st(nfp_prog, meta, 8); 1574 } 1575 1576 static int 1577 mem_stx_data(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1578 unsigned int size) 1579 { 1580 swreg off_reg; 1581 1582 off_reg = re_load_imm_any(nfp_prog, meta->insn.off, imm_b(nfp_prog)); 1583 1584 return data_stx_host_order(nfp_prog, meta->insn.dst_reg * 2, off_reg, 1585 meta->insn.src_reg * 2, size); 1586 } 1587 1588 static int 1589 mem_stx_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1590 unsigned int size, unsigned int ptr_off) 1591 { 1592 return mem_op_stack(nfp_prog, meta, size, ptr_off, 1593 meta->insn.src_reg * 2, meta->insn.dst_reg * 2, 1594 false, wrp_lmem_store); 1595 } 1596 1597 static int 1598 mem_stx(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 1599 unsigned int size) 1600 { 1601 if (meta->ptr.type == PTR_TO_PACKET) 1602 return mem_stx_data(nfp_prog, meta, size); 1603 1604 if (meta->ptr.type == PTR_TO_STACK) 1605 return mem_stx_stack(nfp_prog, meta, size, 1606 meta->ptr.off + meta->ptr.var_off.value); 1607 1608 return -EOPNOTSUPP; 1609 } 1610 1611 static int mem_stx1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1612 { 1613 return mem_stx(nfp_prog, meta, 1); 1614 } 1615 1616 static int mem_stx2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1617 { 1618 return mem_stx(nfp_prog, meta, 2); 1619 } 1620 1621 static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1622 { 1623 return mem_stx(nfp_prog, meta, 4); 1624 } 1625 1626 static int mem_stx8(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1627 { 1628 return mem_stx(nfp_prog, meta, 8); 1629 } 1630 1631 static int jump(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1632 { 1633 if (meta->insn.off < 0) /* TODO */ 1634 return -EOPNOTSUPP; 1635 emit_br(nfp_prog, BR_UNC, meta->insn.off, 0); 1636 1637 return 0; 1638 } 1639 1640 static int jeq_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1641 { 1642 const struct bpf_insn *insn = &meta->insn; 1643 u64 imm = insn->imm; /* sign extend */ 1644 swreg or1, or2, tmp_reg; 1645 1646 or1 = reg_a(insn->dst_reg * 2); 1647 or2 = reg_b(insn->dst_reg * 2 + 1); 1648 1649 if (insn->off < 0) /* TODO */ 1650 return -EOPNOTSUPP; 1651 1652 if (imm & ~0U) { 1653 tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog)); 1654 emit_alu(nfp_prog, imm_a(nfp_prog), 1655 reg_a(insn->dst_reg * 2), ALU_OP_XOR, tmp_reg); 1656 or1 = imm_a(nfp_prog); 1657 } 1658 1659 if (imm >> 32) { 1660 tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog)); 1661 emit_alu(nfp_prog, imm_b(nfp_prog), 1662 reg_a(insn->dst_reg * 2 + 1), ALU_OP_XOR, tmp_reg); 1663 or2 = imm_b(nfp_prog); 1664 } 1665 1666 emit_alu(nfp_prog, reg_none(), or1, ALU_OP_OR, or2); 1667 emit_br(nfp_prog, BR_BEQ, insn->off, 0); 1668 1669 return 0; 1670 } 1671 1672 static int jgt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1673 { 1674 return wrp_cmp_imm(nfp_prog, meta, BR_BLO, true); 1675 } 1676 1677 static int jge_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1678 { 1679 return wrp_cmp_imm(nfp_prog, meta, BR_BHS, false); 1680 } 1681 1682 static int jlt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1683 { 1684 return wrp_cmp_imm(nfp_prog, meta, BR_BLO, false); 1685 } 1686 1687 static int jle_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1688 { 1689 return wrp_cmp_imm(nfp_prog, meta, BR_BHS, true); 1690 } 1691 1692 static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1693 { 1694 const struct bpf_insn *insn = &meta->insn; 1695 u64 imm = insn->imm; /* sign extend */ 1696 swreg tmp_reg; 1697 1698 if (insn->off < 0) /* TODO */ 1699 return -EOPNOTSUPP; 1700 1701 if (!imm) { 1702 meta->skip = true; 1703 return 0; 1704 } 1705 1706 if (imm & ~0U) { 1707 tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog)); 1708 emit_alu(nfp_prog, reg_none(), 1709 reg_a(insn->dst_reg * 2), ALU_OP_AND, tmp_reg); 1710 emit_br(nfp_prog, BR_BNE, insn->off, 0); 1711 } 1712 1713 if (imm >> 32) { 1714 tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog)); 1715 emit_alu(nfp_prog, reg_none(), 1716 reg_a(insn->dst_reg * 2 + 1), ALU_OP_AND, tmp_reg); 1717 emit_br(nfp_prog, BR_BNE, insn->off, 0); 1718 } 1719 1720 return 0; 1721 } 1722 1723 static int jne_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1724 { 1725 const struct bpf_insn *insn = &meta->insn; 1726 u64 imm = insn->imm; /* sign extend */ 1727 swreg tmp_reg; 1728 1729 if (insn->off < 0) /* TODO */ 1730 return -EOPNOTSUPP; 1731 1732 if (!imm) { 1733 emit_alu(nfp_prog, reg_none(), reg_a(insn->dst_reg * 2), 1734 ALU_OP_OR, reg_b(insn->dst_reg * 2 + 1)); 1735 emit_br(nfp_prog, BR_BNE, insn->off, 0); 1736 return 0; 1737 } 1738 1739 tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog)); 1740 emit_alu(nfp_prog, reg_none(), 1741 reg_a(insn->dst_reg * 2), ALU_OP_XOR, tmp_reg); 1742 emit_br(nfp_prog, BR_BNE, insn->off, 0); 1743 1744 tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog)); 1745 emit_alu(nfp_prog, reg_none(), 1746 reg_a(insn->dst_reg * 2 + 1), ALU_OP_XOR, tmp_reg); 1747 emit_br(nfp_prog, BR_BNE, insn->off, 0); 1748 1749 return 0; 1750 } 1751 1752 static int jeq_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1753 { 1754 const struct bpf_insn *insn = &meta->insn; 1755 1756 if (insn->off < 0) /* TODO */ 1757 return -EOPNOTSUPP; 1758 1759 emit_alu(nfp_prog, imm_a(nfp_prog), reg_a(insn->dst_reg * 2), 1760 ALU_OP_XOR, reg_b(insn->src_reg * 2)); 1761 emit_alu(nfp_prog, imm_b(nfp_prog), reg_a(insn->dst_reg * 2 + 1), 1762 ALU_OP_XOR, reg_b(insn->src_reg * 2 + 1)); 1763 emit_alu(nfp_prog, reg_none(), 1764 imm_a(nfp_prog), ALU_OP_OR, imm_b(nfp_prog)); 1765 emit_br(nfp_prog, BR_BEQ, insn->off, 0); 1766 1767 return 0; 1768 } 1769 1770 static int jgt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1771 { 1772 return wrp_cmp_reg(nfp_prog, meta, BR_BLO, true); 1773 } 1774 1775 static int jge_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1776 { 1777 return wrp_cmp_reg(nfp_prog, meta, BR_BHS, false); 1778 } 1779 1780 static int jlt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1781 { 1782 return wrp_cmp_reg(nfp_prog, meta, BR_BLO, false); 1783 } 1784 1785 static int jle_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1786 { 1787 return wrp_cmp_reg(nfp_prog, meta, BR_BHS, true); 1788 } 1789 1790 static int jset_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1791 { 1792 return wrp_test_reg(nfp_prog, meta, ALU_OP_AND, BR_BNE); 1793 } 1794 1795 static int jne_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1796 { 1797 return wrp_test_reg(nfp_prog, meta, ALU_OP_XOR, BR_BNE); 1798 } 1799 1800 static int goto_out(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) 1801 { 1802 wrp_br_special(nfp_prog, BR_UNC, OP_BR_GO_OUT); 1803 1804 return 0; 1805 } 1806 1807 static const instr_cb_t instr_cb[256] = { 1808 [BPF_ALU64 | BPF_MOV | BPF_X] = mov_reg64, 1809 [BPF_ALU64 | BPF_MOV | BPF_K] = mov_imm64, 1810 [BPF_ALU64 | BPF_XOR | BPF_X] = xor_reg64, 1811 [BPF_ALU64 | BPF_XOR | BPF_K] = xor_imm64, 1812 [BPF_ALU64 | BPF_AND | BPF_X] = and_reg64, 1813 [BPF_ALU64 | BPF_AND | BPF_K] = and_imm64, 1814 [BPF_ALU64 | BPF_OR | BPF_X] = or_reg64, 1815 [BPF_ALU64 | BPF_OR | BPF_K] = or_imm64, 1816 [BPF_ALU64 | BPF_ADD | BPF_X] = add_reg64, 1817 [BPF_ALU64 | BPF_ADD | BPF_K] = add_imm64, 1818 [BPF_ALU64 | BPF_SUB | BPF_X] = sub_reg64, 1819 [BPF_ALU64 | BPF_SUB | BPF_K] = sub_imm64, 1820 [BPF_ALU64 | BPF_NEG] = neg_reg64, 1821 [BPF_ALU64 | BPF_LSH | BPF_K] = shl_imm64, 1822 [BPF_ALU64 | BPF_RSH | BPF_K] = shr_imm64, 1823 [BPF_ALU | BPF_MOV | BPF_X] = mov_reg, 1824 [BPF_ALU | BPF_MOV | BPF_K] = mov_imm, 1825 [BPF_ALU | BPF_XOR | BPF_X] = xor_reg, 1826 [BPF_ALU | BPF_XOR | BPF_K] = xor_imm, 1827 [BPF_ALU | BPF_AND | BPF_X] = and_reg, 1828 [BPF_ALU | BPF_AND | BPF_K] = and_imm, 1829 [BPF_ALU | BPF_OR | BPF_X] = or_reg, 1830 [BPF_ALU | BPF_OR | BPF_K] = or_imm, 1831 [BPF_ALU | BPF_ADD | BPF_X] = add_reg, 1832 [BPF_ALU | BPF_ADD | BPF_K] = add_imm, 1833 [BPF_ALU | BPF_SUB | BPF_X] = sub_reg, 1834 [BPF_ALU | BPF_SUB | BPF_K] = sub_imm, 1835 [BPF_ALU | BPF_NEG] = neg_reg, 1836 [BPF_ALU | BPF_LSH | BPF_K] = shl_imm, 1837 [BPF_ALU | BPF_END | BPF_X] = end_reg32, 1838 [BPF_LD | BPF_IMM | BPF_DW] = imm_ld8, 1839 [BPF_LD | BPF_ABS | BPF_B] = data_ld1, 1840 [BPF_LD | BPF_ABS | BPF_H] = data_ld2, 1841 [BPF_LD | BPF_ABS | BPF_W] = data_ld4, 1842 [BPF_LD | BPF_IND | BPF_B] = data_ind_ld1, 1843 [BPF_LD | BPF_IND | BPF_H] = data_ind_ld2, 1844 [BPF_LD | BPF_IND | BPF_W] = data_ind_ld4, 1845 [BPF_LDX | BPF_MEM | BPF_B] = mem_ldx1, 1846 [BPF_LDX | BPF_MEM | BPF_H] = mem_ldx2, 1847 [BPF_LDX | BPF_MEM | BPF_W] = mem_ldx4, 1848 [BPF_LDX | BPF_MEM | BPF_DW] = mem_ldx8, 1849 [BPF_STX | BPF_MEM | BPF_B] = mem_stx1, 1850 [BPF_STX | BPF_MEM | BPF_H] = mem_stx2, 1851 [BPF_STX | BPF_MEM | BPF_W] = mem_stx4, 1852 [BPF_STX | BPF_MEM | BPF_DW] = mem_stx8, 1853 [BPF_ST | BPF_MEM | BPF_B] = mem_st1, 1854 [BPF_ST | BPF_MEM | BPF_H] = mem_st2, 1855 [BPF_ST | BPF_MEM | BPF_W] = mem_st4, 1856 [BPF_ST | BPF_MEM | BPF_DW] = mem_st8, 1857 [BPF_JMP | BPF_JA | BPF_K] = jump, 1858 [BPF_JMP | BPF_JEQ | BPF_K] = jeq_imm, 1859 [BPF_JMP | BPF_JGT | BPF_K] = jgt_imm, 1860 [BPF_JMP | BPF_JGE | BPF_K] = jge_imm, 1861 [BPF_JMP | BPF_JLT | BPF_K] = jlt_imm, 1862 [BPF_JMP | BPF_JLE | BPF_K] = jle_imm, 1863 [BPF_JMP | BPF_JSET | BPF_K] = jset_imm, 1864 [BPF_JMP | BPF_JNE | BPF_K] = jne_imm, 1865 [BPF_JMP | BPF_JEQ | BPF_X] = jeq_reg, 1866 [BPF_JMP | BPF_JGT | BPF_X] = jgt_reg, 1867 [BPF_JMP | BPF_JGE | BPF_X] = jge_reg, 1868 [BPF_JMP | BPF_JLT | BPF_X] = jlt_reg, 1869 [BPF_JMP | BPF_JLE | BPF_X] = jle_reg, 1870 [BPF_JMP | BPF_JSET | BPF_X] = jset_reg, 1871 [BPF_JMP | BPF_JNE | BPF_X] = jne_reg, 1872 [BPF_JMP | BPF_EXIT] = goto_out, 1873 }; 1874 1875 /* --- Misc code --- */ 1876 static void br_set_offset(u64 *instr, u16 offset) 1877 { 1878 u16 addr_lo, addr_hi; 1879 1880 addr_lo = offset & (OP_BR_ADDR_LO >> __bf_shf(OP_BR_ADDR_LO)); 1881 addr_hi = offset != addr_lo; 1882 *instr &= ~(OP_BR_ADDR_HI | OP_BR_ADDR_LO); 1883 *instr |= FIELD_PREP(OP_BR_ADDR_HI, addr_hi); 1884 *instr |= FIELD_PREP(OP_BR_ADDR_LO, addr_lo); 1885 } 1886 1887 /* --- Assembler logic --- */ 1888 static int nfp_fixup_branches(struct nfp_prog *nfp_prog) 1889 { 1890 struct nfp_insn_meta *meta, *next; 1891 u32 off, br_idx; 1892 u32 idx; 1893 1894 nfp_for_each_insn_walk2(nfp_prog, meta, next) { 1895 if (meta->skip) 1896 continue; 1897 if (BPF_CLASS(meta->insn.code) != BPF_JMP) 1898 continue; 1899 1900 br_idx = nfp_prog_offset_to_index(nfp_prog, next->off) - 1; 1901 if (!nfp_is_br(nfp_prog->prog[br_idx])) { 1902 pr_err("Fixup found block not ending in branch %d %02x %016llx!!\n", 1903 br_idx, meta->insn.code, nfp_prog->prog[br_idx]); 1904 return -ELOOP; 1905 } 1906 /* Leave special branches for later */ 1907 if (FIELD_GET(OP_BR_SPECIAL, nfp_prog->prog[br_idx])) 1908 continue; 1909 1910 /* Find the target offset in assembler realm */ 1911 off = meta->insn.off; 1912 if (!off) { 1913 pr_err("Fixup found zero offset!!\n"); 1914 return -ELOOP; 1915 } 1916 1917 while (off && nfp_meta_has_next(nfp_prog, next)) { 1918 next = nfp_meta_next(next); 1919 off--; 1920 } 1921 if (off) { 1922 pr_err("Fixup found too large jump!! %d\n", off); 1923 return -ELOOP; 1924 } 1925 1926 if (next->skip) { 1927 pr_err("Branch landing on removed instruction!!\n"); 1928 return -ELOOP; 1929 } 1930 1931 for (idx = nfp_prog_offset_to_index(nfp_prog, meta->off); 1932 idx <= br_idx; idx++) { 1933 if (!nfp_is_br(nfp_prog->prog[idx])) 1934 continue; 1935 br_set_offset(&nfp_prog->prog[idx], next->off); 1936 } 1937 } 1938 1939 /* Fixup 'goto out's separately, they can be scattered around */ 1940 for (br_idx = 0; br_idx < nfp_prog->prog_len; br_idx++) { 1941 enum br_special special; 1942 1943 if ((nfp_prog->prog[br_idx] & OP_BR_BASE_MASK) != OP_BR_BASE) 1944 continue; 1945 1946 special = FIELD_GET(OP_BR_SPECIAL, nfp_prog->prog[br_idx]); 1947 switch (special) { 1948 case OP_BR_NORMAL: 1949 break; 1950 case OP_BR_GO_OUT: 1951 br_set_offset(&nfp_prog->prog[br_idx], 1952 nfp_prog->tgt_out); 1953 break; 1954 case OP_BR_GO_ABORT: 1955 br_set_offset(&nfp_prog->prog[br_idx], 1956 nfp_prog->tgt_abort); 1957 break; 1958 } 1959 1960 nfp_prog->prog[br_idx] &= ~OP_BR_SPECIAL; 1961 } 1962 1963 return 0; 1964 } 1965 1966 static void nfp_intro(struct nfp_prog *nfp_prog) 1967 { 1968 wrp_immed(nfp_prog, plen_reg(nfp_prog), GENMASK(13, 0)); 1969 emit_alu(nfp_prog, plen_reg(nfp_prog), 1970 plen_reg(nfp_prog), ALU_OP_AND, pv_len(nfp_prog)); 1971 } 1972 1973 static void nfp_outro_tc_da(struct nfp_prog *nfp_prog) 1974 { 1975 /* TC direct-action mode: 1976 * 0,1 ok NOT SUPPORTED[1] 1977 * 2 drop 0x22 -> drop, count as stat1 1978 * 4,5 nuke 0x02 -> drop 1979 * 7 redir 0x44 -> redir, count as stat2 1980 * * unspec 0x11 -> pass, count as stat0 1981 * 1982 * [1] We can't support OK and RECLASSIFY because we can't tell TC 1983 * the exact decision made. We are forced to support UNSPEC 1984 * to handle aborts so that's the only one we handle for passing 1985 * packets up the stack. 1986 */ 1987 /* Target for aborts */ 1988 nfp_prog->tgt_abort = nfp_prog_current_offset(nfp_prog); 1989 1990 emit_br_def(nfp_prog, nfp_prog->tgt_done, 2); 1991 1992 wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS); 1993 emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x11), SHF_SC_L_SHF, 16); 1994 1995 /* Target for normal exits */ 1996 nfp_prog->tgt_out = nfp_prog_current_offset(nfp_prog); 1997 1998 /* if R0 > 7 jump to abort */ 1999 emit_alu(nfp_prog, reg_none(), reg_imm(7), ALU_OP_SUB, reg_b(0)); 2000 emit_br(nfp_prog, BR_BLO, nfp_prog->tgt_abort, 0); 2001 wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS); 2002 2003 wrp_immed(nfp_prog, reg_b(2), 0x41221211); 2004 wrp_immed(nfp_prog, reg_b(3), 0x41001211); 2005 2006 emit_shf(nfp_prog, reg_a(1), 2007 reg_none(), SHF_OP_NONE, reg_b(0), SHF_SC_L_SHF, 2); 2008 2009 emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0)); 2010 emit_shf(nfp_prog, reg_a(2), 2011 reg_imm(0xf), SHF_OP_AND, reg_b(2), SHF_SC_R_SHF, 0); 2012 2013 emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0)); 2014 emit_shf(nfp_prog, reg_b(2), 2015 reg_imm(0xf), SHF_OP_AND, reg_b(3), SHF_SC_R_SHF, 0); 2016 2017 emit_br_def(nfp_prog, nfp_prog->tgt_done, 2); 2018 2019 emit_shf(nfp_prog, reg_b(2), 2020 reg_a(2), SHF_OP_OR, reg_b(2), SHF_SC_L_SHF, 4); 2021 emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16); 2022 } 2023 2024 static void nfp_outro_xdp(struct nfp_prog *nfp_prog) 2025 { 2026 /* XDP return codes: 2027 * 0 aborted 0x82 -> drop, count as stat3 2028 * 1 drop 0x22 -> drop, count as stat1 2029 * 2 pass 0x11 -> pass, count as stat0 2030 * 3 tx 0x44 -> redir, count as stat2 2031 * * unknown 0x82 -> drop, count as stat3 2032 */ 2033 /* Target for aborts */ 2034 nfp_prog->tgt_abort = nfp_prog_current_offset(nfp_prog); 2035 2036 emit_br_def(nfp_prog, nfp_prog->tgt_done, 2); 2037 2038 wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS); 2039 emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x82), SHF_SC_L_SHF, 16); 2040 2041 /* Target for normal exits */ 2042 nfp_prog->tgt_out = nfp_prog_current_offset(nfp_prog); 2043 2044 /* if R0 > 3 jump to abort */ 2045 emit_alu(nfp_prog, reg_none(), reg_imm(3), ALU_OP_SUB, reg_b(0)); 2046 emit_br(nfp_prog, BR_BLO, nfp_prog->tgt_abort, 0); 2047 2048 wrp_immed(nfp_prog, reg_b(2), 0x44112282); 2049 2050 emit_shf(nfp_prog, reg_a(1), 2051 reg_none(), SHF_OP_NONE, reg_b(0), SHF_SC_L_SHF, 3); 2052 2053 emit_alu(nfp_prog, reg_none(), reg_a(1), ALU_OP_OR, reg_imm(0)); 2054 emit_shf(nfp_prog, reg_b(2), 2055 reg_imm(0xff), SHF_OP_AND, reg_b(2), SHF_SC_R_SHF, 0); 2056 2057 emit_br_def(nfp_prog, nfp_prog->tgt_done, 2); 2058 2059 wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS); 2060 emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16); 2061 } 2062 2063 static void nfp_outro(struct nfp_prog *nfp_prog) 2064 { 2065 switch (nfp_prog->type) { 2066 case BPF_PROG_TYPE_SCHED_CLS: 2067 nfp_outro_tc_da(nfp_prog); 2068 break; 2069 case BPF_PROG_TYPE_XDP: 2070 nfp_outro_xdp(nfp_prog); 2071 break; 2072 default: 2073 WARN_ON(1); 2074 } 2075 } 2076 2077 static int nfp_translate(struct nfp_prog *nfp_prog) 2078 { 2079 struct nfp_insn_meta *meta; 2080 int err; 2081 2082 nfp_intro(nfp_prog); 2083 if (nfp_prog->error) 2084 return nfp_prog->error; 2085 2086 list_for_each_entry(meta, &nfp_prog->insns, l) { 2087 instr_cb_t cb = instr_cb[meta->insn.code]; 2088 2089 meta->off = nfp_prog_current_offset(nfp_prog); 2090 2091 if (meta->skip) { 2092 nfp_prog->n_translated++; 2093 continue; 2094 } 2095 2096 if (nfp_meta_has_prev(nfp_prog, meta) && 2097 nfp_meta_prev(meta)->double_cb) 2098 cb = nfp_meta_prev(meta)->double_cb; 2099 if (!cb) 2100 return -ENOENT; 2101 err = cb(nfp_prog, meta); 2102 if (err) 2103 return err; 2104 2105 nfp_prog->n_translated++; 2106 } 2107 2108 nfp_outro(nfp_prog); 2109 if (nfp_prog->error) 2110 return nfp_prog->error; 2111 2112 wrp_nops(nfp_prog, NFP_USTORE_PREFETCH_WINDOW); 2113 if (nfp_prog->error) 2114 return nfp_prog->error; 2115 2116 return nfp_fixup_branches(nfp_prog); 2117 } 2118 2119 /* --- Optimizations --- */ 2120 static void nfp_bpf_opt_reg_init(struct nfp_prog *nfp_prog) 2121 { 2122 struct nfp_insn_meta *meta; 2123 2124 list_for_each_entry(meta, &nfp_prog->insns, l) { 2125 struct bpf_insn insn = meta->insn; 2126 2127 /* Programs converted from cBPF start with register xoring */ 2128 if (insn.code == (BPF_ALU64 | BPF_XOR | BPF_X) && 2129 insn.src_reg == insn.dst_reg) 2130 continue; 2131 2132 /* Programs start with R6 = R1 but we ignore the skb pointer */ 2133 if (insn.code == (BPF_ALU64 | BPF_MOV | BPF_X) && 2134 insn.src_reg == 1 && insn.dst_reg == 6) 2135 meta->skip = true; 2136 2137 /* Return as soon as something doesn't match */ 2138 if (!meta->skip) 2139 return; 2140 } 2141 } 2142 2143 /* Remove masking after load since our load guarantees this is not needed */ 2144 static void nfp_bpf_opt_ld_mask(struct nfp_prog *nfp_prog) 2145 { 2146 struct nfp_insn_meta *meta1, *meta2; 2147 const s32 exp_mask[] = { 2148 [BPF_B] = 0x000000ffU, 2149 [BPF_H] = 0x0000ffffU, 2150 [BPF_W] = 0xffffffffU, 2151 }; 2152 2153 nfp_for_each_insn_walk2(nfp_prog, meta1, meta2) { 2154 struct bpf_insn insn, next; 2155 2156 insn = meta1->insn; 2157 next = meta2->insn; 2158 2159 if (BPF_CLASS(insn.code) != BPF_LD) 2160 continue; 2161 if (BPF_MODE(insn.code) != BPF_ABS && 2162 BPF_MODE(insn.code) != BPF_IND) 2163 continue; 2164 2165 if (next.code != (BPF_ALU64 | BPF_AND | BPF_K)) 2166 continue; 2167 2168 if (!exp_mask[BPF_SIZE(insn.code)]) 2169 continue; 2170 if (exp_mask[BPF_SIZE(insn.code)] != next.imm) 2171 continue; 2172 2173 if (next.src_reg || next.dst_reg) 2174 continue; 2175 2176 meta2->skip = true; 2177 } 2178 } 2179 2180 static void nfp_bpf_opt_ld_shift(struct nfp_prog *nfp_prog) 2181 { 2182 struct nfp_insn_meta *meta1, *meta2, *meta3; 2183 2184 nfp_for_each_insn_walk3(nfp_prog, meta1, meta2, meta3) { 2185 struct bpf_insn insn, next1, next2; 2186 2187 insn = meta1->insn; 2188 next1 = meta2->insn; 2189 next2 = meta3->insn; 2190 2191 if (BPF_CLASS(insn.code) != BPF_LD) 2192 continue; 2193 if (BPF_MODE(insn.code) != BPF_ABS && 2194 BPF_MODE(insn.code) != BPF_IND) 2195 continue; 2196 if (BPF_SIZE(insn.code) != BPF_W) 2197 continue; 2198 2199 if (!(next1.code == (BPF_LSH | BPF_K | BPF_ALU64) && 2200 next2.code == (BPF_RSH | BPF_K | BPF_ALU64)) && 2201 !(next1.code == (BPF_RSH | BPF_K | BPF_ALU64) && 2202 next2.code == (BPF_LSH | BPF_K | BPF_ALU64))) 2203 continue; 2204 2205 if (next1.src_reg || next1.dst_reg || 2206 next2.src_reg || next2.dst_reg) 2207 continue; 2208 2209 if (next1.imm != 0x20 || next2.imm != 0x20) 2210 continue; 2211 2212 meta2->skip = true; 2213 meta3->skip = true; 2214 } 2215 } 2216 2217 static int nfp_bpf_optimize(struct nfp_prog *nfp_prog) 2218 { 2219 nfp_bpf_opt_reg_init(nfp_prog); 2220 2221 nfp_bpf_opt_ld_mask(nfp_prog); 2222 nfp_bpf_opt_ld_shift(nfp_prog); 2223 2224 return 0; 2225 } 2226 2227 static int nfp_bpf_ustore_calc(struct nfp_prog *nfp_prog, __le64 *ustore) 2228 { 2229 int i; 2230 2231 for (i = 0; i < nfp_prog->prog_len; i++) { 2232 int err; 2233 2234 err = nfp_ustore_check_valid_no_ecc(nfp_prog->prog[i]); 2235 if (err) 2236 return err; 2237 2238 nfp_prog->prog[i] = nfp_ustore_calc_ecc_insn(nfp_prog->prog[i]); 2239 2240 ustore[i] = cpu_to_le64(nfp_prog->prog[i]); 2241 } 2242 2243 return 0; 2244 } 2245 2246 int nfp_bpf_jit(struct nfp_prog *nfp_prog) 2247 { 2248 int ret; 2249 2250 ret = nfp_bpf_optimize(nfp_prog); 2251 if (ret) 2252 return ret; 2253 2254 ret = nfp_translate(nfp_prog); 2255 if (ret) { 2256 pr_err("Translation failed with error %d (translated: %u)\n", 2257 ret, nfp_prog->n_translated); 2258 return -EINVAL; 2259 } 2260 2261 return nfp_bpf_ustore_calc(nfp_prog, (__force __le64 *)nfp_prog->prog); 2262 } 2263