aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/x2apic_uv_x.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic/x2apic_uv_x.c')
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 6ef2899eb861..4b8dbb256147 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -21,6 +21,7 @@
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/pci.h> 23#include <linux/pci.h>
24#include <linux/kdebug.h>
24 25
25#include <asm/uv/uv_mmrs.h> 26#include <asm/uv/uv_mmrs.h>
26#include <asm/uv/uv_hub.h> 27#include <asm/uv/uv_hub.h>
@@ -41,6 +42,7 @@ static enum uv_system_type uv_system_type;
41static u64 gru_start_paddr, gru_end_paddr; 42static u64 gru_start_paddr, gru_end_paddr;
42int uv_min_hub_revision_id; 43int uv_min_hub_revision_id;
43EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); 44EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
45static DEFINE_SPINLOCK(uv_nmi_lock);
44 46
45static inline bool is_GRU_range(u64 start, u64 end) 47static inline bool is_GRU_range(u64 start, u64 end)
46{ 48{
@@ -74,6 +76,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
74 if (!strcmp(oem_id, "SGI")) { 76 if (!strcmp(oem_id, "SGI")) {
75 nodeid = early_get_nodeid(); 77 nodeid = early_get_nodeid();
76 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; 78 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
79 x86_platform.nmi_init = uv_nmi_init;
77 if (!strcmp(oem_table_id, "UVL")) 80 if (!strcmp(oem_table_id, "UVL"))
78 uv_system_type = UV_LEGACY_APIC; 81 uv_system_type = UV_LEGACY_APIC;
79 else if (!strcmp(oem_table_id, "UVX")) 82 else if (!strcmp(oem_table_id, "UVX"))
@@ -596,6 +599,46 @@ void __cpuinit uv_cpu_init(void)
596 set_x2apic_extra_bits(uv_hub_info->pnode); 599 set_x2apic_extra_bits(uv_hub_info->pnode);
597} 600}
598 601
602/*
603 * When NMI is received, print a stack trace.
604 */
605int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
606{
607 if (reason != DIE_NMI_IPI)
608 return NOTIFY_OK;
609 /*
610 * Use a lock so only one cpu prints at a time
611 * to prevent intermixed output.
612 */
613 spin_lock(&uv_nmi_lock);
614 pr_info("NMI stack dump cpu %u:\n", smp_processor_id());
615 dump_stack();
616 spin_unlock(&uv_nmi_lock);
617
618 return NOTIFY_STOP;
619}
620
621static struct notifier_block uv_dump_stack_nmi_nb = {
622 .notifier_call = uv_handle_nmi
623};
624
625void uv_register_nmi_notifier(void)
626{
627 if (register_die_notifier(&uv_dump_stack_nmi_nb))
628 printk(KERN_WARNING "UV NMI handler failed to register\n");
629}
630
631void uv_nmi_init(void)
632{
633 unsigned int value;
634
635 /*
636 * Unmask NMI on all cpus
637 */
638 value = apic_read(APIC_LVT1) | APIC_DM_NMI;
639 value &= ~APIC_LVT_MASKED;
640 apic_write(APIC_LVT1, value);
641}
599 642
600void __init uv_system_init(void) 643void __init uv_system_init(void)
601{ 644{
@@ -717,6 +760,7 @@ void __init uv_system_init(void)
717 760
718 uv_cpu_init(); 761 uv_cpu_init();
719 uv_scir_register_cpu_notifier(); 762 uv_scir_register_cpu_notifier();
763 uv_register_nmi_notifier();
720 proc_mkdir("sgi_uv", NULL); 764 proc_mkdir("sgi_uv", NULL);
721 765
722 /* register Legacy VGA I/O redirection handler */ 766 /* register Legacy VGA I/O redirection handler */