[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <a6e7aed9-ecf1-4715-a422-962a720f4cb7@siemens.com>
Date: Wed, 9 Jul 2025 17:45:28 +0200
From: Jan Kiszka <jan.kiszka@...mens.com>
To: Ilya Leoshkevich <iii@...ux.ibm.com>, Kieran Bingham
<kbingham@...nel.org>, Andrew Morton <akpm@...ux-foundation.org>
Cc: linux-kernel@...r.kernel.org, Heiko Carstens <hca@...ux.ibm.com>,
Vasily Gorbik <gor@...ux.ibm.com>, Alexander Gordeev <agordeev@...ux.ibm.com>
Subject: Re: [PATCH 2/2] scripts/gdb/symbols: make lx-symbols skip the s390
decompressor
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@...ux.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@...mens.com>
Jan
--
Siemens AG, Foundational Technologies
Linux Expert Center
Powered by blists - more mailing lists