[RFC PATCH 1/2] powerpc: Don't use extable for WARN

Nicholas Piggin npiggin at gmail.com
Sat Sep 24 01:41:42 AEST 2022


extable is used for handling user memory access faults from kernel mode,
as such it is a fast-ish path. Using it in the very slow WARN path
increases the number of extable entries from 1306 to 6516 in a
ppc64le_defconfig vmlinux, increasing the average number of search
steps by ~2.3.

This patch adds a recovery address to the bug_entry struct instead of
using the extable. The size of the bug entry table plus the extable
go from 137kB to 126kB.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 arch/powerpc/Kconfig           |  4 ++++
 arch/powerpc/include/asm/bug.h | 31 ++++++++++++++++++++++++++++---
 arch/powerpc/kernel/traps.c    | 16 ++++++++++------
 include/asm-generic/bug.h      |  3 +++
 4 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 4c466acdc70d..3b379fa15082 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -336,6 +336,10 @@ config GENERIC_BUG_RELATIVE_POINTERS
 	def_bool y
 	depends on GENERIC_BUG
 
+config GENERIC_BUG_ARCH_ENTRY
+	def_bool y
+	depends on GENERIC_BUG
+
 config SYS_SUPPORTS_APM_EMULATION
 	default y if PMAC_APM_EMU
 	bool
diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
index 61a4736355c2..dec73137fea0 100644
--- a/arch/powerpc/include/asm/bug.h
+++ b/arch/powerpc/include/asm/bug.h
@@ -14,6 +14,7 @@
 .macro __EMIT_BUG_ENTRY addr,file,line,flags
 	 .section __bug_table,"aw"
 5001:	 .4byte \addr - .
+	 .4byte 0
 	 .4byte 5002f - .
 	 .short \line, \flags
 	 .org 5001b+BUG_ENTRY_SIZE
@@ -26,6 +27,7 @@
 .macro __EMIT_BUG_ENTRY addr,file,line,flags
 	 .section __bug_table,"aw"
 5001:	 .4byte \addr - .
+	 .4byte 0
 	 .short \flags
 	 .org 5001b+BUG_ENTRY_SIZE
 	 .previous
@@ -33,7 +35,6 @@
 #endif /* verbose */
 
 .macro EMIT_WARN_ENTRY addr,file,line,flags
-	EX_TABLE(\addr,\addr+4)
 	__EMIT_BUG_ENTRY \addr,\file,\line,\flags
 .endm
 
@@ -45,12 +46,17 @@
 .endm
 
 #else /* !__ASSEMBLY__ */
+struct arch_bug_entry {
+	signed int recovery_addr_disp;
+};
+
 /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
    sizeof(struct bug_entry), respectively */
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 #define _EMIT_BUG_ENTRY				\
 	".section __bug_table,\"aw\"\n"		\
 	"2:	.4byte 1b - .\n"		\
+	"	.4byte 0\n"			\
 	"	.4byte %0 - .\n"		\
 	"	.short %1, %2\n"		\
 	".org 2b+%3\n"				\
@@ -59,6 +65,26 @@
 #define _EMIT_BUG_ENTRY				\
 	".section __bug_table,\"aw\"\n"		\
 	"2:	.4byte 1b - .\n"		\
+	"	.4byte 0\n"			\
+	"	.short %2\n"			\
+	".org 2b+%3\n"				\
+	".previous\n"
+#endif
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define _EMIT_WARN_ENTRY(label)			\
+	".section __bug_table,\"aw\"\n"		\
+	"2:	.4byte 1b - .\n"		\
+	"	.4byte 1b - %l[" #label "]\n"	\
+	"	.4byte %0 - .\n"		\
+	"	.short %1, %2\n"		\
+	".org 2b+%3\n"				\
+	".previous\n"
+#else
+#define _EMIT_WARN_ENTRY(label)			\
+	".section __bug_table,\"aw\"\n"		\
+	"2:	.4byte 1b - .\n"		\
+	"	.4byte 1b - %l[" #label "]\n"	\
 	"	.short %2\n"			\
 	".org 2b+%3\n"				\
 	".previous\n"
@@ -76,8 +102,7 @@
 #define WARN_ENTRY(insn, flags, label, ...)		\
 	asm_volatile_goto(				\
 		"1:	" insn "\n"			\
-		EX_TABLE(1b, %l[label])			\
-		_EMIT_BUG_ENTRY				\
+		_EMIT_WARN_ENTRY(label)			\
 		: : "i" (__FILE__), "i" (__LINE__),	\
 		  "i" (flags),				\
 		  "i" (sizeof(struct bug_entry)),	\
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index dadfcef5d6db..1e521a432bd0 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1494,13 +1494,17 @@ static void do_program_check(struct pt_regs *regs)
 
 		if (!(regs->msr & MSR_PR) &&  /* not user-mode */
 		    report_bug(bugaddr, regs) == BUG_TRAP_TYPE_WARN) {
-			const struct exception_table_entry *entry;
+			const struct bug_entry *bug;
+			unsigned long recov;
 
-			entry = search_exception_tables(bugaddr);
-			if (entry) {
-				regs_set_return_ip(regs, extable_fixup(entry) + regs->nip - bugaddr);
-				return;
-			}
+			bug = find_bug(bugaddr);
+			if (!bug || bug->arch.recovery_addr_disp == 0)
+				recov = regs->nip + 4;
+			else
+				recov = bugaddr - bug->arch.recovery_addr_disp;
+
+			regs_set_return_ip(regs, recov);
+			return;
 		}
 		_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
 		return;
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index ba1f860af38b..1ce8431bdf02 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -36,6 +36,9 @@ struct bug_entry {
 #else
 	signed int	bug_addr_disp;
 #endif
+#ifdef CONFIG_GENERIC_BUG_ARCH_ENTRY
+	struct arch_bug_entry arch;
+#endif
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 #ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
 	const char	*file;
-- 
2.37.2



More information about the Linuxppc-dev mailing list