@@ -1451,6 +1451,32 @@ void arch_free_bpf_trampoline(void *image, unsigned int size)
14511451 bpf_prog_pack_free (image , size );
14521452}
14531453
1454+ /*
1455+ * Sign-extend the register if necessary
1456+ */
1457+ static void sign_extend (struct jit_ctx * ctx , int rd , int rj , u8 size , u8 flags )
1458+ {
1459+ if (!(flags & BTF_FMODEL_SIGNED_ARG ) && size != 8 )
1460+ return ;
1461+
1462+ switch (size ) {
1463+ case 1 :
1464+ emit_insn (ctx , extwb , rd , rj );
1465+ break ;
1466+ case 2 :
1467+ emit_insn (ctx , extwh , rd , rj );
1468+ break ;
1469+ case 4 :
1470+ emit_insn (ctx , addiw , rd , rj , 0 );
1471+ break ;
1472+ case 8 :
1473+ move_reg (ctx , rd , rj );
1474+ break ;
1475+ default :
1476+ pr_warn ("bpf_jit: invalid size %d for sign_extend\n" , size );
1477+ }
1478+ }
1479+
14541480static int __arch_prepare_bpf_trampoline (struct jit_ctx * ctx , struct bpf_tramp_image * im ,
14551481 const struct btf_func_model * m , struct bpf_tramp_links * tlinks ,
14561482 void * func_addr , u32 flags )
@@ -1659,8 +1685,12 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
16591685 restore_args (ctx , m -> nr_args , args_off );
16601686
16611687 if (save_ret ) {
1662- emit_insn (ctx , ldd , LOONGARCH_GPR_A0 , LOONGARCH_GPR_FP , - retval_off );
16631688 emit_insn (ctx , ldd , regmap [BPF_REG_0 ], LOONGARCH_GPR_FP , - (retval_off - 8 ));
1689+ if (is_struct_ops )
1690+ sign_extend (ctx , LOONGARCH_GPR_A0 , regmap [BPF_REG_0 ],
1691+ m -> ret_size , m -> ret_flags );
1692+ else
1693+ emit_insn (ctx , ldd , LOONGARCH_GPR_A0 , LOONGARCH_GPR_FP , - retval_off );
16641694 }
16651695
16661696 emit_insn (ctx , ldd , LOONGARCH_GPR_S1 , LOONGARCH_GPR_FP , - sreg_off );
0 commit comments