@@ -50,7 +50,6 @@ struct bpf_jit {
5050int r14_thunk_ip ;/* Address of expoline thunk for 'br %r14' */
5151int tail_call_start ;/* Tail call start offset */
5252int excnt ;/* Number of exception table entries */
53- int labels [1 ];/* Labels for local jumps */
5453};
5554
5655#define SEEN_MEM BIT(0)/* use mem[] for temporary storage */
@@ -229,18 +228,18 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
229228REG_SET_SEEN(b3); \
230229})
231230
232- #define EMIT6_PCREL_LABEL (op1 , op2 , b1 , b2 , label , mask ) \
231+ #define EMIT6_PCREL_RIEB (op1 , op2 , b1 , b2 , mask , target ) \
233232({ \
234- int rel = (jit->labels[label] - jit->prg) >> 1; \
233+ unsigned int rel = (int)((target) - jit->prg) / 2; \
235234_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), \
236235 (op2) | (mask) << 12); \
237236REG_SET_SEEN(b1); \
238237REG_SET_SEEN(b2); \
239238})
240239
241- #define EMIT6_PCREL_IMM_LABEL (op1 , op2 , b1 , imm , label , mask ) \
240+ #define EMIT6_PCREL_RIEC (op1 , op2 , b1 , imm , mask , target ) \
242241({ \
243- int rel = (jit->labels[label] - jit->prg) >> 1; \
242+ unsigned int rel = (int)((target) - jit->prg) / 2; \
244243_EMIT6((op1) | (reg_high(b1) | (mask)) << 16 | \
245244(rel & 0xffff), (op2) | ((imm) & 0xff) << 8); \
246245REG_SET_SEEN(b1); \
@@ -1282,7 +1281,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
12821281EMIT4 (0xb9040000 , BPF_REG_0 , REG_2 );
12831282break ;
12841283}
1285- case BPF_JMP | BPF_TAIL_CALL :
1284+ case BPF_JMP | BPF_TAIL_CALL : {
1285+ int patch_1_clrj , patch_2_clij , patch_3_brc ;
1286+
12861287/*
12871288 * Implicit input:
12881289 * B1: pointer to ctx
@@ -1300,16 +1301,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
13001301EMIT6_DISP_LH (0xe3000000 , 0x0016 , REG_W1 , REG_0 , BPF_REG_2 ,
13011302 offsetof(struct bpf_array , map .max_entries ));
13021303/* if ((u32)%b3 >= (u32)%w1) goto out; */
1303- if (!is_first_pass (jit ) && can_use_rel (jit , jit -> labels [0 ])) {
1304- /* clrj %b3,%w1,0xa,label0 */
1305- EMIT6_PCREL_LABEL (0xec000000 , 0x0077 , BPF_REG_3 ,
1306- REG_W1 , 0 , 0xa );
1307- } else {
1308- /* clr %b3,%w1 */
1309- EMIT2 (0x1500 , BPF_REG_3 , REG_W1 );
1310- /* brcl 0xa,label0 */
1311- EMIT6_PCREL_RILC (0xc0040000 , 0xa , jit -> labels [0 ]);
1312- }
1304+ /* clrj %b3,%w1,0xa,out */
1305+ patch_1_clrj = jit -> prg ;
1306+ EMIT6_PCREL_RIEB (0xec000000 , 0x0077 , BPF_REG_3 , REG_W1 , 0xa ,
1307+ jit -> prg );
13131308
13141309/*
13151310 * if (tail_call_cnt++ > MAX_TAIL_CALL_CNT)
@@ -1324,16 +1319,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
13241319EMIT4_IMM (0xa7080000 , REG_W0 , 1 );
13251320/* laal %w1,%w0,off(%r15) */
13261321EMIT6_DISP_LH (0xeb000000 , 0x00fa , REG_W1 , REG_W0 , REG_15 , off );
1327- if (!is_first_pass (jit ) && can_use_rel (jit , jit -> labels [0 ])) {
1328- /* clij %w1,MAX_TAIL_CALL_CNT,0x2,label0 */
1329- EMIT6_PCREL_IMM_LABEL (0xec000000 , 0x007f , REG_W1 ,
1330- MAX_TAIL_CALL_CNT , 0 , 0x2 );
1331- } else {
1332- /* clfi %w1,MAX_TAIL_CALL_CNT */
1333- EMIT6_IMM (0xc20f0000 , REG_W1 , MAX_TAIL_CALL_CNT );
1334- /* brcl 0x2,label0 */
1335- EMIT6_PCREL_RILC (0xc0040000 , 0x2 , jit -> labels [0 ]);
1336- }
1322+ /* clij %w1,MAX_TAIL_CALL_CNT,0x2,out */
1323+ patch_2_clij = jit -> prg ;
1324+ EMIT6_PCREL_RIEC (0xec000000 , 0x007f , REG_W1 , MAX_TAIL_CALL_CNT ,
1325+ 2 , jit -> prg );
13371326
13381327/*
13391328 * prog = array->ptrs[index];
@@ -1348,13 +1337,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
13481337/* ltg %r1,prog(%b2,%r1) */
13491338EMIT6_DISP_LH (0xe3000000 , 0x0002 , REG_1 , BPF_REG_2 ,
13501339 REG_1 , offsetof(struct bpf_array , ptrs ));
1351- if (!is_first_pass (jit ) && can_use_rel (jit , jit -> labels [0 ])) {
1352- /* brc 0x8,label0 */
1353- EMIT4_PCREL_RIC (0xa7040000 , 0x8 , jit -> labels [0 ]);
1354- } else {
1355- /* brcl 0x8,label0 */
1356- EMIT6_PCREL_RILC (0xc0040000 , 0x8 , jit -> labels [0 ]);
1357- }
1340+ /* brc 0x8,out */
1341+ patch_3_brc = jit -> prg ;
1342+ EMIT4_PCREL_RIC (0xa7040000 , 8 , jit -> prg );
13581343
13591344/*
13601345 * Restore registers before calling function
@@ -1371,8 +1356,16 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
13711356/* bc 0xf,tail_call_start(%r1) */
13721357_EMIT4 (0x47f01000 + jit -> tail_call_start );
13731358/* out: */
1374- jit -> labels [0 ] = jit -> prg ;
1359+ if (jit -> prg_buf ) {
1360+ * (u16 * )(jit -> prg_buf + patch_1_clrj + 2 ) =
1361+ (jit -> prg - patch_1_clrj ) >> 1 ;
1362+ * (u16 * )(jit -> prg_buf + patch_2_clij + 2 ) =
1363+ (jit -> prg - patch_2_clij ) >> 1 ;
1364+ * (u16 * )(jit -> prg_buf + patch_3_brc + 2 ) =
1365+ (jit -> prg - patch_3_brc ) >> 1 ;
1366+ }
13751367break ;
1368+ }
13761369case BPF_JMP | BPF_EXIT : /* return b0 */
13771370last = (i == fp -> len - 1 ) ? 1 : 0 ;
13781371if (last )
0 commit comments