* [PATCH bpf-next v3 1/2] bpf: Print breakdown of insns processed by subprogs
@ 2026-04-30 8:44 Paul Chaignon
2026-04-30 8:45 ` [PATCH bpf-next v3 2/2] selftests/bpf: Test insns processed breakdown Paul Chaignon
2026-04-30 11:30 ` [PATCH bpf-next v3 1/2] bpf: Print breakdown of insns processed by subprogs patchwork-bot+netdevbpf
0 siblings, 2 replies; 3+ messages in thread
From: Paul Chaignon @ 2026-04-30 8:44 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi
When using global functions (i.e. subprogs), the verifier performs
function-by-function verification. In that case, the sum of the
instructions processed in each global function and in the main program
counts towards the 1 million instructions limit. Only that sum is
reported in the verifier logs.
While starting to use global functions in Cilium (finally!), we found it
can be useful to have the breakdown per global function, to understand
exactly where the budget is currently spent. This patch implements this
breakdown, under BPF_LOG_STATS, as done for the stack depths.
When iterating over subprogs, we need to skip the hidden subprogs at the
end because they don't have a corresponding func_info_aux entry and
calling bpf_subprog_is_global() would result in an OOB access.
Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
---
Changes in v3:
- Skip hidden subprogs when displaying stack depths and insns counts.
Changes in v2:
- None for this patch.
include/linux/bpf_verifier.h | 1 +
kernel/bpf/verifier.c | 25 ++++++++++++++++---------
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 101ca6cc5424..976e2b2f40e8 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -779,6 +779,7 @@ struct bpf_subprog_info {
u32 exit_idx; /* Index of one of the BPF_EXIT instructions in this subprogram */
u16 stack_depth; /* max. stack depth used by this function */
u16 stack_extra;
+ u32 insn_processed;
/* offsets in range [stack_depth .. fastcall_stack_off)
* are used for bpf_fastcall spills and fills.
*/
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 03f9e16c2abe..11054ad89c14 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -18215,6 +18215,7 @@ static int do_check_subprogs(struct bpf_verifier_env *env)
struct bpf_prog_aux *aux = env->prog->aux;
struct bpf_func_info_aux *sub_aux;
int i, ret, new_cnt;
+ u32 insn_processed;
if (!aux->func_info)
return 0;
@@ -18229,6 +18230,8 @@ static int do_check_subprogs(struct bpf_verifier_env *env)
if (!bpf_subprog_is_global(env, i))
continue;
+ insn_processed = env->insn_processed;
+
sub_aux = subprog_aux(env, i);
if (!sub_aux->called || sub_aux->verified)
continue;
@@ -18236,6 +18239,7 @@ static int do_check_subprogs(struct bpf_verifier_env *env)
env->insn_idx = env->subprog_info[i].start;
WARN_ON_ONCE(env->insn_idx == 0);
ret = do_check_common(env, i);
+ env->subprog_info[i].insn_processed = env->insn_processed - insn_processed;
if (ret) {
return ret;
} else if (env->log.level & BPF_LOG_LEVEL) {
@@ -18262,10 +18266,12 @@ static int do_check_subprogs(struct bpf_verifier_env *env)
static int do_check_main(struct bpf_verifier_env *env)
{
+ u32 insn_processed = env->insn_processed;
int ret;
env->insn_idx = 0;
ret = do_check_common(env, 0);
+ env->subprog_info[0].insn_processed = env->insn_processed - insn_processed;
if (!ret)
env->prog->aux->stack_depth = env->subprog_info[0].stack_depth;
return ret;
@@ -18274,19 +18280,20 @@ static int do_check_main(struct bpf_verifier_env *env)
static void print_verification_stats(struct bpf_verifier_env *env)
{
- int i;
+ /* Skip over hidden subprogs which are not verified. */
+ int i, subprog_cnt = env->subprog_cnt - env->hidden_subprog_cnt;
if (env->log.level & BPF_LOG_STATS) {
verbose(env, "verification time %lld usec\n",
div_u64(env->verification_time, 1000));
- verbose(env, "stack depth ");
- for (i = 0; i < env->subprog_cnt; i++) {
- u32 depth = env->subprog_info[i].stack_depth;
-
- verbose(env, "%d", depth);
- if (i + 1 < env->subprog_cnt)
- verbose(env, "+");
- }
+ verbose(env, "stack depth %d", env->subprog_info[0].stack_depth);
+ for (i = 1; i < subprog_cnt; i++)
+ verbose(env, "+%d", env->subprog_info[i].stack_depth);
+ verbose(env, "\n");
+ verbose(env, "insns processed %d", env->subprog_info[0].insn_processed);
+ for (i = 1; i < subprog_cnt; i++)
+ if (bpf_subprog_is_global(env, i))
+ verbose(env, "+%d", env->subprog_info[i].insn_processed);
verbose(env, "\n");
}
verbose(env, "processed %d insns (limit %d) max_states_per_insn %d "
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH bpf-next v3 2/2] selftests/bpf: Test insns processed breakdown
2026-04-30 8:44 [PATCH bpf-next v3 1/2] bpf: Print breakdown of insns processed by subprogs Paul Chaignon
@ 2026-04-30 8:45 ` Paul Chaignon
2026-04-30 11:30 ` [PATCH bpf-next v3 1/2] bpf: Print breakdown of insns processed by subprogs patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: Paul Chaignon @ 2026-04-30 8:45 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi
This patch covers in global subprog selftests the new verifier log with
the breakdown of instructions processed by global subprogs. The test
ensures the log line is present and that it has the right number of
subcounts.
Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
---
Changes in v3:
- Limit testing to one program and use a regex to prevent failures
across compiler versions.
Changes in v2:
- Adapted the tests to pass on cpu=v4 and alu32.
tools/testing/selftests/bpf/progs/verifier_global_subprogs.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c b/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c
index 1e08aff7532e..dc09d0e2d8ad 100644
--- a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c
+++ b/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c
@@ -46,12 +46,13 @@ __noinline long global_dead(void)
}
SEC("?raw_tp")
-__success __log_level(2)
+__success __log_level(6)
/* main prog is validated completely first */
__msg("('global_calls_good_only') is global and assumed valid.")
/* eventually global_good() is transitively validated as well */
__msg("Validating global_good() func")
__msg("('global_good') is safe for any args that match its prototype")
+__msg("insns processed {{[0-9]+\\+[0-9]+\\+[0-9]+$}}")
int chained_global_func_calls_success(void)
{
int sum = 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH bpf-next v3 1/2] bpf: Print breakdown of insns processed by subprogs
2026-04-30 8:44 [PATCH bpf-next v3 1/2] bpf: Print breakdown of insns processed by subprogs Paul Chaignon
2026-04-30 8:45 ` [PATCH bpf-next v3 2/2] selftests/bpf: Test insns processed breakdown Paul Chaignon
@ 2026-04-30 11:30 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-04-30 11:30 UTC (permalink / raw)
To: Paul Chaignon; +Cc: bpf, ast, daniel, andrii, eddyz87, memxor
Hello:
This series was applied to bpf/bpf-next.git (master)
by Kumar Kartikeya Dwivedi <memxor@gmail.com>:
On Thu, 30 Apr 2026 10:44:28 +0200 you wrote:
> When using global functions (i.e. subprogs), the verifier performs
> function-by-function verification. In that case, the sum of the
> instructions processed in each global function and in the main program
> counts towards the 1 million instructions limit. Only that sum is
> reported in the verifier logs.
>
> While starting to use global functions in Cilium (finally!), we found it
> can be useful to have the breakdown per global function, to understand
> exactly where the budget is currently spent. This patch implements this
> breakdown, under BPF_LOG_STATS, as done for the stack depths.
>
> [...]
Here is the summary with links:
- [bpf-next,v3,1/2] bpf: Print breakdown of insns processed by subprogs
https://git.kernel.org/bpf/bpf-next/c/f603e84ab791
- [bpf-next,v3,2/2] selftests/bpf: Test insns processed breakdown
https://git.kernel.org/bpf/bpf-next/c/2ca6723a5f7b
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-04-30 11:30 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-30 8:44 [PATCH bpf-next v3 1/2] bpf: Print breakdown of insns processed by subprogs Paul Chaignon
2026-04-30 8:45 ` [PATCH bpf-next v3 2/2] selftests/bpf: Test insns processed breakdown Paul Chaignon
2026-04-30 11:30 ` [PATCH bpf-next v3 1/2] bpf: Print breakdown of insns processed by subprogs patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox