@@ -954,6 +954,35 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
954
954
return ret ;
955
955
}
956
956
957
+ /*
958
+ * Sign-extend the register if necessary
959
+ */
960
+ static int sign_extend (int rd , int rs , u8 size , u8 flags , struct rv_jit_context * ctx )
961
+ {
962
+ if (!(flags & BTF_FMODEL_SIGNED_ARG ) && (size == 1 || size == 2 ))
963
+ return 0 ;
964
+
965
+ switch (size ) {
966
+ case 1 :
967
+ emit_sextb (rd , rs , ctx );
968
+ break ;
969
+ case 2 :
970
+ emit_sexth (rd , rs , ctx );
971
+ break ;
972
+ case 4 :
973
+ emit_sextw (rd , rs , ctx );
974
+ break ;
975
+ case 8 :
976
+ emit_mv (rd , rs , ctx );
977
+ break ;
978
+ default :
979
+ pr_err ("bpf-jit: invalid size %d for sign_extend\n" , size );
980
+ return - EINVAL ;
981
+ }
982
+
983
+ return 0 ;
984
+ }
985
+
957
986
static int __arch_prepare_bpf_trampoline (struct bpf_tramp_image * im ,
958
987
const struct btf_func_model * m ,
959
988
struct bpf_tramp_links * tlinks ,
@@ -1175,8 +1204,15 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
1175
1204
restore_args (min_t (int , nr_arg_slots , RV_MAX_REG_ARGS ), args_off , ctx );
1176
1205
1177
1206
if (save_ret ) {
1178
- emit_ld (RV_REG_A0 , - retval_off , RV_REG_FP , ctx );
1179
1207
emit_ld (regmap [BPF_REG_0 ], - (retval_off - 8 ), RV_REG_FP , ctx );
1208
+ if (is_struct_ops ) {
1209
+ ret = sign_extend (RV_REG_A0 , regmap [BPF_REG_0 ],
1210
+ m -> ret_size , m -> ret_flags , ctx );
1211
+ if (ret )
1212
+ goto out ;
1213
+ } else {
1214
+ emit_ld (RV_REG_A0 , - retval_off , RV_REG_FP , ctx );
1215
+ }
1180
1216
}
1181
1217
1182
1218
emit_ld (RV_REG_S1 , - sreg_off , RV_REG_FP , ctx );
0 commit comments