1313#include <linux/filter.h>
1414#include <asm/cacheflush.h>
1515
16+ /* verify runtime detection extension status */
17+ #define rv_ext_enabled (ext ) \
18+ (IS_ENABLED(CONFIG_RISCV_ISA_##ext) && riscv_has_extension_likely(RISCV_ISA_EXT_##ext))
19+
1620static inline bool rvc_enabled (void )
1721{
1822 return IS_ENABLED (CONFIG_RISCV_ISA_C );
1923}
2024
21- static inline bool rvzba_enabled (void )
22- {
23- return IS_ENABLED (CONFIG_RISCV_ISA_ZBA ) && riscv_has_extension_likely (RISCV_ISA_EXT_ZBA );
24- }
25-
26- static inline bool rvzbb_enabled (void )
27- {
28- return IS_ENABLED (CONFIG_RISCV_ISA_ZBB ) && riscv_has_extension_likely (RISCV_ISA_EXT_ZBB );
29- }
30-
3125enum {
3226 RV_REG_ZERO = 0 , /* The constant value 0 */
3327 RV_REG_RA = 1 , /* Return address */
@@ -84,6 +78,8 @@ struct rv_jit_context {
8478 int epilogue_offset ;
8579 int * offset ; /* BPF to RV */
8680 int nexentries ;
81+ int ex_insn_off ;
82+ int ex_jmp_off ;
8783 unsigned long flags ;
8884 int stack_size ;
8985 u64 arena_vm_start ;
@@ -757,6 +753,17 @@ static inline u16 rvc_swsp(u32 imm8, u8 rs2)
757753 return rv_css_insn (0x6 , imm , rs2 , 0x2 );
758754}
759755
756+ /* RVZACAS instructions. */
757+ static inline u32 rvzacas_amocas_w (u8 rd , u8 rs2 , u8 rs1 , u8 aq , u8 rl )
758+ {
759+ return rv_amo_insn (0x5 , aq , rl , rs2 , rs1 , 2 , rd , 0x2f );
760+ }
761+
762+ static inline u32 rvzacas_amocas_d (u8 rd , u8 rs2 , u8 rs1 , u8 aq , u8 rl )
763+ {
764+ return rv_amo_insn (0x5 , aq , rl , rs2 , rs1 , 3 , rd , 0x2f );
765+ }
766+
760767/* RVZBA instructions. */
761768static inline u32 rvzba_sh2add (u8 rd , u8 rs1 , u8 rs2 )
762769{
@@ -1123,7 +1130,7 @@ static inline void emit_sw(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx)
11231130
11241131static inline void emit_sh2add (u8 rd , u8 rs1 , u8 rs2 , struct rv_jit_context * ctx )
11251132{
1126- if (rvzba_enabled ( )) {
1133+ if (rv_ext_enabled ( ZBA )) {
11271134 emit (rvzba_sh2add (rd , rs1 , rs2 ), ctx );
11281135 return ;
11291136 }
@@ -1134,7 +1141,7 @@ static inline void emit_sh2add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx
11341141
11351142static inline void emit_sh3add (u8 rd , u8 rs1 , u8 rs2 , struct rv_jit_context * ctx )
11361143{
1137- if (rvzba_enabled ( )) {
1144+ if (rv_ext_enabled ( ZBA )) {
11381145 emit (rvzba_sh3add (rd , rs1 , rs2 ), ctx );
11391146 return ;
11401147 }
@@ -1184,7 +1191,7 @@ static inline void emit_subw(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
11841191
11851192static inline void emit_sextb (u8 rd , u8 rs , struct rv_jit_context * ctx )
11861193{
1187- if (rvzbb_enabled ( )) {
1194+ if (rv_ext_enabled ( ZBB )) {
11881195 emit (rvzbb_sextb (rd , rs ), ctx );
11891196 return ;
11901197 }
@@ -1195,7 +1202,7 @@ static inline void emit_sextb(u8 rd, u8 rs, struct rv_jit_context *ctx)
11951202
11961203static inline void emit_sexth (u8 rd , u8 rs , struct rv_jit_context * ctx )
11971204{
1198- if (rvzbb_enabled ( )) {
1205+ if (rv_ext_enabled ( ZBB )) {
11991206 emit (rvzbb_sexth (rd , rs ), ctx );
12001207 return ;
12011208 }
@@ -1211,7 +1218,7 @@ static inline void emit_sextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
12111218
12121219static inline void emit_zexth (u8 rd , u8 rs , struct rv_jit_context * ctx )
12131220{
1214- if (rvzbb_enabled ( )) {
1221+ if (rv_ext_enabled ( ZBB )) {
12151222 emit (rvzbb_zexth (rd , rs ), ctx );
12161223 return ;
12171224 }
@@ -1222,7 +1229,7 @@ static inline void emit_zexth(u8 rd, u8 rs, struct rv_jit_context *ctx)
12221229
12231230static inline void emit_zextw (u8 rd , u8 rs , struct rv_jit_context * ctx )
12241231{
1225- if (rvzba_enabled ( )) {
1232+ if (rv_ext_enabled ( ZBA )) {
12261233 emit (rvzba_zextw (rd , rs ), ctx );
12271234 return ;
12281235 }
@@ -1233,7 +1240,7 @@ static inline void emit_zextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
12331240
12341241static inline void emit_bswap (u8 rd , s32 imm , struct rv_jit_context * ctx )
12351242{
1236- if (rvzbb_enabled ( )) {
1243+ if (rv_ext_enabled ( ZBB )) {
12371244 int bits = 64 - imm ;
12381245
12391246 emit (rvzbb_rev8 (rd , rd ), ctx );
@@ -1289,6 +1296,35 @@ static inline void emit_bswap(u8 rd, s32 imm, struct rv_jit_context *ctx)
12891296 emit_mv (rd , RV_REG_T2 , ctx );
12901297}
12911298
1299+ static inline void emit_cmpxchg (u8 rd , u8 rs , u8 r0 , bool is64 , struct rv_jit_context * ctx )
1300+ {
1301+ int jmp_offset ;
1302+
1303+ if (rv_ext_enabled (ZACAS )) {
1304+ ctx -> ex_insn_off = ctx -> ninsns ;
1305+ emit (is64 ? rvzacas_amocas_d (r0 , rs , rd , 1 , 1 ) :
1306+ rvzacas_amocas_w (r0 , rs , rd , 1 , 1 ), ctx );
1307+ ctx -> ex_jmp_off = ctx -> ninsns ;
1308+ if (!is64 )
1309+ emit_zextw (r0 , r0 , ctx );
1310+ return ;
1311+ }
1312+
1313+ if (is64 )
1314+ emit_mv (RV_REG_T2 , r0 , ctx );
1315+ else
1316+ emit_addiw (RV_REG_T2 , r0 , 0 , ctx );
1317+ emit (is64 ? rv_lr_d (r0 , 0 , rd , 0 , 0 ) :
1318+ rv_lr_w (r0 , 0 , rd , 0 , 0 ), ctx );
1319+ jmp_offset = ninsns_rvoff (8 );
1320+ emit (rv_bne (RV_REG_T2 , r0 , jmp_offset >> 1 ), ctx );
1321+ emit (is64 ? rv_sc_d (RV_REG_T3 , rs , rd , 0 , 1 ) :
1322+ rv_sc_w (RV_REG_T3 , rs , rd , 0 , 1 ), ctx );
1323+ jmp_offset = ninsns_rvoff (-6 );
1324+ emit (rv_bne (RV_REG_T3 , 0 , jmp_offset >> 1 ), ctx );
1325+ emit_fence_rw_rw (ctx );
1326+ }
1327+
12921328#endif /* __riscv_xlen == 64 */
12931329
12941330void bpf_jit_build_prologue (struct rv_jit_context * ctx , bool is_subprog );
0 commit comments