• Petr Mladek's avatar
    printk/nmi: generic solution for safe printk in NMI · 42a0bb3f
    Petr Mladek authored
    printk() takes some locks and could not be used a safe way in NMI
    context.
    
    The chance of a deadlock is real especially when printing stacks from
    all CPUs.  This particular problem has been addressed on x86 by the
    commit a9edc880 ("x86/nmi: Perform a safe NMI stack trace on all
    CPUs").
    
    The patchset brings two big advantages.  First, it makes the NMI
    backtraces safe on all architectures for free.  Second, it makes all NMI
    messages almost safe on all architectures (the temporary buffer is
    limited.  We still should keep the number of messages in NMI context at
    minimum).
    
    Note that there already are several messages printed in NMI context:
    WARN_ON(in_nmi()), BUG_ON(in_nmi()), anything being printed out from MCE
    handlers.  These are not easy to avoid.
    
    This patch reuses most of the code and makes it generic.  It is useful
    for all messages and architectures that support NMI.
    
    The alternative printk_func is set when entering and is reseted when
    leaving NMI context.  It queues IRQ work to copy the messages into the
    main ring buffer in a safe context.
    
    __printk_nmi_flush() copies all available messages and reset the buffer.
    Then we could use a simple cmpxchg operations to get synchronized with
    writers.  There is also used a spinlock to get synchronized with other
    flushers.
    
    We do not longer use seq_buf because it depends on external lock.  It
    would be hard to make all supported operations safe for a lockless use.
    It would be confusing and error prone to make only some operations safe.
    
    The code is put into separate printk/nmi.c as suggested by Steven
    Rostedt.  It needs a per-CPU buffer and is compiled only on
    architectures that call nmi_enter().  This is achieved by the new
    HAVE_NMI Kconfig flag.
    
    The are MN10300 and Xtensa architectures.  We need to clean up NMI
    handling there first.  Let's do it separately.
    
    The patch is heavily based on the draft from Peter Zijlstra, see
    
      https://lkml.org/lkml/2015/6/10/327
    
    [arnd@arndb.de: printk-nmi: use %zu format string for size_t]
    [akpm@linux-foundation.org: min_t->min - all types are size_t here]
    Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
    Suggested-by: default avatarPeter Zijlstra <peterz@infradead.org>
    Suggested-by: default avatarSteven Rostedt <rostedt@goodmis.org>
    Cc: Jan Kara <jack@suse.cz>
    Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>	[arm part]
    Cc: Daniel Thompson <daniel.thompson@linaro.org>
    Cc: Jiri Kosina <jkosina@suse.com>
    Cc: Ingo Molnar <mingo@redhat.com>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Ralf Baechle <ralf@linux-mips.org>
    Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
    Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
    Cc: David Miller <davem@davemloft.net>
    Cc: Daniel Thompson <daniel.thompson@linaro.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    42a0bb3f
hw_nmi.c 1.25 KB