Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7ba176b authored by Haavard Skinnemoen's avatar Haavard Skinnemoen
Browse files

[AVR32] NMI debugging



Change the NMI handler to use the die notifier chain to signal anyone
who cares. Add a simple "nmi debugger" which hooks into this chain and
that may dump registers, task state, etc. when it happens.

Signed-off-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent f6135d12
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@ parameter is applicable:
	ALSA	ALSA sound support is enabled.
	ALSA	ALSA sound support is enabled.
	APIC	APIC support is enabled.
	APIC	APIC support is enabled.
	APM	Advanced Power Management support is enabled.
	APM	Advanced Power Management support is enabled.
	AVR32	AVR32 architecture is enabled.
	AX25	Appropriate AX.25 support is enabled.
	AX25	Appropriate AX.25 support is enabled.
	BLACKFIN Blackfin architecture is enabled.
	BLACKFIN Blackfin architecture is enabled.
	DRM	Direct Rendering Management support is enabled.
	DRM	Direct Rendering Management support is enabled.
@@ -1123,6 +1124,10 @@ and is between 256 and 4096 characters. It is defined in the file
			of returning the full 64-bit number.
			of returning the full 64-bit number.
			The default is to return 64-bit inode numbers.
			The default is to return 64-bit inode numbers.


	nmi_debug=	[KNL,AVR32] Specify one or more actions to take
			when a NMI is triggered.
			Format: [state][,regs][,debounce][,die]

	nmi_watchdog=	[KNL,BUGS=X86-32] Debugging features for SMP kernels
	nmi_watchdog=	[KNL,BUGS=X86-32] Debugging features for SMP kernels


	no387		[BUGS=X86-32] Tells the kernel to use the 387 maths
	no387		[BUGS=X86-32] Tells the kernel to use the 387 maths
+10 −0
Original line number Original line Diff line number Diff line
@@ -170,6 +170,16 @@ config OWNERSHIP_TRACE
	  enabling Nexus-compliant debuggers to keep track of the PID of the
	  enabling Nexus-compliant debuggers to keep track of the PID of the
	  currently executing task.
	  currently executing task.


config NMI_DEBUGGING
	bool "NMI Debugging"
	default n
	help
	  Say Y here and pass the nmi_debug command-line parameter to
	  the kernel to turn on NMI debugging. Depending on the value
	  of the nmi_debug option, various pieces of information will
	  be dumped to the console when a Non-Maskable Interrupt
	  happens.

# FPU emulation goes here
# FPU emulation goes here


source "kernel/Kconfig.hz"
source "kernel/Kconfig.hz"
+1 −0
Original line number Original line Diff line number Diff line
@@ -12,3 +12,4 @@ obj-y += init_task.o switch_to.o cpu.o
obj-$(CONFIG_MODULES)		+= module.o avr32_ksyms.o
obj-$(CONFIG_MODULES)		+= module.o avr32_ksyms.o
obj-$(CONFIG_KPROBES)		+= kprobes.o
obj-$(CONFIG_KPROBES)		+= kprobes.o
obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
obj-$(CONFIG_NMI_DEBUGGING)	+= nmi_debug.o
+11 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,17 @@ void ack_bad_irq(unsigned int irq)
	printk("unexpected IRQ %u\n", irq);
	printk("unexpected IRQ %u\n", irq);
}
}


/* May be overridden by platform code */
int __weak nmi_enable(void)
{
	return -ENOSYS;
}

void __weak nmi_disable(void)
{

}

#ifdef CONFIG_PROC_FS
#ifdef CONFIG_PROC_FS
int show_interrupts(struct seq_file *p, void *v)
int show_interrupts(struct seq_file *p, void *v)
{
{
+82 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2007 Atmel Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/delay.h>
#include <linux/kdebug.h>
#include <linux/notifier.h>
#include <linux/sched.h>

#include <asm/irq.h>

enum nmi_action {
	NMI_SHOW_STATE	= 1 << 0,
	NMI_SHOW_REGS	= 1 << 1,
	NMI_DIE		= 1 << 2,
	NMI_DEBOUNCE	= 1 << 3,
};

static unsigned long nmi_actions;

static int nmi_debug_notify(struct notifier_block *self,
		unsigned long val, void *data)
{
	struct die_args *args = data;

	if (likely(val != DIE_NMI))
		return NOTIFY_DONE;

	if (nmi_actions & NMI_SHOW_STATE)
		show_state();
	if (nmi_actions & NMI_SHOW_REGS)
		show_regs(args->regs);
	if (nmi_actions & NMI_DEBOUNCE)
		mdelay(10);
	if (nmi_actions & NMI_DIE)
		return NOTIFY_BAD;

	return NOTIFY_OK;
}

static struct notifier_block nmi_debug_nb = {
	.notifier_call = nmi_debug_notify,
};

static int __init nmi_debug_setup(char *str)
{
	char *p, *sep;

	register_die_notifier(&nmi_debug_nb);
	if (nmi_enable()) {
		printk(KERN_WARNING "Unable to enable NMI.\n");
		return 0;
	}

	if (*str != '=')
		return 0;

	for (p = str + 1; *p; p = sep + 1) {
		sep = strchr(p, ',');
		if (sep)
			*sep = 0;
		if (strcmp(p, "state") == 0)
			nmi_actions |= NMI_SHOW_STATE;
		else if (strcmp(p, "regs") == 0)
			nmi_actions |= NMI_SHOW_REGS;
		else if (strcmp(p, "debounce") == 0)
			nmi_actions |= NMI_DEBOUNCE;
		else if (strcmp(p, "die") == 0)
			nmi_actions |= NMI_DIE;
		else
			printk(KERN_WARNING "NMI: Unrecognized action `%s'\n",
				p);
		if (!sep)
			break;
	}

	return 0;
}
__setup("nmi_debug", nmi_debug_setup);
Loading