@@ -580,7 +580,8 @@ static int add_exception_handler(const struct bpf_insn *insn,
580580 unsigned long pc ;
581581 off_t offset ;
582582
583- if (!ctx -> insns || !ctx -> prog -> aux -> extable || BPF_MODE (insn -> code ) != BPF_PROBE_MEM )
583+ if (!ctx -> insns || !ctx -> prog -> aux -> extable ||
584+ (BPF_MODE (insn -> code ) != BPF_PROBE_MEM && BPF_MODE (insn -> code ) != BPF_PROBE_MEMSX ))
584585 return 0 ;
585586
586587 if (WARN_ON_ONCE (ctx -> nexentries >= ctx -> prog -> aux -> num_exentries ))
@@ -1046,7 +1047,19 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
10461047 emit_zext_32 (rd , ctx );
10471048 break ;
10481049 }
1049- emit_mv (rd , rs , ctx );
1050+ switch (insn -> off ) {
1051+ case 0 :
1052+ emit_mv (rd , rs , ctx );
1053+ break ;
1054+ case 8 :
1055+ case 16 :
1056+ emit_slli (RV_REG_T1 , rs , 64 - insn -> off , ctx );
1057+ emit_srai (rd , RV_REG_T1 , 64 - insn -> off , ctx );
1058+ break ;
1059+ case 32 :
1060+ emit_addiw (rd , rs , 0 , ctx );
1061+ break ;
1062+ }
10501063 if (!is64 && !aux -> verifier_zext )
10511064 emit_zext_32 (rd , ctx );
10521065 break ;
@@ -1094,13 +1107,19 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
10941107 break ;
10951108 case BPF_ALU | BPF_DIV | BPF_X :
10961109 case BPF_ALU64 | BPF_DIV | BPF_X :
1097- emit (is64 ? rv_divu (rd , rd , rs ) : rv_divuw (rd , rd , rs ), ctx );
1110+ if (off )
1111+ emit (is64 ? rv_div (rd , rd , rs ) : rv_divw (rd , rd , rs ), ctx );
1112+ else
1113+ emit (is64 ? rv_divu (rd , rd , rs ) : rv_divuw (rd , rd , rs ), ctx );
10981114 if (!is64 && !aux -> verifier_zext )
10991115 emit_zext_32 (rd , ctx );
11001116 break ;
11011117 case BPF_ALU | BPF_MOD | BPF_X :
11021118 case BPF_ALU64 | BPF_MOD | BPF_X :
1103- emit (is64 ? rv_remu (rd , rd , rs ) : rv_remuw (rd , rd , rs ), ctx );
1119+ if (off )
1120+ emit (is64 ? rv_rem (rd , rd , rs ) : rv_remw (rd , rd , rs ), ctx );
1121+ else
1122+ emit (is64 ? rv_remu (rd , rd , rs ) : rv_remuw (rd , rd , rs ), ctx );
11041123 if (!is64 && !aux -> verifier_zext )
11051124 emit_zext_32 (rd , ctx );
11061125 break ;
@@ -1149,6 +1168,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
11491168 break ;
11501169
11511170 case BPF_ALU | BPF_END | BPF_FROM_BE :
1171+ case BPF_ALU64 | BPF_END | BPF_FROM_LE :
11521172 emit_li (RV_REG_T2 , 0 , ctx );
11531173
11541174 emit_andi (RV_REG_T1 , rd , 0xff , ctx );
@@ -1271,16 +1291,24 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
12711291 case BPF_ALU | BPF_DIV | BPF_K :
12721292 case BPF_ALU64 | BPF_DIV | BPF_K :
12731293 emit_imm (RV_REG_T1 , imm , ctx );
1274- emit (is64 ? rv_divu (rd , rd , RV_REG_T1 ) :
1275- rv_divuw (rd , rd , RV_REG_T1 ), ctx );
1294+ if (off )
1295+ emit (is64 ? rv_div (rd , rd , RV_REG_T1 ) :
1296+ rv_divw (rd , rd , RV_REG_T1 ), ctx );
1297+ else
1298+ emit (is64 ? rv_divu (rd , rd , RV_REG_T1 ) :
1299+ rv_divuw (rd , rd , RV_REG_T1 ), ctx );
12761300 if (!is64 && !aux -> verifier_zext )
12771301 emit_zext_32 (rd , ctx );
12781302 break ;
12791303 case BPF_ALU | BPF_MOD | BPF_K :
12801304 case BPF_ALU64 | BPF_MOD | BPF_K :
12811305 emit_imm (RV_REG_T1 , imm , ctx );
1282- emit (is64 ? rv_remu (rd , rd , RV_REG_T1 ) :
1283- rv_remuw (rd , rd , RV_REG_T1 ), ctx );
1306+ if (off )
1307+ emit (is64 ? rv_rem (rd , rd , RV_REG_T1 ) :
1308+ rv_remw (rd , rd , RV_REG_T1 ), ctx );
1309+ else
1310+ emit (is64 ? rv_remu (rd , rd , RV_REG_T1 ) :
1311+ rv_remuw (rd , rd , RV_REG_T1 ), ctx );
12841312 if (!is64 && !aux -> verifier_zext )
12851313 emit_zext_32 (rd , ctx );
12861314 break ;
@@ -1314,7 +1342,11 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
13141342
13151343 /* JUMP off */
13161344 case BPF_JMP | BPF_JA :
1317- rvoff = rv_offset (i , off , ctx );
1345+ case BPF_JMP32 | BPF_JA :
1346+ if (BPF_CLASS (code ) == BPF_JMP )
1347+ rvoff = rv_offset (i , off , ctx );
1348+ else
1349+ rvoff = rv_offset (i , imm , ctx );
13181350 ret = emit_jump_and_link (RV_REG_ZERO , rvoff , true, ctx );
13191351 if (ret )
13201352 return ret ;
@@ -1486,7 +1518,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
14861518 return 1 ;
14871519 }
14881520
1489- /* LDX: dst = *(size *)(src + off) */
1521+ /* LDX: dst = *(unsigned size *)(src + off) */
14901522 case BPF_LDX | BPF_MEM | BPF_B :
14911523 case BPF_LDX | BPF_MEM | BPF_H :
14921524 case BPF_LDX | BPF_MEM | BPF_W :
@@ -1495,57 +1527,80 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
14951527 case BPF_LDX | BPF_PROBE_MEM | BPF_H :
14961528 case BPF_LDX | BPF_PROBE_MEM | BPF_W :
14971529 case BPF_LDX | BPF_PROBE_MEM | BPF_DW :
1530+ /* LDSX: dst = *(signed size *)(src + off) */
1531+ case BPF_LDX | BPF_MEMSX | BPF_B :
1532+ case BPF_LDX | BPF_MEMSX | BPF_H :
1533+ case BPF_LDX | BPF_MEMSX | BPF_W :
1534+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_B :
1535+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_H :
1536+ case BPF_LDX | BPF_PROBE_MEMSX | BPF_W :
14981537 {
14991538 int insn_len , insns_start ;
1539+ bool sign_ext ;
1540+
1541+ sign_ext = BPF_MODE (insn -> code ) == BPF_MEMSX ||
1542+ BPF_MODE (insn -> code ) == BPF_PROBE_MEMSX ;
15001543
15011544 switch (BPF_SIZE (code )) {
15021545 case BPF_B :
15031546 if (is_12b_int (off )) {
15041547 insns_start = ctx -> ninsns ;
1505- emit (rv_lbu (rd , off , rs ), ctx );
1548+ if (sign_ext )
1549+ emit (rv_lb (rd , off , rs ), ctx );
1550+ else
1551+ emit (rv_lbu (rd , off , rs ), ctx );
15061552 insn_len = ctx -> ninsns - insns_start ;
15071553 break ;
15081554 }
15091555
15101556 emit_imm (RV_REG_T1 , off , ctx );
15111557 emit_add (RV_REG_T1 , RV_REG_T1 , rs , ctx );
15121558 insns_start = ctx -> ninsns ;
1513- emit (rv_lbu (rd , 0 , RV_REG_T1 ), ctx );
1559+ if (sign_ext )
1560+ emit (rv_lb (rd , 0 , RV_REG_T1 ), ctx );
1561+ else
1562+ emit (rv_lbu (rd , 0 , RV_REG_T1 ), ctx );
15141563 insn_len = ctx -> ninsns - insns_start ;
1515- if (insn_is_zext (& insn [1 ]))
1516- return 1 ;
15171564 break ;
15181565 case BPF_H :
15191566 if (is_12b_int (off )) {
15201567 insns_start = ctx -> ninsns ;
1521- emit (rv_lhu (rd , off , rs ), ctx );
1568+ if (sign_ext )
1569+ emit (rv_lh (rd , off , rs ), ctx );
1570+ else
1571+ emit (rv_lhu (rd , off , rs ), ctx );
15221572 insn_len = ctx -> ninsns - insns_start ;
15231573 break ;
15241574 }
15251575
15261576 emit_imm (RV_REG_T1 , off , ctx );
15271577 emit_add (RV_REG_T1 , RV_REG_T1 , rs , ctx );
15281578 insns_start = ctx -> ninsns ;
1529- emit (rv_lhu (rd , 0 , RV_REG_T1 ), ctx );
1579+ if (sign_ext )
1580+ emit (rv_lh (rd , 0 , RV_REG_T1 ), ctx );
1581+ else
1582+ emit (rv_lhu (rd , 0 , RV_REG_T1 ), ctx );
15301583 insn_len = ctx -> ninsns - insns_start ;
1531- if (insn_is_zext (& insn [1 ]))
1532- return 1 ;
15331584 break ;
15341585 case BPF_W :
15351586 if (is_12b_int (off )) {
15361587 insns_start = ctx -> ninsns ;
1537- emit (rv_lwu (rd , off , rs ), ctx );
1588+ if (sign_ext )
1589+ emit (rv_lw (rd , off , rs ), ctx );
1590+ else
1591+ emit (rv_lwu (rd , off , rs ), ctx );
15381592 insn_len = ctx -> ninsns - insns_start ;
15391593 break ;
15401594 }
15411595
15421596 emit_imm (RV_REG_T1 , off , ctx );
15431597 emit_add (RV_REG_T1 , RV_REG_T1 , rs , ctx );
15441598 insns_start = ctx -> ninsns ;
1545- emit (rv_lwu (rd , 0 , RV_REG_T1 ), ctx );
1599+ if (sign_ext )
1600+ emit (rv_lw (rd , 0 , RV_REG_T1 ), ctx );
1601+ else
1602+ emit (rv_lwu (rd , 0 , RV_REG_T1 ), ctx );
15461603 insn_len = ctx -> ninsns - insns_start ;
1547- if (insn_is_zext (& insn [1 ]))
1548- return 1 ;
15491604 break ;
15501605 case BPF_DW :
15511606 if (is_12b_int (off )) {
@@ -1566,6 +1621,9 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
15661621 ret = add_exception_handler (insn , ctx , rd , insn_len );
15671622 if (ret )
15681623 return ret ;
1624+
1625+ if (BPF_SIZE (code ) != BPF_DW && insn_is_zext (& insn [1 ]))
1626+ return 1 ;
15691627 break ;
15701628 }
15711629 /* speculation barrier */
0 commit comments