summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorYonghong Song <yonghong.song@linux.dev>2026-09-12 12:52:42 -0700
committerAlexei Starovoitov <ast@kernel.org>2026-09-12 20:54:18 -0700
commit1e6c598b02e72ddd62b4d4e0c05159794b8bddbf (patch)
tree9f1184954840ff19d1fc47fd7ee460e538d8c8a6 /include/linux
parentae6abae582b750418ae1b09d3b295c416c61e082 (diff)
downloadlinux-1e6c598b02e72ddd62b4d4e0c05159794b8bddbf.tar.gz
linux-1e6c598b02e72ddd62b4d4e0c05159794b8bddbf.zip
bpf: Prepare kfunc arguments for the JIT from an ABI description
The previous patch refuses a kfunc argument of more than one eightbyte. This patch allows up to 16 byte kfunc arguments. But different architectures have different ways to map the BPF calling convention (no gap, no backfill) to the native one. Rather than have each arch open-code where it wants an argument, describe the convention with a register count and four booleans, and let each arch set what applies to it: struct bpf_jit_arg_abi { u8 nr_arg_regs; bool even_reg_align; bool even_stack_align; bool split_at_boundary; bool backfill_after_stack; }; The four booleans are meant to cover x86-64, arm64, RISC-V LP64 and PowerPC64 ELFv2, although only x86-64 and arm64 fill the struct in here. bpf_jit_place_args() and bpf_jit_plan_arg_moves() use that description to work out where each argument belongs and which slots the JIT then has to move, to be used in the JIT later on. Signed-off-by: Yonghong Song <yonghong.song@linux.dev> Link: https://lore.kernel.org/r/20260912195242.989416-1-yonghong.song@linux.dev Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/bpf.h15
-rw-r--r--include/linux/bpf_verifier.h1
-rw-r--r--include/linux/filter.h32
3 files changed, 48 insertions, 0 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index d0066d744ceb..2a5fa346aada 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -993,6 +993,13 @@ static_assert(__BPF_RET_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);
*/
#define MAX_BPF_FUNC_REG_ARGS 5
+/* A by-value argument takes two eightbytes at most, so the maximum number of
+ * argument slots of any function is 2 * MAX_BPF_FUNC_ARGS. A local array may
+ * need that size for processing, although eventually the maximum slots will
+ * be capped at MAX_BPF_FUNC_ARGS.
+ */
+#define MAX_BPF_FUNC_ARG_SLOTS (2 * MAX_BPF_FUNC_ARGS)
+
/* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs
* to in-kernel helper functions and for adjusting imm32 field in BPF_CALL
* instructions after verifying
@@ -1210,6 +1217,9 @@ struct bpf_prog_offload {
u32 jited_len;
};
+/* The argument is aligned to 16 bytes. */
+#define BTF_FMODEL_ALIGN16_ARG BIT(0)
+
/* The argument is signed. */
#define BTF_FMODEL_SIGNED_ARG BIT(1)
@@ -1227,6 +1237,11 @@ struct btf_func_model {
u8 arg_flags[MAX_BPF_FUNC_ARGS];
};
+static inline u32 btf_func_model_arg_slots(const struct btf_func_model *m, u32 arg)
+{
+ return (m->arg_size[arg] + sizeof(u64) - 1) / sizeof(u64);
+}
+
/* Restore arguments before returning from trampoline to let original function
* continue executing. This flag is used for fentry progs when there are no
* fexit progs.
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 1b836c6d570f..cf85141ea167 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -1512,6 +1512,7 @@ enum btf_member_kind {
bool btf_struct_is_composed_of(struct bpf_verifier_env *env, const struct btf *btf,
const struct btf_type *t, u32 member_kinds);
+u32 btf_func_arg_align(const struct btf *btf, const struct btf_type *t);
int bpf_find_subprog(struct bpf_verifier_env *env, int off);
bool bpf_is_throw_kfunc(struct bpf_insn *insn);
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 00ad8b63aa47..b17222db2efc 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1248,6 +1248,38 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena);
bool bpf_jit_supports_private_stack(void);
bool bpf_jit_supports_timed_may_goto(void);
bool bpf_jit_supports_fsession(void);
+
+struct bpf_jit_arg_abi {
+ /* Argument registers of the kernel convention. */
+ u8 nr_arg_regs;
+ /* Round the register number up to an even one for 16-byte alignment. */
+ bool even_reg_align;
+ /* Round the stack slot up to an even one for 16-byte alignment. */
+ bool even_stack_align;
+ /* An argument may straddle the last register and the stack. */
+ bool split_at_boundary;
+ /* A later argument may reuse a register a stack-passed one skipped. */
+ bool backfill_after_stack;
+};
+
+const struct bpf_jit_arg_abi *bpf_jit_arg_abi(void);
+u32 bpf_jit_place_args(const struct bpf_jit_arg_abi *abi,
+ const struct btf_func_model *fm, u8 *pos_of_slot);
+
+/* The JIT's scratch register, in place of an argument slot. */
+#define BPF_JIT_ARG_TMP 0xff
+
+/* Every argument slot moves at most once, and the scratch goes out and back. */
+#define BPF_JIT_MAX_ARG_MOVES (MAX_BPF_FUNC_ARG_SLOTS + 2)
+
+struct bpf_jit_arg_move {
+ u8 dst;
+ u8 src;
+};
+
+u32 bpf_jit_plan_arg_moves(const struct bpf_jit_arg_abi *abi,
+ const struct btf_func_model *fm,
+ struct bpf_jit_arg_move *moves);
u64 bpf_arch_uaddress_limit(void);
void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie);
u64 arch_bpf_timed_may_goto(void);