[PATCH 00/32] s390: Improve exception table handling and disassembler

From: Heiko Carstens

Date: Thu Oct 01 2026 - 06:34:41 EST


Extend the existing get_trap_ip() so that it returns the address of
the instruction which caused an exception, and use that for both the
disassembler as well as exception handling.

This allows improving two things:

- The in kernel disassembler prints PGM+PSW markers which clearly
identify the instruction causing an exception, and the current PSW
address. This replaces the previous "best guess" approach with '*' and
'>' markers

- EX_TABLE entries for inline assemblies are simplified. Only the address
of the faulting instruction needs to be provided from now on. The second
entry, which is the address following the faulting instruction, is not
needed anymore

Disassembler
------------

The output of the kernel disassembler changes. If the disassembly is
printed as a result of a program check, 'PGM' and 'PSW' markers identify
the instruction which caused the exception, and where the PSW points
to. For suppressing exceptions, the output now looks like this:

Krnl Code:
000003ff8dc7bff8: e310f0080004 lg %r1,8(%r15)
PGM >000003ff8dc7bffe: e3a0e0000004 lg %r10,0(%r14)
PSW >000003ff8dc7c004: a7280000 lhi %r2,0
000003ff8dc7c008: eb9ff0900024 stmg %r9,%r15,144(%r15)

For nullifying exceptions where both addresses are the same,
'PGM+PSW >' is printed instead:

Krnl Code:
000003ff8dc7bff8: e310f0080004 lg %r1,8(%r15)
PGM+PSW >000003ff8dc7bffe: e3a0e0000004 lg %r10,0(%r14)
000003ff8dc7c004: a7280000 lhi %r2,0
000003ff8dc7c008: eb9ff0900024 stmg %r9,%r15,144(%r15)

EX_TABLE entries
----------------

With get_trap_ip() now returning the exact faulting instruction address,
EX_TABLE entries for inline assemblies are simplified. Only the address
of the faulting instruction needs to be provided. The second entry - the
address following the faulting instruction - is no longer needed.

For example, an inline assembly using a single instruction can now be
written as:

asm_inline volatile(
"0: lg %[data],%[addr]\n"
"1:\n"
EX_TABLE_INSN(0b, 1b));

Previously this required:

asm_inline volatile(
" nopr %%r7\n"
"0: lg %[data],%[addr]\n"
"1: nopr %%r7\n"
EX_TABLE(0b, 1b)
EX_TABLE(1b, 1b));

The old approach had several non-obvious restrictions:

- If an instruction immediately preceding the inline assembly caused a
non-nullifying exception, the PSW would point to the start of the
inline assembly. If the faulting instruction was placed there, the
exception handler would incorrectly resolve the fault using the inline
assembly's fixup handler. Hence, a leading NOP was required before the
faulting instruction

- Similarly, an exception table entry placed behind a faulting
instruction must also point to an instruction that cannot fault. A
nullifying exception on the following instruction would otherwise be
incorrectly resolved by that entry

- Furthermore, instructions that can cause both nullifying and
non-nullifying exceptions required two separate exception table entries

These restrictions are error-prone and have caused several bugs in the
past.

All EX_TABLE* macros have been renamed to EX_TABLE_INSN*. This allows the
old and new semantics to be distinguished, and ensures that backports of
code using the new semantics will intentionally fail to compile if the
new infrastructure is not present.

Note
----

There are some existing oddities and corner cases with kprobes. Only
some of them will be addressed with this series. The other ones will
be addressed with follow-on changes, since this series is already
large enough.

Thanks,
Heiko

Heiko Carstens (32):
s390/kprobes: Prevent kprobes on instructions with exception table entry
s390/early: Fix early warning handling
s390: Clear pt_regs flags field
s390/bug: Indicate modified PSW in disassembly
s390/tools: Rename gen_facilities to gen_bitmaps
s390/tools: Generate bitmap of nullified program checks
s390/traps: Handle nullifying program checks in get_trap_ip()
s390/dis: Improve show_code() output
s390/extable: Rework exception handling logic
s390/diag: Convert amode31 exception tables to EX_TABLE_INSN
s390/uaccess: Convert inline assembly to EX_TABLE_INSN
s390/lib/uaccess: Convert inline assembly to EX_TABLE_INSN
s390/futex: Convert inline assembly to EX_TABLE_INSN
s390/diag: Convert inline assembly to EX_TABLE_INSN
s390/mm/pfault: Convert inline assembly to EX_TABLE_INSN
s390/cpu_mf: Convert inline assembly to EX_TABLE_INSN
s390/cert_store: Convert inline assembly to EX_TABLE_INSN
s390/ipl: Convert inline assembly to EX_TABLE_INSN
s390/hypfs: Convert inline assembly to EX_TABLE_INSN
s390/ap: Convert inline assembly to EX_TABLE_INSN
s390/fpu: Convert inline assembly to EX_TABLE_INSN
s390/traps: Convert inline assembly to EX_TABLE_INSN
s390/word-at-a-time: Convert inline assembly to EX_TABLE_INSN
s390/kvm: Convert inline assembly to EX_TABLE_INSN
s390/pci: Convert inline assembly to EX_TABLE_INSN
s390/boot: Convert inline assembly to EX_TABLE_INSN
s390/cio: Convert inline assembly to EX_TABLE_INSN
s390/dasd: Convert inline assembly to EX_TABLE_INSN
s390/diag_ftp: Convert inline assembly to EX_TABLE_INSN
s390/sclp: Convert inline assembly to EX_TABLE_INSN
s390/bpf: Simplify exception table entry handling
s390/extable: Remove EX_TABLE macros and fallback extable search

arch/s390/boot/ipl_parm.c | 6 +-
arch/s390/boot/pgm_check.c | 14 ++-
arch/s390/boot/physmem_info.c | 18 +--
arch/s390/boot/startup.c | 12 +-
arch/s390/hypfs/hypfs_vm.c | 6 +-
arch/s390/include/asm/Kbuild | 1 +
arch/s390/include/asm/ap.h | 12 +-
arch/s390/include/asm/asm-extable.h | 28 +++--
arch/s390/include/asm/cpu_mf.h | 18 +--
arch/s390/include/asm/diag.h | 5 +-
arch/s390/include/asm/diag288.h | 6 +-
arch/s390/include/asm/extable.h | 25 ++---
arch/s390/include/asm/fpu-insn.h | 6 +-
arch/s390/include/asm/futex.h | 17 ++-
arch/s390/include/asm/ptrace.h | 6 +
arch/s390/include/asm/uaccess.h | 45 +++-----
arch/s390/include/asm/word-at-a-time.h | 5 +-
arch/s390/kernel/cert_store.c | 6 +-
arch/s390/kernel/diag/diag.c | 12 +-
arch/s390/kernel/dis.c | 35 +++---
arch/s390/kernel/dumpstack.c | 7 +-
arch/s390/kernel/early.c | 26 ++++-
arch/s390/kernel/entry.S | 1 +
arch/s390/kernel/ipl.c | 6 +-
arch/s390/kernel/kprobes.c | 3 +
arch/s390/kernel/text_amode31.S | 34 +++---
arch/s390/kernel/traps.c | 30 +++--
arch/s390/kvm/s390/gaccess.c | 11 +-
arch/s390/lib/uaccess.c | 29 ++---
arch/s390/mm/extable.c | 2 +-
arch/s390/mm/pfault.c | 12 +-
arch/s390/net/bpf_jit_comp.c | 78 ++++---------
arch/s390/pci/pci_clp.c | 12 +-
arch/s390/pci/pci_insn.c | 36 +++---
arch/s390/pci/pci_mmio.c | 28 ++---
arch/s390/tools/.gitignore | 1 +
arch/s390/tools/Makefile | 16 ++-
.../tools/{gen_facilities.c => gen_bitmaps.c} | 103 ++++++++++++++----
drivers/s390/block/dasd_diag.c | 6 +-
drivers/s390/char/diag_ftp.c | 6 +-
drivers/s390/char/sclp.h | 7 +-
drivers/s390/cio/ioasm.c | 24 ++--
42 files changed, 409 insertions(+), 352 deletions(-)
rename arch/s390/tools/{gen_facilities.c => gen_bitmaps.c} (65%)

--
2.53.0