.. | .. |
---|
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; |
---|