Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/boot: Introduce jump_to_kernel() function

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>

authored by

Ilya Leoshkevich and committed by
Alexander Gordeev
996f7f29 b367017c

+20 -3
+1 -1
arch/s390/boot/Makefile
··· 27 27 obj-y := head.o als.o startup.o physmem_info.o ipl_parm.o ipl_report.o vmem.o 28 28 obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o 29 29 obj-y += version.o pgm_check.o ctype.o ipl_data.o relocs.o alternative.o 30 - obj-y += uv.o printk.o 30 + obj-y += uv.o printk.o trampoline.o 31 31 obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o 32 32 obj-y += $(if $(CONFIG_KERNEL_UNCOMPRESSED),,decompressor.o) info.o 33 33 obj-$(CONFIG_KERNEL_ZSTD) += clz_ctz.o
+1
arch/s390/boot/boot.h
··· 74 74 void error(char *m); 75 75 int get_random(unsigned long limit, unsigned long *value); 76 76 void boot_rb_dump(void); 77 + void __noreturn jump_to_kernel(psw_t *psw); 77 78 78 79 #ifndef boot_fmt 79 80 #define boot_fmt(fmt) fmt
+8 -1
arch/s390/boot/ipl_data.c
··· 16 16 struct ccw0 ccwpgm[2]; /* 0x0008 */ 17 17 u8 fill[56]; /* 0x0018 */ 18 18 struct ccw0 ccwpgmcc[20]; /* 0x0050 */ 19 - u8 pad_0xf0[0x01a0-0x00f0]; /* 0x00f0 */ 19 + u8 pad_0xf0[0x0140-0x00f0]; /* 0x00f0 */ 20 + psw_t svc_old_psw; /* 0x0140 */ 21 + u8 pad_0x150[0x01a0-0x0150]; /* 0x0150 */ 20 22 psw_t restart_psw; /* 0x01a0 */ 21 23 psw_t external_new_psw; /* 0x01b0 */ 22 24 psw_t svc_new_psw; /* 0x01c0 */ ··· 77 75 [18] = CCW0(CCW_CMD_READ_IPL, 0x690, 0x50, CCW_FLAG_SLI | CCW_FLAG_CC), 78 76 [19] = CCW0(CCW_CMD_READ_IPL, 0x6e0, 0x50, CCW_FLAG_SLI), 79 77 }, 78 + /* 79 + * Let the GDB's lx-symbols command find the jump_to_kernel symbol 80 + * without having to load decompressor symbols. 81 + */ 82 + .svc_old_psw = { .mask = 0, .addr = (unsigned long)jump_to_kernel }, 80 83 .restart_psw = { .mask = 0, .addr = IPL_START, }, 81 84 .external_new_psw = { .mask = PSW_MASK_DISABLED, .addr = __LC_EXT_NEW_PSW, }, 82 85 .svc_new_psw = { .mask = PSW_MASK_DISABLED, .addr = __LC_SVC_NEW_PSW, },
+1 -1
arch/s390/boot/startup.c
··· 642 642 psw.addr = __kaslr_offset + vmlinux.entry; 643 643 psw.mask = PSW_KERNEL_BITS; 644 644 boot_debug("Starting kernel at: 0x%016lx\n", psw.addr); 645 - __load_psw(psw); 645 + jump_to_kernel(&psw); 646 646 }
+9
arch/s390/boot/trampoline.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #include <linux/linkage.h> 4 + 5 + # This function is identical to __load_psw(), but the lx-symbols GDB command 6 + # puts a breakpoint on it, so it needs to be kept separate. 7 + SYM_CODE_START(jump_to_kernel) 8 + lpswe 0(%r2) 9 + SYM_CODE_END(jump_to_kernel)