@@ -1448,6 +1448,37 @@ void arch_free_bpf_trampoline(void *image, unsigned int size)
1448
1448
bpf_prog_pack_free (image , size );
1449
1449
}
1450
1450
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
+
1451
1482
static int __arch_prepare_bpf_trampoline (struct jit_ctx * ctx , struct bpf_tramp_image * im ,
1452
1483
const struct btf_func_model * m , struct bpf_tramp_links * tlinks ,
1453
1484
void * func_addr , u32 flags )
@@ -1655,8 +1686,12 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
1655
1686
restore_args (ctx , m -> nr_args , args_off );
1656
1687
1657
1688
if (save_ret ) {
1658
- emit_insn (ctx , ldd , LOONGARCH_GPR_A0 , LOONGARCH_GPR_FP , - retval_off );
1659
1689
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 );
1660
1695
}
1661
1696
1662
1697
emit_insn (ctx , ldd , LOONGARCH_GPR_S1 , LOONGARCH_GPR_FP , - sreg_off );
0 commit comments