• Jeremy Fitzhardinge's avatar
    [PATCH] Generic BUG implementation · 7664c5a1
    Jeremy Fitzhardinge authored
    This patch adds common handling for kernel BUGs, for use by architectures as
    they wish.  The code is derived from arch/powerpc.
    
    The advantages of having common BUG handling are:
     - consistent BUG reporting across architectures
     - shared implementation of out-of-line file/line data
     - implement CONFIG_DEBUG_BUGVERBOSE consistently
    
    This means that in inline impact of BUG is just the illegal instruction
    itself, which is an improvement for i386 and x86-64.
    
    A BUG is represented in the instruction stream as an illegal instruction,
    which has file/line information associated with it.  This extra information is
    stored in the __bug_table section in the ELF file.
    
    When the kernel gets an illegal instruction, it first confirms it might
    possibly be from a BUG (ie, in kernel mode, the right illegal instruction).
    It then calls report_bug().  This searches __bug_table for a matching
    instruction pointer, and if found, prints the corresponding file/line
    information.  If report_bug() determines that it wasn't a BUG which caused the
    trap, it returns BUG_TRAP_TYPE_NONE.
    
    Some architectures (powerpc) implement WARN using the same mechanism; if the
    illegal instruction was the result of a WARN, then report_bug(Q) returns
    CONFIG_DEBUG_BUGVERBOSE; otherwise it returns BUG_TRAP_TYPE_BUG.
    
    lib/bug.c keeps a list of loaded modules which can be searched for __bug_table
    entries.  The architecture must call
    module_bug_finalize()/module_bug_cleanup() from its corresponding
    module_finalize/cleanup functions.
    
    Unsetting CONFIG_DEBUG_BUGVERBOSE will reduce the kernel size by some amount.
    At the very least, filename and line information will not be recorded for each
    but, but architectures may decide to store no extra information per BUG at
    all.
    
    Unfortunately, gcc doesn't have a general way to mark an asm() as noreturn, so
    architectures will generally have to include an infinite loop (or similar) in
    the BUG code, so that gcc knows execution won't continue beyond that point.
    gcc does have a __builtin_trap() operator which may be useful to achieve the
    same effect, unfortunately it cannot be used to actually implement the BUG
    itself, because there's no way to get the instruction's address for use in
    generating the __bug_table entry.
    
    [randy.dunlap@oracle.com: Handle BUG=n, GENERIC_BUG=n to prevent build errors]
    [bunk@stusta.de: include/linux/bug.h must always #include <linux/module.h]
    Signed-off-by: default avatarJeremy Fitzhardinge <jeremy@goop.org>
    Cc: Andi Kleen <ak@muc.de>
    Cc: Hugh Dickens <hugh@veritas.com>
    Cc: Michael Ellerman <michael@ellerman.id.au>
    Cc: Paul Mackerras <paulus@samba.org>
    Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
    Cc: Rusty Russell <rusty@rustcorp.com.au>
    Signed-off-by: default avatarAdrian Bunk <bunk@stusta.de>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    7664c5a1
bug.c 4.03 KB