bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator
@ 2023-10-12 20:03 Hari Bathini
  2023-10-12 20:03 ` [PATCH v6 1/5] powerpc/code-patching: introduce patch_instructions() Hari Bathini
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Hari Bathini @ 2023-10-12 20:03 UTC (permalink / raw)
  To: linuxppc-dev, bpf
  Cc: Michael Ellerman, Naveen N. Rao, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Song Liu, Christophe Leroy

Most BPF programs are small, but they consume a page each. For systems
with busy traffic and many BPF programs, this may also add significant
pressure on instruction TLB. High iTLB pressure usually slows down the
whole system causing visible performance degradation for production
workloads.

bpf_prog_pack, a customized allocator that packs multiple bpf programs
into preallocated memory chunks, was proposed [1] to address it. This
series extends this support on powerpc.

Both bpf_arch_text_copy() & bpf_arch_text_invalidate() functions,
needed for this support depend on instruction patching in text area.
Currently, patch_instruction() supports patching only one instruction
at a time. The first patch introduces patch_instructions() function
to enable patching more than one instruction at a time. This helps in
avoiding performance degradation while JITing bpf programs.

Patches 2 & 3 implement the above mentioned arch specific functions
using patch_instructions(). Patch 4 fixes a misnomer in bpf JITing
code. The last patch enables the use of BPF prog pack allocator on
powerpc and also, ensures cleanup is handled gracefully.

[1] https://lore.kernel.org/bpf/20220204185742.271030-1-song@kernel.org/

Changes in v6:
* No changes in patches 2-5/5 except addition of Acked-by tags from Song.
* Skipped merging code path of patch_instruction() & patch_instructions()
  to avoid performance overhead observed on ppc32 with that.

Changes in v5:
* Moved introduction of patch_instructions() as 1st patch in series.
* Improved patch_instructions() to use memset & memcpy.
* Fixed the misnomer in JITing code as a separate patch.
* Removed unused bpf_flush_icache() function.

Changes in v4:
* Updated bpf_patch_instructions() definition in patch 1/5 so that
  it doesn't have to be updated again in patch 2/5.
* Addressed Christophe's comment on bpf_arch_text_invalidate() return
  value in patch 2/5.

Changes in v3:
* Fixed segfault issue observed on ppc32 due to inaccurate offset
  calculation for branching.
* Tried to minimize the performance impact for patch_instruction()
  with the introduction of patch_instructions().
* Corrected uses of u32* vs ppc_instr_t.
* Moved the change that introduces patch_instructions() to after
  enabling bpf_prog_pack support.
* Added few comments to improve code readability.

Changes in v2:
* Introduced patch_instructions() to help with patching bpf programs.


Hari Bathini (5):
  powerpc/code-patching: introduce patch_instructions()
  powerpc/bpf: implement bpf_arch_text_copy
  powerpc/bpf: implement bpf_arch_text_invalidate for bpf_prog_pack
  powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data
  powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free]

 arch/powerpc/include/asm/code-patching.h |   1 +
 arch/powerpc/lib/code-patching.c         | 138 +++++++++++++++++++++
 arch/powerpc/net/bpf_jit.h               |  18 +--
 arch/powerpc/net/bpf_jit_comp.c          | 145 ++++++++++++++++++-----
 arch/powerpc/net/bpf_jit_comp32.c        |  13 +-
 arch/powerpc/net/bpf_jit_comp64.c        |  10 +-
 6 files changed, 271 insertions(+), 54 deletions(-)

-- 
2.41.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v6 1/5] powerpc/code-patching: introduce patch_instructions()
  2023-10-12 20:03 [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Hari Bathini
@ 2023-10-12 20:03 ` Hari Bathini
  2023-10-12 20:03 ` [PATCH v6 2/5] powerpc/bpf: implement bpf_arch_text_copy Hari Bathini
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Hari Bathini @ 2023-10-12 20:03 UTC (permalink / raw)
  To: linuxppc-dev, bpf
  Cc: Michael Ellerman, Naveen N. Rao, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Song Liu, Christophe Leroy,
	Song Liu

patch_instruction() entails setting up pte, patching the instruction,
clearing the pte and flushing the tlb. If multiple instructions need
to be patched, every instruction would have to go through the above
drill unnecessarily. Instead, introduce patch_instructions() function
that sets up the pte, clears the pte and flushes the tlb only once per
page range of instructions to be patched. This duplicates most of the
code patching logic, instead of merging with it, to avoid performance
degradation observed for single instruction patching on ppc32 with
the code path merged.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Acked-by: Song Liu <song@kernel.org>
---

Changes in v6:
* Skipped merging code path of patch_instruction() & patch_instructions()
  to avoid performance overhead observed on ppc32 with that.


 arch/powerpc/include/asm/code-patching.h |   1 +
 arch/powerpc/lib/code-patching.c         | 138 +++++++++++++++++++++++
 2 files changed, 139 insertions(+)

diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 3f881548fb61..0e29ccf903d0 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -74,6 +74,7 @@ int create_cond_branch(ppc_inst_t *instr, const u32 *addr,
 int patch_branch(u32 *addr, unsigned long target, int flags);
 int patch_instruction(u32 *addr, ppc_inst_t instr);
 int raw_patch_instruction(u32 *addr, ppc_inst_t instr);
+int patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr);
 
 static inline unsigned long patch_site_addr(s32 *site)
 {
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index b00112d7ad46..a115496f934b 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -378,6 +378,144 @@ int patch_instruction(u32 *addr, ppc_inst_t instr)
 }
 NOKPROBE_SYMBOL(patch_instruction);
 
+static int __patch_instructions(u32 *patch_addr, u32 *code, size_t len, bool repeat_instr)
+{
+	unsigned long start = (unsigned long)patch_addr;
+
+	/* Repeat instruction */
+	if (repeat_instr) {
+		ppc_inst_t instr = ppc_inst_read(code);
+
+		if (ppc_inst_prefixed(instr)) {
+			u64 val = ppc_inst_as_ulong(instr);
+
+			memset64((u64 *)patch_addr, val, len / 8);
+		} else {
+			u32 val = ppc_inst_val(instr);
+
+			memset32(patch_addr, val, len / 4);
+		}
+	} else {
+		memcpy(patch_addr, code, len);
+	}
+
+	smp_wmb();	/* smp write barrier */
+	flush_icache_range(start, start + len);
+	return 0;
+}
+
+/*
+ * A page is mapped and instructions that fit the page are patched.
+ * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below.
+ */
+static int __do_patch_instructions_mm(u32 *addr, u32 *code, size_t len, bool repeat_instr)
+{
+	struct mm_struct *patching_mm, *orig_mm;
+	unsigned long pfn = get_patch_pfn(addr);
+	unsigned long text_poke_addr;
+	spinlock_t *ptl;
+	u32 *patch_addr;
+	pte_t *pte;
+	int err;
+
+	patching_mm = __this_cpu_read(cpu_patching_context.mm);
+	text_poke_addr = __this_cpu_read(cpu_patching_context.addr);
+	patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
+
+	pte = get_locked_pte(patching_mm, text_poke_addr, &ptl);
+	if (!pte)
+		return -ENOMEM;
+
+	__set_pte_at(patching_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), 0);
+
+	/* order PTE update before use, also serves as the hwsync */
+	asm volatile("ptesync" ::: "memory");
+
+	/* order context switch after arbitrary prior code */
+	isync();
+
+	orig_mm = start_using_temp_mm(patching_mm);
+
+	err = __patch_instructions(patch_addr, code, len, repeat_instr);
+
+	/* context synchronisation performed by __patch_instructions */
+	stop_using_temp_mm(patching_mm, orig_mm);
+
+	pte_clear(patching_mm, text_poke_addr, pte);
+	/*
+	 * ptesync to order PTE update before TLB invalidation done
+	 * by radix__local_flush_tlb_page_psize (in _tlbiel_va)
+	 */
+	local_flush_tlb_page_psize(patching_mm, text_poke_addr, mmu_virtual_psize);
+
+	pte_unmap_unlock(pte, ptl);
+
+	return err;
+}
+
+/*
+ * A page is mapped and instructions that fit the page are patched.
+ * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below.
+ */
+static int __do_patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr)
+{
+	unsigned long pfn = get_patch_pfn(addr);
+	unsigned long text_poke_addr;
+	u32 *patch_addr;
+	pte_t *pte;
+	int err;
+
+	text_poke_addr = (unsigned long)__this_cpu_read(cpu_patching_context.addr) & PAGE_MASK;
+	patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
+
+	pte = __this_cpu_read(cpu_patching_context.pte);
+	__set_pte_at(&init_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), 0);
+	/* See ptesync comment in radix__set_pte_at() */
+	if (radix_enabled())
+		asm volatile("ptesync" ::: "memory");
+
+	err = __patch_instructions(patch_addr, code, len, repeat_instr);
+
+	pte_clear(&init_mm, text_poke_addr, pte);
+	flush_tlb_kernel_range(text_poke_addr, text_poke_addr + PAGE_SIZE);
+
+	return err;
+}
+
+/*
+ * Patch 'addr' with 'len' bytes of instructions from 'code'.
+ *
+ * If repeat_instr is true, the same instruction is filled for
+ * 'len' bytes.
+ */
+int patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr)
+{
+	while (len > 0) {
+		unsigned long flags;
+		size_t plen;
+		int err;
+
+		plen = min_t(size_t, PAGE_SIZE - offset_in_page(addr), len);
+
+		local_irq_save(flags);
+		if (mm_patch_enabled())
+			err = __do_patch_instructions_mm(addr, code, plen, repeat_instr);
+		else
+			err = __do_patch_instructions(addr, code, plen, repeat_instr);
+		local_irq_restore(flags);
+		if (err)
+			return err;
+
+		len -= plen;
+		addr = (u32 *)((unsigned long)addr + plen);
+		if (!repeat_instr)
+			code = (u32 *)((unsigned long)code + plen);
+	}
+
+	return 0;
+}
+NOKPROBE_SYMBOL(patch_instructions);
+
 int patch_branch(u32 *addr, unsigned long target, int flags)
 {
 	ppc_inst_t instr;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v6 2/5] powerpc/bpf: implement bpf_arch_text_copy
  2023-10-12 20:03 [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Hari Bathini
  2023-10-12 20:03 ` [PATCH v6 1/5] powerpc/code-patching: introduce patch_instructions() Hari Bathini
@ 2023-10-12 20:03 ` Hari Bathini
  2023-10-12 20:03 ` [PATCH v6 3/5] powerpc/bpf: implement bpf_arch_text_invalidate for bpf_prog_pack Hari Bathini
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Hari Bathini @ 2023-10-12 20:03 UTC (permalink / raw)
  To: linuxppc-dev, bpf
  Cc: Michael Ellerman, Naveen N. Rao, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Song Liu, Christophe Leroy,
	Song Liu

bpf_arch_text_copy is used to dump JITed binary to RX page, allowing
multiple BPF programs to share the same page. Use the newly introduced
patch_instructions() to implement it.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Acked-by: Song Liu <song@kernel.org>
---
 arch/powerpc/net/bpf_jit_comp.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 37043dfc1add..c740eac8d584 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -13,9 +13,13 @@
 #include <linux/netdevice.h>
 #include <linux/filter.h>
 #include <linux/if_vlan.h>
-#include <asm/kprobes.h>
+#include <linux/kernel.h>
+#include <linux/memory.h>
 #include <linux/bpf.h>
 
+#include <asm/kprobes.h>
+#include <asm/code-patching.h>
+
 #include "bpf_jit.h"
 
 static void bpf_jit_fill_ill_insns(void *area, unsigned int size)
@@ -274,3 +278,17 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code
 	ctx->exentry_idx++;
 	return 0;
 }
+
+void *bpf_arch_text_copy(void *dst, void *src, size_t len)
+{
+	int err;
+
+	if (WARN_ON_ONCE(core_kernel_text((unsigned long)dst)))
+		return ERR_PTR(-EINVAL);
+
+	mutex_lock(&text_mutex);
+	err = patch_instructions(dst, src, len, false);
+	mutex_unlock(&text_mutex);
+
+	return err ? ERR_PTR(err) : dst;
+}
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v6 3/5] powerpc/bpf: implement bpf_arch_text_invalidate for bpf_prog_pack
  2023-10-12 20:03 [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Hari Bathini
  2023-10-12 20:03 ` [PATCH v6 1/5] powerpc/code-patching: introduce patch_instructions() Hari Bathini
  2023-10-12 20:03 ` [PATCH v6 2/5] powerpc/bpf: implement bpf_arch_text_copy Hari Bathini
@ 2023-10-12 20:03 ` Hari Bathini
  2023-10-12 20:03 ` [PATCH v6 4/5] powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data Hari Bathini
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Hari Bathini @ 2023-10-12 20:03 UTC (permalink / raw)
  To: linuxppc-dev, bpf
  Cc: Michael Ellerman, Naveen N. Rao, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Song Liu, Christophe Leroy,
	Song Liu

Implement bpf_arch_text_invalidate and use it to fill unused part of
the bpf_prog_pack with trap instructions when a BPF program is freed.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Acked-by: Song Liu <song@kernel.org>
---
 arch/powerpc/net/bpf_jit_comp.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index c740eac8d584..ecd7cffbbe28 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -292,3 +292,18 @@ void *bpf_arch_text_copy(void *dst, void *src, size_t len)
 
 	return err ? ERR_PTR(err) : dst;
 }
+
+int bpf_arch_text_invalidate(void *dst, size_t len)
+{
+	u32 insn = BREAKPOINT_INSTRUCTION;
+	int ret;
+
+	if (WARN_ON_ONCE(core_kernel_text((unsigned long)dst)))
+		return -EINVAL;
+
+	mutex_lock(&text_mutex);
+	ret = patch_instructions(dst, &insn, len, true);
+	mutex_unlock(&text_mutex);
+
+	return ret;
+}
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v6 4/5] powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data
  2023-10-12 20:03 [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Hari Bathini
                   ` (2 preceding siblings ...)
  2023-10-12 20:03 ` [PATCH v6 3/5] powerpc/bpf: implement bpf_arch_text_invalidate for bpf_prog_pack Hari Bathini
@ 2023-10-12 20:03 ` Hari Bathini
  2023-10-12 20:03 ` [PATCH v6 5/5] powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free] Hari Bathini
  2023-10-16 12:07 ` [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Daniel Borkmann
  5 siblings, 0 replies; 10+ messages in thread
From: Hari Bathini @ 2023-10-12 20:03 UTC (permalink / raw)
  To: linuxppc-dev, bpf
  Cc: Michael Ellerman, Naveen N. Rao, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Song Liu, Christophe Leroy,
	Song Liu

powerpc64_jit_data is a misnomer as it is meant for both ppc32 and
ppc64. Rename it to powerpc_jit_data.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Acked-by: Song Liu <song@kernel.org>
---
 arch/powerpc/net/bpf_jit_comp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index ecd7cffbbe28..e7ca270a39d5 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -43,7 +43,7 @@ int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg,
 	return 0;
 }
 
-struct powerpc64_jit_data {
+struct powerpc_jit_data {
 	struct bpf_binary_header *header;
 	u32 *addrs;
 	u8 *image;
@@ -63,7 +63,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	u8 *image = NULL;
 	u32 *code_base;
 	u32 *addrs;
-	struct powerpc64_jit_data *jit_data;
+	struct powerpc_jit_data *jit_data;
 	struct codegen_context cgctx;
 	int pass;
 	int flen;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v6 5/5] powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free]
  2023-10-12 20:03 [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Hari Bathini
                   ` (3 preceding siblings ...)
  2023-10-12 20:03 ` [PATCH v6 4/5] powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data Hari Bathini
@ 2023-10-12 20:03 ` Hari Bathini
  2023-10-19  6:11   ` Michael Ellerman
  2023-10-16 12:07 ` [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Daniel Borkmann
  5 siblings, 1 reply; 10+ messages in thread
From: Hari Bathini @ 2023-10-12 20:03 UTC (permalink / raw)
  To: linuxppc-dev, bpf
  Cc: Michael Ellerman, Naveen N. Rao, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Song Liu, Christophe Leroy,
	Song Liu

Use bpf_jit_binary_pack_alloc in powerpc 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.
With multiple jit_subprogs, bpf_jit_free is called on some subprograms
that haven't got bpf_jit_binary_pack_finalize() yet. Implement custom
bpf_jit_free() like in commit 1d5f82d9dd47 ("bpf, x86: fix freeing of
not-finalized bpf_prog_pack") to call bpf_jit_binary_pack_finalize(),
if necessary. As bpf_flush_icache() is not needed anymore, remove it.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Acked-by: Song Liu <song@kernel.org>
---
 arch/powerpc/net/bpf_jit.h        |  18 ++---
 arch/powerpc/net/bpf_jit_comp.c   | 106 ++++++++++++++++++++++--------
 arch/powerpc/net/bpf_jit_comp32.c |  13 ++--
 arch/powerpc/net/bpf_jit_comp64.c |  10 +--
 4 files changed, 96 insertions(+), 51 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 72b7bb34fade..cdea5dccaefe 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -36,9 +36,6 @@
 		EMIT(PPC_RAW_BRANCH(offset));				      \
 	} while (0)
 
-/* bl (unconditional 'branch' with link) */
-#define PPC_BL(dest)	EMIT(PPC_RAW_BL((dest) - (unsigned long)(image + ctx->idx)))
-
 /* "cond" here covers BO:BI fields. */
 #define PPC_BCC_SHORT(cond, dest)					      \
 	do {								      \
@@ -147,12 +144,6 @@ struct codegen_context {
 #define BPF_FIXUP_LEN	2 /* Two instructions => 8 bytes */
 #endif
 
-static inline void bpf_flush_icache(void *start, void *end)
-{
-	smp_wmb();	/* smp write barrier */
-	flush_icache_range((unsigned long)start, (unsigned long)end);
-}
-
 static inline bool bpf_is_seen_register(struct codegen_context *ctx, int i)
 {
 	return ctx->seen & (1 << (31 - i));
@@ -169,16 +160,17 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i)
 }
 
 void bpf_jit_init_reg_mapping(struct codegen_context *ctx);
-int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func);
-int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
+int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func);
+int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx,
 		       u32 *addrs, int pass, bool extra_pass);
 void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
 void bpf_jit_realloc_regs(struct codegen_context *ctx);
 int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr);
 
-int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx,
-			  int insn_idx, int jmp_off, int dst_reg);
+int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, u32 *fimage, int pass,
+			  struct codegen_context *ctx, int insn_idx,
+			  int jmp_off, int dst_reg);
 
 #endif
 
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index e7ca270a39d5..a79d7c478074 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -44,9 +44,12 @@ int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg,
 }
 
 struct powerpc_jit_data {
-	struct bpf_binary_header *header;
+	/* address of rw header */
+	struct bpf_binary_header *hdr;
+	/* address of ro final header */
+	struct bpf_binary_header *fhdr;
 	u32 *addrs;
-	u8 *image;
+	u8 *fimage;
 	u32 proglen;
 	struct codegen_context ctx;
 };
@@ -67,11 +70,14 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	struct codegen_context cgctx;
 	int pass;
 	int flen;
-	struct bpf_binary_header *bpf_hdr;
+	struct bpf_binary_header *fhdr = NULL;
+	struct bpf_binary_header *hdr = NULL;
 	struct bpf_prog *org_fp = fp;
 	struct bpf_prog *tmp_fp;
 	bool bpf_blinded = false;
 	bool extra_pass = false;
+	u8 *fimage = NULL;
+	u32 *fcode_base;
 	u32 extable_len;
 	u32 fixup_len;
 
@@ -101,9 +107,16 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	addrs = jit_data->addrs;
 	if (addrs) {
 		cgctx = jit_data->ctx;
-		image = jit_data->image;
-		bpf_hdr = jit_data->header;
+		/*
+		 * JIT compiled to a writable location (image/code_base) first.
+		 * It is then moved to the readonly final location (fimage/fcode_base)
+		 * using instruction patching.
+		 */
+		fimage = jit_data->fimage;
+		fhdr = jit_data->fhdr;
 		proglen = jit_data->proglen;
+		hdr = jit_data->hdr;
+		image = (void *)hdr + ((void *)fimage - (void *)fhdr);
 		extra_pass = true;
 		/* During extra pass, ensure index is reset before repopulating extable entries */
 		cgctx.exentry_idx = 0;
@@ -123,7 +136,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	cgctx.stack_size = round_up(fp->aux->stack_depth, 16);
 
 	/* Scouting faux-generate pass 0 */
-	if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0, false)) {
+	if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) {
 		/* We hit something illegal or unsupported. */
 		fp = org_fp;
 		goto out_addrs;
@@ -138,7 +151,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	 */
 	if (cgctx.seen & SEEN_TAILCALL || !is_offset_in_branch_range((long)cgctx.idx * 4)) {
 		cgctx.idx = 0;
-		if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0, false)) {
+		if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) {
 			fp = org_fp;
 			goto out_addrs;
 		}
@@ -160,17 +173,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 	proglen = cgctx.idx * 4;
 	alloclen = proglen + FUNCTION_DESCR_SIZE + fixup_len + extable_len;
 
-	bpf_hdr = bpf_jit_binary_alloc(alloclen, &image, 4, bpf_jit_fill_ill_insns);
-	if (!bpf_hdr) {
+	fhdr = bpf_jit_binary_pack_alloc(alloclen, &fimage, 4, &hdr, &image,
+					      bpf_jit_fill_ill_insns);
+	if (!fhdr) {
 		fp = org_fp;
 		goto out_addrs;
 	}
 
 	if (extable_len)
-		fp->aux->extable = (void *)image + FUNCTION_DESCR_SIZE + proglen + fixup_len;
+		fp->aux->extable = (void *)fimage + FUNCTION_DESCR_SIZE + proglen + fixup_len;
 
 skip_init_ctx:
 	code_base = (u32 *)(image + FUNCTION_DESCR_SIZE);
+	fcode_base = (u32 *)(fimage + FUNCTION_DESCR_SIZE);
 
 	/* Code generation passes 1-2 */
 	for (pass = 1; pass < 3; pass++) {
@@ -178,8 +193,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		cgctx.idx = 0;
 		cgctx.alt_exit_addr = 0;
 		bpf_jit_build_prologue(code_base, &cgctx);
-		if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, pass, extra_pass)) {
-			bpf_jit_binary_free(bpf_hdr);
+		if (bpf_jit_build_body(fp, code_base, fcode_base, &cgctx, addrs, pass,
+				       extra_pass)) {
+			bpf_arch_text_copy(&fhdr->size, &hdr->size, sizeof(hdr->size));
+			bpf_jit_binary_pack_free(fhdr, hdr);
 			fp = org_fp;
 			goto out_addrs;
 		}
@@ -199,17 +216,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 
 #ifdef CONFIG_PPC64_ELF_ABI_V1
 	/* Function descriptor nastiness: Address + TOC */
-	((u64 *)image)[0] = (u64)code_base;
+	((u64 *)image)[0] = (u64)fcode_base;
 	((u64 *)image)[1] = local_paca->kernel_toc;
 #endif
 
-	fp->bpf_func = (void *)image;
+	fp->bpf_func = (void *)fimage;
 	fp->jited = 1;
 	fp->jited_len = proglen + FUNCTION_DESCR_SIZE;
 
-	bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + bpf_hdr->size);
 	if (!fp->is_func || extra_pass) {
-		bpf_jit_binary_lock_ro(bpf_hdr);
+		if (bpf_jit_binary_pack_finalize(fp, fhdr, hdr)) {
+			fp = org_fp;
+			goto out_addrs;
+		}
 		bpf_prog_fill_jited_linfo(fp, addrs);
 out_addrs:
 		kfree(addrs);
@@ -219,8 +238,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 		jit_data->addrs = addrs;
 		jit_data->ctx = cgctx;
 		jit_data->proglen = proglen;
-		jit_data->image = image;
-		jit_data->header = bpf_hdr;
+		jit_data->fimage = fimage;
+		jit_data->fhdr = fhdr;
+		jit_data->hdr = hdr;
 	}
 
 out:
@@ -234,12 +254,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
  * The caller should check for (BPF_MODE(code) == BPF_PROBE_MEM) before calling
  * this function, as this only applies to BPF_PROBE_MEM, for now.
  */
-int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx,
-			  int insn_idx, int jmp_off, int dst_reg)
+int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, u32 *fimage, int pass,
+			  struct codegen_context *ctx, int insn_idx, int jmp_off,
+			  int dst_reg)
 {
 	off_t offset;
 	unsigned long pc;
-	struct exception_table_entry *ex;
+	struct exception_table_entry *ex, *ex_entry;
 	u32 *fixup;
 
 	/* Populate extable entries only in the last pass */
@@ -250,9 +271,16 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code
 	    WARN_ON_ONCE(ctx->exentry_idx >= fp->aux->num_exentries))
 		return -EINVAL;
 
+	/*
+	 * Program is first written to image before copying to the
+	 * final location (fimage). Accordingly, update in the image first.
+	 * As all offsets used are relative, copying as is to the
+	 * final location should be alright.
+	 */
 	pc = (unsigned long)&image[insn_idx];
+	ex = (void *)fp->aux->extable - (void *)fimage + (void *)image;
 
-	fixup = (void *)fp->aux->extable -
+	fixup = (void *)ex -
 		(fp->aux->num_exentries * BPF_FIXUP_LEN * 4) +
 		(ctx->exentry_idx * BPF_FIXUP_LEN * 4);
 
@@ -263,17 +291,17 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code
 	fixup[BPF_FIXUP_LEN - 1] =
 		PPC_RAW_BRANCH((long)(pc + jmp_off) - (long)&fixup[BPF_FIXUP_LEN - 1]);
 
-	ex = &fp->aux->extable[ctx->exentry_idx];
+	ex_entry = &ex[ctx->exentry_idx];
 
-	offset = pc - (long)&ex->insn;
+	offset = pc - (long)&ex_entry->insn;
 	if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN))
 		return -ERANGE;
-	ex->insn = offset;
+	ex_entry->insn = offset;
 
-	offset = (long)fixup - (long)&ex->fixup;
+	offset = (long)fixup - (long)&ex_entry->fixup;
 	if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN))
 		return -ERANGE;
-	ex->fixup = offset;
+	ex_entry->fixup = offset;
 
 	ctx->exentry_idx++;
 	return 0;
@@ -307,3 +335,27 @@ int bpf_arch_text_invalidate(void *dst, size_t len)
 
 	return ret;
 }
+
+void bpf_jit_free(struct bpf_prog *fp)
+{
+	if (fp->jited) {
+		struct powerpc_jit_data *jit_data = fp->aux->jit_data;
+		struct bpf_binary_header *hdr;
+
+		/*
+		 * If we fail the final pass of JIT (from jit_subprogs),
+		 * the program may not be finalized yet. Call finalize here
+		 * before freeing it.
+		 */
+		if (jit_data) {
+			bpf_jit_binary_pack_finalize(fp, jit_data->fhdr, jit_data->hdr);
+			kvfree(jit_data->addrs);
+			kfree(jit_data);
+		}
+		hdr = bpf_jit_binary_pack_hdr(fp);
+		bpf_jit_binary_pack_free(hdr, NULL);
+		WARN_ON_ONCE(!bpf_prog_kallsyms_verify_off(fp));
+	}
+
+	bpf_prog_unlock_free(fp);
+}
diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c
index 7f91ea064c08..434417c755fd 100644
--- a/arch/powerpc/net/bpf_jit_comp32.c
+++ b/arch/powerpc/net/bpf_jit_comp32.c
@@ -200,12 +200,13 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
 	EMIT(PPC_RAW_BLR());
 }
 
-int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func)
+/* Relative offset needs to be calculated based on final image location */
+int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
 {
-	s32 rel = (s32)func - (s32)(image + ctx->idx);
+	s32 rel = (s32)func - (s32)(fimage + ctx->idx);
 
 	if (image && rel < 0x2000000 && rel >= -0x2000000) {
-		PPC_BL(func);
+		EMIT(PPC_RAW_BL(rel));
 	} else {
 		/* Load function address into r0 */
 		EMIT(PPC_RAW_LIS(_R0, IMM_H(func)));
@@ -278,7 +279,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
 }
 
 /* Assemble the body code between the prologue & epilogue */
-int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
+int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx,
 		       u32 *addrs, int pass, bool extra_pass)
 {
 	const struct bpf_insn *insn = fp->insnsi;
@@ -997,7 +998,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 					jmp_off += 4;
 				}
 
-				ret = bpf_add_extable_entry(fp, image, pass, ctx, insn_idx,
+				ret = bpf_add_extable_entry(fp, image, fimage, pass, ctx, insn_idx,
 							    jmp_off, dst_reg);
 				if (ret)
 					return ret;
@@ -1053,7 +1054,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 				EMIT(PPC_RAW_STW(bpf_to_ppc(BPF_REG_5), _R1, 12));
 			}
 
-			ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+			ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr);
 			if (ret)
 				return ret;
 
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index 0f8048f6dad6..79f23974a320 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -240,7 +240,7 @@ static int bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx, u
 	return 0;
 }
 
-int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func)
+int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
 {
 	unsigned int i, ctx_idx = ctx->idx;
 
@@ -361,7 +361,7 @@ asm (
 );
 
 /* Assemble the body code between the prologue & epilogue */
-int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
+int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx,
 		       u32 *addrs, int pass, bool extra_pass)
 {
 	enum stf_barrier_type stf_barrier = stf_barrier_type_get();
@@ -940,8 +940,8 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 				addrs[++i] = ctx->idx * 4;
 
 			if (BPF_MODE(code) == BPF_PROBE_MEM) {
-				ret = bpf_add_extable_entry(fp, image, pass, ctx, ctx->idx - 1,
-							    4, dst_reg);
+				ret = bpf_add_extable_entry(fp, image, fimage, pass, ctx,
+							    ctx->idx - 1, 4, dst_reg);
 				if (ret)
 					return ret;
 			}
@@ -995,7 +995,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
 			if (func_addr_fixed)
 				ret = bpf_jit_emit_func_call_hlp(image, ctx, func_addr);
 			else
-				ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr);
+				ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr);
 
 			if (ret)
 				return ret;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator
  2023-10-12 20:03 [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Hari Bathini
                   ` (4 preceding siblings ...)
  2023-10-12 20:03 ` [PATCH v6 5/5] powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free] Hari Bathini
@ 2023-10-16 12:07 ` Daniel Borkmann
  2023-10-17  6:26   ` Hari Bathini
  5 siblings, 1 reply; 10+ messages in thread
From: Daniel Borkmann @ 2023-10-16 12:07 UTC (permalink / raw)
  To: Hari Bathini, linuxppc-dev, bpf
  Cc: Michael Ellerman, Naveen N. Rao, Alexei Starovoitov,
	Andrii Nakryiko, Song Liu, Christophe Leroy

On 10/12/23 10:03 PM, Hari Bathini wrote:
> Most BPF programs are small, but they consume a page each. For systems
> with busy traffic and many BPF programs, this may also add significant
> pressure on instruction TLB. High iTLB pressure usually slows down the
> whole system causing visible performance degradation for production
> workloads.
> 
> bpf_prog_pack, a customized allocator that packs multiple bpf programs
> into preallocated memory chunks, was proposed [1] to address it. This
> series extends this support on powerpc.
> 
> Both bpf_arch_text_copy() & bpf_arch_text_invalidate() functions,
> needed for this support depend on instruction patching in text area.
> Currently, patch_instruction() supports patching only one instruction
> at a time. The first patch introduces patch_instructions() function
> to enable patching more than one instruction at a time. This helps in
> avoiding performance degradation while JITing bpf programs.
> 
> Patches 2 & 3 implement the above mentioned arch specific functions
> using patch_instructions(). Patch 4 fixes a misnomer in bpf JITing
> code. The last patch enables the use of BPF prog pack allocator on
> powerpc and also, ensures cleanup is handled gracefully.
> 
> [1] https://lore.kernel.org/bpf/20220204185742.271030-1-song@kernel.org/
> 
> Changes in v6:
> * No changes in patches 2-5/5 except addition of Acked-by tags from Song.
> * Skipped merging code path of patch_instruction() & patch_instructions()
>    to avoid performance overhead observed on ppc32 with that.

I presume this will be routed via Michael?

Thanks,
Daniel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator
  2023-10-16 12:07 ` [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Daniel Borkmann
@ 2023-10-17  6:26   ` Hari Bathini
  0 siblings, 0 replies; 10+ messages in thread
From: Hari Bathini @ 2023-10-17  6:26 UTC (permalink / raw)
  To: Daniel Borkmann, linuxppc-dev, bpf
  Cc: Song Liu, Alexei Starovoitov, Andrii Nakryiko, Naveen N. Rao



On 16/10/23 5:37 pm, Daniel Borkmann wrote:
> On 10/12/23 10:03 PM, Hari Bathini wrote:
>> Most BPF programs are small, but they consume a page each. For systems
>> with busy traffic and many BPF programs, this may also add significant
>> pressure on instruction TLB. High iTLB pressure usually slows down the
>> whole system causing visible performance degradation for production
>> workloads.
>>
>> bpf_prog_pack, a customized allocator that packs multiple bpf programs
>> into preallocated memory chunks, was proposed [1] to address it. This
>> series extends this support on powerpc.
>>
>> Both bpf_arch_text_copy() & bpf_arch_text_invalidate() functions,
>> needed for this support depend on instruction patching in text area.
>> Currently, patch_instruction() supports patching only one instruction
>> at a time. The first patch introduces patch_instructions() function
>> to enable patching more than one instruction at a time. This helps in
>> avoiding performance degradation while JITing bpf programs.
>>
>> Patches 2 & 3 implement the above mentioned arch specific functions
>> using patch_instructions(). Patch 4 fixes a misnomer in bpf JITing
>> code. The last patch enables the use of BPF prog pack allocator on
>> powerpc and also, ensures cleanup is handled gracefully.
>>
>> [1] https://lore.kernel.org/bpf/20220204185742.271030-1-song@kernel.org/
>>
>> Changes in v6:
>> * No changes in patches 2-5/5 except addition of Acked-by tags from Song.
>> * Skipped merging code path of patch_instruction() & patch_instructions()
>>    to avoid performance overhead observed on ppc32 with that.
> 
> I presume this will be routed via Michael?

Yes, Daniel. This can go via linuxppc tree.

Thanks
Hari

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 5/5] powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free]
  2023-10-12 20:03 ` [PATCH v6 5/5] powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free] Hari Bathini
@ 2023-10-19  6:11   ` Michael Ellerman
  2023-10-20 14:15     ` Hari Bathini
  0 siblings, 1 reply; 10+ messages in thread
From: Michael Ellerman @ 2023-10-19  6:11 UTC (permalink / raw)
  To: Hari Bathini, linuxppc-dev, bpf
  Cc: Naveen N. Rao, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Song Liu, Christophe Leroy, Song Liu

Hari Bathini <hbathini@linux.ibm.com> writes:
> Use bpf_jit_binary_pack_alloc in powerpc 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.
> With multiple jit_subprogs, bpf_jit_free is called on some subprograms
> that haven't got bpf_jit_binary_pack_finalize() yet. Implement custom
> bpf_jit_free() like in commit 1d5f82d9dd47 ("bpf, x86: fix freeing of
> not-finalized bpf_prog_pack") to call bpf_jit_binary_pack_finalize(),
> if necessary. As bpf_flush_icache() is not needed anymore, remove it.
>
> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
> Acked-by: Song Liu <song@kernel.org>
> ---
>  arch/powerpc/net/bpf_jit.h        |  18 ++---
>  arch/powerpc/net/bpf_jit_comp.c   | 106 ++++++++++++++++++++++--------
>  arch/powerpc/net/bpf_jit_comp32.c |  13 ++--
>  arch/powerpc/net/bpf_jit_comp64.c |  10 +--
>  4 files changed, 96 insertions(+), 51 deletions(-)

This causes a crash at boot on my Power7 box:

[    0.141514][    T1] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.141544][    T1] futex hash table entries: 16384 (order: 5, 2097152 bytes, vmalloc)
[    0.276735][    T1] BUG: Kernel NULL pointer dereference at 0x00000000
[    0.276757][    T1] Faulting instruction address: 0xc00000000009e154
[    0.276764][    T1] Oops: Kernel access of bad area, sig: 11 [#1]
[    0.276769][    T1] BE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=64 NUMA pSeries
[    0.276777][    T1] Modules linked in:
[    0.276783][    T1] CPU: 12 PID: 1 Comm: swapper/0 Not tainted 6.6.0-rc2-00037-ge4f551719dee-dirty #1
[    0.276790][    T1] Hardware name: IBM,8406-71Y POWER7 (raw) 0x3f0201 0xf000003 of:IBM,AA730_159 hv:phyp pSeries
[    0.276797][    T1] NIP:  c00000000009e154 LR: c00000000009e398 CTR: 0000000000000000
[    0.276803][    T1] REGS: c000000006d07580 TRAP: 0380   Not tainted  (6.6.0-rc2-00037-ge4f551719dee-dirty)
[    0.276810][    T1] MSR:  8000000000009032 <SF,EE,ME,IR,DR,RI>  CR: 28002288  XER: 0000000b
[    0.276825][    T1] CFAR: c00000000009e150 IRQMASK: 1
[    0.276825][    T1] GPR00: c00000000009e398 c000000006d07820 c000000001357a00 0000000000000000
[    0.276825][    T1] GPR04: 000000000000000a ffffffffffffffff 0000000000000000 00000007ae5c0000
[    0.276825][    T1] GPR08: c000000001441810 c0000000081f018e 00000000081f0000 0000000000004400
[    0.276825][    T1] GPR12: 0000000000000014 c00000000ee71700 0000000000000000 0000000000000000
[    0.276825][    T1] GPR16: 0000000000010000 c000000001441808 c000000001441810 c00000000000018e
[    0.276825][    T1] GPR20: c0000007b576d000 c0000007b34f3080 0000000000000000 ffffffffffffffff
[    0.276825][    T1] GPR24: 0000000000000000 c000000006c6a800 0000000000000a00 0000000000000000
[    0.276825][    T1] GPR28: c008000006490000 0000000000000a00 c0000007b576d000 0000000000000000
[    0.276899][    T1] NIP [c00000000009e154] patch_instructions+0x304/0x570
[    0.276909][    T1] LR [c00000000009e398] patch_instructions+0x548/0x570
[    0.276917][    T1] Call Trace:
[    0.276920][    T1] [c000000006d07820] [c00000000009e398] patch_instructions+0x548/0x570 (unreliable)
[    0.276930][    T1] [c000000006d07900] [c000000000120de8] bpf_arch_text_copy+0x68/0x110
[    0.276940][    T1] [c000000006d07940] [c0000000002c1f54] bpf_jit_binary_pack_finalize+0x34/0xb0
[    0.276951][    T1] [c000000006d07970] [c000000000121130] bpf_int_jit_compile+0x2a0/0x6b0
[    0.276960][    T1] [c000000006d07ac0] [c0000000002c16c4] bpf_prog_select_runtime+0x184/0x230
[    0.276970][    T1] [c000000006d07b10] [c000000000d8ea60] bpf_prepare_filter+0x520/0x730
[    0.276980][    T1] [c000000006d07b90] [c000000000d8ed0c] bpf_prog_create+0x9c/0x130
[    0.276989][    T1] [c000000006d07bd0] [c0000000013d7ca8] ptp_classifier_init+0x4c/0x80
[    0.276998][    T1] [c000000006d07c10] [c0000000013d6d90] sock_init+0xe0/0x100
[    0.277006][    T1] [c000000006d07c40] [c00000000000efb8] do_one_initcall+0x88/0x288
[    0.277014][    T1] [c000000006d07d10] [c000000001364ef0] kernel_init_freeable+0x2f4/0x39c
[    0.277024][    T1] [c000000006d07de0] [c00000000000f450] kernel_init+0x30/0x170
[    0.277032][    T1] [c000000006d07e50] [c00000000000d394] ret_from_kernel_user_thread+0x14/0x1c
[    0.277040][    T1] --- interrupt: 0 at 0x0
[    0.277149][    T1] Code: 7bff03e4 7dc7502a 7f63fb78 0b060000 792a83e4 79298284 0b090000 3d20c000 792907c6 6129018e 7d494b78 48000004 <f92e0000> 48000008 7c4004ac e8c10030
[    0.277178][    T1] ---[ end trace 0000000000000000 ]---

Code around the crash:

c00000000009e0f4:       48 34 6f 65     bl      c0000000003e5058 <is_vmalloc_or_module_addr+0x8>
c00000000009e0f8:       60 00 00 00     nop
c00000000009e0fc:       2c 03 00 00     cmpwi   r3,0
c00000000009e100:       40 82 02 90     bne     c00000000009e390 <patch_instructions+0x540>
c00000000009e104:       7f 89 e3 78     mr      r9,r28
c00000000009e108:       38 c0 00 00     li      r6,0
c00000000009e10c:       79 29 85 02     rldicl  r9,r9,48,20
c00000000009e110:       e8 ed 00 30     ld      r7,48(r13)
c00000000009e114:       e9 01 00 40     ld      r8,64(r1)
c00000000009e118:       e9 41 00 38     ld      r10,56(r1)
c00000000009e11c:       7f e8 38 2a     ldx     r31,r8,r7
c00000000009e120:       39 4a 00 10     addi    r10,r10,16
c00000000009e124:       7b ff 03 e4     clrrdi  r31,r31,16
c00000000009e128:       7d c7 50 2a     ldx     r14,r7,r10      <-- r14
c00000000009e12c:       7f 63 fb 78     or      r3,r27,r31
c00000000009e130:       0b 06 00 00     tdnei   r6,0
c00000000009e134:       79 2a 83 e4     sldi    r10,r9,16
c00000000009e138:       79 29 82 84     rldicr  r9,r9,16,10
c00000000009e13c:       0b 09 00 00     tdnei   r9,0
c00000000009e140:       3d 20 c0 00     lis     r9,-16384
c00000000009e144:       79 29 07 c6     sldi    r9,r9,32
c00000000009e148:       61 29 01 8e     ori     r9,r9,398
c00000000009e14c:       7d 49 4b 78     or      r9,r10,r9
c00000000009e150:       60 00 00 00     nop
c00000000009e154:       f9 2e 00 00     std     r9,0(r14)        <-- oops
c00000000009e158:       60 00 00 00     nop
c00000000009e15c:       7c 40 04 ac     ptesync
c00000000009e160:       e8 c1 00 30     ld      r6,48(r1)
c00000000009e164:       7f a5 eb 78     mr      r5,r29
c00000000009e168:       7e 84 a3 78     mr      r4,r20


I haven't had time to diagnose it any further. Will try and have a look tonight.

cheers

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 5/5] powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free]
  2023-10-19  6:11   ` Michael Ellerman
@ 2023-10-20 14:15     ` Hari Bathini
  0 siblings, 0 replies; 10+ messages in thread
From: Hari Bathini @ 2023-10-20 14:15 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev, bpf
  Cc: Naveen N. Rao, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Song Liu, Christophe Leroy, Song Liu



On 19/10/23 11:41 am, Michael Ellerman wrote:
> Hari Bathini <hbathini@linux.ibm.com> writes:
>> Use bpf_jit_binary_pack_alloc in powerpc 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.
>> With multiple jit_subprogs, bpf_jit_free is called on some subprograms
>> that haven't got bpf_jit_binary_pack_finalize() yet. Implement custom
>> bpf_jit_free() like in commit 1d5f82d9dd47 ("bpf, x86: fix freeing of
>> not-finalized bpf_prog_pack") to call bpf_jit_binary_pack_finalize(),
>> if necessary. As bpf_flush_icache() is not needed anymore, remove it.
>>
>> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
>> Acked-by: Song Liu <song@kernel.org>
>> ---
>>   arch/powerpc/net/bpf_jit.h        |  18 ++---
>>   arch/powerpc/net/bpf_jit_comp.c   | 106 ++++++++++++++++++++++--------
>>   arch/powerpc/net/bpf_jit_comp32.c |  13 ++--
>>   arch/powerpc/net/bpf_jit_comp64.c |  10 +--
>>   4 files changed, 96 insertions(+), 51 deletions(-)
> 
> This causes a crash at boot on my Power7 box:

Thanks, Michael.
Posted v7.

- Hari

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-10-20 14:33 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-12 20:03 [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Hari Bathini
2023-10-12 20:03 ` [PATCH v6 1/5] powerpc/code-patching: introduce patch_instructions() Hari Bathini
2023-10-12 20:03 ` [PATCH v6 2/5] powerpc/bpf: implement bpf_arch_text_copy Hari Bathini
2023-10-12 20:03 ` [PATCH v6 3/5] powerpc/bpf: implement bpf_arch_text_invalidate for bpf_prog_pack Hari Bathini
2023-10-12 20:03 ` [PATCH v6 4/5] powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data Hari Bathini
2023-10-12 20:03 ` [PATCH v6 5/5] powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free] Hari Bathini
2023-10-19  6:11   ` Michael Ellerman
2023-10-20 14:15     ` Hari Bathini
2023-10-16 12:07 ` [PATCH v6 0/5] powerpc/bpf: use BPF prog pack allocator Daniel Borkmann
2023-10-17  6:26   ` Hari Bathini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).