-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch moves the UV NMI support from the x2apic file to a new separate uv_nmi.c file in preparation for the next sequence of patches. It prevents upcoming bloat of the x2apic file, and has the added benefit of putting the upcoming /sys/module parameters under the name 'uv_nmi' instead of 'x2apic_uv_x', which was obscure. Signed-off-by: Mike Travis <travis@sgi.com> Reviewed-by: Dimitri Sivanich <sivanich@sgi.com> Reviewed-by: Hedi Berriche <hedi@sgi.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Cc: Jason Wessel <jason.wessel@windriver.com> Link: http://lkml.kernel.org/r/20130923212500.183295611@asylum.americas.sgi.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
- Loading branch information
Mike Travis
authored and
Ingo Molnar
committed
Sep 24, 2013
1 parent
4a10c2a
commit 1e01942
Showing
4 changed files
with
105 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o | ||
obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o uv_nmi.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* SGI NMI support routines | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
* | ||
* Copyright (c) 2009-2013 Silicon Graphics, Inc. All Rights Reserved. | ||
* Copyright (c) Mike Travis | ||
*/ | ||
|
||
#include <linux/cpu.h> | ||
#include <linux/nmi.h> | ||
|
||
#include <asm/apic.h> | ||
#include <asm/nmi.h> | ||
#include <asm/uv/uv.h> | ||
#include <asm/uv/uv_hub.h> | ||
#include <asm/uv/uv_mmrs.h> | ||
|
||
/* BMC sets a bit this MMR non-zero before sending an NMI */ | ||
#define UVH_NMI_MMR UVH_SCRATCH5 | ||
#define UVH_NMI_MMR_CLEAR (UVH_NMI_MMR + 8) | ||
#define UV_NMI_PENDING_MASK (1UL << 63) | ||
DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count); | ||
static DEFINE_SPINLOCK(uv_nmi_lock); | ||
|
||
/* | ||
* When NMI is received, print a stack trace. | ||
*/ | ||
int uv_handle_nmi(unsigned int reason, struct pt_regs *regs) | ||
{ | ||
unsigned long real_uv_nmi; | ||
int bid; | ||
|
||
/* | ||
* Each blade has an MMR that indicates when an NMI has been sent | ||
* to cpus on the blade. If an NMI is detected, atomically | ||
* clear the MMR and update a per-blade NMI count used to | ||
* cause each cpu on the blade to notice a new NMI. | ||
*/ | ||
bid = uv_numa_blade_id(); | ||
real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK); | ||
|
||
if (unlikely(real_uv_nmi)) { | ||
spin_lock(&uv_blade_info[bid].nmi_lock); | ||
real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & | ||
UV_NMI_PENDING_MASK); | ||
if (real_uv_nmi) { | ||
uv_blade_info[bid].nmi_count++; | ||
uv_write_local_mmr(UVH_NMI_MMR_CLEAR, | ||
UV_NMI_PENDING_MASK); | ||
} | ||
spin_unlock(&uv_blade_info[bid].nmi_lock); | ||
} | ||
|
||
if (likely(__get_cpu_var(cpu_last_nmi_count) == | ||
uv_blade_info[bid].nmi_count)) | ||
return NMI_DONE; | ||
|
||
__get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count; | ||
|
||
/* | ||
* Use a lock so only one cpu prints at a time. | ||
* This prevents intermixed output. | ||
*/ | ||
spin_lock(&uv_nmi_lock); | ||
pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id()); | ||
dump_stack(); | ||
spin_unlock(&uv_nmi_lock); | ||
|
||
return NMI_HANDLED; | ||
} | ||
|
||
void uv_register_nmi_notifier(void) | ||
{ | ||
if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv")) | ||
pr_warn("UV NMI handler failed to register\n"); | ||
} | ||
|
||
void uv_nmi_init(void) | ||
{ | ||
unsigned int value; | ||
|
||
/* | ||
* Unmask NMI on all cpus | ||
*/ | ||
value = apic_read(APIC_LVT1) | APIC_DM_NMI; | ||
value &= ~APIC_LVT_MASKED; | ||
apic_write(APIC_LVT1, value); | ||
} | ||
|