Changes v8 => v9:
1. Fix an error with multi function program, in 4/9.
Changes v7 => v8:
1. Rebase and fix conflicts.
2. Lock text_mutex for text_poke_copy. (Daniel)
Changes v6 => v7:
1. Redesign the interface between generic and arch logic, based on feedback
from Alexei and Ilya.
2. Split 6/7 of v6 to 7/9 and 8/9 in v7, for cleaner logic.
3. Add bpf_arch_text_copy in 6/9.
Changes v5 => v6:
1. Make jit_hole_buffer 128 byte long. Only fill the first and last 128
bytes of header with INT3. (Alexei)
2. Use kvmalloc for temporary buffer. (Alexei)
3. Rename tmp_header/tmp_image => rw_header/rw_image. Remove tmp_image from
x64_jit_data. (Alexei)
4. Change fall back round_up_to in bpf_jit_binary_alloc_pack() from
BPF_PROG_MAX_PACK_PROG_SIZE to PAGE_SIZE.
Changes v4 => v5:
1. Do not use atomic64 for bpf_jit_current. (Alexei)
Changes v3 => v4:
1. Rename text_poke_jit() => text_poke_copy(). (Peter)
2. Change comment style. (Peter)
Changes v2 => v3:
1. Fix tailcall.
Changes v1 => v2:
1. Use text_poke instead of writing through linear mapping. (Peter)
2. Avoid making changes to non-x86_64 code.
Most BPF programs are small, but they consume a page each. For systems
with busy traffic and many BPF programs, this could also add significant
pressure to instruction TLB. High iTLB pressure usually causes slow down
for the whole system, which includes visible performance degradation for
production workloads.
This set tries to solve this problem with customized allocator that pack
multiple programs into a huge page.
Patches 1-6 prepare the work. Patch 7 contains key logic of bpf_prog_pack
allocator. Patch 8 contains bpf_jit_binary_pack_alloc logic on top of
bpf_prog_pack allocator. Patch 9 uses this allocator in x86_64 jit.
Song Liu (9):
x86/Kconfig: select HAVE_ARCH_HUGE_VMALLOC with HAVE_ARCH_HUGE_VMAP
bpf: use bytes instead of pages for bpf_jit_[charge|uncharge]_modmem
bpf: use size instead of pages in bpf_binary_header
bpf: use prog->jited_len in bpf_prog_ksym_set_addr()
x86/alternative: introduce text_poke_copy
bpf: introduce bpf_arch_text_copy
bpf: introduce bpf_prog_pack allocator
bpf: introduce bpf_jit_binary_pack_[alloc|finalize|free]
bpf, x86_64: use bpf_jit_binary_pack_alloc
arch/x86/Kconfig | 1 +
arch/x86/include/asm/text-patching.h | 1 +
arch/x86/kernel/alternative.c | 34 ++++
arch/x86/net/bpf_jit_comp.c | 65 ++++---
include/linux/bpf.h | 7 +-
include/linux/filter.h | 27 +--
kernel/bpf/core.c | 269 +++++++++++++++++++++++++--
kernel/bpf/trampoline.c | 6 +-
kernel/bpf/verifier.c | 1 +
9 files changed, 349 insertions(+), 62 deletions(-)
--
2.30.2
From: Song Liu <[email protected]>
Use bpf_jit_binary_pack_alloc in x86_64 jit. The jit engine first writes
the program to the rw buffer. When the jit is done, the program is copied
to the final location with bpf_jit_binary_pack_finalize.
Note that we need to do bpf_tail_call_direct_fixup after finalize.
Therefore, the text_live = false logic in __bpf_arch_text_poke is no
longer needed.
Signed-off-by: Song Liu <[email protected]>
---
arch/x86/net/bpf_jit_comp.c | 58 ++++++++++++++++++++-----------------
1 file changed, 31 insertions(+), 27 deletions(-)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index c13d148f7396..643f38b91e30 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -330,8 +330,7 @@ static int emit_jump(u8 **pprog, void *func, void *ip)
}
static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
- void *old_addr, void *new_addr,
- const bool text_live)
+ void *old_addr, void *new_addr)
{
const u8 *nop_insn = x86_nops[5];
u8 old_insn[X86_PATCH_SIZE];
@@ -365,10 +364,7 @@ static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
goto out;
ret = 1;
if (memcmp(ip, new_insn, X86_PATCH_SIZE)) {
- if (text_live)
- text_poke_bp(ip, new_insn, X86_PATCH_SIZE, NULL);
- else
- memcpy(ip, new_insn, X86_PATCH_SIZE);
+ text_poke_bp(ip, new_insn, X86_PATCH_SIZE, NULL);
ret = 0;
}
out:
@@ -384,7 +380,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
/* BPF poking in modules is not supported */
return -EINVAL;
- return __bpf_arch_text_poke(ip, t, old_addr, new_addr, true);
+ return __bpf_arch_text_poke(ip, t, old_addr, new_addr);
}
#define EMIT_LFENCE() EMIT3(0x0F, 0xAE, 0xE8)
@@ -558,24 +554,15 @@ static void bpf_tail_call_direct_fixup(struct bpf_prog *prog)
mutex_lock(&array->aux->poke_mutex);
target = array->ptrs[poke->tail_call.key];
if (target) {
- /* Plain memcpy is used when image is not live yet
- * and still not locked as read-only. Once poke
- * location is active (poke->tailcall_target_stable),
- * any parallel bpf_arch_text_poke() might occur
- * still on the read-write image until we finally
- * locked it as read-only. Both modifications on
- * the given image are under text_mutex to avoid
- * interference.
- */
ret = __bpf_arch_text_poke(poke->tailcall_target,
BPF_MOD_JUMP, NULL,
(u8 *)target->bpf_func +
- poke->adj_off, false);
+ poke->adj_off);
BUG_ON(ret < 0);
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
BPF_MOD_JUMP,
(u8 *)poke->tailcall_target +
- X86_PATCH_SIZE, NULL, false);
+ X86_PATCH_SIZE, NULL);
BUG_ON(ret < 0);
}
WRITE_ONCE(poke->tailcall_target_stable, true);
@@ -866,7 +853,7 @@ static void emit_nops(u8 **pprog, int len)
#define INSN_SZ_DIFF (((addrs[i] - addrs[i - 1]) - (prog - temp)))
-static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
+static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
int oldproglen, struct jit_context *ctx, bool jmp_padding)
{
bool tail_call_reachable = bpf_prog->aux->tail_call_reachable;
@@ -893,8 +880,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
push_callee_regs(&prog, callee_regs_used);
ilen = prog - temp;
- if (image)
- memcpy(image + proglen, temp, ilen);
+ if (rw_image)
+ memcpy(rw_image + proglen, temp, ilen);
proglen += ilen;
addrs[0] = proglen;
prog = temp;
@@ -1323,6 +1310,9 @@ st: if (is_imm8(insn->off))
pr_err("extable->insn doesn't fit into 32-bit\n");
return -EFAULT;
}
+ /* switch ex to rw buffer for writes */
+ ex = (void *)rw_image + ((void *)ex - (void *)image);
+
ex->insn = delta;
ex->data = EX_TYPE_BPF;
@@ -1705,7 +1695,7 @@ st: if (is_imm8(insn->off))
pr_err("bpf_jit: fatal error\n");
return -EFAULT;
}
- memcpy(image + proglen, temp, ilen);
+ memcpy(rw_image + proglen, temp, ilen);
}
proglen += ilen;
addrs[i] = proglen;
@@ -2246,6 +2236,7 @@ int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs)
}
struct x64_jit_data {
+ struct bpf_binary_header *rw_header;
struct bpf_binary_header *header;
int *addrs;
u8 *image;
@@ -2258,6 +2249,7 @@ struct x64_jit_data {
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
{
+ struct bpf_binary_header *rw_header = NULL;
struct bpf_binary_header *header = NULL;
struct bpf_prog *tmp, *orig_prog = prog;
struct x64_jit_data *jit_data;
@@ -2266,6 +2258,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
bool tmp_blinded = false;
bool extra_pass = false;
bool padding = false;
+ u8 *rw_image = NULL;
u8 *image = NULL;
int *addrs;
int pass;
@@ -2301,6 +2294,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
oldproglen = jit_data->proglen;
image = jit_data->image;
header = jit_data->header;
+ rw_header = jit_data->rw_header;
+ rw_image = (void *)rw_header + ((void *)image - (void *)header);
extra_pass = true;
padding = true;
goto skip_init_addrs;
@@ -2331,12 +2326,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
for (pass = 0; pass < MAX_PASSES || image; pass++) {
if (!padding && pass >= PADDING_PASSES)
padding = true;
- proglen = do_jit(prog, addrs, image, oldproglen, &ctx, padding);
+ proglen = do_jit(prog, addrs, image, rw_image, oldproglen, &ctx, padding);
if (proglen <= 0) {
out_image:
image = NULL;
if (header)
- bpf_jit_binary_free(header);
+ bpf_jit_binary_pack_free(header, rw_header);
prog = orig_prog;
goto out_addrs;
}
@@ -2360,8 +2355,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
sizeof(struct exception_table_entry);
/* allocate module memory for x86 insns and extable */
- header = bpf_jit_binary_alloc(roundup(proglen, align) + extable_size,
- &image, align, jit_fill_hole);
+ header = bpf_jit_binary_pack_alloc(roundup(proglen, align) + extable_size,
+ &image, align, &rw_header, &rw_image,
+ jit_fill_hole);
if (!header) {
prog = orig_prog;
goto out_addrs;
@@ -2377,14 +2373,22 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
if (image) {
if (!prog->is_func || extra_pass) {
+ /*
+ * bpf_jit_binary_pack_finalize fails in two scenarios:
+ * 1) header is not pointing to proper module memory;
+ * 2) the arch doesn't support bpf_arch_text_copy().
+ *
+ * Both cases are serious bugs that we should not continue.
+ */
+ BUG_ON(bpf_jit_binary_pack_finalize(prog, header, rw_header));
bpf_tail_call_direct_fixup(prog);
- bpf_jit_binary_lock_ro(header);
} else {
jit_data->addrs = addrs;
jit_data->ctx = ctx;
jit_data->proglen = proglen;
jit_data->image = image;
jit_data->header = header;
+ jit_data->rw_header = rw_header;
}
prog->bpf_func = (void *)image;
prog->jited = 1;
--
2.30.2
This will be used by BPF jit compiler to dump JITed binary to a RX huge
page, and thus allow multiple BPF programs sharing the a huge (2MB) page.
Acked-by: Peter Zijlstra (Intel) <[email protected]>
Signed-off-by: Song Liu <[email protected]>
---
arch/x86/include/asm/text-patching.h | 1 +
arch/x86/kernel/alternative.c | 34 ++++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
index b7421780e4e9..4cc18ba1b75e 100644
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -44,6 +44,7 @@ extern void text_poke_early(void *addr, const void *opcode, size_t len);
extern void *text_poke(void *addr, const void *opcode, size_t len);
extern void text_poke_sync(void);
extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
+extern void *text_poke_copy(void *addr, const void *opcode, size_t len);
extern int poke_int3_handler(struct pt_regs *regs);
extern void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate);
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 5007c3ffe96f..018b61febf0e 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -1102,6 +1102,40 @@ void *text_poke_kgdb(void *addr, const void *opcode, size_t len)
return __text_poke(addr, opcode, len);
}
+/**
+ * text_poke_copy - Copy instructions into (an unused part of) RX memory
+ * @addr: address to modify
+ * @opcode: source of the copy
+ * @len: length to copy, could be more than 2x PAGE_SIZE
+ *
+ * Not safe against concurrent execution; useful for JITs to dump
+ * new code blocks into unused regions of RX memory. Can be used in
+ * conjunction with synchronize_rcu_tasks() to wait for existing
+ * execution to quiesce after having made sure no existing functions
+ * pointers are live.
+ */
+void *text_poke_copy(void *addr, const void *opcode, size_t len)
+{
+ unsigned long start = (unsigned long)addr;
+ size_t patched = 0;
+
+ if (WARN_ON_ONCE(core_kernel_text(start)))
+ return NULL;
+
+ mutex_lock(&text_mutex);
+ while (patched < len) {
+ unsigned long ptr = start + patched;
+ size_t s;
+
+ s = min_t(size_t, PAGE_SIZE * 2 - offset_in_page(ptr), len - patched);
+
+ __text_poke((void *)ptr, opcode + patched, s);
+ patched += s;
+ }
+ mutex_unlock(&text_mutex);
+ return addr;
+}
+
static void do_sync_core(void *info)
{
sync_core();
--
2.30.2
Using prog->jited_len is simpler and more accurate than current
estimation (header + header->size).
Also, fix missing prog->jited_len with multi function program. This hasn't
been a real issue before this.
Signed-off-by: Song Liu <[email protected]>
---
kernel/bpf/core.c | 5 +----
kernel/bpf/verifier.c | 1 +
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 14199228a6f0..e3fe53df0a71 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -537,13 +537,10 @@ long bpf_jit_limit_max __read_mostly;
static void
bpf_prog_ksym_set_addr(struct bpf_prog *prog)
{
- const struct bpf_binary_header *hdr = bpf_jit_binary_hdr(prog);
- unsigned long addr = (unsigned long)hdr;
-
WARN_ON_ONCE(!bpf_prog_ebpf_jited(prog));
prog->aux->ksym.start = (unsigned long) prog->bpf_func;
- prog->aux->ksym.end = addr + hdr->size;
+ prog->aux->ksym.end = prog->aux->ksym.start + prog->jited_len;
}
static void
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 1ae41d0cf96c..bbef86cb4e72 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -13067,6 +13067,7 @@ static int jit_subprogs(struct bpf_verifier_env *env)
prog->jited = 1;
prog->bpf_func = func[0]->bpf_func;
+ prog->jited_len = func[0]->jited_len;
prog->aux->func = func;
prog->aux->func_cnt = env->subprog_cnt;
bpf_prog_jit_attempt_done(prog);
--
2.30.2
On Fri, Feb 04, 2022 at 10:57:42AM -0800, Song Liu wrote:
> if (image) {
> if (!prog->is_func || extra_pass) {
> + /*
> + * bpf_jit_binary_pack_finalize fails in two scenarios:
> + * 1) header is not pointing to proper module memory;
> + * 2) the arch doesn't support bpf_arch_text_copy().
> + *
> + * Both cases are serious bugs that we should not continue.
> + */
> + BUG_ON(bpf_jit_binary_pack_finalize(prog, header, rw_header));
> bpf_tail_call_direct_fixup(prog);
> - bpf_jit_binary_lock_ro(header);
BUG_ON is discouraged.
It should only be used when the kernel absolutely cannot continue.
Here ro/rw_headers will be freed. We can WARN and goto out_addrs without drama.
Please send a follow up.
The rest looks great. Applied to bpf-next.
Hello:
This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <[email protected]>:
On Fri, 4 Feb 2022 10:57:33 -0800 you wrote:
> Changes v8 => v9:
> 1. Fix an error with multi function program, in 4/9.
>
> Changes v7 => v8:
> 1. Rebase and fix conflicts.
> 2. Lock text_mutex for text_poke_copy. (Daniel)
>
> [...]
Here is the summary with links:
- [v9,bpf-next,1/9] x86/Kconfig: select HAVE_ARCH_HUGE_VMALLOC with HAVE_ARCH_HUGE_VMAP
https://git.kernel.org/bpf/bpf-next/c/fac54e2bfb5b
- [v9,bpf-next,2/9] bpf: use bytes instead of pages for bpf_jit_[charge|uncharge]_modmem
https://git.kernel.org/bpf/bpf-next/c/3486bedd9919
- [v9,bpf-next,3/9] bpf: use size instead of pages in bpf_binary_header
https://git.kernel.org/bpf/bpf-next/c/ed2d9e1a26cc
- [v9,bpf-next,4/9] bpf: use prog->jited_len in bpf_prog_ksym_set_addr()
https://git.kernel.org/bpf/bpf-next/c/d00c6473b1ee
- [v9,bpf-next,5/9] x86/alternative: introduce text_poke_copy
https://git.kernel.org/bpf/bpf-next/c/0e06b4037168
- [v9,bpf-next,6/9] bpf: introduce bpf_arch_text_copy
https://git.kernel.org/bpf/bpf-next/c/ebc1415d9b4f
- [v9,bpf-next,7/9] bpf: introduce bpf_prog_pack allocator
https://git.kernel.org/bpf/bpf-next/c/57631054fae6
- [v9,bpf-next,8/9] bpf: introduce bpf_jit_binary_pack_[alloc|finalize|free]
https://git.kernel.org/bpf/bpf-next/c/33c9805860e5
- [v9,bpf-next,9/9] bpf, x86_64: use bpf_jit_binary_pack_alloc
https://git.kernel.org/bpf/bpf-next/c/1022a5498f6f
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
This will be used to copy JITed text to RO protected module memory. On
x86, bpf_arch_text_copy is implemented with text_poke_copy.
bpf_arch_text_copy returns pointer to dst on success, and ERR_PTR(errno)
on errors.
Signed-off-by: Song Liu <[email protected]>
---
arch/x86/net/bpf_jit_comp.c | 7 +++++++
include/linux/bpf.h | 2 ++
kernel/bpf/core.c | 5 +++++
3 files changed, 14 insertions(+)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 36f6fc3e6e69..c13d148f7396 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -2412,3 +2412,10 @@ bool bpf_jit_supports_kfunc_call(void)
{
return true;
}
+
+void *bpf_arch_text_copy(void *dst, void *src, size_t len)
+{
+ if (text_poke_copy(dst, src, len) == NULL)
+ return ERR_PTR(-EINVAL);
+ return dst;
+}
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 366f88afd56b..ea0d7fd4a410 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2362,6 +2362,8 @@ enum bpf_text_poke_type {
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
void *addr1, void *addr2);
+void *bpf_arch_text_copy(void *dst, void *src, size_t len);
+
struct btf_id_set;
bool btf_id_set_contains(const struct btf_id_set *set, u32 id);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index e3fe53df0a71..a5ec480f9862 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2440,6 +2440,11 @@ int __weak bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
return -ENOTSUPP;
}
+void * __weak bpf_arch_text_copy(void *dst, void *src, size_t len)
+{
+ return ERR_PTR(-ENOTSUPP);
+}
+
DEFINE_STATIC_KEY_FALSE(bpf_stats_enabled_key);
EXPORT_SYMBOL(bpf_stats_enabled_key);
--
2.30.2
On Sat, Jul 2, 2022 at 8:02 PM Andres Freund <[email protected]> wrote:
>
> Hi,
>
> On 2022-02-04 10:57:42 -0800, Song Liu wrote:
> > From: Song Liu <[email protected]>
> >
> > Use bpf_jit_binary_pack_alloc in x86_64 jit. The jit engine first writes
> > the program to the rw buffer. When the jit is done, the program is copied
> > to the final location with bpf_jit_binary_pack_finalize.
> >
> > Note that we need to do bpf_tail_call_direct_fixup after finalize.
> > Therefore, the text_live = false logic in __bpf_arch_text_poke is no
> > longer needed.
>
> I think this broke bpf_jit_enable = 2.
Good. We need to remove that knob.
It's been wrong for a long time.
Hi,
On 2022-02-04 10:57:42 -0800, Song Liu wrote:
> From: Song Liu <[email protected]>
>
> Use bpf_jit_binary_pack_alloc in x86_64 jit. The jit engine first writes
> the program to the rw buffer. When the jit is done, the program is copied
> to the final location with bpf_jit_binary_pack_finalize.
>
> Note that we need to do bpf_tail_call_direct_fixup after finalize.
> Therefore, the text_live = false logic in __bpf_arch_text_poke is no
> longer needed.
I think this broke bpf_jit_enable = 2. I just tried to use that, to verify I
didn't break tools/bpf/bpf_jit_disasm, and I just see output like
Jul 02 18:34:40 awork3 kernel: flen=142 proglen=735 pass=5 image=00000000d076e0db from=sshd pid=440127
Jul 02 18:34:40 awork3 kernel: JIT code: 00000000: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
Jul 02 18:34:40 awork3 kernel: JIT code: 00000010: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
Jul 02 18:34:40 awork3 kernel: JIT code: 00000020: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
Jul 02 18:34:40 awork3 kernel: JIT code: 00000030: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
...
while bpftool keeps showing reasonable content. The 'cc' content only started
with a later commit, but I think this is the commit that broke bpf_jit_enable
== 2.
At the time bpf_jit_dump() is called bpf_jit_binary_pack_alloc() pointed image to
ro_header->image, but that's not yet written to, because
bpf_jit_binary_pack_finalize() hasn't been called.
Greetings,
Andres Freund
Hi,
On 2022-07-02 20:03:56 -0700, Alexei Starovoitov wrote:
> On Sat, Jul 2, 2022 at 8:02 PM Andres Freund <[email protected]> wrote:
> > On 2022-02-04 10:57:42 -0800, Song Liu wrote:
> > > From: Song Liu <[email protected]>
> > >
> > > Use bpf_jit_binary_pack_alloc in x86_64 jit. The jit engine first writes
> > > the program to the rw buffer. When the jit is done, the program is copied
> > > to the final location with bpf_jit_binary_pack_finalize.
> > >
> > > Note that we need to do bpf_tail_call_direct_fixup after finalize.
> > > Therefore, the text_live = false logic in __bpf_arch_text_poke is no
> > > longer needed.
> >
> > I think this broke bpf_jit_enable = 2.
>
> Good. We need to remove that knob.
> It's been wrong for a long time.
Fine with me - I've never used it before trying to verify I am not breaking
tools/bpf/bpf_jit_disasm...
And yea, it does look like it bpf_jit_dump() was called too early before that
commit as well, just not as consequentially so.
Greetings,
Andres Freund