13
13
#include <linux/filter.h>
14
14
#include <asm/cacheflush.h>
15
15
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
+
16
20
static inline bool rvc_enabled (void )
17
21
{
18
22
return IS_ENABLED (CONFIG_RISCV_ISA_C );
19
23
}
20
24
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
-
31
25
enum {
32
26
RV_REG_ZERO = 0 , /* The constant value 0 */
33
27
RV_REG_RA = 1 , /* Return address */
@@ -84,6 +78,8 @@ struct rv_jit_context {
84
78
int epilogue_offset ;
85
79
int * offset ; /* BPF to RV */
86
80
int nexentries ;
81
+ int ex_insn_off ;
82
+ int ex_jmp_off ;
87
83
unsigned long flags ;
88
84
int stack_size ;
89
85
u64 arena_vm_start ;
@@ -757,6 +753,17 @@ static inline u16 rvc_swsp(u32 imm8, u8 rs2)
757
753
return rv_css_insn (0x6 , imm , rs2 , 0x2 );
758
754
}
759
755
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
+
760
767
/* RVZBA instructions. */
761
768
static inline u32 rvzba_sh2add (u8 rd , u8 rs1 , u8 rs2 )
762
769
{
@@ -1123,7 +1130,7 @@ static inline void emit_sw(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx)
1123
1130
1124
1131
static inline void emit_sh2add (u8 rd , u8 rs1 , u8 rs2 , struct rv_jit_context * ctx )
1125
1132
{
1126
- if (rvzba_enabled ( )) {
1133
+ if (rv_ext_enabled ( ZBA )) {
1127
1134
emit (rvzba_sh2add (rd , rs1 , rs2 ), ctx );
1128
1135
return ;
1129
1136
}
@@ -1134,7 +1141,7 @@ static inline void emit_sh2add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx
1134
1141
1135
1142
static inline void emit_sh3add (u8 rd , u8 rs1 , u8 rs2 , struct rv_jit_context * ctx )
1136
1143
{
1137
- if (rvzba_enabled ( )) {
1144
+ if (rv_ext_enabled ( ZBA )) {
1138
1145
emit (rvzba_sh3add (rd , rs1 , rs2 ), ctx );
1139
1146
return ;
1140
1147
}
@@ -1184,7 +1191,7 @@ static inline void emit_subw(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
1184
1191
1185
1192
static inline void emit_sextb (u8 rd , u8 rs , struct rv_jit_context * ctx )
1186
1193
{
1187
- if (rvzbb_enabled ( )) {
1194
+ if (rv_ext_enabled ( ZBB )) {
1188
1195
emit (rvzbb_sextb (rd , rs ), ctx );
1189
1196
return ;
1190
1197
}
@@ -1195,7 +1202,7 @@ static inline void emit_sextb(u8 rd, u8 rs, struct rv_jit_context *ctx)
1195
1202
1196
1203
static inline void emit_sexth (u8 rd , u8 rs , struct rv_jit_context * ctx )
1197
1204
{
1198
- if (rvzbb_enabled ( )) {
1205
+ if (rv_ext_enabled ( ZBB )) {
1199
1206
emit (rvzbb_sexth (rd , rs ), ctx );
1200
1207
return ;
1201
1208
}
@@ -1211,7 +1218,7 @@ static inline void emit_sextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
1211
1218
1212
1219
static inline void emit_zexth (u8 rd , u8 rs , struct rv_jit_context * ctx )
1213
1220
{
1214
- if (rvzbb_enabled ( )) {
1221
+ if (rv_ext_enabled ( ZBB )) {
1215
1222
emit (rvzbb_zexth (rd , rs ), ctx );
1216
1223
return ;
1217
1224
}
@@ -1222,7 +1229,7 @@ static inline void emit_zexth(u8 rd, u8 rs, struct rv_jit_context *ctx)
1222
1229
1223
1230
static inline void emit_zextw (u8 rd , u8 rs , struct rv_jit_context * ctx )
1224
1231
{
1225
- if (rvzba_enabled ( )) {
1232
+ if (rv_ext_enabled ( ZBA )) {
1226
1233
emit (rvzba_zextw (rd , rs ), ctx );
1227
1234
return ;
1228
1235
}
@@ -1233,7 +1240,7 @@ static inline void emit_zextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
1233
1240
1234
1241
static inline void emit_bswap (u8 rd , s32 imm , struct rv_jit_context * ctx )
1235
1242
{
1236
- if (rvzbb_enabled ( )) {
1243
+ if (rv_ext_enabled ( ZBB )) {
1237
1244
int bits = 64 - imm ;
1238
1245
1239
1246
emit (rvzbb_rev8 (rd , rd ), ctx );
@@ -1289,6 +1296,35 @@ static inline void emit_bswap(u8 rd, s32 imm, struct rv_jit_context *ctx)
1289
1296
emit_mv (rd , RV_REG_T2 , ctx );
1290
1297
}
1291
1298
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
+
1292
1328
#endif /* __riscv_xlen == 64 */
1293
1329
1294
1330
void bpf_jit_build_prologue (struct rv_jit_context * ctx , bool is_subprog );
0 commit comments