|
@@ -81,6 +81,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
|
|
|
*/
|
|
@@ -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;
|
|
@@ -2557,3 +2567,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);
|