@@ -787,17 +787,25 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
787
787
else
788
788
EMIT (PPC_RAW_LWARX (tmp2_reg , tmp1_reg , dst_reg , 0 ));
789
789
790
+ /* Save old value in _R0 */
791
+ if (imm & BPF_FETCH )
792
+ EMIT (PPC_RAW_MR (_R0 , tmp2_reg ));
793
+
790
794
switch (imm ) {
791
795
case BPF_ADD :
796
+ case BPF_ADD | BPF_FETCH :
792
797
EMIT (PPC_RAW_ADD (tmp2_reg , tmp2_reg , src_reg ));
793
798
break ;
794
799
case BPF_AND :
800
+ case BPF_AND | BPF_FETCH :
795
801
EMIT (PPC_RAW_AND (tmp2_reg , tmp2_reg , src_reg ));
796
802
break ;
797
803
case BPF_OR :
804
+ case BPF_OR | BPF_FETCH :
798
805
EMIT (PPC_RAW_OR (tmp2_reg , tmp2_reg , src_reg ));
799
806
break ;
800
807
case BPF_XOR :
808
+ case BPF_XOR | BPF_FETCH :
801
809
EMIT (PPC_RAW_XOR (tmp2_reg , tmp2_reg , src_reg ));
802
810
break ;
803
811
default :
@@ -807,13 +815,17 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
807
815
return - EOPNOTSUPP ;
808
816
}
809
817
810
- /* store result back */
818
+ /* store new value */
811
819
if (size == BPF_DW )
812
820
EMIT (PPC_RAW_STDCX (tmp2_reg , tmp1_reg , dst_reg ));
813
821
else
814
822
EMIT (PPC_RAW_STWCX (tmp2_reg , tmp1_reg , dst_reg ));
815
823
/* we're done if this succeeded */
816
824
PPC_BCC_SHORT (COND_NE , tmp_idx );
825
+
826
+ /* For the BPF_FETCH variant, get old value into src_reg */
827
+ if (imm & BPF_FETCH )
828
+ EMIT (PPC_RAW_MR (src_reg , _R0 ));
817
829
break ;
818
830
819
831
/*
0 commit comments