25
25
#include <linux/bpf.h>
26
26
#include <asm/cacheflush.h>
27
27
#include <asm/dis.h>
28
+ #include <asm/facility.h>
29
+ #include <asm/nospec-branch.h>
28
30
#include <asm/set_memory.h>
29
31
#include "bpf_jit.h"
30
32
@@ -41,6 +43,8 @@ struct bpf_jit {
41
43
int base_ip ; /* Base address for literal pool */
42
44
int ret0_ip ; /* Address of return 0 */
43
45
int exit_ip ; /* Address of exit */
46
+ int r1_thunk_ip ; /* Address of expoline thunk for 'br %r1' */
47
+ int r14_thunk_ip ; /* Address of expoline thunk for 'br %r14' */
44
48
int tail_call_start ; /* Tail call start offset */
45
49
int labels [1 ]; /* Labels for local jumps */
46
50
};
@@ -250,6 +254,19 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
250
254
REG_SET_SEEN(b2); \
251
255
})
252
256
257
+ #define EMIT6_PCREL_RILB (op , b , target ) \
258
+ ({ \
259
+ int rel = (target - jit->prg) / 2; \
260
+ _EMIT6(op | reg_high(b) << 16 | rel >> 16, rel & 0xffff); \
261
+ REG_SET_SEEN(b); \
262
+ })
263
+
264
+ #define EMIT6_PCREL_RIL (op , target ) \
265
+ ({ \
266
+ int rel = (target - jit->prg) / 2; \
267
+ _EMIT6(op | rel >> 16, rel & 0xffff); \
268
+ })
269
+
253
270
#define _EMIT6_IMM (op , imm ) \
254
271
({ \
255
272
unsigned int __imm = (imm); \
@@ -469,8 +486,45 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
469
486
EMIT4 (0xb9040000 , REG_2 , BPF_REG_0 );
470
487
/* Restore registers */
471
488
save_restore_regs (jit , REGS_RESTORE , stack_depth );
489
+ if (IS_ENABLED (CC_USING_EXPOLINE ) && !nospec_disable ) {
490
+ jit -> r14_thunk_ip = jit -> prg ;
491
+ /* Generate __s390_indirect_jump_r14 thunk */
492
+ if (test_facility (35 )) {
493
+ /* exrl %r0,.+10 */
494
+ EMIT6_PCREL_RIL (0xc6000000 , jit -> prg + 10 );
495
+ } else {
496
+ /* larl %r1,.+14 */
497
+ EMIT6_PCREL_RILB (0xc0000000 , REG_1 , jit -> prg + 14 );
498
+ /* ex 0,0(%r1) */
499
+ EMIT4_DISP (0x44000000 , REG_0 , REG_1 , 0 );
500
+ }
501
+ /* j . */
502
+ EMIT4_PCREL (0xa7f40000 , 0 );
503
+ }
472
504
/* br %r14 */
473
505
_EMIT2 (0x07fe );
506
+
507
+ if (IS_ENABLED (CC_USING_EXPOLINE ) && !nospec_disable &&
508
+ (jit -> seen & SEEN_FUNC )) {
509
+ jit -> r1_thunk_ip = jit -> prg ;
510
+ /* Generate __s390_indirect_jump_r1 thunk */
511
+ if (test_facility (35 )) {
512
+ /* exrl %r0,.+10 */
513
+ EMIT6_PCREL_RIL (0xc6000000 , jit -> prg + 10 );
514
+ /* j . */
515
+ EMIT4_PCREL (0xa7f40000 , 0 );
516
+ /* br %r1 */
517
+ _EMIT2 (0x07f1 );
518
+ } else {
519
+ /* larl %r1,.+14 */
520
+ EMIT6_PCREL_RILB (0xc0000000 , REG_1 , jit -> prg + 14 );
521
+ /* ex 0,S390_lowcore.br_r1_tampoline */
522
+ EMIT4_DISP (0x44000000 , REG_0 , REG_0 ,
523
+ offsetof(struct lowcore , br_r1_trampoline ));
524
+ /* j . */
525
+ EMIT4_PCREL (0xa7f40000 , 0 );
526
+ }
527
+ }
474
528
}
475
529
476
530
/*
@@ -966,8 +1020,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
966
1020
/* lg %w1,<d(imm)>(%l) */
967
1021
EMIT6_DISP_LH (0xe3000000 , 0x0004 , REG_W1 , REG_0 , REG_L ,
968
1022
EMIT_CONST_U64 (func ));
969
- /* basr %r14,%w1 */
970
- EMIT2 (0x0d00 , REG_14 , REG_W1 );
1023
+ if (IS_ENABLED (CC_USING_EXPOLINE ) && !nospec_disable ) {
1024
+ /* brasl %r14,__s390_indirect_jump_r1 */
1025
+ EMIT6_PCREL_RILB (0xc0050000 , REG_14 , jit -> r1_thunk_ip );
1026
+ } else {
1027
+ /* basr %r14,%w1 */
1028
+ EMIT2 (0x0d00 , REG_14 , REG_W1 );
1029
+ }
971
1030
/* lgr %b0,%r2: load return value into %b0 */
972
1031
EMIT4 (0xb9040000 , BPF_REG_0 , REG_2 );
973
1032
if ((jit -> seen & SEEN_SKB ) &&
0 commit comments