+++ /dev/null
-From 3f5a238f24d7b75f9efe324d3539ad388f58536e Mon Sep 17 00:00:00 2001
-From: Hengqi Chen <hengqi.chen@gmail.com>
-Date: Wed, 31 Dec 2025 15:19:20 +0800
-Subject: LoongArch: BPF: Sign extend kfunc call arguments
-
-From: Hengqi Chen <hengqi.chen@gmail.com>
-
-commit 3f5a238f24d7b75f9efe324d3539ad388f58536e upstream.
-
-The kfunc calls are native calls so they should follow LoongArch calling
-conventions. Sign extend its arguments properly to avoid kernel panic.
-This is done by adding a new emit_abi_ext() helper. The emit_abi_ext()
-helper performs extension in place meaning a value already store in the
-target register (Note: this is different from the existing sign_extend()
-helper and thus we can't reuse it).
-
-Cc: stable@vger.kernel.org
-Fixes: 5dc615520c4d ("LoongArch: Add BPF JIT support")
-Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
-Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- arch/loongarch/net/bpf_jit.c | 16 ++++++++++++++++
- arch/loongarch/net/bpf_jit.h | 26 ++++++++++++++++++++++++++
- 2 files changed, 42 insertions(+)
-
---- a/arch/loongarch/net/bpf_jit.c
-+++ b/arch/loongarch/net/bpf_jit.c
-@@ -773,6 +773,22 @@ static int build_insn(const struct bpf_i
- if (ret < 0)
- return ret;
-
-+ if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
-+ const struct btf_func_model *m;
-+ int i;
-+
-+ m = bpf_jit_find_kfunc_model(ctx->prog, insn);
-+ if (!m)
-+ return -EINVAL;
-+
-+ for (i = 0; i < m->nr_args; i++) {
-+ u8 reg = regmap[BPF_REG_1 + i];
-+ bool sign = m->arg_flags[i] & BTF_FMODEL_SIGNED_ARG;
-+
-+ emit_abi_ext(ctx, reg, m->arg_size[i], sign);
-+ }
-+ }
-+
- move_addr(ctx, t1, func_addr);
- emit_insn(ctx, jirl, t1, LOONGARCH_GPR_RA, 0);
- move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_A0);
---- a/arch/loongarch/net/bpf_jit.h
-+++ b/arch/loongarch/net/bpf_jit.h
-@@ -80,6 +80,32 @@ static inline void emit_sext_32(struct j
- emit_insn(ctx, addiw, reg, reg, 0);
- }
-
-+/* Emit proper extension according to ABI requirements.
-+ * Note that it requires a value of size `size` already resides in register `reg`.
-+ */
-+static inline void emit_abi_ext(struct jit_ctx *ctx, int reg, u8 size, bool sign)
-+{
-+ /* ABI requires unsigned char/short to be zero-extended */
-+ if (!sign && (size == 1 || size == 2))
-+ return;
-+
-+ switch (size) {
-+ case 1:
-+ emit_insn(ctx, extwb, reg, reg);
-+ break;
-+ case 2:
-+ emit_insn(ctx, extwh, reg, reg);
-+ break;
-+ case 4:
-+ emit_insn(ctx, addiw, reg, reg, 0);
-+ break;
-+ case 8:
-+ break;
-+ default:
-+ pr_warn("bpf_jit: invalid size %d for extension\n", size);
-+ }
-+}
-+
- static inline void move_addr(struct jit_ctx *ctx, enum loongarch_gpr rd, u64 addr)
- {
- u64 imm_11_0, imm_31_12, imm_51_32, imm_63_52;