@@ -48,8 +48,6 @@ struct bpf_jit {
4848 int lit64 ; /* Current position in 64-bit literal pool */
4949 int base_ip ; /* Base address for literal pool */
5050 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' */
5351 int tail_call_start ; /* Tail call start offset */
5452 int excnt ; /* Number of exception table entries */
5553 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)
127125 jit -> seen_regs |= (1 << r1 );
128126}
129127
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+
130140#define REG_SET_SEEN (b1 ) \
131141({ \
132142 reg_set_seen(jit, b1); \
@@ -201,7 +211,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
201211
202212#define EMIT4_PCREL_RIC (op , mask , target ) \
203213({ \
204- int __rel = (( target) - jit->prg) / 2; \
214+ int __rel = off_to_pcrel(jit, target) / 2; \
205215 _EMIT4((op) | (mask) << 20 | (__rel & 0xffff)); \
206216})
207217
@@ -239,7 +249,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
239249
240250#define EMIT6_PCREL_RIEB (op1 , op2 , b1 , b2 , mask , target ) \
241251({ \
242- unsigned int rel = (int)((target) - jit->prg ) / 2; \
252+ unsigned int rel = off_to_pcrel( jit, target ) / 2; \
243253 _EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), \
244254 (op2) | (mask) << 12); \
245255 REG_SET_SEEN(b1); \
@@ -248,7 +258,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
248258
249259#define EMIT6_PCREL_RIEC (op1 , op2 , b1 , imm , mask , target ) \
250260({ \
251- unsigned int rel = (int)((target) - jit->prg ) / 2; \
261+ unsigned int rel = off_to_pcrel( jit, target ) / 2; \
252262 _EMIT6((op1) | (reg_high(b1) | (mask)) << 16 | \
253263 (rel & 0xffff), (op2) | ((imm) & 0xff) << 8); \
254264 REG_SET_SEEN(b1); \
@@ -257,29 +267,41 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
257267
258268#define EMIT6_PCREL (op1 , op2 , b1 , b2 , i , off , mask ) \
259269({ \
260- int rel = ( addrs[(i) + (off) + 1] - jit->prg ) / 2; \
270+ int rel = off_to_pcrel(jit, addrs[(i) + (off) + 1]) / 2;\
261271 _EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\
262272 REG_SET_SEEN(b1); \
263273 REG_SET_SEEN(b2); \
264274})
265275
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+
266289#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))
272291
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+ }
278299
279300#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))
283305
284306#define _EMIT6_IMM (op , imm ) \
285307({ \
@@ -503,7 +525,7 @@ static void bpf_skip(struct bpf_jit *jit, int size)
503525{
504526 if (size >= 6 && !is_valid_rel (size )) {
505527 /* brcl 0xf,size */
506- EMIT6_PCREL_RIL ( 0xc0f4000000 , size );
528+ EMIT6_PCREL_RILC ( 0xc0040000 , 0xf , size );
507529 size -= 6 ;
508530 } else if (size >= 4 && is_valid_rel (size )) {
509531 /* brc 0xf,size */
@@ -618,28 +640,17 @@ static void bpf_jit_prologue(struct bpf_jit *jit, struct bpf_prog *fp,
618640}
619641
620642/*
621- * Emit an expoline for a jump that follows
643+ * Jump using a register either directly or via an expoline thunk
622644 */
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 )
643654
644655/*
645656 * Call r1 either directly or via __s390_indirect_jump_r1 thunk
@@ -648,7 +659,8 @@ static void call_r1(struct bpf_jit *jit)
648659{
649660 if (nospec_uses_trampoline ())
650661 /* 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 );
652664 else
653665 /* basr %r14,%r1 */
654666 EMIT2 (0x0d00 , REG_14 , REG_1 );
@@ -664,16 +676,7 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
664676 EMIT4 (0xb9040000 , REG_2 , BPF_REG_0 );
665677 /* Restore registers */
666678 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 );
677680
678681 jit -> prg = ALIGN (jit -> prg , 8 );
679682 jit -> prologue_plt = jit -> prg ;
@@ -1875,7 +1878,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
18751878 /* aghi %r1,tail_call_start */
18761879 EMIT4_IMM (0xa70b0000 , REG_1 , jit -> tail_call_start );
18771880 /* 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 );
18791883 } else {
18801884 /* bc 0xf,tail_call_start(%r1) */
18811885 _EMIT4 (0x47f01000 + jit -> tail_call_start );
@@ -2844,17 +2848,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
28442848 0xf000 | tjit -> tccnt_off );
28452849 /* aghi %r15,stack_size */
28462850 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 );
28502851 if (flags & BPF_TRAMP_F_SKIP_FRAME )
2851- /* br %r14 */
2852- _EMIT2 (0x07fe );
2852+ EMIT_JUMP_REG (14 );
28532853 else
2854- /* br %r1 */
2855- _EMIT2 (0x07f1 );
2856-
2857- emit_r1_thunk (jit );
2854+ EMIT_JUMP_REG (1 );
28582855
28592856 return 0 ;
28602857}
0 commit comments