Re: [PATCH v2 2/3] LoongArch: BPF: Sign extend struct ops return values properly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Aug 28, 2025 at 2:11 PM Jinyang He <hejinyang@xxxxxxxxxxx> wrote:
>
> On 2025-08-27 17:47, Hengqi Chen wrote:
>
> > The ns_bpf_qdisc selftest triggers a kernel panic:
> >
> >      CPU 0 Unable to handle kernel paging request at virtual address 0000000000741d58, era == 90000000851b5ac0, ra == 90000000851b5aa4
> >      Oops[#1]:
> >      CPU: 0 UID: 0 PID: 449 Comm: test_progs Tainted: G           OE       6.16.0+ #3 PREEMPT(full)
> >      Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
> >      Hardware name: QEMU QEMU Virtual Machine, BIOS unknown 2/2/2022
> >      pc 90000000851b5ac0 ra 90000000851b5aa4 tp 90000001076b8000 sp 90000001076bb600
> >      a0 0000000000741ce8 a1 0000000000000001 a2 90000001076bb5c0 a3 0000000000000008
> >      a4 90000001004c4620 a5 9000000100741ce8 a6 0000000000000000 a7 0100000000000000
> >      t0 0000000000000010 t1 0000000000000000 t2 9000000104d24d30 t3 0000000000000001
> >      t4 4f2317da8a7e08c4 t5 fffffefffc002f00 t6 90000001004c4620 t7 ffffffffc61c5b3d
> >      t8 0000000000000000 u0 0000000000000001 s9 0000000000000050 s0 90000001075bc800
> >      s1 0000000000000040 s2 900000010597c400 s3 0000000000000008 s4 90000001075bc880
> >      s5 90000001075bc8f0 s6 0000000000000000 s7 0000000000741ce8 s8 0000000000000000
> >         ra: 90000000851b5aa4 __qdisc_run+0xac/0x8d8
> >        ERA: 90000000851b5ac0 __qdisc_run+0xc8/0x8d8
> >       CRMD: 000000b0 (PLV0 -IE -DA +PG DACF=CC DACM=CC -WE)
> >       PRMD: 00000004 (PPLV0 +PIE -PWE)
> >       EUEN: 00000007 (+FPE +SXE +ASXE -BTE)
> >       ECFG: 00071c1d (LIE=0,2-4,10-12 VS=7)
> >      ESTAT: 00010000 [PIL] (IS= ECode=1 EsubCode=0)
> >       BADV: 0000000000741d58
> >       PRID: 0014c010 (Loongson-64bit, Loongson-3A5000)
> >      Modules linked in: bpf_testmod(OE) [last unloaded: bpf_testmod(OE)]
> >      Process test_progs (pid: 449, threadinfo=000000009af02b3a, task=00000000e9ba4956)
> >      Stack : 0000000000000000 90000001075bc8ac 90000000869524a8 9000000100741ce8
> >              90000001075bc800 9000000100415300 90000001075bc8ac 0000000000000000
> >              900000010597c400 900000008694a000 0000000000000000 9000000105b59000
> >              90000001075bc800 9000000100741ce8 0000000000000050 900000008513000c
> >              9000000086936000 0000000100094d4c fffffff400676208 0000000000000000
> >              9000000105b59000 900000008694a000 9000000086bf0dc0 9000000105b59000
> >              9000000086bf0d68 9000000085147010 90000001075be788 0000000000000000
> >              9000000086bf0f98 0000000000000001 0000000000000010 9000000006015840
> >              0000000000000000 9000000086be6c40 0000000000000000 0000000000000000
> >              0000000000000000 4f2317da8a7e08c4 0000000000000101 4f2317da8a7e08c4
> >              ...
> >      Call Trace:
> >      [<90000000851b5ac0>] __qdisc_run+0xc8/0x8d8
> >      [<9000000085130008>] __dev_queue_xmit+0x578/0x10f0
> >      [<90000000853701c0>] ip6_finish_output2+0x2f0/0x950
> >      [<9000000085374bc8>] ip6_finish_output+0x2b8/0x448
> >      [<9000000085370b24>] ip6_xmit+0x304/0x858
> >      [<90000000853c4438>] inet6_csk_xmit+0x100/0x170
> >      [<90000000852b32f0>] __tcp_transmit_skb+0x490/0xdd0
> >      [<90000000852b47fc>] tcp_connect+0xbcc/0x1168
> >      [<90000000853b9088>] tcp_v6_connect+0x580/0x8a0
> >      [<90000000852e7738>] __inet_stream_connect+0x170/0x480
> >      [<90000000852e7a98>] inet_stream_connect+0x50/0x88
> >      [<90000000850f2814>] __sys_connect+0xe4/0x110
> >      [<90000000850f2858>] sys_connect+0x18/0x28
> >      [<9000000085520c94>] do_syscall+0x94/0x1a0
> >      [<9000000083df1fb8>] handle_syscall+0xb8/0x158
> >
> >      Code: 4001ad80  2400873f  2400832d <240073cc> 001137ff  001133ff  6407b41f  001503cc  0280041d
> >
> >      ---[ end trace 0000000000000000 ]---
> >
> > The bpf_fifo_dequeue prog returns a skb which is a pointer.
> > The pointer is treated as a 32bit value and sign extend to
> > 64bit in epilogue. This behavior is right for most bpf prog
> > types but wrong for struct ops which requires LoongArch ABI.
> >
> > So let's sign extend struct ops return values according to
> > the return value spec in function model.
> >
> > Fixes: 6abf17d690d8 ("LoongArch: BPF: Add struct ops support for trampoline")
> > Tested-by: Tiezhu Yang <yangtiezhu@xxxxxxxxxxx>
> > Tested-by: Vincent Li <vincent.mc.li@xxxxxxxxx>
> > Signed-off-by: Hengqi Chen <hengqi.chen@xxxxxxxxx>
> > ---
> >   arch/loongarch/net/bpf_jit.c | 26 ++++++++++++++++++++++++++
> >   1 file changed, 26 insertions(+)
> >
> > diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
> > index b646c6b73014..c239e5ed0c92 100644
> > --- a/arch/loongarch/net/bpf_jit.c
> > +++ b/arch/loongarch/net/bpf_jit.c
> > @@ -1448,6 +1448,28 @@ void arch_free_bpf_trampoline(void *image, unsigned int size)
> >       bpf_prog_pack_free(image, size);
> >   }
> >
> > +/*
> > + * Sign-extend the register if necessary
> > + */
> > +static void sign_extend(struct jit_ctx *ctx, int r, u8 size)
> > +{
> > +     switch (size) {
> > +     case 1:
> > +             emit_insn(ctx, extwb, r, r);
> > +             break;
> > +     case 2:
> > +             emit_insn(ctx, extwh, r, r);
> > +             break;
> > +     case 4:
> > +             emit_insn(ctx, addiw, r, r, 0);
> > +             break;
> > +     case 8:
> > +             break;
> > +     default:
> > +             pr_warn("bpf_jit: invalid size %d for sign_extend\n", size);
> > +     }
> > +}
> > +
> >   static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
> >                                        const struct btf_func_model *m, struct bpf_tramp_links *tlinks,
> >                                        void *func_addr, u32 flags)
> > @@ -1654,6 +1676,10 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
> >       if (save_ret) {
> >               emit_insn(ctx, ldd, LOONGARCH_GPR_A0, LOONGARCH_GPR_FP, -retval_off);
> >               emit_insn(ctx, ldd, regmap[BPF_REG_0], LOONGARCH_GPR_FP, -(retval_off - 8));
> > +             if (is_struct_ops) {
> > +                     move_reg(ctx, LOONGARCH_GPR_A0, regmap[BPF_REG_0]);
> > +                     sign_extend(ctx, LOONGARCH_GPR_A0, m->ret_size);
> > +             }
> >       }
> Hi, Hengqi,
>
> It can be did same as Tiezhu's patch, named "LoongArch: BPF: Optimize
> sign-extention mov instructions", which use only one sign-extend
> instruction.
>
> And btw, how about,
> if (save_ret) {
>    if (is_struct_ops) {
>      ld.{d,w,h,b} LOONGARCH_GPR_A0, LOONGARCH_GPR_FP, -(retval_off - 8)
>      emit_insn(ctx, ldd, regmap[BPF_REG_0], LOONGARCH_GPR_FP,
> -(retval_off - 8)); // I don't know is it needed.
>    } else {
>      emit_insn(ctx, ldd, LOONGARCH_GPR_A0, LOONGARCH_GPR_FP, -retval_off);
>      emit_insn(ctx, ldd, regmap[BPF_REG_0], LOONGARCH_GPR_FP,
> -(retval_off - 8));
>    }

Hmm, how about:

static void sign_extend(struct jit_ctx *ctx, int rd, int rj, u8 size)

and sign extend regmap[BPF_REG_0] to LOONGARCH_GPR_A0

> }
> >
> >       emit_insn(ctx, ldd, LOONGARCH_GPR_S1, LOONGARCH_GPR_FP, -sreg_off);
>





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux