All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Out-of-line static calls for powerpc64 ELF V2
@ 2022-09-16  6:23 Benjamin Gray
  2022-09-16  6:23 ` [PATCH 1/6] powerpc/code-patching: Implement generic text patching function Benjamin Gray
                   ` (5 more replies)
  0 siblings, 6 replies; 21+ messages in thread
From: Benjamin Gray @ 2022-09-16  6:23 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: christophe.leroy, ajd, peterz, Benjamin Gray, npiggin, ardb,
	jbaron, rostedt, jpoimboe

Implementation of out-of-line static calls for PowerPC 64-bit ELF V2 ABI.
Static calls patch an indirect branch into a direct branch at runtime.
Out-of-line specifically has a caller directly call a trampoline, and
the trampoline gets patched to directly call the target.

More context regarding the challenges with the ELF V2 ABI is in the RFC
https://lore.kernel.org/linuxppc-dev/20220901055823.152983-1-bgray@linux.ibm.com/

This resolves the stack issue in the RFC by marking the trampoline as not
preserving the TOC, so the linker will insert its own TOC saving trampoline +
restore the TOC when the target returns.

It is sub-optimal (a separate TOC saving trampoline is not necessary), but does
not require any additional support beyond what's given in the ABI (unlike the
other two suggestions in the RFC). Microbenchmarking shows a performance improvement
in kernel-kernel-kernel calls on a Power9 when the indirect branch predictor is disabled.
However the generic implementation performs better in every other case. And when
branch prediction is enabled the generic implementation behaves like the control cases.

    |    Case    |    Generic      |     Static      |
    |------------|-----------------|-----------------|
    | control_kk | 221536 calls/ms | 221443 calls/ms |  // control is direct call, no SC trampoline
    | control_mm | 221941 calls/ms | 221913 calls/ms |
    | kkk        |  89657 calls/ms | 177835 calls/ms |  // kernel caller -> kernel tramp -> kernel target
    | kkm        |  89835 calls/ms |  53853 calls/ms |  // kernel caller -> kernel tramp -> module target
    | kmk        | 101808 calls/ms |  52280 calls/ms |  // etc.
    | kmm        | 101973 calls/ms |  52347 calls/ms |
    | mkk        |  97621 calls/ms |  78044 calls/ms |
    | mkm        |  97738 calls/ms |  38370 calls/ms |
    | mmk        |  98839 calls/ms |  68436 calls/ms |
    | mmm        |  98967 calls/ms |  68511 calls/ms |

Using a noinline page-aligned target that adds 1 to a counter then runs 64 NOPs
to iron out some processor timing quirks. The target is called in a loop like

	while (!READ_ONCE(stop))
		static_call(bench_sc)(&counter);

Again page aligned. The benchmark is stopped by a timer.

The kernel trampoline's hardcoded TOC offset is done because importing
the asm constants header imports an unrelated macro definition that is the same as the
enum name it was generated from, which confuses the compiler when it reaches said enum
definition.


Benjamin Gray (6):
  powerpc/code-patching: Implement generic text patching function
  powerpc/module: Handle caller-saved TOC in module linker
  powerpc/module: Optimise nearby branches in ELF V2 ABI stub
  static_call: Move static call selftest to static_call_selftest.c
  powerpc/64: Add support for out-of-line static calls
  powerpc/64: Add tests for out-of-line static calls

 arch/powerpc/Kconfig                     |  22 +-
 arch/powerpc/include/asm/code-patching.h |   2 +
 arch/powerpc/include/asm/static_call.h   |  80 ++++++-
 arch/powerpc/kernel/Makefile             |   4 +-
 arch/powerpc/kernel/module_64.c          |  25 ++-
 arch/powerpc/kernel/static_call.c        | 203 ++++++++++++++++-
 arch/powerpc/kernel/static_call_test.c   | 263 +++++++++++++++++++++++
 arch/powerpc/lib/code-patching.c         | 135 ++++++++----
 kernel/Makefile                          |   1 +
 kernel/static_call_inline.c              |  43 ----
 kernel/static_call_selftest.c            |  41 ++++
 11 files changed, 713 insertions(+), 106 deletions(-)
 create mode 100644 arch/powerpc/kernel/static_call_test.c
 create mode 100644 kernel/static_call_selftest.c

--
2.37.3

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

* [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-16  6:23 [PATCH 0/6] Out-of-line static calls for powerpc64 ELF V2 Benjamin Gray
@ 2022-09-16  6:23 ` Benjamin Gray
  2022-09-16  9:39   ` kernel test robot
                     ` (3 more replies)
  2022-09-16  6:23 ` [PATCH 2/6] powerpc/module: Handle caller-saved TOC in module linker Benjamin Gray
                   ` (4 subsequent siblings)
  5 siblings, 4 replies; 21+ messages in thread
From: Benjamin Gray @ 2022-09-16  6:23 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: christophe.leroy, ajd, peterz, Benjamin Gray, npiggin, ardb,
	jbaron, rostedt, jpoimboe

Adds a generic text patching mechanism for patches of 1, 2, 4, or 8
bytes. The patcher conditionally syncs the icache depending on if
the content will be executed (as opposed to, e.g., read-only data).

The `patch_instruction` function is reimplemented in terms of this
more generic function. This generic implementation allows patching of
arbitrary 64-bit data, whereas the original `patch_instruction` decided
the size based on the 'instruction' opcode, so was not suitable for
arbitrary data.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/include/asm/code-patching.h |   1 +
 arch/powerpc/lib/code-patching.c         | 135 +++++++++++++++--------
 2 files changed, 89 insertions(+), 47 deletions(-)

diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 1c6316ec4b74..6a52c19dae46 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -76,6 +76,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_text_data(void *dest, const void *src, size_t size);
 
 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 ad0cf3108dd0..a09a0898c2ce 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -3,6 +3,7 @@
  *  Copyright 2008 Michael Ellerman, IBM Corporation.
  */
 
+#include <linux/mm.h>
 #include <linux/kprobes.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
@@ -14,32 +15,7 @@
 #include <asm/page.h>
 #include <asm/code-patching.h>
 #include <asm/inst.h>
-
-static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr, u32 *patch_addr)
-{
-	if (!ppc_inst_prefixed(instr)) {
-		u32 val = ppc_inst_val(instr);
-
-		__put_kernel_nofault(patch_addr, &val, u32, failed);
-	} else {
-		u64 val = ppc_inst_as_ulong(instr);
-
-		__put_kernel_nofault(patch_addr, &val, u64, failed);
-	}
-
-	asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
-							    "r" (exec_addr));
-
-	return 0;
-
-failed:
-	return -EPERM;
-}
-
-int raw_patch_instruction(u32 *addr, ppc_inst_t instr)
-{
-	return __patch_instruction(addr, instr, addr);
-}
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_STRICT_KERNEL_RWX
 static DEFINE_PER_CPU(struct vm_struct *, text_poke_area);
@@ -147,16 +123,44 @@ static void unmap_patch_area(unsigned long addr)
 	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
 }
 
-static int __do_patch_instruction(u32 *addr, ppc_inst_t instr)
+static int __patch_text(void *dest, const void *src, size_t size, bool is_exec, void *exec_addr)
+{
+	if (virt_to_pfn(dest) != virt_to_pfn(dest + size - 1))
+		return -EFAULT;
+
+	switch (size) {
+		case 1:
+			__put_kernel_nofault(dest, src, u8, failed);
+			break;
+		case 2:
+			__put_kernel_nofault(dest, src, u16, failed);
+			break;
+		case 4:
+			__put_kernel_nofault(dest, src, u32, failed);
+			break;
+		case 8:
+			__put_kernel_nofault(dest, src, u64, failed);
+			break;
+	}
+
+	asm ("dcbst 0, %0; sync" :: "r" (dest));
+
+	if (is_exec)
+		asm ("icbi 0,%0; sync; isync" :: "r" (exec_addr));
+
+	return 0;
+
+failed:
+	return -EPERM;
+}
+
+static pte_t *start_text_patch(void* dest, u32 **patch_addr)
 {
-	int err;
-	u32 *patch_addr;
-	unsigned long text_poke_addr;
 	pte_t *pte;
-	unsigned long pfn = get_patch_pfn(addr);
+	unsigned long text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr & PAGE_MASK;
+	unsigned long pfn = get_patch_pfn(dest);
 
-	text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr & PAGE_MASK;
-	patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
+	*patch_addr = (u32 *)(text_poke_addr + offset_in_page(dest));
 
 	pte = virt_to_kpte(text_poke_addr);
 	__set_pte_at(&init_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), 0);
@@ -164,33 +168,63 @@ static int __do_patch_instruction(u32 *addr, ppc_inst_t instr)
 	if (radix_enabled())
 		asm volatile("ptesync": : :"memory");
 
-	err = __patch_instruction(addr, instr, patch_addr);
+	return pte;
+}
 
+static void finish_text_patch(pte_t *pte)
+{
+	unsigned long text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr & PAGE_MASK;
 	pte_clear(&init_mm, text_poke_addr, pte);
 	flush_tlb_kernel_range(text_poke_addr, text_poke_addr + PAGE_SIZE);
+}
+
+static int do_patch_text(void *dest, const void *src, size_t size, bool is_exec)
+{
+	int err;
+	pte_t *pte;
+	u32 *patch_addr;
+
+	pte = start_text_patch(dest, &patch_addr);
+	err = __patch_text(patch_addr, src, size, is_exec, dest);
+	finish_text_patch(pte);
 
 	return err;
 }
 
-static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
+static int patch_text(void *dest, const void *src, size_t size, bool is_exec)
 {
 	int err;
 	unsigned long flags;
 
-	/*
-	 * During early early boot patch_instruction is called
-	 * when text_poke_area is not ready, but we still need
-	 * to allow patching. We just do the plain old patching
-	 */
+	/* Make sure we aren't patching a freed init section */
+	if (static_branch_likely(&init_mem_is_free) && init_section_contains(dest, 4))
+		return 0;
+
 	if (!static_branch_likely(&poking_init_done))
-		return raw_patch_instruction(addr, instr);
+		return __patch_text(dest, src, size, is_exec, dest);
 
 	local_irq_save(flags);
-	err = __do_patch_instruction(addr, instr);
+	err = do_patch_text(dest, src, size, is_exec);
 	local_irq_restore(flags);
 
 	return err;
 }
+
+int patch_text_data(void *dest, const void *src, size_t size) {
+	return patch_text(dest, src, size, false);
+}
+
+int raw_patch_instruction(u32 *addr, ppc_inst_t instr)
+{
+	if (!ppc_inst_prefixed(instr)) {
+		u32 val = ppc_inst_val(instr);
+		return __patch_text(addr, &val, sizeof(val), true, addr);
+	} else {
+		u64 val = ppc_inst_as_ulong(instr);
+		return __patch_text(addr, &val, sizeof(val), true, addr);
+	}
+}
+
 #else /* !CONFIG_STRICT_KERNEL_RWX */
 
 static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
@@ -198,17 +232,24 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
 	return raw_patch_instruction(addr, instr);
 }
 
+void *patch_memory(void *dest, const void *src, size_t size)
+{
+	return memcpy(dest, src, size);
+}
+
 #endif /* CONFIG_STRICT_KERNEL_RWX */
 
 __ro_after_init DEFINE_STATIC_KEY_FALSE(init_mem_is_free);
 
 int patch_instruction(u32 *addr, ppc_inst_t instr)
 {
-	/* Make sure we aren't patching a freed init section */
-	if (static_branch_likely(&init_mem_is_free) && init_section_contains(addr, 4))
-		return 0;
-
-	return do_patch_instruction(addr, instr);
+	if (!ppc_inst_prefixed(instr)) {
+		u32 val = ppc_inst_val(instr);
+		return patch_text(addr, &val, sizeof(val), true);
+	} else {
+		u64 val = ppc_inst_as_ulong(instr);
+		return patch_text(addr, &val, sizeof(val), true);
+	}
 }
 NOKPROBE_SYMBOL(patch_instruction);
 
-- 
2.37.3


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

* [PATCH 2/6] powerpc/module: Handle caller-saved TOC in module linker
  2022-09-16  6:23 [PATCH 0/6] Out-of-line static calls for powerpc64 ELF V2 Benjamin Gray
  2022-09-16  6:23 ` [PATCH 1/6] powerpc/code-patching: Implement generic text patching function Benjamin Gray
@ 2022-09-16  6:23 ` Benjamin Gray
  2022-09-19  6:09   ` Christophe Leroy
  2022-09-16  6:23 ` [PATCH 3/6] powerpc/module: Optimise nearby branches in ELF V2 ABI stub Benjamin Gray
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 21+ messages in thread
From: Benjamin Gray @ 2022-09-16  6:23 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: christophe.leroy, ajd, peterz, Benjamin Gray, npiggin, ardb,
	jbaron, rostedt, jpoimboe

The callee may set a field in `st_other` to 1 to indicate r2 should be
treated as caller-saved. This means a trampoline must be used to save
the current TOC before calling it and restore it afterwards, much like
external calls.

This is necessary for supporting V2 ABI static calls that do not
preserve the TOC.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/kernel/module_64.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 7e45dc98df8a..3656476097c2 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -55,6 +55,11 @@ static unsigned int local_entry_offset(const Elf64_Sym *sym)
 	 * of function and try to derive r2 from it). */
 	return PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
 }
+
+static bool need_r2save_stub(unsigned char st_other) {
+	return ((st_other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT) == 1;
+}
+
 #else
 
 static func_desc_t func_desc(unsigned long addr)
@@ -66,6 +71,10 @@ static unsigned int local_entry_offset(const Elf64_Sym *sym)
 	return 0;
 }
 
+static bool need_r2save_stub(unsigned char st_other) {
+	return false;
+}
+
 void *dereference_module_function_descriptor(struct module *mod, void *ptr)
 {
 	if (ptr < (void *)mod->arch.start_opd ||
@@ -632,7 +641,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
 		case R_PPC_REL24:
 			/* FIXME: Handle weak symbols here --RR */
 			if (sym->st_shndx == SHN_UNDEF ||
-			    sym->st_shndx == SHN_LIVEPATCH) {
+			    sym->st_shndx == SHN_LIVEPATCH ||
+			    need_r2save_stub(sym->st_other)) {
 				/* External: go via stub */
 				value = stub_for_addr(sechdrs, value, me,
 						strtab + sym->st_name);
-- 
2.37.3


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

* [PATCH 3/6] powerpc/module: Optimise nearby branches in ELF V2 ABI stub
  2022-09-16  6:23 [PATCH 0/6] Out-of-line static calls for powerpc64 ELF V2 Benjamin Gray
  2022-09-16  6:23 ` [PATCH 1/6] powerpc/code-patching: Implement generic text patching function Benjamin Gray
  2022-09-16  6:23 ` [PATCH 2/6] powerpc/module: Handle caller-saved TOC in module linker Benjamin Gray
@ 2022-09-16  6:23 ` Benjamin Gray
  2022-09-19  6:11   ` Christophe Leroy
  2022-09-16  6:23 ` [PATCH 4/6] static_call: Move static call selftest to static_call_selftest.c Benjamin Gray
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 21+ messages in thread
From: Benjamin Gray @ 2022-09-16  6:23 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: christophe.leroy, ajd, peterz, Benjamin Gray, npiggin, ardb,
	jbaron, rostedt, jpoimboe

Inserts a direct branch to the stub target when possible, replacing the
mtctr/btctr sequence.

The load into r12 could potentially be skipped too, but that change
would need to refactor the arguments to indicate that the address
does not have a separate local entry point.

This helps the static call implementation, where modules calling their
own trampolines are called through this stub and the trampoline is
easily within range of a direct branch.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/kernel/module_64.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 3656476097c2..03ab28d86008 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -432,8 +432,17 @@ static inline int create_stub(const Elf64_Shdr *sechdrs,
 		return create_ftrace_stub(entry, addr, me);
 
 	for (i = 0; i < ARRAY_SIZE(ppc64_stub_insns); i++) {
-		if (patch_instruction(&entry->jump[i],
-				      ppc_inst(ppc64_stub_insns[i])))
+		ppc_inst_t inst = ppc_inst(ppc64_stub_insns[i]);
+
+		// Replace the indirect branch with a direct branch where possible
+		if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2) && i == 4) {
+			ppc_inst_t direct;
+			if (create_branch(&direct, (void*) entry + (i * 4), addr, 0) == 0) {
+				inst = direct;
+			}
+		}
+
+		if (patch_instruction(&entry->jump[i], inst))
 			return 0;
 	}
 
-- 
2.37.3


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

* [PATCH 4/6] static_call: Move static call selftest to static_call_selftest.c
  2022-09-16  6:23 [PATCH 0/6] Out-of-line static calls for powerpc64 ELF V2 Benjamin Gray
                   ` (2 preceding siblings ...)
  2022-09-16  6:23 ` [PATCH 3/6] powerpc/module: Optimise nearby branches in ELF V2 ABI stub Benjamin Gray
@ 2022-09-16  6:23 ` Benjamin Gray
  2022-09-20  4:30   ` Andrew Donnellan
  2022-09-16  6:23 ` [PATCH 5/6] powerpc/64: Add support for out-of-line static calls Benjamin Gray
  2022-09-16  6:23 ` [PATCH 6/6] powerpc/64: Add tests " Benjamin Gray
  5 siblings, 1 reply; 21+ messages in thread
From: Benjamin Gray @ 2022-09-16  6:23 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: christophe.leroy, ajd, peterz, Benjamin Gray, npiggin, ardb,
	jbaron, rostedt, jpoimboe

These tests are out-of-line only, so moving them to the
their own file allows them to be run when an arch does
not implement inline static calls.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 kernel/Makefile               |  1 +
 kernel/static_call_inline.c   | 43 -----------------------------------
 kernel/static_call_selftest.c | 41 +++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 43 deletions(-)
 create mode 100644 kernel/static_call_selftest.c

diff --git a/kernel/Makefile b/kernel/Makefile
index 318789c728d3..8ce8beaa3cc0 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_KCSAN) += kcsan/
 obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
 obj-$(CONFIG_HAVE_STATIC_CALL) += static_call.o
 obj-$(CONFIG_HAVE_STATIC_CALL_INLINE) += static_call_inline.o
+obj-$(CONFIG_STATIC_CALL_SELFTEST) += static_call_selftest.o
 obj-$(CONFIG_CFI_CLANG) += cfi.o
 
 obj-$(CONFIG_PERF_EVENTS) += events/
diff --git a/kernel/static_call_inline.c b/kernel/static_call_inline.c
index dc5665b62814..64d04d054698 100644
--- a/kernel/static_call_inline.c
+++ b/kernel/static_call_inline.c
@@ -498,46 +498,3 @@ int __init static_call_init(void)
 	return 0;
 }
 early_initcall(static_call_init);
-
-#ifdef CONFIG_STATIC_CALL_SELFTEST
-
-static int func_a(int x)
-{
-	return x+1;
-}
-
-static int func_b(int x)
-{
-	return x+2;
-}
-
-DEFINE_STATIC_CALL(sc_selftest, func_a);
-
-static struct static_call_data {
-      int (*func)(int);
-      int val;
-      int expect;
-} static_call_data [] __initdata = {
-      { NULL,   2, 3 },
-      { func_b, 2, 4 },
-      { func_a, 2, 3 }
-};
-
-static int __init test_static_call_init(void)
-{
-      int i;
-
-      for (i = 0; i < ARRAY_SIZE(static_call_data); i++ ) {
-	      struct static_call_data *scd = &static_call_data[i];
-
-              if (scd->func)
-                      static_call_update(sc_selftest, scd->func);
-
-              WARN_ON(static_call(sc_selftest)(scd->val) != scd->expect);
-      }
-
-      return 0;
-}
-early_initcall(test_static_call_init);
-
-#endif /* CONFIG_STATIC_CALL_SELFTEST */
diff --git a/kernel/static_call_selftest.c b/kernel/static_call_selftest.c
new file mode 100644
index 000000000000..246ad89f64eb
--- /dev/null
+++ b/kernel/static_call_selftest.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/static_call.h>
+
+static int func_a(int x)
+{
+	return x+1;
+}
+
+static int func_b(int x)
+{
+	return x+2;
+}
+
+DEFINE_STATIC_CALL(sc_selftest, func_a);
+
+static struct static_call_data {
+	int (*func)(int);
+	int val;
+	int expect;
+} static_call_data [] __initdata = {
+	{ NULL,   2, 3 },
+	{ func_b, 2, 4 },
+	{ func_a, 2, 3 }
+};
+
+static int __init test_static_call_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(static_call_data); i++ ) {
+		struct static_call_data *scd = &static_call_data[i];
+
+		if (scd->func)
+			static_call_update(sc_selftest, scd->func);
+
+		WARN_ON(static_call(sc_selftest)(scd->val) != scd->expect);
+	}
+
+	return 0;
+}
+early_initcall(test_static_call_init);
-- 
2.37.3


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

* [PATCH 5/6] powerpc/64: Add support for out-of-line static calls
  2022-09-16  6:23 [PATCH 0/6] Out-of-line static calls for powerpc64 ELF V2 Benjamin Gray
                   ` (3 preceding siblings ...)
  2022-09-16  6:23 ` [PATCH 4/6] static_call: Move static call selftest to static_call_selftest.c Benjamin Gray
@ 2022-09-16  6:23 ` Benjamin Gray
  2022-09-16  8:32   ` kernel test robot
  2022-09-16  6:23 ` [PATCH 6/6] powerpc/64: Add tests " Benjamin Gray
  5 siblings, 1 reply; 21+ messages in thread
From: Benjamin Gray @ 2022-09-16  6:23 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: christophe.leroy, ajd, peterz, Benjamin Gray, npiggin, ardb,
	jbaron, rostedt, jpoimboe

Implement static call support for 64 bit V2 ABI. This requires
making sure the TOC is kept correct across kernel-module
boundaries. As a secondary concern, it tries to use the local
entry point of a target wherever possible. It does so by
checking if both tramp & target are kernel code, and falls
back to detecting the common global entry point patterns
if modules are involved. Detecting the global entry point is
also required for setting the local entry point as the trampoline
target: if we cannot detect the local entry point, then we need to
convservatively initialise r12 and use the global entry point.

The trampolines are marked with `.localentry NAME, 1` to make the
linker save and restore the TOC on each call to the trampoline. This
allows the trampoline to safely target functions with different TOC
values.

However this directive also implies the TOC is not initialised on entry
to the trampoline. The kernel TOC is easily found in the PACA, but not
an arbitrary module TOC. Therefore the trampoline implementation depends
on whether it's in the kernel or not. If in the kernel, we initialise
the TOC using the PACA. If in a module, we have to initialise the TOC
with zero context, so it's quite expensive.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/Kconfig                     | 12 +++-
 arch/powerpc/include/asm/code-patching.h |  1 +
 arch/powerpc/include/asm/static_call.h   | 80 +++++++++++++++++++--
 arch/powerpc/kernel/Makefile             |  3 +-
 arch/powerpc/kernel/static_call.c        | 92 ++++++++++++++++++++++--
 5 files changed, 175 insertions(+), 13 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 4c466acdc70d..d3bb61e0de43 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -248,7 +248,7 @@ config PPC
 	select HAVE_SOFTIRQ_ON_OWN_STACK
 	select HAVE_STACKPROTECTOR		if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2)
 	select HAVE_STACKPROTECTOR		if PPC64 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r13)
-	select HAVE_STATIC_CALL			if PPC32
+	select HAVE_STATIC_CALL			if PPC_ENABLE_STATIC_CALL
 	select HAVE_SYSCALL_TRACEPOINTS
 	select HAVE_VIRT_CPU_ACCOUNTING
 	select HUGETLB_PAGE_SIZE_VARIABLE	if PPC_BOOK3S_64 && HUGETLB_PAGE
@@ -1023,6 +1023,16 @@ config PPC_RTAS_FILTER
 	  Say Y unless you know what you are doing and the filter is causing
 	  problems for you.
 
+config PPC_ENABLE_STATIC_CALL
+	bool "Enable static calls"
+	default y
+	depends on PPC32 || PPC64_ELF_ABI_V2
+	help
+	  PowerPC static calls with the ELF V2 ABI must ensure the TOC remains
+	  consistent. The benefit is only noticeable when indirect branch prediction
+	  is disabled. Otherwise, the generic implementation is better as it is
+	  inlined and effectively a direct branch with a hot predictor.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 6a52c19dae46..1ab7f3522da2 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -126,6 +126,7 @@ int translate_branch(ppc_inst_t *instr, const u32 *dest, const u32 *src);
 bool is_conditional_branch(ppc_inst_t instr);
 
 #define OP_RT_RA_MASK	0xffff0000UL
+#define OP_SI_MASK	0x0000ffffUL
 #define LIS_R2		(PPC_RAW_LIS(_R2, 0))
 #define ADDIS_R2_R12	(PPC_RAW_ADDIS(_R2, _R12, 0))
 #define ADDI_R2_R2	(PPC_RAW_ADDI(_R2, _R2, 0))
diff --git a/arch/powerpc/include/asm/static_call.h b/arch/powerpc/include/asm/static_call.h
index de1018cc522b..5e763cf16e9c 100644
--- a/arch/powerpc/include/asm/static_call.h
+++ b/arch/powerpc/include/asm/static_call.h
@@ -2,12 +2,75 @@
 #ifndef _ASM_POWERPC_STATIC_CALL_H
 #define _ASM_POWERPC_STATIC_CALL_H
 
+#ifdef CONFIG_PPC64_ELF_ABI_V2
+
+#ifdef MODULE
+
+#define __PPC_SCT(name, inst)					\
+	asm(".pushsection .text, \"ax\"				\n"	\
+	    ".align 6						\n"	\
+	    ".globl " STATIC_CALL_TRAMP_STR(name) "		\n"	\
+	    ".localentry " STATIC_CALL_TRAMP_STR(name) ", 1	\n"	\
+	    STATIC_CALL_TRAMP_STR(name) ":			\n"	\
+	    "	mflr	11					\n"	\
+	    "	bcl	20, 31, $+4				\n"	\
+	    "0:	mflr	12					\n"	\
+	    "	mtlr	11					\n"	\
+	    "	addi	12, 12, (" STATIC_CALL_TRAMP_STR(name) " - 0b)	\n"	\
+	    "	addis 2, 12, (.TOC.-" STATIC_CALL_TRAMP_STR(name) ")@ha	\n"	\
+	    "	addi 2, 2, (.TOC.-" STATIC_CALL_TRAMP_STR(name) ")@l	\n"	\
+	    "	" inst "					\n"	\
+	    "	ld	12, (2f - " STATIC_CALL_TRAMP_STR(name) ")(12)	\n"	\
+	    "	mtctr	12					\n"	\
+	    "	bctr						\n"	\
+	    "1:	li	3, 0					\n"	\
+	    "	blr						\n"	\
+	    ".balign 8						\n"	\
+	    "2:	.8byte 0					\n"	\
+	    ".type " STATIC_CALL_TRAMP_STR(name) ", @function	\n"	\
+	    ".size " STATIC_CALL_TRAMP_STR(name) ", . - " STATIC_CALL_TRAMP_STR(name) " \n" \
+	    ".popsection					\n")
+
+#else /* KERNEL */
+
+#define __PPC_SCT(name, inst)					\
+	asm(".pushsection .text, \"ax\"				\n"	\
+	    ".align 5						\n"	\
+	    ".globl " STATIC_CALL_TRAMP_STR(name) "		\n"	\
+	    ".localentry " STATIC_CALL_TRAMP_STR(name) ", 1	\n"	\
+	    STATIC_CALL_TRAMP_STR(name) ":			\n"	\
+	    "	ld	2, 16(13)				\n"	\
+	    "	" inst "					\n"	\
+	    "	addis	12, 2, 2f@toc@ha			\n"	\
+	    "	ld	12, 2f@toc@l(12)			\n"	\
+	    "	mtctr	12					\n"	\
+	    "	bctr						\n"	\
+	    "1:	li	3, 0					\n"	\
+	    "	blr						\n"	\
+	    ".balign 8						\n"	\
+	    "2:	.8byte 0					\n"	\
+	    ".type " STATIC_CALL_TRAMP_STR(name) ", @function	\n"	\
+	    ".size " STATIC_CALL_TRAMP_STR(name) ", . - " STATIC_CALL_TRAMP_STR(name) " \n" \
+	    ".popsection					\n")
+
+#endif /* MODULE */
+
+#define PPC_SCT_INST_MODULE		28		/* Offset of instruction to update */
+#define PPC_SCT_RET0_MODULE		44		/* Offset of label 1 */
+#define PPC_SCT_DATA_MODULE		56		/* Offset of label 2 (aligned) */
+
+#define PPC_SCT_INST_KERNEL		4		/* Offset of instruction to update */
+#define PPC_SCT_RET0_KERNEL		24		/* Offset of label 1 */
+#define PPC_SCT_DATA_KERNEL		32		/* Offset of label 2 (aligned) */
+
+#elif defined(PPC32)
+
 #define __PPC_SCT(name, inst)					\
 	asm(".pushsection .text, \"ax\"				\n"	\
 	    ".align 5						\n"	\
 	    ".globl " STATIC_CALL_TRAMP_STR(name) "		\n"	\
 	    STATIC_CALL_TRAMP_STR(name) ":			\n"	\
-	    inst "						\n"	\
+	    "	" inst "					\n"	\
 	    "	lis	12,2f@ha				\n"	\
 	    "	lwz	12,2f@l(12)				\n"	\
 	    "	mtctr	12					\n"	\
@@ -19,11 +82,20 @@
 	    ".size " STATIC_CALL_TRAMP_STR(name) ", . - " STATIC_CALL_TRAMP_STR(name) " \n" \
 	    ".popsection					\n")
 
-#define PPC_SCT_RET0		20		/* Offset of label 1 */
-#define PPC_SCT_DATA		28		/* Offset of label 2 */
+#define PPC_SCT_INST_MODULE		0		/* Offset of instruction to update */
+#define PPC_SCT_RET0_MODULE		20		/* Offset of label 1 */
+#define PPC_SCT_DATA_MODULE		28		/* Offset of label 2 */
+
+#define PPC_SCT_INST_KERNEL		PPC_SCT_INST_MODULE
+#define PPC_SCT_RET0_KERNEL		PPC_SCT_RET0_MODULE
+#define PPC_SCT_DATA_KERNEL		PPC_SCT_DATA_MODULE
+
+#else /* !CONFIG_PPC64_ELF_ABI_V2 && !PPC32 */
+#error "Unsupported ABI"
+#endif /* CONFIG_PPC64_ELF_ABI_V2 */
 
 #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)	__PPC_SCT(name, "b " #func)
 #define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name)	__PPC_SCT(name, "blr")
-#define ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name)	__PPC_SCT(name, "b .+20")
+#define ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name)	__PPC_SCT(name, "b 1f")
 
 #endif /* _ASM_POWERPC_STATIC_CALL_H */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 06d2d1f78f71..a30d0d0f5499 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -128,8 +128,9 @@ extra-y				+= vmlinux.lds
 
 obj-$(CONFIG_RELOCATABLE)	+= reloc_$(BITS).o
 
-obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o early_32.o static_call.o
+obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o early_32.o
 obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
+obj-$(CONFIG_HAVE_STATIC_CALL)	+= static_call.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/powerpc/kernel/static_call.c b/arch/powerpc/kernel/static_call.c
index 863a7aa24650..d2d9b496381d 100644
--- a/arch/powerpc/kernel/static_call.c
+++ b/arch/powerpc/kernel/static_call.c
@@ -1,33 +1,111 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <asm/code-patching.h>
+#include <linux/export.h>
+#include <linux/kconfig.h>
+#include <linux/kernel.h>
 #include <linux/memory.h>
 #include <linux/static_call.h>
+#include <linux/syscalls.h>
 
-#include <asm/code-patching.h>
+static void* ppc_function_toc(u32 *func) {
+	if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2)) {
+		u32 insn1 = *func;
+		u32 insn2 = *(func+1);
+		u64 si1 = sign_extend64((insn1 & OP_SI_MASK) << 16, 31);
+		u64 si2 = sign_extend64(insn2 & OP_SI_MASK, 15);
+		u64 addr = ((u64) func + si1) + si2;
+
+		if ((((insn1 & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
+		     ((insn1 & OP_RT_RA_MASK) == LIS_R2)) &&
+		    ((insn2 & OP_RT_RA_MASK) == ADDI_R2_R2))
+			return (void*)addr;
+	}
+
+	return NULL;
+}
+
+static bool shares_toc(void *func1, void *func2) {
+	if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2)) {
+		void* func1_toc;
+		void* func2_toc;
+
+		if (func1 == NULL || func2 == NULL)
+			return false;
+
+		/* Assume the kernel only uses a single TOC */
+		if (core_kernel_text((unsigned long)func1) &&
+		    core_kernel_text((unsigned long)func2))
+			return true;
+
+		/* Fall back to calculating the TOC from common patterns
+		 * if modules are involved
+		 */
+		func1_toc = ppc_function_toc(func1);
+		func2_toc = ppc_function_toc(func2);
+		return func1_toc != NULL && func2_toc != NULL && (func1_toc == func2_toc);
+	}
+
+	return true;
+}
+
+static unsigned long get_inst_addr(unsigned long tramp) {
+	return tramp + (core_kernel_text(tramp) ? PPC_SCT_INST_KERNEL : PPC_SCT_INST_MODULE);
+}
+
+static unsigned long get_ret0_addr(unsigned long tramp) {
+	return tramp + (core_kernel_text(tramp) ? PPC_SCT_RET0_KERNEL : PPC_SCT_RET0_MODULE);
+}
+
+static unsigned long get_data_addr(unsigned long tramp) {
+	return tramp + (core_kernel_text(tramp) ? PPC_SCT_DATA_KERNEL : PPC_SCT_DATA_MODULE);
+}
 
 void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
 {
 	int err;
 	bool is_ret0 = (func == __static_call_return0);
-	unsigned long target = (unsigned long)(is_ret0 ? tramp + PPC_SCT_RET0 : func);
-	bool is_short = is_offset_in_branch_range((long)target - (long)tramp);
+	unsigned long target = is_ret0
+		? get_ret0_addr((unsigned long)tramp)
+		: (unsigned long)func;
+	bool is_short;
+	void* tramp_inst;
 
 	if (!tramp)
 		return;
 
+	tramp_inst = (void*)get_inst_addr((unsigned long)tramp);
+
+	if (is_ret0) {
+		is_short = true;
+	} else if (shares_toc(tramp, (void*)target)) {
+		/* Confirm that the local entry point is in range */
+		is_short = is_offset_in_branch_range(
+			(long)ppc_function_entry((void*)target) - (long)tramp_inst);
+	} else {
+		/* Combine out-of-range with not sharing a TOC. Though it's possible an
+		 * out-of-range target shares a TOC, handling this separately complicates
+		 * the trampoline. It's simpler to always use the global entry point
+		 * in this case.
+		 */
+		is_short = false;
+	}
+
 	mutex_lock(&text_mutex);
 
 	if (func && !is_short) {
-		err = patch_instruction(tramp + PPC_SCT_DATA, ppc_inst(target));
+		err = patch_text_data(
+			(void*)get_data_addr((unsigned long)tramp), &target, sizeof(target));
 		if (err)
 			goto out;
 	}
 
 	if (!func)
-		err = patch_instruction(tramp, ppc_inst(PPC_RAW_BLR()));
+		err = patch_instruction(tramp_inst, ppc_inst(PPC_RAW_BLR()));
 	else if (is_short)
-		err = patch_branch(tramp, target, 0);
+		err = patch_branch(tramp_inst, ppc_function_entry((void*)target), 0);
 	else
-		err = patch_instruction(tramp, ppc_inst(PPC_RAW_NOP()));
+		err = patch_instruction(tramp_inst, ppc_inst(PPC_RAW_NOP()));
+
 out:
 	mutex_unlock(&text_mutex);
 
-- 
2.37.3


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

* [PATCH 6/6] powerpc/64: Add tests for out-of-line static calls
  2022-09-16  6:23 [PATCH 0/6] Out-of-line static calls for powerpc64 ELF V2 Benjamin Gray
                   ` (4 preceding siblings ...)
  2022-09-16  6:23 ` [PATCH 5/6] powerpc/64: Add support for out-of-line static calls Benjamin Gray
@ 2022-09-16  6:23 ` Benjamin Gray
  5 siblings, 0 replies; 21+ messages in thread
From: Benjamin Gray @ 2022-09-16  6:23 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: christophe.leroy, ajd, peterz, Benjamin Gray, npiggin, ardb,
	jbaron, rostedt, jpoimboe

KUnit tests for the various combinations of caller/trampoline/target and
kernel/module. They must be run from a module loaded at runtime to
guarantee they have a different TOC to the kernel.

The tests try to mitigate the chance of panicing by restoring the
TOC after every static call. Not all possible errors can be caught
by this (we can't stop a trampoline from using a bad TOC itself),
but it makes certain errors easier to debug.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
 arch/powerpc/Kconfig                   |  10 +
 arch/powerpc/kernel/Makefile           |   1 +
 arch/powerpc/kernel/static_call.c      | 111 +++++++++++
 arch/powerpc/kernel/static_call_test.c | 263 +++++++++++++++++++++++++
 4 files changed, 385 insertions(+)
 create mode 100644 arch/powerpc/kernel/static_call_test.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index d3bb61e0de43..86fb7444dd85 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -1033,6 +1033,16 @@ config PPC_ENABLE_STATIC_CALL
 	  is disabled. Otherwise, the generic implementation is better as it is
 	  inlined and effectively a direct branch with a hot predictor.
 
+config PPC_STATIC_CALL_KUNIT_TEST
+	tristate "KUnit tests for PPC64 ELF ABI V2 static calls"
+	default KUNIT_ALL_TESTS
+	depends on HAVE_STATIC_CALL && PPC64_ELF_ABI_V2 && KUNIT && m
+	help
+	  Tests that check the TOC is kept consistent across all combinations
+	  of caller/trampoline/target being kernel/module. Must be built as a
+	  module and loaded at runtime to ensure the module has a different
+	  TOC to the kernel.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index a30d0d0f5499..22c07e3d34df 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -131,6 +131,7 @@ obj-$(CONFIG_RELOCATABLE)	+= reloc_$(BITS).o
 obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o early_32.o
 obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
 obj-$(CONFIG_HAVE_STATIC_CALL)	+= static_call.o
+obj-$(CONFIG_PPC_STATIC_CALL_KUNIT_TEST)	+= static_call_test.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/powerpc/kernel/static_call.c b/arch/powerpc/kernel/static_call.c
index d2d9b496381d..18c78f7b044a 100644
--- a/arch/powerpc/kernel/static_call.c
+++ b/arch/powerpc/kernel/static_call.c
@@ -113,3 +113,114 @@ void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
 		panic("%s: patching failed %pS at %pS\n", __func__, func, tramp);
 }
 EXPORT_SYMBOL_GPL(arch_static_call_transform);
+
+
+#if IS_MODULE(CONFIG_PPC_STATIC_CALL_KUNIT_TEST)
+
+#include <kunit/test.h>
+
+/* The following are some kernel hooks for testing the static call
+ * implementation from the static_call_test module. The bulk of the
+ * assertions are run in that module, except for the TOC checks that
+ * must be done in the core kernel context.
+ */
+
+/* Reserve these registers for testing (same registers as in static_call_test.c) */
+register void* current_toc asm ("r2");
+register void* module_toc asm ("r14");
+register void* actual_module_toc asm ("r15");
+register void* kernel_toc asm ("r16");
+register void* actual_toc asm ("r17");
+
+static void* static_kernel_toc;
+static void* static_actual_toc;
+
+#define restore_toc(test) \
+	actual_toc = current_toc; \
+	current_toc = kernel_toc
+
+#define check_toc(test) KUNIT_EXPECT_PTR_EQ(test, kernel_toc, actual_toc)
+
+#define toc_fixup(test) \
+	restore_toc(); \
+	check_toc(test)
+
+#define PROTECTED_SC(test, call) \
+({ \
+	long ret; \
+	ret = call; \
+	toc_fixup(test); \
+	ret; \
+})
+
+void ppc_sc_kernel_toc_init(void)
+{
+	static_kernel_toc = kernel_toc;
+	static_actual_toc = actual_toc;  /* save so we can restore when the tests finish */
+
+	kernel_toc = current_toc;
+}
+
+void ppc_sc_kernel_toc_exit(void)
+{
+	kernel_toc = static_kernel_toc;
+	actual_toc = static_actual_toc;
+}
+
+int ppc_sc_kernel_target_1(struct kunit* test)
+{
+	toc_fixup(test);
+	return 1;
+}
+
+int ppc_sc_kernel_target_2(struct kunit* test)
+{
+	toc_fixup(test);
+	return 2;
+}
+
+DEFINE_STATIC_CALL(ppc_sc_kernel, ppc_sc_kernel_target_1);
+
+int ppc_sc_kernel_call(struct kunit* test)
+{
+	return PROTECTED_SC(test, static_call(ppc_sc_kernel)(test));
+}
+
+int ppc_sc_kernel_call_indirect(struct kunit* test, int (*fn)(struct kunit*))
+{
+	return PROTECTED_SC(test, fn(test));
+}
+
+long ppc_sc_kernel_target_big(struct kunit* test,
+			      long a,
+			      long b,
+			      long c,
+			      long d,
+			      long e,
+			      long f,
+			      long g,
+			      long h,
+			      long i)
+{
+	toc_fixup(test);
+	KUNIT_EXPECT_EQ(test, a, b);
+	KUNIT_EXPECT_EQ(test, a, c);
+	KUNIT_EXPECT_EQ(test, a, d);
+	KUNIT_EXPECT_EQ(test, a, e);
+	KUNIT_EXPECT_EQ(test, a, f);
+	KUNIT_EXPECT_EQ(test, a, g);
+	KUNIT_EXPECT_EQ(test, a, h);
+	KUNIT_EXPECT_EQ(test, a, i);
+	return ~a;
+}
+
+EXPORT_SYMBOL_GPL(ppc_sc_kernel_toc_init);
+EXPORT_SYMBOL_GPL(ppc_sc_kernel_toc_exit);
+EXPORT_SYMBOL_GPL(ppc_sc_kernel_target_1);
+EXPORT_SYMBOL_GPL(ppc_sc_kernel_target_2);
+EXPORT_SYMBOL_GPL(ppc_sc_kernel_target_big);
+EXPORT_STATIC_CALL_GPL(ppc_sc_kernel);
+EXPORT_SYMBOL_GPL(ppc_sc_kernel_call);
+EXPORT_SYMBOL_GPL(ppc_sc_kernel_call_indirect);
+
+#endif /* IS_MODULE(CONFIG_PPC_STATIC_CALL_KUNIT_TEST) */
diff --git a/arch/powerpc/kernel/static_call_test.c b/arch/powerpc/kernel/static_call_test.c
new file mode 100644
index 000000000000..057892d43a0a
--- /dev/null
+++ b/arch/powerpc/kernel/static_call_test.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <kunit/test.h>
+#include <linux/kconfig.h>
+#include <linux/module.h>
+#include <linux/static_call.h>
+
+/*
+ * Tests to ensure correctness in a variety of cases for static calls.
+ *
+ * The tests focus on ensuring the TOC is kept consistent across the
+ * module-kernel boundary, as compilers can't see that a trampoline
+ * defined locally in the kernel might be jumping to a function in a
+ * module. This makes it important that these tests are compiled as a
+ * module, so the TOC will be different to the kernel's.
+ *
+ * Register variables are used to allow easy position independent
+ * correction of a TOC before it is used for anything. This means
+ * a failing test doesn't always crash the whole kernel. The registers
+ * are initialised on entry and restored on exit of each test using
+ * KUnit's init and exit hooks. The tests only call internal and
+ * specially defined kernel functions, so the use of these registers
+ * will not clobber anything else.
+ */
+
+extern void ppc_sc_kernel_toc_init(void);
+extern void ppc_sc_kernel_toc_exit(void);
+DECLARE_STATIC_CALL(ppc_sc_kernel, int(struct kunit*));
+extern int ppc_sc_kernel_target_1(struct kunit* test);
+extern int ppc_sc_kernel_target_2(struct kunit* test);
+extern long ppc_sc_kernel_target_big(struct kunit* test,
+				     long a,
+				     long b,
+				     long c,
+				     long d,
+				     long e,
+				     long f,
+				     long g,
+				     long h,
+				     long i);
+extern int ppc_sc_kernel_call(struct kunit* test);
+extern int ppc_sc_kernel_call_indirect(struct kunit* test, int(*fn)(struct kunit*));
+
+/* Registers we reserve for use while testing */
+register void* current_toc asm ("r2");
+register void* module_toc asm ("r14");
+register void* actual_toc asm ("r15");
+register void* kernel_toc asm ("r16");
+register void* actual_kernel_toc asm ("r17");
+
+/* To hold a copy of the old register values while we test */
+static void* static_module_toc;
+static void* static_actual_toc;
+
+#define restore_toc(test) \
+	actual_toc = current_toc; \
+	current_toc = module_toc
+
+#define check_toc(test) KUNIT_EXPECT_PTR_EQ(test, module_toc, actual_toc)
+
+/* Corrects, then asserts the original TOC was valid */
+#define toc_fixup(test) \
+	restore_toc(); \
+	check_toc(test)
+
+/* Wrapper around a static call to verify and correct the TOC
+ * before running further code that might depend on it's value.
+ */
+#define PROTECTED_SC(test, call) \
+({ \
+	long ret; \
+	ret = call; \
+	toc_fixup(test); \
+	ret; \
+})
+
+static int module_target_11(struct kunit *test)
+{
+	toc_fixup(test);
+	return 11;
+}
+
+static int module_target_12(struct kunit *test)
+{
+	toc_fixup(test);
+	return 12;
+}
+
+DEFINE_STATIC_CALL(module_sc, module_target_11);
+
+DEFINE_STATIC_CALL_RET0(module_sc_ret0, long(void));
+DEFINE_STATIC_CALL_NULL(module_sc_null, long(long));
+
+static long add_one(long *val)
+{
+	return (*val)++;
+}
+
+static void null_function_test(struct kunit *test)
+{
+	long val = 0;
+
+	/* Check argument unconditionally evaluated */
+	static_call_cond(module_sc_null)(add_one(&val));
+	KUNIT_ASSERT_EQ(test, 1, val);
+}
+
+static void return_zero_test(struct kunit *test)
+{
+	long ret;
+
+	ret = PROTECTED_SC(test, static_call(module_sc_ret0)());
+	KUNIT_ASSERT_EQ(test, 0, ret);
+
+	static_call_update(ppc_sc_kernel, (void*)__static_call_return0);
+	ret = PROTECTED_SC(test, static_call(ppc_sc_kernel)(test));
+	KUNIT_ASSERT_EQ(test, 0, ret);
+
+	static_call_update(module_sc, (void*)__static_call_return0);
+	ret = PROTECTED_SC(test, static_call(module_sc)(test));
+	KUNIT_ASSERT_EQ(test, 0, ret);
+}
+
+static void kernel_kernel_kernel_test(struct kunit *test)
+{
+	static_call_update(ppc_sc_kernel, ppc_sc_kernel_target_1);
+	KUNIT_ASSERT_EQ(test, 1, ppc_sc_kernel_call(test));
+
+	static_call_update(ppc_sc_kernel, ppc_sc_kernel_target_2);
+	KUNIT_ASSERT_EQ(test, 2, ppc_sc_kernel_call(test));
+}
+
+static void kernel_kernel_module_test(struct kunit *test)
+{
+	static_call_update(ppc_sc_kernel, module_target_11);
+	KUNIT_ASSERT_EQ(test, 11, ppc_sc_kernel_call(test));
+
+	static_call_update(ppc_sc_kernel, module_target_12);
+	KUNIT_ASSERT_EQ(test, 12, ppc_sc_kernel_call(test));
+}
+
+static void kernel_module_kernel_test(struct kunit *test)
+{
+	static_call_update(module_sc, ppc_sc_kernel_target_1);
+	KUNIT_ASSERT_EQ(test, 1, ppc_sc_kernel_call_indirect(test, static_call(module_sc)));
+
+	static_call_update(module_sc, ppc_sc_kernel_target_2);
+	KUNIT_ASSERT_EQ(test, 2, ppc_sc_kernel_call_indirect(test, static_call(module_sc)));
+}
+
+static void kernel_module_module_test(struct kunit *test)
+{
+	static_call_update(module_sc, module_target_11);
+	KUNIT_ASSERT_EQ(test, 11, ppc_sc_kernel_call_indirect(test, static_call(module_sc)));
+
+	static_call_update(module_sc, module_target_12);
+	KUNIT_ASSERT_EQ(test, 12, ppc_sc_kernel_call_indirect(test, static_call(module_sc)));
+}
+
+static void module_kernel_kernel_test(struct kunit *test)
+{
+	long ret;
+
+	static_call_update(ppc_sc_kernel, ppc_sc_kernel_target_1);
+	ret = PROTECTED_SC(test, static_call(ppc_sc_kernel)(test));
+	KUNIT_ASSERT_EQ(test, 1, ret);
+
+	static_call_update(ppc_sc_kernel, ppc_sc_kernel_target_2);
+	ret = PROTECTED_SC(test, static_call(ppc_sc_kernel)(test));
+	KUNIT_ASSERT_EQ(test, 2, ret);
+}
+
+static void module_kernel_module_test(struct kunit *test)
+{
+	long ret;
+
+	static_call_update(ppc_sc_kernel, module_target_11);
+	ret = PROTECTED_SC(test, static_call(ppc_sc_kernel)(test));
+	KUNIT_ASSERT_EQ(test, 11, ret);
+
+	static_call_update(ppc_sc_kernel, module_target_12);
+	ret = PROTECTED_SC(test, static_call(ppc_sc_kernel)(test));
+	KUNIT_ASSERT_EQ(test, 12, ret);
+}
+
+static void module_module_kernel_test(struct kunit *test)
+{
+	long ret;
+
+	static_call_update(module_sc, ppc_sc_kernel_target_1);
+	ret = PROTECTED_SC(test, static_call(module_sc)(test));
+	KUNIT_ASSERT_EQ(test, 1, ret);
+
+	static_call_update(module_sc, ppc_sc_kernel_target_2);
+	ret = PROTECTED_SC(test, static_call(module_sc)(test));
+	KUNIT_ASSERT_EQ(test, 2, ret);
+}
+
+static void module_module_module_test(struct kunit *test)
+{
+	long ret;
+
+	static_call_update(module_sc, module_target_11);
+	ret = PROTECTED_SC(test, static_call(module_sc)(test));
+	KUNIT_ASSERT_EQ(test, 11, ret);
+
+	static_call_update(module_sc, module_target_12);
+	ret = PROTECTED_SC(test, static_call(module_sc)(test));
+	KUNIT_ASSERT_EQ(test, 12, ret);
+}
+
+DEFINE_STATIC_CALL(module_sc_stack_params, ppc_sc_kernel_target_big);
+
+static void stack_parameters_test(struct kunit *test)
+{
+	long m = 0x1234567887654321;
+	long ret = PROTECTED_SC(test, static_call(module_sc_stack_params)(test, m, m, m, m, m, m, m, m, m));
+	KUNIT_ASSERT_EQ(test, ~m, ret);
+}
+
+static struct kunit_case static_call_test_cases[] = {
+	KUNIT_CASE(null_function_test),
+	KUNIT_CASE(return_zero_test),
+	KUNIT_CASE(stack_parameters_test),
+	KUNIT_CASE(kernel_kernel_kernel_test),
+	KUNIT_CASE(kernel_kernel_module_test),
+	KUNIT_CASE(kernel_module_kernel_test),
+	KUNIT_CASE(kernel_module_module_test),
+	KUNIT_CASE(module_kernel_kernel_test),
+	KUNIT_CASE(module_kernel_module_test),
+	KUNIT_CASE(module_module_kernel_test),
+	KUNIT_CASE(module_module_module_test),
+	{}
+};
+
+static int ppc_static_call_test_init(struct kunit *test)
+{
+	static_module_toc = module_toc;
+	static_actual_toc = actual_toc;
+	module_toc = current_toc;
+
+	ppc_sc_kernel_toc_init();
+
+	return 0;
+}
+
+static void ppc_static_call_test_exit(struct kunit *test)
+{
+	module_toc = static_module_toc;
+	actual_toc = static_actual_toc;
+
+	ppc_sc_kernel_toc_exit();
+}
+
+static struct kunit_suite ppc_static_call_test_suite = {
+	.name = "ppc-static-call",
+	.test_cases = static_call_test_cases,
+	.init = ppc_static_call_test_init,
+	.exit = ppc_static_call_test_exit,
+};
+kunit_test_suite(ppc_static_call_test_suite);
+
+MODULE_AUTHOR("Benjamin Gray <bgray@linux.ibm.com>");
+MODULE_LICENSE("GPL");
-- 
2.37.3


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

* Re: [PATCH 5/6] powerpc/64: Add support for out-of-line static calls
  2022-09-16  6:23 ` [PATCH 5/6] powerpc/64: Add support for out-of-line static calls Benjamin Gray
@ 2022-09-16  8:32   ` kernel test robot
  0 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-09-16  8:32 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: christophe.leroy, kbuild-all, ajd, peterz, npiggin, jpoimboe,
	jbaron, rostedt, Benjamin Gray, ardb

Hi Benjamin,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on powerpc/next]
[also build test ERROR on next-20220915]
[cannot apply to linus/master v6.0-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Benjamin-Gray/Out-of-line-static-calls-for-powerpc64-ELF-V2/20220916-142951
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-allyesconfig (https://download.01.org/0day-ci/archive/20220916/202209161627.bZaVohGQ-lkp@intel.com/config)
compiler: powerpc-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/f76701ac48849394d2a140d87c4263e796f4920f
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Benjamin-Gray/Out-of-line-static-calls-for-powerpc64-ELF-V2/20220916-142951
        git checkout f76701ac48849394d2a140d87c4263e796f4920f
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=powerpc SHELL=/bin/bash arch/powerpc/kernel/ kernel/trace/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

Note: the linux-review/Benjamin-Gray/Out-of-line-static-calls-for-powerpc64-ELF-V2/20220916-142951 HEAD d2702454a6382dfec6e4f47e4c3e49f70bec7049 builds fine.
      It only hurts bisectability.

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/static_call.h:139,
                    from include/linux/tracepoint.h:22,
                    from include/trace/syscall.h:5,
                    from include/linux/syscalls.h:88,
                    from arch/powerpc/kernel/syscalls.c:19:
>> arch/powerpc/include/asm/static_call.h:94:2: error: #error "Unsupported ABI"
      94 | #error "Unsupported ABI"
         |  ^~~~~
--
   In file included from include/linux/static_call.h:139,
                    from arch/powerpc/kernel/irq.c:55:
>> arch/powerpc/include/asm/static_call.h:94:2: error: #error "Unsupported ABI"
      94 | #error "Unsupported ABI"
         |  ^~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:57:9: note: in expansion of macro 'DEFINE_TRACE'
      57 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   arch/powerpc/include/asm/trace.h:29:1: note: in expansion of macro 'DEFINE_EVENT'
      29 | DEFINE_EVENT(ppc64_interrupt_class, irq_entry,
         | ^~~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:57:9: note: in expansion of macro 'DEFINE_TRACE'
      57 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   arch/powerpc/include/asm/trace.h:36:1: note: in expansion of macro 'DEFINE_EVENT'
      36 | DEFINE_EVENT(ppc64_interrupt_class, irq_exit,
         | ^~~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:57:9: note: in expansion of macro 'DEFINE_TRACE'
      57 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   arch/powerpc/include/asm/trace.h:43:1: note: in expansion of macro 'DEFINE_EVENT'
      43 | DEFINE_EVENT(ppc64_interrupt_class, timer_interrupt_entry,
         | ^~~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:57:9: note: in expansion of macro 'DEFINE_TRACE'
      57 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   arch/powerpc/include/asm/trace.h:50:1: note: in expansion of macro 'DEFINE_EVENT'
      50 | DEFINE_EVENT(ppc64_interrupt_class, timer_interrupt_exit,
         | ^~~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:28:9: note: in expansion of macro 'DEFINE_TRACE'
      28 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   arch/powerpc/include/asm/trace.h:167:1: note: in expansion of macro 'TRACE_EVENT'
     167 | TRACE_EVENT(hash_fault,
         | ^~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:28:9: note: in expansion of macro 'DEFINE_TRACE'
      28 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   arch/powerpc/include/asm/trace.h:188:1: note: in expansion of macro 'TRACE_EVENT'
     188 | TRACE_EVENT(tlbie,
         | ^~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:28:9: note: in expansion of macro 'DEFINE_TRACE'
      28 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   arch/powerpc/include/asm/trace.h:220:1: note: in expansion of macro 'TRACE_EVENT'
     220 | TRACE_EVENT(tlbia,
         | ^~~~~~~~~~~
   arch/powerpc/include/asm/static_call.h:99:73: error: expected ')' before string constant
      99 | #define ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name)        __PPC_SCT(name, "b 1f")
         |                                                                         ^~~~~~
   include/linux/static_call.h:247:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_RET0_TRAMP'
     247 |         ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/powerpc/kernel/irq.c:223:1: note: in expansion of macro 'DEFINE_STATIC_CALL_RET0'
     223 | DEFINE_STATIC_CALL_RET0(ppc_get_irq, *ppc_md.get_irq);
         | ^~~~~~~~~~~~~~~~~~~~~~~
--
   In file included from include/linux/static_call.h:139,
                    from arch/powerpc/kernel/static_call.c:7:
>> arch/powerpc/include/asm/static_call.h:94:2: error: #error "Unsupported ABI"
      94 | #error "Unsupported ABI"
         |  ^~~~~
   arch/powerpc/kernel/static_call.c: In function 'ppc_function_toc':
>> arch/powerpc/kernel/static_call.c:16:29: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
      16 |                 u64 addr = ((u64) func + si1) + si2;
         |                             ^
>> arch/powerpc/kernel/static_call.c:21:32: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
      21 |                         return (void*)addr;
         |                                ^
   arch/powerpc/kernel/static_call.c: In function 'get_inst_addr':
>> arch/powerpc/kernel/static_call.c:52:51: error: 'PPC_SCT_INST_KERNEL' undeclared (first use in this function)
      52 |         return tramp + (core_kernel_text(tramp) ? PPC_SCT_INST_KERNEL : PPC_SCT_INST_MODULE);
         |                                                   ^~~~~~~~~~~~~~~~~~~
   arch/powerpc/kernel/static_call.c:52:51: note: each undeclared identifier is reported only once for each function it appears in
>> arch/powerpc/kernel/static_call.c:52:73: error: 'PPC_SCT_INST_MODULE' undeclared (first use in this function)
      52 |         return tramp + (core_kernel_text(tramp) ? PPC_SCT_INST_KERNEL : PPC_SCT_INST_MODULE);
         |                                                                         ^~~~~~~~~~~~~~~~~~~
   arch/powerpc/kernel/static_call.c: In function 'get_ret0_addr':
>> arch/powerpc/kernel/static_call.c:56:51: error: 'PPC_SCT_RET0_KERNEL' undeclared (first use in this function)
      56 |         return tramp + (core_kernel_text(tramp) ? PPC_SCT_RET0_KERNEL : PPC_SCT_RET0_MODULE);
         |                                                   ^~~~~~~~~~~~~~~~~~~
>> arch/powerpc/kernel/static_call.c:56:73: error: 'PPC_SCT_RET0_MODULE' undeclared (first use in this function)
      56 |         return tramp + (core_kernel_text(tramp) ? PPC_SCT_RET0_KERNEL : PPC_SCT_RET0_MODULE);
         |                                                                         ^~~~~~~~~~~~~~~~~~~
   arch/powerpc/kernel/static_call.c: In function 'get_data_addr':
>> arch/powerpc/kernel/static_call.c:60:51: error: 'PPC_SCT_DATA_KERNEL' undeclared (first use in this function)
      60 |         return tramp + (core_kernel_text(tramp) ? PPC_SCT_DATA_KERNEL : PPC_SCT_DATA_MODULE);
         |                                                   ^~~~~~~~~~~~~~~~~~~
>> arch/powerpc/kernel/static_call.c:60:73: error: 'PPC_SCT_DATA_MODULE' undeclared (first use in this function)
      60 |         return tramp + (core_kernel_text(tramp) ? PPC_SCT_DATA_KERNEL : PPC_SCT_DATA_MODULE);
         |                                                                         ^~~~~~~~~~~~~~~~~~~
   arch/powerpc/kernel/static_call.c: In function 'get_ret0_addr':
   arch/powerpc/kernel/static_call.c:57:1: error: control reaches end of non-void function [-Werror=return-type]
      57 | }
         | ^
   arch/powerpc/kernel/static_call.c: In function 'get_inst_addr':
   arch/powerpc/kernel/static_call.c:53:1: error: control reaches end of non-void function [-Werror=return-type]
      53 | }
         | ^
   arch/powerpc/kernel/static_call.c: In function 'get_data_addr':
   arch/powerpc/kernel/static_call.c:61:1: error: control reaches end of non-void function [-Werror=return-type]
      61 | }
         | ^
   cc1: some warnings being treated as errors
--
   In file included from include/linux/static_call.h:139,
                    from include/linux/tracepoint.h:22,
                    from include/trace/events/sched.h:10,
                    from kernel/trace/ftrace.c:39:
>> arch/powerpc/include/asm/static_call.h:94:2: error: #error "Unsupported ABI"
      94 | #error "Unsupported ABI"
         |  ^~~~~
   kernel/trace/ftrace.c:299:5: warning: no previous prototype for '__register_ftrace_function' [-Wmissing-prototypes]
     299 | int __register_ftrace_function(struct ftrace_ops *ops)
         |     ^~~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/trace/ftrace.c:342:5: warning: no previous prototype for '__unregister_ftrace_function' [-Wmissing-prototypes]
     342 | int __unregister_ftrace_function(struct ftrace_ops *ops)
         |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   kernel/trace/ftrace.c:4044:15: warning: no previous prototype for 'arch_ftrace_match_adjust' [-Wmissing-prototypes]
    4044 | char * __weak arch_ftrace_match_adjust(char *str, const char *search)
         |               ^~~~~~~~~~~~~~~~~~~~~~~~
--
   In file included from include/linux/static_call.h:139,
                    from include/linux/tracepoint.h:22,
                    from kernel/trace/trace.h:12,
                    from kernel/trace/trace.c:53:
>> arch/powerpc/include/asm/static_call.h:94:2: error: #error "Unsupported ABI"
      94 | #error "Unsupported ABI"
         |  ^~~~~
   kernel/trace/trace.c: In function 'trace_check_vprintf':
   kernel/trace/trace.c:3846:17: warning: function 'trace_check_vprintf' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
    3846 |                 trace_seq_vprintf(&iter->seq, iter->fmt, ap);
         |                 ^~~~~~~~~~~~~~~~~
   kernel/trace/trace.c:3913:17: warning: function 'trace_check_vprintf' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
    3913 |                 trace_seq_vprintf(&iter->seq, p, ap);
         |                 ^~~~~~~~~~~~~~~~~
--
   In file included from include/linux/static_call.h:139,
                    from include/linux/tracepoint.h:22,
                    from kernel/trace/trace.h:12,
                    from kernel/trace/trace_output.h:6,
                    from kernel/trace/trace_output.c:15:
>> arch/powerpc/include/asm/static_call.h:94:2: error: #error "Unsupported ABI"
      94 | #error "Unsupported ABI"
         |  ^~~~~
   kernel/trace/trace_output.c: In function 'trace_output_raw':
   kernel/trace/trace_output.c:332:9: warning: function 'trace_output_raw' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
     332 |         trace_seq_vprintf(s, trace_event_format(iter, fmt), ap);
         |         ^~~~~~~~~~~~~~~~~
--
   In file included from include/linux/static_call.h:139,
                    from include/linux/tracepoint.h:22,
                    from kernel/trace/trace.h:12,
                    from kernel/trace/trace_preemptirq.c:13:
>> arch/powerpc/include/asm/static_call.h:94:2: error: #error "Unsupported ABI"
      94 | #error "Unsupported ABI"
         |  ^~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:57:9: note: in expansion of macro 'DEFINE_TRACE'
      57 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   include/trace/events/preemptirq.h:36:1: note: in expansion of macro 'DEFINE_EVENT'
      36 | DEFINE_EVENT(preemptirq_template, irq_disable,
         | ^~~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:57:9: note: in expansion of macro 'DEFINE_TRACE'
      57 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   include/trace/events/preemptirq.h:40:1: note: in expansion of macro 'DEFINE_EVENT'
      40 | DEFINE_EVENT(preemptirq_template, irq_enable,
         | ^~~~~~~~~~~~
   kernel/trace/trace_preemptirq.c:88:16: warning: no previous prototype for 'trace_hardirqs_on_caller' [-Wmissing-prototypes]
      88 | __visible void trace_hardirqs_on_caller(unsigned long caller_addr)
         |                ^~~~~~~~~~~~~~~~~~~~~~~~
   kernel/trace/trace_preemptirq.c:103:16: warning: no previous prototype for 'trace_hardirqs_off_caller' [-Wmissing-prototypes]
     103 | __visible void trace_hardirqs_off_caller(unsigned long caller_addr)
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~
--
   In file included from include/linux/static_call.h:139,
                    from include/linux/tracepoint.h:22,
                    from kernel/trace/trace.h:12,
                    from kernel/trace/trace_osnoise.c:27:
>> arch/powerpc/include/asm/static_call.h:94:2: error: #error "Unsupported ABI"
      94 | #error "Unsupported ABI"
         |  ^~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:28:9: note: in expansion of macro 'DEFINE_TRACE'
      28 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   include/trace/events/osnoise.h:9:1: note: in expansion of macro 'TRACE_EVENT'
       9 | TRACE_EVENT(thread_noise,
         | ^~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:28:9: note: in expansion of macro 'DEFINE_TRACE'
      28 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   include/trace/events/osnoise.h:37:1: note: in expansion of macro 'TRACE_EVENT'
      37 | TRACE_EVENT(softirq_noise,
         | ^~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:28:9: note: in expansion of macro 'DEFINE_TRACE'
      28 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   include/trace/events/osnoise.h:63:1: note: in expansion of macro 'TRACE_EVENT'
      63 | TRACE_EVENT(irq_noise,
         | ^~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:28:9: note: in expansion of macro 'DEFINE_TRACE'
      28 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   include/trace/events/osnoise.h:92:1: note: in expansion of macro 'TRACE_EVENT'
      92 | TRACE_EVENT(nmi_noise,
         | ^~~~~~~~~~~
>> arch/powerpc/include/asm/static_call.h:97:73: error: expected ')' before string constant
      97 | #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)       __PPC_SCT(name, "b " #func)
         |                                                                         ^~~~
   include/linux/static_call.h:233:9: note: in expansion of macro 'ARCH_DEFINE_STATIC_CALL_TRAMP'
     233 |         ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:325:9: note: in expansion of macro 'DEFINE_STATIC_CALL'
     325 |         DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
         |         ^~~~~~~~~~~~~~~~~~
   include/linux/tracepoint.h:328:9: note: in expansion of macro 'DEFINE_TRACE_FN'
     328 |         DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
         |         ^~~~~~~~~~~~~~~
   include/trace/define_trace.h:28:9: note: in expansion of macro 'DEFINE_TRACE'
      28 |         DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~
   include/trace/events/osnoise.h:114:1: note: in expansion of macro 'TRACE_EVENT'
     114 | TRACE_EVENT(sample_threshold,
         | ^~~~~~~~~~~
..


vim +94 arch/powerpc/include/asm/static_call.h

    92	
    93	#else /* !CONFIG_PPC64_ELF_ABI_V2 && !PPC32 */
  > 94	#error "Unsupported ABI"
    95	#endif /* CONFIG_PPC64_ELF_ABI_V2 */
    96	
  > 97	#define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func)	__PPC_SCT(name, "b " #func)
    98	#define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name)	__PPC_SCT(name, "blr")
    99	#define ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name)	__PPC_SCT(name, "b 1f")
   100	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-16  6:23 ` [PATCH 1/6] powerpc/code-patching: Implement generic text patching function Benjamin Gray
@ 2022-09-16  9:39   ` kernel test robot
  2022-09-16 11:16   ` kernel test robot
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-09-16  9:39 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: christophe.leroy, kbuild-all, ajd, npiggin, jpoimboe, jbaron,
	rostedt, Benjamin Gray, ardb

[-- Attachment #1: Type: text/plain, Size: 2925 bytes --]

Hi Benjamin,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on powerpc/next]
[also build test ERROR on next-20220916]
[cannot apply to linus/master v6.0-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Benjamin-Gray/Out-of-line-static-calls-for-powerpc64-ELF-V2/20220916-142951
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-allnoconfig
compiler: powerpc-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/31a9d4d694a3a20129f20390f3d7af2c154c8ed1
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Benjamin-Gray/Out-of-line-static-calls-for-powerpc64-ELF-V2/20220916-142951
        git checkout 31a9d4d694a3a20129f20390f3d7af2c154c8ed1
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=powerpc SHELL=/bin/bash arch/powerpc/lib/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> arch/powerpc/lib/code-patching.c:235:7: error: no previous prototype for 'patch_memory' [-Werror=missing-prototypes]
     235 | void *patch_memory(void *dest, const void *src, size_t size)
         |       ^~~~~~~~~~~~
   arch/powerpc/lib/code-patching.c: In function 'patch_instruction':
   arch/powerpc/lib/code-patching.c:248:24: error: implicit declaration of function 'patch_text'; did you mean 'path_get'? [-Werror=implicit-function-declaration]
     248 |                 return patch_text(addr, &val, sizeof(val), true);
         |                        ^~~~~~~~~~
         |                        path_get
   arch/powerpc/lib/code-patching.c: At top level:
>> arch/powerpc/lib/code-patching.c:230:12: error: 'do_patch_instruction' defined but not used [-Werror=unused-function]
     230 | static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
         |            ^~~~~~~~~~~~~~~~~~~~
   cc1: all warnings being treated as errors


vim +/patch_memory +235 arch/powerpc/lib/code-patching.c

   229	
 > 230	static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
   231	{
   232		return raw_patch_instruction(addr, instr);
   233	}
   234	
 > 235	void *patch_memory(void *dest, const void *src, size_t size)
   236	{
   237		return memcpy(dest, src, size);
   238	}
   239	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

[-- Attachment #2: config --]
[-- Type: text/plain, Size: 30526 bytes --]

#
# Automatically generated file; DO NOT EDIT.
# Linux/powerpc 6.0.0-rc2 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="powerpc-linux-gcc (GCC) 12.1.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=120100
CONFIG_CLANG_VERSION=0
CONFIG_AS_IS_GNU=y
CONFIG_AS_VERSION=23800
CONFIG_LD_IS_BFD=y
CONFIG_LD_VERSION=23800
CONFIG_LLD_VERSION=0
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
CONFIG_PAHOLE_VERSION=123
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y

#
# General setup
#
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_XZ is not set
CONFIG_DEFAULT_INIT=""
CONFIG_DEFAULT_HOSTNAME="(none)"
# CONFIG_SYSVIPC is not set
# CONFIG_WATCH_QUEUE is not set
# CONFIG_CROSS_MEMORY_ATTACH is not set
# CONFIG_USELIB is not set
CONFIG_HAVE_ARCH_AUDITSYSCALL=y

#
# IRQ subsystem
#
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
# end of IRQ subsystem

CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CMOS_UPDATE=y

#
# Timers subsystem
#
CONFIG_HZ_PERIODIC=y
# CONFIG_NO_HZ_IDLE is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
# end of Timers subsystem

CONFIG_HAVE_EBPF_JIT=y

#
# BPF subsystem
#
# CONFIG_BPF_SYSCALL is not set
# end of BPF subsystem

CONFIG_PREEMPT_NONE_BUILD=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set

#
# CPU/Task time and stats accounting
#
CONFIG_TICK_CPU_ACCOUNTING=y
# CONFIG_VIRT_CPU_ACCOUNTING_NATIVE is not set
# CONFIG_IRQ_TIME_ACCOUNTING is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_PSI is not set
# end of CPU/Task time and stats accounting

#
# RCU Subsystem
#
CONFIG_TINY_RCU=y
# CONFIG_RCU_EXPERT is not set
CONFIG_SRCU=y
CONFIG_TINY_SRCU=y
# end of RCU Subsystem

# CONFIG_IKCONFIG is not set
# CONFIG_IKHEADERS is not set
CONFIG_LOG_BUF_SHIFT=17
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13

#
# Scheduler features
#
# end of Scheduler features

CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
CONFIG_GCC12_NO_ARRAY_BOUNDS=y
CONFIG_CC_NO_ARRAY_BOUNDS=y
# CONFIG_CGROUPS is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_TIME_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
# CONFIG_CHECKPOINT_RESTORE is not set
# CONFIG_SCHED_AUTOGROUP is not set
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_BOOT_CONFIG is not set
# CONFIG_INITRAMFS_PRESERVE_MTIME is not set
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
# CONFIG_LD_DEAD_CODE_DATA_ELIMINATION is not set
CONFIG_LD_ORPHAN_WARN=y
CONFIG_SYSCTL=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_EXPERT=y
CONFIG_MULTIUSER=y
CONFIG_SGETMASK_SYSCALL=y
CONFIG_SYSFS_SYSCALL=y
CONFIG_FHANDLE=y
CONFIG_POSIX_TIMERS=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_FUTEX_PI=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_IO_URING=y
CONFIG_ADVISE_SYSCALLS=y
CONFIG_MEMBARRIER=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
CONFIG_KALLSYMS_BASE_RELATIVE=y
CONFIG_ARCH_HAS_MEMBARRIER_CALLBACKS=y
CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
# CONFIG_KCMP is not set
CONFIG_RSEQ=y
# CONFIG_DEBUG_RSEQ is not set
# CONFIG_EMBEDDED is not set
CONFIG_HAVE_PERF_EVENTS=y
# CONFIG_PC104 is not set

#
# Kernel Performance Events And Counters
#
# CONFIG_PERF_EVENTS is not set
# end of Kernel Performance Events And Counters

# CONFIG_PROFILING is not set
# end of General setup

CONFIG_PPC32=y
# CONFIG_PPC64 is not set

#
# Processor support
#
CONFIG_PPC_BOOK3S_32=y
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_PPC_BOOK3S_603 is not set
CONFIG_PPC_BOOK3S_604=y
CONFIG_POWERPC_CPU=y
# CONFIG_E300C2_CPU is not set
# CONFIG_E300C3_CPU is not set
# CONFIG_G4_CPU is not set
# CONFIG_TOOLCHAIN_DEFAULT_CPU is not set
CONFIG_TARGET_CPU_BOOL=y
CONFIG_TARGET_CPU="powerpc"
CONFIG_PPC_BOOK3S=y
CONFIG_PPC_FPU_REGS=y
CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
# CONFIG_PPC_KUEP is not set
# CONFIG_PPC_KUAP is not set
CONFIG_PPC_HAVE_PMU_SUPPORT=y
# CONFIG_PMU_SYSFS is not set
# CONFIG_SMP is not set
CONFIG_NR_CPUS=1
# end of Processor support

CONFIG_VDSO32=y
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_32BIT=y
CONFIG_MMU=y
CONFIG_ARCH_MMAP_RND_BITS_MAX=17
CONFIG_ARCH_MMAP_RND_BITS_MIN=11
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
CONFIG_NR_IRQS=512
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_PANIC_TIMEOUT=180
CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_HAS_ADD_PAGES=y
# CONFIG_PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT is not set
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_PGTABLE_LEVELS=2

#
# Platform support
#
# CONFIG_PPC_CHRP is not set
# CONFIG_PPC_MPC512x is not set
# CONFIG_PPC_MPC52xx is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_AMIGAONE is not set
# CONFIG_KVM_GUEST is not set
# CONFIG_EPAPR_PARAVIRT is not set
# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set

#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
# end of CPU Frequency scaling

#
# CPUIdle driver
#

#
# CPU Idle
#
# CONFIG_CPU_IDLE is not set
# end of CPU Idle
# end of CPUIdle driver

# CONFIG_TAU is not set
# CONFIG_GEN_RTC is not set
# end of Platform support

#
# Kernel options
#
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ILLEGAL_POINTER_VALUE=0
CONFIG_PPC_4K_PAGES=y
CONFIG_PAGE_SIZE_4KB=y
CONFIG_PPC_PAGE_SHIFT=12
CONFIG_THREAD_SHIFT=13
CONFIG_DATA_SHIFT=12
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_CMDLINE=""
CONFIG_EXTRA_TARGETS=""
# CONFIG_PM is not set
# end of Kernel options

#
# Bus options
#
# CONFIG_FSL_LBC is not set
# end of Bus options

#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set

#
# Default settings for advanced configuration options are used
#
CONFIG_LOWMEM_SIZE=0x30000000
CONFIG_PAGE_OFFSET=0xc0000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
CONFIG_TASK_SIZE=0xb0000000
# end of Advanced setup

# CONFIG_VIRTUALIZATION is not set
CONFIG_HAVE_LIVEPATCH=y

#
# General architecture-dependent options
#
# CONFIG_JUMP_LABEL is not set
# CONFIG_STATIC_CALL_SELFTEST is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_KPROBES_ON_FTRACE=y
CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
CONFIG_ARCH_HAS_SET_MEMORY=y
CONFIG_ARCH_WANTS_NO_INSTR=y
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_HAVE_ASM_MODVERSIONS=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_RSEQ=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
CONFIG_MMU_GATHER_TABLE_FREE=y
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
CONFIG_MMU_GATHER_PAGE_SIZE=y
CONFIG_MMU_GATHER_MERGE_VMAS=y
CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM=y
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
CONFIG_ARCH_WEAK_RELEASE_ACQUIRE=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_HAVE_ARCH_SECCOMP=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
# CONFIG_SECCOMP is not set
CONFIG_HAVE_STACKPROTECTOR=y
# CONFIG_STACKPROTECTOR is not set
CONFIG_LTO_NONE=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC=y
CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
CONFIG_ARCH_MMAP_RND_BITS=11
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y
CONFIG_HAVE_RELIABLE_STACKTRACE=y
CONFIG_HAVE_ARCH_NVRAM_OPS=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_OLD_SIGSUSPEND=y
CONFIG_OLD_SIGACTION=y
# CONFIG_COMPAT_32BIT_TIME is not set
CONFIG_HAVE_ARCH_VMAP_STACK=y
# CONFIG_VMAP_STACK is not set
CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y
CONFIG_RANDOMIZE_KSTACK_OFFSET=y
# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
# CONFIG_STRICT_KERNEL_RWX is not set
CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
CONFIG_ARCH_HAS_PHYS_TO_DMA=y
CONFIG_HAVE_STATIC_CALL=y
CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y

#
# GCOV-based kernel profiling
#
CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
# end of GCOV-based kernel profiling

CONFIG_HAVE_GCC_PLUGINS=y
# CONFIG_GCC_PLUGINS is not set
# end of General architecture-dependent options

CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
# CONFIG_BLK_DEV_BSGLIB is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
# CONFIG_BLK_DEV_ZONED is not set
# CONFIG_BLK_WBT is not set
# CONFIG_BLK_SED_OPAL is not set
# CONFIG_BLK_INLINE_ENCRYPTION is not set

#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
CONFIG_EFI_PARTITION=y
# end of Partition Types

#
# IO Schedulers
#
# CONFIG_MQ_IOSCHED_DEADLINE is not set
# CONFIG_MQ_IOSCHED_KYBER is not set
# CONFIG_IOSCHED_BFQ is not set
# end of IO Schedulers

CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
CONFIG_INLINE_READ_UNLOCK=y
CONFIG_INLINE_READ_UNLOCK_IRQ=y
CONFIG_INLINE_WRITE_UNLOCK=y
CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y

#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
CONFIG_ELFCORE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_BINFMT_SCRIPT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_COREDUMP=y
# end of Executable file formats

#
# Memory Management options
#
# CONFIG_SWAP is not set

#
# SLAB allocator options
#
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_SLAB_MERGE_DEFAULT is not set
# CONFIG_SLAB_FREELIST_RANDOM is not set
# CONFIG_SLAB_FREELIST_HARDENED is not set
# CONFIG_SLUB_STATS is not set
# end of SLAB allocator options

# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_FLATMEM=y
CONFIG_HAVE_FAST_GUP=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
CONFIG_EXCLUSIVE_SYSTEM_RAM=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_COMPACTION is not set
# CONFIG_PAGE_REPORTING is not set
# CONFIG_MIGRATION is not set
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_NEED_PER_CPU_KM=y
# CONFIG_CMA is not set
CONFIG_GENERIC_EARLY_IOREMAP=y
# CONFIG_IDLE_PAGE_TRACKING is not set
CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y
CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_PERCPU_STATS is not set

#
# GUP_TEST needs to have DEBUG_FS enabled
#
CONFIG_ARCH_HAS_PTE_SPECIAL=y
# CONFIG_ANON_VMA_NAME is not set
# CONFIG_USERFAULTFD is not set

#
# Data Access Monitoring
#
# CONFIG_DAMON is not set
# end of Data Access Monitoring
# end of Memory Management options

# CONFIG_NET is not set

#
# Device Drivers
#
# CONFIG_PCCARD is not set

#
# Generic Driver Options
#
# CONFIG_UEVENT_HELPER is not set
# CONFIG_DEVTMPFS is not set
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set

#
# Firmware loader
#
CONFIG_FW_LOADER=y
CONFIG_EXTRA_FIRMWARE=""
# CONFIG_FW_LOADER_USER_HELPER is not set
# CONFIG_FW_LOADER_COMPRESS is not set
# CONFIG_FW_UPLOAD is not set
# end of Firmware loader

CONFIG_ALLOW_DEV_COREDUMP=y
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
CONFIG_GENERIC_CPU_AUTOPROBE=y
# end of Generic Driver Options

#
# Bus devices
#
# CONFIG_MHI_BUS is not set
# CONFIG_MHI_BUS_EP is not set
# end of Bus devices

#
# Firmware Drivers
#

#
# ARM System Control and Management Interface Protocol
#
# end of ARM System Control and Management Interface Protocol

# CONFIG_FIRMWARE_MEMMAP is not set
# CONFIG_GOOGLE_FIRMWARE is not set

#
# Tegra firmware driver
#
# end of Tegra firmware driver
# end of Firmware Drivers

# CONFIG_GNSS is not set
# CONFIG_MTD is not set
CONFIG_DTC=y
CONFIG_OF=y
# CONFIG_OF_UNITTEST is not set
CONFIG_OF_FLATTREE=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_KOBJ=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_IRQ=y
CONFIG_OF_RESERVED_MEM=y
# CONFIG_OF_OVERLAY is not set
CONFIG_OF_DMA_DEFAULT_COHERENT=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
# CONFIG_PARPORT is not set
# CONFIG_BLK_DEV is not set

#
# NVME Support
#
# CONFIG_NVME_FC is not set
# end of NVME Support

#
# Misc devices
#
# CONFIG_DUMMY_IRQ is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_SRAM is not set
# CONFIG_XILINX_SDFEC is not set
# CONFIG_OPEN_DICE is not set
# CONFIG_VCPU_STALL_DETECTOR is not set
# CONFIG_C2PORT is not set

#
# EEPROM support
#
# CONFIG_EEPROM_93CX6 is not set
# end of EEPROM support

#
# Texas Instruments shared transport line discipline
#
# end of Texas Instruments shared transport line discipline

#
# Altera FPGA firmware download module (requires I2C)
#
# CONFIG_ECHO is not set
# CONFIG_PVPANIC is not set
# end of Misc devices

#
# SCSI device support
#
CONFIG_SCSI_MOD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# end of SCSI device support

# CONFIG_ATA is not set
# CONFIG_MD is not set
# CONFIG_TARGET_CORE is not set
# CONFIG_MACINTOSH_DRIVERS is not set

#
# Input device support
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
# CONFIG_INPUT_SPARSEKMAP is not set
# CONFIG_INPUT_MATRIXKMAP is not set

#
# Userland interfaces
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set

#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
# CONFIG_RMI4_CORE is not set

#
# Hardware I/O ports
#
# CONFIG_SERIO is not set
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
# CONFIG_GAMEPORT is not set
# end of Hardware I/O ports
# end of Input device support

#
# Character devices
#
CONFIG_TTY=y
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_LDISC_AUTOLOAD is not set

#
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set

#
# Non-8250 serial port support
#
# CONFIG_SERIAL_UARTLITE is not set
# CONFIG_SERIAL_SIFIVE is not set
# CONFIG_SERIAL_SCCNXP is not set
# CONFIG_SERIAL_ALTERA_JTAGUART is not set
# CONFIG_SERIAL_ALTERA_UART is not set
# CONFIG_SERIAL_XILINX_PS_UART is not set
# CONFIG_SERIAL_ARC is not set
# CONFIG_SERIAL_FSL_LPUART is not set
# CONFIG_SERIAL_FSL_LINFLEXUART is not set
# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
# end of Serial drivers

# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_PPC_EPAPR_HV_BYTECHAN is not set
# CONFIG_NULL_TTY is not set
# CONFIG_HVC_UDBG is not set
# CONFIG_SERIAL_DEV_BUS is not set
# CONFIG_TTY_PRINTK is not set
# CONFIG_VIRTIO_CONSOLE is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_DEVMEM is not set
# CONFIG_NVRAM is not set
# CONFIG_TCG_TPM is not set
# CONFIG_XILLYBUS is not set
# CONFIG_RANDOM_TRUST_CPU is not set
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
# end of Character devices

#
# I2C support
#
# CONFIG_I2C is not set
# end of I2C support

# CONFIG_I3C is not set
# CONFIG_SPI is not set
# CONFIG_SPMI is not set
# CONFIG_HSI is not set
# CONFIG_PPS is not set

#
# PTP clock support
#
CONFIG_PTP_1588_CLOCK_OPTIONAL=y

#
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
#
# end of PTP clock support

# CONFIG_PINCTRL is not set
# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_RESET is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
CONFIG_BCMA_POSSIBLE=y
# CONFIG_BCMA is not set

#
# Multifunction device drivers
#
# CONFIG_MFD_ATMEL_FLEXCOM is not set
# CONFIG_MFD_ATMEL_HLCDC is not set
# CONFIG_MFD_MADERA is not set
# CONFIG_MFD_HI6421_PMIC is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_KEMPLD is not set
# CONFIG_MFD_MT6397 is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_MFD_SYSCON is not set
# CONFIG_MFD_TI_AM335X_TSCADC is not set
# CONFIG_MFD_TQMX86 is not set
# end of Multifunction device drivers

# CONFIG_REGULATOR is not set
# CONFIG_RC_CORE is not set

#
# CEC support
#
# CONFIG_MEDIA_CEC_SUPPORT is not set
# end of CEC support

# CONFIG_MEDIA_SUPPORT is not set

#
# Graphics support
#
# CONFIG_DRM is not set
# CONFIG_DRM_DEBUG_MODESET_LOCK is not set

#
# ARM devices
#
# end of ARM devices

#
# Frame buffer Devices
#
# CONFIG_FB is not set
# end of Frame buffer Devices

#
# Backlight & LCD device support
#
# CONFIG_LCD_CLASS_DEVICE is not set
# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
# end of Backlight & LCD device support

#
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=80
CONFIG_DUMMY_CONSOLE_ROWS=25
# end of Console display driver support
# end of Graphics support

# CONFIG_SOUND is not set

#
# HID support
#
# CONFIG_HID is not set
# end of HID support

CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_RTC_LIB=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set

#
# DMABUF options
#
# CONFIG_SYNC_FILE is not set
# CONFIG_DMABUF_HEAPS is not set
# end of DMABUF options

# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_VFIO is not set
# CONFIG_VIRT_DRIVERS is not set
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set

#
# Microsoft Hyper-V guest support
#
# end of Microsoft Hyper-V guest support

# CONFIG_GREYBUS is not set
# CONFIG_COMEDI is not set
# CONFIG_STAGING is not set
# CONFIG_GOLDFISH is not set
# CONFIG_COMMON_CLK is not set
# CONFIG_HWSPINLOCK is not set

#
# Clock Source drivers
#
# CONFIG_MICROCHIP_PIT64B is not set
# end of Clock Source drivers

# CONFIG_MAILBOX is not set
# CONFIG_IOMMU_SUPPORT is not set

#
# Remoteproc drivers
#
# CONFIG_REMOTEPROC is not set
# end of Remoteproc drivers

#
# Rpmsg drivers
#
# CONFIG_RPMSG_VIRTIO is not set
# end of Rpmsg drivers

# CONFIG_SOUNDWIRE is not set

#
# SOC (System On Chip) specific Drivers
#

#
# Amlogic SoC drivers
#
# end of Amlogic SoC drivers

#
# Broadcom SoC drivers
#
# end of Broadcom SoC drivers

#
# NXP/Freescale QorIQ SoC drivers
#
# CONFIG_QUICC_ENGINE is not set
# end of NXP/Freescale QorIQ SoC drivers

#
# fujitsu SoC drivers
#
# end of fujitsu SoC drivers

#
# i.MX SoC drivers
#
# end of i.MX SoC drivers

#
# Enable LiteX SoC Builder specific drivers
#
# CONFIG_LITEX_SOC_CONTROLLER is not set
# end of Enable LiteX SoC Builder specific drivers

#
# Qualcomm SoC drivers
#
# end of Qualcomm SoC drivers

# CONFIG_SOC_TI is not set

#
# Xilinx SoC drivers
#
# end of Xilinx SoC drivers
# end of SOC (System On Chip) specific Drivers

# CONFIG_PM_DEVFREQ is not set
# CONFIG_EXTCON is not set
# CONFIG_MEMORY is not set
# CONFIG_IIO is not set
# CONFIG_PWM is not set

#
# IRQ chip support
#
CONFIG_IRQCHIP=y
# CONFIG_AL_FIC is not set
# CONFIG_XILINX_INTC is not set
# end of IRQ chip support

# CONFIG_IPACK_BUS is not set
# CONFIG_RESET_CONTROLLER is not set

#
# PHY Subsystem
#
# CONFIG_GENERIC_PHY is not set
# CONFIG_PHY_CAN_TRANSCEIVER is not set

#
# PHY drivers for Broadcom platforms
#
# CONFIG_BCM_KONA_USB2_PHY is not set
# end of PHY drivers for Broadcom platforms

# CONFIG_PHY_CADENCE_DPHY is not set
# CONFIG_PHY_CADENCE_DPHY_RX is not set
# CONFIG_PHY_CADENCE_SALVO is not set
# CONFIG_PHY_PXA_28NM_HSIC is not set
# CONFIG_PHY_PXA_28NM_USB2 is not set
# end of PHY Subsystem

# CONFIG_POWERCAP is not set
# CONFIG_MCB is not set
# CONFIG_RAS is not set

#
# Android
#
# CONFIG_ANDROID_BINDER_IPC is not set
# end of Android

# CONFIG_DAX is not set
# CONFIG_NVMEM is not set

#
# HW tracing support
#
# CONFIG_STM is not set
# CONFIG_INTEL_TH is not set
# end of HW tracing support

# CONFIG_FPGA is not set
# CONFIG_FSI is not set
# CONFIG_SIOX is not set
# CONFIG_SLIMBUS is not set
# CONFIG_INTERCONNECT is not set
# CONFIG_COUNTER is not set
# CONFIG_PECI is not set
# CONFIG_HTE is not set
# end of Device Drivers

#
# File systems
#
# CONFIG_VALIDATE_FS_PARSER is not set
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_BTRFS_FS is not set
# CONFIG_NILFS2_FS is not set
# CONFIG_F2FS_FS is not set
CONFIG_EXPORTFS=y
# CONFIG_EXPORTFS_BLOCK_OPS is not set
CONFIG_FILE_LOCKING=y
# CONFIG_FS_ENCRYPTION is not set
# CONFIG_FS_VERITY is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
# CONFIG_FANOTIFY is not set
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_FUSE_FS is not set
# CONFIG_OVERLAY_FS is not set

#
# Caches
#
# CONFIG_FSCACHE is not set
# end of Caches

#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
# end of CD-ROM/DVD Filesystems

#
# DOS/FAT/EXFAT/NT Filesystems
#
# CONFIG_MSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EXFAT_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS3_FS is not set
# end of DOS/FAT/EXFAT/NT Filesystems

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_PROC_CHILDREN is not set
CONFIG_KERNFS=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_CONFIGFS_FS is not set
# end of Pseudo filesystems

# CONFIG_MISC_FILESYSTEMS is not set
# CONFIG_NLS is not set
# CONFIG_UNICODE is not set
CONFIG_IO_WQ=y
# end of File systems

#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY_DMESG_RESTRICT is not set
# CONFIG_SECURITY is not set
# CONFIG_SECURITYFS is not set
CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
# CONFIG_HARDENED_USERCOPY is not set
# CONFIG_FORTIFY_SOURCE is not set
# CONFIG_STATIC_USERMODEHELPER is not set
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,integrity,bpf"

#
# Kernel hardening options
#

#
# Memory initialization
#
CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y
# CONFIG_INIT_STACK_NONE is not set
# CONFIG_INIT_STACK_ALL_PATTERN is not set
CONFIG_INIT_STACK_ALL_ZERO=y
# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set
# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y
# CONFIG_ZERO_CALL_USED_REGS is not set
# end of Memory initialization

CONFIG_RANDSTRUCT_NONE=y
# end of Kernel hardening options
# end of Security options

# CONFIG_CRYPTO is not set

#
# Library routines
#
# CONFIG_PACKING is not set
CONFIG_BITREVERSE=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
# CONFIG_CORDIC is not set
# CONFIG_PRIME_NUMBERS is not set

#
# Crypto library routines
#
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
# CONFIG_CRYPTO_LIB_CURVE25519 is not set
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
# CONFIG_CRYPTO_LIB_POLY1305 is not set
# end of Crypto library routines

# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC64_ROCKSOFT is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC32_SELFTEST is not set
CONFIG_CRC32_SLICEBY8=y
# CONFIG_CRC32_SLICEBY4 is not set
# CONFIG_CRC32_SARWATE is not set
# CONFIG_CRC32_BIT is not set
# CONFIG_CRC64 is not set
# CONFIG_CRC4 is not set
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
# CONFIG_CRC8 is not set
# CONFIG_RANDOM32_SELFTEST is not set
# CONFIG_XZ_DEC is not set
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAS_DMA=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_DMA_DECLARE_COHERENT=y
# CONFIG_DMA_API_DEBUG is not set
CONFIG_GENERIC_ATOMIC64=y
# CONFIG_IRQ_POLL is not set
CONFIG_LIBFDT=y
CONFIG_HAVE_GENERIC_VDSO=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_VDSO_TIME_NS=y
CONFIG_ARCH_HAS_PMEM_API=y
CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
CONFIG_ARCH_STACKWALK=y
CONFIG_STACKDEPOT=y
CONFIG_SBITMAP=y
# end of Library routines

#
# Kernel hacking
#

#
# printk and dmesg options
#
# CONFIG_PRINTK_TIME is not set
# CONFIG_PRINTK_CALLER is not set
# CONFIG_STACKTRACE_BUILD_ID is not set
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
CONFIG_CONSOLE_LOGLEVEL_QUIET=4
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_DYNAMIC_DEBUG_CORE is not set
# CONFIG_SYMBOLIC_ERRNAME is not set
CONFIG_DEBUG_BUGVERBOSE=y
# end of printk and dmesg options

CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MISC=y

#
# Compile-time checks and compiler options
#
CONFIG_DEBUG_INFO_NONE=y
# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
# CONFIG_DEBUG_INFO_DWARF4 is not set
# CONFIG_DEBUG_INFO_DWARF5 is not set
CONFIG_FRAME_WARN=1024
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_READABLE_ASM is not set
# CONFIG_HEADERS_INSTALL is not set
CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set
# CONFIG_VMLINUX_MAP is not set
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
# end of Compile-time checks and compiler options

#
# Generic Kernel Debugging Instruments
#
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_FS is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
# CONFIG_UBSAN is not set
CONFIG_HAVE_KCSAN_COMPILER=y
# end of Generic Kernel Debugging Instruments

#
# Networking Debugging
#
# CONFIG_NET_DEV_REFCNT_TRACKER is not set
# CONFIG_NET_NS_REFCNT_TRACKER is not set
# end of Networking Debugging

#
# Memory Debugging
#
# CONFIG_PAGE_EXTENSION is not set
# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_SLUB_DEBUG=y
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_PAGE_OWNER is not set
# CONFIG_PAGE_POISONING is not set
CONFIG_GENERIC_PTDUMP=y
# CONFIG_DEBUG_OBJECTS is not set
CONFIG_HAVE_DEBUG_KMEMLEAK=y
# CONFIG_DEBUG_KMEMLEAK is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_SCHED_STACK_END_CHECK is not set
CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_VM_PGTABLE is not set
CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
# CONFIG_DEBUG_VIRTUAL is not set
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACKOVERFLOW is not set
CONFIG_HAVE_ARCH_KASAN=y
CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
CONFIG_CC_HAS_KASAN_GENERIC=y
CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y
# CONFIG_KASAN is not set
CONFIG_HAVE_ARCH_KFENCE=y
# CONFIG_KFENCE is not set
# end of Memory Debugging

# CONFIG_DEBUG_SHIRQ is not set

#
# Debug Oops, Lockups and Hangs
#
# CONFIG_PANIC_ON_OOPS is not set
CONFIG_PANIC_ON_OOPS_VALUE=0
# CONFIG_SOFTLOCKUP_DETECTOR is not set
# CONFIG_DETECT_HUNG_TASK is not set
# CONFIG_WQ_WATCHDOG is not set
# end of Debug Oops, Lockups and Hangs

#
# Scheduler Debugging
#
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# end of Scheduler Debugging

# CONFIG_DEBUG_TIMEKEEPING is not set

#
# Lock Debugging (spinlocks, mutexes, etc...)
#
CONFIG_LOCK_DEBUGGING_SUPPORT=y
# CONFIG_PROVE_LOCKING is not set
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_DEBUG_ATOMIC_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_LOCK_TORTURE_TEST is not set
# CONFIG_WW_MUTEX_SELFTEST is not set
# CONFIG_SCF_TORTURE_TEST is not set
# end of Lock Debugging (spinlocks, mutexes, etc...)

# CONFIG_DEBUG_IRQFLAGS is not set
CONFIG_STACKTRACE=y
# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
# CONFIG_DEBUG_KOBJECT is not set

#
# Debug kernel data structures
#
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_PLIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BUG_ON_DATA_CORRUPTION is not set
# end of Debug kernel data structures

# CONFIG_DEBUG_CREDENTIALS is not set

#
# RCU Debugging
#
# CONFIG_RCU_SCALE_TEST is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_REF_SCALE_TEST is not set
# CONFIG_RCU_TRACE is not set
# CONFIG_RCU_EQS_DEBUG is not set
# end of RCU Debugging

# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
# CONFIG_SAMPLES is not set
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y

#
# powerpc Debugging
#
# CONFIG_PPC_DISABLE_WERROR is not set
CONFIG_PPC_WERROR=y
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_CODE_PATCHING_SELFTEST is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
# CONFIG_XMON is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
# end of powerpc Debugging

#
# Kernel Testing and Coverage
#
# CONFIG_KUNIT is not set
# CONFIG_NOTIFIER_ERROR_INJECTION is not set
# CONFIG_FAULT_INJECTION is not set
CONFIG_ARCH_HAS_KCOV=y
CONFIG_CC_HAS_SANCOV_TRACE_PC=y
# CONFIG_KCOV is not set
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_ARCH_USE_MEMTEST=y
# CONFIG_MEMTEST is not set
# end of Kernel Testing and Coverage
# end of Kernel hacking

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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-16  6:23 ` [PATCH 1/6] powerpc/code-patching: Implement generic text patching function Benjamin Gray
  2022-09-16  9:39   ` kernel test robot
@ 2022-09-16 11:16   ` kernel test robot
  2022-09-19  6:04   ` Christophe Leroy
  2022-09-19  6:38   ` Christophe Leroy
  3 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-09-16 11:16 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: christophe.leroy, kbuild-all, ajd, npiggin, jpoimboe, jbaron,
	rostedt, Benjamin Gray, ardb

Hi Benjamin,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on powerpc/next]
[also build test WARNING on next-20220916]
[cannot apply to linus/master v6.0-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Benjamin-Gray/Out-of-line-static-calls-for-powerpc64-ELF-V2/20220916-142951
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-allyesconfig (https://download.01.org/0day-ci/archive/20220916/202209161957.R4ivN9mo-lkp@intel.com/config)
compiler: powerpc-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/31a9d4d694a3a20129f20390f3d7af2c154c8ed1
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Benjamin-Gray/Out-of-line-static-calls-for-powerpc64-ELF-V2/20220916-142951
        git checkout 31a9d4d694a3a20129f20390f3d7af2c154c8ed1
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=powerpc SHELL=/bin/bash arch/powerpc/lib/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> arch/powerpc/lib/code-patching.c:235:7: warning: no previous prototype for 'patch_memory' [-Wmissing-prototypes]
     235 | void *patch_memory(void *dest, const void *src, size_t size)
         |       ^~~~~~~~~~~~
   arch/powerpc/lib/code-patching.c: In function 'patch_instruction':
   arch/powerpc/lib/code-patching.c:248:24: error: implicit declaration of function 'patch_text'; did you mean 'path_get'? [-Werror=implicit-function-declaration]
     248 |                 return patch_text(addr, &val, sizeof(val), true);
         |                        ^~~~~~~~~~
         |                        path_get
   arch/powerpc/lib/code-patching.c: At top level:
   arch/powerpc/lib/code-patching.c:230:12: warning: 'do_patch_instruction' defined but not used [-Wunused-function]
     230 | static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
         |            ^~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +/patch_memory +235 arch/powerpc/lib/code-patching.c

   234	
 > 235	void *patch_memory(void *dest, const void *src, size_t size)
   236	{
   237		return memcpy(dest, src, size);
   238	}
   239	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-16  6:23 ` [PATCH 1/6] powerpc/code-patching: Implement generic text patching function Benjamin Gray
  2022-09-16  9:39   ` kernel test robot
  2022-09-16 11:16   ` kernel test robot
@ 2022-09-19  6:04   ` Christophe Leroy
  2022-09-19  6:49     ` Benjamin Gray
  2022-09-19  6:38   ` Christophe Leroy
  3 siblings, 1 reply; 21+ messages in thread
From: Christophe Leroy @ 2022-09-19  6:04 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: ajd, peterz, ardb, jbaron, rostedt, npiggin, jpoimboe



Le 16/09/2022 à 08:23, Benjamin Gray a écrit :
> Adds a generic text patching mechanism for patches of 1, 2, 4, or 8
> bytes. The patcher conditionally syncs the icache depending on if
> the content will be executed (as opposed to, e.g., read-only data).
> 
> The `patch_instruction` function is reimplemented in terms of this
> more generic function. This generic implementation allows patching of
> arbitrary 64-bit data, whereas the original `patch_instruction` decided
> the size based on the 'instruction' opcode, so was not suitable for
> arbitrary data.

With CONFIG_STRICT_KERNEL_RWX, this patches causes a 15% time increase 
for activation/deactivation of ftrace.

Without CONFIG_STRICT_KERNEL_RWX, it doesn't build.

> 
> Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
> ---
>   arch/powerpc/include/asm/code-patching.h |   1 +
>   arch/powerpc/lib/code-patching.c         | 135 +++++++++++++++--------
>   2 files changed, 89 insertions(+), 47 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
> index 1c6316ec4b74..6a52c19dae46 100644
> --- a/arch/powerpc/include/asm/code-patching.h
> +++ b/arch/powerpc/include/asm/code-patching.h
> @@ -76,6 +76,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_text_data(void *dest, const void *src, size_t size);
>   
>   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 ad0cf3108dd0..a09a0898c2ce 100644
> --- a/arch/powerpc/lib/code-patching.c
> +++ b/arch/powerpc/lib/code-patching.c
> @@ -3,6 +3,7 @@
>    *  Copyright 2008 Michael Ellerman, IBM Corporation.
>    */
>   
> +#include <linux/mm.h>
>   #include <linux/kprobes.h>
>   #include <linux/vmalloc.h>
>   #include <linux/init.h>
> @@ -14,32 +15,7 @@
>   #include <asm/page.h>
>   #include <asm/code-patching.h>
>   #include <asm/inst.h>
> -
> -static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr, u32 *patch_addr)
> -{
> -	if (!ppc_inst_prefixed(instr)) {
> -		u32 val = ppc_inst_val(instr);
> -
> -		__put_kernel_nofault(patch_addr, &val, u32, failed);
> -	} else {
> -		u64 val = ppc_inst_as_ulong(instr);
> -
> -		__put_kernel_nofault(patch_addr, &val, u64, failed);
> -	}
> -
> -	asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
> -							    "r" (exec_addr));
> -
> -	return 0;
> -
> -failed:
> -	return -EPERM;
> -}
> -
> -int raw_patch_instruction(u32 *addr, ppc_inst_t instr)
> -{
> -	return __patch_instruction(addr, instr, addr);
> -}
> +#include <asm/cacheflush.h>
>   
>   #ifdef CONFIG_STRICT_KERNEL_RWX
>   static DEFINE_PER_CPU(struct vm_struct *, text_poke_area);
> @@ -147,16 +123,44 @@ static void unmap_patch_area(unsigned long addr)
>   	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
>   }
>   
> -static int __do_patch_instruction(u32 *addr, ppc_inst_t instr)
> +static int __patch_text(void *dest, const void *src, size_t size, bool is_exec, void *exec_addr)

Is 'text' a good name ? For me text mean executable code. Should it be 
__patch_memory() ?


Why pass src as a void * ? This forces data to go via the stack. Can't 
you pass it as a 'long' ?

> +{
> +	if (virt_to_pfn(dest) != virt_to_pfn(dest + size - 1))
> +		return -EFAULT;

Why do you need that new check ?

> +
> +	switch (size) {
> +		case 1:
> +			__put_kernel_nofault(dest, src, u8, failed);
> +			break;
> +		case 2:
> +			__put_kernel_nofault(dest, src, u16, failed);
> +			break;
> +		case 4:
> +			__put_kernel_nofault(dest, src, u32, failed);
> +			break;
> +		case 8:
> +			__put_kernel_nofault(dest, src, u64, failed);
> +			break;

Is case 8 needed for PPC32 ?

> +	}

Do you catch it when size if none of 1,2,4,8 ?

> +
> +	asm ("dcbst 0, %0; sync" :: "r" (dest));

Maybe write it in C:

	dcbst(dest);
	mb(); /* sync */

> +
> +	if (is_exec)
> +		asm ("icbi 0,%0; sync; isync" :: "r" (exec_addr));

Same, can be:

	if (is_exec) {
		icbi(exec_addr);
		mb(); /* sync */
		isync();
	}

Or keep it flat:

	if (!is_exec)
		return 0;

	icbi(exec_addr);
	mb(); /* sync */
	isync();

	return 0;

> +
> +	return 0;
> +
> +failed:
> +	return -EPERM;
> +}
> +
> +static pte_t *start_text_patch(void* dest, u32 **patch_addr)
>   {
> -	int err;
> -	u32 *patch_addr;
> -	unsigned long text_poke_addr;
>   	pte_t *pte;
> -	unsigned long pfn = get_patch_pfn(addr);
> +	unsigned long text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr & PAGE_MASK;
> +	unsigned long pfn = get_patch_pfn(dest);
>   
> -	text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr & PAGE_MASK;
> -	patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
> +	*patch_addr = (u32 *)(text_poke_addr + offset_in_page(dest));
>   
>   	pte = virt_to_kpte(text_poke_addr);
>   	__set_pte_at(&init_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), 0);
> @@ -164,33 +168,63 @@ static int __do_patch_instruction(u32 *addr, ppc_inst_t instr)
>   	if (radix_enabled())
>   		asm volatile("ptesync": : :"memory");
>   
> -	err = __patch_instruction(addr, instr, patch_addr);
> +	return pte;
> +}
>   
> +static void finish_text_patch(pte_t *pte)
> +{
> +	unsigned long text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr & PAGE_MASK;

Leave a blank line after variables declaration.

>   	pte_clear(&init_mm, text_poke_addr, pte);
>   	flush_tlb_kernel_range(text_poke_addr, text_poke_addr + PAGE_SIZE);
> +}
> +
> +static int do_patch_text(void *dest, const void *src, size_t size, bool is_exec)
> +{
> +	int err;
> +	pte_t *pte;
> +	u32 *patch_addr;
> +
> +	pte = start_text_patch(dest, &patch_addr);
> +	err = __patch_text(patch_addr, src, size, is_exec, dest);
> +	finish_text_patch(pte);

Why do you need to split this function in three parts ? I can't see the 
added value, all it does is reduce readability.

Did you check the impact of calling __this_cpu_read() twice ?

>   
>   	return err;
>   }
>   
> -static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
> +static int patch_text(void *dest, const void *src, size_t size, bool is_exec)

Same, do you need the source data to go via stack ?

>   {
>   	int err;
>   	unsigned long flags;
>   
> -	/*
> -	 * During early early boot patch_instruction is called
> -	 * when text_poke_area is not ready, but we still need
> -	 * to allow patching. We just do the plain old patching
> -	 */
> +	/* Make sure we aren't patching a freed init section */
> +	if (static_branch_likely(&init_mem_is_free) && init_section_contains(dest, 4))
> +		return 0;
> +
>   	if (!static_branch_likely(&poking_init_done))
> -		return raw_patch_instruction(addr, instr);
> +		return __patch_text(dest, src, size, is_exec, dest);
>   
>   	local_irq_save(flags);
> -	err = __do_patch_instruction(addr, instr);
> +	err = do_patch_text(dest, src, size, is_exec);
>   	local_irq_restore(flags);
>   
>   	return err;
>   }
> +
> +int patch_text_data(void *dest, const void *src, size_t size) {

{ must be on next line for functions start.

> +	return patch_text(dest, src, size, false);
> +}
> +
> +int raw_patch_instruction(u32 *addr, ppc_inst_t instr)
> +{
> +	if (!ppc_inst_prefixed(instr)) {
> +		u32 val = ppc_inst_val(instr);
> +		return __patch_text(addr, &val, sizeof(val), true, addr);
> +	} else {
> +		u64 val = ppc_inst_as_ulong(instr);
> +		return __patch_text(addr, &val, sizeof(val), true, addr);
> +	}
> +}
> +
>   #else /* !CONFIG_STRICT_KERNEL_RWX */
>   
>   static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
> @@ -198,17 +232,24 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
>   	return raw_patch_instruction(addr, instr);
>   }
>   
> +void *patch_memory(void *dest, const void *src, size_t size)

What is this function used for ?

> +{
> +	return memcpy(dest, src, size);
> +}
> +
>   #endif /* CONFIG_STRICT_KERNEL_RWX */
>   
>   __ro_after_init DEFINE_STATIC_KEY_FALSE(init_mem_is_free);
>   
>   int patch_instruction(u32 *addr, ppc_inst_t instr)
>   {
> -	/* Make sure we aren't patching a freed init section */
> -	if (static_branch_likely(&init_mem_is_free) && init_section_contains(addr, 4))
> -		return 0;
> -
> -	return do_patch_instruction(addr, instr);
> +	if (!ppc_inst_prefixed(instr)) {
> +		u32 val = ppc_inst_val(instr);
> +		return patch_text(addr, &val, sizeof(val), true);
> +	} else {
> +		u64 val = ppc_inst_as_ulong(instr);
> +		return patch_text(addr, &val, sizeof(val), true);
> +	}
>   }
>   NOKPROBE_SYMBOL(patch_instruction);
>   

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

* Re: [PATCH 2/6] powerpc/module: Handle caller-saved TOC in module linker
  2022-09-16  6:23 ` [PATCH 2/6] powerpc/module: Handle caller-saved TOC in module linker Benjamin Gray
@ 2022-09-19  6:09   ` Christophe Leroy
  0 siblings, 0 replies; 21+ messages in thread
From: Christophe Leroy @ 2022-09-19  6:09 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: ajd, peterz, ardb, jbaron, rostedt, npiggin, jpoimboe



Le 16/09/2022 à 08:23, Benjamin Gray a écrit :
> The callee may set a field in `st_other` to 1 to indicate r2 should be
> treated as caller-saved. This means a trampoline must be used to save
> the current TOC before calling it and restore it afterwards, much like
> external calls.
> 
> This is necessary for supporting V2 ABI static calls that do not
> preserve the TOC.
> 
> Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
> ---
>   arch/powerpc/kernel/module_64.c | 12 +++++++++++-
>   1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
> index 7e45dc98df8a..3656476097c2 100644
> --- a/arch/powerpc/kernel/module_64.c
> +++ b/arch/powerpc/kernel/module_64.c
> @@ -55,6 +55,11 @@ static unsigned int local_entry_offset(const Elf64_Sym *sym)
>   	 * of function and try to derive r2 from it). */
>   	return PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
>   }
> +
> +static bool need_r2save_stub(unsigned char st_other) {

Please read 
https://docs.kernel.org/process/coding-style.html#placing-braces-and-spaces

" ... functions: they have the opening brace at the beginning of the 
next line ..."

> +	return ((st_other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT) == 1;
> +}
> +
>   #else
>   
>   static func_desc_t func_desc(unsigned long addr)
> @@ -66,6 +71,10 @@ static unsigned int local_entry_offset(const Elf64_Sym *sym)
>   	return 0;
>   }
>   
> +static bool need_r2save_stub(unsigned char st_other) {
> +	return false;
> +}
> +
>   void *dereference_module_function_descriptor(struct module *mod, void *ptr)
>   {
>   	if (ptr < (void *)mod->arch.start_opd ||
> @@ -632,7 +641,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
>   		case R_PPC_REL24:
>   			/* FIXME: Handle weak symbols here --RR */
>   			if (sym->st_shndx == SHN_UNDEF ||
> -			    sym->st_shndx == SHN_LIVEPATCH) {
> +			    sym->st_shndx == SHN_LIVEPATCH ||
> +			    need_r2save_stub(sym->st_other)) {
>   				/* External: go via stub */
>   				value = stub_for_addr(sechdrs, value, me,
>   						strtab + sym->st_name);

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

* Re: [PATCH 3/6] powerpc/module: Optimise nearby branches in ELF V2 ABI stub
  2022-09-16  6:23 ` [PATCH 3/6] powerpc/module: Optimise nearby branches in ELF V2 ABI stub Benjamin Gray
@ 2022-09-19  6:11   ` Christophe Leroy
  0 siblings, 0 replies; 21+ messages in thread
From: Christophe Leroy @ 2022-09-19  6:11 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: ajd, peterz, ardb, jbaron, rostedt, npiggin, jpoimboe



Le 16/09/2022 à 08:23, Benjamin Gray a écrit :
> Inserts a direct branch to the stub target when possible, replacing the
> mtctr/btctr sequence.
> 
> The load into r12 could potentially be skipped too, but that change
> would need to refactor the arguments to indicate that the address
> does not have a separate local entry point.
> 
> This helps the static call implementation, where modules calling their
> own trampolines are called through this stub and the trampoline is
> easily within range of a direct branch.
> 
> Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
> ---
>   arch/powerpc/kernel/module_64.c | 13 +++++++++++--
>   1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
> index 3656476097c2..03ab28d86008 100644
> --- a/arch/powerpc/kernel/module_64.c
> +++ b/arch/powerpc/kernel/module_64.c
> @@ -432,8 +432,17 @@ static inline int create_stub(const Elf64_Shdr *sechdrs,
>   		return create_ftrace_stub(entry, addr, me);
>   
>   	for (i = 0; i < ARRAY_SIZE(ppc64_stub_insns); i++) {
> -		if (patch_instruction(&entry->jump[i],
> -				      ppc_inst(ppc64_stub_insns[i])))
> +		ppc_inst_t inst = ppc_inst(ppc64_stub_insns[i]);
> +
> +		// Replace the indirect branch with a direct branch where possible
> +		if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2) && i == 4) {
> +			ppc_inst_t direct;

Add blank line here.

> +			if (create_branch(&direct, (void*) entry + (i * 4), addr, 0) == 0) {

No braces for single lines if statement.

> +				inst = direct;
> +			}
> +		}
> +
> +		if (patch_instruction(&entry->jump[i], inst))
>   			return 0;
>   	}
>   

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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-16  6:23 ` [PATCH 1/6] powerpc/code-patching: Implement generic text patching function Benjamin Gray
                     ` (2 preceding siblings ...)
  2022-09-19  6:04   ` Christophe Leroy
@ 2022-09-19  6:38   ` Christophe Leroy
  2022-09-20  1:49     ` Benjamin Gray
  3 siblings, 1 reply; 21+ messages in thread
From: Christophe Leroy @ 2022-09-19  6:38 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: ajd, peterz, ardb, jbaron, rostedt, npiggin, jpoimboe



Le 16/09/2022 à 08:23, Benjamin Gray a écrit :
>   
> -static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
> +static int patch_text(void *dest, const void *src, size_t size, bool is_exec)
>   {
>   	int err;
>   	unsigned long flags;
>   
> -	/*
> -	 * During early early boot patch_instruction is called
> -	 * when text_poke_area is not ready, but we still need
> -	 * to allow patching. We just do the plain old patching
> -	 */
> +	/* Make sure we aren't patching a freed init section */
> +	if (static_branch_likely(&init_mem_is_free) && init_section_contains(dest, 4))
> +		return 0;
> +
>   	if (!static_branch_likely(&poking_init_done))
> -		return raw_patch_instruction(addr, instr);
> +		return __patch_text(dest, src, size, is_exec, dest);
>   

Test ordering looks odd. How can init_mem_is_free be true and 
poking_init_done be false ?

>   	local_irq_save(flags);
> -	err = __do_patch_instruction(addr, instr);
> +	err = do_patch_text(dest, src, size, is_exec);
>   	local_irq_restore(flags);
>   
>   	return err;
>   }

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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-19  6:04   ` Christophe Leroy
@ 2022-09-19  6:49     ` Benjamin Gray
  2022-09-19  7:16       ` Christophe Leroy
  0 siblings, 1 reply; 21+ messages in thread
From: Benjamin Gray @ 2022-09-19  6:49 UTC (permalink / raw)
  To: Christophe Leroy, linuxppc-dev
  Cc: ajd, peterz, npiggin, ardb, jbaron, rostedt, jpoimboe

On Mon, 2022-09-19 at 06:04 +0000, Christophe Leroy wrote:
> With CONFIG_STRICT_KERNEL_RWX, this patches causes a 15% time
> increase 
> for activation/deactivation of ftrace.

It's possible that new alignment check is the cause. I'll see


> Without CONFIG_STRICT_KERNEL_RWX, it doesn't build.

Yup, fixed for v2

> > +static int __patch_text(void *dest, const void *src, size_t size,
> > bool is_exec, void *exec_addr)
> 
> Is 'text' a good name ? For me text mean executable code. Should it
> be 
> __patch_memory() ?

Well patching regular memory is just a normal store. Text to me implies
its non-writeable. Though __patch_memory would be fine.

> Why pass src as a void * ? This forces data to go via the stack.
> Can't 
> you pass it as a 'long' ?

Probably, I wasn't aware that it would make a difference. I prefer
pointers in general for their semantic meaning, but will change if it
affects param passing.

> > +       if (virt_to_pfn(dest) != virt_to_pfn(dest + size - 1))
> > +               return -EFAULT;
> 
> Why do you need that new check ?

If the patch crosses a page boundary then letting it happen is
unpredictable. Though perhaps this requirement can just be put as a
comment, or require that patches be aligned to the patch size.

> > +               case 8:
> > +                       __put_kernel_nofault(dest, src, u64,
> > failed);
> > +                       break;
> 
> Is case 8 needed for PPC32 ?

I don't have a particular need for it, but the underlying
__put_kernel_nofault is capable of it so I included it.

> > +       }
> 
> Do you catch it when size if none of 1,2,4,8 ?
> 

Not yet. Perhaps I should wrap patch_text_data in a macro that checks
the size with BUILD_BUG_ON? I'd rather not check at runtime.

> > +
> > +       asm ("dcbst 0, %0; sync" :: "r" (dest));
> 
> Maybe write it in C:
> 
>         dcbst(dest);
>         mb(); /* sync */
> 
> > +
> > +       if (is_exec)
> > +               asm ("icbi 0,%0; sync; isync" :: "r" (exec_addr));
> 
> Same, can be:
> 
>         if (is_exec) {
>                 icbi(exec_addr);
>                 mb(); /* sync */
>                 isync();
>         }
> 
> Or keep it flat:
> 
>         if (!is_exec)
>                 return 0;
> 
>         icbi(exec_addr);
>         mb(); /* sync */
>         isync();
> 
>         return 0;

Will try this.

> > +static int do_patch_text(void *dest, const void *src, size_t size,
> > bool is_exec)
> > +{
> > +       int err;
> > +       pte_t *pte;
> > +       u32 *patch_addr;
> > +
> > +       pte = start_text_patch(dest, &patch_addr);
> > +       err = __patch_text(patch_addr, src, size, is_exec, dest);
> > +       finish_text_patch(pte);
> 
> Why do you need to split this function in three parts ? I can't see
> the 
> added value, all it does is reduce readability.

It made it more readable to me, so the __patch_text didn't get buried.
It also made it easier to do the refactoring, and potentially add code
patching variants that use the poke area but not __patch_text. I'll
remove it for v2 though given this is the only use right now.

> Did you check the impact of calling __this_cpu_read() twice ?

I wasn't concerned about performance, but given I'll merge it back
again it will only be read once in v2 again.

> > +void *patch_memory(void *dest, const void *src, size_t size)
> 
> What is this function used for ?
> 

Build failure apparently :)

It's removed in v2.
> 

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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-19  6:49     ` Benjamin Gray
@ 2022-09-19  7:16       ` Christophe Leroy
  2022-09-20  2:32         ` Benjamin Gray
  0 siblings, 1 reply; 21+ messages in thread
From: Christophe Leroy @ 2022-09-19  7:16 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: ajd, peterz, npiggin, ardb, jbaron, rostedt, jpoimboe



Le 19/09/2022 à 08:49, Benjamin Gray a écrit :
> On Mon, 2022-09-19 at 06:04 +0000, Christophe Leroy wrote:
>> With CONFIG_STRICT_KERNEL_RWX, this patches causes a 15% time
>> increase
>> for activation/deactivation of ftrace.
> 
> It's possible that new alignment check is the cause. I'll see
> 
> 
>> Without CONFIG_STRICT_KERNEL_RWX, it doesn't build.
> 
> Yup, fixed for v2
> 
>>> +static int __patch_text(void *dest, const void *src, size_t size,
>>> bool is_exec, void *exec_addr)
>>
>> Is 'text' a good name ? For me text mean executable code. Should it
>> be
>> __patch_memory() ?
> 
> Well patching regular memory is just a normal store. Text to me implies
> its non-writeable. Though __patch_memory would be fine.
> 
>> Why pass src as a void * ? This forces data to go via the stack.
>> Can't
>> you pass it as a 'long' ?
> 
> Probably, I wasn't aware that it would make a difference. I prefer
> pointers in general for their semantic meaning, but will change if it
> affects param passing.
> 
>>> +       if (virt_to_pfn(dest) != virt_to_pfn(dest + size - 1))
>>> +               return -EFAULT;
>>
>> Why do you need that new check ?
> 
> If the patch crosses a page boundary then letting it happen is
> unpredictable. Though perhaps this requirement can just be put as a
> comment, or require that patches be aligned to the patch size.

Why would it be unpredictable ? Only one page is mapped. If it crosses 
the boundary, __put_kernel_nofault() will fail in a controled manner.
I see no point in doing the check before every write.

Requiring an alignment to the patch size may be problematic when 
patching prefixed instructions (8 bytes). Allthough they are garantied 
to lie in a single cache line hence a single page, they are not 
garantied to be aligned to more than 4 bytes.

And while you are thinking about alignment, don't forget that dcbst and 
icbi apply on a give cacheline. If your memory crosses a cacheline you 
may have a problem.

> 
>>> +               case 8:
>>> +                       __put_kernel_nofault(dest, src, u64,
>>> failed);
>>> +                       break;
>>
>> Is case 8 needed for PPC32 ?
> 
> I don't have a particular need for it, but the underlying
> __put_kernel_nofault is capable of it so I included it.

Well, not including it will allow you to pass the source as a 'long' as 
mentionned above.

> 
>>> +       }
>>
>> Do you catch it when size if none of 1,2,4,8 ?
>>
> 
> Not yet. Perhaps I should wrap patch_text_data in a macro that checks
> the size with BUILD_BUG_ON? I'd rather not check at runtime.

Not necessarily a macro. WOuld be better as a static __always_inline in 
code_patching.h

> 
>>> +
>>> +       asm ("dcbst 0, %0; sync" :: "r" (dest));
>>
>> Maybe write it in C:
>>
>>          dcbst(dest);
>>          mb(); /* sync */
>>
>>> +
>>> +       if (is_exec)
>>> +               asm ("icbi 0,%0; sync; isync" :: "r" (exec_addr));
>>
>> Same, can be:
>>
>>          if (is_exec) {
>>                  icbi(exec_addr);
>>                  mb(); /* sync */
>>                  isync();
>>          }
>>
>> Or keep it flat:
>>
>>          if (!is_exec)
>>                  return 0;
>>
>>          icbi(exec_addr);
>>          mb(); /* sync */
>>          isync();
>>
>>          return 0;
> 
> Will try this.
> 
>>> +static int do_patch_text(void *dest, const void *src, size_t size,
>>> bool is_exec)
>>> +{
>>> +       int err;
>>> +       pte_t *pte;
>>> +       u32 *patch_addr;
>>> +
>>> +       pte = start_text_patch(dest, &patch_addr);
>>> +       err = __patch_text(patch_addr, src, size, is_exec, dest);
>>> +       finish_text_patch(pte);
>>
>> Why do you need to split this function in three parts ? I can't see
>> the
>> added value, all it does is reduce readability.
> 
> It made it more readable to me, so the __patch_text didn't get buried.
> It also made it easier to do the refactoring, and potentially add code
> patching variants that use the poke area but not __patch_text. I'll
> remove it for v2 though given this is the only use right now.
> 
>> Did you check the impact of calling __this_cpu_read() twice ?
> 
> I wasn't concerned about performance, but given I'll merge it back
> again it will only be read once in v2 again.
> 
>>> +void *patch_memory(void *dest, const void *src, size_t size)
>>
>> What is this function used for ?
>>
> 
> Build failure apparently :)
> 
> It's removed in v2.
>>

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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-19  6:38   ` Christophe Leroy
@ 2022-09-20  1:49     ` Benjamin Gray
  0 siblings, 0 replies; 21+ messages in thread
From: Benjamin Gray @ 2022-09-20  1:49 UTC (permalink / raw)
  To: Christophe Leroy, linuxppc-dev
  Cc: ajd, peterz, npiggin, ardb, jbaron, rostedt, jpoimboe

On Mon, 2022-09-19 at 06:38 +0000, Christophe Leroy wrote:
> Le 16/09/2022 à 08:23, Benjamin Gray a écrit :
> > [...]
> > +       /* Make sure we aren't patching a freed init section */
> > +       if (static_branch_likely(&init_mem_is_free) &&
> > init_section_contains(dest, 4))
> > +               return 0;
> > +
> >         if (!static_branch_likely(&poking_init_done))
> > -               return raw_patch_instruction(addr, instr);
> > +               return __patch_text(dest, src, size, is_exec,
> > dest);
> >   
> 
> Test ordering looks odd. How can init_mem_is_free be true and 
> poking_init_done be false ?
> > 
That's just the flattened result of the original STRICT_KERNEL_RWX case
(as I hadn't tested building with it disabled).

With the build fixed for v2, the structure is similar to the original
the second check is not performed if CONFIG_STRICT_KERNEL_RWX is
disabled.
> 

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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-19  7:16       ` Christophe Leroy
@ 2022-09-20  2:32         ` Benjamin Gray
  2022-09-20  5:44           ` Christophe Leroy
  0 siblings, 1 reply; 21+ messages in thread
From: Benjamin Gray @ 2022-09-20  2:32 UTC (permalink / raw)
  To: Christophe Leroy, linuxppc-dev
  Cc: ajd, peterz, npiggin, ardb, jbaron, rostedt, jpoimboe

On Mon, 2022-09-19 at 07:16 +0000, Christophe Leroy wrote:
> Why would it be unpredictable ? Only one page is mapped. If it
> crosses 
> the boundary, __put_kernel_nofault() will fail in a controled manner.
> I see no point in doing the check before every write.

Oh I didn't see that get_vm_area automatically adds a guard. You're
right then, it's redundant. I had assumed there could be a writeable
mapping directly after.

> And while you are thinking about alignment, don't forget that dcbst
> and 
> icbi apply on a give cacheline. If your memory crosses a cacheline
> you 
> may have a problem.

Yeah, though this applies to the existing patch_instruction too (in
theory; prefixed instructions cannot cross a 64 byte boundary, but the
ISA does not specify minimum cacheline size). I don't have a nice
solution right now though. The flush needs to be done on the effective
address (i.e. text poke address) according to the ISA, but the text
poke address is only valid within the IRQ save region. So non-prefixed
instruction patching would either pay for some kind of check, or need
special casing.

Maybe an "is aligned" flag in a generic __patch_text to make the extra
flush conditional is good enough?


Related to EA based flushing, data patching ought to run 'dcbst' on the
'exec_addr' too. So given the icache flush only needs to be applied to
instruction patching, and data flush only to data patching, I plan to
move those exec_addr syncs outside of __patch_text to the relevant
public instruction/data specific entry points.

> > > > +               case 8:
> > > > +                       __put_kernel_nofault(dest, src, u64,
> > > > failed);
> > > > +                       break;
> > > 
> > > Is case 8 needed for PPC32 ?
> > 
> > I don't have a particular need for it, but the underlying
> > __put_kernel_nofault is capable of it so I included it.
> 
> Well, not including it will allow you to pass the source as a 'long'
> as 
> mentionned above.

I checked the machine code of a 32 bit build, but it still passes the
pointer in a register. I also checked all 3 ABI docs and they say a
pointer is the same size as a long. Could you clarify when a pointer is
passed on the stack but not a long?

Or do you mean that we could pass the pointed-to data in a register and
skip the pointer altogether? That seems like a good choice, but
__put_kernel_nofault takes a pointer to the source and the
implementation is very complex. I don't think I can safely write the
modified version we'd need at this point.

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

* Re: [PATCH 4/6] static_call: Move static call selftest to static_call_selftest.c
  2022-09-16  6:23 ` [PATCH 4/6] static_call: Move static call selftest to static_call_selftest.c Benjamin Gray
@ 2022-09-20  4:30   ` Andrew Donnellan
  0 siblings, 0 replies; 21+ messages in thread
From: Andrew Donnellan @ 2022-09-20  4:30 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: christophe.leroy, peterz, npiggin, ardb, jbaron, rostedt, jpoimboe

On Fri, 2022-09-16 at 16:23 +1000, Benjamin Gray wrote:
> These tests are out-of-line only, so moving them to the
> their own file allows them to be run when an arch does
> not implement inline static calls.
> 
> Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>

This looks very sensible.

Reviewed-by: Andrew Donnellan <ajd@linux.ibm.com>


-- 
Andrew Donnellan    OzLabs, ADL Canberra
ajd@linux.ibm.com   IBM Australia Limited


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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-20  2:32         ` Benjamin Gray
@ 2022-09-20  5:44           ` Christophe Leroy
  2022-09-20  7:01             ` Benjamin Gray
  0 siblings, 1 reply; 21+ messages in thread
From: Christophe Leroy @ 2022-09-20  5:44 UTC (permalink / raw)
  To: Benjamin Gray, linuxppc-dev
  Cc: ajd, peterz, npiggin, ardb, jbaron, rostedt, jpoimboe



Le 20/09/2022 à 04:32, Benjamin Gray a écrit :
> On Mon, 2022-09-19 at 07:16 +0000, Christophe Leroy wrote:
>> Why would it be unpredictable ? Only one page is mapped. If it
>> crosses
>> the boundary, __put_kernel_nofault() will fail in a controled manner.
>> I see no point in doing the check before every write.
> 
> Oh I didn't see that get_vm_area automatically adds a guard. You're
> right then, it's redundant. I had assumed there could be a writeable
> mapping directly after.
> 
>> And while you are thinking about alignment, don't forget that dcbst
>> and
>> icbi apply on a give cacheline. If your memory crosses a cacheline
>> you
>> may have a problem.
> 
> Yeah, though this applies to the existing patch_instruction too (in
> theory; prefixed instructions cannot cross a 64 byte boundary, but the
> ISA does not specify minimum cacheline size). I don't have a nice
> solution right now though. The flush needs to be done on the effective
> address (i.e. text poke address) according to the ISA, but the text
> poke address is only valid within the IRQ save region. So non-prefixed
> instruction patching would either pay for some kind of check, or need
> special casing.

As far as I know, cachelines are minimum 64 bytes on PPC64 aren't they ?

> 
> Maybe an "is aligned" flag in a generic __patch_text to make the extra
> flush conditional is good enough?

Well, if the cacheline is already flushed, the operation will be a nop 
anyway so it shouldn't cost much to flush both addresses, after all it 
is the sync that costs and you'll still have only one.

> 
> 
> Related to EA based flushing, data patching ought to run 'dcbst' on the
> 'exec_addr' too. So given the icache flush only needs to be applied to
> instruction patching, and data flush only to data patching, I plan to
> move those exec_addr syncs outside of __patch_text to the relevant
> public instruction/data specific entry points.

Why should it run 'dcbst' on the 'exec_addr' at all ? We have not 
written anything there.

Anyway, powerpc handles cachelines by physical address, so no matter 
which EA you use as far as it is done.

And dcbst is handled as a write by the MMU, so you just can't apply it 
on the read-only exec address.


> 
>>>>> +               case 8:
>>>>> +                       __put_kernel_nofault(dest, src, u64,
>>>>> failed);
>>>>> +                       break;
>>>>
>>>> Is case 8 needed for PPC32 ?
>>>
>>> I don't have a particular need for it, but the underlying
>>> __put_kernel_nofault is capable of it so I included it.
>>
>> Well, not including it will allow you to pass the source as a 'long'
>> as
>> mentionned above.
> 
> I checked the machine code of a 32 bit build, but it still passes the
> pointer in a register. I also checked all 3 ABI docs and they say a
> pointer is the same size as a long. Could you clarify when a pointer is
> passed on the stack but not a long?
> 
> Or do you mean that we could pass the pointed-to data in a register and
> skip the pointer altogether? That seems like a good choice, but
> __put_kernel_nofault takes a pointer to the source and the
> implementation is very complex. I don't think I can safely write the
> modified version we'd need at this point.

Yes I meant to pass the value instead of passing a pointer to the value.
When you pass a pointer to a value, it forces gcc to put that value in 
memory, namely in the stack. While when you pass the value directly , 
then it gets passed in a register.

So I think you have to pass the value and only change it to a pointer to 
that value at the time you are calling __put_kernel_nofault(). That way 
gcc is able to handle it efficiently and most of the time voids going 
via memory.

Today raw_patch_instruction() is :

c0017ebc <raw_patch_instruction>:
c0017ebc:	90 83 00 00 	stw     r4,0(r3)
c0017ec0:	7c 00 18 6c 	dcbst   0,r3
c0017ec4:	7c 00 04 ac 	hwsync
c0017ec8:	7c 00 1f ac 	icbi    0,r3
c0017ecc:	7c 00 04 ac 	hwsync
c0017ed0:	4c 00 01 2c 	isync
c0017ed4:	38 60 00 00 	li      r3,0
c0017ed8:	4e 80 00 20 	blr
c0017edc:	38 60 ff ff 	li      r3,-1
c0017ee0:	4e 80 00 20 	blr

Here r4 is the value to be written.


With your patch, extract from __patch_text() is:

c0017fdc:	28 05 00 04 	cmplwi  r5,4
c0017fe0:	41 82 00 74 	beq     c0018054 <__patch_text+0x98>
c0017fe4:	41 81 00 40 	bgt     c0018024 <__patch_text+0x68>
c0017fe8:	28 05 00 01 	cmplwi  r5,1
c0017fec:	41 82 00 74 	beq     c0018060 <__patch_text+0xa4>
c0017ff0:	28 05 00 02 	cmplwi  r5,2
c0017ff4:	40 82 00 0c 	bne     c0018000 <__patch_text+0x44>
c0017ff8:	a1 24 00 00 	lhz     r9,0(r4)
c0017ffc:	b1 23 00 00 	sth     r9,0(r3)
c0018000:	7c 00 18 6c 	dcbst   0,r3
c0018004:	7c 00 04 ac 	hwsync
c0018008:	2c 06 00 00 	cmpwi   r6,0
c001800c:	38 60 00 00 	li      r3,0
c0018010:	4d 82 00 20 	beqlr
c0018014:	7c 00 3f ac 	icbi    0,r7
c0018018:	7c 00 04 ac 	hwsync
c001801c:	4c 00 01 2c 	isync
c0018020:	4e 80 00 20 	blr
c0018024:	28 05 00 08 	cmplwi  r5,8
c0018028:	40 a2 ff d8 	bne     c0018000 <__patch_text+0x44>
c001802c:	81 44 00 00 	lwz     r10,0(r4)
c0018030:	81 64 00 04 	lwz     r11,4(r4)
c0018034:	91 43 00 00 	stw     r10,0(r3)
c0018038:	91 63 00 04 	stw     r11,4(r3)
c001803c:	7c 00 18 6c 	dcbst   0,r3
c0018040:	7c 00 04 ac 	hwsync
c0018044:	2c 06 00 00 	cmpwi   r6,0
c0018048:	38 60 00 00 	li      r3,0
c001804c:	4d 82 00 20 	beqlr
c0018050:	4b ff ff c4 	b       c0018014 <__patch_text+0x58>
c0018054:	81 24 00 00 	lwz     r9,0(r4)
c0018058:	91 23 00 00 	stw     r9,0(r3)
c001805c:	4b ff ff a4 	b       c0018000 <__patch_text+0x44>
c0018060:	89 24 00 00 	lbz     r9,0(r4)
c0018064:	99 23 00 00 	stb     r9,0(r3)
c0018068:	4b ff ff 98 	b       c0018000 <__patch_text+0x44>
c001806c:	38 60 ff ff 	li      r3,-1
c0018070:	4e 80 00 20 	blr
c0018074:	38 60 ff f2 	li      r3,-14
c0018078:	4e 80 00 20 	blr

So as you can see, r4 now is a memory pointer and the data has to be 
loaded from there.


Christophe

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

* Re: [PATCH 1/6] powerpc/code-patching: Implement generic text patching function
  2022-09-20  5:44           ` Christophe Leroy
@ 2022-09-20  7:01             ` Benjamin Gray
  0 siblings, 0 replies; 21+ messages in thread
From: Benjamin Gray @ 2022-09-20  7:01 UTC (permalink / raw)
  To: Christophe Leroy, linuxppc-dev
  Cc: ajd, peterz, npiggin, ardb, jbaron, rostedt, jpoimboe

On Tue, 2022-09-20 at 05:44 +0000, Christophe Leroy wrote:
> 
> As far as I know, cachelines are minimum 64 bytes on PPC64 aren't
> they ?

In practice maybe. I don't know what the convention is in the kernel in
cases where the ISA is less specific than what the supported machines
do.

> > Related to EA based flushing, data patching ought to run 'dcbst' on
> > the
> > 'exec_addr' too. So given the icache flush only needs to be applied
> > to
> > instruction patching, and data flush only to data patching, I plan
> > to
> > move those exec_addr syncs outside of __patch_text to the relevant
> > public instruction/data specific entry points.
> 
> Why should it run 'dcbst' on the 'exec_addr' at all ? We have not 
> written anything there.
> 
> Anyway, powerpc handles cachelines by physical address, so no matter 
> which EA you use as far as it is done.
> 
> And dcbst is handled as a write by the MMU, so you just can't apply
> it 
> on the read-only exec address.

I was talking with Michael Ellerman and he said that, for instructions
at least, the cache operations apply to the EA. So the exec address and
the text poke address are not interchangeable. Flushing the icache
needs to be done on the exec address, not the text poke address.

The ISA uses identical wording for icache and dcache blocks ("block
containing the byte addressed by EA"), so I assume the same applies for
data too. I am trying to flush a cached value for the data EA to ensure
that the value in main memory from the text-poke EA is correctly loaded
(that's the goal, I guess that was the wrong instruction).

Or given that multiple processes sharing a physical page for RW data is
a common scenario, it could just be expected that the hardware handles
virtual address aliases for data cache.

So I don't know, and the ISA doesn't look any different to me. I'll
need some kind of confirmation either way on this.

> Today raw_patch_instruction() is :
> 
> c0017ebc <raw_patch_instruction>:
> c0017ebc:       90 83 00 00     stw     r4,0(r3)
> c0017ec0:       7c 00 18 6c     dcbst   0,r3
> c0017ec4:       7c 00 04 ac     hwsync
> c0017ec8:       7c 00 1f ac     icbi    0,r3
> c0017ecc:       7c 00 04 ac     hwsync
> c0017ed0:       4c 00 01 2c     isync
> c0017ed4:       38 60 00 00     li      r3,0
> c0017ed8:       4e 80 00 20     blr
> c0017edc:       38 60 ff ff     li      r3,-1
> c0017ee0:       4e 80 00 20     blr
> 
> Here r4 is the value to be written.
> 
> 
> With your patch, extract from __patch_text() is:
> 
> [...]
> 
> So as you can see, r4 now is a memory pointer and the data has to be 
> loaded from there.

For this version of raw_patch_instruction

int raw_patch_instruction(u32 *addr, ppc_inst_t instr)
{
	int err;

	if (!ppc_inst_prefixed(instr)) {
		u32 val = ppc_inst_val(instr);
		err = __patch_text(addr, &val, sizeof(val));
	} else {
		u64 val = ppc_inst_as_ulong(instr);
		err = __patch_text(addr, &val, sizeof(val));
	}

	icbi(addr);
	mb(); /* sync */
	isync();

	return err;
}

This is the 32-bit machine code my compiler generated

c0040994 <raw_patch_instruction>:
c0040994:   7c 69 1b 78     mr      r9,r3
c0040998:   90 83 00 00     stw     r4,0(r3)
c004099c:   7c 00 18 6c     dcbst   0,r3
c00409a0:   7c 00 04 ac     hwsync
c00409a4:   38 60 00 00     li      r3,0
c00409a8:   7c 00 4f ac     icbi    0,r9
c00409ac:   7c 00 04 ac     hwsync
c00409b0:   4c 00 01 2c     isync
c00409b4:   4e 80 00 20     blr
c00409b8:   38 60 ff ff     li      r3,-1
c00409bc:   4b ff ff ec     b       c00409a8
                                      <raw_patch_instruction+0x14>

It seems GCC is able to use the register automatically. But I agree
that the __patch_text generation is better, and GCC can automatically
elide the pointer stuff, so will change for v2.

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

end of thread, other threads:[~2022-09-20  7:04 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-16  6:23 [PATCH 0/6] Out-of-line static calls for powerpc64 ELF V2 Benjamin Gray
2022-09-16  6:23 ` [PATCH 1/6] powerpc/code-patching: Implement generic text patching function Benjamin Gray
2022-09-16  9:39   ` kernel test robot
2022-09-16 11:16   ` kernel test robot
2022-09-19  6:04   ` Christophe Leroy
2022-09-19  6:49     ` Benjamin Gray
2022-09-19  7:16       ` Christophe Leroy
2022-09-20  2:32         ` Benjamin Gray
2022-09-20  5:44           ` Christophe Leroy
2022-09-20  7:01             ` Benjamin Gray
2022-09-19  6:38   ` Christophe Leroy
2022-09-20  1:49     ` Benjamin Gray
2022-09-16  6:23 ` [PATCH 2/6] powerpc/module: Handle caller-saved TOC in module linker Benjamin Gray
2022-09-19  6:09   ` Christophe Leroy
2022-09-16  6:23 ` [PATCH 3/6] powerpc/module: Optimise nearby branches in ELF V2 ABI stub Benjamin Gray
2022-09-19  6:11   ` Christophe Leroy
2022-09-16  6:23 ` [PATCH 4/6] static_call: Move static call selftest to static_call_selftest.c Benjamin Gray
2022-09-20  4:30   ` Andrew Donnellan
2022-09-16  6:23 ` [PATCH 5/6] powerpc/64: Add support for out-of-line static calls Benjamin Gray
2022-09-16  8:32   ` kernel test robot
2022-09-16  6:23 ` [PATCH 6/6] powerpc/64: Add tests " Benjamin Gray

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.