@@ -1448,6 +1448,37 @@ void arch_free_bpf_trampoline(void *image, unsigned int size)
14481448 bpf_prog_pack_free (image , size );
14491449}
14501450
1451+ /*
1452+ * Sign-extend the register if necessary
1453+ */
1454+ static void sign_extend (struct jit_ctx * ctx , int rd , int rj , u8 size , bool sign )
1455+ {
1456+ /* ABI requires unsigned char/short to be zero-extended */
1457+ if (!sign && (size == 1 || size == 2 )) {
1458+ if (rd != rj )
1459+ move_reg (ctx , rd , rj );
1460+ return ;
1461+ }
1462+
1463+ switch (size ) {
1464+ case 1 :
1465+ emit_insn (ctx , extwb , rd , rj );
1466+ break ;
1467+ case 2 :
1468+ emit_insn (ctx , extwh , rd , rj );
1469+ break ;
1470+ case 4 :
1471+ emit_insn (ctx , addiw , rd , rj , 0 );
1472+ break ;
1473+ case 8 :
1474+ if (rd != rj )
1475+ move_reg (ctx , rd , rj );
1476+ break ;
1477+ default :
1478+ pr_warn ("bpf_jit: invalid size %d for sign_extend\n" , size );
1479+ }
1480+ }
1481+
14511482static int __arch_prepare_bpf_trampoline (struct jit_ctx * ctx , struct bpf_tramp_image * im ,
14521483 const struct btf_func_model * m , struct bpf_tramp_links * tlinks ,
14531484 void * func_addr , u32 flags )
@@ -1655,8 +1686,12 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
16551686 restore_args (ctx , m -> nr_args , args_off );
16561687
16571688 if (save_ret ) {
1658- emit_insn (ctx , ldd , LOONGARCH_GPR_A0 , LOONGARCH_GPR_FP , - retval_off );
16591689 emit_insn (ctx , ldd , regmap [BPF_REG_0 ], LOONGARCH_GPR_FP , - (retval_off - 8 ));
1690+ if (is_struct_ops )
1691+ sign_extend (ctx , LOONGARCH_GPR_A0 , regmap [BPF_REG_0 ],
1692+ m -> ret_size , m -> ret_flags & BTF_FMODEL_SIGNED_ARG );
1693+ else
1694+ emit_insn (ctx , ldd , LOONGARCH_GPR_A0 , LOONGARCH_GPR_FP , - retval_off );
16601695 }
16611696
16621697 emit_insn (ctx , ldd , LOONGARCH_GPR_S1 , LOONGARCH_GPR_FP , - sreg_off );
0 commit comments