]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
s390/boot: Introduce jump_to_kernel() function
authorIlya Leoshkevich <iii@linux.ibm.com>
Wed, 25 Jun 2025 15:36:51 +0000 (17:36 +0200)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Thu, 10 Jul 2025 12:42:10 +0000 (14:42 +0200)
Introduce a global function that jumps from the decompressor to the
decompressed kernel. Put its address into svc_old_psw, from where GDB
can take it without loading decompressor symbols. It should be
available throughout the entire decompressor execution, because it's
placed there statically, and nothing in the decompressor uses the SVC
instruction.

Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Tested-by: Alexander Gordeev <agordeev@linux.ibm.com>
Link: https://lore.kernel.org/r/20250625154220.75300-2-iii@linux.ibm.com
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/boot/Makefile
arch/s390/boot/boot.h
arch/s390/boot/ipl_data.c
arch/s390/boot/startup.c
arch/s390/boot/trampoline.S [new file with mode: 0644]

index 0986c7c67eaf243d36db2947d5aea86163fd982b..02f2cf08274876ebcb4cf99edd579413506a0b75 100644 (file)
@@ -27,7 +27,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
 obj-y  := head.o als.o startup.o physmem_info.o ipl_parm.o ipl_report.o vmem.o
 obj-y  += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
 obj-y  += version.o pgm_check.o ctype.o ipl_data.o relocs.o alternative.o
-obj-y  += uv.o printk.o
+obj-y  += uv.o printk.o trampoline.o
 obj-$(CONFIG_RANDOMIZE_BASE)   += kaslr.o
 obj-y  += $(if $(CONFIG_KERNEL_UNCOMPRESSED),,decompressor.o) info.o
 obj-$(CONFIG_KERNEL_ZSTD) += clz_ctz.o
index 759aaf5b4fd202f8c72efb015cdd9097a556a0e8..c0152db285f0b9d785eb1cf90a94d539d3803c61 100644 (file)
@@ -74,6 +74,7 @@ void print_stacktrace(unsigned long sp);
 void error(char *m);
 int get_random(unsigned long limit, unsigned long *value);
 void boot_rb_dump(void);
+void __noreturn jump_to_kernel(psw_t *psw);
 
 #ifndef boot_fmt
 #define boot_fmt(fmt)  fmt
index 0846e2b249c62e19ee6a9d5e1852c0b6b45893e5..c4130a80b058e237a5375420fc4f7820d0686af2 100644 (file)
@@ -16,7 +16,9 @@ struct ipl_lowcore {
        struct ccw0     ccwpgm[2];                      /* 0x0008 */
        u8              fill[56];                       /* 0x0018 */
        struct ccw0     ccwpgmcc[20];                   /* 0x0050 */
-       u8              pad_0xf0[0x01a0-0x00f0];        /* 0x00f0 */
+       u8              pad_0xf0[0x0140-0x00f0];        /* 0x00f0 */
+       psw_t           svc_old_psw;                    /* 0x0140 */
+       u8              pad_0x150[0x01a0-0x0150];       /* 0x0150 */
        psw_t           restart_psw;                    /* 0x01a0 */
        psw_t           external_new_psw;               /* 0x01b0 */
        psw_t           svc_new_psw;                    /* 0x01c0 */
@@ -75,6 +77,11 @@ static struct ipl_lowcore ipl_lowcore __used __section(".ipldata") = {
                [18] = CCW0(CCW_CMD_READ_IPL, 0x690, 0x50, CCW_FLAG_SLI | CCW_FLAG_CC),
                [19] = CCW0(CCW_CMD_READ_IPL, 0x6e0, 0x50, CCW_FLAG_SLI),
        },
+       /*
+        * Let the GDB's lx-symbols command find the jump_to_kernel symbol
+        * without having to load decompressor symbols.
+        */
+       .svc_old_psw      = { .mask = 0, .addr = (unsigned long)jump_to_kernel },
        .restart_psw      = { .mask = 0, .addr = IPL_START, },
        .external_new_psw = { .mask = PSW_MASK_DISABLED, .addr = __LC_EXT_NEW_PSW, },
        .svc_new_psw      = { .mask = PSW_MASK_DISABLED, .addr = __LC_SVC_NEW_PSW, },
index da8337e63a3e234108ac00e4eea639d28ba3f4fd..305e6c7910710b6c442c9f914293ea34b17b4d94 100644 (file)
@@ -642,5 +642,5 @@ void startup_kernel(void)
        psw.addr = __kaslr_offset + vmlinux.entry;
        psw.mask = PSW_KERNEL_BITS;
        boot_debug("Starting kernel at:  0x%016lx\n", psw.addr);
-       __load_psw(psw);
+       jump_to_kernel(&psw);
 }
diff --git a/arch/s390/boot/trampoline.S b/arch/s390/boot/trampoline.S
new file mode 100644 (file)
index 0000000..1cb5adf
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/linkage.h>
+
+# This function is identical to __load_psw(), but the lx-symbols GDB command
+# puts a breakpoint on it, so it needs to be kept separate.
+SYM_CODE_START(jump_to_kernel)
+       lpswe 0(%r2)
+SYM_CODE_END(jump_to_kernel)