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

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

# define CHK_DEBUGGER_TRAP() \
	do { \
50
		kgdb_handle_exception(trapnr, sig, info.si_code, fp); \
51 52 53 54 55 56 57 58 59
	} 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 已提交
60 61
#endif

62

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

B
Bryan Wu 已提交
71 72 73 74 75 76 77 78
/* Initiate the event table handler */
void __init trap_init(void)
{
	CSYNC();
	bfin_write_EVT3(trap);
	CSYNC();
}

79
static void decode_address(char *buf, unsigned long address)
B
Bryan Wu 已提交
80
{
81
#ifdef CONFIG_DEBUG_VERBOSE
B
Bryan Wu 已提交
82 83 84
	struct vm_list_struct *vml;
	struct task_struct *p;
	struct mm_struct *mm;
85
	unsigned long flags, offset;
86
	unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
87
	struct rb_node *n;
B
Bryan Wu 已提交
88 89

#ifdef CONFIG_KALLSYMS
90
	unsigned long symsize;
B
Bryan Wu 已提交
91 92 93 94 95 96 97 98 99 100 101 102
	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 = "";
103
		sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }",
104
		              (void *)address, delim, modname, delim, symname,
B
Bryan Wu 已提交
105
		              (unsigned long)offset);
106
		return;
B
Bryan Wu 已提交
107 108 109 110

	}
#endif

111 112 113 114 115 116 117 118 119 120 121 122
	/* 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 已提交
123 124 125 126
	/* 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
	 */
127
	write_lock_irqsave(&tasklist_lock, flags);
B
Bryan Wu 已提交
128
	for_each_process(p) {
129
		mm = (in_atomic ? p->mm : get_task_mm(p));
B
Bryan Wu 已提交
130 131 132
		if (!mm)
			continue;

133 134 135 136
		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 已提交
137 138

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

143 144
				if (file) {
					char *d_name = d_path(&file->f_path, _tmpbuf,
145
						      sizeof(_tmpbuf));
146 147 148
					if (!IS_ERR(d_name))
						name = d_name;
				}
B
Bryan Wu 已提交
149

150 151 152
				/* FLAT does not have its text aligned to the start of
				 * the map while FDPIC ELF does ...
				 */
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

				/* 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);

174
				if (!in_atomic)
175
					mmput(mm);
176

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

180
				goto done;
B
Bryan Wu 已提交
181 182
			}
		}
183
		if (!in_atomic)
184
			mmput(mm);
B
Bryan Wu 已提交
185 186 187
	}

	/* we were unable to find this address anywhere */
188
	sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
189 190 191

done:
	write_unlock_irqrestore(&tasklist_lock, flags);
192 193 194
#else
	sprintf(buf, " ");
#endif
B
Bryan Wu 已提交
195 196
}

197 198
asmlinkage void double_fault_c(struct pt_regs *fp)
{
199 200
	console_verbose();
	oops_in_progress = 1;
201
#ifdef CONFIG_DEBUG_VERBOSE
202
	printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
203 204
#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) == VEC_UNCOV) {
205
		unsigned int cpu = smp_processor_id();
206
		char buf[150];
207
		decode_address(buf, cpu_pda[cpu].retx);
208
		printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
209 210
			(unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
		decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
211
		printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %s\n", buf);
212
		decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
213 214 215
		printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %s\n", buf);

		decode_address(buf, fp->retx);
216
		printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf);
217 218 219 220 221 222 223
	} else
#endif
	{
		dump_bfin_process(fp);
		dump_bfin_mem(fp);
		show_regs(fp);
	}
224
#endif
225 226 227 228
	panic("Double Fault - unrecoverable event\n");

}

B
Bryan Wu 已提交
229 230
asmlinkage void trap_c(struct pt_regs *fp)
{
231 232
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
	int j;
233 234 235
#endif
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
	unsigned int cpu = smp_processor_id();
236 237
#endif
	int sig = 0;
B
Bryan Wu 已提交
238 239 240
	siginfo_t info;
	unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;

241 242 243 244 245 246 247 248 249 250
	trace_buffer_save(j);

	/* 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
	*/
251 252 253 254

	/* TODO: check to see if we are in some sort of deferred HWERR
	 * that we should be able to recover from, not kernel panic
	 */
255
	if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP)
B
Bryan Wu 已提交
256
#ifdef CONFIG_KGDB
257
		&& (trapnr != VEC_EXCPT02)
B
Bryan Wu 已提交
258
#endif
259 260 261 262 263 264 265 266 267
	){
		console_verbose();
		oops_in_progress = 1;
	} else if (current) {
		if (current->mm == NULL) {
			console_verbose();
			oops_in_progress = 1;
		}
	}
B
Bryan Wu 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298

	/* 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 已提交
299
	/* 0x03 - User Defined, userspace stack overflow */
B
Bryan Wu 已提交
300 301 302
	case VEC_EXCPT03:
		info.si_code = SEGV_STACKFLOW;
		sig = SIGSEGV;
303
		verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
304
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
305
		break;
306 307 308 309 310 311 312 313
	/* 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
314 315 316 317 318 319 320 321 322 323 324 325
	/* 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 */
326
	/* If we got here, it is most likely that someone was trying to use a
327 328 329 330 331
	 * custom exception handler, and it is not actually installed properly
	 */
	case VEC_EXCPT04 ... VEC_EXCPT15:
		info.si_code = ILL_ILLPARAOP;
		sig = SIGILL;
332
		verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE));
333 334
		CHK_DEBUGGER_TRAP_MAYBE();
		break;
B
Bryan Wu 已提交
335 336 337 338 339 340 341 342 343 344 345 346 347 348
	/* 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;
349
		verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
350
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
		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:
		info.si_code = ILL_ILLOPC;
		sig = SIGILL;
371
		verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
372
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
373 374 375 376 377
		break;
	/* 0x22 - Illegal Instruction Combination, handled here */
	case VEC_ILGAL_I:
		info.si_code = ILL_ILLPARAOP;
		sig = SIGILL;
378
		verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
379
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
380
		break;
381
	/* 0x23 - Data CPLB protection violation, handled here */
B
Bryan Wu 已提交
382 383
	case VEC_CPLB_VL:
		info.si_code = ILL_CPLB_VI;
384
		sig = SIGBUS;
385
		verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
386
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
387 388 389 390 391
		break;
	/* 0x24 - Data access misaligned, handled here */
	case VEC_MISALI_D:
		info.si_code = BUS_ADRALN;
		sig = SIGBUS;
392
		verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
393
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
394 395 396 397 398
		break;
	/* 0x25 - Unrecoverable Event, handled here */
	case VEC_UNCOV:
		info.si_code = ILL_ILLEXCPT;
		sig = SIGILL;
399
		verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
400
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
401 402 403 404 405 406
		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;
407
		verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
B
Bryan Wu 已提交
408 409 410 411 412
		break;
	/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
	case VEC_CPLB_MHIT:
		info.si_code = ILL_CPLB_MULHIT;
		sig = SIGSEGV;
413
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
414
		if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
415
			verbose_printk(KERN_NOTICE "NULL pointer access\n");
416
		else
B
Bryan Wu 已提交
417
#endif
418
			verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
419
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
420 421 422 423 424
		break;
	/* 0x28 - Emulation Watchpoint, handled here */
	case VEC_WATCH:
		info.si_code = TRAP_WATCHPT;
		sig = SIGTRAP;
425
		pr_debug(EXC_0x28(KERN_DEBUG));
B
Bryan Wu 已提交
426 427 428 429 430 431 432 433 434 435 436
		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;
437
		verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
438
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
439 440 441 442 443 444 445 446
		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;
447
		verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
448
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
449
		break;
450
	/* 0x2B - Instruction CPLB protection violation, handled here */
B
Bryan Wu 已提交
451 452
	case VEC_CPLB_I_VL:
		info.si_code = ILL_CPLB_VI;
453
		sig = SIGBUS;
454
		verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
455
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
456 457 458 459 460
		break;
	/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
	case VEC_CPLB_I_M:
		info.si_code = ILL_CPLB_MISS;
		sig = SIGBUS;
461
		verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
B
Bryan Wu 已提交
462 463 464 465 466
		break;
	/* 0x2D - Instruction CPLB Multiple Hits, handled here */
	case VEC_CPLB_I_MHIT:
		info.si_code = ILL_CPLB_MULHIT;
		sig = SIGSEGV;
467
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
468
		if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
469
			verbose_printk(KERN_NOTICE "Jump to NULL address\n");
470
		else
B
Bryan Wu 已提交
471
#endif
472
			verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
473
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
474 475 476 477 478
		break;
	/* 0x2E - Illegal use of Supervisor Resource, handled here */
	case VEC_ILL_RES:
		info.si_code = ILL_PRVOPC;
		sig = SIGILL;
479
		verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
480
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
		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 */
499 500 501 502 503 504 505 506
	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;
507
			verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
508 509 510 511 512
			break;
		/* External Memory Addressing Error */
		case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
			info.si_code = BUS_ADRERR;
			sig = SIGBUS;
513
			verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
514 515 516
			break;
		/* Performance Monitor Overflow */
		case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
517
			verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
518 519 520 521 522 523 524 525 526
			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;
		}
527
		CHK_DEBUGGER_TRAP_MAYBE();
528
		break;
529 530 531 532
	/*
	 * We should be handling all known exception types above,
	 * if we get here we hit a reserved one, so panic
	 */
B
Bryan Wu 已提交
533
	default:
534 535 536
		oops_in_progress = 1;
		info.si_code = ILL_ILLPARAOP;
		sig = SIGILL;
537
		verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
B
Bryan Wu 已提交
538
			(fp->seqstat & SEQSTAT_EXCAUSE));
539
		CHK_DEBUGGER_TRAP_MAYBE();
B
Bryan Wu 已提交
540 541 542
		break;
	}

543 544 545
	BUG_ON(sig == 0);

	if (sig != SIGTRAP) {
546
		dump_bfin_process(fp);
547
		dump_bfin_mem(fp);
548
		show_regs(fp);
549 550 551 552

		/* 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)
553
			verbose_printk(KERN_NOTICE "No trace since you do not have "
554 555 556 557 558
				"CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"
				KERN_NOTICE "\n");
		else
#endif
			dump_bfin_trace_buffer();
559

560
		if (oops_in_progress) {
561
			/* Dump the current kernel stack */
562
			verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
563
			show_stack(current, NULL);
564
			print_modules();
565
#ifndef CONFIG_ACCESS_CHECK
566
			verbose_printk(KERN_EMERG "Please turn on "
567
			       "CONFIG_ACCESS_CHECK\n");
568
#endif
B
Bryan Wu 已提交
569
			panic("Kernel exception");
570
		} else {
571
#ifdef CONFIG_DEBUG_VERBOSE
572
			unsigned long *stack;
573 574
			/* Dump the user space stack */
			stack = (unsigned long *)rdusp();
575
			verbose_printk(KERN_NOTICE "Userspace Stack\n");
576
			show_stack(NULL, stack);
577
#endif
578
		}
B
Bryan Wu 已提交
579
	}
580

581 582 583 584 585 586 587 588 589
#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 已提交
590 591 592 593 594 595 596

	trace_buffer_restore(j);
	return;
}

/* Typical exception handling routines	*/

597 598
#define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)

599 600 601 602
/*
 * Similar to get_user, do some address checking, then dereference
 * Return true on sucess, false on bad address
 */
603
static bool get_instruction(unsigned short *val, unsigned short *address)
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
{

	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) ||
624
#if L2_LENGTH != 0
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
	    (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)) {
649
		isram_memcpy(val, address, 2);
650 651 652 653 654 655 656 657
		return true;
	}
#endif


	return false;
}

658
/*
659 660 661 662 663
 * 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
 */
664
#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_BFIN_HWTRACE_ON)
665
static void decode_instruction(unsigned short *address)
666 667 668 669 670
{
	unsigned short opcode;

	if (get_instruction(&opcode, address)) {
		if (opcode == 0x0010)
671
			verbose_printk("RTS");
672
		else if (opcode == 0x0011)
673
			verbose_printk("RTI");
674
		else if (opcode == 0x0012)
675
			verbose_printk("RTX");
676 677 678 679 680 681 682 683
		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);
684
		else if (opcode >= 0x0050 && opcode <= 0x0057)
685
			verbose_printk("JUMP (P%i)", opcode & 7);
686
		else if (opcode >= 0x0060 && opcode <= 0x0067)
687
			verbose_printk("CALL (P%i)", opcode & 7);
688
		else if (opcode >= 0x0070 && opcode <= 0x0077)
689
			verbose_printk("CALL (PC+P%i)", opcode & 7);
690
		else if (opcode >= 0x0080 && opcode <= 0x0087)
691
			verbose_printk("JUMP (PC+P%i)", opcode & 7);
692 693 694 695
		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);
696
		else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF))
697
			verbose_printk("IF !CC JUMP");
698
		else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff))
699
			verbose_printk("IF CC JUMP");
700
		else if (opcode >= 0x2000 && opcode <= 0x2fff)
701
			verbose_printk("JUMP.S");
702
		else if (opcode >= 0xe080 && opcode <= 0xe0ff)
703
			verbose_printk("LSETUP");
704
		else if (opcode >= 0xe200 && opcode <= 0xe2ff)
705
			verbose_printk("JUMP.L");
706
		else if (opcode >= 0xe300 && opcode <= 0xe3ff)
707
			verbose_printk("CALL pcrel");
708
		else
709
			verbose_printk("0x%04x", opcode);
710 711 712
	}

}
713
#endif
714

B
Bryan Wu 已提交
715 716
void dump_bfin_trace_buffer(void)
{
717
#ifdef CONFIG_DEBUG_VERBOSE
718 719
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
	int tflags, i = 0;
720
	char buf[150];
721
	unsigned short *addr;
722 723 724 725
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
	int j, index;
#endif

B
Bryan Wu 已提交
726 727
	trace_buffer_save(tflags);

728
	printk(KERN_NOTICE "Hardware Trace:\n");
729

730 731 732 733
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
	printk(KERN_NOTICE "WARNING: Expanded trace turned on - can not trace exceptions\n");
#endif

B
Bryan Wu 已提交
734
	if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
735
		for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
736 737
			decode_address(buf, (unsigned long)bfin_read_TBUF());
			printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
738 739 740
			addr = (unsigned short *)bfin_read_TBUF();
			decode_address(buf, (unsigned long)addr);
			printk(KERN_NOTICE "     Source : %s ", buf);
741
			decode_instruction(addr);
742
			printk("\n");
B
Bryan Wu 已提交
743 744 745
		}
	}

746 747
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
	if (trace_buff_offset)
748
		index = trace_buff_offset / 4;
749 750 751 752 753
	else
		index = EXPAND_LEN;

	j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128;
	while (j) {
754 755
		decode_address(buf, software_trace_buff[index]);
		printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
756 757 758
		index -= 1;
		if (index < 0 )
			index = EXPAND_LEN;
759
		decode_address(buf, software_trace_buff[index]);
760 761 762
		printk(KERN_NOTICE "     Source : %s ", buf);
		decode_instruction((unsigned short *)software_trace_buff[index]);
		printk("\n");
763 764 765 766 767 768 769 770
		index -= 1;
		if (index < 0)
			index = EXPAND_LEN;
		j--;
		i++;
	}
#endif

B
Bryan Wu 已提交
771
	trace_buffer_restore(tflags);
772
#endif
773
#endif
B
Bryan Wu 已提交
774 775 776
}
EXPORT_SYMBOL(dump_bfin_trace_buffer);

777 778 779 780
/*
 * Checks to see if the address pointed to is either a
 * 16-bit CALL instruction, or a 32-bit CALL instruction
 */
781
static bool is_bfin_call(unsigned short *addr)
B
Bryan Wu 已提交
782
{
783 784
	unsigned short opcode = 0, *ins_addr;
	ins_addr = (unsigned short *)addr;
B
Bryan Wu 已提交
785

786 787
	if (!get_instruction(&opcode, ins_addr))
		return false;
B
Bryan Wu 已提交
788

789 790 791 792 793 794 795
	if ((opcode >= 0x0060 && opcode <= 0x0067) ||
	    (opcode >= 0x0070 && opcode <= 0x0077))
		return true;

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

797 798 799 800 801 802
	if (opcode >= 0xE300 && opcode <= 0xE3FF)
		return true;

	return false;

}
803

B
Bryan Wu 已提交
804 805
void show_stack(struct task_struct *task, unsigned long *stack)
{
806
#ifdef CONFIG_PRINTK
807 808 809 810
	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 已提交
811

812 813 814 815
	/*
	 * 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 已提交
816 817
	 */

818 819 820
	if (stack == NULL) {
		if (task) {
			/* We know this is a kernel stack, so this is the start/end */
B
Bryan Wu 已提交
821
			stack = (unsigned long *)task->thread.ksp;
822 823 824
			endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
		} else {
			/* print out the existing stack info */
B
Bryan Wu 已提交
825
			stack = (unsigned long *)&stack;
826 827 828 829 830
			endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
		}
	} else
		endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);

831
	printk(KERN_NOTICE "Stack info:\n");
832
	decode_address(buf, (unsigned int)stack);
833 834
	printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);

835
	/* First thing is to look for a frame pointer */
836
	for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {
837 838 839 840 841 842 843 844 845
		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 */
846 847
			while (fp >= (addr - 1) && fp < endstack
			       && fp && ((unsigned int) fp & 0x3) == 0)
848 849 850 851 852 853 854
				fp = (unsigned int *)*fp;
			if (fp == 0 || fp == endstack) {
				fp = addr - 1;
				break;
			}
			fp = 0;
		}
B
Bryan Wu 已提交
855
	}
856 857
	if (fp) {
		frame = fp;
858
		printk(KERN_NOTICE " FP: (0x%p)\n", fp);
859 860
	} else
		frame = 0;
B
Bryan Wu 已提交
861

862 863 864 865 866 867
	/*
	 * 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 已提交
868

869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
	/* 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 已提交
922
	}
923
#endif
B
Bryan Wu 已提交
924 925 926 927 928
}

void dump_stack(void)
{
	unsigned long stack;
929
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
B
Bryan Wu 已提交
930
	int tflags;
931
#endif
B
Bryan Wu 已提交
932 933 934 935 936 937 938
	trace_buffer_save(tflags);
	dump_bfin_trace_buffer();
	show_stack(current, &stack);
	trace_buffer_restore(tflags);
}
EXPORT_SYMBOL(dump_stack);

939
void dump_bfin_process(struct pt_regs *fp)
B
Bryan Wu 已提交
940
{
941
#ifdef CONFIG_DEBUG_VERBOSE
942 943 944 945 946
	/* 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)
947
		verbose_printk(KERN_EMERG "Kernel OOPS in progress\n");
948

949
	if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)
950
		verbose_printk(KERN_NOTICE "HW Error context\n");
951
	else if (context & 0x0020)
952
		verbose_printk(KERN_NOTICE "Deferred Exception context\n");
953
	else if (context & 0x3FC0)
954
		verbose_printk(KERN_NOTICE "Interrupt context\n");
955
	else if (context & 0x4000)
956
		verbose_printk(KERN_NOTICE "Deferred Interrupt context\n");
957
	else if (context & 0x8000)
958
		verbose_printk(KERN_NOTICE "Kernel process context\n");
959

960 961 962
	/* Because we are crashing, and pointers could be bad, we check things
	 * pretty closely before we use them
	 */
963 964
	if ((unsigned long)current >= FIXED_CODE_START &&
	    !((unsigned long)current & 0x3) && current->pid) {
965
		verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n");
966
		if (current->comm >= (char *)FIXED_CODE_START)
967
			verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n",
968 969
				current->comm, current->pid);
		else
970
			verbose_printk(KERN_NOTICE "COMM= invalid\n");
971

972
		printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
973
		if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
974
			verbose_printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
975 976 977 978 979 980 981 982 983 984
				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
985
			verbose_printk(KERN_NOTICE "invalid mm\n");
986
	} else
987
		verbose_printk(KERN_NOTICE "\n" KERN_NOTICE
988
		     "No Valid process in current context\n");
989
#endif
990
}
991

992
void dump_bfin_mem(struct pt_regs *fp)
993
{
994
#ifdef CONFIG_DEBUG_VERBOSE
995 996
	unsigned short *addr, *erraddr, val = 0, err = 0;
	char sti = 0, buf[6];
B
Bryan Wu 已提交
997

998
	erraddr = (void *)fp->pc;
999

1000
	verbose_printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
1001 1002 1003 1004 1005

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

1008
		if (!get_instruction(&val, addr)) {
1009 1010 1011 1012 1013 1014
				val = 0;
				sprintf(buf, "????");
		} else
			sprintf(buf, "%04x", val);

		if (addr == erraddr) {
1015
			verbose_printk("[%s]", buf);
1016 1017
			err = val;
		} else
1018
			verbose_printk(" %s ", buf);
1019 1020 1021 1022 1023 1024 1025 1026

		/* 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;
	}

1027
	verbose_printk("\n");
1028 1029 1030 1031

	/* Hardware error interrupts can be deferred */
	if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR &&
	    oops_in_progress)){
1032
		verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
B
Bryan Wu 已提交
1033
#ifndef CONFIG_DEBUG_HWERR
1034
		verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n"
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
			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) {
1048 1049
				verbose_printk(KERN_NOTICE "It might be better to look around here : \n");
				verbose_printk(KERN_NOTICE "-------------------------------------------\n");
1050
				show_regs(fp + 1);
1051
				verbose_printk(KERN_NOTICE "-------------------------------------------\n");
1052
			}
B
Bryan Wu 已提交
1053
		}
1054 1055
#endif
	}
1056
#endif
1057 1058 1059 1060
}

void show_regs(struct pt_regs *fp)
{
1061
#ifdef CONFIG_DEBUG_VERBOSE
1062
	char buf [150];
1063 1064
	struct irqaction *action;
	unsigned int i;
1065
	unsigned long flags = 0;
1066
	unsigned int cpu = smp_processor_id();
1067
	unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
1068

1069 1070
	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",
1071
		(long)fp->seqstat, fp->ipend, fp->syscfg);
1072
	if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
1073
		verbose_printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
1074 1075 1076 1077
			(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) {
1078
			verbose_printk(KERN_NOTICE "  EBIU Error Reason  : 0x%04x\n",
1079
				bfin_read_EBIU_ERRMST());
1080
			verbose_printk(KERN_NOTICE "  EBIU Error Address : 0x%08x\n",
1081 1082 1083 1084
				bfin_read_EBIU_ERRADD());
		}
#endif
	}
1085
	verbose_printk(KERN_NOTICE "  EXCAUSE   : 0x%lx\n",
1086
		fp->seqstat & SEQSTAT_EXCAUSE);
1087
	for (i = 2; i <= 15 ; i++) {
1088
		if (fp->ipend & (1 << i)) {
1089 1090 1091 1092 1093
			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");
1094 1095 1096 1097 1098 1099
		}
	}

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

1103 1104 1105 1106 1107
			action = irq_desc[i].action;
			if (!action)
				goto unlock;

			decode_address(buf, (unsigned int)action->handler);
1108
			verbose_printk(KERN_NOTICE "  logical irq %3d mapped  : %s", i, buf);
1109 1110
			for (action = action->next; action; action = action->next) {
				decode_address(buf, (unsigned int)action->handler);
1111
				verbose_printk(", %s", buf);
1112
			}
1113
			verbose_printk("\n");
1114
unlock:
1115 1116
			if (!in_atomic)
				spin_unlock_irqrestore(&irq_desc[i].lock, flags);
1117 1118
		}
	}
1119

1120
	decode_address(buf, fp->rete);
1121
	verbose_printk(KERN_NOTICE " RETE: %s\n", buf);
1122
	decode_address(buf, fp->retn);
1123
	verbose_printk(KERN_NOTICE " RETN: %s\n", buf);
1124
	decode_address(buf, fp->retx);
1125
	verbose_printk(KERN_NOTICE " RETX: %s\n", buf);
1126
	decode_address(buf, fp->rets);
1127
	verbose_printk(KERN_NOTICE " RETS: %s\n", buf);
1128
	decode_address(buf, fp->pc);
1129
	verbose_printk(KERN_NOTICE " PC  : %s\n", buf);
1130

1131 1132
	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
	    (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
1133
		decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
1134
		verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
1135
		decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
1136
		verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
1137 1138
	}

1139 1140
	verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
	verbose_printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
1141
		fp->r0, fp->r1, fp->r2, fp->r3);
1142
	verbose_printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",
1143
		fp->r4, fp->r5, fp->r6, fp->r7);
1144
	verbose_printk(KERN_NOTICE " P0 : %08lx    P1 : %08lx    P2 : %08lx    P3 : %08lx\n",
1145
		fp->p0, fp->p1, fp->p2, fp->p3);
1146
	verbose_printk(KERN_NOTICE " P4 : %08lx    P5 : %08lx    FP : %08lx    SP : %08lx\n",
1147
		fp->p4, fp->p5, fp->fp, (long)fp);
1148
	verbose_printk(KERN_NOTICE " LB0: %08lx    LT0: %08lx    LC0: %08lx\n",
1149
		fp->lb0, fp->lt0, fp->lc0);
1150
	verbose_printk(KERN_NOTICE " LB1: %08lx    LT1: %08lx    LC1: %08lx\n",
1151
		fp->lb1, fp->lt1, fp->lc1);
1152
	verbose_printk(KERN_NOTICE " B0 : %08lx    L0 : %08lx    M0 : %08lx    I0 : %08lx\n",
1153
		fp->b0, fp->l0, fp->m0, fp->i0);
1154
	verbose_printk(KERN_NOTICE " B1 : %08lx    L1 : %08lx    M1 : %08lx    I1 : %08lx\n",
1155
		fp->b1, fp->l1, fp->m1, fp->i1);
1156
	verbose_printk(KERN_NOTICE " B2 : %08lx    L2 : %08lx    M2 : %08lx    I2 : %08lx\n",
1157
		fp->b2, fp->l2, fp->m2, fp->i2);
1158
	verbose_printk(KERN_NOTICE " B3 : %08lx    L3 : %08lx    M3 : %08lx    I3 : %08lx\n",
1159
		fp->b3, fp->l3, fp->m3, fp->i3);
1160
	verbose_printk(KERN_NOTICE "A0.w: %08lx   A0.x: %08lx   A1.w: %08lx   A1.x: %08lx\n",
1161
		fp->a0w, fp->a0x, fp->a1w, fp->a1x);
1162

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

1166 1167
	verbose_printk(KERN_NOTICE "\n");
#endif
B
Bryan Wu 已提交
1168 1169 1170 1171 1172 1173
}

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

1174 1175 1176
static DEFINE_SPINLOCK(bfin_spinlock_lock);

asmlinkage int sys_bfin_spinlock(int *p)
B
Bryan Wu 已提交
1177
{
1178
	int ret, tmp = 0;
B
Bryan Wu 已提交
1179

1180 1181 1182 1183
	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 已提交
1184
			ret = 1;
1185 1186
		else
			put_user(1, p);
B
Bryan Wu 已提交
1187
	}
1188
	spin_unlock(&bfin_spinlock_lock);
B
Bryan Wu 已提交
1189 1190 1191
	return ret;
}

1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
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 已提交
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242
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;
	}

1243 1244
	oops_in_progress = 1;

1245
	dump_bfin_process(fp);
1246
	dump_bfin_mem(fp);
1247
	show_regs(fp);
B
Bryan Wu 已提交
1248 1249 1250
	dump_stack();
	panic("Unrecoverable event\n");
}