traps.c revision f4585a08479a730fb809606b8ee327a5398c117c
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
301f83b8f148a1eb967d2a628cbb741cd56fb54572Mike Frysinger#include <linux/uaccess.h>
311f83b8f148a1eb967d2a628cbb741cd56fb54572Mike Frysinger#include <linux/interrupt.h>
321f83b8f148a1eb967d2a628cbb741cd56fb54572Mike Frysinger#include <linux/module.h>
331f83b8f148a1eb967d2a628cbb741cd56fb54572Mike Frysinger#include <linux/kallsyms.h>
34d31c5ab147e0b17b9ec0daa5e4d1fc0bd6b19974Bryan Wu#include <linux/fs.h>
351394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#include <asm/traps.h>
361394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#include <asm/cacheflush.h>
37f4585a08479a730fb809606b8ee327a5398c117cMike Frysinger#include <asm/cplb.h>
381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#include <asm/blackfin.h>
391394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#include <asm/irq_handler.h>
40d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz#include <linux/irq.h>
41669b792c77bbc30e9f4d9c95dbc918dc348c49c2Robin Getz#include <asm/trace.h>
42226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#include <asm/fixed_code.h>
43b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz#include <asm/dma.h>
441394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
451394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_KGDB
461394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu# include <linux/debugger.h>
471394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu# include <linux/kgdb.h>
48226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
49226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz# define CHK_DEBUGGER_TRAP() \
50226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	do { \
51226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \
52226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	} while (0)
53226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz# define CHK_DEBUGGER_TRAP_MAYBE() \
54226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	do { \
55226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		if (kgdb_connected) \
56226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			CHK_DEBUGGER_TRAP(); \
57226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	} while (0)
58226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#else
59226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz# define CHK_DEBUGGER_TRAP() do { } while (0)
60226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
611394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
621394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
631394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu/* Initiate the event table handler */
641394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid __init trap_init(void)
651394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
661394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	CSYNC();
671394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	bfin_write_EVT3(trap);
681394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	CSYNC();
691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
701394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
71bd628bd085c459838d38f93f2f154f1a2e019e48Mike Frysingerunsigned long saved_icplb_fault_addr, saved_dcplb_fault_addr;
725d750b9e4f6ca7d366b4954517ff8be9ee07e1bfBernd Schmidt
73226eb1ef523a33c66193bc319a92c647e47311d4Robin Getzstatic void decode_address(char *buf, unsigned long address)
741394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
751394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	struct vm_list_struct *vml;
761394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	struct task_struct *p;
771394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	struct mm_struct *mm;
78885be03b069131d242506f0f717d38659b2bdb6cRobin Getz	unsigned long flags, offset;
79904656cda10ce985e6bc8b16488b58236eaec8e2Robin Getz	unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
801394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
811394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_KALLSYMS
828a0e6656030ffe9bcb81b725e956917bafc7522dMike Frysinger	unsigned long symsize;
831394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	const char *symname;
841394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	char *modname;
851394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	char *delim = ":";
861394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	char namebuf[128];
871394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
881394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* look up the address and see if we are in kernel space */
891394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
901394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
911394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	if (symname) {
921394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		/* yeah! kernel space! */
931394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		if (!modname)
941394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			modname = delim = "";
95226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }",
961f83b8f148a1eb967d2a628cbb741cd56fb54572Mike Frysinger		              (void *)address, delim, modname, delim, symname,
971394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		              (unsigned long)offset);
98885be03b069131d242506f0f717d38659b2bdb6cRobin Getz		return;
991394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1001394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
1011394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
1021394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
103226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	/* Problem in fixed code section? */
104226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	if (address >= FIXED_CODE_START && address < FIXED_CODE_END) {
105226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address);
106226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		return;
107226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	}
108226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
109226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	/* Problem somewhere before the kernel start address */
110226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	if (address < CONFIG_BOOT_LOAD) {
111226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address);
112226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		return;
113226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	}
114226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
1151394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* looks like we're off in user-land, so let's walk all the
1161394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * mappings of all our processes and see if we can't be a whee
1171394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * bit more specific
1181394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 */
119885be03b069131d242506f0f717d38659b2bdb6cRobin Getz	write_lock_irqsave(&tasklist_lock, flags);
1201394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	for_each_process(p) {
121904656cda10ce985e6bc8b16488b58236eaec8e2Robin Getz		mm = (in_atomic ? p->mm : get_task_mm(p));
1221394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		if (!mm)
1231394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			continue;
1241394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1251394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		vml = mm->context.vmlist;
1261394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		while (vml) {
1271394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			struct vm_area_struct *vma = vml->vma;
1281394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1291394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			if (address >= vma->vm_start && address < vma->vm_end) {
130cf28b4863f9ee8f122e8ff3ac0d403e07ba9c6d9Jan Blunck				char _tmpbuf[256];
1311394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu				char *name = p->comm;
1321394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu				struct file *file = vma->vm_file;
133cf28b4863f9ee8f122e8ff3ac0d403e07ba9c6d9Jan Blunck
134cf28b4863f9ee8f122e8ff3ac0d403e07ba9c6d9Jan Blunck				if (file)
135cf28b4863f9ee8f122e8ff3ac0d403e07ba9c6d9Jan Blunck					name = d_path(&file->f_path, _tmpbuf,
136cf28b4863f9ee8f122e8ff3ac0d403e07ba9c6d9Jan Blunck						      sizeof(_tmpbuf));
1371394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1388a0e6656030ffe9bcb81b725e956917bafc7522dMike Frysinger				/* FLAT does not have its text aligned to the start of
1398a0e6656030ffe9bcb81b725e956917bafc7522dMike Frysinger				 * the map while FDPIC ELF does ...
1408a0e6656030ffe9bcb81b725e956917bafc7522dMike Frysinger				 */
1417f1c906808a36630990d83d872935c079b76595bRobin Getz
1427f1c906808a36630990d83d872935c079b76595bRobin Getz				/* before we can check flat/fdpic, we need to
1437f1c906808a36630990d83d872935c079b76595bRobin Getz				 * make sure current is valid
1447f1c906808a36630990d83d872935c079b76595bRobin Getz				 */
1457f1c906808a36630990d83d872935c079b76595bRobin Getz				if ((unsigned long)current >= FIXED_CODE_START &&
1467f1c906808a36630990d83d872935c079b76595bRobin Getz				    !((unsigned long)current & 0x3)) {
1477f1c906808a36630990d83d872935c079b76595bRobin Getz					if (current->mm &&
1487f1c906808a36630990d83d872935c079b76595bRobin Getz					    (address > current->mm->start_code) &&
1497f1c906808a36630990d83d872935c079b76595bRobin Getz					    (address < current->mm->end_code))
1507f1c906808a36630990d83d872935c079b76595bRobin Getz						offset = address - current->mm->start_code;
1517f1c906808a36630990d83d872935c079b76595bRobin Getz					else
1527f1c906808a36630990d83d872935c079b76595bRobin Getz						offset = (address - vma->vm_start) +
1537f1c906808a36630990d83d872935c079b76595bRobin Getz							 (vma->vm_pgoff << PAGE_SHIFT);
1547f1c906808a36630990d83d872935c079b76595bRobin Getz
1557f1c906808a36630990d83d872935c079b76595bRobin Getz					sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
1567f1c906808a36630990d83d872935c079b76595bRobin Getz						(void *)address, name, offset);
1577f1c906808a36630990d83d872935c079b76595bRobin Getz				} else
1587f1c906808a36630990d83d872935c079b76595bRobin Getz					sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
1597f1c906808a36630990d83d872935c079b76595bRobin Getz						(void *)address, name,
1607f1c906808a36630990d83d872935c079b76595bRobin Getz						vma->vm_start, vma->vm_end);
1617f1c906808a36630990d83d872935c079b76595bRobin Getz
162904656cda10ce985e6bc8b16488b58236eaec8e2Robin Getz				if (!in_atomic)
163885be03b069131d242506f0f717d38659b2bdb6cRobin Getz					mmput(mm);
1647f1c906808a36630990d83d872935c079b76595bRobin Getz
165f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				if (!strlen(buf))
166f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name);
167f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
168885be03b069131d242506f0f717d38659b2bdb6cRobin Getz				goto done;
1691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			}
1701394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1711394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			vml = vml->next;
1721394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		}
173904656cda10ce985e6bc8b16488b58236eaec8e2Robin Getz		if (!in_atomic)
174885be03b069131d242506f0f717d38659b2bdb6cRobin Getz			mmput(mm);
1751394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
1761394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1771394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* we were unable to find this address anywhere */
178f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
179885be03b069131d242506f0f717d38659b2bdb6cRobin Getz
180885be03b069131d242506f0f717d38659b2bdb6cRobin Getzdone:
181885be03b069131d242506f0f717d38659b2bdb6cRobin Getz	write_unlock_irqrestore(&tasklist_lock, flags);
1821394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
1831394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1842ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getzasmlinkage void double_fault_c(struct pt_regs *fp)
1852ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz{
186226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	console_verbose();
187226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	oops_in_progress = 1;
1882ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz	printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
18949dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	dump_bfin_process(fp);
190b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	dump_bfin_mem(fp);
19149dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	show_regs(fp);
1922ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz	panic("Double Fault - unrecoverable event\n");
1932ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz
1942ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz}
1952ebcade590dcf822dcdadcc4f8f68efd3ff2e217Robin Getz
1961394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuasmlinkage void trap_c(struct pt_regs *fp)
1971394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
198518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
199518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	int j;
200518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
201518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	int sig = 0;
2021394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	siginfo_t info;
2031394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
2041394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
205226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	trace_buffer_save(j);
206226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
207226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	/* Important - be very careful dereferncing pointers - will lead to
208226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	 * double faults if the stack has become corrupt
209226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	 */
210226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
211226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	/* If the fault was caused by a kernel thread, or interrupt handler
212226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	 * we will kernel panic, so the system reboots.
213226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	 * If KGDB is enabled, don't set this for kernel breakpoints
214226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	*/
215b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
216b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	/* TODO: check to see if we are in some sort of deferred HWERR
217b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	 * that we should be able to recover from, not kernel panic
218b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	 */
2196b5eace2f15b53d5a6849078d22e78db77625929Robin Getz	if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP)
2201394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_KGDB
2216b5eace2f15b53d5a6849078d22e78db77625929Robin Getz		&& (trapnr != VEC_EXCPT02)
2221394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
223226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	){
224226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		console_verbose();
225226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		oops_in_progress = 1;
226226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	} else if (current) {
227226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		if (current->mm == NULL) {
228226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			console_verbose();
229226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			oops_in_progress = 1;
230226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		}
231226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	}
2321394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
2331394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* trap_c() will be called for exceptions. During exceptions
2341394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * processing, the pc value should be set with retx value.
2351394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * With this change we can cleanup some code in signal.c- TODO
2361394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 */
2371394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	fp->orig_pc = fp->retx;
2381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* printk("exception: 0x%x, ipend=%x, reti=%x, retx=%x\n",
2391394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		trapnr, fp->ipend, fp->pc, fp->retx); */
2401394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
2411394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* send the appropriate signal to the user program */
2421394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	switch (trapnr) {
2431394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
2441394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* This table works in conjuction with the one in ./mach-common/entry.S
2451394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * Some exceptions are handled there (in assembly, in exception space)
2461394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * Some are handled here, (in C, in interrupt space)
2471394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * Some, like CPLB, are handled in both, where the normal path is
2481394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * handled in assembly/exception space, and the error path is handled
2491394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 * here
2501394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 */
2511394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
2521394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x00 - Linux Syscall, getting here is an error */
2531394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x01 - userspace gdb breakpoint, handled here */
2541394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_EXCPT01:
2551394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_ILLTRAP;
2561394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
2571394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP_MAYBE();
2581394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		/* Check if this is a breakpoint in kernel space */
2591394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		if (fp->ipend & 0xffc0)
2601394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			return;
2611394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		else
2621394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			break;
2631394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_KGDB
2641394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_EXCPT02 :		 /* gdb connection */
2651394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_ILLTRAP;
2661394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
2671394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
2681394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		return;
2691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#else
2701394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x02 - User Defined, Caught by default */
2711394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
2729401e618c8f70920f34893946239e24d40a3519aMike Frysinger	/* 0x03 - User Defined, userspace stack overflow */
2731394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_EXCPT03:
2741394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = SEGV_STACKFLOW;
2751394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGSEGV;
276569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
2771394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
2781394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
2799401e618c8f70920f34893946239e24d40a3519aMike Frysinger	/* 0x04 - User Defined, Caught by default */
2801394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x05 - User Defined, Caught by default */
2811394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x06 - User Defined, Caught by default */
2821394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x07 - User Defined, Caught by default */
2831394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x08 - User Defined, Caught by default */
2841394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x09 - User Defined, Caught by default */
2851394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x0A - User Defined, Caught by default */
2861394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x0B - User Defined, Caught by default */
2871394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x0C - User Defined, Caught by default */
2881394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x0D - User Defined, Caught by default */
2891394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x0E - User Defined, Caught by default */
2901394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x0F - User Defined, Caught by default */
2911394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x10 HW Single step, handled here */
2921394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_STEP:
2931394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_STEP;
2941394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
2951394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP_MAYBE();
2961394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		/* Check if this is a single step in kernel space */
2971394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		if (fp->ipend & 0xffc0)
2981394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			return;
2991394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		else
3001394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			break;
3011394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x11 - Trace Buffer Full, handled here */
3021394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_OVFLOW:
3031394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_TRACEFLOW;
3041394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
305569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
3061394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
3071394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
3081394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x12 - Reserved, Caught by default */
3091394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x13 - Reserved, Caught by default */
3101394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x14 - Reserved, Caught by default */
3111394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x15 - Reserved, Caught by default */
3121394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x16 - Reserved, Caught by default */
3131394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x17 - Reserved, Caught by default */
3141394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x18 - Reserved, Caught by default */
3151394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x19 - Reserved, Caught by default */
3161394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1A - Reserved, Caught by default */
3171394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1B - Reserved, Caught by default */
3181394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1C - Reserved, Caught by default */
3191394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1D - Reserved, Caught by default */
3201394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1E - Reserved, Caught by default */
3211394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x1F - Reserved, Caught by default */
3221394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x20 - Reserved, Caught by default */
3231394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x21 - Undefined Instruction, handled here */
3241394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_UNDEF_I:
3251394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_ILLOPC;
3261394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGILL;
327569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
3281394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
3291394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
3301394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x22 - Illegal Instruction Combination, handled here */
3311394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_ILGAL_I:
3321394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_ILLPARAOP;
3331394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGILL;
334569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
3351394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
3361394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
337f26fbc48f130962fce15f37d079968f0f272e0c2Robin Getz	/* 0x23 - Data CPLB protection violation, handled here */
3381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_VL:
3391394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_VI;
340f26fbc48f130962fce15f37d079968f0f272e0c2Robin Getz		sig = SIGBUS;
341569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
3421394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
3431394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
3441394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x24 - Data access misaligned, handled here */
3451394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_MISALI_D:
3461394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = BUS_ADRALN;
3471394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
348569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
3491394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
3501394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
3511394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x25 - Unrecoverable Event, handled here */
3521394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_UNCOV:
3531394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_ILLEXCPT;
3541394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGILL;
355569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
3561394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
3571394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
3581394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
3591394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		error case is handled here */
3601394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_M:
3611394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = BUS_ADRALN;
3621394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
363569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
3641394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
3651394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
3661394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
3671394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_MHIT:
3681394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_MULHIT;
3691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGSEGV;
370c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
371bd628bd085c459838d38f93f2f154f1a2e019e48Mike Frysinger		if (saved_dcplb_fault_addr < FIXED_CODE_START)
372c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger			printk(KERN_NOTICE "NULL pointer access\n");
373c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger		else
3741394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
375c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger			printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
3761394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
3771394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
3781394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x28 - Emulation Watchpoint, handled here */
3791394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_WATCH:
3801394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_WATCHPT;
3811394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
382569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		pr_debug(EXC_0x28(KERN_DEBUG));
3831394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP_MAYBE();
3841394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		/* Check if this is a watchpoint in kernel space */
3851394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		if (fp->ipend & 0xffc0)
3861394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			return;
3871394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		else
3881394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			break;
3891394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_BF535
3901394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x29 - Instruction fetch access error (535 only) */
3911394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_ISTRU_VL:      /* ADSP-BF535 only (MH) */
3921394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = BUS_OPFETCH;
3931394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
394226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
3951394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
3961394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
3971394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#else
3981394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x29 - Reserved, Caught by default */
3991394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
4001394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2A - Instruction fetch misaligned, handled here */
4011394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_MISALI_I:
4021394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = BUS_ADRALN;
4031394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
404569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
4051394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
4061394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
407f26fbc48f130962fce15f37d079968f0f272e0c2Robin Getz	/* 0x2B - Instruction CPLB protection violation, handled here */
4081394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_I_VL:
4091394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_VI;
410f26fbc48f130962fce15f37d079968f0f272e0c2Robin Getz		sig = SIGBUS;
411569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
4121394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
4131394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4141394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
4151394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_I_M:
4161394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_MISS;
4171394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGBUS;
418569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
4191394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
4201394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4211394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2D - Instruction CPLB Multiple Hits, handled here */
4221394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_CPLB_I_MHIT:
4231394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_CPLB_MULHIT;
4241394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGSEGV;
425c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
426bd628bd085c459838d38f93f2f154f1a2e019e48Mike Frysinger		if (saved_icplb_fault_addr < FIXED_CODE_START)
427c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger			printk(KERN_NOTICE "Jump to NULL address\n");
428c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger		else
4291394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
430c6c6f75d54ca734c409e336245662934c21fcee0Mike Frysinger			printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
4311394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
4321394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4331394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2E - Illegal use of Supervisor Resource, handled here */
4341394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case VEC_ILL_RES:
4351394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = ILL_PRVOPC;
4361394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGILL;
437569a50ca3f56cd69199733580e7ca0e81029473aRobin Getz		printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
4381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
4391394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4401394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x2F - Reserved, Caught by default */
4411394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x30 - Reserved, Caught by default */
4421394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x31 - Reserved, Caught by default */
4431394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x32 - Reserved, Caught by default */
4441394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x33 - Reserved, Caught by default */
4451394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x34 - Reserved, Caught by default */
4461394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x35 - Reserved, Caught by default */
4471394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x36 - Reserved, Caught by default */
4481394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x37 - Reserved, Caught by default */
4491394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x38 - Reserved, Caught by default */
4501394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x39 - Reserved, Caught by default */
4511394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3A - Reserved, Caught by default */
4521394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3B - Reserved, Caught by default */
4531394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3C - Reserved, Caught by default */
4541394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3D - Reserved, Caught by default */
4551394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3E - Reserved, Caught by default */
4561394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	/* 0x3F - Reserved, Caught by default */
45713fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz	case VEC_HWERR:
45813fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		info.si_code = BUS_ADRALN;
45913fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		sig = SIGBUS;
46013fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		switch (fp->seqstat & SEQSTAT_HWERRCAUSE) {
46113fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		/* System MMR Error */
46213fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
46313fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			info.si_code = BUS_ADRALN;
46413fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			sig = SIGBUS;
46513fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
46613fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
46713fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		/* External Memory Addressing Error */
46813fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
46913fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			info.si_code = BUS_ADRERR;
47013fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			sig = SIGBUS;
47113fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
47213fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
47313fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		/* Performance Monitor Overflow */
47413fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
47513fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
47613fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
47713fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		/* RAISE 5 instruction */
47813fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		case (SEQSTAT_HWERRCAUSE_RAISE_5):
47913fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			printk(KERN_NOTICE HWC_x18(KERN_NOTICE));
48013fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
48113fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		default:        /* Reserved */
48213fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			printk(KERN_NOTICE HWC_default(KERN_NOTICE));
48313fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz			break;
48413fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		}
48513fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		CHK_DEBUGGER_TRAP();
48613fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		break;
4871394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	default:
4881394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		info.si_code = TRAP_ILLTRAP;
4891394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		sig = SIGTRAP;
4901394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
4911394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			(fp->seqstat & SEQSTAT_EXCAUSE));
4921394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		CHK_DEBUGGER_TRAP();
4931394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
4941394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
4951394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
496226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	BUG_ON(sig == 0);
497226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
498226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	if (sig != SIGTRAP) {
499f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		unsigned long *stack;
50049dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		dump_bfin_process(fp);
501b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		dump_bfin_mem(fp);
50249dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		show_regs(fp);
503226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
504226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		/* Print out the trace buffer if it makes sense */
505226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
506226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
507226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			printk(KERN_NOTICE "No trace since you do not have "
508226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz				"CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"
509226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz				KERN_NOTICE "\n");
510226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		else
511226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#endif
512226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			dump_bfin_trace_buffer();
513f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
514226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		if (oops_in_progress) {
515f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* Dump the current kernel stack */
516f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
517f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			show_stack(current, NULL);
518f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
519aee3a29240ad167ad7875d859506d8bb90431c70Robin Getz			print_modules();
520226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#ifndef CONFIG_ACCESS_CHECK
52190c7f4686f82aef875aadf8e5c9c1a9465e5143bRobin Getz			printk(KERN_EMERG "Please turn on "
52290c7f4686f82aef875aadf8e5c9c1a9465e5143bRobin Getz			       "CONFIG_ACCESS_CHECK\n");
523226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz#endif
5241394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			panic("Kernel exception");
525f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		} else {
526f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* Dump the user space stack */
527f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			stack = (unsigned long *)rdusp();
528f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk(KERN_NOTICE "Userspace Stack\n");
529f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			show_stack(NULL, stack);
530226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		}
5311394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
532fb322915a05804a3a153f714f2f08e4c32ce84c7Robin Getz
533ce3afa1c043ab3d4125671441a57353d80f5f6f7Robin Getz	info.si_signo = sig;
534ce3afa1c043ab3d4125671441a57353d80f5f6f7Robin Getz	info.si_errno = 0;
5350ddeeca25ce33686262459e2387f57bd09574e47Mike Frysinger	info.si_addr = (void __user *)fp->pc;
536ce3afa1c043ab3d4125671441a57353d80f5f6f7Robin Getz	force_sig_info(sig, &info, current);
5371394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
5381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_restore(j);
5391394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	return;
5401394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
5411394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
5421394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu/* Typical exception handling routines	*/
5431394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
544518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)
545518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
546f09630bff51daaf427968c61c0f2370c64148e06Robin Getz/*
547f09630bff51daaf427968c61c0f2370c64148e06Robin Getz * Similar to get_user, do some address checking, then dereference
548f09630bff51daaf427968c61c0f2370c64148e06Robin Getz * Return true on sucess, false on bad address
549f09630bff51daaf427968c61c0f2370c64148e06Robin Getz */
550f09630bff51daaf427968c61c0f2370c64148e06Robin Getzbool get_instruction(unsigned short *val, unsigned short *address)
551f09630bff51daaf427968c61c0f2370c64148e06Robin Getz{
552f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
553f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	unsigned long addr;
554f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
555f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	addr = (unsigned long)address;
556f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
557f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/* Check for odd addresses */
558f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (addr & 0x1)
559f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return false;
560f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
561f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/* Check that things do not wrap around */
562f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (addr > (addr + 2))
563f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return false;
564f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
565f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/*
566f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * Since we are in exception context, we need to do a little address checking
567f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * We need to make sure we are only accessing valid memory, and
568f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * we don't read something in the async space that can hang forever
569f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 */
570f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if ((addr >= FIXED_CODE_START && (addr + 2) <= physical_mem_end) ||
57107aa7be5708afb3d9afa68f6f853c98e51bc64b3Mike Frysinger#if L2_LENGTH != 0
572f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (addr >= L2_START && (addr + 2) <= (L2_START + L2_LENGTH)) ||
573f09630bff51daaf427968c61c0f2370c64148e06Robin Getz#endif
574f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (addr >= BOOT_ROM_START && (addr + 2) <= (BOOT_ROM_START + BOOT_ROM_LENGTH)) ||
575f09630bff51daaf427968c61c0f2370c64148e06Robin Getz#if L1_DATA_A_LENGTH != 0
576f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (addr >= L1_DATA_A_START && (addr + 2) <= (L1_DATA_A_START + L1_DATA_A_LENGTH)) ||
577f09630bff51daaf427968c61c0f2370c64148e06Robin Getz#endif
578f09630bff51daaf427968c61c0f2370c64148e06Robin Getz#if L1_DATA_B_LENGTH != 0
579f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (addr >= L1_DATA_B_START && (addr + 2) <= (L1_DATA_B_START + L1_DATA_B_LENGTH)) ||
580f09630bff51daaf427968c61c0f2370c64148e06Robin Getz#endif
581f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (addr >= L1_SCRATCH_START && (addr + 2) <= (L1_SCRATCH_START + L1_SCRATCH_LENGTH)) ||
582f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (!(bfin_read_EBIU_AMBCTL0() & B0RDYEN) &&
583f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	       addr >= ASYNC_BANK0_BASE && (addr + 2) <= (ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)) ||
584f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (!(bfin_read_EBIU_AMBCTL0() & B1RDYEN) &&
585f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	       addr >= ASYNC_BANK1_BASE && (addr + 2) <= (ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)) ||
586f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (!(bfin_read_EBIU_AMBCTL1() & B2RDYEN) &&
587f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	       addr >= ASYNC_BANK2_BASE && (addr + 2) <= (ASYNC_BANK2_BASE + ASYNC_BANK1_SIZE)) ||
588f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (!(bfin_read_EBIU_AMBCTL1() & B3RDYEN) &&
589f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	      addr >= ASYNC_BANK3_BASE && (addr + 2) <= (ASYNC_BANK3_BASE + ASYNC_BANK1_SIZE))) {
590f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		*val = *address;
591f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return true;
592f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	}
593f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
594f09630bff51daaf427968c61c0f2370c64148e06Robin Getz#if L1_CODE_LENGTH != 0
595f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) {
596f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		dma_memcpy(val, address, 2);
597f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return true;
598f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	}
599f09630bff51daaf427968c61c0f2370c64148e06Robin Getz#endif
600f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
601f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
602f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	return false;
603f09630bff51daaf427968c61c0f2370c64148e06Robin Getz}
604f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
605d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz/*
606d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz * decode the instruction if we are printing out the trace, as it
607d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz * makes things easier to follow, without running it through objdump
608d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz * These are the normal instructions which cause change of flow, which
609d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz * would be at the source of the trace buffer
610d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz */
611d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getzvoid decode_instruction(unsigned short *address)
612d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz{
613d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	unsigned short opcode;
614d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz
615d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	if (get_instruction(&opcode, address)) {
616d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		if (opcode == 0x0010)
617d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("RTS");
618d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode == 0x0011)
619d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("RTI");
620d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode == 0x0012)
621d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("RTX");
622d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x0050 && opcode <= 0x0057)
623d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("JUMP (P%i)", opcode & 7);
624d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x0060 && opcode <= 0x0067)
625d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("CALL (P%i)", opcode & 7);
626d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x0070 && opcode <= 0x0077)
627d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("CALL (PC+P%i)", opcode & 7);
628d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x0080 && opcode <= 0x0087)
629d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("JUMP (PC+P%i)", opcode & 7);
630d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF))
631d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("IF !CC JUMP");
632d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff))
633d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("IF CC JUMP");
634d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0x2000 && opcode <= 0x2fff)
635d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("JUMP.S");
636d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0xe080 && opcode <= 0xe0ff)
637d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("LSETUP");
638d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0xe200 && opcode <= 0xe2ff)
639d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("JUMP.L");
640d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else if (opcode >= 0xe300 && opcode <= 0xe3ff)
641d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("CALL pcrel");
642d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		else
643d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			printk("0x%04x", opcode);
644d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	}
645d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz
646d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz}
647d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz
6481394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid dump_bfin_trace_buffer(void)
6491394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
650518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
651518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	int tflags, i = 0;
652226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	char buf[150];
653d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	unsigned short *addr;
654518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
655518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	int j, index;
656518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
657518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
6581394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_save(tflags);
6591394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
660226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE "Hardware Trace:\n");
661518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
662d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
663d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz	printk(KERN_NOTICE "WARNING: Expanded trace turned on - can not trace exceptions\n");
664d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz#endif
665d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz
6661394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
667518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
668226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			decode_address(buf, (unsigned long)bfin_read_TBUF());
669226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz			printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
670f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			addr = (unsigned short *)bfin_read_TBUF();
671f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			decode_address(buf, (unsigned long)addr);
672f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk(KERN_NOTICE "     Source : %s ", buf);
673d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz			decode_instruction(addr);
674f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk("\n");
6751394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		}
6761394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
6771394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
678518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
679518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	if (trace_buff_offset)
680d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		index = trace_buff_offset / 4;
681518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	else
682518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		index = EXPAND_LEN;
683518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
684518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128;
685518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	while (j) {
686226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		decode_address(buf, software_trace_buff[index]);
687226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
688518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		index -= 1;
689518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		if (index < 0 )
690518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz			index = EXPAND_LEN;
691226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		decode_address(buf, software_trace_buff[index]);
692d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		printk(KERN_NOTICE "     Source : %s ", buf);
693d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		decode_instruction((unsigned short *)software_trace_buff[index]);
694d3d0ac23a308f92fc5e5e2846ca40e7bffa5cec3Robin Getz		printk("\n");
695518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		index -= 1;
696518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		if (index < 0)
697518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz			index = EXPAND_LEN;
698518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		j--;
699518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz		i++;
700518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz	}
701518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
702518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz
7031394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_restore(tflags);
704518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
7051394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
7061394f03221790a988afc3e4b3cb79f2e477246a9Bryan WuEXPORT_SYMBOL(dump_bfin_trace_buffer);
7071394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
708f09630bff51daaf427968c61c0f2370c64148e06Robin Getz/*
709f09630bff51daaf427968c61c0f2370c64148e06Robin Getz * Checks to see if the address pointed to is either a
710f09630bff51daaf427968c61c0f2370c64148e06Robin Getz * 16-bit CALL instruction, or a 32-bit CALL instruction
711f09630bff51daaf427968c61c0f2370c64148e06Robin Getz */
712f09630bff51daaf427968c61c0f2370c64148e06Robin Getzbool is_bfin_call(unsigned short *addr)
7131394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
714f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	unsigned short opcode = 0, *ins_addr;
715f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	ins_addr = (unsigned short *)addr;
7161394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
717f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (!get_instruction(&opcode, ins_addr))
718f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return false;
7191394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
720f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if ((opcode >= 0x0060 && opcode <= 0x0067) ||
721f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	    (opcode >= 0x0070 && opcode <= 0x0077))
722f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return true;
723f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
724f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	ins_addr--;
725f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (!get_instruction(&opcode, ins_addr))
726f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return false;
7271394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
728f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (opcode >= 0xE300 && opcode <= 0xE3FF)
729f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		return true;
730f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
731f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	return false;
732f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
733f09630bff51daaf427968c61c0f2370c64148e06Robin Getz}
7341394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid show_stack(struct task_struct *task, unsigned long *stack)
7351394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
736f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	unsigned int *addr, *endstack, *fp = 0, *frame;
737f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	unsigned short *ins_addr;
738f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	char buf[150];
739f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	unsigned int i, j, ret_addr, frame_no = 0;
7401394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
741f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/*
742f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * If we have been passed a specific stack, use that one otherwise
743f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 *    if we have been passed a task structure, use that, otherwise
744f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 *    use the stack of where the variable "stack" exists
7451394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	 */
7461394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
747f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (stack == NULL) {
748f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (task) {
749f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* We know this is a kernel stack, so this is the start/end */
7501394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			stack = (unsigned long *)task->thread.ksp;
751f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
752f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		} else {
753f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* print out the existing stack info */
7541394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			stack = (unsigned long *)&stack;
755f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
756f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		}
757f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	} else
758f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
759f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
760f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	decode_address(buf, (unsigned int)stack);
761f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	printk(KERN_NOTICE "Stack info:\n" KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
762f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	addr = (unsigned int *)((unsigned int)stack & ~0x3F);
763f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
764f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/* First thing is to look for a frame pointer */
765f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
766f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		addr < endstack; addr++, i++) {
767f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (*addr & 0x1)
768f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			continue;
769f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		ins_addr = (unsigned short *)*addr;
770f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		ins_addr--;
771f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (is_bfin_call(ins_addr))
772f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			fp = addr - 1;
773f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
774f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (fp) {
775f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* Let's check to see if it is a frame pointer */
776f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			while (fp >= (addr - 1) && fp < endstack && fp)
777f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				fp = (unsigned int *)*fp;
778f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			if (fp == 0 || fp == endstack) {
779f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				fp = addr - 1;
780f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				break;
781f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			}
782f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			fp = 0;
783f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		}
7841394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
785f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	if (fp) {
786f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		frame = fp;
787f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		printk(" FP: (0x%p)\n", fp);
788f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	} else
789f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		frame = 0;
7901394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
791f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/*
792f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * Now that we think we know where things are, we
793f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * walk the stack again, this time printing things out
794f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * incase there is no frame pointer, we still look for
795f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 * valid return addresses
796f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	 */
7971394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
798f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	/* First time print out data, next time, print out symbols */
799f09630bff51daaf427968c61c0f2370c64148e06Robin Getz	for (j = 0; j <= 1; j++) {
800f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (j)
801f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk(KERN_NOTICE "Return addresses in stack:\n");
802f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		else
803f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);
804f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
805f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		fp = frame;
806f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		frame_no = 0;
807f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
808f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
809f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		     addr <= endstack; addr++, i++) {
810f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
811f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			ret_addr = 0;
812f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			if (!j && i % 8 == 0)
813f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				printk("\n" KERN_NOTICE "%p:",addr);
814f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
815f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* if it is an odd address, or zero, just skip it */
816f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			if (*addr & 0x1 || !*addr)
817f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				goto print;
818f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
819f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			ins_addr = (unsigned short *)*addr;
820f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
821f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			/* Go back one instruction, and see if it is a CALL */
822f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			ins_addr--;
823f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			ret_addr = is_bfin_call(ins_addr);
824f09630bff51daaf427968c61c0f2370c64148e06Robin Getz print:
825f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			if (!j && stack == (unsigned long *)addr)
826f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				printk("[%08x]", *addr);
827f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			else if (ret_addr)
828f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				if (j) {
829f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					decode_address(buf, (unsigned int)*addr);
830f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					if (frame == addr) {
831f09630bff51daaf427968c61c0f2370c64148e06Robin Getz						printk(KERN_NOTICE "   frame %2i : %s\n", frame_no, buf);
832f09630bff51daaf427968c61c0f2370c64148e06Robin Getz						continue;
833f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					}
834f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					printk(KERN_NOTICE "    address : %s\n", buf);
835f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				} else
836f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					printk("<%08x>", *addr);
837f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			else if (fp == addr) {
838f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				if (j)
839f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					frame = addr+1;
840f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				else
841f09630bff51daaf427968c61c0f2370c64148e06Robin Getz					printk("(%08x)", *addr);
842f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
843f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				fp = (unsigned int *)*addr;
844f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				frame_no++;
845f09630bff51daaf427968c61c0f2370c64148e06Robin Getz
846f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			} else if (!j)
847f09630bff51daaf427968c61c0f2370c64148e06Robin Getz				printk(" %08x ", *addr);
848f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		}
849f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (!j)
850f09630bff51daaf427968c61c0f2370c64148e06Robin Getz			printk("\n");
8511394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
8521394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
8531394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
8541394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
8551394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid dump_stack(void)
8561394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
8571394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	unsigned long stack;
858518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
8591394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	int tflags;
860518039bc24cbb9ce34665814fe120eac50bedd9aRobin Getz#endif
8611394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_save(tflags);
8621394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	dump_bfin_trace_buffer();
8631394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	show_stack(current, &stack);
8641394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	trace_buffer_restore(tflags);
8651394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
8661394f03221790a988afc3e4b3cb79f2e477246a9Bryan WuEXPORT_SYMBOL(dump_stack);
8671394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
86849dce9124b41984bf1e918847bc17929c2e8f80fMike Frysingervoid dump_bfin_process(struct pt_regs *fp)
8691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
87049dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	/* We should be able to look at fp->ipend, but we don't push it on the
87149dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	 * stack all the time, so do this until we fix that */
87249dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	unsigned int context = bfin_read_IPEND();
87349dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger
87449dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	if (oops_in_progress)
87549dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		printk(KERN_EMERG "Kernel OOPS in progress\n");
87649dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger
877b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)
878b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		printk(KERN_NOTICE "HW Error context\n");
879b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	else if (context & 0x0020)
880a3acf52885a2312efb30a043062ef88dc3813082Mike Frysinger		printk(KERN_NOTICE "Deferred Exception context\n");
88149dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	else if (context & 0x3FC0)
88249dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		printk(KERN_NOTICE "Interrupt context\n");
88349dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	else if (context & 0x4000)
88449dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		printk(KERN_NOTICE "Deferred Interrupt context\n");
88549dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	else if (context & 0x8000)
88649dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		printk(KERN_NOTICE "Kernel process context\n");
88749dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger
8889a62ca40fd793742f92565104c6b44319af8c282Robin Getz	/* Because we are crashing, and pointers could be bad, we check things
8899a62ca40fd793742f92565104c6b44319af8c282Robin Getz	 * pretty closely before we use them
8909a62ca40fd793742f92565104c6b44319af8c282Robin Getz	 */
8917f1c906808a36630990d83d872935c079b76595bRobin Getz	if ((unsigned long)current >= FIXED_CODE_START &&
8927f1c906808a36630990d83d872935c079b76595bRobin Getz	    !((unsigned long)current & 0x3) && current->pid) {
89349dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		printk(KERN_NOTICE "CURRENT PROCESS:\n");
8949a62ca40fd793742f92565104c6b44319af8c282Robin Getz		if (current->comm >= (char *)FIXED_CODE_START)
8959a62ca40fd793742f92565104c6b44319af8c282Robin Getz			printk(KERN_NOTICE "COMM=%s PID=%d\n",
8969a62ca40fd793742f92565104c6b44319af8c282Robin Getz				current->comm, current->pid);
8979a62ca40fd793742f92565104c6b44319af8c282Robin Getz		else
8989a62ca40fd793742f92565104c6b44319af8c282Robin Getz			printk(KERN_NOTICE "COMM= invalid\n");
8999a62ca40fd793742f92565104c6b44319af8c282Robin Getz
9009a62ca40fd793742f92565104c6b44319af8c282Robin Getz		if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
9019a62ca40fd793742f92565104c6b44319af8c282Robin Getz			printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
9029a62ca40fd793742f92565104c6b44319af8c282Robin Getz				KERN_NOTICE " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n"
9039a62ca40fd793742f92565104c6b44319af8c282Robin Getz				KERN_NOTICE "\n",
9049a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->start_code,
9059a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->end_code,
9069a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->start_data,
9079a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->end_data,
9089a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->end_data,
9099a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->brk,
9109a62ca40fd793742f92565104c6b44319af8c282Robin Getz				(void *)current->mm->start_stack);
9119a62ca40fd793742f92565104c6b44319af8c282Robin Getz		else
9129a62ca40fd793742f92565104c6b44319af8c282Robin Getz			printk(KERN_NOTICE "invalid mm\n");
91349dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	} else
91449dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		printk(KERN_NOTICE "\n" KERN_NOTICE
91549dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger		     "No Valid process in current context\n");
91649dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger}
917226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
918b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getzvoid dump_bfin_mem(struct pt_regs *fp)
91949dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger{
920b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	unsigned short *addr, *erraddr, val = 0, err = 0;
921b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	char sti = 0, buf[6];
9221394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
9235d750b9e4f6ca7d366b4954517ff8be9ee07e1bfBernd Schmidt	erraddr = (void *)fp->pc;
924b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
925b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
926b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
927b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10;
928b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	     addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
929b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	     addr++) {
930b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		if (!((unsigned long)addr & 0xF))
931b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			printk("\n" KERN_NOTICE "0x%p: ", addr);
932b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
933f09630bff51daaf427968c61c0f2370c64148e06Robin Getz		if (get_instruction(&val, addr)) {
934b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz				val = 0;
935b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz				sprintf(buf, "????");
936b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		} else
937b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			sprintf(buf, "%04x", val);
938b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
939b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		if (addr == erraddr) {
940b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			printk("[%s]", buf);
941b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			err = val;
942b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		} else
943b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			printk(" %s ", buf);
944b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
945b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		/* Do any previous instructions turn on interrupts? */
946b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		if (addr <= erraddr &&				/* in the past */
947b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		    ((val >= 0x0040 && val <= 0x0047) ||	/* STI instruction */
948b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		      val == 0x017b))				/* [SP++] = RETI */
949b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			sti = 1;
950b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	}
951b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
952b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	printk("\n");
953b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz
954b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	/* Hardware error interrupts can be deferred */
955b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR &&
956b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	    oops_in_progress)){
957b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
9581394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifndef CONFIG_DEBUG_HWERR
959b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		printk(KERN_NOTICE "The remaining message may be meaningless\n"
960b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a"
961b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			 " better idea where it came from\n");
962b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz#else
963b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		/* If we are handling only one peripheral interrupt
964b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		 * and current mm and pid are valid, and the last error
965b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		 * was in that user space process's text area
966b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		 * print it out - because that is where the problem exists
967b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		 */
968b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		if ((!(((fp)->ipend & ~0x30) & (((fp)->ipend & ~0x30) - 1))) &&
969b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz		     (current->pid && current->mm)) {
970b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			/* And the last RETI points to the current userspace context */
971b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			if ((fp + 1)->pc >= current->mm->start_code &&
972b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			    (fp + 1)->pc <= current->mm->end_code) {
973b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz				printk(KERN_NOTICE "It might be better to look around here : \n");
974b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz				printk(KERN_NOTICE "-------------------------------------------\n");
975b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz				show_regs(fp + 1);
976b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz				printk(KERN_NOTICE "-------------------------------------------\n");
977b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz			}
9781394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		}
979b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz#endif
980b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	}
98149dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger}
98249dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger
98349dce9124b41984bf1e918847bc17929c2e8f80fMike Frysingervoid show_regs(struct pt_regs *fp)
98449dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger{
98549dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	char buf [150];
986d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	struct irqaction *action;
987d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	unsigned int i;
988d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	unsigned long flags;
989226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
990aee3a29240ad167ad7875d859506d8bb90431c70Robin Getz	printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
991226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
992226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		(long)fp->seqstat, fp->ipend, fp->syscfg);
99313fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz	printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
99413fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
99513fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz	printk(KERN_NOTICE "  EXCAUSE   : 0x%lx\n",
99613fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz		fp->seqstat & SEQSTAT_EXCAUSE);
997d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	for (i = 6; i <= 15 ; i++) {
998d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz		if (fp->ipend & (1 << i)) {
999d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			decode_address(buf, bfin_read32(EVT0 + 4*i));
1000d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			printk(KERN_NOTICE "  physical IVG%i asserted : %s\n", i, buf);
1001d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz		}
1002d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	}
1003d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz
1004d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	/* if no interrupts are going off, don't print this out */
1005d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	if (fp->ipend & ~0x3F) {
1006d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz		for (i = 0; i < (NR_IRQS - 1); i++) {
1007d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			spin_lock_irqsave(&irq_desc[i].lock, flags);
1008d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			action = irq_desc[i].action;
1009d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			if (!action)
1010d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz				goto unlock;
1011d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz
1012d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			decode_address(buf, (unsigned int)action->handler);
1013d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			printk(KERN_NOTICE "  logical irq %3d mapped  : %s", i, buf);
1014d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			for (action = action->next; action; action = action->next) {
1015d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz				decode_address(buf, (unsigned int)action->handler);
1016d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz				printk(", %s", buf);
1017d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			}
1018d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			printk("\n");
1019d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getzunlock:
1020d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz			spin_unlock_irqrestore(&irq_desc[i].lock, flags);
1021d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz		}
1022d8f66c8c1ea8e948483ee4739ad91120f5f7de51Robin Getz	}
1023c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz
1024226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	decode_address(buf, fp->rete);
1025226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " RETE: %s\n", buf);
1026226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	decode_address(buf, fp->retn);
1027226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " RETN: %s\n", buf);
1028226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	decode_address(buf, fp->retx);
1029226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " RETX: %s\n", buf);
1030226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	decode_address(buf, fp->rets);
1031226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " RETS: %s\n", buf);
103249dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	decode_address(buf, fp->pc);
103313fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz	printk(KERN_NOTICE " PC  : %s\n", buf);
1034c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz
103513fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
103613fe24f37df20e580a5a364e67ec8cf3219d8f8cRobin Getz	    (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
10375d750b9e4f6ca7d366b4954517ff8be9ee07e1bfBernd Schmidt		decode_address(buf, saved_dcplb_fault_addr);
1038226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
10395d750b9e4f6ca7d366b4954517ff8be9ee07e1bfBernd Schmidt		decode_address(buf, saved_icplb_fault_addr);
1040226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
1041226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	}
1042226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
1043226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
1044226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
1045c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->r0, fp->r1, fp->r2, fp->r3);
1046226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",
1047c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->r4, fp->r5, fp->r6, fp->r7);
1048226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " P0 : %08lx    P1 : %08lx    P2 : %08lx    P3 : %08lx\n",
1049c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->p0, fp->p1, fp->p2, fp->p3);
1050226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " P4 : %08lx    P5 : %08lx    FP : %08lx    SP : %08lx\n",
1051226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		fp->p4, fp->p5, fp->fp, (long)fp);
1052226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " LB0: %08lx    LT0: %08lx    LC0: %08lx\n",
1053c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->lb0, fp->lt0, fp->lc0);
1054226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " LB1: %08lx    LT1: %08lx    LC1: %08lx\n",
1055c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->lb1, fp->lt1, fp->lc1);
1056226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " B0 : %08lx    L0 : %08lx    M0 : %08lx    I0 : %08lx\n",
1057c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->b0, fp->l0, fp->m0, fp->i0);
1058226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " B1 : %08lx    L1 : %08lx    M1 : %08lx    I1 : %08lx\n",
1059c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->b1, fp->l1, fp->m1, fp->i1);
1060226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " B2 : %08lx    L2 : %08lx    M2 : %08lx    I2 : %08lx\n",
1061c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->b2, fp->l2, fp->m2, fp->i2);
1062226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE " B3 : %08lx    L3 : %08lx    M3 : %08lx    I3 : %08lx\n",
1063c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		fp->b3, fp->l3, fp->m3, fp->i3);
1064226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE "A0.w: %08lx   A0.x: %08lx   A1.w: %08lx   A1.x: %08lx\n",
1065226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz		fp->a0w, fp->a0x, fp->a1w, fp->a1x);
1066c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz
1067226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE "USP : %08lx  ASTAT: %08lx\n",
1068c5d88d9e2566e7ddccb0e001446b9a39882560a3Robin Getz		rdusp(), fp->astat);
10691394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1070226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	printk(KERN_NOTICE "\n");
10711394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
10721394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
10731394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
10741394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuasmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
10751394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu#endif
10761394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
10771394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuasmlinkage int sys_bfin_spinlock(int *spinlock)
10781394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
10791394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	int ret = 0;
10801394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	int tmp = 0;
10811394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
10821394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	local_irq_disable();
10831394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	ret = get_user(tmp, spinlock);
10841394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	if (ret == 0) {
10851394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		if (tmp)
10861394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu			ret = 1;
10871394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		tmp = 1;
10881394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		put_user(tmp, spinlock);
10891394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
10901394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	local_irq_enable();
10911394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	return ret;
10921394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
10931394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
10941ffe6646babf8471714e649849ec2c9662bf410cMike Frysingerint bfin_request_exception(unsigned int exception, void (*handler)(void))
10951ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger{
10961ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	void (*curr_handler)(void);
10971ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
10981ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	if (exception > 0x3F)
10991ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger		return -EINVAL;
11001ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11011ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	curr_handler = ex_table[exception];
11021ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11031ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	if (curr_handler != ex_replaceable)
11041ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger		return -EBUSY;
11051ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11061ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	ex_table[exception] = handler;
11071ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11081ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	return 0;
11091ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger}
11101ffe6646babf8471714e649849ec2c9662bf410cMike FrysingerEXPORT_SYMBOL(bfin_request_exception);
11111ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11121ffe6646babf8471714e649849ec2c9662bf410cMike Frysingerint bfin_free_exception(unsigned int exception, void (*handler)(void))
11131ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger{
11141ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	void (*curr_handler)(void);
11151ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11161ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	if (exception > 0x3F)
11171ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger		return -EINVAL;
11181ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11191ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	curr_handler = ex_table[exception];
11201ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11211ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	if (curr_handler != handler)
11221ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger		return -EBUSY;
11231ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11241ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	ex_table[exception] = ex_replaceable;
11251ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11261ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger	return 0;
11271ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger}
11281ffe6646babf8471714e649849ec2c9662bf410cMike FrysingerEXPORT_SYMBOL(bfin_free_exception);
11291ffe6646babf8471714e649849ec2c9662bf410cMike Frysinger
11301394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wuvoid panic_cplb_error(int cplb_panic, struct pt_regs *fp)
11311394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu{
11321394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	switch (cplb_panic) {
11331394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case CPLB_NO_UNLOCKED:
11341394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		printk(KERN_EMERG "All CPLBs are locked\n");
11351394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
11361394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case CPLB_PROT_VIOL:
11371394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		return;
11381394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case CPLB_NO_ADDR_MATCH:
11391394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		return;
11401394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	case CPLB_UNKNOWN_ERR:
11411394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		printk(KERN_EMERG "Unknown CPLB Exception\n");
11421394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu		break;
11431394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	}
11441394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu
1145226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz	oops_in_progress = 1;
1146226eb1ef523a33c66193bc319a92c647e47311d4Robin Getz
114749dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	dump_bfin_process(fp);
1148b03b08ba9c7235861adf4dde712dade0bb756fe0Robin Getz	dump_bfin_mem(fp);
114949dce9124b41984bf1e918847bc17929c2e8f80fMike Frysinger	show_regs(fp);
11501394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	dump_stack();
11511394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu	panic("Unrecoverable event\n");
11521394f03221790a988afc3e4b3cb79f2e477246a9Bryan Wu}
1153