traps.c revision 36b841288656b9b30b5d2add2fd136ac7eab5867
11394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu/*
21394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * File:         arch/blackfin/kernel/traps.c
31394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * Based on:
41394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * Author:       Hamish Macdonald
51394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu *
61394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * Created:
71394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * Description:  uses S/W interrupt 15 for the system calls
81394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu *
91394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * Modified:
101394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu *               Copyright 2004-2006 Analog Devices Inc.
111394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu *
121394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * Bugs:         Enter bugs at http://blackfin.uclinux.org/
131394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu *
141394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * This program is free software; you can redistribute it and/or modify
151394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * it under the terms of the GNU General Public License as published by
161394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * the Free Software Foundation; either version 2 of the License, or
171394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * (at your option) any later version.
181394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu *
191394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * This program is distributed in the hope that it will be useful,
201394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * but WITHOUT ANY WARRANTY; without even the implied warranty of
211394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
221394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * GNU General Public License for more details.
231394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu *
241394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * You should have received a copy of the GNU General Public License
251394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * along with this program; if not, see the file COPYING, or write
261394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * to the Free Software Foundation, Inc.,
271394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
281394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu */
291394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
3070f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger#include <linux/bug.h>
311f83b8f148a1eb967d2a628cbb741cd56fb54572Mike Frysinger#include <linux/uaccess.h>
321f83b8f148a1eb967d2a628cbb741cd56fb54572Mike Frysinger#include <linux/interrupt.h>
331f83b8f148a1eb967d2a628cbb741cd56fb54572Mike Frysinger#include <linux/module.h>
341f83b8f148a1eb967d2a628cbb741cd56fb54572Mike Frysinger#include <linux/kallsyms.h>
35d31c5ab147e0b17b9ec0daa5e4d1fc0bd6b19974Bryan Wu#include <linux/fs.h>
368feae13110d60cc6287afabc2887366b0eb226c2David Howells#include <linux/rbtree.h>
371394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#include <asm/traps.h>
381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#include <asm/cacheflush.h>
39f4585a08479a730fb809606b8ee327a5398c117cMike Frysinger#include <asm/cplb.h>
40e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger#include <asm/dma.h>
411394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#include <asm/blackfin.h>
421394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#include <asm/irq_handler.h>
43d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz#include <linux/irq.h>
44669b792c77bbc30e9f4d9c95dbc918dc348c49c2Robin Getz#include <asm/trace.h>
45226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#include <asm/fixed_code.h>
461394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
471394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_KGDB
481394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu# include <linux/kgdb.h>
49226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
50226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz# define CHK_DEBUGGER_TRAP() \
51226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	do { \
52a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		kgdb_handle_exception(trapnr, sig, info.si_code, fp); \
53226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	} while (0)
54226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz# define CHK_DEBUGGER_TRAP_MAYBE() \
55226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	do { \
56226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		if (kgdb_connected) \
57226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			CHK_DEBUGGER_TRAP(); \
58226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	} while (0)
59226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#else
60226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz# define CHK_DEBUGGER_TRAP() do { } while (0)
61226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
621394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
631394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
649f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz
654ee1c45337e7b529eed644c6f62399d797dcbc10Robin Getz#ifdef CONFIG_DEBUG_VERBOSE
669f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#define verbose_printk(fmt, arg...) \
679f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	printk(fmt, ##arg)
689f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#else
699f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#define verbose_printk(fmt, arg...) \
709f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	({ if (0) printk(fmt, ##arg); 0; })
719f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
729f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz
7381f7f45606812f1d15d618c2646d0f33ca111f87Robin Getz#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE)
7481f7f45606812f1d15d618c2646d0f33ca111f87Robin Getzu32 last_seqstat;
7581f7f45606812f1d15d618c2646d0f33ca111f87Robin Getz#ifdef CONFIG_DEBUG_MMRS_MODULE
7681f7f45606812f1d15d618c2646d0f33ca111f87Robin GetzEXPORT_SYMBOL(last_seqstat);
7781f7f45606812f1d15d618c2646d0f33ca111f87Robin Getz#endif
7881f7f45606812f1d15d618c2646d0f33ca111f87Robin Getz#endif
7981f7f45606812f1d15d618c2646d0f33ca111f87Robin Getz
801394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu/* Initiate the event table handler */
811394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid __init trap_init(void)
821394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
831394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	CSYNC();
841394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	bfin_write_EVT3(trap);
851394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	CSYNC();
861394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
871394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
88226eb1ef523a33c66193bc319a92c647e47311d4Robin Getzstatic void decode_address(char *buf, unsigned long address)
891394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
909f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#ifdef CONFIG_DEBUG_VERBOSE
911394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	struct task_struct *p;
921394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	struct mm_struct *mm;
93885be03b069131d242506f0f717d38659b2bdb6cRobin Getz	unsigned long flags, offset;
94904656cda10ce985e6bc8b16488b58236eaec8e2Robin Getz	unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
958feae13110d60cc6287afabc2887366b0eb226c2David Howells	struct rb_node *n;
961394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
971394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_KALLSYMS
988a0e6656030ffe9bcb81b725e956917bafc7522dMike Frysinger	unsigned long symsize;
991394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	const char *symname;
1001394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	char *modname;
1011394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	char *delim = ":";
1021394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	char namebuf[128];
10318070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger#endif
10418070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger
10518070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger	buf += sprintf(buf, "<0x%08lx> ", address);
1061394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
10718070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger#ifdef CONFIG_KALLSYMS
1081394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* look up the address and see if we are in kernel space */
1091394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
1101394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1111394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	if (symname) {
1121394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		/* yeah! kernel space! */
1131394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		if (!modname)
1141394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			modname = delim = "";
11518070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		sprintf(buf, "{ %s%s%s%s + 0x%lx }",
11618070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		        delim, modname, delim, symname,
11718070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		        (unsigned long)offset);
118885be03b069131d242506f0f717d38659b2bdb6cRobin Getz		return;
1191394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
1201394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
1211394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
122226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	if (address >= FIXED_CODE_START && address < FIXED_CODE_END) {
12318070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		/* Problem in fixed code section? */
12418070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		strcat(buf, "/* Maybe fixed code section */");
12518070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		return;
12618070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger
12718070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger	} else if (address < CONFIG_BOOT_LOAD) {
12818070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		/* Problem somewhere before the kernel start address */
12918070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		strcat(buf, "/* Maybe null pointer? */");
13018070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		return;
13118070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger
13218070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger	} else if (address >= COREMMR_BASE) {
13318070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		strcat(buf, "/* core mmrs */");
13418070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		return;
13518070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger
13618070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger	} else if (address >= SYSMMR_BASE) {
13718070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		strcat(buf, "/* system mmrs */");
138226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		return;
139226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
14018070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger	} else if (address >= L1_ROM_START && address < L1_ROM_START + L1_ROM_LENGTH) {
14118070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger		strcat(buf, "/* on-chip L1 ROM */");
142226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		return;
143226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	}
144226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
1451394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* looks like we're off in user-land, so let's walk all the
1461394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * mappings of all our processes and see if we can't be a whee
1471394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * bit more specific
1481394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 */
149885be03b069131d242506f0f717d38659b2bdb6cRobin Getz	write_lock_irqsave(&tasklist_lock, flags);
1501394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	for_each_process(p) {
151904656cda10ce985e6bc8b16488b58236eaec8e2Robin Getz		mm = (in_atomic ? p->mm : get_task_mm(p));
1521394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		if (!mm)
1531394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			continue;
1541394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1558feae13110d60cc6287afabc2887366b0eb226c2David Howells		for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) {
1568feae13110d60cc6287afabc2887366b0eb226c2David Howells			struct vm_area_struct *vma;
1578feae13110d60cc6287afabc2887366b0eb226c2David Howells
1588feae13110d60cc6287afabc2887366b0eb226c2David Howells			vma = rb_entry(n, struct vm_area_struct, vm_rb);
1591394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1601394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			if (address >= vma->vm_start && address < vma->vm_end) {
161cf28b4863f9ee8f122e8ff3ac0d403e07ba9c6d9Jan Blunck				char _tmpbuf[256];
1621394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu				char *name = p->comm;
1631394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu				struct file *file = vma->vm_file;
164cf28b4863f9ee8f122e8ff3ac0d403e07ba9c6d9Jan Blunck
1656a0bfff44e4aa4ee1721b3daa004d2039576c70dTim Pepper				if (file) {
1666a0bfff44e4aa4ee1721b3daa004d2039576c70dTim Pepper					char *d_name = d_path(&file->f_path, _tmpbuf,
167cf28b4863f9ee8f122e8ff3ac0d403e07ba9c6d9Jan Blunck						      sizeof(_tmpbuf));
1686a0bfff44e4aa4ee1721b3daa004d2039576c70dTim Pepper					if (!IS_ERR(d_name))
1696a0bfff44e4aa4ee1721b3daa004d2039576c70dTim Pepper						name = d_name;
1706a0bfff44e4aa4ee1721b3daa004d2039576c70dTim Pepper				}
1711394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1728a0e6656030ffe9bcb81b725e956917bafc7522dMike Frysinger				/* FLAT does not have its text aligned to the start of
1738a0e6656030ffe9bcb81b725e956917bafc7522dMike Frysinger				 * the map while FDPIC ELF does ...
1748a0e6656030ffe9bcb81b725e956917bafc7522dMike Frysinger				 */
1757f1c906808a36630990d83d872935c079b76595bRobin Getz
1767f1c906808a36630990d83d872935c079b76595bRobin Getz				/* before we can check flat/fdpic, we need to
1777f1c906808a36630990d83d872935c079b76595bRobin Getz				 * make sure current is valid
1787f1c906808a36630990d83d872935c079b76595bRobin Getz				 */
1797f1c906808a36630990d83d872935c079b76595bRobin Getz				if ((unsigned long)current >= FIXED_CODE_START &&
1807f1c906808a36630990d83d872935c079b76595bRobin Getz				    !((unsigned long)current & 0x3)) {
1817f1c906808a36630990d83d872935c079b76595bRobin Getz					if (current->mm &&
1827f1c906808a36630990d83d872935c079b76595bRobin Getz					    (address > current->mm->start_code) &&
1837f1c906808a36630990d83d872935c079b76595bRobin Getz					    (address < current->mm->end_code))
1847f1c906808a36630990d83d872935c079b76595bRobin Getz						offset = address - current->mm->start_code;
1857f1c906808a36630990d83d872935c079b76595bRobin Getz					else
1867f1c906808a36630990d83d872935c079b76595bRobin Getz						offset = (address - vma->vm_start) +
1877f1c906808a36630990d83d872935c079b76595bRobin Getz							 (vma->vm_pgoff << PAGE_SHIFT);
1887f1c906808a36630990d83d872935c079b76595bRobin Getz
18918070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger					sprintf(buf, "[ %s + 0x%lx ]", name, offset);
1907f1c906808a36630990d83d872935c079b76595bRobin Getz				} else
19118070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger					sprintf(buf, "[ %s vma:0x%lx-0x%lx]",
19218070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger						name, vma->vm_start, vma->vm_end);
1937f1c906808a36630990d83d872935c079b76595bRobin Getz
194904656cda10ce985e6bc8b16488b58236eaec8e2Robin Getz				if (!in_atomic)
195885be03b069131d242506f0f717d38659b2bdb6cRobin Getz					mmput(mm);
1967f1c906808a36630990d83d872935c079b76595bRobin Getz
19718070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger				if (buf[0] == '\0')
19818070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger					sprintf(buf, "[ %s ] dynamic memory", name);
199f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
200885be03b069131d242506f0f717d38659b2bdb6cRobin Getz				goto done;
2011394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			}
2021394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		}
203904656cda10ce985e6bc8b16488b58236eaec8e2Robin Getz		if (!in_atomic)
204885be03b069131d242506f0f717d38659b2bdb6cRobin Getz			mmput(mm);
2051394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
2061394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
2071394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* we were unable to find this address anywhere */
20818070dd6692a35bec266ed9ea559c24da4fdeeefMike Frysinger	sprintf(buf, "/* kernel dynamic memory */");
209885be03b069131d242506f0f717d38659b2bdb6cRobin Getz
210885be03b069131d242506f0f717d38659b2bdb6cRobin Getzdone:
211885be03b069131d242506f0f717d38659b2bdb6cRobin Getz	write_unlock_irqrestore(&tasklist_lock, flags);
2129f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#else
2139f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	sprintf(buf, " ");
2149f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
2151394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
2161394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
2172ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getzasmlinkage void double_fault_c(struct pt_regs *fp)
2182ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz{
219a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
220a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz	int j;
221a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz	trace_buffer_save(j);
222a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz#endif
223a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz
224226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	console_verbose();
225226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	oops_in_progress = 1;
2269f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#ifdef CONFIG_DEBUG_VERBOSE
227ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches	printk(KERN_EMERG "Double Fault\n");
2280c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
2290c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) == VEC_UNCOV) {
2308f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		unsigned int cpu = smp_processor_id();
2310c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz		char buf[150];
2328f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		decode_address(buf, cpu_pda[cpu].retx);
2330c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz		printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
2348f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang			(unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
2358f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
2360c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz		printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %s\n", buf);
2378f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
2380c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz		printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %s\n", buf);
2390c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz
2400c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz		decode_address(buf, fp->retx);
2418f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf);
2420c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz	} else
2430c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz#endif
2440c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz	{
2450c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz		dump_bfin_process(fp);
2460c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz		dump_bfin_mem(fp);
2470c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz		show_regs(fp);
248a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz		dump_bfin_trace_buffer();
2490c7a6b2135c1bcb5139ca9ca87f292caafcb9410Robin Getz	}
2509f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
251d8804adf52f5991388fa9af77428e4cc7768059dMike Frysinger	panic("Double Fault - unrecoverable event");
2522ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz
2532ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz}
2542ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz
25582bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysingerstatic int kernel_mode_regs(struct pt_regs *regs)
25682bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger{
25782bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger	return regs->ipend & 0xffc0;
25882bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger}
25982bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger
2601394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuasmlinkage void trap_c(struct pt_regs *fp)
2611394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
262518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
263518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	int j;
264518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
2658f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
2668f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang	unsigned int cpu = smp_processor_id();
2678f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang#endif
26882bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger	const char *strerror = NULL;
269518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	int sig = 0;
2701394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	siginfo_t info;
2711394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
2721394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
273226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	trace_buffer_save(j);
27481f7f45606812f1d15d618c2646d0f33ca111f87Robin Getz#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE)
27581f7f45606812f1d15d618c2646d0f33ca111f87Robin Getz	last_seqstat = (u32)fp->seqstat;
27681f7f45606812f1d15d618c2646d0f33ca111f87Robin Getz#endif
277226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
278226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	/* Important - be very careful dereferncing pointers - will lead to
279226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	 * double faults if the stack has become corrupt
280226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	 */
281226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
2821394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* trap_c() will be called for exceptions. During exceptions
2831394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * processing, the pc value should be set with retx value.
2841394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * With this change we can cleanup some code in signal.c- TODO
2851394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 */
2861394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	fp->orig_pc = fp->retx;
2871394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* printk("exception: 0x%x, ipend=%x, reti=%x, retx=%x\n",
2881394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		trapnr, fp->ipend, fp->pc, fp->retx); */
2891394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
2901394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* send the appropriate signal to the user program */
2911394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	switch (trapnr) {
2921394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
2931394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* This table works in conjuction with the one in ./mach-common/entry.S
2941394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * Some exceptions are handled there (in assembly, in exception space)
2951394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * Some are handled here, (in C, in interrupt space)
2961394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * Some, like CPLB, are handled in both, where the normal path is
2971394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * handled in assembly/exception space, and the error path is handled
2981394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * here
2991394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 */
3001394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
3011394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x00 - Linux Syscall, getting here is an error */
3021394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x01 - userspace gdb breakpoint, handled here */
3031394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_EXCPT01:
3041394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_ILLTRAP;
3051394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
3061394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP_MAYBE();
3071394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		/* Check if this is a breakpoint in kernel space */
30882bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		if (kernel_mode_regs(fp))
3096510a20e1b1a3a5703429a09d03adf44882ae373Mike Frysinger			goto traps_done;
3101394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		else
3111394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			break;
3129401e618c8f70920f34893946239e24d40a3519aMike Frysinger	/* 0x03 - User Defined, userspace stack overflow */
3131394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_EXCPT03:
3141394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = SEGV_STACKFLOW;
3151394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGSEGV;
31682bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE);
317a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
3181394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
31927707d3e43e3a9c53e75cd7769f3ef74b1d56625Sonic Zhang	/* 0x02 - KGDB initial connection and break signal trap */
32027707d3e43e3a9c53e75cd7769f3ef74b1d56625Sonic Zhang	case VEC_EXCPT02:
32127707d3e43e3a9c53e75cd7769f3ef74b1d56625Sonic Zhang#ifdef CONFIG_KGDB
32227707d3e43e3a9c53e75cd7769f3ef74b1d56625Sonic Zhang		info.si_code = TRAP_ILLTRAP;
32327707d3e43e3a9c53e75cd7769f3ef74b1d56625Sonic Zhang		sig = SIGTRAP;
32427707d3e43e3a9c53e75cd7769f3ef74b1d56625Sonic Zhang		CHK_DEBUGGER_TRAP();
3256510a20e1b1a3a5703429a09d03adf44882ae373Mike Frysinger		goto traps_done;
32627707d3e43e3a9c53e75cd7769f3ef74b1d56625Sonic Zhang#endif
3275c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x04 - User Defined */
3285c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x05 - User Defined */
3295c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x06 - User Defined */
3305c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x07 - User Defined */
3315c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x08 - User Defined */
3325c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x09 - User Defined */
3335c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x0A - User Defined */
3345c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x0B - User Defined */
3355c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x0C - User Defined */
3365c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x0D - User Defined */
3375c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x0E - User Defined */
3385c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/* 0x0F - User Defined */
33927707d3e43e3a9c53e75cd7769f3ef74b1d56625Sonic Zhang	/* If we got here, it is most likely that someone was trying to use a
3405c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	 * custom exception handler, and it is not actually installed properly
3415c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	 */
3425c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	case VEC_EXCPT04 ... VEC_EXCPT15:
3435c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz		info.si_code = ILL_ILLPARAOP;
3445c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz		sig = SIGILL;
34582bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE);
3465c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz		CHK_DEBUGGER_TRAP_MAYBE();
3475c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz		break;
3481394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x10 HW Single step, handled here */
3491394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_STEP:
3501394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_STEP;
3511394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
3521394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP_MAYBE();
3531394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		/* Check if this is a single step in kernel space */
35482bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		if (kernel_mode_regs(fp))
3556510a20e1b1a3a5703429a09d03adf44882ae373Mike Frysinger			goto traps_done;
3561394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		else
3571394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			break;
3581394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x11 - Trace Buffer Full, handled here */
3591394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_OVFLOW:
3601394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_TRACEFLOW;
3611394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
36282bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE);
363a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
3641394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
3651394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x12 - Reserved, Caught by default */
3661394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x13 - Reserved, Caught by default */
3671394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x14 - Reserved, Caught by default */
3681394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x15 - Reserved, Caught by default */
3691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x16 - Reserved, Caught by default */
3701394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x17 - Reserved, Caught by default */
3711394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x18 - Reserved, Caught by default */
3721394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x19 - Reserved, Caught by default */
3731394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1A - Reserved, Caught by default */
3741394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1B - Reserved, Caught by default */
3751394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1C - Reserved, Caught by default */
3761394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1D - Reserved, Caught by default */
3771394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1E - Reserved, Caught by default */
3781394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1F - Reserved, Caught by default */
3791394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x20 - Reserved, Caught by default */
3801394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x21 - Undefined Instruction, handled here */
3811394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_UNDEF_I:
38270f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger#ifdef CONFIG_BUG
38370f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger		if (kernel_mode_regs(fp)) {
38470f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger			switch (report_bug(fp->pc, fp)) {
38570f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger			case BUG_TRAP_TYPE_NONE:
38670f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger				break;
38770f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger			case BUG_TRAP_TYPE_WARN:
38870f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger				dump_bfin_trace_buffer();
38970f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger				fp->pc += 2;
39070f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger				goto traps_done;
39170f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger			case BUG_TRAP_TYPE_BUG:
39270f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger				/* call to panic() will dump trace, and it is
39370f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger				 * off at this point, so it won't be clobbered
39470f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger				 */
39570f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger				panic("BUG()");
39670f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger			}
39770f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger		}
39870f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger#endif
3991394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_ILLOPC;
4001394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGILL;
40182bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE);
402a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
4031394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4041394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x22 - Illegal Instruction Combination, handled here */
4051394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_ILGAL_I:
4061394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_ILLPARAOP;
4071394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGILL;
40882bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE);
409a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
4101394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
411f26fbc48f130962fce15f37d079968f0f272e0c2Robin Getz	/* 0x23 - Data CPLB protection violation, handled here */
4121394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_VL:
4131394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_VI;
41436b841288656b9b30b5d2add2fd136ac7eab5867Graf Yang		sig = SIGSEGV;
41582bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
416a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
4171394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4181394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x24 - Data access misaligned, handled here */
4191394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_MISALI_D:
4201394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = BUS_ADRALN;
4211394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
42282bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE);
423a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
4241394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4251394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x25 - Unrecoverable Event, handled here */
4261394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_UNCOV:
4271394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_ILLEXCPT;
4281394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGILL;
42982bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE);
430a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
4311394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4321394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
4331394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		error case is handled here */
4341394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_M:
4351394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = BUS_ADRALN;
4361394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
43782bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE);
4381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4391394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
4401394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_MHIT:
4411394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_MULHIT;
4421394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGSEGV;
443c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
4448f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
44582bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger			strerror = KERN_NOTICE "NULL pointer access\n";
446c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger		else
4471394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
44882bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger			strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE);
449a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
4501394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4511394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x28 - Emulation Watchpoint, handled here */
4521394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_WATCH:
4531394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_WATCHPT;
4541394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
455569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		pr_debug(EXC_0x28(KERN_DEBUG));
4561394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP_MAYBE();
4571394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		/* Check if this is a watchpoint in kernel space */
45882bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		if (kernel_mode_regs(fp))
4596510a20e1b1a3a5703429a09d03adf44882ae373Mike Frysinger			goto traps_done;
4601394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		else
4611394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			break;
4621394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_BF535
4631394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x29 - Instruction fetch access error (535 only) */
4641394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_ISTRU_VL:      /* ADSP-BF535 only (MH) */
4651394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = BUS_OPFETCH;
4661394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
46782bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n";
468a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
4691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4701394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#else
4711394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x29 - Reserved, Caught by default */
4721394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
4731394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2A - Instruction fetch misaligned, handled here */
4741394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_MISALI_I:
4751394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = BUS_ADRALN;
4761394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
47782bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE);
478a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
4791394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
480f26fbc48f130962fce15f37d079968f0f272e0c2Robin Getz	/* 0x2B - Instruction CPLB protection violation, handled here */
4811394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_I_VL:
4821394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_VI;
483f26fbc48f130962fce15f37d079968f0f272e0c2Robin Getz		sig = SIGBUS;
48482bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE);
485a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
4861394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4871394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
4881394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_I_M:
4891394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_MISS;
4901394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
49182bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE);
4921394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4931394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2D - Instruction CPLB Multiple Hits, handled here */
4941394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_I_MHIT:
4951394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_MULHIT;
4961394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGSEGV;
497c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
4988f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
49982bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger			strerror = KERN_NOTICE "Jump to NULL address\n";
500c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger		else
5011394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
50282bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger			strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE);
503a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
5041394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
5051394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2E - Illegal use of Supervisor Resource, handled here */
5061394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_ILL_RES:
5071394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_PRVOPC;
5081394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGILL;
50982bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE);
510a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
5111394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
5121394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2F - Reserved, Caught by default */
5131394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x30 - Reserved, Caught by default */
5141394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x31 - Reserved, Caught by default */
5151394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x32 - Reserved, Caught by default */
5161394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x33 - Reserved, Caught by default */
5171394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x34 - Reserved, Caught by default */
5181394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x35 - Reserved, Caught by default */
5191394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x36 - Reserved, Caught by default */
5201394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x37 - Reserved, Caught by default */
5211394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x38 - Reserved, Caught by default */
5221394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x39 - Reserved, Caught by default */
5231394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3A - Reserved, Caught by default */
5241394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3B - Reserved, Caught by default */
5251394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3C - Reserved, Caught by default */
5261394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3D - Reserved, Caught by default */
5271394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3E - Reserved, Caught by default */
5281394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3F - Reserved, Caught by default */
52913fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz	case VEC_HWERR:
53013fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		info.si_code = BUS_ADRALN;
53113fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		sig = SIGBUS;
53213fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		switch (fp->seqstat & SEQSTAT_HWERRCAUSE) {
53313fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		/* System MMR Error */
53413fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
53513fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			info.si_code = BUS_ADRALN;
53613fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			sig = SIGBUS;
53782bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger			strerror = KERN_NOTICE HWC_x2(KERN_NOTICE);
53813fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
53913fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		/* External Memory Addressing Error */
54013fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
54113fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			info.si_code = BUS_ADRERR;
54213fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			sig = SIGBUS;
54382bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger			strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);
54413fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
54513fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		/* Performance Monitor Overflow */
54613fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
54782bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger			strerror = KERN_NOTICE HWC_x12(KERN_NOTICE);
54813fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
54913fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		/* RAISE 5 instruction */
55013fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		case (SEQSTAT_HWERRCAUSE_RAISE_5):
55113fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			printk(KERN_NOTICE HWC_x18(KERN_NOTICE));
55213fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
55313fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		default:        /* Reserved */
55413fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			printk(KERN_NOTICE HWC_default(KERN_NOTICE));
55513fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
55613fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		}
557a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
55813fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		break;
5595c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	/*
5605c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	 * We should be handling all known exception types above,
5615c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	 * if we get here we hit a reserved one, so panic
5625c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz	 */
5631394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	default:
5645c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz		info.si_code = ILL_ILLPARAOP;
5655c64e0d5109532f8184be29c1dc163059e3ded4bRobin Getz		sig = SIGILL;
5669f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
5671394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			(fp->seqstat & SEQSTAT_EXCAUSE));
568a5ac0129249611fc4a35e6d7cd9b8462d67e5798Sonic Zhang		CHK_DEBUGGER_TRAP_MAYBE();
5691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
5701394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
5711394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
572226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	BUG_ON(sig == 0);
573226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
57482bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger	/* If the fault was caused by a kernel thread, or interrupt handler
57582bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger	 * we will kernel panic, so the system reboots.
57682bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger	 */
57782bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger	if (kernel_mode_regs(fp) || (current && !current->mm)) {
57882bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		console_verbose();
57982bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger		oops_in_progress = 1;
58082bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger	}
58182bd1d7d45a69c54fb6beedb78ccb1c7d308dd93Mike Frysinger
582226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	if (sig != SIGTRAP) {
58315627bd35c6f02d159e0cb41d287dcba3a23a135Mike Frysinger		if (strerror)
58415627bd35c6f02d159e0cb41d287dcba3a23a135Mike Frysinger			verbose_printk(strerror);
58515627bd35c6f02d159e0cb41d287dcba3a23a135Mike Frysinger
58649dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		dump_bfin_process(fp);
587b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		dump_bfin_mem(fp);
58849dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		show_regs(fp);
589226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
590226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		/* Print out the trace buffer if it makes sense */
591226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
592226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
5939f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(KERN_NOTICE "No trace since you do not have "
594ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			       "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n\n");
595226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		else
596226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#endif
597226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			dump_bfin_trace_buffer();
598f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
599226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		if (oops_in_progress) {
600f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* Dump the current kernel stack */
601ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			verbose_printk(KERN_NOTICE "Kernel Stack\n");
602f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			show_stack(current, NULL);
603aee3a29240ad167ad7875d859506d8bb90431c70Robin Getz			print_modules();
604226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#ifndef CONFIG_ACCESS_CHECK
6059f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(KERN_EMERG "Please turn on "
60690c7f4686f82aef875aadf8e5c9c1a9465e5143bRobin Getz			       "CONFIG_ACCESS_CHECK\n");
607226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#endif
6081394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			panic("Kernel exception");
609f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		} else {
6104ee1c45337e7b529eed644c6f62399d797dcbc10Robin Getz#ifdef CONFIG_DEBUG_VERBOSE
6119f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			unsigned long *stack;
612f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* Dump the user space stack */
613f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			stack = (unsigned long *)rdusp();
6149f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(KERN_NOTICE "Userspace Stack\n");
615f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			show_stack(NULL, stack);
6169f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
617226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		}
6181394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
619fb322915a05804a3a153f714f2f08e4c32ce84c7Robin Getz
6206a01f230339321292cf065551f8cf55361052461Yi Li#ifdef CONFIG_IPIPE
6216a01f230339321292cf065551f8cf55361052461Yi Li	if (!ipipe_trap_notify(fp->seqstat & 0x3f, fp))
6226a01f230339321292cf065551f8cf55361052461Yi Li#endif
6236a01f230339321292cf065551f8cf55361052461Yi Li	{
6246a01f230339321292cf065551f8cf55361052461Yi Li		info.si_signo = sig;
6256a01f230339321292cf065551f8cf55361052461Yi Li		info.si_errno = 0;
6266a01f230339321292cf065551f8cf55361052461Yi Li		info.si_addr = (void __user *)fp->pc;
6276a01f230339321292cf065551f8cf55361052461Yi Li		force_sig_info(sig, &info, current);
6286a01f230339321292cf065551f8cf55361052461Yi Li	}
6291394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
6300e4edcf0b0f7d96c4be7788b13bee82e4d3ba0ceRobin Getz	if ((ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) ||
631f574a76a3b19848ac61814756716e26f85f2c3f7Robin Getz	    (ANOMALY_05000281 && trapnr == VEC_HWERR) ||
632f574a76a3b19848ac61814756716e26f85f2c3f7Robin Getz	    (ANOMALY_05000189 && (trapnr == VEC_CPLB_I_VL || trapnr == VEC_CPLB_VL)))
6330acad8dfee6bde7e246a95a52f864a8eee777ed8Robin Getz		fp->pc = SAFE_USER_INSTRUCTION;
6340acad8dfee6bde7e246a95a52f864a8eee777ed8Robin Getz
6356510a20e1b1a3a5703429a09d03adf44882ae373Mike Frysinger traps_done:
6361394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_restore(j);
6371394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
6381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
6391394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu/* Typical exception handling routines	*/
6401394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
641518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)
642518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
643f09630bff51daaf427968c61c0f2370c64148e06Robin Getz/*
644f09630bff51daaf427968c61c0f2370c64148e06Robin Getz * Similar to get_user, do some address checking, then dereference
645f09630bff51daaf427968c61c0f2370c64148e06Robin Getz * Return true on sucess, false on bad address
646f09630bff51daaf427968c61c0f2370c64148e06Robin Getz */
6479f06c38fb230720371397a57faa24aa6e31b2c87Robin Getzstatic bool get_instruction(unsigned short *val, unsigned short *address)
648f09630bff51daaf427968c61c0f2370c64148e06Robin Getz{
649e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger	unsigned long addr = (unsigned long)address;
650f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
651f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/* Check for odd addresses */
652f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (addr & 0x1)
653f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return false;
654f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
655e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger	/* MMR region will never have instructions */
656e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger	if (addr >= SYSMMR_BASE)
657f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return false;
658f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
659e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger	switch (bfin_mem_access_type(addr, 2)) {
660e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger		case BFIN_MEM_ACCESS_CORE:
661e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger		case BFIN_MEM_ACCESS_CORE_ONLY:
662e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger			*val = *address;
663e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger			return true;
664e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger		case BFIN_MEM_ACCESS_DMA:
665e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger			dma_memcpy(val, address, 2);
666e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger			return true;
667e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger		case BFIN_MEM_ACCESS_ITEST:
668e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger			isram_memcpy(val, address, 2);
669e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger			return true;
670e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger		default: /* invalid access */
671e56e03b0cfeb997a4be9ad874c193824364942e0Mike Frysinger			return false;
672f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	}
673f09630bff51daaf427968c61c0f2370c64148e06Robin Getz}
674f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
67536f649a55aa3ad1e2196403ba95a652f9900bc50Mike Frysinger/*
676d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz * decode the instruction if we are printing out the trace, as it
677d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz * makes things easier to follow, without running it through objdump
678d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz * These are the normal instructions which cause change of flow, which
679d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz * would be at the source of the trace buffer
680d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz */
68136f649a55aa3ad1e2196403ba95a652f9900bc50Mike Frysinger#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_BFIN_HWTRACE_ON)
6829f06c38fb230720371397a57faa24aa6e31b2c87Robin Getzstatic void decode_instruction(unsigned short *address)
683d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz{
684d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	unsigned short opcode;
685d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz
686d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	if (get_instruction(&opcode, address)) {
687d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		if (opcode == 0x0010)
6889f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("RTS");
689d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode == 0x0011)
6909f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("RTI");
691d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode == 0x0012)
6929f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("RTX");
6930be58939146f28394a04b61fec7e0676cdafa47eRobin Getz		else if (opcode == 0x0013)
6940be58939146f28394a04b61fec7e0676cdafa47eRobin Getz			verbose_printk("RTN");
6950be58939146f28394a04b61fec7e0676cdafa47eRobin Getz		else if (opcode == 0x0014)
6960be58939146f28394a04b61fec7e0676cdafa47eRobin Getz			verbose_printk("RTE");
6970be58939146f28394a04b61fec7e0676cdafa47eRobin Getz		else if (opcode == 0x0025)
6980be58939146f28394a04b61fec7e0676cdafa47eRobin Getz			verbose_printk("EMUEXCPT");
6990be58939146f28394a04b61fec7e0676cdafa47eRobin Getz		else if (opcode == 0x0040 && opcode <= 0x0047)
7000be58939146f28394a04b61fec7e0676cdafa47eRobin Getz			verbose_printk("STI R%i", opcode & 7);
701d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x0050 && opcode <= 0x0057)
7029f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("JUMP (P%i)", opcode & 7);
703d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x0060 && opcode <= 0x0067)
7049f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("CALL (P%i)", opcode & 7);
705d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x0070 && opcode <= 0x0077)
7069f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("CALL (PC+P%i)", opcode & 7);
707d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x0080 && opcode <= 0x0087)
7089f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("JUMP (PC+P%i)", opcode & 7);
7090be58939146f28394a04b61fec7e0676cdafa47eRobin Getz		else if (opcode >= 0x0090 && opcode <= 0x009F)
7100be58939146f28394a04b61fec7e0676cdafa47eRobin Getz			verbose_printk("RAISE 0x%x", opcode & 0xF);
7110be58939146f28394a04b61fec7e0676cdafa47eRobin Getz		else if (opcode >= 0x00A0 && opcode <= 0x00AF)
7120be58939146f28394a04b61fec7e0676cdafa47eRobin Getz			verbose_printk("EXCPT 0x%x", opcode & 0xF);
713d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF))
7149f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("IF !CC JUMP");
715d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff))
7169f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("IF CC JUMP");
717d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x2000 && opcode <= 0x2fff)
7189f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("JUMP.S");
719d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0xe080 && opcode <= 0xe0ff)
7209f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("LSETUP");
721d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0xe200 && opcode <= 0xe2ff)
7229f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("JUMP.L");
723d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0xe300 && opcode <= 0xe3ff)
7249f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("CALL pcrel");
725d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else
7269f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("0x%04x", opcode);
727d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	}
728d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz
729d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz}
7309f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
731d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz
7321394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid dump_bfin_trace_buffer(void)
7331394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
7349f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#ifdef CONFIG_DEBUG_VERBOSE
735518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
736518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	int tflags, i = 0;
737226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	char buf[150];
738d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	unsigned short *addr;
739518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
740518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	int j, index;
741518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
742518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
7431394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_save(tflags);
7441394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
745226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE "Hardware Trace:\n");
746518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
747d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
748d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	printk(KERN_NOTICE "WARNING: Expanded trace turned on - can not trace exceptions\n");
749d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz#endif
750d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz
7511394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
752518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
753226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			decode_address(buf, (unsigned long)bfin_read_TBUF());
754226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
755f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			addr = (unsigned short *)bfin_read_TBUF();
756f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			decode_address(buf, (unsigned long)addr);
757f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk(KERN_NOTICE "     Source : %s ", buf);
758d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			decode_instruction(addr);
759f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk("\n");
7601394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		}
7611394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
7621394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
763518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
764518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	if (trace_buff_offset)
765d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		index = trace_buff_offset / 4;
766518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	else
767518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		index = EXPAND_LEN;
768518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
769518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128;
770518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	while (j) {
771226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		decode_address(buf, software_trace_buff[index]);
772226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
773518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		index -= 1;
774518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		if (index < 0 )
775518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz			index = EXPAND_LEN;
776226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		decode_address(buf, software_trace_buff[index]);
777d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		printk(KERN_NOTICE "     Source : %s ", buf);
778d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		decode_instruction((unsigned short *)software_trace_buff[index]);
779d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		printk("\n");
780518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		index -= 1;
781518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		if (index < 0)
782518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz			index = EXPAND_LEN;
783518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		j--;
784518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		i++;
785518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	}
786518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
787518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
7881394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_restore(tflags);
789518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
7909f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
7911394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
7921394f03221790a988afc3e4b3cb79f2e477246a9Bryan WuEXPORT_SYMBOL(dump_bfin_trace_buffer);
7931394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
79470f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger#ifdef CONFIG_BUG
79570f12567ac9aca9c2f242ae060d7de245904889eMike Frysingerint is_valid_bugaddr(unsigned long addr)
79670f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger{
79770f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger	unsigned short opcode;
79870f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger
79970f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger	if (!get_instruction(&opcode, (unsigned short *)addr))
80070f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger		return 0;
80170f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger
80270f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger	return opcode == BFIN_BUG_OPCODE;
80370f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger}
80470f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger#endif
80570f12567ac9aca9c2f242ae060d7de245904889eMike Frysinger
806f09630bff51daaf427968c61c0f2370c64148e06Robin Getz/*
807f09630bff51daaf427968c61c0f2370c64148e06Robin Getz * Checks to see if the address pointed to is either a
808f09630bff51daaf427968c61c0f2370c64148e06Robin Getz * 16-bit CALL instruction, or a 32-bit CALL instruction
809f09630bff51daaf427968c61c0f2370c64148e06Robin Getz */
8109f06c38fb230720371397a57faa24aa6e31b2c87Robin Getzstatic bool is_bfin_call(unsigned short *addr)
8111394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
812f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	unsigned short opcode = 0, *ins_addr;
813f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	ins_addr = (unsigned short *)addr;
8141394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
815f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (!get_instruction(&opcode, ins_addr))
816f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return false;
8171394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
818f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if ((opcode >= 0x0060 && opcode <= 0x0067) ||
819f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (opcode >= 0x0070 && opcode <= 0x0077))
820f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return true;
821f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
822f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	ins_addr--;
823f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (!get_instruction(&opcode, ins_addr))
824f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return false;
8251394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
826f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (opcode >= 0xE300 && opcode <= 0xE3FF)
827f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return true;
828f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
829f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	return false;
830f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
831f09630bff51daaf427968c61c0f2370c64148e06Robin Getz}
8329f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz
8331394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid show_stack(struct task_struct *task, unsigned long *stack)
8341394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
8359f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#ifdef CONFIG_PRINTK
836f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	unsigned int *addr, *endstack, *fp = 0, *frame;
837f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	unsigned short *ins_addr;
838f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	char buf[150];
839f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	unsigned int i, j, ret_addr, frame_no = 0;
8401394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
841f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/*
842f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * If we have been passed a specific stack, use that one otherwise
843f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 *    if we have been passed a task structure, use that, otherwise
844f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 *    use the stack of where the variable "stack" exists
8451394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 */
8461394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
847f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (stack == NULL) {
848f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (task) {
849f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* We know this is a kernel stack, so this is the start/end */
8501394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			stack = (unsigned long *)task->thread.ksp;
851f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
852f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		} else {
853f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* print out the existing stack info */
8541394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			stack = (unsigned long *)&stack;
855f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
856f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		}
857f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	} else
858f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
859f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
8609f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	printk(KERN_NOTICE "Stack info:\n");
861f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	decode_address(buf, (unsigned int)stack);
8629f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
8639f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz
864a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz	if (!access_ok(VERIFY_READ, stack, (unsigned int)endstack - (unsigned int)stack)) {
865a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz		printk(KERN_NOTICE "Invalid stack pointer\n");
866a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz		return;
867a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz	}
868a0cab65642813b7990e1b4b2ab6ad92e171571f4Robin Getz
869f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/* First thing is to look for a frame pointer */
870881eb621fc191e58fa638c533073683be2b63c24Jie Zhang	for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {
871f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (*addr & 0x1)
872f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			continue;
873f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		ins_addr = (unsigned short *)*addr;
874f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		ins_addr--;
875f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (is_bfin_call(ins_addr))
876f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			fp = addr - 1;
877f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
878f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (fp) {
879f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* Let's check to see if it is a frame pointer */
880881eb621fc191e58fa638c533073683be2b63c24Jie Zhang			while (fp >= (addr - 1) && fp < endstack
881881eb621fc191e58fa638c533073683be2b63c24Jie Zhang			       && fp && ((unsigned int) fp & 0x3) == 0)
882f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				fp = (unsigned int *)*fp;
883f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			if (fp == 0 || fp == endstack) {
884f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				fp = addr - 1;
885f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				break;
886f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			}
887f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			fp = 0;
888f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		}
8891394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
890f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (fp) {
891f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		frame = fp;
892b339dc79b49841eff0aeecfc444cbb7b26007649Jie Zhang		printk(KERN_NOTICE " FP: (0x%p)\n", fp);
893f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	} else
894f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		frame = 0;
8951394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
896f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/*
897f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * Now that we think we know where things are, we
898f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * walk the stack again, this time printing things out
899f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * incase there is no frame pointer, we still look for
900f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * valid return addresses
901f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 */
9021394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
903f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/* First time print out data, next time, print out symbols */
904f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	for (j = 0; j <= 1; j++) {
905f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (j)
906f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk(KERN_NOTICE "Return addresses in stack:\n");
907f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		else
908f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);
909f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
910f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		fp = frame;
911f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		frame_no = 0;
912f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
913f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
914407505dc01ac2b4f2944cd3c6a0c02473ffb869eSonic Zhang		     addr < endstack; addr++, i++) {
915f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
916f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			ret_addr = 0;
917f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			if (!j && i % 8 == 0)
918ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches				printk(KERN_NOTICE "%p:",addr);
919f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
920f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* if it is an odd address, or zero, just skip it */
921f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			if (*addr & 0x1 || !*addr)
922f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				goto print;
923f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
924f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			ins_addr = (unsigned short *)*addr;
925f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
926f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* Go back one instruction, and see if it is a CALL */
927f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			ins_addr--;
928f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			ret_addr = is_bfin_call(ins_addr);
929f09630bff51daaf427968c61c0f2370c64148e06Robin Getz print:
930f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			if (!j && stack == (unsigned long *)addr)
931f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				printk("[%08x]", *addr);
932f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			else if (ret_addr)
933f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				if (j) {
934f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					decode_address(buf, (unsigned int)*addr);
935f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					if (frame == addr) {
936f09630bff51daaf427968c61c0f2370c64148e06Robin Getz						printk(KERN_NOTICE "   frame %2i : %s\n", frame_no, buf);
937f09630bff51daaf427968c61c0f2370c64148e06Robin Getz						continue;
938f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					}
939f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					printk(KERN_NOTICE "    address : %s\n", buf);
940f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				} else
941f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					printk("<%08x>", *addr);
942f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			else if (fp == addr) {
943f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				if (j)
944f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					frame = addr+1;
945f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				else
946f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					printk("(%08x)", *addr);
947f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
948f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				fp = (unsigned int *)*addr;
949f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				frame_no++;
950f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
951f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			} else if (!j)
952f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				printk(" %08x ", *addr);
953f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		}
954f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (!j)
955f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk("\n");
9561394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
9579f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
9581394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
959bc569f1a77199926be97ba6266dbea27768264dfPhilippe GerumEXPORT_SYMBOL(show_stack);
9601394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
9611394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid dump_stack(void)
9621394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
9631394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	unsigned long stack;
964518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
9651394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	int tflags;
966518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
9671394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_save(tflags);
9681394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	dump_bfin_trace_buffer();
9691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	show_stack(current, &stack);
9701394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_restore(tflags);
9711394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
9721394f03221790a988afc3e4b3cb79f2e477246a9Bryan WuEXPORT_SYMBOL(dump_stack);
9731394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
97449dce9124b41984bf1e918847bc17929c2e8f80fMike Frysingervoid dump_bfin_process(struct pt_regs *fp)
9751394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
9769f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#ifdef CONFIG_DEBUG_VERBOSE
97749dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	/* We should be able to look at fp->ipend, but we don't push it on the
97849dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	 * stack all the time, so do this until we fix that */
97949dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	unsigned int context = bfin_read_IPEND();
98049dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger
98149dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	if (oops_in_progress)
9829f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_EMERG "Kernel OOPS in progress\n");
98349dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger
984b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)
9859f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "HW Error context\n");
986b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	else if (context & 0x0020)
9879f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "Deferred Exception context\n");
98849dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	else if (context & 0x3FC0)
9899f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "Interrupt context\n");
99049dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	else if (context & 0x4000)
9919f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "Deferred Interrupt context\n");
99249dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	else if (context & 0x8000)
9939f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "Kernel process context\n");
99449dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger
9959a62ca40fd793742f92565104c6b44319af8c282Robin Getz	/* Because we are crashing, and pointers could be bad, we check things
9969a62ca40fd793742f92565104c6b44319af8c282Robin Getz	 * pretty closely before we use them
9979a62ca40fd793742f92565104c6b44319af8c282Robin Getz	 */
9987f1c906808a36630990d83d872935c079b76595bRobin Getz	if ((unsigned long)current >= FIXED_CODE_START &&
9997f1c906808a36630990d83d872935c079b76595bRobin Getz	    !((unsigned long)current & 0x3) && current->pid) {
10009f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n");
10019a62ca40fd793742f92565104c6b44319af8c282Robin Getz		if (current->comm >= (char *)FIXED_CODE_START)
10029f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n",
10039a62ca40fd793742f92565104c6b44319af8c282Robin Getz				current->comm, current->pid);
10049a62ca40fd793742f92565104c6b44319af8c282Robin Getz		else
10059f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(KERN_NOTICE "COMM= invalid\n");
10069a62ca40fd793742f92565104c6b44319af8c282Robin Getz
10078f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
10089a62ca40fd793742f92565104c6b44319af8c282Robin Getz		if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
1009ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			verbose_printk(KERN_NOTICE
1010ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches				"TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
1011ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches				" BSS = 0x%p-0x%p  USER-STACK = 0x%p\n\n",
10129a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->start_code,
10139a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->end_code,
10149a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->start_data,
10159a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->end_data,
10169a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->end_data,
10179a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->brk,
10189a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->start_stack);
10199a62ca40fd793742f92565104c6b44319af8c282Robin Getz		else
10209f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(KERN_NOTICE "invalid mm\n");
102149dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	} else
1022ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches		verbose_printk(KERN_NOTICE
1023ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			       "No Valid process in current context\n");
10249f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
102549dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger}
1026226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
1027b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getzvoid dump_bfin_mem(struct pt_regs *fp)
102849dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger{
10299f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#ifdef CONFIG_DEBUG_VERBOSE
1030b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	unsigned short *addr, *erraddr, val = 0, err = 0;
1031b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	char sti = 0, buf[6];
10321394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
10335d750b9e4f6ca7d366b4954517ff8be9ee07e1bfBernd Schmidt	erraddr = (void *)fp->pc;
1034b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
10359f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
1036b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
1037b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10;
1038b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	     addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
1039b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	     addr++) {
1040b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		if (!((unsigned long)addr & 0xF))
1041ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			verbose_printk(KERN_NOTICE "0x%p: ", addr);
1042b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
10437d98c881eed9e19767bc77ffd650d0041b4f41ecRobin Getz		if (!get_instruction(&val, addr)) {
1044b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz				val = 0;
1045b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz				sprintf(buf, "????");
1046b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		} else
1047b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			sprintf(buf, "%04x", val);
1048b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
1049b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		if (addr == erraddr) {
10509f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("[%s]", buf);
1051b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			err = val;
1052b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		} else
10539f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(" %s ", buf);
1054b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
1055b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		/* Do any previous instructions turn on interrupts? */
1056b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		if (addr <= erraddr &&				/* in the past */
1057b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		    ((val >= 0x0040 && val <= 0x0047) ||	/* STI instruction */
1058b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		      val == 0x017b))				/* [SP++] = RETI */
1059b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			sti = 1;
1060b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	}
1061b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
10629f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk("\n");
1063b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
1064b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	/* Hardware error interrupts can be deferred */
1065b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR &&
1066b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	    oops_in_progress)){
10679f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
10681394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifndef CONFIG_DEBUG_HWERR
1069ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches		verbose_printk(KERN_NOTICE
1070ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches"The remaining message may be meaningless\n"
1071ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches"You should enable CONFIG_DEBUG_HWERR to get a better idea where it came from\n");
1072b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz#else
1073b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		/* If we are handling only one peripheral interrupt
1074b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		 * and current mm and pid are valid, and the last error
1075b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		 * was in that user space process's text area
1076b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		 * print it out - because that is where the problem exists
1077b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		 */
1078b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		if ((!(((fp)->ipend & ~0x30) & (((fp)->ipend & ~0x30) - 1))) &&
1079b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		     (current->pid && current->mm)) {
1080b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			/* And the last RETI points to the current userspace context */
1081b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			if ((fp + 1)->pc >= current->mm->start_code &&
1082b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			    (fp + 1)->pc <= current->mm->end_code) {
10839f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz				verbose_printk(KERN_NOTICE "It might be better to look around here : \n");
10849f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz				verbose_printk(KERN_NOTICE "-------------------------------------------\n");
1085b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz				show_regs(fp + 1);
10869f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz				verbose_printk(KERN_NOTICE "-------------------------------------------\n");
1087b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			}
10881394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		}
1089b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz#endif
1090b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	}
10919f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
109249dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger}
109349dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger
109449dce9124b41984bf1e918847bc17929c2e8f80fMike Frysingervoid show_regs(struct pt_regs *fp)
109549dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger{
10969f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#ifdef CONFIG_DEBUG_VERBOSE
109749dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	char buf [150];
1098d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	struct irqaction *action;
1099d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	unsigned int i;
11002f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz	unsigned long flags = 0;
11018f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang	unsigned int cpu = smp_processor_id();
11022f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz	unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
1103226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
11049ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz	verbose_printk(KERN_NOTICE "\n");
11059ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz	if (CPUID != bfin_cpuid())
11069ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz		verbose_printk(KERN_NOTICE "Compiled for cpu family 0x%04x (Rev %d), "
11079ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz			"but running on:0x%04x (Rev %d)\n",
11089ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz			CPUID, bfin_compiled_revid(), bfin_cpuid(), bfin_revid());
11099ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz
11109ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz	verbose_printk(KERN_NOTICE "ADSP-%s-0.%d",
11119ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz		CPU, bfin_compiled_revid());
11129ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz
11139ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz	if (bfin_compiled_revid() !=  bfin_revid())
11149ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz		verbose_printk("(Detected 0.%d)", bfin_revid());
11159ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz
11169ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz	verbose_printk(" %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n",
11179ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz		get_cclk()/1000000, get_sclk()/1000000,
11189ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz#ifdef CONFIG_MPU
11199ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz		"mpu on"
11209ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz#else
11219ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz		"mpu off"
11229ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz#endif
11239ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz		);
11249ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz
11259ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz	verbose_printk(KERN_NOTICE "%s", linux_banner);
11269ba3c24f10c948dadac2ca91ed714dfbcedd61caRobin Getz
1127ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz	verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", print_tainted());
1128ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz	verbose_printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  IMASK: %04lx  SYSCFG: %04lx\n",
1129ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz		(long)fp->seqstat, fp->ipend, cpu_pda[smp_processor_id()].ex_imask, fp->syscfg);
1130ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz	if (fp->ipend & EVT_IRPTEN)
1131ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz		verbose_printk(KERN_NOTICE "  Global Interrupts Disabled (IPEND[4])\n");
1132ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz	if (!(cpu_pda[smp_processor_id()].ex_imask & (EVT_IVG13 | EVT_IVG12 | EVT_IVG11 |
1133ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz			EVT_IVG10 | EVT_IVG9 | EVT_IVG8 | EVT_IVG7 | EVT_IVTMR)))
1134ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz		verbose_printk(KERN_NOTICE "  Peripheral interrupts masked off\n");
1135ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz	if (!(cpu_pda[smp_processor_id()].ex_imask & (EVT_IVG15 | EVT_IVG14)))
1136ae4f073c40bf677b03826262e6022b4a251fe437Robin Getz		verbose_printk(KERN_NOTICE "  Kernel interrupts masked off\n");
11371d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz	if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
11389f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
11391d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz			(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
11401d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz#ifdef EBIU_ERRMST
11411d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz		/* If the error was from the EBIU, print it out */
11421d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz		if (bfin_read_EBIU_ERRMST() & CORE_ERROR) {
11439f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(KERN_NOTICE "  EBIU Error Reason  : 0x%04x\n",
11441d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz				bfin_read_EBIU_ERRMST());
11459f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(KERN_NOTICE "  EBIU Error Address : 0x%08x\n",
11461d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz				bfin_read_EBIU_ERRADD());
11471d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz		}
11481d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz#endif
11491d5ff7e27d2ca30cd3f61afd353b03dd67330818Robin Getz	}
11509f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE "  EXCAUSE   : 0x%lx\n",
115113fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		fp->seqstat & SEQSTAT_EXCAUSE);
11522f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz	for (i = 2; i <= 15 ; i++) {
1153d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz		if (fp->ipend & (1 << i)) {
11542f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz			if (i != 4) {
11552f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz				decode_address(buf, bfin_read32(EVT0 + 4*i));
11562f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz				verbose_printk(KERN_NOTICE "  physical IVG%i asserted : %s\n", i, buf);
11572f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz			} else
11582f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz				verbose_printk(KERN_NOTICE "  interrupts disabled\n");
1159d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz		}
1160d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	}
1161d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz
1162d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	/* if no interrupts are going off, don't print this out */
1163d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	if (fp->ipend & ~0x3F) {
1164d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz		for (i = 0; i < (NR_IRQS - 1); i++) {
11652f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz			if (!in_atomic)
11662f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz				spin_lock_irqsave(&irq_desc[i].lock, flags);
11672f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz
1168d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			action = irq_desc[i].action;
1169d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			if (!action)
1170d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz				goto unlock;
1171d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz
1172d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			decode_address(buf, (unsigned int)action->handler);
11739f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk(KERN_NOTICE "  logical irq %3d mapped  : %s", i, buf);
1174d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			for (action = action->next; action; action = action->next) {
1175d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz				decode_address(buf, (unsigned int)action->handler);
11769f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz				verbose_printk(", %s", buf);
1177d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			}
11789f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz			verbose_printk("\n");
1179d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getzunlock:
11802f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz			if (!in_atomic)
11812f95d5bd84bfbe8cf62cb1c4306354cfc139370bRobin Getz				spin_unlock_irqrestore(&irq_desc[i].lock, flags);
1182d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz		}
1183d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	}
1184c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz
1185226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	decode_address(buf, fp->rete);
11869f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " RETE: %s\n", buf);
1187226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	decode_address(buf, fp->retn);
11889f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " RETN: %s\n", buf);
1189226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	decode_address(buf, fp->retx);
11909f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " RETX: %s\n", buf);
1191226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	decode_address(buf, fp->rets);
11929f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " RETS: %s\n", buf);
119349dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	decode_address(buf, fp->pc);
11949f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " PC  : %s\n", buf);
1195c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz
119613fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
119713fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz	    (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
11988f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
11999f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
12008f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
12019f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz		verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
1202226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	}
1203226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
1204ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches	verbose_printk(KERN_NOTICE "PROCESSOR STATE:\n");
12059f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
1206c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->r0, fp->r1, fp->r2, fp->r3);
12079f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",
1208c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->r4, fp->r5, fp->r6, fp->r7);
12099f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " P0 : %08lx    P1 : %08lx    P2 : %08lx    P3 : %08lx\n",
1210c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->p0, fp->p1, fp->p2, fp->p3);
12119f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " P4 : %08lx    P5 : %08lx    FP : %08lx    SP : %08lx\n",
1212226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		fp->p4, fp->p5, fp->fp, (long)fp);
12139f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " LB0: %08lx    LT0: %08lx    LC0: %08lx\n",
1214c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->lb0, fp->lt0, fp->lc0);
12159f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " LB1: %08lx    LT1: %08lx    LC1: %08lx\n",
1216c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->lb1, fp->lt1, fp->lc1);
12179f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " B0 : %08lx    L0 : %08lx    M0 : %08lx    I0 : %08lx\n",
1218c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->b0, fp->l0, fp->m0, fp->i0);
12199f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " B1 : %08lx    L1 : %08lx    M1 : %08lx    I1 : %08lx\n",
1220c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->b1, fp->l1, fp->m1, fp->i1);
12219f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " B2 : %08lx    L2 : %08lx    M2 : %08lx    I2 : %08lx\n",
1222c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->b2, fp->l2, fp->m2, fp->i2);
12239f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE " B3 : %08lx    L3 : %08lx    M3 : %08lx    I3 : %08lx\n",
1224c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->b3, fp->l3, fp->m3, fp->i3);
12259f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE "A0.w: %08lx   A0.x: %08lx   A1.w: %08lx   A1.x: %08lx\n",
1226226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		fp->a0w, fp->a0x, fp->a1w, fp->a1x);
1227c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz
12289f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE "USP : %08lx  ASTAT: %08lx\n",
1229c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		rdusp(), fp->astat);
12301394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
12319f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz	verbose_printk(KERN_NOTICE "\n");
12329f06c38fb230720371397a57faa24aa6e31b2c87Robin Getz#endif
12331394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
12341394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
12351394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
12361394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuasmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
12371394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
12381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
12398f65873e47784a390949f0d61e5692dbf2a8253eGraf Yangstatic DEFINE_SPINLOCK(bfin_spinlock_lock);
12408f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang
12418f65873e47784a390949f0d61e5692dbf2a8253eGraf Yangasmlinkage int sys_bfin_spinlock(int *p)
12421394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
12438f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang	int ret, tmp = 0;
12441394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
12458f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang	spin_lock(&bfin_spinlock_lock);	/* This would also hold kernel preemption. */
12468f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang	ret = get_user(tmp, p);
12478f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang	if (likely(ret == 0)) {
12488f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		if (unlikely(tmp))
12491394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			ret = 1;
12508f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang		else
12518f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang			put_user(1, p);
12521394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
12538f65873e47784a390949f0d61e5692dbf2a8253eGraf Yang	spin_unlock(&bfin_spinlock_lock);
12541394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	return ret;
12551394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
12561394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
12571ffe6646babf8471714e649849ec2c9662bf410cMike Frysingerint bfin_request_exception(unsigned int exception, void (*handler)(void))
12581ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger{
12591ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	void (*curr_handler)(void);
12601ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12611ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	if (exception > 0x3F)
12621ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger		return -EINVAL;
12631ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12641ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	curr_handler = ex_table[exception];
12651ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12661ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	if (curr_handler != ex_replaceable)
12671ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger		return -EBUSY;
12681ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12691ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	ex_table[exception] = handler;
12701ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12711ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	return 0;
12721ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger}
12731ffe6646babf8471714e649849ec2c9662bf410cMike FrysingerEXPORT_SYMBOL(bfin_request_exception);
12741ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12751ffe6646babf8471714e649849ec2c9662bf410cMike Frysingerint bfin_free_exception(unsigned int exception, void (*handler)(void))
12761ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger{
12771ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	void (*curr_handler)(void);
12781ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12791ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	if (exception > 0x3F)
12801ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger		return -EINVAL;
12811ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12821ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	curr_handler = ex_table[exception];
12831ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12841ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	if (curr_handler != handler)
12851ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger		return -EBUSY;
12861ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12871ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	ex_table[exception] = ex_replaceable;
12881ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12891ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	return 0;
12901ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger}
12911ffe6646babf8471714e649849ec2c9662bf410cMike FrysingerEXPORT_SYMBOL(bfin_free_exception);
12921ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
12931394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid panic_cplb_error(int cplb_panic, struct pt_regs *fp)
12941394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
12951394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	switch (cplb_panic) {
12961394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case CPLB_NO_UNLOCKED:
12971394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		printk(KERN_EMERG "All CPLBs are locked\n");
12981394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
12991394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case CPLB_PROT_VIOL:
13001394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		return;
13011394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case CPLB_NO_ADDR_MATCH:
13021394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		return;
13031394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case CPLB_UNKNOWN_ERR:
13041394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		printk(KERN_EMERG "Unknown CPLB Exception\n");
13051394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
13061394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
13071394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1308226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	oops_in_progress = 1;
1309226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
131049dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	dump_bfin_process(fp);
1311b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	dump_bfin_mem(fp);
131249dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	show_regs(fp);
13131394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	dump_stack();
1314d8804adf52f5991388fa9af77428e4cc7768059dMike Frysinger	panic("Unrecoverable event");
13151394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
1316