@@ -50,7 +50,6 @@ struct bpf_jit {
50
50
int r14_thunk_ip ; /* Address of expoline thunk for 'br %r14' */
51
51
int tail_call_start ; /* Tail call start offset */
52
52
int excnt ; /* Number of exception table entries */
53
- int labels [1 ]; /* Labels for local jumps */
54
53
};
55
54
56
55
#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)
229
228
REG_SET_SEEN(b3); \
230
229
})
231
230
232
- #define EMIT6_PCREL_LABEL (op1 , op2 , b1 , b2 , label , mask ) \
231
+ #define EMIT6_PCREL_RIEB (op1 , op2 , b1 , b2 , mask , target ) \
233
232
({ \
234
- int rel = (jit->labels[label] - jit->prg) >> 1; \
233
+ unsigned int rel = (int)((target) - jit->prg) / 2; \
235
234
_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), \
236
235
(op2) | (mask) << 12); \
237
236
REG_SET_SEEN(b1); \
238
237
REG_SET_SEEN(b2); \
239
238
})
240
239
241
- #define EMIT6_PCREL_IMM_LABEL (op1 , op2 , b1 , imm , label , mask ) \
240
+ #define EMIT6_PCREL_RIEC (op1 , op2 , b1 , imm , mask , target ) \
242
241
({ \
243
- int rel = (jit->labels[label] - jit->prg) >> 1; \
242
+ unsigned int rel = (int)((target) - jit->prg) / 2; \
244
243
_EMIT6((op1) | (reg_high(b1) | (mask)) << 16 | \
245
244
(rel & 0xffff), (op2) | ((imm) & 0xff) << 8); \
246
245
REG_SET_SEEN(b1); \
@@ -1282,7 +1281,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
1282
1281
EMIT4 (0xb9040000 , BPF_REG_0 , REG_2 );
1283
1282
break ;
1284
1283
}
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
+
1286
1287
/*
1287
1288
* Implicit input:
1288
1289
* B1: pointer to ctx
@@ -1300,16 +1301,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
1300
1301
EMIT6_DISP_LH (0xe3000000 , 0x0016 , REG_W1 , REG_0 , BPF_REG_2 ,
1301
1302
offsetof(struct bpf_array , map .max_entries ));
1302
1303
/* 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 );
1313
1308
1314
1309
/*
1315
1310
* 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,
1324
1319
EMIT4_IMM (0xa7080000 , REG_W0 , 1 );
1325
1320
/* laal %w1,%w0,off(%r15) */
1326
1321
EMIT6_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 );
1337
1326
1338
1327
/*
1339
1328
* prog = array->ptrs[index];
@@ -1348,13 +1337,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
1348
1337
/* ltg %r1,prog(%b2,%r1) */
1349
1338
EMIT6_DISP_LH (0xe3000000 , 0x0002 , REG_1 , BPF_REG_2 ,
1350
1339
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 );
1358
1343
1359
1344
/*
1360
1345
* Restore registers before calling function
@@ -1371,8 +1356,16 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
1371
1356
/* bc 0xf,tail_call_start(%r1) */
1372
1357
_EMIT4 (0x47f01000 + jit -> tail_call_start );
1373
1358
/* 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
+ }
1375
1367
break ;
1368
+ }
1376
1369
case BPF_JMP | BPF_EXIT : /* return b0 */
1377
1370
last = (i == fp -> len - 1 ) ? 1 : 0 ;
1378
1371
if (last )
0 commit comments