s390/decompressor: add stacktrace support
authorVasily Gorbik <gor@linux.ibm.com>
Tue, 10 Nov 2020 16:05:35 +0000 (17:05 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Fri, 20 Nov 2020 18:19:11 +0000 (19:19 +0100)
Decompressor works on a single statically allocated stack. Stacktrace
implementation with -mbackchain just takes few lines of code.

Linux version 5.10.0-rc3-22793-g0f84a355b776-dirty (gor@tuxmaker) #27 SMP PREEMPT Mon Nov 9 17:30:18 CET 2020
Kernel fault: interruption code 0005 ilc:2
PSW : 0000000180000000 0000000000012f92 (parse_boot_command_line+0x27a/0x46c)
      R:0 T:0 IO:0 EX:0 Key:0 M:0 W:0 P:0 AS:0 CC:0 PM:0 RI:0 EA:3
GPRS: 0000000000000000 00ffffffffffffff 0000000000000000 000000000001a62c
      000000000000bf60 0000000000000000 00000000000003c0 0000000000000000
      0000000000000080 000000000002322d 000000007f29ef20 0000000000efd018
      000000000311c000 0000000000010070 0000000000012f82 000000000000bea8
Call Trace:
(sp:000000000000bea8 [<000000000002016e>] 000000000002016e)
 sp:000000000000bf18 [<0000000000012408>] startup_kernel+0x88/0x2fc
 sp:000000000000bf60 [<00000000000100c4>] startup_normal+0xb0/0xb0

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/Makefile
arch/s390/boot/boot.h
arch/s390/boot/head.S
arch/s390/boot/pgm_check_info.c
arch/s390/include/asm/thread_info.h

index ba94b03c8b2f4e0871848f487a03aafdbcc37380..8db267d2a543ab7a66faf3cbf4a481ba17135a28 100644 (file)
@@ -25,7 +25,7 @@ KBUILD_AFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -D__ASSEMBLY__
 KBUILD_AFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),$(aflags_dwarf))
 KBUILD_CFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -O2
 KBUILD_CFLAGS_DECOMPRESSOR += -DDISABLE_BRANCH_PROFILING -D__NO_FORTIFY
-KBUILD_CFLAGS_DECOMPRESSOR += -fno-delete-null-pointer-checks -msoft-float
+KBUILD_CFLAGS_DECOMPRESSOR += -fno-delete-null-pointer-checks -msoft-float -mbackchain
 KBUILD_CFLAGS_DECOMPRESSOR += -fno-asynchronous-unwind-tables
 KBUILD_CFLAGS_DECOMPRESSOR += -ffreestanding
 KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-member)
index ca485bfa4e503bccb73e2ae6f80a53a431c5d173..8b50967f58048f2b80344e0902996ddf5adb4145 100644 (file)
@@ -4,6 +4,10 @@
 
 #include <linux/types.h>
 
+#define BOOT_STACK_OFFSET 0x8000
+
+#ifndef __ASSEMBLY__
+
 #include <linux/compiler.h>
 
 void startup_kernel(void);
@@ -25,4 +29,5 @@ extern int kaslr_enabled;
 
 unsigned long read_ipl_report(unsigned long safe_offset);
 
+#endif /* __ASSEMBLY__ */
 #endif /* BOOT_BOOT_H */
index cf70917f98e889da5e881c9bd5a95400f936ead9..dacb7813f98257a2811062d98afe14c197824f17 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/thread_info.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
+#include "boot.h"
 
 #define ARCH_OFFSET    4
 
@@ -325,7 +326,7 @@ SYM_CODE_START_LOCAL(startup_normal)
 SYM_CODE_END(startup_normal)
 
 .Lstack:
-       .long   0x8000 + (1<<(PAGE_SHIFT+BOOT_STACK_ORDER)) - STACK_FRAME_OVERHEAD
+       .long   BOOT_STACK_OFFSET + BOOT_STACK_SIZE - STACK_FRAME_OVERHEAD
        .align  8
 6:     .long   0x7fffffff,0xffffffff
 .Lext_new_psw:
index 8ba8136adb4d66d5521e8eba3446aa06af4625fb..d8bfc56739569f13a3608c13e9ae30b0610fd904 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
+#include <asm/stacktrace.h>
 #include <asm/lowcore.h>
 #include <asm/setup.h>
 #include <asm/sclp.h>
@@ -121,6 +122,27 @@ out:
        sclp_early_printk(buf);
 }
 
+static noinline void print_stacktrace(void)
+{
+       struct stack_info boot_stack = { STACK_TYPE_TASK, BOOT_STACK_OFFSET,
+                                        BOOT_STACK_OFFSET + BOOT_STACK_SIZE };
+       unsigned long sp = S390_lowcore.gpregs_save_area[15];
+       bool first = true;
+
+       decompressor_printk("Call Trace:\n");
+       while (!(sp & 0x7) && on_stack(&boot_stack, sp, sizeof(struct stack_frame))) {
+               struct stack_frame *sf = (struct stack_frame *)sp;
+
+               decompressor_printk(first ? "(sp:%016lx [<%016lx>] %pS)\n" :
+                                           " sp:%016lx [<%016lx>] %pS\n",
+                                   sp, sf->gprs[8], (void *)sf->gprs[8]);
+               if (sf->back_chain <= sp)
+                       break;
+               sp = sf->back_chain;
+               first = false;
+       }
+}
+
 void print_pgm_check_info(void)
 {
        unsigned long *gpregs = (unsigned long *)S390_lowcore.gpregs_save_area;
@@ -148,4 +170,5 @@ void print_pgm_check_info(void)
                            gpregs[8], gpregs[9], gpregs[10], gpregs[11]);
        decompressor_printk("      %016lx %016lx %016lx %016lx\n",
                            gpregs[12], gpregs[13], gpregs[14], gpregs[15]);
+       print_stacktrace();
 }
index 13a04fcf77625618221ee68cb77d8a4715b213ba..ce788f3e534d0409b862520dbd3212b5d9d4f117 100644 (file)
@@ -18,7 +18,7 @@
 #else
 #define THREAD_SIZE_ORDER 2
 #endif
-#define BOOT_STACK_ORDER  2
+#define BOOT_STACK_SIZE (PAGE_SIZE << 2)
 #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
 
 #ifndef __ASSEMBLY__