bpf, arm64/riscv: Remove redundant icache flush after pack allocator finalize
Subsystems (6)
Puranjay Mohan
maintainerv2 cover bpf, arm64/riscv: Remove redundant icache flush after pack allocator finalize
Changelog:
v1: https://lore.kernel.org/all/[email protected]/
Changes in v2:
- Remove "#include <asm/cacheflush.h>" as it is not needed now.
- Add Acked-by: Song Liu <[email protected]>
When the BPF prog pack allocator was added for arm64 and riscv, the existing bpf_flush_icache() calls were retained after bpf_jit_binary_pack_finalize(). However, the finalize path copies the JITed code via architecture text patching routines (__text_poke on arm64, patch_text_nosync on riscv) that already perform a full flush_icache_range() internally. The subsequent bpf_flush_icache() repeats the same cache maintenance on the same range.
Remove the redundant flush and the now-unused bpf_flush_icache() definitions on both architectures.
Puranjay Mohan (2):
bpf, arm64: Remove redundant bpf_flush_icache() after pack allocator
finalize
bpf, riscv: Remove redundant bpf_flush_icache() after pack allocator
finalize
arch/arm64/net/bpf_jit_comp.c | 12 ------------ arch/riscv/net/bpf_jit.h | 6 ------ arch/riscv/net/bpf_jit_core.c | 7 ------- 3 files changed, 25 deletions(-)
base-commit: 71b500afd2f7336f5b6c6026f2af546fc079be26
Signature · 1 line
2.52.0
Puranjay Mohan
maintainerPATCH v2 1/2 bpf, arm64: Remove redundant bpf_flush_icache() after pack allocator finalize
bpf_flush_icache() calls flush_icache_range() to clean the data cache and invalidate the instruction cache for the JITed code region. However, since commit 1dad391daef1 ("bpf, arm64: use bpf_prog_pack for memory management"), this flush is redundant.
bpf_jit_binary_pack_finalize() copies the JITed instructions to the ROX region via bpf_arch_text_copy() -> aarch64_insn_copy() -> __text_poke(), and __text_poke() already calls flush_icache_range() on the written range. The subsequent bpf_flush_icache() repeats the same cache maintenance on an overlapping range, including an unnecessary second synchronous IPI to all CPUs via kick_all_cpus_sync().
Remove the redundant bpf_flush_icache() call and its now-unused definition.
--- arch/arm64/net/bpf_jit_comp.c | 12 ------------ 1 file changed, 12 deletions(-)
arch/arm64/net/bpf_jit_comp.c +0 -12
@@ -18,7 +18,6 @@#include <asm/asm-extable.h> #include <asm/byteorder.h> -#include <asm/cacheflush.h> #include <asm/cpufeature.h> #include <asm/debug-monitors.h> #include <asm/insn.h>
@@ -1961,11 +1960,6 @@ static int validate_ctx(struct jit_ctx *ctx)return 0 ; } -static inline void bpf_flush_icache (void *start,void *end) -{ -flush_icache_range ((unsigned long )start, (unsigned long )end); -} -static void priv_stack_init_guard (void __percpu *priv_stack_ptr,int alloc_size) {int cpu, underflow_idx = (alloc_size -PRIV_STACK_GUARD_SZ ) >>3 ;
@@ -2204,12 +2198,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = orig_prog; goto out_off; } -/* -* The instructions have now been copied to the ROX region from -* where they will execute. Now the data cache has to be cleaned to -* the PoU and the I-cache has to be invalidated for the VAs. -*/ -bpf_flush_icache (ro_header, ctx.ro_image + ctx.idx); }else { jit_data->ctx = ctx; jit_data->ro_image = ro_image_ptr;
Signature · 1 line
2.52.0
Xu Kuohai
reviewerRe: [PATCH bpf-next v2 1/2] bpf, arm64: Remove redundant bpf_flush_icache() after pack allocator finalize
Quoted 5 lines · Puranjay Mohan
bpf_flush_icache()callsflush_icache_range()to clean the data cache and invalidate the instruction cache for the JITed code region. However, since commit1dad391daef1("bpf, arm64: usebpf_prog_packfor memory management"), this flush is redundant.
Quoted 7 lines
bpf_jit_binary_pack_finalize()copies the JITed instructions to the ROX region viabpf_arch_text_copy()->aarch64_insn_copy()->__text_poke(), and__text_poke()already callsflush_icache_range()on the written range. The subsequentbpf_flush_icache()repeats the same cache maintenance on an overlapping range, including an unnecessary second synchronous IPI to all CPUs viakick_all_cpus_sync().
So icache is flushed twice: once per instruction and again after all instructions are copied. I think it's better to remove the per-instruction flush and retain the single final flush to avoid repeating flush overhead for each instruction.
Quoted 47 lines
Remove the redundant
bpf_flush_icache()call and its now-unused definition.Fixes 1dad391daef1 ("bpf, arm64: use bpf_prog_pack for memory management")Acked-by Song Liu <[email protected]>Signed-off-by Puranjay Mohan <[email protected]>--- arch/arm64/net/bpf_jit_comp.c | 12 ------------ 1 file changed, 12 deletions(-)arch/arm64/net/bpf_jit_comp.c +0
-12@@ -18,7 +18,6 @@#include <asm/asm-extable.h> #include <asm/byteorder.h> -#include <asm/cacheflush.h> #include <asm/cpufeature.h> #include <asm/debug-monitors.h> #include <asm/insn.h> @@ -1961,11 +1960,6 @@ static int validate_ctx(struct jit_ctx *ctx)return 0 ; } -static inline void bpf_flush_icache (void *start,void *end) -{ -flush_icache_range ((unsigned long )start, (unsigned long )end); -} -static void priv_stack_init_guard (void __percpu *priv_stack_ptr,int alloc_size) {int cpu, underflow_idx = (alloc_size -PRIV_STACK_GUARD_SZ ) >>3 ;@@ -2204,12 +2198,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = orig_prog; goto out_off; } -/* -* The instructions have now been copied to the ROX region from -* where they will execute. Now the data cache has to be cleaned to -* the PoU and the I-cache has to be invalidated for the VAs. -*/ -bpf_flush_icache (ro_header, ctx.ro_image + ctx.idx); }else { jit_data->ctx = ctx; jit_data->ro_image = ro_image_ptr;
Re: [PATCH bpf-next v2 1/2] bpf, arm64: Remove redundant bpf_flush_icache() after pack allocator finalize
Quoted 15 lines · Xu Kuohai
Quoted 5 lines · Puranjay Mohan
bpf_flush_icache()callsflush_icache_range()to clean the data cache and invalidate the instruction cache for the JITed code region. However, since commit1dad391daef1("bpf, arm64: usebpf_prog_packfor memory management"), this flush is redundant.Quoted 7 lines
bpf_jit_binary_pack_finalize()copies the JITed instructions to the ROX region viabpf_arch_text_copy()->aarch64_insn_copy()->__text_poke(), and__text_poke()already callsflush_icache_range()on the written range. The subsequentbpf_flush_icache()repeats the same cache maintenance on an overlapping range, including an unnecessary second synchronous IPI to all CPUs viakick_all_cpus_sync().
Quoted 4 lines
So icache is flushed twice: once per instruction and again after all instructions are copied. I think it's better to remove the per-instruction flush and retain the single final flush to avoid repeating flush overhead for each instruction.
No, bpf_jit_binary_pack_finalize() is called at the end after the whole program is jited, and it calls: bpf_arch_text_copy(ro_header, rw_header, rw_header->size); which does aarch64_insn_copy(dst, src, len), this calls __text_poke() which copies the whole program and then does flush_icache_range((uintptr_t)addr, (uintptr_t)addr + len); once. This is correct, after this we don't need to call flush_icache_range() on the same range again.
If we had been calling flush_icache_range() for each instruction, the system would hang due to the storm of IPIs.
Xu Kuohai
reviewerRe: [PATCH bpf-next v2 1/2] bpf, arm64: Remove redundant bpf_flush_icache() after pack allocator finalize
Quoted 29 lines · Puranjay Mohan
Quoted 15 lines · Xu Kuohai
Quoted 5 lines · Puranjay Mohan
bpf_flush_icache()callsflush_icache_range()to clean the data cache and invalidate the instruction cache for the JITed code region. However, since commit1dad391daef1("bpf, arm64: usebpf_prog_packfor memory management"), this flush is redundant.Quoted 7 lines
bpf_jit_binary_pack_finalize()copies the JITed instructions to the ROX region viabpf_arch_text_copy()->aarch64_insn_copy()->__text_poke(), and__text_poke()already callsflush_icache_range()on the written range. The subsequentbpf_flush_icache()repeats the same cache maintenance on an overlapping range, including an unnecessary second synchronous IPI to all CPUs viakick_all_cpus_sync().Quoted 4 lines
So icache is flushed twice: once per instruction and again after all instructions are copied. I think it's better to remove the per-instruction flush and retain the single final flush to avoid repeating flush overhead for each instruction.
No,
bpf_jit_binary_pack_finalize()is called at the end after the whole program is jited, and it calls:bpf_arch_text_copy(ro_header, rw_header, rw_header->size); which doesaarch64_insn_copy(dst, src, len), this calls__text_poke()which copies the whole program and then doesflush_icache_range((uintptr_t)addr, (uintptr_t)addr + len); once. This is correct, after this we don't need to callflush_icache_range()on the same range again.
Quoted 2 lines
If we had been calling
flush_icache_range()for each instruction, the system would hang due to the storm of IPIs.
Right, thanks for the explanation!
LGTM.
Re: [PATCH bpf-next v2 1/2] bpf, arm64: Remove redundant bpf_flush_icache() after pack allocator finalize
In reply to Puranjay MohanQuoted 12 lines · Puranjay Mohan
bpf_flush_icache()callsflush_icache_range()to clean the data cache and invalidate the instruction cache for the JITed code region. However, since commit1dad391daef1("bpf, arm64: usebpf_prog_packfor memory management"), this flush is redundant.
bpf_jit_binary_pack_finalize()copies the JITed instructions to the ROX region viabpf_arch_text_copy()->aarch64_insn_copy()->__text_poke(), and__text_poke()already callsflush_icache_range()on the written range. The subsequentbpf_flush_icache()repeats the same cache maintenance on an overlapping range, including an unnecessary second synchronous IPI to all CPUs viakick_all_cpus_sync().
Quoted 6 lines
Remove the redundant
bpf_flush_icache()call and its now-unused definition.Fixes 1dad391daef1 ("bpf, arm64: use bpf_prog_pack for memory management")Acked-by Song Liu <[email protected]>Signed-off-by Puranjay Mohan <[email protected]>
Puranjay Mohan
maintainerPATCH v2 2/2 bpf, riscv: Remove redundant bpf_flush_icache() after pack allocator finalize
In reply to Puranjay Mohanbpf_flush_icache() calls flush_icache_range() to clean the data cache and invalidate the instruction cache for the JITed code region. However, since commit 48a8f78c50bd ("bpf, riscv: use prog pack allocator in the BPF JIT"), this flush is redundant.
bpf_jit_binary_pack_finalize() copies the JITed instructions to the ROX region via bpf_arch_text_copy() -> patch_text_nosync(), and patch_text_nosync() already calls flush_icache_range() on the written range. The subsequent bpf_flush_icache() repeats the same cache maintenance on an overlapping range.
Remove the redundant bpf_flush_icache() call and its now-unused definition.
--- arch/riscv/net/bpf_jit.h | 6 ------ arch/riscv/net/bpf_jit_core.c | 7 ------- 2 files changed, 13 deletions(-)
arch/riscv/net/bpf_jit.h +0 -6
@@ -11,7 +11,6 @@#include <linux/bpf.h> #include <linux/filter.h> -#include <asm/cacheflush.h> /* verify runtime detection extension status */ #define rv_ext_enabled (ext) \
@@ -105,11 +104,6 @@ static inline void bpf_fill_ill_insns(void *area, unsigned int size)memset (area,0 , size); } -static inline void bpf_flush_icache (void *start,void *end) -{ -flush_icache_range ((unsigned long )start, (unsigned long )end); -} -/* Emit a 4-byte riscv instruction. */ static inline void emit (const u32 insn,struct rv_jit_context *ctx) {
arch/riscv/net/bpf_jit_core.c +0 -7
@@ -183,13 +183,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = orig_prog; goto out_offset; } -/* -* The instructions have now been copied to the ROX region from -* where they will execute. -* Write any modified data cache blocks out to memory and -* invalidate the corresponding blocks in the instruction cache. -*/ -bpf_flush_icache (jit_data->ro_header, ctx->ro_insns + ctx->ninsns);for (i =0 ; i < prog->len; i++) ctx->offset[i] =ninsns_rvoff (ctx->offset[i]);bpf_prog_fill_jited_linfo (prog, ctx->offset);
Signature · 1 line
2.52.0
Re: [PATCH bpf-next v2 2/2] bpf, riscv: Remove redundant bpf_flush_icache() after pack allocator finalize
Quoted 54 lines · Puranjay Mohan
bpf_flush_icache()callsflush_icache_range()to clean the data cache and invalidate the instruction cache for the JITed code region. However, since commit48a8f78c50bd("bpf, riscv: use prog pack allocator in the BPF JIT"), this flush is redundant.
bpf_jit_binary_pack_finalize()copies the JITed instructions to the ROX region viabpf_arch_text_copy()->patch_text_nosync(), andpatch_text_nosync()already callsflush_icache_range()on the written range. The subsequentbpf_flush_icache()repeats the same cache maintenance on an overlapping range.Remove the redundant
bpf_flush_icache()call and its now-unused definition.Fixes 48a8f78c50bd ("bpf, riscv: use prog pack allocator in the BPF JIT")Acked-by Song Liu <[email protected]>Signed-off-by Puranjay Mohan <[email protected]>--- arch/riscv/net/bpf_jit.h | 6 ------ arch/riscv/net/bpf_jit_core.c | 7 ------- 2 files changed, 13 deletions(-)arch/riscv/net/bpf_jit.h +0
-6@@ -11,7 +11,6 @@#include <linux/bpf.h> #include <linux/filter.h> -#include <asm/cacheflush.h> /* verify runtime detection extension status */ #define rv_ext_enabled (ext) \@@ -105,11 +104,6 @@ static inline void bpf_fill_ill_insns(void *area, unsigned int size)memset (area,0 , size); } -static inline void bpf_flush_icache (void *start,void *end) -{ -flush_icache_range ((unsigned long )start, (unsigned long )end); -} -/* Emit a 4-byte riscv instruction. */ static inline void emit (const u32 insn,struct rv_jit_context *ctx) {arch/riscv/net/bpf_jit_core.c +0
-0@@ -183,13 +183,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = orig_prog; goto out_offset; }
arch/riscv/net/bpf_jit_core.c struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) · line 188
Quoted 10 lines
arch/riscv/net/bpf_jit_core.c +0
-7-/* -* The instructions have now been copied to the ROX region from -* where they will execute. -* Write any modified data cache blocks out to memory and -* invalidate the corresponding blocks in the instruction cache. -*/ -bpf_flush_icache (jit_data->ro_header, ctx->ro_insns + ctx->ninsns);for (i =0 ; i < prog->len; i++) ctx->offset[i] =ninsns_rvoff (ctx->offset[i]);bpf_prog_fill_jited_linfo (prog, ctx->offset);
Re: [PATCH bpf-next v2 2/2] bpf, riscv: Remove redundant bpf_flush_icache() after pack allocator finalize
In reply to Puranjay MohanQuoted 11 lines · Puranjay Mohan
bpf_flush_icache()callsflush_icache_range()to clean the data cache and invalidate the instruction cache for the JITed code region. However, since commit48a8f78c50bd("bpf, riscv: use prog pack allocator in the BPF JIT"), this flush is redundant.
bpf_jit_binary_pack_finalize()copies the JITed instructions to the ROX region viabpf_arch_text_copy()->patch_text_nosync(), andpatch_text_nosync()already callsflush_icache_range()on the written range. The subsequentbpf_flush_icache()repeats the same cache maintenance on an overlapping range.
Quoted 6 lines
Remove the redundant
bpf_flush_icache()call and its now-unused definition.Fixes 48a8f78c50bd ("bpf, riscv: use prog pack allocator in the BPF JIT")Acked-by Song Liu <[email protected]>Signed-off-by Puranjay Mohan <[email protected]>
[...]
This series was applied to bpf/bpf.git (master) by Alexei Starovoitov <[email protected]>:
Hello:
This series was applied to bpf/bpf.git (master)
by Alexei Starovoitov <[email protected]>:
Quoted 14 lines · On Mon, 13 Apr 2026 12:11:07 -0700 you wrote:
Changelog:
v1: https://lore.kernel.org/all/[email protected]/
Changes in v2:
- Remove "#include <asm/cacheflush.h>" as it is not needed now.
- Add Acked-by: Song Liu <[email protected]>When the BPF prog pack allocator was added for arm64 and riscv, the existing
bpf_flush_icache()calls were retained afterbpf_jit_binary_pack_finalize(). However, the finalize path copies the JITed code via architecture text patching routines (__text_pokeon arm64,patch_text_nosyncon riscv) that already perform a fullflush_icache_range()internally. The subsequentbpf_flush_icache()repeats the same cache maintenance on the same range.
Quoted 1 line
[...]
Here is the summary with links:
- [bpf-next,v2,1/2] bpf, arm64: Remove redundant bpf_flush_icache() after pack allocator finalize
https://git.kernel.org/bpf/bpf/c/42f18ae53011 - [bpf-next,v2,2/2] bpf, riscv: Remove redundant bpf_flush_icache() after pack allocator finalize https://git.kernel.org/bpf/bpf/c/46ee1342b887
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html
This series was applied to riscv/linux.git (fixes) by Alexei Starovoitov <[email protected]>:
Hello:
This series was applied to riscv/linux.git (fixes) by Alexei Starovoitov <[email protected]>:
Quoted 14 lines · On Mon, 13 Apr 2026 12:11:07 -0700 you wrote:
Changelog:
v1: https://lore.kernel.org/all/[email protected]/
Changes in v2:
- Remove "#include <asm/cacheflush.h>" as it is not needed now.
- Add Acked-by: Song Liu <[email protected]>When the BPF prog pack allocator was added for arm64 and riscv, the existing
bpf_flush_icache()calls were retained afterbpf_jit_binary_pack_finalize(). However, the finalize path copies the JITed code via architecture text patching routines (__text_pokeon arm64,patch_text_nosyncon riscv) that already perform a fullflush_icache_range()internally. The subsequentbpf_flush_icache()repeats the same cache maintenance on the same range.
Quoted 1 line
[...]
Here is the summary with links:
- [bpf-next,v2,1/2] bpf, arm64: Remove redundant bpf_flush_icache() after pack allocator finalize
https://git.kernel.org/riscv/c/42f18ae53011 - [bpf-next,v2,2/2] bpf, riscv: Remove redundant bpf_flush_icache() after pack allocator finalize https://git.kernel.org/riscv/c/46ee1342b887
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html