mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 04:04:43 +01:00
s390/bug: Implement __WARN_printf()
This is the s390 variant of commit 5b472b6e5b ("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.
Reviewed-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
parent
ee44f4e7eb
commit
04dabb4261
4 changed files with 105 additions and 7 deletions
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <asm/bug.h>
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm-generic/asm-prototypes.h>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <linux/const.h>
|
||||
|
||||
#define MONCODE_BUG _AC(0, U)
|
||||
#define MONCODE_BUG_ARG _AC(1, U)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
|
||||
|
|
@ -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 && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
|
|
|||
|
|
@ -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,16 @@ SYM_FUNC_START(__switch_to_asm)
|
|||
BR_EX %r14
|
||||
SYM_FUNC_END(__switch_to_asm)
|
||||
|
||||
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
|
||||
|
||||
SYM_FUNC_START(__WARN_trap)
|
||||
mc MONCODE_BUG_ARG(%r0),0
|
||||
BR_EX %r14
|
||||
SYM_FUNC_END(__WARN_trap)
|
||||
EXPORT_SYMBOL(__WARN_trap)
|
||||
|
||||
#endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
|
||||
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
/*
|
||||
* __sie64a calling convention:
|
||||
|
|
|
|||
|
|
@ -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,46 @@ static void space_switch_exception(struct pt_regs *regs)
|
|||
do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event");
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
|
||||
|
||||
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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue