@@ -392,6 +392,71 @@ asm (
392392" blr ;"
393393);
394394
395+ static int emit_atomic_ld_st (const struct bpf_insn insn , struct codegen_context * ctx , u32 * image )
396+ {
397+ u32 code = insn .code ;
398+ u32 dst_reg = bpf_to_ppc (insn .dst_reg );
399+ u32 src_reg = bpf_to_ppc (insn .src_reg );
400+ u32 size = BPF_SIZE (code );
401+ u32 tmp1_reg = bpf_to_ppc (TMP_REG_1 );
402+ u32 tmp2_reg = bpf_to_ppc (TMP_REG_2 );
403+ s16 off = insn .off ;
404+ s32 imm = insn .imm ;
405+
406+ switch (imm ) {
407+ case BPF_LOAD_ACQ :
408+ switch (size ) {
409+ case BPF_B :
410+ EMIT (PPC_RAW_LBZ (dst_reg , src_reg , off ));
411+ break ;
412+ case BPF_H :
413+ EMIT (PPC_RAW_LHZ (dst_reg , src_reg , off ));
414+ break ;
415+ case BPF_W :
416+ EMIT (PPC_RAW_LWZ (dst_reg , src_reg , off ));
417+ break ;
418+ case BPF_DW :
419+ if (off % 4 ) {
420+ EMIT (PPC_RAW_LI (tmp1_reg , off ));
421+ EMIT (PPC_RAW_LDX (dst_reg , src_reg , tmp1_reg ));
422+ } else {
423+ EMIT (PPC_RAW_LD (dst_reg , src_reg , off ));
424+ }
425+ break ;
426+ }
427+ EMIT (PPC_RAW_LWSYNC ());
428+ break ;
429+ case BPF_STORE_REL :
430+ EMIT (PPC_RAW_LWSYNC ());
431+ switch (size ) {
432+ case BPF_B :
433+ EMIT (PPC_RAW_STB (src_reg , dst_reg , off ));
434+ break ;
435+ case BPF_H :
436+ EMIT (PPC_RAW_STH (src_reg , dst_reg , off ));
437+ break ;
438+ case BPF_W :
439+ EMIT (PPC_RAW_STW (src_reg , dst_reg , off ));
440+ break ;
441+ case BPF_DW :
442+ if (off % 4 ) {
443+ EMIT (PPC_RAW_LI (tmp2_reg , off ));
444+ EMIT (PPC_RAW_STDX (src_reg , dst_reg , tmp2_reg ));
445+ } else {
446+ EMIT (PPC_RAW_STD (src_reg , dst_reg , off ));
447+ }
448+ break ;
449+ }
450+ break ;
451+ default :
452+ pr_err_ratelimited ("unexpected atomic load/store op code %02x\n" ,
453+ imm );
454+ return - EINVAL ;
455+ }
456+
457+ return 0 ;
458+ }
459+
395460/* Assemble the body code between the prologue & epilogue */
396461int bpf_jit_build_body (struct bpf_prog * fp , u32 * image , u32 * fimage , struct codegen_context * ctx ,
397462 u32 * addrs , int pass , bool extra_pass )
@@ -859,8 +924,25 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
859924 /*
860925 * BPF_STX ATOMIC (atomic ops)
861926 */
927+ case BPF_STX | BPF_ATOMIC | BPF_B :
928+ case BPF_STX | BPF_ATOMIC | BPF_H :
862929 case BPF_STX | BPF_ATOMIC | BPF_W :
863930 case BPF_STX | BPF_ATOMIC | BPF_DW :
931+ if (bpf_atomic_is_load_store (& insn [i ])) {
932+ ret = emit_atomic_ld_st (insn [i ], ctx , image );
933+ if (ret )
934+ return ret ;
935+
936+ if (size != BPF_DW && insn_is_zext (& insn [i + 1 ]))
937+ addrs [++ i ] = ctx -> idx * 4 ;
938+ break ;
939+ } else if (size == BPF_B || size == BPF_H ) {
940+ pr_err_ratelimited (
941+ "eBPF filter atomic op code %02x (@%d) unsupported\n" ,
942+ code , i );
943+ return - EOPNOTSUPP ;
944+ }
945+
864946 save_reg = tmp2_reg ;
865947 ret_reg = src_reg ;
866948
0 commit comments