Skip to content
  • Hidehiro Kawai's avatar
    panic, x86: Allow CPUs to save registers even if looping in NMI context · 58c5661f
    Hidehiro Kawai authored
    
    
    Currently, kdump_nmi_shootdown_cpus(), a subroutine of crash_kexec(),
    sends an NMI IPI to CPUs which haven't called panic() to stop them,
    save their register information and do some cleanups for crash dumping.
    However, if such a CPU is infinitely looping in NMI context, we fail to
    save its register information into the crash dump.
    
    For example, this can happen when unknown NMIs are broadcast to all
    CPUs as follows:
    
      CPU 0                             CPU 1
      ===========================       ==========================
      receive an unknown NMI
      unknown_nmi_error()
        panic()                         receive an unknown NMI
          spin_trylock(&panic_lock)     unknown_nmi_error()
          crash_kexec()                   panic()
                                            spin_trylock(&panic_lock)
                                            panic_smp_self_stop()
                                              infinite loop
            kdump_nmi_shootdown_cpus()
              issue NMI IPI -----------> blocked until IRET
                                              infinite loop...
    
    Here, since CPU 1 is in NMI context, the second NMI from CPU 0 is
    blocked until CPU 1 executes IRET. However, CPU 1 never executes IRET,
    so the NMI is not handled and the callback function to save registers is
    never called.
    
    In practice, this can happen on some servers which broadcast NMIs to all
    CPUs when the NMI button is pushed.
    
    To save registers in this case, we need to:
    
      a) Return from NMI handler instead of looping infinitely
      or
      b) Call the callback function directly from the infinite loop
    
    Inherently, a) is risky because NMI is also used to prevent corrupted
    data from being propagated to devices.  So, we chose b).
    
    This patch does the following:
    
    1. Move the infinite looping of CPUs which haven't called panic() in NMI
       context (actually done by panic_smp_self_stop()) outside of panic() to
       enable us to refer pt_regs. Please note that panic_smp_self_stop() is
       still used for normal context.
    
    2. Call a callback of kdump_nmi_shootdown_cpus() directly to save
       registers and do some cleanups after setting waiting_for_crash_ipi which
       is used for counting down the number of CPUs which handled the callback
    
    Signed-off-by: default avatarHidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
    Acked-by: default avatarMichal Hocko <mhocko@suse.com>
    Cc: Aaron Tomlin <atomlin@redhat.com>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Andy Lutomirski <luto@kernel.org>
    Cc: Baoquan He <bhe@redhat.com>
    Cc: Chris Metcalf <cmetcalf@ezchip.com>
    Cc: Dave Young <dyoung@redhat.com>
    Cc: David Hildenbrand <dahi@linux.vnet.ibm.com>
    Cc: Don Zickus <dzickus@redhat.com>
    Cc: Eric Biederman <ebiederm@xmission.com>
    Cc: Frederic Weisbecker <fweisbec@gmail.com>
    Cc: Gobinda Charan Maji <gobinda.cemk07@gmail.com>
    Cc: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
    Cc: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
    Cc: "H. Peter Anvin" <hpa@zytor.com>
    Cc: Ingo Molnar <mingo@kernel.org>
    Cc: Javi Merino <javi.merino@arm.com>
    Cc: Jiang Liu <jiang.liu@linux.intel.com>
    Cc: Jonathan Corbet <corbet@lwn.net>
    Cc: kexec@lists.infradead.org
    Cc: linux-doc@vger.kernel.org
    Cc: lkml <linux-kernel@vger.kernel.org>
    Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
    Cc: Michal Nazarewicz <mina86@mina86.com>
    Cc: Nicolas Iooss <nicolas.iooss_linux@m4x.org>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Prarit Bhargava <prarit@redhat.com>
    Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
    Cc: Seth Jennings <sjenning@redhat.com>
    Cc: Stefan Lippers-Hollmann <s.l-h@gmx.de>
    Cc: Steven Rostedt <rostedt@goodmis.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Ulrich Obergfell <uobergfe@redhat.com>
    Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
    Cc: Vivek Goyal <vgoyal@redhat.com>
    Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
    Link: http://lkml.kernel.org/r/20151210014628.25437.75256.stgit@softrs
    
    
    [ Cleanup comments, fixup formatting. ]
    Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    58c5661f