@@ -571,6 +571,11 @@ static int emit_atomic_ld_st(u8 rd, u8 rs, const struct bpf_insn *insn,
571
571
switch (imm ) {
572
572
/* dst_reg = load_acquire(src_reg + off16) */
573
573
case BPF_LOAD_ACQ :
574
+ if (BPF_MODE (code ) == BPF_PROBE_ATOMIC ) {
575
+ emit_add (RV_REG_T2 , rs , RV_REG_ARENA , ctx );
576
+ rs = RV_REG_T2 ;
577
+ }
578
+
574
579
emit_ldx (rd , off , rs , BPF_SIZE (code ), false, ctx );
575
580
emit_fence_r_rw (ctx );
576
581
@@ -582,6 +587,11 @@ static int emit_atomic_ld_st(u8 rd, u8 rs, const struct bpf_insn *insn,
582
587
break ;
583
588
/* store_release(dst_reg + off16, src_reg) */
584
589
case BPF_STORE_REL :
590
+ if (BPF_MODE (code ) == BPF_PROBE_ATOMIC ) {
591
+ emit_add (RV_REG_T2 , rd , RV_REG_ARENA , ctx );
592
+ rd = RV_REG_T2 ;
593
+ }
594
+
585
595
emit_fence_rw_w (ctx );
586
596
emit_stx (rd , off , rs , BPF_SIZE (code ), ctx );
587
597
break ;
@@ -599,13 +609,12 @@ static int emit_atomic_rmw(u8 rd, u8 rs, const struct bpf_insn *insn,
599
609
u8 code = insn -> code ;
600
610
s16 off = insn -> off ;
601
611
s32 imm = insn -> imm ;
602
- bool is64 ;
612
+ bool is64 = BPF_SIZE ( code ) == BPF_DW ;
603
613
604
614
if (BPF_SIZE (code ) != BPF_W && BPF_SIZE (code ) != BPF_DW ) {
605
615
pr_err_once ("bpf-jit: 1- and 2-byte RMW atomics are not supported\n" );
606
616
return - EINVAL ;
607
617
}
608
- is64 = BPF_SIZE (code ) == BPF_DW ;
609
618
610
619
if (off ) {
611
620
if (is_12b_int (off )) {
@@ -617,53 +626,76 @@ static int emit_atomic_rmw(u8 rd, u8 rs, const struct bpf_insn *insn,
617
626
rd = RV_REG_T1 ;
618
627
}
619
628
629
+ if (BPF_MODE (code ) == BPF_PROBE_ATOMIC ) {
630
+ emit_add (RV_REG_T1 , rd , RV_REG_ARENA , ctx );
631
+ rd = RV_REG_T1 ;
632
+ }
633
+
620
634
switch (imm ) {
621
635
/* lock *(u32/u64 *)(dst_reg + off16) <op>= src_reg */
622
636
case BPF_ADD :
637
+ ctx -> ex_insn_off = ctx -> ninsns ;
623
638
emit (is64 ? rv_amoadd_d (RV_REG_ZERO , rs , rd , 0 , 0 ) :
624
639
rv_amoadd_w (RV_REG_ZERO , rs , rd , 0 , 0 ), ctx );
640
+ ctx -> ex_jmp_off = ctx -> ninsns ;
625
641
break ;
626
642
case BPF_AND :
643
+ ctx -> ex_insn_off = ctx -> ninsns ;
627
644
emit (is64 ? rv_amoand_d (RV_REG_ZERO , rs , rd , 0 , 0 ) :
628
645
rv_amoand_w (RV_REG_ZERO , rs , rd , 0 , 0 ), ctx );
646
+ ctx -> ex_jmp_off = ctx -> ninsns ;
629
647
break ;
630
648
case BPF_OR :
649
+ ctx -> ex_insn_off = ctx -> ninsns ;
631
650
emit (is64 ? rv_amoor_d (RV_REG_ZERO , rs , rd , 0 , 0 ) :
632
651
rv_amoor_w (RV_REG_ZERO , rs , rd , 0 , 0 ), ctx );
652
+ ctx -> ex_jmp_off = ctx -> ninsns ;
633
653
break ;
634
654
case BPF_XOR :
655
+ ctx -> ex_insn_off = ctx -> ninsns ;
635
656
emit (is64 ? rv_amoxor_d (RV_REG_ZERO , rs , rd , 0 , 0 ) :
636
657
rv_amoxor_w (RV_REG_ZERO , rs , rd , 0 , 0 ), ctx );
658
+ ctx -> ex_jmp_off = ctx -> ninsns ;
637
659
break ;
638
660
/* src_reg = atomic_fetch_<op>(dst_reg + off16, src_reg) */
639
661
case BPF_ADD | BPF_FETCH :
662
+ ctx -> ex_insn_off = ctx -> ninsns ;
640
663
emit (is64 ? rv_amoadd_d (rs , rs , rd , 1 , 1 ) :
641
664
rv_amoadd_w (rs , rs , rd , 1 , 1 ), ctx );
665
+ ctx -> ex_jmp_off = ctx -> ninsns ;
642
666
if (!is64 )
643
667
emit_zextw (rs , rs , ctx );
644
668
break ;
645
669
case BPF_AND | BPF_FETCH :
670
+ ctx -> ex_insn_off = ctx -> ninsns ;
646
671
emit (is64 ? rv_amoand_d (rs , rs , rd , 1 , 1 ) :
647
672
rv_amoand_w (rs , rs , rd , 1 , 1 ), ctx );
673
+ ctx -> ex_jmp_off = ctx -> ninsns ;
648
674
if (!is64 )
649
675
emit_zextw (rs , rs , ctx );
650
676
break ;
651
677
case BPF_OR | BPF_FETCH :
678
+ ctx -> ex_insn_off = ctx -> ninsns ;
652
679
emit (is64 ? rv_amoor_d (rs , rs , rd , 1 , 1 ) :
653
680
rv_amoor_w (rs , rs , rd , 1 , 1 ), ctx );
681
+ ctx -> ex_jmp_off = ctx -> ninsns ;
654
682
if (!is64 )
655
683
emit_zextw (rs , rs , ctx );
656
684
break ;
657
685
case BPF_XOR | BPF_FETCH :
686
+ ctx -> ex_insn_off = ctx -> ninsns ;
658
687
emit (is64 ? rv_amoxor_d (rs , rs , rd , 1 , 1 ) :
659
688
rv_amoxor_w (rs , rs , rd , 1 , 1 ), ctx );
689
+ ctx -> ex_jmp_off = ctx -> ninsns ;
660
690
if (!is64 )
661
691
emit_zextw (rs , rs , ctx );
662
692
break ;
663
693
/* src_reg = atomic_xchg(dst_reg + off16, src_reg); */
664
694
case BPF_XCHG :
695
+ ctx -> ex_insn_off = ctx -> ninsns ;
665
696
emit (is64 ? rv_amoswap_d (rs , rs , rd , 1 , 1 ) :
666
697
rv_amoswap_w (rs , rs , rd , 1 , 1 ), ctx );
698
+ ctx -> ex_jmp_off = ctx -> ninsns ;
667
699
if (!is64 )
668
700
emit_zextw (rs , rs , ctx );
669
701
break ;
@@ -711,7 +743,8 @@ static int add_exception_handler(const struct bpf_insn *insn, int dst_reg,
711
743
712
744
if (BPF_MODE (insn -> code ) != BPF_PROBE_MEM &&
713
745
BPF_MODE (insn -> code ) != BPF_PROBE_MEMSX &&
714
- BPF_MODE (insn -> code ) != BPF_PROBE_MEM32 )
746
+ BPF_MODE (insn -> code ) != BPF_PROBE_MEM32 &&
747
+ BPF_MODE (insn -> code ) != BPF_PROBE_ATOMIC )
715
748
return 0 ;
716
749
717
750
if (WARN_ON_ONCE (ctx -> nexentries >= ctx -> prog -> aux -> num_exentries ))
@@ -1841,14 +1874,21 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
1841
1874
return ret ;
1842
1875
break ;
1843
1876
1877
+ /* Atomics */
1844
1878
case BPF_STX | BPF_ATOMIC | BPF_B :
1845
1879
case BPF_STX | BPF_ATOMIC | BPF_H :
1846
1880
case BPF_STX | BPF_ATOMIC | BPF_W :
1847
1881
case BPF_STX | BPF_ATOMIC | BPF_DW :
1882
+ case BPF_STX | BPF_PROBE_ATOMIC | BPF_B :
1883
+ case BPF_STX | BPF_PROBE_ATOMIC | BPF_H :
1884
+ case BPF_STX | BPF_PROBE_ATOMIC | BPF_W :
1885
+ case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW :
1848
1886
if (bpf_atomic_is_load_store (insn ))
1849
1887
ret = emit_atomic_ld_st (rd , rs , insn , ctx );
1850
1888
else
1851
1889
ret = emit_atomic_rmw (rd , rs , insn , ctx );
1890
+
1891
+ ret = ret ?: add_exception_handler (insn , REG_DONT_CLEAR_MARKER , ctx );
1852
1892
if (ret )
1853
1893
return ret ;
1854
1894
break ;
@@ -1979,6 +2019,20 @@ bool bpf_jit_supports_arena(void)
1979
2019
return true;
1980
2020
}
1981
2021
2022
+ bool bpf_jit_supports_insn (struct bpf_insn * insn , bool in_arena )
2023
+ {
2024
+ if (in_arena ) {
2025
+ switch (insn -> code ) {
2026
+ case BPF_STX | BPF_ATOMIC | BPF_W :
2027
+ case BPF_STX | BPF_ATOMIC | BPF_DW :
2028
+ if (insn -> imm == BPF_CMPXCHG )
2029
+ return rv_ext_enabled (ZACAS );
2030
+ }
2031
+ }
2032
+
2033
+ return true;
2034
+ }
2035
+
1982
2036
bool bpf_jit_supports_percpu_insn (void )
1983
2037
{
1984
2038
return true;
0 commit comments