traps.c 37.7 KB
Newer Older
B
Bryan Wu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*
 * File:         arch/blackfin/kernel/traps.c
 * Based on:
 * Author:       Hamish Macdonald
 *
 * Created:
 * Description:  uses S/W interrupt 15 for the system calls
 *
 * Modified:
 *               Copyright 2004-2006 Analog Devices Inc.
 *
 * Bugs:         Enter bugs at http://blackfin.uclinux.org/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see the file COPYING, or write
 * to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

30
#include <linux/bug.h>
31 32 33 34
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
35
#include <linux/fs.h>
36
#include <linux/rbtree.h>
B
Bryan Wu 已提交
37 38
#include <asm/traps.h>
#include <asm/cacheflush.h>
39
#include <asm/cplb.h>
B
Bryan Wu 已提交
40 41
#include <asm/blackfin.h>
#include <asm/irq_handler.h>
42
#include <linux/irq.h>
43
#include <asm/trace.h>
44
#include <asm/fixed_code.h>
B
Bryan Wu 已提交
45 46 47

#ifdef CONFIG_KGDB
# include <linux/kgdb.h>
48 49 50

# define CHK_DEBUGGER_TRAP() \
	do { \
51
		kgdb_handle_exception(trapnr, sig, info.si_code, fp); \
52 53 54 55 56 57 58 59 60
	} while (0)
# define CHK_DEBUGGER_TRAP_MAYBE() \
	do { \
		if (kgdb_connected) \
			CHK_DEBUGGER_TRAP(); \
	} while (0)
#else
# define CHK_DEBUGGER_TRAP() do { } while (0)
# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
B
Bryan Wu 已提交
61 62
#endif

63

64
#ifdef CONFIG_DEBUG_VERBOSE
65 66 67 68 69 70 71
#define verbose_printk(fmt, arg...) \
	printk(fmt, ##arg)
#else
#define verbose_printk(fmt, arg...) \
	({ if (0) printk(fmt, ##arg); 0; })
#endif

72 73 74 75 76 77 78
#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE)
u32 last_seqstat;
#ifdef CONFIG_DEBUG_MMRS_MODULE
EXPORT_SYMBOL(last_seqstat);
#endif
#endif

B
Bryan Wu 已提交
79 80 81 82 83 84 85 86
/* Initiate the event table handler */
void __init trap_init(void)
{
	CSYNC();
	bfin_write_EVT3(trap);
	CSYNC();
}

87
static void decode_address(char *buf, unsigned long address)
B
Bryan Wu 已提交
88
{
89
#ifdef CONFIG_DEBUG_VERBOSE
B
Bryan Wu 已提交
90 91
	struct task_struct *p;
	struct mm_struct *mm;
92
	unsigned long flags, offset;
93
	unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
94
	struct rb_node *n;
B
Bryan Wu 已提交
95 96

#ifdef CONFIG_KALLSYMS
97
	unsigned long symsize;
B
Bryan Wu 已提交
98 99 100 101 102 103 104 105 106 107 108 109
	const char *symname;
	char *modname;
	char *delim = ":";
	char namebuf[128];

	/* look up the address and see if we are in kernel space */
	symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);

	if (symname) {
		/* yeah! kernel space! */
		if (!modname)
			modname = delim = "";
110
		sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }",
111
		              (void *)address, delim, modname, delim, symname,
B
Bryan Wu 已提交
112
		              (unsigned long)offset);
113
		return;
B
Bryan Wu 已提交
114 115 116 117

	}
#endif

118 119 120 121 122 123 124 125 126 127 128 129
	/* Problem in fixed code section? */
	if (address >= FIXED_CODE_START && address < FIXED_CODE_END) {
		sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address);
		return;
	}

	/* Problem somewhere before the kernel start address */
	if (address < CONFIG_BOOT_LOAD) {
		sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address);
		return;
	}

B
Bryan Wu 已提交
130 131 132 133
	/* looks like we're off in user-land, so let's walk all the
	 * mappings of all our processes and see if we can't be a whee
	 * bit more specific
	 */
134
	write_lock_irqsave(&tasklist_lock, flags);
B
Bryan Wu 已提交
135
	for_each_process(p) {
136
		mm = (in_atomic ? p->mm : get_task_mm(p));
B
Bryan Wu 已提交
137 138 139
		if (!mm)
			continue;

140 141 142 143
		for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) {
			struct vm_area_struct *vma;

			vma = rb_entry(n, struct vm_area_struct, vm_rb);
B
Bryan Wu 已提交
144 145

			if (address >= vma->vm_start && address < vma->vm_end) {
146
				char _tmpbuf[256];
B
Bryan Wu 已提交
147 148
				char *name = p->comm;
				struct file *file = vma->vm_file;
149

150 151
				if (file) {
					char *d_name = d_path(&file->f_path, _tmpbuf,
152
						      sizeof(_tmpbuf));
153 154 155
					if (!IS_ERR(d_name))
						name = d_name;
				}
B
Bryan Wu 已提交
156

157 158 159
				/* FLAT does not have its text aligned to the start of
				 * the map while FDPIC ELF does ...
				 */
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180

				/* before we can check flat/fdpic, we need to
				 * make sure current is valid
				 */
				if ((unsigned long)current >= FIXED_CODE_START &&
				    !((unsigned long)current & 0x3)) {
					if (current->mm &&
					    (address > current->mm->start_code) &&
					    (address < current->mm->end_code))
						offset = address - current->mm->start_code;
					else
						offset = (address - vma->vm_start) +
							 (vma->vm_pgoff << PAGE_SHIFT);

					sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
						(void *)address, name, offset);
				} else
					sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
						(void *)address, name,
						vma->vm_start, vma->vm_end);

181
				if (!in_atomic)
182
					mmput(mm);
183

184 185 186
				if (!strlen(buf))
					sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name);

187
				goto done;
B
Bryan Wu 已提交
188 189
			}
		}
190
		if (!in_atomic)
191
			mmput(mm);
B
Bryan Wu 已提交
192 193 194
	}

	/* we were unable to find this address anywhere */
195
	sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
196 197 198

done:
	write_unlock_irqrestore(&tasklist_lock, flags);
199 200 201
#else
	sprintf(buf, " ");
#endif
B
Bryan Wu 已提交
202 203
}

204 205
asmlinkage void double_fault_c(struct pt_regs *fp)
{
206 207 208 209 210
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
	int j;
	trace_buffer_save(j);
#endif

211 212
	console_verbose();
	oops_in_progress = 1;
213
#ifdef CONFIG_DEBUG_VERBOSE
214
	printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
215 216
#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) == VEC_UNCOV) {
217
		unsigned int cpu = smp_processor_id();
218
		char buf[150];
219
		decode_address(buf, cpu_pda[cpu].retx);
220
		printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
221 222
			(unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
		decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
223
		printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %s\n", buf);
224
		decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
225 226 227
		printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %s\n", buf);

		decode_address(buf, fp->retx);
228
		printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf);
229 230 231 232 233 234
	} else
#endif
	{
		dump_bfin_process(fp);
		dump_bfin_mem(fp);
		show_regs(fp);
235
		dump_bfin_trace_buffer();
236
	}
237
#endif
238
	panic("Double Fault - unrecoverable event");
239 240 241

}

B
Bryan Wu 已提交
242 243
asmlinkage void trap_c(struct pt_regs *fp)
{
244 245
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
	int j;
246 247 248
#endif
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
	unsigned int cpu = smp_processor_id();
249 250
#endif
	int sig = 0;
B
Bryan Wu 已提交
251 252 253
	siginfo_t info;
	unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;

254
	trace_buffer_save(j);
255 256 257
#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE)
	last_seqstat = (u32)fp->seqstat;
#endif
258 259 260 261 262 263 264 265 266

	/* Important - be very careful dereferncing pointers - will lead to
	 * double faults if the stack has become corrupt
	 */

	/* If the fault was caused by a kernel thread, or interrupt handler
	 * we will kernel panic, so the system reboots.
	 * If KGDB is enabled, don't set this for kernel breakpoints
	*/
267 268 269 270

	/* TODO: check to see if we are in some sort of deferred HWERR
	 * that we should be able to recover from, not kernel panic
	 */
271
	if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP)
B
Bryan Wu 已提交
272
#ifdef CONFIG_KGDB
273
		&& (trapnr != VEC_EXCPT02)
B
Bryan Wu 已提交
274
#endif
275 276 277 278 279 280 281 282 283
	){
		console_verbose();
		oops_in_progress = 1;
	} else if (current) {
		if (current->mm == NULL) {
			console_verbose();
			oops_in_progress = 1;
		}
	}
B
Bryan Wu 已提交
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314

	/* trap_c() will be called for exceptions. During exceptions
	 * processing, the pc value should be set with retx value.
	 * With this change we can cleanup some code in signal.c- TODO
	 */
	fp->orig_pc = fp->retx;
	/* printk("exception: 0x%x, ipend=%x, reti=%x, retx=%x\n",
		trapnr, fp->ipend, fp->pc, fp->retx); */

	/* send the appropriate signal to the user program */
	switch (trapnr) {

	/* This table works in conjuction with the one in ./mach-common/entry.S
	 * Some exceptions are handled there (in assembly, in exception space)
	 * Some are handled here, (in C, in interrupt space)
	 * Some, like CPLB, are handled in both, where the normal path is
	 * handled in assembly/exception space, and the error path is handled
	 * here
	 */

	/* 0x00 - Linux Syscall, getting here is an error */
	/* 0x01 - userspace gdb breakpoint, handled here */
	case VEC_EXCPT01:
		info.si_code = TRAP_ILLTRAP;
		sig = SIGTRAP;
		CHK_DEBUGGER_TRAP_MAYBE();
		/* Check if this is a breakpoint in kernel space */
		if (fp->ipend & 0xffc0)
			return;
		else
			break;
M
Mike Frysinger 已提交
315
	/* 0x03 - User Defined, userspace stack overflow */
B
Bryan Wu 已提交
316 317 318
	case VEC_EXCPT03:
		info.si_code = SEGV_STACKFLOW;
		sig = SIGSEGV;
319
		verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
320
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
321
		break;
322 323 324 325 326 327 328 329
	/* 0x02 - KGDB initial connection and break signal trap */
	case VEC_EXCPT02:
#ifdef CONFIG_KGDB
		info.si_code = TRAP_ILLTRAP;
		sig = SIGTRAP;
		CHK_DEBUGGER_TRAP();
		return;
#endif
330 331 332 333 334 335 336 337 338 339 340 341
	/* 0x04 - User Defined */
	/* 0x05 - User Defined */
	/* 0x06 - User Defined */
	/* 0x07 - User Defined */
	/* 0x08 - User Defined */
	/* 0x09 - User Defined */
	/* 0x0A - User Defined */
	/* 0x0B - User Defined */
	/* 0x0C - User Defined */
	/* 0x0D - User Defined */
	/* 0x0E - User Defined */
	/* 0x0F - User Defined */
342
	/* If we got here, it is most likely that someone was trying to use a
343 344 345 346 347
	 * custom exception handler, and it is not actually installed properly
	 */
	case VEC_EXCPT04 ... VEC_EXCPT15:
		info.si_code = ILL_ILLPARAOP;
		sig = SIGILL;
348
		verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE));
349 350
		CHK_DEBUGGER_TRAP_MAYBE();
		break;
B
Bryan Wu 已提交
351 352 353 354 355 356 357 358 359 360 361 362 363 364
	/* 0x10 HW Single step, handled here */
	case VEC_STEP:
		info.si_code = TRAP_STEP;
		sig = SIGTRAP;
		CHK_DEBUGGER_TRAP_MAYBE();
		/* Check if this is a single step in kernel space */
		if (fp->ipend & 0xffc0)
			return;
		else
			break;
	/* 0x11 - Trace Buffer Full, handled here */
	case VEC_OVFLOW:
		info.si_code = TRAP_TRACEFLOW;
		sig = SIGTRAP;
365
		verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
366
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
		break;
	/* 0x12 - Reserved, Caught by default */
	/* 0x13 - Reserved, Caught by default */
	/* 0x14 - Reserved, Caught by default */
	/* 0x15 - Reserved, Caught by default */
	/* 0x16 - Reserved, Caught by default */
	/* 0x17 - Reserved, Caught by default */
	/* 0x18 - Reserved, Caught by default */
	/* 0x19 - Reserved, Caught by default */
	/* 0x1A - Reserved, Caught by default */
	/* 0x1B - Reserved, Caught by default */
	/* 0x1C - Reserved, Caught by default */
	/* 0x1D - Reserved, Caught by default */
	/* 0x1E - Reserved, Caught by default */
	/* 0x1F - Reserved, Caught by default */
	/* 0x20 - Reserved, Caught by default */
	/* 0x21 - Undefined Instruction, handled here */
	case VEC_UNDEF_I:
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
#ifdef CONFIG_BUG
		if (kernel_mode_regs(fp)) {
			switch (report_bug(fp->pc, fp)) {
			case BUG_TRAP_TYPE_NONE:
				break;
			case BUG_TRAP_TYPE_WARN:
				dump_bfin_trace_buffer();
				fp->pc += 2;
				goto traps_done;
			case BUG_TRAP_TYPE_BUG:
				/* call to panic() will dump trace, and it is
				 * off at this point, so it won't be clobbered
				 */
				panic("BUG()");
			}
		}
#endif
B
Bryan Wu 已提交
402 403
		info.si_code = ILL_ILLOPC;
		sig = SIGILL;
404
		verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
405
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
406 407 408 409 410
		break;
	/* 0x22 - Illegal Instruction Combination, handled here */
	case VEC_ILGAL_I:
		info.si_code = ILL_ILLPARAOP;
		sig = SIGILL;
411
		verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
412
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
413
		break;
414
	/* 0x23 - Data CPLB protection violation, handled here */
B
Bryan Wu 已提交
415 416
	case VEC_CPLB_VL:
		info.si_code = ILL_CPLB_VI;
417
		sig = SIGBUS;
418
		verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
419
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
420 421 422 423 424
		break;
	/* 0x24 - Data access misaligned, handled here */
	case VEC_MISALI_D:
		info.si_code = BUS_ADRALN;
		sig = SIGBUS;
425
		verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
426
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
427 428 429 430 431
		break;
	/* 0x25 - Unrecoverable Event, handled here */
	case VEC_UNCOV:
		info.si_code = ILL_ILLEXCPT;
		sig = SIGILL;
432
		verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
433
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
434 435 436 437 438 439
		break;
	/* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
		error case is handled here */
	case VEC_CPLB_M:
		info.si_code = BUS_ADRALN;
		sig = SIGBUS;
440
		verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
B
Bryan Wu 已提交
441 442 443 444 445
		break;
	/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
	case VEC_CPLB_MHIT:
		info.si_code = ILL_CPLB_MULHIT;
		sig = SIGSEGV;
446
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
447
		if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
448
			verbose_printk(KERN_NOTICE "NULL pointer access\n");
449
		else
B
Bryan Wu 已提交
450
#endif
451
			verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
452
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
453 454 455 456 457
		break;
	/* 0x28 - Emulation Watchpoint, handled here */
	case VEC_WATCH:
		info.si_code = TRAP_WATCHPT;
		sig = SIGTRAP;
458
		pr_debug(EXC_0x28(KERN_DEBUG));
B
Bryan Wu 已提交
459 460 461 462 463 464 465 466 467 468 469
		CHK_DEBUGGER_TRAP_MAYBE();
		/* Check if this is a watchpoint in kernel space */
		if (fp->ipend & 0xffc0)
			return;
		else
			break;
#ifdef CONFIG_BF535
	/* 0x29 - Instruction fetch access error (535 only) */
	case VEC_ISTRU_VL:      /* ADSP-BF535 only (MH) */
		info.si_code = BUS_OPFETCH;
		sig = SIGBUS;
470
		verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
471
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
472 473 474 475 476 477 478 479
		break;
#else
	/* 0x29 - Reserved, Caught by default */
#endif
	/* 0x2A - Instruction fetch misaligned, handled here */
	case VEC_MISALI_I:
		info.si_code = BUS_ADRALN;
		sig = SIGBUS;
480
		verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
481
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
482
		break;
483
	/* 0x2B - Instruction CPLB protection violation, handled here */
B
Bryan Wu 已提交
484 485
	case VEC_CPLB_I_VL:
		info.si_code = ILL_CPLB_VI;
486
		sig = SIGBUS;
487
		verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
488
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
489 490 491 492 493
		break;
	/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
	case VEC_CPLB_I_M:
		info.si_code = ILL_CPLB_MISS;
		sig = SIGBUS;
494
		verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
B
Bryan Wu 已提交
495 496 497 498 499
		break;
	/* 0x2D - Instruction CPLB Multiple Hits, handled here */
	case VEC_CPLB_I_MHIT:
		info.si_code = ILL_CPLB_MULHIT;
		sig = SIGSEGV;
500
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
501
		if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
502
			verbose_printk(KERN_NOTICE "Jump to NULL address\n");
503
		else
B
Bryan Wu 已提交
504
#endif
505
			verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
506
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
507 508 509 510 511
		break;
	/* 0x2E - Illegal use of Supervisor Resource, handled here */
	case VEC_ILL_RES:
		info.si_code = ILL_PRVOPC;
		sig = SIGILL;
512
		verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
513
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
		break;
	/* 0x2F - Reserved, Caught by default */
	/* 0x30 - Reserved, Caught by default */
	/* 0x31 - Reserved, Caught by default */
	/* 0x32 - Reserved, Caught by default */
	/* 0x33 - Reserved, Caught by default */
	/* 0x34 - Reserved, Caught by default */
	/* 0x35 - Reserved, Caught by default */
	/* 0x36 - Reserved, Caught by default */
	/* 0x37 - Reserved, Caught by default */
	/* 0x38 - Reserved, Caught by default */
	/* 0x39 - Reserved, Caught by default */
	/* 0x3A - Reserved, Caught by default */
	/* 0x3B - Reserved, Caught by default */
	/* 0x3C - Reserved, Caught by default */
	/* 0x3D - Reserved, Caught by default */
	/* 0x3E - Reserved, Caught by default */
	/* 0x3F - Reserved, Caught by default */
532 533 534 535 536 537 538 539
	case VEC_HWERR:
		info.si_code = BUS_ADRALN;
		sig = SIGBUS;
		switch (fp->seqstat & SEQSTAT_HWERRCAUSE) {
		/* System MMR Error */
		case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
			info.si_code = BUS_ADRALN;
			sig = SIGBUS;
540
			verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
541 542 543 544 545
			break;
		/* External Memory Addressing Error */
		case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
			info.si_code = BUS_ADRERR;
			sig = SIGBUS;
546
			verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
547 548 549
			break;
		/* Performance Monitor Overflow */
		case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
550
			verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
551 552 553 554 555 556 557 558 559
			break;
		/* RAISE 5 instruction */
		case (SEQSTAT_HWERRCAUSE_RAISE_5):
			printk(KERN_NOTICE HWC_x18(KERN_NOTICE));
			break;
		default:        /* Reserved */
			printk(KERN_NOTICE HWC_default(KERN_NOTICE));
			break;
		}
560
		CHK_DEBUGGER_TRAP_MAYBE();
561
		break;
562 563 564 565
	/*
	 * We should be handling all known exception types above,
	 * if we get here we hit a reserved one, so panic
	 */
B
Bryan Wu 已提交
566
	default:
567 568 569
		oops_in_progress = 1;
		info.si_code = ILL_ILLPARAOP;
		sig = SIGILL;
570
		verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
B
Bryan Wu 已提交
571
			(fp->seqstat & SEQSTAT_EXCAUSE));
572
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
573 574 575
		break;
	}

576 577 578
	BUG_ON(sig == 0);

	if (sig != SIGTRAP) {
579
		dump_bfin_process(fp);
580
		dump_bfin_mem(fp);
581
		show_regs(fp);
582 583 584 585

		/* Print out the trace buffer if it makes sense */
#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
		if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
586
			verbose_printk(KERN_NOTICE "No trace since you do not have "
587 588 589 590 591
				"CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"
				KERN_NOTICE "\n");
		else
#endif
			dump_bfin_trace_buffer();
592

593
		if (oops_in_progress) {
594
			/* Dump the current kernel stack */
595
			verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
596
			show_stack(current, NULL);
597
			print_modules();
598
#ifndef CONFIG_ACCESS_CHECK
599
			verbose_printk(KERN_EMERG "Please turn on "
600
			       "CONFIG_ACCESS_CHECK\n");
601
#endif
B
Bryan Wu 已提交
602
			panic("Kernel exception");
603
		} else {
604
#ifdef CONFIG_DEBUG_VERBOSE
605
			unsigned long *stack;
606 607
			/* Dump the user space stack */
			stack = (unsigned long *)rdusp();
608
			verbose_printk(KERN_NOTICE "Userspace Stack\n");
609
			show_stack(NULL, stack);
610
#endif
611
		}
B
Bryan Wu 已提交
612
	}
613

614 615 616 617 618 619 620 621 622
#ifdef CONFIG_IPIPE
	if (!ipipe_trap_notify(fp->seqstat & 0x3f, fp))
#endif
	{
		info.si_signo = sig;
		info.si_errno = 0;
		info.si_addr = (void __user *)fp->pc;
		force_sig_info(sig, &info, current);
	}
B
Bryan Wu 已提交
623

624 625 626
	if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8))
		fp->pc = SAFE_USER_INSTRUCTION;

B
Bryan Wu 已提交
627 628 629 630 631 632
	trace_buffer_restore(j);
	return;
}

/* Typical exception handling routines	*/

633 634
#define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)

635 636 637 638
/*
 * Similar to get_user, do some address checking, then dereference
 * Return true on sucess, false on bad address
 */
639
static bool get_instruction(unsigned short *val, unsigned short *address)
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
{

	unsigned long addr;

	addr = (unsigned long)address;

	/* Check for odd addresses */
	if (addr & 0x1)
		return false;

	/* Check that things do not wrap around */
	if (addr > (addr + 2))
		return false;

	/*
	 * Since we are in exception context, we need to do a little address checking
	 * We need to make sure we are only accessing valid memory, and
	 * we don't read something in the async space that can hang forever
	 */
	if ((addr >= FIXED_CODE_START && (addr + 2) <= physical_mem_end) ||
660
#if L2_LENGTH != 0
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
	    (addr >= L2_START && (addr + 2) <= (L2_START + L2_LENGTH)) ||
#endif
	    (addr >= BOOT_ROM_START && (addr + 2) <= (BOOT_ROM_START + BOOT_ROM_LENGTH)) ||
#if L1_DATA_A_LENGTH != 0
	    (addr >= L1_DATA_A_START && (addr + 2) <= (L1_DATA_A_START + L1_DATA_A_LENGTH)) ||
#endif
#if L1_DATA_B_LENGTH != 0
	    (addr >= L1_DATA_B_START && (addr + 2) <= (L1_DATA_B_START + L1_DATA_B_LENGTH)) ||
#endif
	    (addr >= L1_SCRATCH_START && (addr + 2) <= (L1_SCRATCH_START + L1_SCRATCH_LENGTH)) ||
	    (!(bfin_read_EBIU_AMBCTL0() & B0RDYEN) &&
	       addr >= ASYNC_BANK0_BASE && (addr + 2) <= (ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)) ||
	    (!(bfin_read_EBIU_AMBCTL0() & B1RDYEN) &&
	       addr >= ASYNC_BANK1_BASE && (addr + 2) <= (ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)) ||
	    (!(bfin_read_EBIU_AMBCTL1() & B2RDYEN) &&
	       addr >= ASYNC_BANK2_BASE && (addr + 2) <= (ASYNC_BANK2_BASE + ASYNC_BANK1_SIZE)) ||
	    (!(bfin_read_EBIU_AMBCTL1() & B3RDYEN) &&
	      addr >= ASYNC_BANK3_BASE && (addr + 2) <= (ASYNC_BANK3_BASE + ASYNC_BANK1_SIZE))) {
		*val = *address;
		return true;
	}

#if L1_CODE_LENGTH != 0
	if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) {
685
		isram_memcpy(val, address, 2);
686 687 688 689 690 691 692 693
		return true;
	}
#endif


	return false;
}

694
/*
695 696 697 698 699
 * decode the instruction if we are printing out the trace, as it
 * makes things easier to follow, without running it through objdump
 * These are the normal instructions which cause change of flow, which
 * would be at the source of the trace buffer
 */
700
#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_BFIN_HWTRACE_ON)
701
static void decode_instruction(unsigned short *address)
702 703 704 705 706
{
	unsigned short opcode;

	if (get_instruction(&opcode, address)) {
		if (opcode == 0x0010)
707
			verbose_printk("RTS");
708
		else if (opcode == 0x0011)
709
			verbose_printk("RTI");
710
		else if (opcode == 0x0012)
711
			verbose_printk("RTX");
712 713 714 715 716 717 718 719
		else if (opcode == 0x0013)
			verbose_printk("RTN");
		else if (opcode == 0x0014)
			verbose_printk("RTE");
		else if (opcode == 0x0025)
			verbose_printk("EMUEXCPT");
		else if (opcode == 0x0040 && opcode <= 0x0047)
			verbose_printk("STI R%i", opcode & 7);
720
		else if (opcode >= 0x0050 && opcode <= 0x0057)
721
			verbose_printk("JUMP (P%i)", opcode & 7);
722
		else if (opcode >= 0x0060 && opcode <= 0x0067)
723
			verbose_printk("CALL (P%i)", opcode & 7);
724
		else if (opcode >= 0x0070 && opcode <= 0x0077)
725
			verbose_printk("CALL (PC+P%i)", opcode & 7);
726
		else if (opcode >= 0x0080 && opcode <= 0x0087)
727
			verbose_printk("JUMP (PC+P%i)", opcode & 7);
728 729 730 731
		else if (opcode >= 0x0090 && opcode <= 0x009F)
			verbose_printk("RAISE 0x%x", opcode & 0xF);
		else if (opcode >= 0x00A0 && opcode <= 0x00AF)
			verbose_printk("EXCPT 0x%x", opcode & 0xF);
732
		else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF))
733
			verbose_printk("IF !CC JUMP");
734
		else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff))
735
			verbose_printk("IF CC JUMP");
736
		else if (opcode >= 0x2000 && opcode <= 0x2fff)
737
			verbose_printk("JUMP.S");
738
		else if (opcode >= 0xe080 && opcode <= 0xe0ff)
739
			verbose_printk("LSETUP");
740
		else if (opcode >= 0xe200 && opcode <= 0xe2ff)
741
			verbose_printk("JUMP.L");
742
		else if (opcode >= 0xe300 && opcode <= 0xe3ff)
743
			verbose_printk("CALL pcrel");
744
		else
745
			verbose_printk("0x%04x", opcode);
746 747 748
	}

}
749
#endif
750

B
Bryan Wu 已提交
751 752
void dump_bfin_trace_buffer(void)
{
753
#ifdef CONFIG_DEBUG_VERBOSE
754 755
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
	int tflags, i = 0;
756
	char buf[150];
757
	unsigned short *addr;
758 759 760 761
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
	int j, index;
#endif

B
Bryan Wu 已提交
762 763
	trace_buffer_save(tflags);

764
	printk(KERN_NOTICE "Hardware Trace:\n");
765

766 767 768 769
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
	printk(KERN_NOTICE "WARNING: Expanded trace turned on - can not trace exceptions\n");
#endif

B
Bryan Wu 已提交
770
	if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
771
		for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
772 773
			decode_address(buf, (unsigned long)bfin_read_TBUF());
			printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
774 775 776
			addr = (unsigned short *)bfin_read_TBUF();
			decode_address(buf, (unsigned long)addr);
			printk(KERN_NOTICE "     Source : %s ", buf);
777
			decode_instruction(addr);
778
			printk("\n");
B
Bryan Wu 已提交
779 780 781
		}
	}

782 783
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
	if (trace_buff_offset)
784
		index = trace_buff_offset / 4;
785 786 787 788 789
	else
		index = EXPAND_LEN;

	j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128;
	while (j) {
790 791
		decode_address(buf, software_trace_buff[index]);
		printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
792 793 794
		index -= 1;
		if (index < 0 )
			index = EXPAND_LEN;
795
		decode_address(buf, software_trace_buff[index]);
796 797 798
		printk(KERN_NOTICE "     Source : %s ", buf);
		decode_instruction((unsigned short *)software_trace_buff[index]);
		printk("\n");
799 800 801 802 803 804 805 806
		index -= 1;
		if (index < 0)
			index = EXPAND_LEN;
		j--;
		i++;
	}
#endif

B
Bryan Wu 已提交
807
	trace_buffer_restore(tflags);
808
#endif
809
#endif
B
Bryan Wu 已提交
810 811 812
}
EXPORT_SYMBOL(dump_bfin_trace_buffer);

813 814 815 816 817 818 819 820 821 822 823 824
#ifdef CONFIG_BUG
int is_valid_bugaddr(unsigned long addr)
{
	unsigned short opcode;

	if (!get_instruction(&opcode, (unsigned short *)addr))
		return 0;

	return opcode == BFIN_BUG_OPCODE;
}
#endif

825 826 827 828
/*
 * Checks to see if the address pointed to is either a
 * 16-bit CALL instruction, or a 32-bit CALL instruction
 */
829
static bool is_bfin_call(unsigned short *addr)
B
Bryan Wu 已提交
830
{
831 832
	unsigned short opcode = 0, *ins_addr;
	ins_addr = (unsigned short *)addr;
B
Bryan Wu 已提交
833

834 835
	if (!get_instruction(&opcode, ins_addr))
		return false;
B
Bryan Wu 已提交
836

837 838 839 840 841 842 843
	if ((opcode >= 0x0060 && opcode <= 0x0067) ||
	    (opcode >= 0x0070 && opcode <= 0x0077))
		return true;

	ins_addr--;
	if (!get_instruction(&opcode, ins_addr))
		return false;
B
Bryan Wu 已提交
844

845 846 847 848 849 850
	if (opcode >= 0xE300 && opcode <= 0xE3FF)
		return true;

	return false;

}
851

B
Bryan Wu 已提交
852 853
void show_stack(struct task_struct *task, unsigned long *stack)
{
854
#ifdef CONFIG_PRINTK
855 856 857 858
	unsigned int *addr, *endstack, *fp = 0, *frame;
	unsigned short *ins_addr;
	char buf[150];
	unsigned int i, j, ret_addr, frame_no = 0;
B
Bryan Wu 已提交
859

860 861 862 863
	/*
	 * If we have been passed a specific stack, use that one otherwise
	 *    if we have been passed a task structure, use that, otherwise
	 *    use the stack of where the variable "stack" exists
B
Bryan Wu 已提交
864 865
	 */

866 867 868
	if (stack == NULL) {
		if (task) {
			/* We know this is a kernel stack, so this is the start/end */
B
Bryan Wu 已提交
869
			stack = (unsigned long *)task->thread.ksp;
870 871 872
			endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
		} else {
			/* print out the existing stack info */
B
Bryan Wu 已提交
873
			stack = (unsigned long *)&stack;
874 875 876 877 878
			endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
		}
	} else
		endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);

879
	printk(KERN_NOTICE "Stack info:\n");
880
	decode_address(buf, (unsigned int)stack);
881 882
	printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);

883 884 885 886 887
	if (!access_ok(VERIFY_READ, stack, (unsigned int)endstack - (unsigned int)stack)) {
		printk(KERN_NOTICE "Invalid stack pointer\n");
		return;
	}

888
	/* First thing is to look for a frame pointer */
889
	for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {
890 891 892 893 894 895 896 897 898
		if (*addr & 0x1)
			continue;
		ins_addr = (unsigned short *)*addr;
		ins_addr--;
		if (is_bfin_call(ins_addr))
			fp = addr - 1;

		if (fp) {
			/* Let's check to see if it is a frame pointer */
899 900
			while (fp >= (addr - 1) && fp < endstack
			       && fp && ((unsigned int) fp & 0x3) == 0)
901 902 903 904 905 906 907
				fp = (unsigned int *)*fp;
			if (fp == 0 || fp == endstack) {
				fp = addr - 1;
				break;
			}
			fp = 0;
		}
B
Bryan Wu 已提交
908
	}
909 910
	if (fp) {
		frame = fp;
911
		printk(KERN_NOTICE " FP: (0x%p)\n", fp);
912 913
	} else
		frame = 0;
B
Bryan Wu 已提交
914

915 916 917 918 919 920
	/*
	 * Now that we think we know where things are, we
	 * walk the stack again, this time printing things out
	 * incase there is no frame pointer, we still look for
	 * valid return addresses
	 */
B
Bryan Wu 已提交
921

922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974
	/* First time print out data, next time, print out symbols */
	for (j = 0; j <= 1; j++) {
		if (j)
			printk(KERN_NOTICE "Return addresses in stack:\n");
		else
			printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);

		fp = frame;
		frame_no = 0;

		for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
		     addr <= endstack; addr++, i++) {

			ret_addr = 0;
			if (!j && i % 8 == 0)
				printk("\n" KERN_NOTICE "%p:",addr);

			/* if it is an odd address, or zero, just skip it */
			if (*addr & 0x1 || !*addr)
				goto print;

			ins_addr = (unsigned short *)*addr;

			/* Go back one instruction, and see if it is a CALL */
			ins_addr--;
			ret_addr = is_bfin_call(ins_addr);
 print:
			if (!j && stack == (unsigned long *)addr)
				printk("[%08x]", *addr);
			else if (ret_addr)
				if (j) {
					decode_address(buf, (unsigned int)*addr);
					if (frame == addr) {
						printk(KERN_NOTICE "   frame %2i : %s\n", frame_no, buf);
						continue;
					}
					printk(KERN_NOTICE "    address : %s\n", buf);
				} else
					printk("<%08x>", *addr);
			else if (fp == addr) {
				if (j)
					frame = addr+1;
				else
					printk("(%08x)", *addr);

				fp = (unsigned int *)*addr;
				frame_no++;

			} else if (!j)
				printk(" %08x ", *addr);
		}
		if (!j)
			printk("\n");
B
Bryan Wu 已提交
975
	}
976
#endif
B
Bryan Wu 已提交
977 978 979 980 981
}

void dump_stack(void)
{
	unsigned long stack;
982
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
B
Bryan Wu 已提交
983
	int tflags;
984
#endif
B
Bryan Wu 已提交
985 986 987 988 989 990 991
	trace_buffer_save(tflags);
	dump_bfin_trace_buffer();
	show_stack(current, &stack);
	trace_buffer_restore(tflags);
}
EXPORT_SYMBOL(dump_stack);

992
void dump_bfin_process(struct pt_regs *fp)
B
Bryan Wu 已提交
993
{
994
#ifdef CONFIG_DEBUG_VERBOSE
995 996 997 998 999
	/* We should be able to look at fp->ipend, but we don't push it on the
	 * stack all the time, so do this until we fix that */
	unsigned int context = bfin_read_IPEND();

	if (oops_in_progress)
1000
		verbose_printk(KERN_EMERG "Kernel OOPS in progress\n");
1001

1002
	if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)
1003
		verbose_printk(KERN_NOTICE "HW Error context\n");
1004
	else if (context & 0x0020)
1005
		verbose_printk(KERN_NOTICE "Deferred Exception context\n");
1006
	else if (context & 0x3FC0)
1007
		verbose_printk(KERN_NOTICE "Interrupt context\n");
1008
	else if (context & 0x4000)
1009
		verbose_printk(KERN_NOTICE "Deferred Interrupt context\n");
1010
	else if (context & 0x8000)
1011
		verbose_printk(KERN_NOTICE "Kernel process context\n");
1012

1013 1014 1015
	/* Because we are crashing, and pointers could be bad, we check things
	 * pretty closely before we use them
	 */
1016 1017
	if ((unsigned long)current >= FIXED_CODE_START &&
	    !((unsigned long)current & 0x3) && current->pid) {
1018
		verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n");
1019
		if (current->comm >= (char *)FIXED_CODE_START)
1020
			verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n",
1021 1022
				current->comm, current->pid);
		else
1023
			verbose_printk(KERN_NOTICE "COMM= invalid\n");
1024

1025
		printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
1026
		if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
1027
			verbose_printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
				KERN_NOTICE " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n"
				KERN_NOTICE "\n",
				(void *)current->mm->start_code,
				(void *)current->mm->end_code,
				(void *)current->mm->start_data,
				(void *)current->mm->end_data,
				(void *)current->mm->end_data,
				(void *)current->mm->brk,
				(void *)current->mm->start_stack);
		else
1038
			verbose_printk(KERN_NOTICE "invalid mm\n");
1039
	} else
1040
		verbose_printk(KERN_NOTICE "\n" KERN_NOTICE
1041
		     "No Valid process in current context\n");
1042
#endif
1043
}
1044

1045
void dump_bfin_mem(struct pt_regs *fp)
1046
{
1047
#ifdef CONFIG_DEBUG_VERBOSE
1048 1049
	unsigned short *addr, *erraddr, val = 0, err = 0;
	char sti = 0, buf[6];
B
Bryan Wu 已提交
1050

1051
	erraddr = (void *)fp->pc;
1052

1053
	verbose_printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
1054 1055 1056 1057 1058

	for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10;
	     addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
	     addr++) {
		if (!((unsigned long)addr & 0xF))
1059
			verbose_printk("\n" KERN_NOTICE "0x%p: ", addr);
1060

1061
		if (!get_instruction(&val, addr)) {
1062 1063 1064 1065 1066 1067
				val = 0;
				sprintf(buf, "????");
		} else
			sprintf(buf, "%04x", val);

		if (addr == erraddr) {
1068
			verbose_printk("[%s]", buf);
1069 1070
			err = val;
		} else
1071
			verbose_printk(" %s ", buf);
1072 1073 1074 1075 1076 1077 1078 1079

		/* Do any previous instructions turn on interrupts? */
		if (addr <= erraddr &&				/* in the past */
		    ((val >= 0x0040 && val <= 0x0047) ||	/* STI instruction */
		      val == 0x017b))				/* [SP++] = RETI */
			sti = 1;
	}

1080
	verbose_printk("\n");
1081 1082 1083 1084

	/* Hardware error interrupts can be deferred */
	if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR &&
	    oops_in_progress)){
1085
		verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
B
Bryan Wu 已提交
1086
#ifndef CONFIG_DEBUG_HWERR
1087
		verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n"
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
			KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a"
			 " better idea where it came from\n");
#else
		/* If we are handling only one peripheral interrupt
		 * and current mm and pid are valid, and the last error
		 * was in that user space process's text area
		 * print it out - because that is where the problem exists
		 */
		if ((!(((fp)->ipend & ~0x30) & (((fp)->ipend & ~0x30) - 1))) &&
		     (current->pid && current->mm)) {
			/* And the last RETI points to the current userspace context */
			if ((fp + 1)->pc >= current->mm->start_code &&
			    (fp + 1)->pc <= current->mm->end_code) {
1101 1102
				verbose_printk(KERN_NOTICE "It might be better to look around here : \n");
				verbose_printk(KERN_NOTICE "-------------------------------------------\n");
1103
				show_regs(fp + 1);
1104
				verbose_printk(KERN_NOTICE "-------------------------------------------\n");
1105
			}
B
Bryan Wu 已提交
1106
		}
1107 1108
#endif
	}
1109
#endif
1110 1111 1112 1113
}

void show_regs(struct pt_regs *fp)
{
1114
#ifdef CONFIG_DEBUG_VERBOSE
1115
	char buf [150];
1116 1117
	struct irqaction *action;
	unsigned int i;
1118
	unsigned long flags = 0;
1119
	unsigned int cpu = smp_processor_id();
1120
	unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
1121

1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
	verbose_printk(KERN_NOTICE "\n");
	if (CPUID != bfin_cpuid())
		verbose_printk(KERN_NOTICE "Compiled for cpu family 0x%04x (Rev %d), "
			"but running on:0x%04x (Rev %d)\n",
			CPUID, bfin_compiled_revid(), bfin_cpuid(), bfin_revid());

	verbose_printk(KERN_NOTICE "ADSP-%s-0.%d",
		CPU, bfin_compiled_revid());

	if (bfin_compiled_revid() !=  bfin_revid())
		verbose_printk("(Detected 0.%d)", bfin_revid());

	verbose_printk(" %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n",
		get_cclk()/1000000, get_sclk()/1000000,
#ifdef CONFIG_MPU
		"mpu on"
#else
		"mpu off"
#endif
		);

	verbose_printk(KERN_NOTICE "%s", linux_banner);

1145 1146
	verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
	verbose_printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
1147
		(long)fp->seqstat, fp->ipend, fp->syscfg);
1148
	if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
1149
		verbose_printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
1150 1151 1152 1153
			(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
#ifdef EBIU_ERRMST
		/* If the error was from the EBIU, print it out */
		if (bfin_read_EBIU_ERRMST() & CORE_ERROR) {
1154
			verbose_printk(KERN_NOTICE "  EBIU Error Reason  : 0x%04x\n",
1155
				bfin_read_EBIU_ERRMST());
1156
			verbose_printk(KERN_NOTICE "  EBIU Error Address : 0x%08x\n",
1157 1158 1159 1160
				bfin_read_EBIU_ERRADD());
		}
#endif
	}
1161
	verbose_printk(KERN_NOTICE "  EXCAUSE   : 0x%lx\n",
1162
		fp->seqstat & SEQSTAT_EXCAUSE);
1163
	for (i = 2; i <= 15 ; i++) {
1164
		if (fp->ipend & (1 << i)) {
1165 1166 1167 1168 1169
			if (i != 4) {
				decode_address(buf, bfin_read32(EVT0 + 4*i));
				verbose_printk(KERN_NOTICE "  physical IVG%i asserted : %s\n", i, buf);
			} else
				verbose_printk(KERN_NOTICE "  interrupts disabled\n");
1170 1171 1172 1173 1174 1175
		}
	}

	/* if no interrupts are going off, don't print this out */
	if (fp->ipend & ~0x3F) {
		for (i = 0; i < (NR_IRQS - 1); i++) {
1176 1177 1178
			if (!in_atomic)
				spin_lock_irqsave(&irq_desc[i].lock, flags);

1179 1180 1181 1182 1183
			action = irq_desc[i].action;
			if (!action)
				goto unlock;

			decode_address(buf, (unsigned int)action->handler);
1184
			verbose_printk(KERN_NOTICE "  logical irq %3d mapped  : %s", i, buf);
1185 1186
			for (action = action->next; action; action = action->next) {
				decode_address(buf, (unsigned int)action->handler);
1187
				verbose_printk(", %s", buf);
1188
			}
1189
			verbose_printk("\n");
1190
unlock:
1191 1192
			if (!in_atomic)
				spin_unlock_irqrestore(&irq_desc[i].lock, flags);
1193 1194
		}
	}
1195

1196
	decode_address(buf, fp->rete);
1197
	verbose_printk(KERN_NOTICE " RETE: %s\n", buf);
1198
	decode_address(buf, fp->retn);
1199
	verbose_printk(KERN_NOTICE " RETN: %s\n", buf);
1200
	decode_address(buf, fp->retx);
1201
	verbose_printk(KERN_NOTICE " RETX: %s\n", buf);
1202
	decode_address(buf, fp->rets);
1203
	verbose_printk(KERN_NOTICE " RETS: %s\n", buf);
1204
	decode_address(buf, fp->pc);
1205
	verbose_printk(KERN_NOTICE " PC  : %s\n", buf);
1206

1207 1208
	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
	    (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
1209
		decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
1210
		verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
1211
		decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
1212
		verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
1213 1214
	}

1215 1216
	verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
	verbose_printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
1217
		fp->r0, fp->r1, fp->r2, fp->r3);
1218
	verbose_printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",
1219
		fp->r4, fp->r5, fp->r6, fp->r7);
1220
	verbose_printk(KERN_NOTICE " P0 : %08lx    P1 : %08lx    P2 : %08lx    P3 : %08lx\n",
1221
		fp->p0, fp->p1, fp->p2, fp->p3);
1222
	verbose_printk(KERN_NOTICE " P4 : %08lx    P5 : %08lx    FP : %08lx    SP : %08lx\n",
1223
		fp->p4, fp->p5, fp->fp, (long)fp);
1224
	verbose_printk(KERN_NOTICE " LB0: %08lx    LT0: %08lx    LC0: %08lx\n",
1225
		fp->lb0, fp->lt0, fp->lc0);
1226
	verbose_printk(KERN_NOTICE " LB1: %08lx    LT1: %08lx    LC1: %08lx\n",
1227
		fp->lb1, fp->lt1, fp->lc1);
1228
	verbose_printk(KERN_NOTICE " B0 : %08lx    L0 : %08lx    M0 : %08lx    I0 : %08lx\n",
1229
		fp->b0, fp->l0, fp->m0, fp->i0);
1230
	verbose_printk(KERN_NOTICE " B1 : %08lx    L1 : %08lx    M1 : %08lx    I1 : %08lx\n",
1231
		fp->b1, fp->l1, fp->m1, fp->i1);
1232
	verbose_printk(KERN_NOTICE " B2 : %08lx    L2 : %08lx    M2 : %08lx    I2 : %08lx\n",
1233
		fp->b2, fp->l2, fp->m2, fp->i2);
1234
	verbose_printk(KERN_NOTICE " B3 : %08lx    L3 : %08lx    M3 : %08lx    I3 : %08lx\n",
1235
		fp->b3, fp->l3, fp->m3, fp->i3);
1236
	verbose_printk(KERN_NOTICE "A0.w: %08lx   A0.x: %08lx   A1.w: %08lx   A1.x: %08lx\n",
1237
		fp->a0w, fp->a0x, fp->a1w, fp->a1x);
1238

1239
	verbose_printk(KERN_NOTICE "USP : %08lx  ASTAT: %08lx\n",
1240
		rdusp(), fp->astat);
B
Bryan Wu 已提交
1241

1242 1243
	verbose_printk(KERN_NOTICE "\n");
#endif
B
Bryan Wu 已提交
1244 1245 1246 1247 1248 1249
}

#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
#endif

1250 1251 1252
static DEFINE_SPINLOCK(bfin_spinlock_lock);

asmlinkage int sys_bfin_spinlock(int *p)
B
Bryan Wu 已提交
1253
{
1254
	int ret, tmp = 0;
B
Bryan Wu 已提交
1255

1256 1257 1258 1259
	spin_lock(&bfin_spinlock_lock);	/* This would also hold kernel preemption. */
	ret = get_user(tmp, p);
	if (likely(ret == 0)) {
		if (unlikely(tmp))
B
Bryan Wu 已提交
1260
			ret = 1;
1261 1262
		else
			put_user(1, p);
B
Bryan Wu 已提交
1263
	}
1264
	spin_unlock(&bfin_spinlock_lock);
B
Bryan Wu 已提交
1265 1266 1267
	return ret;
}

1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
int bfin_request_exception(unsigned int exception, void (*handler)(void))
{
	void (*curr_handler)(void);

	if (exception > 0x3F)
		return -EINVAL;

	curr_handler = ex_table[exception];

	if (curr_handler != ex_replaceable)
		return -EBUSY;

	ex_table[exception] = handler;

	return 0;
}
EXPORT_SYMBOL(bfin_request_exception);

int bfin_free_exception(unsigned int exception, void (*handler)(void))
{
	void (*curr_handler)(void);

	if (exception > 0x3F)
		return -EINVAL;

	curr_handler = ex_table[exception];

	if (curr_handler != handler)
		return -EBUSY;

	ex_table[exception] = ex_replaceable;

	return 0;
}
EXPORT_SYMBOL(bfin_free_exception);

B
Bryan Wu 已提交
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318
void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
{
	switch (cplb_panic) {
	case CPLB_NO_UNLOCKED:
		printk(KERN_EMERG "All CPLBs are locked\n");
		break;
	case CPLB_PROT_VIOL:
		return;
	case CPLB_NO_ADDR_MATCH:
		return;
	case CPLB_UNKNOWN_ERR:
		printk(KERN_EMERG "Unknown CPLB Exception\n");
		break;
	}

1319 1320
	oops_in_progress = 1;

1321
	dump_bfin_process(fp);
1322
	dump_bfin_mem(fp);
1323
	show_regs(fp);
B
Bryan Wu 已提交
1324
	dump_stack();
1325
	panic("Unrecoverable event");
B
Bryan Wu 已提交
1326
}