LoongArch: BPF: Sign-extend struct ops return values properly
The ns_bpf_qdisc selftest triggers a kernel panic:
Oops[#1]:
CPU 0 Unable to handle kernel paging request at virtual address
0000000000741d58, era ==
90000000851b5ac0, ra ==
90000000851b5aa4
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 LoongArch
ABI ([1]) and return value spec in function model.
[1]: https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html
Cc: stable@vger.kernel.org
Fixes: 6abf17d690d8 ("LoongArch: BPF: Add struct ops support for trampoline")
Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>