From: Hidehiro Kawai <[email protected]>

This patch introduces a command line parameter apic_extnmi:

 apic_extnmi=( bsp|all|none )

The default value is "bsp" and this is the current behavior: only the
Boot-Strapping Processor receives an external NMI.

"all" allows external NMIs to be broadcast to all CPUs. This would
raise the success rate of panic on NMI when BSP hangs in NMI context
or the external NMI is swallowed by other NMI handlers on the BSP.

If you specify "none", no CPUs receive external NMIs. This is useful for
the dump capture kernel so that it cannot be shot down by accidentally
pressing the external NMI button (on platforms which have it) while
saving a crash dump.

Signed-off-by: Hidehiro Kawai <[email protected]>
Acked-by: Michal Hocko <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Bandan Das <[email protected]>
Cc: Baoquan He <[email protected]>
Cc: "Eric W. Biederman" <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiang Liu <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: "Maciej W. Rozycki" <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ricardo Ribalda Delgado <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Viresh Kumar <[email protected]>
Cc: Vivek Goyal <[email protected]>
Cc: x86-ml <[email protected]>
Link: http://lkml.kernel.org/r/20151210014632.25437.43778.stgit@softrs
Signed-off-by: Borislav Petkov <[email protected]>
---
 Documentation/kernel-parameters.txt |  9 +++++++++
 arch/x86/include/asm/apic.h         |  5 +++++
 arch/x86/kernel/apic/apic.c         | 34 ++++++++++++++++++++++++++++++++--
 3 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
index 742f69d18fc8..74acea53e9e3 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -472,6 +472,15 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
                        Change the amount of debugging information output
                        when initialising the APIC and IO-APIC components.
 
+       apic_extnmi=    [APIC,X86] External NMI delivery setting
+                       Format: { bsp (default) | all | none }
+                       bsp:  External NMI is delivered only to CPU 0
+                       all:  External NMIs are broadcast to all CPUs as a
+                             backup of CPU 0
+                       none: External NMI is masked for all CPUs. This is
+                             useful so that a dump capture kernel won't be
+                             shot down by NMI
+
        autoconf=       [IPV6]
                        See Documentation/networking/ipv6.txt.
 
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index a30316bf801a..357171342f53 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -23,6 +23,11 @@
 #define APIC_VERBOSE 1
 #define APIC_DEBUG   2
 
+/* Macros for apic_extnmi which controls external NMI masking */
+#define APIC_EXTNMI_BSP                0 /* Default */
+#define APIC_EXTNMI_ALL                1
+#define APIC_EXTNMI_NONE       2
+
 /*
  * Define the default level of output to be very little
  * This can be turned up by using apic=verbose for more
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 2f69e3b184f6..8584319d0117 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -82,6 +82,12 @@ physid_mask_t phys_cpu_present_map;
 static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID;
 
 /*
+ * This variable controls which CPUs receive external NMIs.  By default,
+ * external NMIs are delivered only to the BSP.
+ */
+static int apic_extnmi = APIC_EXTNMI_BSP;
+
+/*
  * Map cpu index to physical APIC ID
  */
 DEFINE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid, BAD_APICID);
@@ -1161,6 +1167,8 @@ void __init init_bsp_APIC(void)
        value = APIC_DM_NMI;
        if (!lapic_is_integrated())             /* 82489DX */
                value |= APIC_LVT_LEVEL_TRIGGER;
+       if (apic_extnmi == APIC_EXTNMI_NONE)
+               value |= APIC_LVT_MASKED;
        apic_write(APIC_LVT1, value);
 }
 
@@ -1378,9 +1386,11 @@ void setup_local_APIC(void)
        apic_write(APIC_LVT0, value);
 
        /*
-        * only the BP should see the LINT1 NMI signal, obviously.
+        * Only the BSP sees the LINT1 NMI signal by default. This can be
+        * modified by apic_extnmi= boot option.
         */
-       if (!cpu)
+       if ((!cpu && apic_extnmi != APIC_EXTNMI_NONE) ||
+           apic_extnmi == APIC_EXTNMI_ALL)
                value = APIC_DM_NMI;
        else
                value = APIC_DM_NMI | APIC_LVT_MASKED;
@@ -2548,3 +2558,23 @@ static int __init apic_set_disabled_cpu_apicid(char *arg)
        return 0;
 }
 early_param("disable_cpu_apicid", apic_set_disabled_cpu_apicid);
+
+static int __init apic_set_extnmi(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
+
+       if (!strncmp("all", arg, 3))
+               apic_extnmi = APIC_EXTNMI_ALL;
+       else if (!strncmp("none", arg, 4))
+               apic_extnmi = APIC_EXTNMI_NONE;
+       else if (!strncmp("bsp", arg, 3))
+               apic_extnmi = APIC_EXTNMI_BSP;
+       else {
+               pr_warn("Unknown external NMI delivery mode `%s' ignored\n", 
arg);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+early_param("apic_extnmi", apic_set_extnmi);
-- 
2.3.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to