@@ -371,6 +371,24 @@ static bool is_valid_ldisp(int disp)
371
371
return disp >= -524288 && disp <= 524287 ;
372
372
}
373
373
374
+ /*
375
+ * Return whether the next 32-bit literal pool entry can be referenced using
376
+ * Long-Displacement Facility
377
+ */
378
+ static bool can_use_ldisp_for_lit32 (struct bpf_jit * jit )
379
+ {
380
+ return is_valid_ldisp (jit -> lit32 - jit -> base_ip );
381
+ }
382
+
383
+ /*
384
+ * Return whether the next 64-bit literal pool entry can be referenced using
385
+ * Long-Displacement Facility
386
+ */
387
+ static bool can_use_ldisp_for_lit64 (struct bpf_jit * jit )
388
+ {
389
+ return is_valid_ldisp (jit -> lit64 - jit -> base_ip );
390
+ }
391
+
374
392
/*
375
393
* Fill whole space with illegal instructions
376
394
*/
@@ -752,9 +770,18 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
752
770
EMIT4_IMM (0xa7080000 , REG_W0 , 0 );
753
771
/* lr %w1,%dst */
754
772
EMIT2 (0x1800 , REG_W1 , dst_reg );
755
- /* dl %w0,<d(imm)>(%l) */
756
- EMIT6_DISP_LH (0xe3000000 , 0x0097 , REG_W0 , REG_0 , REG_L ,
757
- EMIT_CONST_U32 (imm ));
773
+ if (!is_first_pass (jit ) && can_use_ldisp_for_lit32 (jit )) {
774
+ /* dl %w0,<d(imm)>(%l) */
775
+ EMIT6_DISP_LH (0xe3000000 , 0x0097 , REG_W0 , REG_0 , REG_L ,
776
+ EMIT_CONST_U32 (imm ));
777
+ } else {
778
+ /* lgfrl %dst,imm */
779
+ EMIT6_PCREL_RILB (0xc40c0000 , dst_reg ,
780
+ _EMIT_CONST_U32 (imm ));
781
+ jit -> seen |= SEEN_LITERAL ;
782
+ /* dlr %w0,%dst */
783
+ EMIT4 (0xb9970000 , REG_W0 , dst_reg );
784
+ }
758
785
/* llgfr %dst,%rc */
759
786
EMIT4 (0xb9160000 , dst_reg , rc_reg );
760
787
if (insn_is_zext (& insn [1 ]))
@@ -776,9 +803,18 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
776
803
EMIT4_IMM (0xa7090000 , REG_W0 , 0 );
777
804
/* lgr %w1,%dst */
778
805
EMIT4 (0xb9040000 , REG_W1 , dst_reg );
779
- /* dlg %w0,<d(imm)>(%l) */
780
- EMIT6_DISP_LH (0xe3000000 , 0x0087 , REG_W0 , REG_0 , REG_L ,
781
- EMIT_CONST_U64 (imm ));
806
+ if (!is_first_pass (jit ) && can_use_ldisp_for_lit64 (jit )) {
807
+ /* dlg %w0,<d(imm)>(%l) */
808
+ EMIT6_DISP_LH (0xe3000000 , 0x0087 , REG_W0 , REG_0 , REG_L ,
809
+ EMIT_CONST_U64 (imm ));
810
+ } else {
811
+ /* lgrl %dst,imm */
812
+ EMIT6_PCREL_RILB (0xc4080000 , dst_reg ,
813
+ _EMIT_CONST_U64 (imm ));
814
+ jit -> seen |= SEEN_LITERAL ;
815
+ /* dlgr %w0,%dst */
816
+ EMIT4 (0xb9870000 , REG_W0 , dst_reg );
817
+ }
782
818
/* lgr %dst,%rc */
783
819
EMIT4 (0xb9040000 , dst_reg , rc_reg );
784
820
break ;
@@ -801,9 +837,19 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
801
837
EMIT_ZERO (dst_reg );
802
838
break ;
803
839
case BPF_ALU64 | BPF_AND | BPF_K : /* dst = dst & imm */
804
- /* ng %dst,<d(imm)>(%l) */
805
- EMIT6_DISP_LH (0xe3000000 , 0x0080 , dst_reg , REG_0 , REG_L ,
806
- EMIT_CONST_U64 (imm ));
840
+ if (!is_first_pass (jit ) && can_use_ldisp_for_lit64 (jit )) {
841
+ /* ng %dst,<d(imm)>(%l) */
842
+ EMIT6_DISP_LH (0xe3000000 , 0x0080 ,
843
+ dst_reg , REG_0 , REG_L ,
844
+ EMIT_CONST_U64 (imm ));
845
+ } else {
846
+ /* lgrl %w0,imm */
847
+ EMIT6_PCREL_RILB (0xc4080000 , REG_W0 ,
848
+ _EMIT_CONST_U64 (imm ));
849
+ jit -> seen |= SEEN_LITERAL ;
850
+ /* ngr %dst,%w0 */
851
+ EMIT4 (0xb9800000 , dst_reg , REG_W0 );
852
+ }
807
853
break ;
808
854
/*
809
855
* BPF_OR
@@ -823,9 +869,19 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
823
869
EMIT_ZERO (dst_reg );
824
870
break ;
825
871
case BPF_ALU64 | BPF_OR | BPF_K : /* dst = dst | imm */
826
- /* og %dst,<d(imm)>(%l) */
827
- EMIT6_DISP_LH (0xe3000000 , 0x0081 , dst_reg , REG_0 , REG_L ,
828
- EMIT_CONST_U64 (imm ));
872
+ if (!is_first_pass (jit ) && can_use_ldisp_for_lit64 (jit )) {
873
+ /* og %dst,<d(imm)>(%l) */
874
+ EMIT6_DISP_LH (0xe3000000 , 0x0081 ,
875
+ dst_reg , REG_0 , REG_L ,
876
+ EMIT_CONST_U64 (imm ));
877
+ } else {
878
+ /* lgrl %w0,imm */
879
+ EMIT6_PCREL_RILB (0xc4080000 , REG_W0 ,
880
+ _EMIT_CONST_U64 (imm ));
881
+ jit -> seen |= SEEN_LITERAL ;
882
+ /* ogr %dst,%w0 */
883
+ EMIT4 (0xb9810000 , dst_reg , REG_W0 );
884
+ }
829
885
break ;
830
886
/*
831
887
* BPF_XOR
@@ -847,9 +903,19 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
847
903
EMIT_ZERO (dst_reg );
848
904
break ;
849
905
case BPF_ALU64 | BPF_XOR | BPF_K : /* dst = dst ^ imm */
850
- /* xg %dst,<d(imm)>(%l) */
851
- EMIT6_DISP_LH (0xe3000000 , 0x0082 , dst_reg , REG_0 , REG_L ,
852
- EMIT_CONST_U64 (imm ));
906
+ if (!is_first_pass (jit ) && can_use_ldisp_for_lit64 (jit )) {
907
+ /* xg %dst,<d(imm)>(%l) */
908
+ EMIT6_DISP_LH (0xe3000000 , 0x0082 ,
909
+ dst_reg , REG_0 , REG_L ,
910
+ EMIT_CONST_U64 (imm ));
911
+ } else {
912
+ /* lgrl %w0,imm */
913
+ EMIT6_PCREL_RILB (0xc4080000 , REG_W0 ,
914
+ _EMIT_CONST_U64 (imm ));
915
+ jit -> seen |= SEEN_LITERAL ;
916
+ /* xgr %dst,%w0 */
917
+ EMIT4 (0xb9820000 , dst_reg , REG_W0 );
918
+ }
853
919
break ;
854
920
/*
855
921
* BPF_LSH
0 commit comments