public inbox for linux-s390@vger.kernel.org
 help / color / mirror / Atom feed
From: Heiko Carstens <hca@linux.ibm.com>
To: Alexander Gordeev <agordeev@linux.ibm.com>,
	Sven Schnelle <svens@linux.ibm.com>,
	Vasily Gorbik <gor@linux.ibm.com>,
	Christian Borntraeger <borntraeger@linux.ibm.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Arnd Bergmann <arnd@arndb.de>, Jens Remus <jremus@linux.ibm.com>,
	Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>,
	Juergen Christ <jchrist@linux.ibm.com>
Cc: linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org
Subject: [PATCH 6/9] s390/bug: Implement __WARN_printf()
Date: Tue,  9 Dec 2025 13:16:58 +0100	[thread overview]
Message-ID: <20251209121701.1856271-7-hca@linux.ibm.com> (raw)
In-Reply-To: <20251209121701.1856271-1-hca@linux.ibm.com>

This is the s390 variant of commit 5b472b6e5bd9 ("x86_64/bug: Implement
__WARN_printf()"). See the x86 commit for the general idea; there are only
implementation details which are different.

With the new exception based __WARN_printf() implementation the generated
code for a simple WARN() is simplified.

For example:

void foo(int a) { WARN(a, "bar"); }

Before this change the generated code looks like this:

0000000000000210 <foo>:
 210:   c0 04 00 00 00 00       jgnop   210 <foo>
 216:   ec 26 00 06 00 7c       cgijne  %r2,0,222 <foo+0x12>
 21c:   c0 f4 00 00 00 00       jg      21c <foo+0xc>
                        21e: R_390_PC32DBL      __s390_indirect_jump_r14+0x2
 222:   eb ef f0 88 00 24       stmg    %r14,%r15,136(%r15)
 228:   b9 04 00 ef             lgr     %r14,%r15
 22c:   e3 f0 ff e8 ff 71       lay     %r15,-24(%r15)
 232:   e3 e0 f0 98 00 24       stg     %r14,152(%r15)
 238:   c0 20 00 00 00 00       larl    %r2,238 <foo+0x28>
                        23a: R_390_PC32DBL      .LC48+0x2
 23e:   c0 e5 00 00 00 00       brasl   %r14,23e <foo+0x2e>
                        240: R_390_PLT32DBL     __warn_printk+0x2
 244:   af 00 00 00             mc      0,0
 248:   eb ef f0 a0 00 04       lmg     %r14,%r15,160(%r15)
 24e:   c0 f4 00 00 00 00       jg      24e <foo+0x3e>
                        250: R_390_PC32DBL      __s390_indirect_jump_r14+0x2

With this change the generated code looks like this:

0000000000000210 <foo>:
 210:   c0 04 00 00 00 00       jgnop   210 <foo>
 216:   ec 26 00 06 00 7c       cgijne  %r2,0,222 <foo+0x12>
 21c:   c0 f4 00 00 00 00       jg      21c <foo+0xc>
                        21e: R_390_PC32DBL      __s390_indirect_jump_r14+0x2
 222:   c0 20 00 00 00 00       larl    %r2,222 <foobar+0x12>
                        224: R_390_PC32DBL      __bug_table+0x2
 228:   c0 f4 00 00 00 00       jg      228 <foobar+0x18>
                        22a: R_390_PLT32DBL     __WARN_trap+0x2

Downside is that the call trace now starts at __WARN_trap():

------------[ cut here ]------------
bar
WARNING: arch/s390/kernel/setup.c:1017 at 0x0, CPU#0: swapper/0/0
...
Krnl PSW : 0704c00180000000 000003ffe0f6a3b4 (__WARN_trap+0x4/0x10)
...
Krnl Code: 000003ffe0f6a3ac: 0707                bcr     0,%r7
           000003ffe0f6a3ae: 0707                bcr     0,%r7
          *000003ffe0f6a3b0: af000001            mc      1,0
          >000003ffe0f6a3b4: 07fe                bcr     15,%r14
           000003ffe0f6a3b6: 47000700            bc      0,1792
           000003ffe0f6a3ba: 0707                bcr     0,%r7
           000003ffe0f6a3bc: 0707                bcr     0,%r7
           000003ffe0f6a3be: 0707                bcr     0,%r7
Call Trace:
 [<000003ffe0f6a3b4>] __WARN_trap+0x4/0x10
([<000003ffe185a54c>] start_kernel+0x53c/0x5d8)
 [<000003ffe010002e>] startup_continue+0x2e/0x40

Which isn't too helpful. This can be addressed by just skipping __WARN_trap(),
which will be addressed in a later patch.

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
---
 arch/s390/include/asm/bug.h | 62 +++++++++++++++++++++++++++++++++----
 arch/s390/kernel/entry.S    |  7 +++++
 arch/s390/kernel/traps.c    | 34 +++++++++++++++++++-
 3 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h
index 1e1dece0eee4..f3aca691bae2 100644
--- a/arch/s390/include/asm/bug.h
+++ b/arch/s390/include/asm/bug.h
@@ -6,6 +6,7 @@
 #include <linux/const.h>
 
 #define	MONCODE_BUG	_AC(0, U)
+#define	MONCODE_BUG_ARG _AC(1, U)
 
 #ifndef __ASSEMBLER__
 #ifdef CONFIG_BUG
@@ -25,16 +26,20 @@
 #define WARN_CONDITION_STR(cond_str) ""
 #endif
 
+#define __BUG_ENTRY(format, file, line, flags, size)			\
+		"	.section __bug_table,\"aw\"\n"			\
+		"1:	.long	0b - .	# bug_entry::bug_addr\n"	\
+		__BUG_ENTRY_VERBOSE(format, file, line)			\
+		"	.short	"flags"	# bug_entry::flags\n"		\
+		"	.org	1b+"size"\n"				\
+		"	.previous"
+
 #define __BUG_ASM(cond_str, flags)					\
 do {									\
 	asm_inline volatile("\n"					\
 		"0:	mc	%[monc](%%r0),0\n"			\
-		"	.section __bug_table,\"aw\"\n"			\
-		"1:	.long	0b - .	# bug_entry::bug_addr\n"	\
-		__BUG_ENTRY_VERBOSE("%[frmt]", "%[file]", "%[line]")	\
-		"	.short	%[flgs]	# bug_entry::flags\n"		\
-		"	.org	1b+%[size]\n"				\
-		"	.previous"					\
+		__BUG_ENTRY("%[frmt]", "%[file]", "%[line]",		\
+			    "%[flgs]", "%[size]")			\
 		:							\
 		: [monc] "i" (MONCODE_BUG),				\
 		  [frmt] "i" (WARN_CONDITION_STR(cond_str)),		\
@@ -55,8 +60,53 @@ do {									\
 	__BUG_ASM(cond_str, BUGFLAG_WARNING | (flags));			\
 } while (0)
 
+#define __WARN_bug_entry(flags, format)					\
+({									\
+	struct bug_entry *bug;						\
+									\
+	asm_inline volatile("\n"					\
+		"0:	larl	%[bug],1f\n"				\
+		__BUG_ENTRY("%[frmt]", "%[file]", "%[line]",		\
+			    "%[flgs]", "%[size]")			\
+		: [bug] "=d" (bug)					\
+		: [frmt] "i" (format),					\
+		  [file] "i" (__FILE__),				\
+		  [line] "i" (__LINE__),				\
+		  [flgs] "i" (flags),					\
+		  [size] "i" (sizeof(struct bug_entry)));		\
+	bug;								\
+})
+
+/*
+ * Variable Argument List (va_list) as defined in ELF Application
+ * Binary Interface s390x Supplement documentation.
+ */
+struct arch_va_list {
+	long __gpr;
+	long __fpr;
+	void *__overflow_arg_area;
+	void *__reg_save_area;
+};
+
+struct bug_entry;
+struct pt_regs;
+
+void *__warn_args(struct arch_va_list *args, struct pt_regs *regs);
+void __WARN_trap(struct bug_entry *bug, ...);
+
+#define __WARN_print_arg(flags, format, arg...)				\
+do {									\
+	int __flags = (flags) | BUGFLAG_WARNING | BUGFLAG_ARGS;		\
+									\
+	__WARN_trap(__WARN_bug_entry(__flags, format), ## arg);		\
+} while (0)
+
+#define __WARN_printf(taint, fmt, arg...) \
+	__WARN_print_arg(BUGFLAG_TAINT(taint), fmt, ## arg)
+
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_BUG_FORMAT
+#define HAVE_ARCH_BUG_FORMAT_ARGS
 
 #endif /* CONFIG_BUG */
 #endif /* __ASSEMBLER__ */
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index b7f1553d9ee5..23ff05746aa6 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -23,6 +23,7 @@
 #include <asm/unistd.h>
 #include <asm/page.h>
 #include <asm/sigp.h>
+#include <asm/bug.h>
 #include <asm/irq.h>
 #include <asm/fpu-insn.h>
 #include <asm/setup.h>
@@ -173,6 +174,12 @@ SYM_FUNC_START(__switch_to_asm)
 	BR_EX	%r14
 SYM_FUNC_END(__switch_to_asm)
 
+SYM_FUNC_START(__WARN_trap)
+	mc	MONCODE_BUG_ARG(%r0),0
+	BR_EX	%r14
+SYM_FUNC_END(__WARN_trap)
+EXPORT_SYMBOL(__WARN_trap)
+
 #if IS_ENABLED(CONFIG_KVM)
 /*
  * __sie64a calling convention:
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index b2d6d7cc3b17..8aca5858b403 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -23,6 +23,7 @@
 #include <linux/cpu.h>
 #include <linux/entry-common.h>
 #include <linux/kmsan.h>
+#include <linux/bug.h>
 #include <asm/asm-extable.h>
 #include <asm/irqflags.h>
 #include <asm/ptrace.h>
@@ -220,11 +221,42 @@ static void space_switch_exception(struct pt_regs *regs)
 	do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event");
 }
 
+void *__warn_args(struct arch_va_list *args, struct pt_regs *regs)
+{
+	struct stack_frame *stack_frame;
+
+	/*
+	 * Generate va_list from pt_regs. See ELF Application Binary Interface
+	 * s390x Supplement documentation for details.
+	 *
+	 * - __overflow_arg_area needs to point to the parameter area, which
+	 *   is right above the standard stack frame (160 bytes)
+	 *
+	 * - __reg_save_area needs to point to a register save area where
+	 *   general registers (%r2 - %r6) can be found at offset 16. Which
+	 *   means that the gprs save area of pt_regs can be used
+	 *
+	 * - __gpr must be set to one, since the first parameter has been
+	 *   processed (pointer to bug_entry)
+	 */
+	stack_frame = (struct stack_frame *)regs->gprs[15];
+	args->__overflow_arg_area = stack_frame + 1;
+	args->__reg_save_area = regs->gprs;
+	args->__gpr = 1;
+	return args;
+}
+
 static void monitor_event_exception(struct pt_regs *regs)
 {
+	enum bug_trap_type btt;
+
 	if (user_mode(regs))
 		return;
-	switch (report_bug(regs->psw.addr - (regs->int_code >> 16), regs)) {
+	if (regs->monitor_code == MONCODE_BUG_ARG)
+		btt = report_bug_entry((struct bug_entry *)regs->gprs[2], regs);
+	else
+		btt = report_bug(regs->psw.addr - (regs->int_code >> 16), regs);
+	switch (btt) {
 	case BUG_TRAP_TYPE_NONE:
 		fixup_exception(regs);
 		break;
-- 
2.51.0


  parent reply	other threads:[~2025-12-09 12:17 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-09 12:16 [PATCH 0/9] s390: Exception based WARN() / WARN_ONCE() Heiko Carstens
2025-12-09 12:16 ` [PATCH 1/9] kbuild: Require gcc-9 for s390 Heiko Carstens
2025-12-09 12:16 ` [PATCH 2/9] s390/bug: Convert to inline assembly with input operands Heiko Carstens
2025-12-09 12:16 ` [PATCH 3/9] s390/bug: Use BUG_FORMAT for DEBUG_BUGVERBOSE_DETAILED Heiko Carstens
2025-12-09 12:16 ` [PATCH 4/9] s390/bug: Introduce and use monitor code macro Heiko Carstens
2025-12-09 12:16 ` [PATCH 5/9] s390/traps: Copy monitor code to pt_regs Heiko Carstens
2025-12-09 12:16 ` Heiko Carstens [this message]
2025-12-09 12:35   ` [PATCH 6/9] s390/bug: Implement __WARN_printf() Peter Zijlstra
2025-12-09 14:42     ` Heiko Carstens
2025-12-10 13:09   ` kernel test robot
2025-12-10 14:57   ` kernel test robot
2025-12-09 12:16 ` [PATCH 7/9] s390/bug: Implement WARN_ONCE() Heiko Carstens
2025-12-09 12:17 ` [PATCH 8/9] s390/bug: Skip __WARN_trap() in call traces Heiko Carstens
2025-12-09 12:17 ` [PATCH 9/9] s390/bug: Prevent tail-call optimization Heiko Carstens
2025-12-09 12:47   ` Peter Zijlstra
2025-12-09 12:56 ` [PATCH 0/9] s390: Exception based WARN() / WARN_ONCE() Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251209121701.1856271-7-hca@linux.ibm.com \
    --to=hca@linux.ibm.com \
    --cc=agordeev@linux.ibm.com \
    --cc=arnd@arndb.de \
    --cc=borntraeger@linux.ibm.com \
    --cc=gor@linux.ibm.com \
    --cc=jchrist@linux.ibm.com \
    --cc=jremus@linux.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=peterz@infradead.org \
    --cc=stefansf@linux.ibm.com \
    --cc=svens@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox