aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/traps.c
diff options
context:
space:
mode:
authorBryan Wu <bryan.wu@analog.com>2007-05-06 17:50:22 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:12:58 -0400
commit1394f03221790a988afc3e4b3cb79f2e477246a9 (patch)
tree2c1963c9a4f2d84a5e021307fde240c5d567cf70 /arch/blackfin/kernel/traps.c
parent73243284463a761e04d69d22c7516b2be7de096c (diff)
blackfin architecture
This adds support for the Analog Devices Blackfin processor architecture, and currently supports the BF533, BF532, BF531, BF537, BF536, BF534, and BF561 (Dual Core) devices, with a variety of development platforms including those avaliable from Analog Devices (BF533-EZKit, BF533-STAMP, BF537-STAMP, BF561-EZKIT), and Bluetechnix! Tinyboards. The Blackfin architecture was jointly developed by Intel and Analog Devices Inc. (ADI) as the Micro Signal Architecture (MSA) core and introduced it in December of 2000. Since then ADI has put this core into its Blackfin processor family of devices. The Blackfin core has the advantages of a clean, orthogonal,RISC-like microprocessor instruction set. It combines a dual-MAC (Multiply/Accumulate), state-of-the-art signal processing engine and single-instruction, multiple-data (SIMD) multimedia capabilities into a single instruction-set architecture. The Blackfin architecture, including the instruction set, is described by the ADSP-BF53x/BF56x Blackfin Processor Programming Reference http://blackfin.uclinux.org/gf/download/frsrelease/29/2549/Blackfin_PRM.pdf The Blackfin processor is already supported by major releases of gcc, and there are binary and source rpms/tarballs for many architectures at: http://blackfin.uclinux.org/gf/project/toolchain/frs There is complete documentation, including "getting started" guides available at: http://docs.blackfin.uclinux.org/ which provides links to the sources and patches you will need in order to set up a cross-compiling environment for bfin-linux-uclibc This patch, as well as the other patches (toolchain, distribution, uClibc) are actively supported by Analog Devices Inc, at: http://blackfin.uclinux.org/ We have tested this on LTP, and our test plan (including pass/fails) can be found at: http://docs.blackfin.uclinux.org/doku.php?id=testing_the_linux_kernel [m.kozlowski@tuxland.pl: balance parenthesis in blackfin header files] Signed-off-by: Bryan Wu <bryan.wu@analog.com> Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl> Signed-off-by: Aubrey Li <aubrey.li@analog.com> Signed-off-by: Jie Zhang <jie.zhang@analog.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r--arch/blackfin/kernel/traps.c649
1 files changed, 649 insertions, 0 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
new file mode 100644
index 000000000000..9556b73de808
--- /dev/null
+++ b/arch/blackfin/kernel/traps.c
@@ -0,0 +1,649 @@
1/*
2 * File: arch/blackfin/kernel/traps.c
3 * Based on:
4 * Author: Hamish Macdonald
5 *
6 * Created:
7 * Description: uses S/W interrupt 15 for the system calls
8 *
9 * Modified:
10 * Copyright 2004-2006 Analog Devices Inc.
11 *
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29
30#include <asm/uaccess.h>
31#include <asm/traps.h>
32#include <asm/cacheflush.h>
33#include <asm/blackfin.h>
34#include <asm/uaccess.h>
35#include <asm/irq_handler.h>
36#include <linux/interrupt.h>
37#include <linux/module.h>
38#include <linux/kallsyms.h>
39
40#ifdef CONFIG_KGDB
41# include <linux/debugger.h>
42# include <linux/kgdb.h>
43#endif
44
45/* Initiate the event table handler */
46void __init trap_init(void)
47{
48 CSYNC();
49 bfin_write_EVT3(trap);
50 CSYNC();
51}
52
53asmlinkage void trap_c(struct pt_regs *fp);
54
55int kstack_depth_to_print = 48;
56
57static int printk_address(unsigned long address)
58{
59 struct vm_list_struct *vml;
60 struct task_struct *p;
61 struct mm_struct *mm;
62
63#ifdef CONFIG_KALLSYMS
64 unsigned long offset = 0, symsize;
65 const char *symname;
66 char *modname;
67 char *delim = ":";
68 char namebuf[128];
69
70 /* look up the address and see if we are in kernel space */
71 symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
72
73 if (symname) {
74 /* yeah! kernel space! */
75 if (!modname)
76 modname = delim = "";
77 return printk("<0x%p> { %s%s%s%s + 0x%lx }",
78 (void*)address, delim, modname, delim, symname,
79 (unsigned long)offset);
80
81 }
82#endif
83
84 /* looks like we're off in user-land, so let's walk all the
85 * mappings of all our processes and see if we can't be a whee
86 * bit more specific
87 */
88 write_lock_irq(&tasklist_lock);
89 for_each_process(p) {
90 mm = get_task_mm(p);
91 if (!mm)
92 continue;
93
94 vml = mm->context.vmlist;
95 while (vml) {
96 struct vm_area_struct *vma = vml->vma;
97
98 if (address >= vma->vm_start && address < vma->vm_end) {
99 char *name = p->comm;
100 struct file *file = vma->vm_file;
101 if (file) {
102 char _tmpbuf[256];
103 name = d_path(file->f_dentry,
104 file->f_vfsmnt,
105 _tmpbuf,
106 sizeof(_tmpbuf));
107 }
108
109 write_unlock_irq(&tasklist_lock);
110 return printk("<0x%p> [ %s + 0x%lx ]",
111 (void*)address, name,
112 (unsigned long)
113 ((address - vma->vm_start) +
114 (vma->vm_pgoff << PAGE_SHIFT)));
115 }
116
117 vml = vml->next;
118 }
119 }
120 write_unlock_irq(&tasklist_lock);
121
122 /* we were unable to find this address anywhere */
123 return printk("[<0x%p>]", (void*)address);
124}
125
126#define trace_buffer_save(x) \
127 do { \
128 (x) = bfin_read_TBUFCTL(); \
129 bfin_write_TBUFCTL((x) & ~TBUFEN); \
130 } while (0)
131#define trace_buffer_restore(x) \
132 do { \
133 bfin_write_TBUFCTL((x)); \
134 } while (0)
135
136asmlinkage void trap_c(struct pt_regs *fp)
137{
138 int j, sig = 0;
139 siginfo_t info;
140 unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
141
142#ifdef CONFIG_KGDB
143# define CHK_DEBUGGER_TRAP() do { CHK_DEBUGGER(trapnr, sig, info.si_code, fp,); } while (0)
144# define CHK_DEBUGGER_TRAP_MAYBE() do { if (kgdb_connected) CHK_DEBUGGER_TRAP(); } while (0)
145#else
146# define CHK_DEBUGGER_TRAP() do { } while (0)
147# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
148#endif
149
150 trace_buffer_save(j);
151
152 /* trap_c() will be called for exceptions. During exceptions
153 * processing, the pc value should be set with retx value.
154 * With this change we can cleanup some code in signal.c- TODO
155 */
156 fp->orig_pc = fp->retx;
157 /* printk("exception: 0x%x, ipend=%x, reti=%x, retx=%x\n",
158 trapnr, fp->ipend, fp->pc, fp->retx); */
159
160 /* send the appropriate signal to the user program */
161 switch (trapnr) {
162
163 /* This table works in conjuction with the one in ./mach-common/entry.S
164 * Some exceptions are handled there (in assembly, in exception space)
165 * Some are handled here, (in C, in interrupt space)
166 * Some, like CPLB, are handled in both, where the normal path is
167 * handled in assembly/exception space, and the error path is handled
168 * here
169 */
170
171 /* 0x00 - Linux Syscall, getting here is an error */
172 /* 0x01 - userspace gdb breakpoint, handled here */
173 case VEC_EXCPT01:
174 info.si_code = TRAP_ILLTRAP;
175 sig = SIGTRAP;
176 CHK_DEBUGGER_TRAP_MAYBE();
177 /* Check if this is a breakpoint in kernel space */
178 if (fp->ipend & 0xffc0)
179 return;
180 else
181 break;
182#ifdef CONFIG_KGDB
183 case VEC_EXCPT02 : /* gdb connection */
184 info.si_code = TRAP_ILLTRAP;
185 sig = SIGTRAP;
186 CHK_DEBUGGER_TRAP();
187 return;
188#else
189 /* 0x02 - User Defined, Caught by default */
190#endif
191 /* 0x03 - Atomic test and set */
192 case VEC_EXCPT03:
193 info.si_code = SEGV_STACKFLOW;
194 sig = SIGSEGV;
195 printk(KERN_EMERG EXC_0x03);
196 CHK_DEBUGGER_TRAP();
197 break;
198 /* 0x04 - spinlock - handled by _ex_spinlock,
199 getting here is an error */
200 /* 0x05 - User Defined, Caught by default */
201 /* 0x06 - User Defined, Caught by default */
202 /* 0x07 - User Defined, Caught by default */
203 /* 0x08 - User Defined, Caught by default */
204 /* 0x09 - User Defined, Caught by default */
205 /* 0x0A - User Defined, Caught by default */
206 /* 0x0B - User Defined, Caught by default */
207 /* 0x0C - User Defined, Caught by default */
208 /* 0x0D - User Defined, Caught by default */
209 /* 0x0E - User Defined, Caught by default */
210 /* 0x0F - User Defined, Caught by default */
211 /* 0x10 HW Single step, handled here */
212 case VEC_STEP:
213 info.si_code = TRAP_STEP;
214 sig = SIGTRAP;
215 CHK_DEBUGGER_TRAP_MAYBE();
216 /* Check if this is a single step in kernel space */
217 if (fp->ipend & 0xffc0)
218 return;
219 else
220 break;
221 /* 0x11 - Trace Buffer Full, handled here */
222 case VEC_OVFLOW:
223 info.si_code = TRAP_TRACEFLOW;
224 sig = SIGTRAP;
225 printk(KERN_EMERG EXC_0x11);
226 CHK_DEBUGGER_TRAP();
227 break;
228 /* 0x12 - Reserved, Caught by default */
229 /* 0x13 - Reserved, Caught by default */
230 /* 0x14 - Reserved, Caught by default */
231 /* 0x15 - Reserved, Caught by default */
232 /* 0x16 - Reserved, Caught by default */
233 /* 0x17 - Reserved, Caught by default */
234 /* 0x18 - Reserved, Caught by default */
235 /* 0x19 - Reserved, Caught by default */
236 /* 0x1A - Reserved, Caught by default */
237 /* 0x1B - Reserved, Caught by default */
238 /* 0x1C - Reserved, Caught by default */
239 /* 0x1D - Reserved, Caught by default */
240 /* 0x1E - Reserved, Caught by default */
241 /* 0x1F - Reserved, Caught by default */
242 /* 0x20 - Reserved, Caught by default */
243 /* 0x21 - Undefined Instruction, handled here */
244 case VEC_UNDEF_I:
245 info.si_code = ILL_ILLOPC;
246 sig = SIGILL;
247 printk(KERN_EMERG EXC_0x21);
248 CHK_DEBUGGER_TRAP();
249 break;
250 /* 0x22 - Illegal Instruction Combination, handled here */
251 case VEC_ILGAL_I:
252 info.si_code = ILL_ILLPARAOP;
253 sig = SIGILL;
254 printk(KERN_EMERG EXC_0x22);
255 CHK_DEBUGGER_TRAP();
256 break;
257 /* 0x23 - Data CPLB Protection Violation,
258 normal case is handled in _cplb_hdr */
259 case VEC_CPLB_VL:
260 info.si_code = ILL_CPLB_VI;
261 sig = SIGILL;
262 printk(KERN_EMERG EXC_0x23);
263 CHK_DEBUGGER_TRAP();
264 break;
265 /* 0x24 - Data access misaligned, handled here */
266 case VEC_MISALI_D:
267 info.si_code = BUS_ADRALN;
268 sig = SIGBUS;
269 printk(KERN_EMERG EXC_0x24);
270 CHK_DEBUGGER_TRAP();
271 break;
272 /* 0x25 - Unrecoverable Event, handled here */
273 case VEC_UNCOV:
274 info.si_code = ILL_ILLEXCPT;
275 sig = SIGILL;
276 printk(KERN_EMERG EXC_0x25);
277 CHK_DEBUGGER_TRAP();
278 break;
279 /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
280 error case is handled here */
281 case VEC_CPLB_M:
282 info.si_code = BUS_ADRALN;
283 sig = SIGBUS;
284 printk(KERN_EMERG EXC_0x26);
285 CHK_DEBUGGER_TRAP();
286 break;
287 /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
288 case VEC_CPLB_MHIT:
289 info.si_code = ILL_CPLB_MULHIT;
290#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
291 sig = SIGSEGV;
292 printk(KERN_EMERG "\n\nNULL pointer access (probably)\n");
293#else
294 sig = SIGILL;
295 printk(KERN_EMERG EXC_0x27);
296#endif
297 CHK_DEBUGGER_TRAP();
298 break;
299 /* 0x28 - Emulation Watchpoint, handled here */
300 case VEC_WATCH:
301 info.si_code = TRAP_WATCHPT;
302 sig = SIGTRAP;
303 pr_debug(EXC_0x28);
304 CHK_DEBUGGER_TRAP_MAYBE();
305 /* Check if this is a watchpoint in kernel space */
306 if (fp->ipend & 0xffc0)
307 return;
308 else
309 break;
310#ifdef CONFIG_BF535
311 /* 0x29 - Instruction fetch access error (535 only) */
312 case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */
313 info.si_code = BUS_OPFETCH;
314 sig = SIGBUS;
315 printk(KERN_EMERG "BF535: VEC_ISTRU_VL\n");
316 CHK_DEBUGGER_TRAP();
317 break;
318#else
319 /* 0x29 - Reserved, Caught by default */
320#endif
321 /* 0x2A - Instruction fetch misaligned, handled here */
322 case VEC_MISALI_I:
323 info.si_code = BUS_ADRALN;
324 sig = SIGBUS;
325 printk(KERN_EMERG EXC_0x2A);
326 CHK_DEBUGGER_TRAP();
327 break;
328 /* 0x2B - Instruction CPLB protection Violation,
329 handled in _cplb_hdr */
330 case VEC_CPLB_I_VL:
331 info.si_code = ILL_CPLB_VI;
332 sig = SIGILL;
333 printk(KERN_EMERG EXC_0x2B);
334 CHK_DEBUGGER_TRAP();
335 break;
336 /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
337 case VEC_CPLB_I_M:
338 info.si_code = ILL_CPLB_MISS;
339 sig = SIGBUS;
340 printk(KERN_EMERG EXC_0x2C);
341 CHK_DEBUGGER_TRAP();
342 break;
343 /* 0x2D - Instruction CPLB Multiple Hits, handled here */
344 case VEC_CPLB_I_MHIT:
345 info.si_code = ILL_CPLB_MULHIT;
346#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
347 sig = SIGSEGV;
348 printk(KERN_EMERG "\n\nJump to address 0 - 0x0fff\n");
349#else
350 sig = SIGILL;
351 printk(KERN_EMERG EXC_0x2D);
352#endif
353 CHK_DEBUGGER_TRAP();
354 break;
355 /* 0x2E - Illegal use of Supervisor Resource, handled here */
356 case VEC_ILL_RES:
357 info.si_code = ILL_PRVOPC;
358 sig = SIGILL;
359 printk(KERN_EMERG EXC_0x2E);
360 CHK_DEBUGGER_TRAP();
361 break;
362 /* 0x2F - Reserved, Caught by default */
363 /* 0x30 - Reserved, Caught by default */
364 /* 0x31 - Reserved, Caught by default */
365 /* 0x32 - Reserved, Caught by default */
366 /* 0x33 - Reserved, Caught by default */
367 /* 0x34 - Reserved, Caught by default */
368 /* 0x35 - Reserved, Caught by default */
369 /* 0x36 - Reserved, Caught by default */
370 /* 0x37 - Reserved, Caught by default */
371 /* 0x38 - Reserved, Caught by default */
372 /* 0x39 - Reserved, Caught by default */
373 /* 0x3A - Reserved, Caught by default */
374 /* 0x3B - Reserved, Caught by default */
375 /* 0x3C - Reserved, Caught by default */
376 /* 0x3D - Reserved, Caught by default */
377 /* 0x3E - Reserved, Caught by default */
378 /* 0x3F - Reserved, Caught by default */
379 default:
380 info.si_code = TRAP_ILLTRAP;
381 sig = SIGTRAP;
382 printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
383 (fp->seqstat & SEQSTAT_EXCAUSE));
384 CHK_DEBUGGER_TRAP();
385 break;
386 }
387
388 info.si_signo = sig;
389 info.si_errno = 0;
390 info.si_addr = (void *)fp->pc;
391 force_sig_info(sig, &info, current);
392 if (sig != 0 && sig != SIGTRAP) {
393 unsigned long stack;
394 dump_bfin_regs(fp, (void *)fp->retx);
395 dump_bfin_trace_buffer();
396 show_stack(current, &stack);
397 if (current->mm == NULL)
398 panic("Kernel exception");
399 }
400
401 /* if the address that we are about to return to is not valid, set it
402 * to a valid address, if we have a current application or panic
403 */
404 if (!(fp->pc <= physical_mem_end
405#if L1_CODE_LENGTH != 0
406 || (fp->pc >= L1_CODE_START &&
407 fp->pc <= (L1_CODE_START + L1_CODE_LENGTH))
408#endif
409 )) {
410 if (current->mm) {
411 fp->pc = current->mm->start_code;
412 } else {
413 printk(KERN_EMERG "I can't return to memory that doesn't exist - bad things happen\n");
414 panic("Help - I've fallen and can't get up\n");
415 }
416 }
417
418 trace_buffer_restore(j);
419 return;
420}
421
422/* Typical exception handling routines */
423
424void dump_bfin_trace_buffer(void)
425{
426 int tflags;
427 trace_buffer_save(tflags);
428
429 if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
430 int i;
431 printk(KERN_EMERG "Hardware Trace:\n");
432 for (i = 0; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
433 printk(KERN_EMERG "%2i Target : ", i);
434 printk_address((unsigned long)bfin_read_TBUF());
435 printk("\n" KERN_EMERG " Source : ");
436 printk_address((unsigned long)bfin_read_TBUF());
437 printk("\n");
438 }
439 }
440
441 trace_buffer_restore(tflags);
442}
443EXPORT_SYMBOL(dump_bfin_trace_buffer);
444
445static void show_trace(struct task_struct *tsk, unsigned long *sp)
446{
447 unsigned long addr;
448
449 printk("\nCall Trace:");
450#ifdef CONFIG_KALLSYMS
451 printk("\n");
452#endif
453
454 while (!kstack_end(sp)) {
455 addr = *sp++;
456 /*
457 * If the address is either in the text segment of the
458 * kernel, or in the region which contains vmalloc'ed
459 * memory, it *may* be the address of a calling
460 * routine; if so, print it so that someone tracing
461 * down the cause of the crash will be able to figure
462 * out the call path that was taken.
463 */
464 if (kernel_text_address(addr))
465 print_ip_sym(addr);
466 }
467
468 printk("\n");
469}
470
471void show_stack(struct task_struct *task, unsigned long *stack)
472{
473 unsigned long *endstack, addr;
474 int i;
475
476 /* Cannot call dump_bfin_trace_buffer() here as show_stack() is
477 * called externally in some places in the kernel.
478 */
479
480 if (!stack) {
481 if (task)
482 stack = (unsigned long *)task->thread.ksp;
483 else
484 stack = (unsigned long *)&stack;
485 }
486
487 addr = (unsigned long)stack;
488 endstack = (unsigned long *)PAGE_ALIGN(addr);
489
490 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
491 for (i = 0; i < kstack_depth_to_print; i++) {
492 if (stack + 1 > endstack)
493 break;
494 if (i % 8 == 0)
495 printk("\n" KERN_EMERG " ");
496 printk(" %08lx", *stack++);
497 }
498
499 show_trace(task, stack);
500}
501
502void dump_stack(void)
503{
504 unsigned long stack;
505 int tflags;
506 trace_buffer_save(tflags);
507 dump_bfin_trace_buffer();
508 show_stack(current, &stack);
509 trace_buffer_restore(tflags);
510}
511
512EXPORT_SYMBOL(dump_stack);
513
514void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
515{
516 if (current->pid) {
517 printk("\nCURRENT PROCESS:\n\n");
518 printk("COMM=%s PID=%d\n", current->comm, current->pid);
519 } else {
520 printk
521 ("\nNo Valid pid - Either things are really messed up, or you are in the kernel\n");
522 }
523
524 if (current->mm) {
525 printk("TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
526 "BSS = 0x%p-0x%p USER-STACK = 0x%p\n\n",
527 (void*)current->mm->start_code,
528 (void*)current->mm->end_code,
529 (void*)current->mm->start_data,
530 (void*)current->mm->end_data,
531 (void*)current->mm->end_data,
532 (void*)current->mm->brk,
533 (void*)current->mm->start_stack);
534 }
535
536 printk("return address: 0x%p; contents of [PC-16...PC+8]:\n", retaddr);
537 if (retaddr != 0 && retaddr <= (void*)physical_mem_end
538#if L1_CODE_LENGTH != 0
539 /* FIXME: Copy the code out of L1 Instruction SRAM through dma
540 memcpy. */
541 && !(retaddr >= (void*)L1_CODE_START
542 && retaddr < (void*)(L1_CODE_START + L1_CODE_LENGTH))
543#endif
544 ) {
545 int i = 0;
546 unsigned short x = 0;
547 for (i = -16; i < 8; i++) {
548 if (get_user(x, (unsigned short *)retaddr + i))
549 break;
550#ifndef CONFIG_DEBUG_HWERR
551 /* If one of the last few instructions was a STI
552 * it is likily that the error occured awhile ago
553 * and we just noticed
554 */
555 if (x >= 0x0040 && x <= 0x0047 && i <= 0)
556 panic("\n\nWARNING : You should reconfigure the kernel to turn on\n"
557 " 'Hardware error interrupt debugging'\n"
558 " The rest of this error is meanless\n");
559#endif
560
561 if (i == -8)
562 printk("\n");
563 if (i == 0)
564 printk("X\n");
565 printk("%04x ", x);
566 }
567 } else
568 printk("Cannot look at the [PC] for it is in unreadable L1 SRAM - sorry\n");
569
570 printk("\n\n");
571
572 printk("RETE: %08lx RETN: %08lx RETX: %08lx RETS: %08lx\n",
573 fp->rete, fp->retn, fp->retx, fp->rets);
574 printk("IPEND: %04lx SYSCFG: %04lx\n", fp->ipend, fp->syscfg);
575 printk("SEQSTAT: %08lx SP: %08lx\n", (long)fp->seqstat, (long)fp);
576 printk("R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n",
577 fp->r0, fp->r1, fp->r2, fp->r3);
578 printk("R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n",
579 fp->r4, fp->r5, fp->r6, fp->r7);
580 printk("P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n",
581 fp->p0, fp->p1, fp->p2, fp->p3);
582 printk("P4: %08lx P5: %08lx FP: %08lx\n", fp->p4, fp->p5, fp->fp);
583 printk("A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n",
584 fp->a0w, fp->a0x, fp->a1w, fp->a1x);
585
586 printk("LB0: %08lx LT0: %08lx LC0: %08lx\n", fp->lb0, fp->lt0,
587 fp->lc0);
588 printk("LB1: %08lx LT1: %08lx LC1: %08lx\n", fp->lb1, fp->lt1,
589 fp->lc1);
590 printk("B0: %08lx L0: %08lx M0: %08lx I0: %08lx\n", fp->b0, fp->l0,
591 fp->m0, fp->i0);
592 printk("B1: %08lx L1: %08lx M1: %08lx I1: %08lx\n", fp->b1, fp->l1,
593 fp->m1, fp->i1);
594 printk("B2: %08lx L2: %08lx M2: %08lx I2: %08lx\n", fp->b2, fp->l2,
595 fp->m2, fp->i2);
596 printk("B3: %08lx L3: %08lx M3: %08lx I3: %08lx\n", fp->b3, fp->l3,
597 fp->m3, fp->i3);
598
599 printk("\nUSP: %08lx ASTAT: %08lx\n", rdusp(), fp->astat);
600 if ((long)fp->seqstat & SEQSTAT_EXCAUSE) {
601 printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR());
602 printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR());
603 }
604
605 printk("\n\n");
606}
607
608#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
609asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
610#endif
611
612asmlinkage int sys_bfin_spinlock(int *spinlock)
613{
614 int ret = 0;
615 int tmp = 0;
616
617 local_irq_disable();
618 ret = get_user(tmp, spinlock);
619 if (ret == 0) {
620 if (tmp)
621 ret = 1;
622 tmp = 1;
623 put_user(tmp, spinlock);
624 }
625 local_irq_enable();
626 return ret;
627}
628
629void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
630{
631 switch (cplb_panic) {
632 case CPLB_NO_UNLOCKED:
633 printk(KERN_EMERG "All CPLBs are locked\n");
634 break;
635 case CPLB_PROT_VIOL:
636 return;
637 case CPLB_NO_ADDR_MATCH:
638 return;
639 case CPLB_UNKNOWN_ERR:
640 printk(KERN_EMERG "Unknown CPLB Exception\n");
641 break;
642 }
643
644 printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR());
645 printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR());
646 dump_bfin_regs(fp, (void *)fp->retx);
647 dump_stack();
648 panic("Unrecoverable event\n");
649}