@@ -711,6 +711,39 @@ static int emit_atomic_rmw(u8 rd, u8 rs, const struct bpf_insn *insn,
711
711
return 0 ;
712
712
}
713
713
714
+ /*
715
+ * Sign-extend the register if necessary
716
+ */
717
+ static int sign_extend (u8 rd , u8 rs , u8 sz , bool sign , struct rv_jit_context * ctx )
718
+ {
719
+ if (!sign && (sz == 1 || sz == 2 )) {
720
+ if (rd != rs )
721
+ emit_mv (rd , rs , ctx );
722
+ return 0 ;
723
+ }
724
+
725
+ switch (sz ) {
726
+ case 1 :
727
+ emit_sextb (rd , rs , ctx );
728
+ break ;
729
+ case 2 :
730
+ emit_sexth (rd , rs , ctx );
731
+ break ;
732
+ case 4 :
733
+ emit_sextw (rd , rs , ctx );
734
+ break ;
735
+ case 8 :
736
+ if (rd != rs )
737
+ emit_mv (rd , rs , ctx );
738
+ break ;
739
+ default :
740
+ pr_err ("bpf-jit: invalid size %d for sign_extend\n" , sz );
741
+ return - EINVAL ;
742
+ }
743
+
744
+ return 0 ;
745
+ }
746
+
714
747
#define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
715
748
#define BPF_FIXUP_REG_MASK GENMASK(31, 27)
716
749
#define REG_DONT_CLEAR_MARKER 0 /* RV_REG_ZERO unused in pt_regmap */
@@ -1175,8 +1208,15 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
1175
1208
restore_args (min_t (int , nr_arg_slots , RV_MAX_REG_ARGS ), args_off , ctx );
1176
1209
1177
1210
if (save_ret ) {
1178
- emit_ld (RV_REG_A0 , - retval_off , RV_REG_FP , ctx );
1179
1211
emit_ld (regmap [BPF_REG_0 ], - (retval_off - 8 ), RV_REG_FP , ctx );
1212
+ if (is_struct_ops ) {
1213
+ ret = sign_extend (RV_REG_A0 , regmap [BPF_REG_0 ], m -> ret_size ,
1214
+ m -> ret_flags & BTF_FMODEL_SIGNED_ARG , ctx );
1215
+ if (ret )
1216
+ goto out ;
1217
+ } else {
1218
+ emit_ld (RV_REG_A0 , - retval_off , RV_REG_FP , ctx );
1219
+ }
1180
1220
}
1181
1221
1182
1222
emit_ld (RV_REG_S1 , - sreg_off , RV_REG_FP , ctx );
0 commit comments