]> git.ipfire.org Git - thirdparty/linux.git/commit
x86_64/bug: Implement __WARN_printf()
authorPeter Zijlstra <peterz@infradead.org>
Mon, 2 Jun 2025 13:08:32 +0000 (15:08 +0200)
committerPeter Zijlstra <peterz@infradead.org>
Mon, 24 Nov 2025 19:23:05 +0000 (20:23 +0100)
commit5b472b6e5bd951b208fbbe373892891398eb5ad1
treee37d8fd7095a9661f09a6bbd35fed0df0d6c9370
parent4f1b701f24bea0900e349aa1c860db24ba0150aa
x86_64/bug: Implement __WARN_printf()

The basic idea is to have __WARN_printf() be a vararg function such
that the compiler can do the optimal calling convention for us. This
function body will be a #UD and then set up a va_list in the exception
from pt_regs.

But because the trap will be in a called function, the bug_entry must
be passed in. Have that be the first argument, with the format tucked
away inside the bug_entry.

The comments should clarify the real fun details.

The big downside is that all WARNs will now show:

 RIP: 0010:__WARN_trap:+0

One possible solution is to simply discard the top frame when
unwinding. A follow up patch takes care of this slightly differently
by abusing the x86 static_call implementation.

This changes (with the next patches):

WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET,
  "corrupted preempt_count: %s/%d/0x%x\n",

from:

cmpl    $2, %ecx #, _7
        jne     .L1472
...

  .L1472:
        cmpb    $0, __already_done.11(%rip)
        je      .L1513
...

  .L1513
movb    $1, __already_done.11(%rip)
movl    1424(%r14), %edx        # _15->pid, _15->pid
        leaq    1912(%r14), %rsi        #, _17
        movq    $.LC43, %rdi    #,
        call    __warn_printk   #
ud2
  .pushsection __bug_table,"aw"
        2:
        .long 1b - .    # bug_entry::bug_addr
        .long .LC1 - .  # bug_entry::file
        .word 5093      # bug_entry::line
        .word 2313      # bug_entry::flags
        .org 2b + 12
  .popsection
  .pushsection .discard.annotate_insn,"M", @progbits, 8
        .long 1b - .
        .long 8         # ANNOTYPE_REACHABLE
  .popsection

into:

cmpl    $2, %ecx        #, _7
        jne     .L1442  #,
...

  .L1442:
        lea (2f)(%rip), %rdi
  1:
  .pushsection __bug_table,"aw"
        2:
        .long 1b - .    # bug_entry::bug_addr
        .long .LC43 - . # bug_entry::format
        .long .LC1 - .  # bug_entry::file
        .word 5093      # bug_entry::line
        .word 2323      # bug_entry::flags
        .org 2b + 16
  .popsection
        movl    1424(%r14), %edx        # _19->pid, _19->pid
        leaq    1912(%r14), %rsi        #, _13
ud1 (%edx), %rdi

Notably, by pushing everything into the exception handler it can take
care of the ONCE thing.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20251110115758.213813530@infradead.org
arch/x86/entry/entry.S
arch/x86/include/asm/bug.h
arch/x86/kernel/traps.c