| .. | .. |
|---|
| 15 | 15 | #include <asm/cacheflush.h> |
|---|
| 16 | 16 | #include <asm/set_memory.h> |
|---|
| 17 | 17 | #include <asm/nospec-branch.h> |
|---|
| 18 | +#include <asm/asm-prototypes.h> |
|---|
| 18 | 19 | #include <linux/bpf.h> |
|---|
| 19 | 20 | |
|---|
| 20 | 21 | /* |
|---|
| .. | .. |
|---|
| 253 | 254 | /* dst = src */ |
|---|
| 254 | 255 | static inline void emit_ia32_mov_r64(const bool is64, const u8 dst[], |
|---|
| 255 | 256 | const u8 src[], bool dstk, |
|---|
| 256 | | - bool sstk, u8 **pprog) |
|---|
| 257 | + bool sstk, u8 **pprog, |
|---|
| 258 | + const struct bpf_prog_aux *aux) |
|---|
| 257 | 259 | { |
|---|
| 258 | 260 | emit_ia32_mov_r(dst_lo, src_lo, dstk, sstk, pprog); |
|---|
| 259 | 261 | if (is64) |
|---|
| 260 | 262 | /* complete 8 byte move */ |
|---|
| 261 | 263 | emit_ia32_mov_r(dst_hi, src_hi, dstk, sstk, pprog); |
|---|
| 262 | | - else |
|---|
| 264 | + else if (!aux->verifier_zext) |
|---|
| 263 | 265 | /* zero out high 4 bytes */ |
|---|
| 264 | 266 | emit_ia32_mov_i(dst_hi, 0, dstk, pprog); |
|---|
| 265 | 267 | } |
|---|
| .. | .. |
|---|
| 313 | 315 | } |
|---|
| 314 | 316 | |
|---|
| 315 | 317 | static inline void emit_ia32_to_le_r64(const u8 dst[], s32 val, |
|---|
| 316 | | - bool dstk, u8 **pprog) |
|---|
| 318 | + bool dstk, u8 **pprog, |
|---|
| 319 | + const struct bpf_prog_aux *aux) |
|---|
| 317 | 320 | { |
|---|
| 318 | 321 | u8 *prog = *pprog; |
|---|
| 319 | 322 | int cnt = 0; |
|---|
| .. | .. |
|---|
| 334 | 337 | */ |
|---|
| 335 | 338 | EMIT2(0x0F, 0xB7); |
|---|
| 336 | 339 | EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo)); |
|---|
| 337 | | - /* xor dreg_hi,dreg_hi */ |
|---|
| 338 | | - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); |
|---|
| 340 | + if (!aux->verifier_zext) |
|---|
| 341 | + /* xor dreg_hi,dreg_hi */ |
|---|
| 342 | + EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); |
|---|
| 339 | 343 | break; |
|---|
| 340 | 344 | case 32: |
|---|
| 341 | | - /* xor dreg_hi,dreg_hi */ |
|---|
| 342 | | - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); |
|---|
| 345 | + if (!aux->verifier_zext) |
|---|
| 346 | + /* xor dreg_hi,dreg_hi */ |
|---|
| 347 | + EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); |
|---|
| 343 | 348 | break; |
|---|
| 344 | 349 | case 64: |
|---|
| 345 | 350 | /* nop */ |
|---|
| .. | .. |
|---|
| 358 | 363 | } |
|---|
| 359 | 364 | |
|---|
| 360 | 365 | static inline void emit_ia32_to_be_r64(const u8 dst[], s32 val, |
|---|
| 361 | | - bool dstk, u8 **pprog) |
|---|
| 366 | + bool dstk, u8 **pprog, |
|---|
| 367 | + const struct bpf_prog_aux *aux) |
|---|
| 362 | 368 | { |
|---|
| 363 | 369 | u8 *prog = *pprog; |
|---|
| 364 | 370 | int cnt = 0; |
|---|
| .. | .. |
|---|
| 380 | 386 | EMIT2(0x0F, 0xB7); |
|---|
| 381 | 387 | EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo)); |
|---|
| 382 | 388 | |
|---|
| 383 | | - /* xor dreg_hi,dreg_hi */ |
|---|
| 384 | | - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); |
|---|
| 389 | + if (!aux->verifier_zext) |
|---|
| 390 | + /* xor dreg_hi,dreg_hi */ |
|---|
| 391 | + EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); |
|---|
| 385 | 392 | break; |
|---|
| 386 | 393 | case 32: |
|---|
| 387 | 394 | /* Emit 'bswap eax' to swap lower 4 bytes */ |
|---|
| 388 | 395 | EMIT1(0x0F); |
|---|
| 389 | 396 | EMIT1(add_1reg(0xC8, dreg_lo)); |
|---|
| 390 | 397 | |
|---|
| 391 | | - /* xor dreg_hi,dreg_hi */ |
|---|
| 392 | | - EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); |
|---|
| 398 | + if (!aux->verifier_zext) |
|---|
| 399 | + /* xor dreg_hi,dreg_hi */ |
|---|
| 400 | + EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); |
|---|
| 393 | 401 | break; |
|---|
| 394 | 402 | case 64: |
|---|
| 395 | 403 | /* Emit 'bswap eax' to swap lower 4 bytes */ |
|---|
| .. | .. |
|---|
| 569 | 577 | static inline void emit_ia32_alu_r64(const bool is64, const u8 op, |
|---|
| 570 | 578 | const u8 dst[], const u8 src[], |
|---|
| 571 | 579 | bool dstk, bool sstk, |
|---|
| 572 | | - u8 **pprog) |
|---|
| 580 | + u8 **pprog, const struct bpf_prog_aux *aux) |
|---|
| 573 | 581 | { |
|---|
| 574 | 582 | u8 *prog = *pprog; |
|---|
| 575 | 583 | |
|---|
| .. | .. |
|---|
| 577 | 585 | if (is64) |
|---|
| 578 | 586 | emit_ia32_alu_r(is64, true, op, dst_hi, src_hi, dstk, sstk, |
|---|
| 579 | 587 | &prog); |
|---|
| 580 | | - else |
|---|
| 588 | + else if (!aux->verifier_zext) |
|---|
| 581 | 589 | emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 582 | 590 | *pprog = prog; |
|---|
| 583 | 591 | } |
|---|
| .. | .. |
|---|
| 668 | 676 | /* ALU operation (64 bit) */ |
|---|
| 669 | 677 | static inline void emit_ia32_alu_i64(const bool is64, const u8 op, |
|---|
| 670 | 678 | const u8 dst[], const u32 val, |
|---|
| 671 | | - bool dstk, u8 **pprog) |
|---|
| 679 | + bool dstk, u8 **pprog, |
|---|
| 680 | + const struct bpf_prog_aux *aux) |
|---|
| 672 | 681 | { |
|---|
| 673 | 682 | u8 *prog = *pprog; |
|---|
| 674 | 683 | u32 hi = 0; |
|---|
| .. | .. |
|---|
| 679 | 688 | emit_ia32_alu_i(is64, false, op, dst_lo, val, dstk, &prog); |
|---|
| 680 | 689 | if (is64) |
|---|
| 681 | 690 | emit_ia32_alu_i(is64, true, op, dst_hi, hi, dstk, &prog); |
|---|
| 682 | | - else |
|---|
| 691 | + else if (!aux->verifier_zext) |
|---|
| 683 | 692 | emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 684 | 693 | |
|---|
| 685 | 694 | *pprog = prog; |
|---|
| .. | .. |
|---|
| 1259 | 1268 | *pprog = prog; |
|---|
| 1260 | 1269 | } |
|---|
| 1261 | 1270 | |
|---|
| 1271 | +static int emit_jmp_edx(u8 **pprog, u8 *ip) |
|---|
| 1272 | +{ |
|---|
| 1273 | + u8 *prog = *pprog; |
|---|
| 1274 | + int cnt = 0; |
|---|
| 1275 | + |
|---|
| 1276 | +#ifdef CONFIG_RETPOLINE |
|---|
| 1277 | + EMIT1_off32(0xE9, (u8 *)__x86_indirect_thunk_edx - (ip + 5)); |
|---|
| 1278 | +#else |
|---|
| 1279 | + EMIT2(0xFF, 0xE2); |
|---|
| 1280 | +#endif |
|---|
| 1281 | + *pprog = prog; |
|---|
| 1282 | + |
|---|
| 1283 | + return cnt; |
|---|
| 1284 | +} |
|---|
| 1285 | + |
|---|
| 1262 | 1286 | /* |
|---|
| 1263 | 1287 | * Generate the following code: |
|---|
| 1264 | 1288 | * ... bpf_tail_call(void *ctx, struct bpf_array *array, u64 index) ... |
|---|
| .. | .. |
|---|
| 1272 | 1296 | * goto *(prog->bpf_func + prologue_size); |
|---|
| 1273 | 1297 | * out: |
|---|
| 1274 | 1298 | */ |
|---|
| 1275 | | -static void emit_bpf_tail_call(u8 **pprog) |
|---|
| 1299 | +static void emit_bpf_tail_call(u8 **pprog, u8 *ip) |
|---|
| 1276 | 1300 | { |
|---|
| 1277 | 1301 | u8 *prog = *pprog; |
|---|
| 1278 | 1302 | int cnt = 0; |
|---|
| .. | .. |
|---|
| 1354 | 1378 | * eax == ctx (1st arg) |
|---|
| 1355 | 1379 | * edx == prog->bpf_func + prologue_size |
|---|
| 1356 | 1380 | */ |
|---|
| 1357 | | - RETPOLINE_EDX_BPF_JIT(); |
|---|
| 1381 | + cnt += emit_jmp_edx(&prog, ip + cnt); |
|---|
| 1358 | 1382 | |
|---|
| 1359 | 1383 | if (jmp_label1 == -1) |
|---|
| 1360 | 1384 | jmp_label1 = cnt; |
|---|
| .. | .. |
|---|
| 1467 | 1491 | for (i = 0; i < insn_cnt; i++, insn++) { |
|---|
| 1468 | 1492 | const s32 imm32 = insn->imm; |
|---|
| 1469 | 1493 | const bool is64 = BPF_CLASS(insn->code) == BPF_ALU64; |
|---|
| 1470 | | - const bool dstk = insn->dst_reg == BPF_REG_AX ? false : true; |
|---|
| 1471 | | - const bool sstk = insn->src_reg == BPF_REG_AX ? false : true; |
|---|
| 1494 | + const bool dstk = insn->dst_reg != BPF_REG_AX; |
|---|
| 1495 | + const bool sstk = insn->src_reg != BPF_REG_AX; |
|---|
| 1472 | 1496 | const u8 code = insn->code; |
|---|
| 1473 | 1497 | const u8 *dst = bpf2ia32[insn->dst_reg]; |
|---|
| 1474 | 1498 | const u8 *src = bpf2ia32[insn->src_reg]; |
|---|
| .. | .. |
|---|
| 1487 | 1511 | case BPF_ALU64 | BPF_MOV | BPF_X: |
|---|
| 1488 | 1512 | switch (BPF_SRC(code)) { |
|---|
| 1489 | 1513 | case BPF_X: |
|---|
| 1490 | | - emit_ia32_mov_r64(is64, dst, src, dstk, |
|---|
| 1491 | | - sstk, &prog); |
|---|
| 1514 | + if (imm32 == 1) { |
|---|
| 1515 | + /* Special mov32 for zext. */ |
|---|
| 1516 | + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1517 | + break; |
|---|
| 1518 | + } |
|---|
| 1519 | + emit_ia32_mov_r64(is64, dst, src, dstk, sstk, |
|---|
| 1520 | + &prog, bpf_prog->aux); |
|---|
| 1492 | 1521 | break; |
|---|
| 1493 | 1522 | case BPF_K: |
|---|
| 1494 | 1523 | /* Sign-extend immediate value to dst reg */ |
|---|
| .. | .. |
|---|
| 1528 | 1557 | switch (BPF_SRC(code)) { |
|---|
| 1529 | 1558 | case BPF_X: |
|---|
| 1530 | 1559 | emit_ia32_alu_r64(is64, BPF_OP(code), dst, |
|---|
| 1531 | | - src, dstk, sstk, &prog); |
|---|
| 1560 | + src, dstk, sstk, &prog, |
|---|
| 1561 | + bpf_prog->aux); |
|---|
| 1532 | 1562 | break; |
|---|
| 1533 | 1563 | case BPF_K: |
|---|
| 1534 | 1564 | emit_ia32_alu_i64(is64, BPF_OP(code), dst, |
|---|
| 1535 | | - imm32, dstk, &prog); |
|---|
| 1565 | + imm32, dstk, &prog, |
|---|
| 1566 | + bpf_prog->aux); |
|---|
| 1536 | 1567 | break; |
|---|
| 1537 | 1568 | } |
|---|
| 1538 | 1569 | break; |
|---|
| .. | .. |
|---|
| 1551 | 1582 | false, &prog); |
|---|
| 1552 | 1583 | break; |
|---|
| 1553 | 1584 | } |
|---|
| 1554 | | - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1585 | + if (!bpf_prog->aux->verifier_zext) |
|---|
| 1586 | + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1555 | 1587 | break; |
|---|
| 1556 | 1588 | case BPF_ALU | BPF_LSH | BPF_X: |
|---|
| 1557 | 1589 | case BPF_ALU | BPF_RSH | BPF_X: |
|---|
| .. | .. |
|---|
| 1571 | 1603 | &prog); |
|---|
| 1572 | 1604 | break; |
|---|
| 1573 | 1605 | } |
|---|
| 1574 | | - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1606 | + if (!bpf_prog->aux->verifier_zext) |
|---|
| 1607 | + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1575 | 1608 | break; |
|---|
| 1576 | 1609 | /* dst = dst / src(imm) */ |
|---|
| 1577 | 1610 | /* dst = dst % src(imm) */ |
|---|
| .. | .. |
|---|
| 1593 | 1626 | &prog); |
|---|
| 1594 | 1627 | break; |
|---|
| 1595 | 1628 | } |
|---|
| 1596 | | - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1629 | + if (!bpf_prog->aux->verifier_zext) |
|---|
| 1630 | + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1597 | 1631 | break; |
|---|
| 1598 | 1632 | case BPF_ALU64 | BPF_DIV | BPF_K: |
|---|
| 1599 | 1633 | case BPF_ALU64 | BPF_DIV | BPF_X: |
|---|
| .. | .. |
|---|
| 1610 | 1644 | EMIT2_off32(0xC7, add_1reg(0xC0, IA32_ECX), imm32); |
|---|
| 1611 | 1645 | emit_ia32_shift_r(BPF_OP(code), dst_lo, IA32_ECX, dstk, |
|---|
| 1612 | 1646 | false, &prog); |
|---|
| 1613 | | - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1647 | + if (!bpf_prog->aux->verifier_zext) |
|---|
| 1648 | + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1614 | 1649 | break; |
|---|
| 1615 | 1650 | /* dst = dst << imm */ |
|---|
| 1616 | 1651 | case BPF_ALU64 | BPF_LSH | BPF_K: |
|---|
| .. | .. |
|---|
| 1646 | 1681 | case BPF_ALU | BPF_NEG: |
|---|
| 1647 | 1682 | emit_ia32_alu_i(is64, false, BPF_OP(code), |
|---|
| 1648 | 1683 | dst_lo, 0, dstk, &prog); |
|---|
| 1649 | | - emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1684 | + if (!bpf_prog->aux->verifier_zext) |
|---|
| 1685 | + emit_ia32_mov_i(dst_hi, 0, dstk, &prog); |
|---|
| 1650 | 1686 | break; |
|---|
| 1651 | 1687 | /* dst = ~dst (64 bit) */ |
|---|
| 1652 | 1688 | case BPF_ALU64 | BPF_NEG: |
|---|
| .. | .. |
|---|
| 1666 | 1702 | break; |
|---|
| 1667 | 1703 | /* dst = htole(dst) */ |
|---|
| 1668 | 1704 | case BPF_ALU | BPF_END | BPF_FROM_LE: |
|---|
| 1669 | | - emit_ia32_to_le_r64(dst, imm32, dstk, &prog); |
|---|
| 1705 | + emit_ia32_to_le_r64(dst, imm32, dstk, &prog, |
|---|
| 1706 | + bpf_prog->aux); |
|---|
| 1670 | 1707 | break; |
|---|
| 1671 | 1708 | /* dst = htobe(dst) */ |
|---|
| 1672 | 1709 | case BPF_ALU | BPF_END | BPF_FROM_BE: |
|---|
| 1673 | | - emit_ia32_to_be_r64(dst, imm32, dstk, &prog); |
|---|
| 1710 | + emit_ia32_to_be_r64(dst, imm32, dstk, &prog, |
|---|
| 1711 | + bpf_prog->aux); |
|---|
| 1674 | 1712 | break; |
|---|
| 1675 | 1713 | /* dst = imm64 */ |
|---|
| 1676 | 1714 | case BPF_LD | BPF_IMM | BPF_DW: { |
|---|
| .. | .. |
|---|
| 1831 | 1869 | case BPF_B: |
|---|
| 1832 | 1870 | case BPF_H: |
|---|
| 1833 | 1871 | case BPF_W: |
|---|
| 1872 | + if (bpf_prog->aux->verifier_zext) |
|---|
| 1873 | + break; |
|---|
| 1834 | 1874 | if (dstk) { |
|---|
| 1835 | 1875 | EMIT3(0xC7, add_1reg(0x40, IA32_EBP), |
|---|
| 1836 | 1876 | STACK_VAR(dst_hi)); |
|---|
| .. | .. |
|---|
| 1905 | 1945 | break; |
|---|
| 1906 | 1946 | } |
|---|
| 1907 | 1947 | case BPF_JMP | BPF_TAIL_CALL: |
|---|
| 1908 | | - emit_bpf_tail_call(&prog); |
|---|
| 1948 | + emit_bpf_tail_call(&prog, image + addrs[i - 1]); |
|---|
| 1909 | 1949 | break; |
|---|
| 1910 | 1950 | |
|---|
| 1911 | 1951 | /* cond jump */ |
|---|
| .. | .. |
|---|
| 1914 | 1954 | case BPF_JMP | BPF_JGT | BPF_X: |
|---|
| 1915 | 1955 | case BPF_JMP | BPF_JLT | BPF_X: |
|---|
| 1916 | 1956 | case BPF_JMP | BPF_JGE | BPF_X: |
|---|
| 1917 | | - case BPF_JMP | BPF_JLE | BPF_X: { |
|---|
| 1957 | + case BPF_JMP | BPF_JLE | BPF_X: |
|---|
| 1958 | + case BPF_JMP32 | BPF_JEQ | BPF_X: |
|---|
| 1959 | + case BPF_JMP32 | BPF_JNE | BPF_X: |
|---|
| 1960 | + case BPF_JMP32 | BPF_JGT | BPF_X: |
|---|
| 1961 | + case BPF_JMP32 | BPF_JLT | BPF_X: |
|---|
| 1962 | + case BPF_JMP32 | BPF_JGE | BPF_X: |
|---|
| 1963 | + case BPF_JMP32 | BPF_JLE | BPF_X: |
|---|
| 1964 | + case BPF_JMP32 | BPF_JSGT | BPF_X: |
|---|
| 1965 | + case BPF_JMP32 | BPF_JSLE | BPF_X: |
|---|
| 1966 | + case BPF_JMP32 | BPF_JSLT | BPF_X: |
|---|
| 1967 | + case BPF_JMP32 | BPF_JSGE | BPF_X: { |
|---|
| 1968 | + bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP; |
|---|
| 1918 | 1969 | u8 dreg_lo = dstk ? IA32_EAX : dst_lo; |
|---|
| 1919 | 1970 | u8 dreg_hi = dstk ? IA32_EDX : dst_hi; |
|---|
| 1920 | 1971 | u8 sreg_lo = sstk ? IA32_ECX : src_lo; |
|---|
| .. | .. |
|---|
| 1923 | 1974 | if (dstk) { |
|---|
| 1924 | 1975 | EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EAX), |
|---|
| 1925 | 1976 | STACK_VAR(dst_lo)); |
|---|
| 1926 | | - EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EDX), |
|---|
| 1927 | | - STACK_VAR(dst_hi)); |
|---|
| 1977 | + if (is_jmp64) |
|---|
| 1978 | + EMIT3(0x8B, |
|---|
| 1979 | + add_2reg(0x40, IA32_EBP, |
|---|
| 1980 | + IA32_EDX), |
|---|
| 1981 | + STACK_VAR(dst_hi)); |
|---|
| 1928 | 1982 | } |
|---|
| 1929 | 1983 | |
|---|
| 1930 | 1984 | if (sstk) { |
|---|
| 1931 | 1985 | EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_ECX), |
|---|
| 1932 | 1986 | STACK_VAR(src_lo)); |
|---|
| 1933 | | - EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EBX), |
|---|
| 1934 | | - STACK_VAR(src_hi)); |
|---|
| 1987 | + if (is_jmp64) |
|---|
| 1988 | + EMIT3(0x8B, |
|---|
| 1989 | + add_2reg(0x40, IA32_EBP, |
|---|
| 1990 | + IA32_EBX), |
|---|
| 1991 | + STACK_VAR(src_hi)); |
|---|
| 1935 | 1992 | } |
|---|
| 1936 | 1993 | |
|---|
| 1937 | | - /* cmp dreg_hi,sreg_hi */ |
|---|
| 1938 | | - EMIT2(0x39, add_2reg(0xC0, dreg_hi, sreg_hi)); |
|---|
| 1939 | | - EMIT2(IA32_JNE, 2); |
|---|
| 1994 | + if (is_jmp64) { |
|---|
| 1995 | + /* cmp dreg_hi,sreg_hi */ |
|---|
| 1996 | + EMIT2(0x39, add_2reg(0xC0, dreg_hi, sreg_hi)); |
|---|
| 1997 | + EMIT2(IA32_JNE, 2); |
|---|
| 1998 | + } |
|---|
| 1940 | 1999 | /* cmp dreg_lo,sreg_lo */ |
|---|
| 1941 | 2000 | EMIT2(0x39, add_2reg(0xC0, dreg_lo, sreg_lo)); |
|---|
| 1942 | 2001 | goto emit_cond_jmp; |
|---|
| .. | .. |
|---|
| 1975 | 2034 | EMIT2(0x39, add_2reg(0xC0, dreg_lo, sreg_lo)); |
|---|
| 1976 | 2035 | goto emit_cond_jmp_signed; |
|---|
| 1977 | 2036 | } |
|---|
| 1978 | | - case BPF_JMP | BPF_JSET | BPF_X: { |
|---|
| 2037 | + case BPF_JMP | BPF_JSET | BPF_X: |
|---|
| 2038 | + case BPF_JMP32 | BPF_JSET | BPF_X: { |
|---|
| 2039 | + bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP; |
|---|
| 1979 | 2040 | u8 dreg_lo = IA32_EAX; |
|---|
| 1980 | 2041 | u8 dreg_hi = IA32_EDX; |
|---|
| 1981 | 2042 | u8 sreg_lo = sstk ? IA32_ECX : src_lo; |
|---|
| .. | .. |
|---|
| 1984 | 2045 | if (dstk) { |
|---|
| 1985 | 2046 | EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EAX), |
|---|
| 1986 | 2047 | STACK_VAR(dst_lo)); |
|---|
| 1987 | | - EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EDX), |
|---|
| 1988 | | - STACK_VAR(dst_hi)); |
|---|
| 2048 | + if (is_jmp64) |
|---|
| 2049 | + EMIT3(0x8B, |
|---|
| 2050 | + add_2reg(0x40, IA32_EBP, |
|---|
| 2051 | + IA32_EDX), |
|---|
| 2052 | + STACK_VAR(dst_hi)); |
|---|
| 1989 | 2053 | } else { |
|---|
| 1990 | 2054 | /* mov dreg_lo,dst_lo */ |
|---|
| 1991 | 2055 | EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo)); |
|---|
| 1992 | | - /* mov dreg_hi,dst_hi */ |
|---|
| 1993 | | - EMIT2(0x89, |
|---|
| 1994 | | - add_2reg(0xC0, dreg_hi, dst_hi)); |
|---|
| 2056 | + if (is_jmp64) |
|---|
| 2057 | + /* mov dreg_hi,dst_hi */ |
|---|
| 2058 | + EMIT2(0x89, |
|---|
| 2059 | + add_2reg(0xC0, dreg_hi, dst_hi)); |
|---|
| 1995 | 2060 | } |
|---|
| 1996 | 2061 | |
|---|
| 1997 | 2062 | if (sstk) { |
|---|
| 1998 | 2063 | EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_ECX), |
|---|
| 1999 | 2064 | STACK_VAR(src_lo)); |
|---|
| 2000 | | - EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EBX), |
|---|
| 2001 | | - STACK_VAR(src_hi)); |
|---|
| 2065 | + if (is_jmp64) |
|---|
| 2066 | + EMIT3(0x8B, |
|---|
| 2067 | + add_2reg(0x40, IA32_EBP, |
|---|
| 2068 | + IA32_EBX), |
|---|
| 2069 | + STACK_VAR(src_hi)); |
|---|
| 2002 | 2070 | } |
|---|
| 2003 | 2071 | /* and dreg_lo,sreg_lo */ |
|---|
| 2004 | 2072 | EMIT2(0x23, add_2reg(0xC0, sreg_lo, dreg_lo)); |
|---|
| 2005 | | - /* and dreg_hi,sreg_hi */ |
|---|
| 2006 | | - EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi)); |
|---|
| 2007 | | - /* or dreg_lo,dreg_hi */ |
|---|
| 2008 | | - EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi)); |
|---|
| 2073 | + if (is_jmp64) { |
|---|
| 2074 | + /* and dreg_hi,sreg_hi */ |
|---|
| 2075 | + EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi)); |
|---|
| 2076 | + /* or dreg_lo,dreg_hi */ |
|---|
| 2077 | + EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi)); |
|---|
| 2078 | + } |
|---|
| 2009 | 2079 | goto emit_cond_jmp; |
|---|
| 2010 | 2080 | } |
|---|
| 2011 | | - case BPF_JMP | BPF_JSET | BPF_K: { |
|---|
| 2012 | | - u32 hi; |
|---|
| 2081 | + case BPF_JMP | BPF_JSET | BPF_K: |
|---|
| 2082 | + case BPF_JMP32 | BPF_JSET | BPF_K: { |
|---|
| 2083 | + bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP; |
|---|
| 2013 | 2084 | u8 dreg_lo = IA32_EAX; |
|---|
| 2014 | 2085 | u8 dreg_hi = IA32_EDX; |
|---|
| 2015 | 2086 | u8 sreg_lo = IA32_ECX; |
|---|
| 2016 | 2087 | u8 sreg_hi = IA32_EBX; |
|---|
| 2088 | + u32 hi; |
|---|
| 2017 | 2089 | |
|---|
| 2018 | 2090 | if (dstk) { |
|---|
| 2019 | 2091 | EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EAX), |
|---|
| 2020 | 2092 | STACK_VAR(dst_lo)); |
|---|
| 2021 | | - EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EDX), |
|---|
| 2022 | | - STACK_VAR(dst_hi)); |
|---|
| 2093 | + if (is_jmp64) |
|---|
| 2094 | + EMIT3(0x8B, |
|---|
| 2095 | + add_2reg(0x40, IA32_EBP, |
|---|
| 2096 | + IA32_EDX), |
|---|
| 2097 | + STACK_VAR(dst_hi)); |
|---|
| 2023 | 2098 | } else { |
|---|
| 2024 | 2099 | /* mov dreg_lo,dst_lo */ |
|---|
| 2025 | 2100 | EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo)); |
|---|
| 2026 | | - /* mov dreg_hi,dst_hi */ |
|---|
| 2027 | | - EMIT2(0x89, |
|---|
| 2028 | | - add_2reg(0xC0, dreg_hi, dst_hi)); |
|---|
| 2101 | + if (is_jmp64) |
|---|
| 2102 | + /* mov dreg_hi,dst_hi */ |
|---|
| 2103 | + EMIT2(0x89, |
|---|
| 2104 | + add_2reg(0xC0, dreg_hi, dst_hi)); |
|---|
| 2029 | 2105 | } |
|---|
| 2030 | | - hi = imm32 & (1<<31) ? (u32)~0 : 0; |
|---|
| 2031 | 2106 | |
|---|
| 2032 | 2107 | /* mov ecx,imm32 */ |
|---|
| 2033 | | - EMIT2_off32(0xC7, add_1reg(0xC0, IA32_ECX), imm32); |
|---|
| 2034 | | - /* mov ebx,imm32 */ |
|---|
| 2035 | | - EMIT2_off32(0xC7, add_1reg(0xC0, IA32_EBX), hi); |
|---|
| 2108 | + EMIT2_off32(0xC7, add_1reg(0xC0, sreg_lo), imm32); |
|---|
| 2036 | 2109 | |
|---|
| 2037 | 2110 | /* and dreg_lo,sreg_lo */ |
|---|
| 2038 | 2111 | EMIT2(0x23, add_2reg(0xC0, sreg_lo, dreg_lo)); |
|---|
| 2039 | | - /* and dreg_hi,sreg_hi */ |
|---|
| 2040 | | - EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi)); |
|---|
| 2041 | | - /* or dreg_lo,dreg_hi */ |
|---|
| 2042 | | - EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi)); |
|---|
| 2112 | + if (is_jmp64) { |
|---|
| 2113 | + hi = imm32 & (1 << 31) ? (u32)~0 : 0; |
|---|
| 2114 | + /* mov ebx,imm32 */ |
|---|
| 2115 | + EMIT2_off32(0xC7, add_1reg(0xC0, sreg_hi), hi); |
|---|
| 2116 | + /* and dreg_hi,sreg_hi */ |
|---|
| 2117 | + EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi)); |
|---|
| 2118 | + /* or dreg_lo,dreg_hi */ |
|---|
| 2119 | + EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi)); |
|---|
| 2120 | + } |
|---|
| 2043 | 2121 | goto emit_cond_jmp; |
|---|
| 2044 | 2122 | } |
|---|
| 2045 | 2123 | case BPF_JMP | BPF_JEQ | BPF_K: |
|---|
| .. | .. |
|---|
| 2047 | 2125 | case BPF_JMP | BPF_JGT | BPF_K: |
|---|
| 2048 | 2126 | case BPF_JMP | BPF_JLT | BPF_K: |
|---|
| 2049 | 2127 | case BPF_JMP | BPF_JGE | BPF_K: |
|---|
| 2050 | | - case BPF_JMP | BPF_JLE | BPF_K: { |
|---|
| 2051 | | - u32 hi; |
|---|
| 2128 | + case BPF_JMP | BPF_JLE | BPF_K: |
|---|
| 2129 | + case BPF_JMP32 | BPF_JEQ | BPF_K: |
|---|
| 2130 | + case BPF_JMP32 | BPF_JNE | BPF_K: |
|---|
| 2131 | + case BPF_JMP32 | BPF_JGT | BPF_K: |
|---|
| 2132 | + case BPF_JMP32 | BPF_JLT | BPF_K: |
|---|
| 2133 | + case BPF_JMP32 | BPF_JGE | BPF_K: |
|---|
| 2134 | + case BPF_JMP32 | BPF_JLE | BPF_K: |
|---|
| 2135 | + case BPF_JMP32 | BPF_JSGT | BPF_K: |
|---|
| 2136 | + case BPF_JMP32 | BPF_JSLE | BPF_K: |
|---|
| 2137 | + case BPF_JMP32 | BPF_JSLT | BPF_K: |
|---|
| 2138 | + case BPF_JMP32 | BPF_JSGE | BPF_K: { |
|---|
| 2139 | + bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP; |
|---|
| 2052 | 2140 | u8 dreg_lo = dstk ? IA32_EAX : dst_lo; |
|---|
| 2053 | 2141 | u8 dreg_hi = dstk ? IA32_EDX : dst_hi; |
|---|
| 2054 | 2142 | u8 sreg_lo = IA32_ECX; |
|---|
| 2055 | 2143 | u8 sreg_hi = IA32_EBX; |
|---|
| 2144 | + u32 hi; |
|---|
| 2056 | 2145 | |
|---|
| 2057 | 2146 | if (dstk) { |
|---|
| 2058 | 2147 | EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EAX), |
|---|
| 2059 | 2148 | STACK_VAR(dst_lo)); |
|---|
| 2060 | | - EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EDX), |
|---|
| 2061 | | - STACK_VAR(dst_hi)); |
|---|
| 2149 | + if (is_jmp64) |
|---|
| 2150 | + EMIT3(0x8B, |
|---|
| 2151 | + add_2reg(0x40, IA32_EBP, |
|---|
| 2152 | + IA32_EDX), |
|---|
| 2153 | + STACK_VAR(dst_hi)); |
|---|
| 2062 | 2154 | } |
|---|
| 2063 | 2155 | |
|---|
| 2064 | | - hi = imm32 & (1<<31) ? (u32)~0 : 0; |
|---|
| 2065 | 2156 | /* mov ecx,imm32 */ |
|---|
| 2066 | 2157 | EMIT2_off32(0xC7, add_1reg(0xC0, IA32_ECX), imm32); |
|---|
| 2067 | | - /* mov ebx,imm32 */ |
|---|
| 2068 | | - EMIT2_off32(0xC7, add_1reg(0xC0, IA32_EBX), hi); |
|---|
| 2069 | | - |
|---|
| 2070 | | - /* cmp dreg_hi,sreg_hi */ |
|---|
| 2071 | | - EMIT2(0x39, add_2reg(0xC0, dreg_hi, sreg_hi)); |
|---|
| 2072 | | - EMIT2(IA32_JNE, 2); |
|---|
| 2158 | + if (is_jmp64) { |
|---|
| 2159 | + hi = imm32 & (1 << 31) ? (u32)~0 : 0; |
|---|
| 2160 | + /* mov ebx,imm32 */ |
|---|
| 2161 | + EMIT2_off32(0xC7, add_1reg(0xC0, IA32_EBX), hi); |
|---|
| 2162 | + /* cmp dreg_hi,sreg_hi */ |
|---|
| 2163 | + EMIT2(0x39, add_2reg(0xC0, dreg_hi, sreg_hi)); |
|---|
| 2164 | + EMIT2(IA32_JNE, 2); |
|---|
| 2165 | + } |
|---|
| 2073 | 2166 | /* cmp dreg_lo,sreg_lo */ |
|---|
| 2074 | 2167 | EMIT2(0x39, add_2reg(0xC0, dreg_lo, sreg_lo)); |
|---|
| 2075 | 2168 | |
|---|
| .. | .. |
|---|
| 2229 | 2322 | return proglen; |
|---|
| 2230 | 2323 | } |
|---|
| 2231 | 2324 | |
|---|
| 2325 | +bool bpf_jit_needs_zext(void) |
|---|
| 2326 | +{ |
|---|
| 2327 | + return true; |
|---|
| 2328 | +} |
|---|
| 2329 | + |
|---|
| 2232 | 2330 | struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) |
|---|
| 2233 | 2331 | { |
|---|
| 2234 | 2332 | struct bpf_binary_header *header = NULL; |
|---|