* [PATCH 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
@ 2025-06-25 15:36 Ilya Leoshkevich
2025-06-25 15:36 ` [PATCH 1/2] s390/boot: Introduce jump_to_kernel() function Ilya Leoshkevich
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Ilya Leoshkevich @ 2025-06-25 15:36 UTC (permalink / raw)
To: Jan Kiszka, Kieran Bingham
Cc: linux-kernel, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Ilya Leoshkevich
Hi,
In order to debug the early s390 kernel boot, one has to skip the
decompressor code, which requires some private scripts or memorized
commands. This series makes it work out of the box with the lx-symbols
command.
Patch 1 adds helper infrastructure to the s390 decompressor code; it is
already acked by Heiko.
Patch 2 is the implementation; it would be great to have an Ack from
one of the GDB scripts maintainers.
We would like to get this series via the s390 tree, if possible.
Best regards,
Ilya
Ilya Leoshkevich (2):
s390/boot: Introduce jump_to_kernel() function
scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
arch/s390/boot/Makefile | 2 +-
arch/s390/boot/boot.h | 1 +
arch/s390/boot/ipl_data.c | 9 ++++++++-
arch/s390/boot/startup.c | 2 +-
arch/s390/boot/trampoline.S | 9 +++++++++
scripts/gdb/linux/symbols.py | 26 ++++++++++++++++++++++++++
6 files changed, 46 insertions(+), 3 deletions(-)
create mode 100644 arch/s390/boot/trampoline.S
--
2.49.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] s390/boot: Introduce jump_to_kernel() function
2025-06-25 15:36 [PATCH 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
@ 2025-06-25 15:36 ` Ilya Leoshkevich
2025-06-25 15:36 ` [PATCH 2/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Ilya Leoshkevich @ 2025-06-25 15:36 UTC (permalink / raw)
To: Jan Kiszka, Kieran Bingham
Cc: linux-kernel, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Ilya Leoshkevich
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>
---
arch/s390/boot/Makefile | 2 +-
arch/s390/boot/boot.h | 1 +
arch/s390/boot/ipl_data.c | 9 ++++++++-
arch/s390/boot/startup.c | 2 +-
arch/s390/boot/trampoline.S | 9 +++++++++
5 files changed, 20 insertions(+), 3 deletions(-)
create mode 100644 arch/s390/boot/trampoline.S
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile
index bee49626be4b..30ceaa42224f 100644
--- a/arch/s390/boot/Makefile
+++ b/arch/s390/boot/Makefile
@@ -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
diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h
index e045cae6e80a..7c1b9a21018a 100644
--- a/arch/s390/boot/boot.h
+++ b/arch/s390/boot/boot.h
@@ -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
diff --git a/arch/s390/boot/ipl_data.c b/arch/s390/boot/ipl_data.c
index 0846e2b249c6..c4130a80b058 100644
--- a/arch/s390/boot/ipl_data.c
+++ b/arch/s390/boot/ipl_data.c
@@ -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, },
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index da8337e63a3e..305e6c791071 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -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
index 000000000000..1cb5adf005ea
--- /dev/null
+++ b/arch/s390/boot/trampoline.S
@@ -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)
--
2.49.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
2025-06-25 15:36 [PATCH 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
2025-06-25 15:36 ` [PATCH 1/2] s390/boot: Introduce jump_to_kernel() function Ilya Leoshkevich
@ 2025-06-25 15:36 ` Ilya Leoshkevich
2025-07-09 11:40 ` Jan Kiszka
2025-06-30 15:32 ` [PATCH 0/2] " Alexander Gordeev
` (2 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Ilya Leoshkevich @ 2025-06-25 15:36 UTC (permalink / raw)
To: Jan Kiszka, Kieran Bingham
Cc: linux-kernel, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Ilya Leoshkevich
When one starts QEMU with the -S flag and attaches GDB, the kernel is
not yet loaded, and the current instruction is an entry point to the
decompressor. In case the intention is to debug the early kernel boot,
and not the decompressor, e.g., put a breakpoint on some kernel
function and see all the invocations, one has to skip the decompressor.
There are many ways to do this, and so far people wrote private scripts
or memorized certain command sequences.
Make it work out of the box like this:
$ gdb -ex 'target remote :6812' -ex 'source vmlinux-gdb.py' vmlinux
Remote debugging using :6812
0x0000000000010000 in ?? ()
(gdb) lx-symbols
loading vmlinux
(gdb) x/i $pc
=> 0x3ffe0100000 <startup_continue>: lghi %r2,0
Implement this by reading the address of the jump_to_kernel() function
from the lowcore, and step until DAT is turned on.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
scripts/gdb/linux/symbols.py | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index 2332bd8eddf1..6edb99221675 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -84,6 +84,30 @@ def get_kerneloffset():
return None
+def is_in_s390_decompressor():
+ # DAT is always off in decompressor. Use this as an indicator.
+ # Note that in the kernel, DAT can be off during kexec() or restart.
+ # Accept this imprecision in order to avoid complicating things.
+ # It is unlikely that someone will run lx-symbols at these points.
+ pswm = int(gdb.parse_and_eval("$pswm"))
+ return (pswm & 0x0400000000000000) == 0
+
+
+def skip_decompressor():
+ if utils.is_target_arch("s390"):
+ if is_in_s390_decompressor():
+ # The address of the jump_to_kernel function is statically placed
+ # into svc_old_psw.addr (see ipl_data.c); read it from there. DAT
+ # is off, so we do not need to care about lowcore relocation.
+ svc_old_pswa = 0x148
+ jump_to_kernel = int(gdb.parse_and_eval("*(unsigned long long *)" +
+ hex(svc_old_pswa)))
+ gdb.execute("tbreak *" + hex(jump_to_kernel))
+ gdb.execute("continue")
+ while is_in_s390_decompressor():
+ gdb.execute("stepi")
+
+
class LxSymbols(gdb.Command):
"""(Re-)load symbols of Linux kernel and currently loaded modules.
@@ -204,6 +228,8 @@ lx-symbols command."""
saved_state['breakpoint'].enabled = saved_state['enabled']
def invoke(self, arg, from_tty):
+ skip_decompressor()
+
self.module_paths = [os.path.abspath(os.path.expanduser(p))
for p in arg.split()]
self.module_paths.append(os.getcwd())
--
2.49.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
2025-06-25 15:36 [PATCH 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
2025-06-25 15:36 ` [PATCH 1/2] s390/boot: Introduce jump_to_kernel() function Ilya Leoshkevich
2025-06-25 15:36 ` [PATCH 2/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
@ 2025-06-30 15:32 ` Alexander Gordeev
2025-07-09 9:27 ` [PATCH PING " Ilya Leoshkevich
2025-07-10 5:46 ` [PATCH " Alexander Gordeev
4 siblings, 0 replies; 9+ messages in thread
From: Alexander Gordeev @ 2025-06-30 15:32 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: Jan Kiszka, Kieran Bingham, linux-kernel, Heiko Carstens,
Vasily Gorbik
On Wed, Jun 25, 2025 at 05:36:50PM +0200, Ilya Leoshkevich wrote:
> Hi,
>
> In order to debug the early s390 kernel boot, one has to skip the
> decompressor code, which requires some private scripts or memorized
> commands. This series makes it work out of the box with the lx-symbols
> command.
>
> Patch 1 adds helper infrastructure to the s390 decompressor code; it is
> already acked by Heiko.
>
> Patch 2 is the implementation; it would be great to have an Ack from
> one of the GDB scripts maintainers.
>
> We would like to get this series via the s390 tree, if possible.
>
> Best regards,
> Ilya
>
> Ilya Leoshkevich (2):
> s390/boot: Introduce jump_to_kernel() function
> scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
>
> arch/s390/boot/Makefile | 2 +-
> arch/s390/boot/boot.h | 1 +
> arch/s390/boot/ipl_data.c | 9 ++++++++-
> arch/s390/boot/startup.c | 2 +-
> arch/s390/boot/trampoline.S | 9 +++++++++
> scripts/gdb/linux/symbols.py | 26 ++++++++++++++++++++++++++
> 6 files changed, 46 insertions(+), 3 deletions(-)
> create mode 100644 arch/s390/boot/trampoline.S
Tested-by: Alexander Gordeev <agordeev@linux.ibm.com>
Thanks!
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH PING 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
2025-06-25 15:36 [PATCH 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
` (2 preceding siblings ...)
2025-06-30 15:32 ` [PATCH 0/2] " Alexander Gordeev
@ 2025-07-09 9:27 ` Ilya Leoshkevich
2025-07-10 5:46 ` [PATCH " Alexander Gordeev
4 siblings, 0 replies; 9+ messages in thread
From: Ilya Leoshkevich @ 2025-07-09 9:27 UTC (permalink / raw)
To: Jan Kiszka, Kieran Bingham
Cc: linux-kernel, Heiko Carstens, Vasily Gorbik, Alexander Gordeev
On Wed, 2025-06-25 at 17:36 +0200, Ilya Leoshkevich wrote:
> Hi,
>
> In order to debug the early s390 kernel boot, one has to skip the
> decompressor code, which requires some private scripts or memorized
> commands. This series makes it work out of the box with the lx-
> symbols
> command.
>
> Patch 1 adds helper infrastructure to the s390 decompressor code; it
> is
> already acked by Heiko.
>
> Patch 2 is the implementation; it would be great to have an Ack from
> one of the GDB scripts maintainers.
>
> We would like to get this series via the s390 tree, if possible.
>
> Best regards,
> Ilya
>
> Ilya Leoshkevich (2):
> s390/boot: Introduce jump_to_kernel() function
> scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
>
> arch/s390/boot/Makefile | 2 +-
> arch/s390/boot/boot.h | 1 +
> arch/s390/boot/ipl_data.c | 9 ++++++++-
> arch/s390/boot/startup.c | 2 +-
> arch/s390/boot/trampoline.S | 9 +++++++++
> scripts/gdb/linux/symbols.py | 26 ++++++++++++++++++++++++++
> 6 files changed, 46 insertions(+), 3 deletions(-)
> create mode 100644 arch/s390/boot/trampoline.S
Gentle ping. Any feedback would be greatly appreciated.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
2025-06-25 15:36 ` [PATCH 2/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
@ 2025-07-09 11:40 ` Jan Kiszka
2025-07-09 14:37 ` Ilya Leoshkevich
0 siblings, 1 reply; 9+ messages in thread
From: Jan Kiszka @ 2025-07-09 11:40 UTC (permalink / raw)
To: Ilya Leoshkevich, Kieran Bingham, Andrew Morton
Cc: linux-kernel, Heiko Carstens, Vasily Gorbik, Alexander Gordeev
On 25.06.25 17:36, Ilya Leoshkevich wrote:
> When one starts QEMU with the -S flag and attaches GDB, the kernel is
> not yet loaded, and the current instruction is an entry point to the
> decompressor. In case the intention is to debug the early kernel boot,
> and not the decompressor, e.g., put a breakpoint on some kernel
> function and see all the invocations, one has to skip the decompressor.
>
> There are many ways to do this, and so far people wrote private scripts
> or memorized certain command sequences.
>
> Make it work out of the box like this:
>
> $ gdb -ex 'target remote :6812' -ex 'source vmlinux-gdb.py' vmlinux
> Remote debugging using :6812
> 0x0000000000010000 in ?? ()
> (gdb) lx-symbols
> loading vmlinux
> (gdb) x/i $pc
> => 0x3ffe0100000 <startup_continue>: lghi %r2,0
>
> Implement this by reading the address of the jump_to_kernel() function
> from the lowcore, and step until DAT is turned on.
Why do you need to stepi until there? SW breakpoint will likely need to
output of the decompressor first. No HW breakpoint available? Or missing
<end-of-decompressor> address?
>
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
> scripts/gdb/linux/symbols.py | 26 ++++++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
>
> diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
> index 2332bd8eddf1..6edb99221675 100644
> --- a/scripts/gdb/linux/symbols.py
> +++ b/scripts/gdb/linux/symbols.py
> @@ -84,6 +84,30 @@ def get_kerneloffset():
> return None
>
>
> +def is_in_s390_decompressor():
> + # DAT is always off in decompressor. Use this as an indicator.
> + # Note that in the kernel, DAT can be off during kexec() or restart.
> + # Accept this imprecision in order to avoid complicating things.
> + # It is unlikely that someone will run lx-symbols at these points.
> + pswm = int(gdb.parse_and_eval("$pswm"))
> + return (pswm & 0x0400000000000000) == 0
> +
> +
> +def skip_decompressor():
> + if utils.is_target_arch("s390"):
> + if is_in_s390_decompressor():
> + # The address of the jump_to_kernel function is statically placed
> + # into svc_old_psw.addr (see ipl_data.c); read it from there. DAT
> + # is off, so we do not need to care about lowcore relocation.
> + svc_old_pswa = 0x148
> + jump_to_kernel = int(gdb.parse_and_eval("*(unsigned long long *)" +
> + hex(svc_old_pswa)))
> + gdb.execute("tbreak *" + hex(jump_to_kernel))
> + gdb.execute("continue")
> + while is_in_s390_decompressor():
> + gdb.execute("stepi")
> +
> +
> class LxSymbols(gdb.Command):
> """(Re-)load symbols of Linux kernel and currently loaded modules.
>
> @@ -204,6 +228,8 @@ lx-symbols command."""
> saved_state['breakpoint'].enabled = saved_state['enabled']
>
> def invoke(self, arg, from_tty):
> + skip_decompressor()
> +
> self.module_paths = [os.path.abspath(os.path.expanduser(p))
> for p in arg.split()]
> self.module_paths.append(os.getcwd())
Otherwise, this series looks good to me and could be picked up if there
is no better way to reach the end of the decompressor.
Jan
--
Siemens AG, Foundational Technologies
Linux Expert Center
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
2025-07-09 11:40 ` Jan Kiszka
@ 2025-07-09 14:37 ` Ilya Leoshkevich
2025-07-09 15:45 ` Jan Kiszka
0 siblings, 1 reply; 9+ messages in thread
From: Ilya Leoshkevich @ 2025-07-09 14:37 UTC (permalink / raw)
To: Jan Kiszka, Kieran Bingham, Andrew Morton
Cc: linux-kernel, Heiko Carstens, Vasily Gorbik, Alexander Gordeev
On Wed, 2025-07-09 at 13:40 +0200, Jan Kiszka wrote:
> On 25.06.25 17:36, Ilya Leoshkevich wrote:
> > When one starts QEMU with the -S flag and attaches GDB, the kernel
> > is
> > not yet loaded, and the current instruction is an entry point to
> > the
> > decompressor. In case the intention is to debug the early kernel
> > boot,
> > and not the decompressor, e.g., put a breakpoint on some kernel
> > function and see all the invocations, one has to skip the
> > decompressor.
> >
> > There are many ways to do this, and so far people wrote private
> > scripts
> > or memorized certain command sequences.
> >
> > Make it work out of the box like this:
> >
> > $ gdb -ex 'target remote :6812' -ex 'source vmlinux-gdb.py'
> > vmlinux
> > Remote debugging using :6812
> > 0x0000000000010000 in ?? ()
> > (gdb) lx-symbols
> > loading vmlinux
> > (gdb) x/i $pc
> > => 0x3ffe0100000 <startup_continue>: lghi %r2,0
> >
> > Implement this by reading the address of the jump_to_kernel()
> > function
> > from the lowcore, and step until DAT is turned on.
>
> Why do you need to stepi until there? SW breakpoint will likely need
> to
> output of the decompressor first. No HW breakpoint available? Or
> missing
> <end-of-decompressor> address?
jump_to_kernel is <end-of-decompressor>; the code from this patch puts
an SW breakpoint there, and this works fine.
However, the problem is that once jump_to_kernel is reached, even
though the kernel is already in place, paging is still off.
jump_to_kernel contains a single "lpswe" instruction, which both jumps
to kernel and enables paging, therefore, we must "stepi" over it. The
loop is there just for future-proofing. Everything happens very
quickly, there are no thousands of "stepi"s.
> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> > ---
> > scripts/gdb/linux/symbols.py | 26 ++++++++++++++++++++++++++
> > 1 file changed, 26 insertions(+)
> >
> > diff --git a/scripts/gdb/linux/symbols.py
> > b/scripts/gdb/linux/symbols.py
> > index 2332bd8eddf1..6edb99221675 100644
> > --- a/scripts/gdb/linux/symbols.py
> > +++ b/scripts/gdb/linux/symbols.py
> > @@ -84,6 +84,30 @@ def get_kerneloffset():
> > return None
> >
> >
> > +def is_in_s390_decompressor():
> > + # DAT is always off in decompressor. Use this as an indicator.
> > + # Note that in the kernel, DAT can be off during kexec() or
> > restart.
> > + # Accept this imprecision in order to avoid complicating
> > things.
> > + # It is unlikely that someone will run lx-symbols at these
> > points.
> > + pswm = int(gdb.parse_and_eval("$pswm"))
> > + return (pswm & 0x0400000000000000) == 0
> > +
> > +
> > +def skip_decompressor():
> > + if utils.is_target_arch("s390"):
> > + if is_in_s390_decompressor():
> > + # The address of the jump_to_kernel function is
> > statically placed
> > + # into svc_old_psw.addr (see ipl_data.c); read it from
> > there. DAT
> > + # is off, so we do not need to care about lowcore
> > relocation.
> > + svc_old_pswa = 0x148
> > + jump_to_kernel = int(gdb.parse_and_eval("*(unsigned
> > long long *)" +
> > +
> > hex(svc_old_pswa)))
> > + gdb.execute("tbreak *" + hex(jump_to_kernel))
> > + gdb.execute("continue")
> > + while is_in_s390_decompressor():
> > + gdb.execute("stepi")
> > +
> > +
> > class LxSymbols(gdb.Command):
> > """(Re-)load symbols of Linux kernel and currently loaded
> > modules.
> >
> > @@ -204,6 +228,8 @@ lx-symbols command."""
> > saved_state['breakpoint'].enabled =
> > saved_state['enabled']
> >
> > def invoke(self, arg, from_tty):
> > + skip_decompressor()
> > +
> > self.module_paths =
> > [os.path.abspath(os.path.expanduser(p))
> > for p in arg.split()]
> > self.module_paths.append(os.getcwd())
>
> Otherwise, this series looks good to me and could be picked up if
> there
> is no better way to reach the end of the decompressor.
Could you please ack this patch if the explanation above is
satisfactory? We would like to take this series via the s390 tree,
if possible.
> Jan
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
2025-07-09 14:37 ` Ilya Leoshkevich
@ 2025-07-09 15:45 ` Jan Kiszka
0 siblings, 0 replies; 9+ messages in thread
From: Jan Kiszka @ 2025-07-09 15:45 UTC (permalink / raw)
To: Ilya Leoshkevich, Kieran Bingham, Andrew Morton
Cc: linux-kernel, Heiko Carstens, Vasily Gorbik, Alexander Gordeev
On 09.07.25 16:37, Ilya Leoshkevich wrote:
> On Wed, 2025-07-09 at 13:40 +0200, Jan Kiszka wrote:
>> On 25.06.25 17:36, Ilya Leoshkevich wrote:
>>> When one starts QEMU with the -S flag and attaches GDB, the kernel
>>> is
>>> not yet loaded, and the current instruction is an entry point to
>>> the
>>> decompressor. In case the intention is to debug the early kernel
>>> boot,
>>> and not the decompressor, e.g., put a breakpoint on some kernel
>>> function and see all the invocations, one has to skip the
>>> decompressor.
>>>
>>> There are many ways to do this, and so far people wrote private
>>> scripts
>>> or memorized certain command sequences.
>>>
>>> Make it work out of the box like this:
>>>
>>> $ gdb -ex 'target remote :6812' -ex 'source vmlinux-gdb.py'
>>> vmlinux
>>> Remote debugging using :6812
>>> 0x0000000000010000 in ?? ()
>>> (gdb) lx-symbols
>>> loading vmlinux
>>> (gdb) x/i $pc
>>> => 0x3ffe0100000 <startup_continue>: lghi %r2,0
>>>
>>> Implement this by reading the address of the jump_to_kernel()
>>> function
>>> from the lowcore, and step until DAT is turned on.
>>
>> Why do you need to stepi until there? SW breakpoint will likely need
>> to
>> output of the decompressor first. No HW breakpoint available? Or
>> missing
>> <end-of-decompressor> address?
>
> jump_to_kernel is <end-of-decompressor>; the code from this patch puts
> an SW breakpoint there, and this works fine.
>
> However, the problem is that once jump_to_kernel is reached, even
> though the kernel is already in place, paging is still off.
>
> jump_to_kernel contains a single "lpswe" instruction, which both jumps
> to kernel and enables paging, therefore, we must "stepi" over it. The
> loop is there just for future-proofing. Everything happens very
> quickly, there are no thousands of "stepi"s.
>
OK, makes sense to me now.
>>> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
>>> ---
>>> scripts/gdb/linux/symbols.py | 26 ++++++++++++++++++++++++++
>>> 1 file changed, 26 insertions(+)
>>>
>>> diff --git a/scripts/gdb/linux/symbols.py
>>> b/scripts/gdb/linux/symbols.py
>>> index 2332bd8eddf1..6edb99221675 100644
>>> --- a/scripts/gdb/linux/symbols.py
>>> +++ b/scripts/gdb/linux/symbols.py
>>> @@ -84,6 +84,30 @@ def get_kerneloffset():
>>> return None
>>>
>>>
>>> +def is_in_s390_decompressor():
>>> + # DAT is always off in decompressor. Use this as an indicator.
>>> + # Note that in the kernel, DAT can be off during kexec() or
>>> restart.
>>> + # Accept this imprecision in order to avoid complicating
>>> things.
>>> + # It is unlikely that someone will run lx-symbols at these
>>> points.
>>> + pswm = int(gdb.parse_and_eval("$pswm"))
>>> + return (pswm & 0x0400000000000000) == 0
>>> +
>>> +
>>> +def skip_decompressor():
>>> + if utils.is_target_arch("s390"):
>>> + if is_in_s390_decompressor():
>>> + # The address of the jump_to_kernel function is
>>> statically placed
>>> + # into svc_old_psw.addr (see ipl_data.c); read it from
>>> there. DAT
>>> + # is off, so we do not need to care about lowcore
>>> relocation.
>>> + svc_old_pswa = 0x148
>>> + jump_to_kernel = int(gdb.parse_and_eval("*(unsigned
>>> long long *)" +
>>> +
>>> hex(svc_old_pswa)))
>>> + gdb.execute("tbreak *" + hex(jump_to_kernel))
>>> + gdb.execute("continue")
>>> + while is_in_s390_decompressor():
>>> + gdb.execute("stepi")
>>> +
>>> +
>>> class LxSymbols(gdb.Command):
>>> """(Re-)load symbols of Linux kernel and currently loaded
>>> modules.
>>>
>>> @@ -204,6 +228,8 @@ lx-symbols command."""
>>> saved_state['breakpoint'].enabled =
>>> saved_state['enabled']
>>>
>>> def invoke(self, arg, from_tty):
>>> + skip_decompressor()
>>> +
>>> self.module_paths =
>>> [os.path.abspath(os.path.expanduser(p))
>>> for p in arg.split()]
>>> self.module_paths.append(os.getcwd())
>>
>> Otherwise, this series looks good to me and could be picked up if
>> there
>> is no better way to reach the end of the decompressor.
>
> Could you please ack this patch if the explanation above is
> satisfactory? We would like to take this series via the s390 tree,
> if possible.
>
Sorry, should have also read your cover letter:
Acked-by: Jan Kiszka <jan.kiszka@siemens.com>
Jan
--
Siemens AG, Foundational Technologies
Linux Expert Center
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
2025-06-25 15:36 [PATCH 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
` (3 preceding siblings ...)
2025-07-09 9:27 ` [PATCH PING " Ilya Leoshkevich
@ 2025-07-10 5:46 ` Alexander Gordeev
4 siblings, 0 replies; 9+ messages in thread
From: Alexander Gordeev @ 2025-07-10 5:46 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: Jan Kiszka, Kieran Bingham, linux-kernel, Heiko Carstens,
Vasily Gorbik
On Wed, Jun 25, 2025 at 05:36:50PM +0200, Ilya Leoshkevich wrote:
> Hi,
>
> In order to debug the early s390 kernel boot, one has to skip the
> decompressor code, which requires some private scripts or memorized
> commands. This series makes it work out of the box with the lx-symbols
> command.
>
> Patch 1 adds helper infrastructure to the s390 decompressor code; it is
> already acked by Heiko.
>
> Patch 2 is the implementation; it would be great to have an Ack from
> one of the GDB scripts maintainers.
>
> We would like to get this series via the s390 tree, if possible.
>
> Best regards,
> Ilya
>
> Ilya Leoshkevich (2):
> s390/boot: Introduce jump_to_kernel() function
> scripts/gdb/symbols: make lx-symbols skip the s390 decompressor
>
> arch/s390/boot/Makefile | 2 +-
> arch/s390/boot/boot.h | 1 +
> arch/s390/boot/ipl_data.c | 9 ++++++++-
> arch/s390/boot/startup.c | 2 +-
> arch/s390/boot/trampoline.S | 9 +++++++++
> scripts/gdb/linux/symbols.py | 26 ++++++++++++++++++++++++++
> 6 files changed, 46 insertions(+), 3 deletions(-)
> create mode 100644 arch/s390/boot/trampoline.S
Applied, thanks!
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-07-10 5:46 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-25 15:36 [PATCH 0/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
2025-06-25 15:36 ` [PATCH 1/2] s390/boot: Introduce jump_to_kernel() function Ilya Leoshkevich
2025-06-25 15:36 ` [PATCH 2/2] scripts/gdb/symbols: make lx-symbols skip the s390 decompressor Ilya Leoshkevich
2025-07-09 11:40 ` Jan Kiszka
2025-07-09 14:37 ` Ilya Leoshkevich
2025-07-09 15:45 ` Jan Kiszka
2025-06-30 15:32 ` [PATCH 0/2] " Alexander Gordeev
2025-07-09 9:27 ` [PATCH PING " Ilya Leoshkevich
2025-07-10 5:46 ` [PATCH " Alexander Gordeev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).