[PATCH bpf-next v2 10/22] bpf: Batch the patches of bpf_opt_subreg_zext_lo32_rnd_hi32()
From: Qiliang Yuan
Date: Fri Oct 30 2026 - 07:59:38 EST
bpf_opt_subreg_zext_lo32_rnd_hi32() inserts a zero extension, or with
BPF_F_TEST_RND_HI32 a randomization of the upper half, after every
instruction that needs it, one bpf_patch_insn_data() at a time.
Each of them costs O(prog->len). Loading pyperf180 with
BPF_F_TEST_RND_HI32 does 4610 of them, which takes more than twice as
long as loading it without.
Queue them with bpf_patch_list_add() and commit them at the end of the
pass.
perf stat -r10 of loading with BPF_F_TEST_RND_HI32, average of two
runs, x86_64 VM with 32 vCPUs, before and after this patch:
before after
pyperf180 1.507 s 0.359 s
pyperf600 4.533 s 0.899 s
Signed-off-by: Qiliang Yuan <odys.yuan@xxxxxxxxx>
---
kernel/bpf/fixups.c | 22 ++++++++--------------
1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c
index 7c7c38eb9f0c2..6c2dce8f3b6eb 100644
--- a/kernel/bpf/fixups.c
+++ b/kernel/bpf/fixups.c
@@ -922,9 +922,8 @@ int bpf_opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env,
struct bpf_insn *zext_patch = env->insn_buf;
struct bpf_insn *rnd_hi32_patch = &env->insn_buf[2];
struct bpf_insn_aux_data *aux = env->insn_aux_data;
- int i, patch_len, delta = 0, len = env->prog->len;
+ int i, patch_len, len = env->prog->len;
struct bpf_insn *insns = env->prog->insnsi;
- struct bpf_prog *new_prog;
bool rnd_hi32;
rnd_hi32 = attr->prog_flags & BPF_F_TEST_RND_HI32;
@@ -933,13 +932,12 @@ int bpf_opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env,
rnd_hi32_patch[2] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_AX, 32);
rnd_hi32_patch[3] = BPF_ALU64_REG(BPF_OR, 0, BPF_REG_AX);
for (i = 0; i < len; i++) {
- int adj_idx = i + delta;
struct bpf_insn insn;
int load_reg;
- insn = insns[adj_idx];
+ insn = insns[i];
load_reg = insn_def_regno(&insn);
- if (!aux[adj_idx].zext_dst) {
+ if (!aux[i].zext_dst) {
u8 code, class;
u32 imm_rnd;
@@ -960,7 +958,7 @@ int bpf_opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env,
/* ctx load could be transformed into wider load. */
if (class == BPF_LDX &&
- aux[adj_idx].ptr_type == PTR_TO_CTX)
+ aux[i].ptr_type == PTR_TO_CTX)
continue;
imm_rnd = get_random_u32();
@@ -999,16 +997,12 @@ int bpf_opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env,
patch = zext_patch;
patch_len = 2;
apply_patch_buffer:
- new_prog = bpf_patch_insn_data(env, adj_idx, patch, patch_len);
- if (!new_prog)
- return -ENOMEM;
- env->prog = new_prog;
- insns = new_prog->insnsi;
- aux = env->insn_aux_data;
- delta += patch_len - 1;
+ patch = bpf_patch_list_add(env, i, patch, patch_len);
+ if (IS_ERR(patch))
+ return PTR_ERR(patch);
}
- return 0;
+ return bpf_patch_list_commit(env);
}
/*
--
2.43.0