@@ -48,8 +48,6 @@ struct bpf_jit {
48
48
int lit64 ; /* Current position in 64-bit literal pool */
49
49
int base_ip ; /* Base address for literal pool */
50
50
int exit_ip ; /* Address of exit */
51
- int r1_thunk_ip ; /* Address of expoline thunk for 'br %r1' */
52
- int r14_thunk_ip ; /* Address of expoline thunk for 'br %r14' */
53
51
int tail_call_start ; /* Tail call start offset */
54
52
int excnt ; /* Number of exception table entries */
55
53
int prologue_plt_ret ; /* Return address for prologue hotpatch PLT */
@@ -127,6 +125,18 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
127
125
jit -> seen_regs |= (1 << r1 );
128
126
}
129
127
128
+ static s32 off_to_pcrel (struct bpf_jit * jit , u32 off )
129
+ {
130
+ return off - jit -> prg ;
131
+ }
132
+
133
+ static s64 ptr_to_pcrel (struct bpf_jit * jit , const void * ptr )
134
+ {
135
+ if (jit -> prg_buf )
136
+ return (const u8 * )ptr - ((const u8 * )jit -> prg_buf + jit -> prg );
137
+ return 0 ;
138
+ }
139
+
130
140
#define REG_SET_SEEN (b1 ) \
131
141
({ \
132
142
reg_set_seen(jit, b1); \
@@ -201,7 +211,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
201
211
202
212
#define EMIT4_PCREL_RIC (op , mask , target ) \
203
213
({ \
204
- int __rel = (( target) - jit->prg) / 2; \
214
+ int __rel = off_to_pcrel(jit, target) / 2; \
205
215
_EMIT4((op) | (mask) << 20 | (__rel & 0xffff)); \
206
216
})
207
217
@@ -239,7 +249,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
239
249
240
250
#define EMIT6_PCREL_RIEB (op1 , op2 , b1 , b2 , mask , target ) \
241
251
({ \
242
- unsigned int rel = (int)((target) - jit->prg ) / 2; \
252
+ unsigned int rel = off_to_pcrel( jit, target ) / 2; \
243
253
_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), \
244
254
(op2) | (mask) << 12); \
245
255
REG_SET_SEEN(b1); \
@@ -248,7 +258,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
248
258
249
259
#define EMIT6_PCREL_RIEC (op1 , op2 , b1 , imm , mask , target ) \
250
260
({ \
251
- unsigned int rel = (int)((target) - jit->prg ) / 2; \
261
+ unsigned int rel = off_to_pcrel( jit, target ) / 2; \
252
262
_EMIT6((op1) | (reg_high(b1) | (mask)) << 16 | \
253
263
(rel & 0xffff), (op2) | ((imm) & 0xff) << 8); \
254
264
REG_SET_SEEN(b1); \
@@ -257,29 +267,41 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
257
267
258
268
#define EMIT6_PCREL (op1 , op2 , b1 , b2 , i , off , mask ) \
259
269
({ \
260
- int rel = ( addrs[(i) + (off) + 1] - jit->prg ) / 2; \
270
+ int rel = off_to_pcrel(jit, addrs[(i) + (off) + 1]) / 2;\
261
271
_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\
262
272
REG_SET_SEEN(b1); \
263
273
REG_SET_SEEN(b2); \
264
274
})
265
275
276
+ static void emit6_pcrel_ril (struct bpf_jit * jit , u32 op , s64 pcrel )
277
+ {
278
+ u32 pc32dbl = (s32 )(pcrel / 2 );
279
+
280
+ _EMIT6 (op | pc32dbl >> 16 , pc32dbl & 0xffff );
281
+ }
282
+
283
+ static void emit6_pcrel_rilb (struct bpf_jit * jit , u32 op , u8 b , s64 pcrel )
284
+ {
285
+ emit6_pcrel_ril (jit , op | reg_high (b ) << 16 , pcrel );
286
+ REG_SET_SEEN (b );
287
+ }
288
+
266
289
#define EMIT6_PCREL_RILB (op , b , target ) \
267
- ({ \
268
- unsigned int rel = (int)((target) - jit->prg) / 2; \
269
- _EMIT6((op) | reg_high(b) << 16 | rel >> 16, rel & 0xffff);\
270
- REG_SET_SEEN(b); \
271
- })
290
+ emit6_pcrel_rilb(jit, op, b, off_to_pcrel(jit, target))
272
291
273
- #define EMIT6_PCREL_RIL (op , target ) \
274
- ({ \
275
- unsigned int rel = (int)((target) - jit->prg) / 2; \
276
- _EMIT6((op) | rel >> 16, rel & 0xffff); \
277
- })
292
+ #define EMIT6_PCREL_RILB_PTR (op , b , target_ptr ) \
293
+ emit6_pcrel_rilb(jit, op, b, ptr_to_pcrel(jit, target_ptr))
294
+
295
+ static void emit6_pcrel_rilc (struct bpf_jit * jit , u32 op , u8 mask , s64 pcrel )
296
+ {
297
+ emit6_pcrel_ril (jit , op | mask << 20 , pcrel );
298
+ }
278
299
279
300
#define EMIT6_PCREL_RILC (op , mask , target ) \
280
- ({ \
281
- EMIT6_PCREL_RIL((op) | (mask) << 20, (target)); \
282
- })
301
+ emit6_pcrel_rilc(jit, op, mask, off_to_pcrel(jit, target))
302
+
303
+ #define EMIT6_PCREL_RILC_PTR (op , mask , target_ptr ) \
304
+ emit6_pcrel_rilc(jit, op, mask, ptr_to_pcrel(jit, target_ptr))
283
305
284
306
#define _EMIT6_IMM (op , imm ) \
285
307
({ \
@@ -503,7 +525,7 @@ static void bpf_skip(struct bpf_jit *jit, int size)
503
525
{
504
526
if (size >= 6 && !is_valid_rel (size )) {
505
527
/* brcl 0xf,size */
506
- EMIT6_PCREL_RIL ( 0xc0f4000000 , size );
528
+ EMIT6_PCREL_RILC ( 0xc0040000 , 0xf , size );
507
529
size -= 6 ;
508
530
} else if (size >= 4 && is_valid_rel (size )) {
509
531
/* brc 0xf,size */
@@ -618,28 +640,17 @@ static void bpf_jit_prologue(struct bpf_jit *jit, struct bpf_prog *fp,
618
640
}
619
641
620
642
/*
621
- * Emit an expoline for a jump that follows
643
+ * Jump using a register either directly or via an expoline thunk
622
644
*/
623
- static void emit_expoline (struct bpf_jit * jit )
624
- {
625
- /* exrl %r0,.+10 */
626
- EMIT6_PCREL_RIL (0xc6000000 , jit -> prg + 10 );
627
- /* j . */
628
- EMIT4_PCREL (0xa7f40000 , 0 );
629
- }
630
-
631
- /*
632
- * Emit __s390_indirect_jump_r1 thunk if necessary
633
- */
634
- static void emit_r1_thunk (struct bpf_jit * jit )
635
- {
636
- if (nospec_uses_trampoline ()) {
637
- jit -> r1_thunk_ip = jit -> prg ;
638
- emit_expoline (jit );
639
- /* br %r1 */
640
- _EMIT2 (0x07f1 );
641
- }
642
- }
645
+ #define EMIT_JUMP_REG (reg ) do { \
646
+ if (nospec_uses_trampoline()) \
647
+ /* brcl 0xf,__s390_indirect_jump_rN */ \
648
+ EMIT6_PCREL_RILC_PTR (0xc0040000 , 0x0f , \
649
+ __s390_indirect_jump_r ## reg ); \
650
+ else \
651
+ /* br %rN */ \
652
+ _EMIT2 (0x07f0 | reg ); \
653
+ } while (0 )
643
654
644
655
/*
645
656
* Call r1 either directly or via __s390_indirect_jump_r1 thunk
@@ -648,7 +659,8 @@ static void call_r1(struct bpf_jit *jit)
648
659
{
649
660
if (nospec_uses_trampoline ())
650
661
/* brasl %r14,__s390_indirect_jump_r1 */
651
- EMIT6_PCREL_RILB (0xc0050000 , REG_14 , jit -> r1_thunk_ip );
662
+ EMIT6_PCREL_RILB_PTR (0xc0050000 , REG_14 ,
663
+ __s390_indirect_jump_r1 );
652
664
else
653
665
/* basr %r14,%r1 */
654
666
EMIT2 (0x0d00 , REG_14 , REG_1 );
@@ -664,16 +676,7 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
664
676
EMIT4 (0xb9040000 , REG_2 , BPF_REG_0 );
665
677
/* Restore registers */
666
678
save_restore_regs (jit , REGS_RESTORE , stack_depth , 0 );
667
- if (nospec_uses_trampoline ()) {
668
- jit -> r14_thunk_ip = jit -> prg ;
669
- /* Generate __s390_indirect_jump_r14 thunk */
670
- emit_expoline (jit );
671
- }
672
- /* br %r14 */
673
- _EMIT2 (0x07fe );
674
-
675
- if (is_first_pass (jit ) || (jit -> seen & SEEN_FUNC ))
676
- emit_r1_thunk (jit );
679
+ EMIT_JUMP_REG (14 );
677
680
678
681
jit -> prg = ALIGN (jit -> prg , 8 );
679
682
jit -> prologue_plt = jit -> prg ;
@@ -1875,7 +1878,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
1875
1878
/* aghi %r1,tail_call_start */
1876
1879
EMIT4_IMM (0xa70b0000 , REG_1 , jit -> tail_call_start );
1877
1880
/* brcl 0xf,__s390_indirect_jump_r1 */
1878
- EMIT6_PCREL_RILC (0xc0040000 , 0xf , jit -> r1_thunk_ip );
1881
+ EMIT6_PCREL_RILC_PTR (0xc0040000 , 0xf ,
1882
+ __s390_indirect_jump_r1 );
1879
1883
} else {
1880
1884
/* bc 0xf,tail_call_start(%r1) */
1881
1885
_EMIT4 (0x47f01000 + jit -> tail_call_start );
@@ -2844,17 +2848,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
2844
2848
0xf000 | tjit -> tccnt_off );
2845
2849
/* aghi %r15,stack_size */
2846
2850
EMIT4_IMM (0xa70b0000 , REG_15 , tjit -> stack_size );
2847
- /* Emit an expoline for the following indirect jump. */
2848
- if (nospec_uses_trampoline ())
2849
- emit_expoline (jit );
2850
2851
if (flags & BPF_TRAMP_F_SKIP_FRAME )
2851
- /* br %r14 */
2852
- _EMIT2 (0x07fe );
2852
+ EMIT_JUMP_REG (14 );
2853
2853
else
2854
- /* br %r1 */
2855
- _EMIT2 (0x07f1 );
2856
-
2857
- emit_r1_thunk (jit );
2854
+ EMIT_JUMP_REG (1 );
2858
2855
2859
2856
return 0 ;
2860
2857
}
0 commit comments