@@ -869,8 +869,31 @@ static void detect_reg_usage(struct bpf_insn *insn, int insn_cnt,
869869 }
870870}
871871
872+ static int emit_nops (u8 * * pprog , int len )
873+ {
874+ u8 * prog = * pprog ;
875+ int i , noplen , cnt = 0 ;
876+
877+ while (len > 0 ) {
878+ noplen = len ;
879+
880+ if (noplen > ASM_NOP_MAX )
881+ noplen = ASM_NOP_MAX ;
882+
883+ for (i = 0 ; i < noplen ; i ++ )
884+ EMIT1 (ideal_nops [noplen ][i ]);
885+ len -= noplen ;
886+ }
887+
888+ * pprog = prog ;
889+
890+ return cnt ;
891+ }
892+
893+ #define INSN_SZ_DIFF (((addrs[i] - addrs[i - 1]) - (prog - temp)))
894+
872895static int do_jit (struct bpf_prog * bpf_prog , int * addrs , u8 * image ,
873- int oldproglen , struct jit_context * ctx )
896+ int oldproglen , struct jit_context * ctx , bool jmp_padding )
874897{
875898 bool tail_call_reachable = bpf_prog -> aux -> tail_call_reachable ;
876899 struct bpf_insn * insn = bpf_prog -> insnsi ;
@@ -880,7 +903,7 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
880903 bool seen_exit = false;
881904 u8 temp [BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY ];
882905 int i , cnt = 0 , excnt = 0 ;
883- int proglen = 0 ;
906+ int ilen , proglen = 0 ;
884907 u8 * prog = temp ;
885908 int err ;
886909
@@ -894,7 +917,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
894917 bpf_prog_was_classic (bpf_prog ), tail_call_reachable ,
895918 bpf_prog -> aux -> func_idx != 0 );
896919 push_callee_regs (& prog , callee_regs_used );
897- addrs [0 ] = prog - temp ;
920+
921+ ilen = prog - temp ;
922+ if (image )
923+ memcpy (image + proglen , temp , ilen );
924+ proglen += ilen ;
925+ addrs [0 ] = proglen ;
926+ prog = temp ;
898927
899928 for (i = 1 ; i <= insn_cnt ; i ++ , insn ++ ) {
900929 const s32 imm32 = insn -> imm ;
@@ -903,8 +932,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
903932 u8 b2 = 0 , b3 = 0 ;
904933 s64 jmp_offset ;
905934 u8 jmp_cond ;
906- int ilen ;
907935 u8 * func ;
936+ int nops ;
908937
909938 switch (insn -> code ) {
910939 /* ALU */
@@ -1502,6 +1531,30 @@ st: if (is_imm8(insn->off))
15021531 }
15031532 jmp_offset = addrs [i + insn -> off ] - addrs [i ];
15041533 if (is_imm8 (jmp_offset )) {
1534+ if (jmp_padding ) {
1535+ /* To keep the jmp_offset valid, the extra bytes are
1536+ * padded before the jump insn, so we substract the
1537+ * 2 bytes of jmp_cond insn from INSN_SZ_DIFF.
1538+ *
1539+ * If the previous pass already emits an imm8
1540+ * jmp_cond, then this BPF insn won't shrink, so
1541+ * "nops" is 0.
1542+ *
1543+ * On the other hand, if the previous pass emits an
1544+ * imm32 jmp_cond, the extra 4 bytes(*) is padded to
1545+ * keep the image from shrinking further.
1546+ *
1547+ * (*) imm32 jmp_cond is 6 bytes, and imm8 jmp_cond
1548+ * is 2 bytes, so the size difference is 4 bytes.
1549+ */
1550+ nops = INSN_SZ_DIFF - 2 ;
1551+ if (nops != 0 && nops != 4 ) {
1552+ pr_err ("unexpected jmp_cond padding: %d bytes\n" ,
1553+ nops );
1554+ return - EFAULT ;
1555+ }
1556+ cnt += emit_nops (& prog , nops );
1557+ }
15051558 EMIT2 (jmp_cond , jmp_offset );
15061559 } else if (is_simm32 (jmp_offset )) {
15071560 EMIT2_off32 (0x0F , jmp_cond + 0x10 , jmp_offset );
@@ -1524,11 +1577,55 @@ st: if (is_imm8(insn->off))
15241577 else
15251578 jmp_offset = addrs [i + insn -> off ] - addrs [i ];
15261579
1527- if (!jmp_offset )
1528- /* Optimize out nop jumps */
1580+ if (!jmp_offset ) {
1581+ /*
1582+ * If jmp_padding is enabled, the extra nops will
1583+ * be inserted. Otherwise, optimize out nop jumps.
1584+ */
1585+ if (jmp_padding ) {
1586+ /* There are 3 possible conditions.
1587+ * (1) This BPF_JA is already optimized out in
1588+ * the previous run, so there is no need
1589+ * to pad any extra byte (0 byte).
1590+ * (2) The previous pass emits an imm8 jmp,
1591+ * so we pad 2 bytes to match the previous
1592+ * insn size.
1593+ * (3) Similarly, the previous pass emits an
1594+ * imm32 jmp, and 5 bytes is padded.
1595+ */
1596+ nops = INSN_SZ_DIFF ;
1597+ if (nops != 0 && nops != 2 && nops != 5 ) {
1598+ pr_err ("unexpected nop jump padding: %d bytes\n" ,
1599+ nops );
1600+ return - EFAULT ;
1601+ }
1602+ cnt += emit_nops (& prog , nops );
1603+ }
15291604 break ;
1605+ }
15301606emit_jmp :
15311607 if (is_imm8 (jmp_offset )) {
1608+ if (jmp_padding ) {
1609+ /* To avoid breaking jmp_offset, the extra bytes
1610+ * are padded before the actual jmp insn, so
1611+ * 2 bytes is substracted from INSN_SZ_DIFF.
1612+ *
1613+ * If the previous pass already emits an imm8
1614+ * jmp, there is nothing to pad (0 byte).
1615+ *
1616+ * If it emits an imm32 jmp (5 bytes) previously
1617+ * and now an imm8 jmp (2 bytes), then we pad
1618+ * (5 - 2 = 3) bytes to stop the image from
1619+ * shrinking further.
1620+ */
1621+ nops = INSN_SZ_DIFF - 2 ;
1622+ if (nops != 0 && nops != 3 ) {
1623+ pr_err ("unexpected jump padding: %d bytes\n" ,
1624+ nops );
1625+ return - EFAULT ;
1626+ }
1627+ cnt += emit_nops (& prog , INSN_SZ_DIFF - 2 );
1628+ }
15321629 EMIT2 (0xEB , jmp_offset );
15331630 } else if (is_simm32 (jmp_offset )) {
15341631 EMIT1_off32 (0xE9 , jmp_offset );
@@ -1671,26 +1768,6 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
16711768 return 0 ;
16721769}
16731770
1674- static void emit_nops (u8 * * pprog , unsigned int len )
1675- {
1676- unsigned int i , noplen ;
1677- u8 * prog = * pprog ;
1678- int cnt = 0 ;
1679-
1680- while (len > 0 ) {
1681- noplen = len ;
1682-
1683- if (noplen > ASM_NOP_MAX )
1684- noplen = ASM_NOP_MAX ;
1685-
1686- for (i = 0 ; i < noplen ; i ++ )
1687- EMIT1 (ideal_nops [noplen ][i ]);
1688- len -= noplen ;
1689- }
1690-
1691- * pprog = prog ;
1692- }
1693-
16941771static void emit_align (u8 * * pprog , u32 align )
16951772{
16961773 u8 * target , * prog = * pprog ;
@@ -2065,6 +2142,9 @@ struct x64_jit_data {
20652142 struct jit_context ctx ;
20662143};
20672144
2145+ #define MAX_PASSES 20
2146+ #define PADDING_PASSES (MAX_PASSES - 5)
2147+
20682148struct bpf_prog * bpf_int_jit_compile (struct bpf_prog * prog )
20692149{
20702150 struct bpf_binary_header * header = NULL ;
@@ -2074,6 +2154,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
20742154 struct jit_context ctx = {};
20752155 bool tmp_blinded = false;
20762156 bool extra_pass = false;
2157+ bool padding = false;
20772158 u8 * image = NULL ;
20782159 int * addrs ;
20792160 int pass ;
@@ -2110,6 +2191,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
21102191 image = jit_data -> image ;
21112192 header = jit_data -> header ;
21122193 extra_pass = true;
2194+ padding = true;
21132195 goto skip_init_addrs ;
21142196 }
21152197 addrs = kmalloc_array (prog -> len + 1 , sizeof (* addrs ), GFP_KERNEL );
@@ -2135,8 +2217,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
21352217 * may converge on the last pass. In such case do one more
21362218 * pass to emit the final image.
21372219 */
2138- for (pass = 0 ; pass < 20 || image ; pass ++ ) {
2139- proglen = do_jit (prog , addrs , image , oldproglen , & ctx );
2220+ for (pass = 0 ; pass < MAX_PASSES || image ; pass ++ ) {
2221+ if (!padding && pass >= PADDING_PASSES )
2222+ padding = true;
2223+ proglen = do_jit (prog , addrs , image , oldproglen , & ctx , padding );
21402224 if (proglen <= 0 ) {
21412225out_image :
21422226 image = NULL ;
0 commit comments