linux/arch/blackfin/kernel/traps.c
<<
>>
Prefs
   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 <linux/uaccess.h>
  31#include <linux/interrupt.h>
  32#include <linux/module.h>
  33#include <linux/kallsyms.h>
  34#include <linux/fs.h>
  35#include <asm/traps.h>
  36#include <asm/cacheflush.h>
  37#include <asm/cplb.h>
  38#include <asm/blackfin.h>
  39#include <asm/irq_handler.h>
  40#include <linux/irq.h>
  41#include <asm/trace.h>
  42#include <asm/fixed_code.h>
  43
  44#ifdef CONFIG_KGDB
  45# include <linux/kgdb.h>
  46
  47# define CHK_DEBUGGER_TRAP() \
  48        do { \
  49                kgdb_handle_exception(trapnr, sig, info.si_code, fp); \
  50        } while (0)
  51# define CHK_DEBUGGER_TRAP_MAYBE() \
  52        do { \
  53                if (kgdb_connected) \
  54                        CHK_DEBUGGER_TRAP(); \
  55        } while (0)
  56#else
  57# define CHK_DEBUGGER_TRAP() do { } while (0)
  58# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
  59#endif
  60
  61
  62#ifdef CONFIG_DEBUG_VERBOSE
  63#define verbose_printk(fmt, arg...) \
  64        printk(fmt, ##arg)
  65#else
  66#define verbose_printk(fmt, arg...) \
  67        ({ if (0) printk(fmt, ##arg); 0; })
  68#endif
  69
  70/* Initiate the event table handler */
  71void __init trap_init(void)
  72{
  73        CSYNC();
  74        bfin_write_EVT3(trap);
  75        CSYNC();
  76}
  77
  78/*
  79 * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR
  80 * values across the transition from exception to IRQ5.
  81 * We put these in L1, so they are going to be in a valid
  82 * location during exception context
  83 */
  84__attribute__((l1_data))
  85unsigned long saved_retx, saved_seqstat,
  86        saved_icplb_fault_addr, saved_dcplb_fault_addr;
  87
  88static void decode_address(char *buf, unsigned long address)
  89{
  90#ifdef CONFIG_DEBUG_VERBOSE
  91        struct vm_list_struct *vml;
  92        struct task_struct *p;
  93        struct mm_struct *mm;
  94        unsigned long flags, offset;
  95        unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
  96
  97#ifdef CONFIG_KALLSYMS
  98        unsigned long symsize;
  99        const char *symname;
 100        char *modname;
 101        char *delim = ":";
 102        char namebuf[128];
 103
 104        /* look up the address and see if we are in kernel space */
 105        symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
 106
 107        if (symname) {
 108                /* yeah! kernel space! */
 109                if (!modname)
 110                        modname = delim = "";
 111                sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }",
 112                              (void *)address, delim, modname, delim, symname,
 113                              (unsigned long)offset);
 114                return;
 115
 116        }
 117#endif
 118
 119        /* Problem in fixed code section? */
 120        if (address >= FIXED_CODE_START && address < FIXED_CODE_END) {
 121                sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address);
 122                return;
 123        }
 124
 125        /* Problem somewhere before the kernel start address */
 126        if (address < CONFIG_BOOT_LOAD) {
 127                sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address);
 128                return;
 129        }
 130
 131        /* looks like we're off in user-land, so let's walk all the
 132         * mappings of all our processes and see if we can't be a whee
 133         * bit more specific
 134         */
 135        write_lock_irqsave(&tasklist_lock, flags);
 136        for_each_process(p) {
 137                mm = (in_atomic ? p->mm : get_task_mm(p));
 138                if (!mm)
 139                        continue;
 140
 141                vml = mm->context.vmlist;
 142                while (vml) {
 143                        struct vm_area_struct *vma = vml->vma;
 144
 145                        if (address >= vma->vm_start && address < vma->vm_end) {
 146                                char _tmpbuf[256];
 147                                char *name = p->comm;
 148                                struct file *file = vma->vm_file;
 149
 150                                if (file) {
 151                                        char *d_name = d_path(&file->f_path, _tmpbuf,
 152                                                      sizeof(_tmpbuf));
 153                                        if (!IS_ERR(d_name))
 154                                                name = d_name;
 155                                }
 156
 157                                /* FLAT does not have its text aligned to the start of
 158                                 * the map while FDPIC ELF does ...
 159                                 */
 160
 161                                /* before we can check flat/fdpic, we need to
 162                                 * make sure current is valid
 163                                 */
 164                                if ((unsigned long)current >= FIXED_CODE_START &&
 165                                    !((unsigned long)current & 0x3)) {
 166                                        if (current->mm &&
 167                                            (address > current->mm->start_code) &&
 168                                            (address < current->mm->end_code))
 169                                                offset = address - current->mm->start_code;
 170                                        else
 171                                                offset = (address - vma->vm_start) +
 172                                                         (vma->vm_pgoff << PAGE_SHIFT);
 173
 174                                        sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
 175                                                (void *)address, name, offset);
 176                                } else
 177                                        sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
 178                                                (void *)address, name,
 179                                                vma->vm_start, vma->vm_end);
 180
 181                                if (!in_atomic)
 182                                        mmput(mm);
 183
 184                                if (!strlen(buf))
 185                                        sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name);
 186
 187                                goto done;
 188                        }
 189
 190                        vml = vml->next;
 191                }
 192                if (!in_atomic)
 193                        mmput(mm);
 194        }
 195
 196        /* we were unable to find this address anywhere */
 197        sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
 198
 199done:
 200        write_unlock_irqrestore(&tasklist_lock, flags);
 201#else
 202        sprintf(buf, " ");
 203#endif
 204}
 205
 206asmlinkage void double_fault_c(struct pt_regs *fp)
 207{
 208        console_verbose();
 209        oops_in_progress = 1;
 210#ifdef CONFIG_DEBUG_VERBOSE
 211        printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
 212#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
 213        if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) == VEC_UNCOV) {
 214                char buf[150];
 215                decode_address(buf, saved_retx);
 216                printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
 217                        (int)saved_seqstat & SEQSTAT_EXCAUSE, buf);
 218                decode_address(buf, saved_dcplb_fault_addr);
 219                printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %s\n", buf);
 220                decode_address(buf, saved_icplb_fault_addr);
 221                printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %s\n", buf);
 222
 223                decode_address(buf, fp->retx);
 224                printk(KERN_NOTICE "The instruction at %s caused a double exception\n",
 225                        buf);
 226        } else
 227#endif
 228        {
 229                dump_bfin_process(fp);
 230                dump_bfin_mem(fp);
 231                show_regs(fp);
 232        }
 233#endif
 234        panic("Double Fault - unrecoverable event\n");
 235
 236}
 237
 238asmlinkage void trap_c(struct pt_regs *fp)
 239{
 240#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
 241        int j;
 242#endif
 243        int sig = 0;
 244        siginfo_t info;
 245        unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
 246
 247        trace_buffer_save(j);
 248
 249        /* Important - be very careful dereferncing pointers - will lead to
 250         * double faults if the stack has become corrupt
 251         */
 252
 253        /* If the fault was caused by a kernel thread, or interrupt handler
 254         * we will kernel panic, so the system reboots.
 255         * If KGDB is enabled, don't set this for kernel breakpoints
 256        */
 257
 258        /* TODO: check to see if we are in some sort of deferred HWERR
 259         * that we should be able to recover from, not kernel panic
 260         */
 261        if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP)
 262#ifdef CONFIG_KGDB
 263                && (trapnr != VEC_EXCPT02)
 264#endif
 265        ){
 266                console_verbose();
 267                oops_in_progress = 1;
 268        } else if (current) {
 269                if (current->mm == NULL) {
 270                        console_verbose();
 271                        oops_in_progress = 1;
 272                }
 273        }
 274
 275        /* trap_c() will be called for exceptions. During exceptions
 276         * processing, the pc value should be set with retx value.
 277         * With this change we can cleanup some code in signal.c- TODO
 278         */
 279        fp->orig_pc = fp->retx;
 280        /* printk("exception: 0x%x, ipend=%x, reti=%x, retx=%x\n",
 281                trapnr, fp->ipend, fp->pc, fp->retx); */
 282
 283        /* send the appropriate signal to the user program */
 284        switch (trapnr) {
 285
 286        /* This table works in conjuction with the one in ./mach-common/entry.S
 287         * Some exceptions are handled there (in assembly, in exception space)
 288         * Some are handled here, (in C, in interrupt space)
 289         * Some, like CPLB, are handled in both, where the normal path is
 290         * handled in assembly/exception space, and the error path is handled
 291         * here
 292         */
 293
 294        /* 0x00 - Linux Syscall, getting here is an error */
 295        /* 0x01 - userspace gdb breakpoint, handled here */
 296        case VEC_EXCPT01:
 297                info.si_code = TRAP_ILLTRAP;
 298                sig = SIGTRAP;
 299                CHK_DEBUGGER_TRAP_MAYBE();
 300                /* Check if this is a breakpoint in kernel space */
 301                if (fp->ipend & 0xffc0)
 302                        return;
 303                else
 304                        break;
 305        /* 0x03 - User Defined, userspace stack overflow */
 306        case VEC_EXCPT03:
 307                info.si_code = SEGV_STACKFLOW;
 308                sig = SIGSEGV;
 309                verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
 310                CHK_DEBUGGER_TRAP_MAYBE();
 311                break;
 312        /* 0x02 - KGDB initial connection and break signal trap */
 313        case VEC_EXCPT02:
 314#ifdef CONFIG_KGDB
 315                info.si_code = TRAP_ILLTRAP;
 316                sig = SIGTRAP;
 317                CHK_DEBUGGER_TRAP();
 318                return;
 319#endif
 320        /* 0x04 - User Defined */
 321        /* 0x05 - User Defined */
 322        /* 0x06 - User Defined */
 323        /* 0x07 - User Defined */
 324        /* 0x08 - User Defined */
 325        /* 0x09 - User Defined */
 326        /* 0x0A - User Defined */
 327        /* 0x0B - User Defined */
 328        /* 0x0C - User Defined */
 329        /* 0x0D - User Defined */
 330        /* 0x0E - User Defined */
 331        /* 0x0F - User Defined */
 332        /* If we got here, it is most likely that someone was trying to use a
 333         * custom exception handler, and it is not actually installed properly
 334         */
 335        case VEC_EXCPT04 ... VEC_EXCPT15:
 336                info.si_code = ILL_ILLPARAOP;
 337                sig = SIGILL;
 338                verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE));
 339                CHK_DEBUGGER_TRAP_MAYBE();
 340                break;
 341        /* 0x10 HW Single step, handled here */
 342        case VEC_STEP:
 343                info.si_code = TRAP_STEP;
 344                sig = SIGTRAP;
 345                CHK_DEBUGGER_TRAP_MAYBE();
 346                /* Check if this is a single step in kernel space */
 347                if (fp->ipend & 0xffc0)
 348                        return;
 349                else
 350                        break;
 351        /* 0x11 - Trace Buffer Full, handled here */
 352        case VEC_OVFLOW:
 353                info.si_code = TRAP_TRACEFLOW;
 354                sig = SIGTRAP;
 355                verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
 356                CHK_DEBUGGER_TRAP_MAYBE();
 357                break;
 358        /* 0x12 - Reserved, Caught by default */
 359        /* 0x13 - Reserved, Caught by default */
 360        /* 0x14 - Reserved, Caught by default */
 361        /* 0x15 - Reserved, Caught by default */
 362        /* 0x16 - Reserved, Caught by default */
 363        /* 0x17 - Reserved, Caught by default */
 364        /* 0x18 - Reserved, Caught by default */
 365        /* 0x19 - Reserved, Caught by default */
 366        /* 0x1A - Reserved, Caught by default */
 367        /* 0x1B - Reserved, Caught by default */
 368        /* 0x1C - Reserved, Caught by default */
 369        /* 0x1D - Reserved, Caught by default */
 370        /* 0x1E - Reserved, Caught by default */
 371        /* 0x1F - Reserved, Caught by default */
 372        /* 0x20 - Reserved, Caught by default */
 373        /* 0x21 - Undefined Instruction, handled here */
 374        case VEC_UNDEF_I:
 375                info.si_code = ILL_ILLOPC;
 376                sig = SIGILL;
 377                verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
 378                CHK_DEBUGGER_TRAP_MAYBE();
 379                break;
 380        /* 0x22 - Illegal Instruction Combination, handled here */
 381        case VEC_ILGAL_I:
 382                info.si_code = ILL_ILLPARAOP;
 383                sig = SIGILL;
 384                verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
 385                CHK_DEBUGGER_TRAP_MAYBE();
 386                break;
 387        /* 0x23 - Data CPLB protection violation, handled here */
 388        case VEC_CPLB_VL:
 389                info.si_code = ILL_CPLB_VI;
 390                sig = SIGBUS;
 391                verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
 392                CHK_DEBUGGER_TRAP_MAYBE();
 393                break;
 394        /* 0x24 - Data access misaligned, handled here */
 395        case VEC_MISALI_D:
 396                info.si_code = BUS_ADRALN;
 397                sig = SIGBUS;
 398                verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
 399                CHK_DEBUGGER_TRAP_MAYBE();
 400                break;
 401        /* 0x25 - Unrecoverable Event, handled here */
 402        case VEC_UNCOV:
 403                info.si_code = ILL_ILLEXCPT;
 404                sig = SIGILL;
 405                verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
 406                CHK_DEBUGGER_TRAP_MAYBE();
 407                break;
 408        /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
 409                error case is handled here */
 410        case VEC_CPLB_M:
 411                info.si_code = BUS_ADRALN;
 412                sig = SIGBUS;
 413                verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
 414                break;
 415        /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
 416        case VEC_CPLB_MHIT:
 417                info.si_code = ILL_CPLB_MULHIT;
 418                sig = SIGSEGV;
 419#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
 420                if (saved_dcplb_fault_addr < FIXED_CODE_START)
 421                        verbose_printk(KERN_NOTICE "NULL pointer access\n");
 422                else
 423#endif
 424                        verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
 425                CHK_DEBUGGER_TRAP_MAYBE();
 426                break;
 427        /* 0x28 - Emulation Watchpoint, handled here */
 428        case VEC_WATCH:
 429                info.si_code = TRAP_WATCHPT;
 430                sig = SIGTRAP;
 431                pr_debug(EXC_0x28(KERN_DEBUG));
 432                CHK_DEBUGGER_TRAP_MAYBE();
 433                /* Check if this is a watchpoint in kernel space */
 434                if (fp->ipend & 0xffc0)
 435                        return;
 436                else
 437                        break;
 438#ifdef CONFIG_BF535
 439        /* 0x29 - Instruction fetch access error (535 only) */
 440        case VEC_ISTRU_VL:      /* ADSP-BF535 only (MH) */
 441                info.si_code = BUS_OPFETCH;
 442                sig = SIGBUS;
 443                verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
 444                CHK_DEBUGGER_TRAP_MAYBE();
 445                break;
 446#else
 447        /* 0x29 - Reserved, Caught by default */
 448#endif
 449        /* 0x2A - Instruction fetch misaligned, handled here */
 450        case VEC_MISALI_I:
 451                info.si_code = BUS_ADRALN;
 452                sig = SIGBUS;
 453                verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
 454                CHK_DEBUGGER_TRAP_MAYBE();
 455                break;
 456        /* 0x2B - Instruction CPLB protection violation, handled here */
 457        case VEC_CPLB_I_VL:
 458                info.si_code = ILL_CPLB_VI;
 459                sig = SIGBUS;
 460                verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
 461                CHK_DEBUGGER_TRAP_MAYBE();
 462                break;
 463        /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
 464        case VEC_CPLB_I_M:
 465                info.si_code = ILL_CPLB_MISS;
 466                sig = SIGBUS;
 467                verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
 468                break;
 469        /* 0x2D - Instruction CPLB Multiple Hits, handled here */
 470        case VEC_CPLB_I_MHIT:
 471                info.si_code = ILL_CPLB_MULHIT;
 472                sig = SIGSEGV;
 473#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
 474                if (saved_icplb_fault_addr < FIXED_CODE_START)
 475                        verbose_printk(KERN_NOTICE "Jump to NULL address\n");
 476                else
 477#endif
 478                        verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
 479                CHK_DEBUGGER_TRAP_MAYBE();
 480                break;
 481        /* 0x2E - Illegal use of Supervisor Resource, handled here */
 482        case VEC_ILL_RES:
 483                info.si_code = ILL_PRVOPC;
 484                sig = SIGILL;
 485                verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
 486                CHK_DEBUGGER_TRAP_MAYBE();
 487                break;
 488        /* 0x2F - Reserved, Caught by default */
 489        /* 0x30 - Reserved, Caught by default */
 490        /* 0x31 - Reserved, Caught by default */
 491        /* 0x32 - Reserved, Caught by default */
 492        /* 0x33 - Reserved, Caught by default */
 493        /* 0x34 - Reserved, Caught by default */
 494        /* 0x35 - Reserved, Caught by default */
 495        /* 0x36 - Reserved, Caught by default */
 496        /* 0x37 - Reserved, Caught by default */
 497        /* 0x38 - Reserved, Caught by default */
 498        /* 0x39 - Reserved, Caught by default */
 499        /* 0x3A - Reserved, Caught by default */
 500        /* 0x3B - Reserved, Caught by default */
 501        /* 0x3C - Reserved, Caught by default */
 502        /* 0x3D - Reserved, Caught by default */
 503        /* 0x3E - Reserved, Caught by default */
 504        /* 0x3F - Reserved, Caught by default */
 505        case VEC_HWERR:
 506                info.si_code = BUS_ADRALN;
 507                sig = SIGBUS;
 508                switch (fp->seqstat & SEQSTAT_HWERRCAUSE) {
 509                /* System MMR Error */
 510                case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
 511                        info.si_code = BUS_ADRALN;
 512                        sig = SIGBUS;
 513                        verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
 514                        break;
 515                /* External Memory Addressing Error */
 516                case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
 517                        info.si_code = BUS_ADRERR;
 518                        sig = SIGBUS;
 519                        verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
 520                        break;
 521                /* Performance Monitor Overflow */
 522                case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
 523                        verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
 524                        break;
 525                /* RAISE 5 instruction */
 526                case (SEQSTAT_HWERRCAUSE_RAISE_5):
 527                        printk(KERN_NOTICE HWC_x18(KERN_NOTICE));
 528                        break;
 529                default:        /* Reserved */
 530                        printk(KERN_NOTICE HWC_default(KERN_NOTICE));
 531                        break;
 532                }
 533                CHK_DEBUGGER_TRAP_MAYBE();
 534                break;
 535        /*
 536         * We should be handling all known exception types above,
 537         * if we get here we hit a reserved one, so panic
 538         */
 539        default:
 540                oops_in_progress = 1;
 541                info.si_code = ILL_ILLPARAOP;
 542                sig = SIGILL;
 543                verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
 544                        (fp->seqstat & SEQSTAT_EXCAUSE));
 545                CHK_DEBUGGER_TRAP_MAYBE();
 546                break;
 547        }
 548
 549        BUG_ON(sig == 0);
 550
 551        if (sig != SIGTRAP) {
 552                dump_bfin_process(fp);
 553                dump_bfin_mem(fp);
 554                show_regs(fp);
 555
 556                /* Print out the trace buffer if it makes sense */
 557#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
 558                if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
 559                        verbose_printk(KERN_NOTICE "No trace since you do not have "
 560                                "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"
 561                                KERN_NOTICE "\n");
 562                else
 563#endif
 564                        dump_bfin_trace_buffer();
 565
 566                if (oops_in_progress) {
 567                        /* Dump the current kernel stack */
 568                        verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
 569                        show_stack(current, NULL);
 570                        print_modules();
 571#ifndef CONFIG_ACCESS_CHECK
 572                        verbose_printk(KERN_EMERG "Please turn on "
 573                               "CONFIG_ACCESS_CHECK\n");
 574#endif
 575                        panic("Kernel exception");
 576                } else {
 577#ifdef CONFIG_DEBUG_VERBOSE
 578                        unsigned long *stack;
 579                        /* Dump the user space stack */
 580                        stack = (unsigned long *)rdusp();
 581                        verbose_printk(KERN_NOTICE "Userspace Stack\n");
 582                        show_stack(NULL, stack);
 583#endif
 584                }
 585        }
 586
 587        info.si_signo = sig;
 588        info.si_errno = 0;
 589        info.si_addr = (void __user *)fp->pc;
 590        force_sig_info(sig, &info, current);
 591
 592        trace_buffer_restore(j);
 593        return;
 594}
 595
 596/* Typical exception handling routines  */
 597
 598#define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)
 599
 600/*
 601 * Similar to get_user, do some address checking, then dereference
 602 * Return true on sucess, false on bad address
 603 */
 604static bool get_instruction(unsigned short *val, unsigned short *address)
 605{
 606
 607        unsigned long addr;
 608
 609        addr = (unsigned long)address;
 610
 611        /* Check for odd addresses */
 612        if (addr & 0x1)
 613                return false;
 614
 615        /* Check that things do not wrap around */
 616        if (addr > (addr + 2))
 617                return false;
 618
 619        /*
 620         * Since we are in exception context, we need to do a little address checking
 621         * We need to make sure we are only accessing valid memory, and
 622         * we don't read something in the async space that can hang forever
 623         */
 624        if ((addr >= FIXED_CODE_START && (addr + 2) <= physical_mem_end) ||
 625#if L2_LENGTH != 0
 626            (addr >= L2_START && (addr + 2) <= (L2_START + L2_LENGTH)) ||
 627#endif
 628            (addr >= BOOT_ROM_START && (addr + 2) <= (BOOT_ROM_START + BOOT_ROM_LENGTH)) ||
 629#if L1_DATA_A_LENGTH != 0
 630            (addr >= L1_DATA_A_START && (addr + 2) <= (L1_DATA_A_START + L1_DATA_A_LENGTH)) ||
 631#endif
 632#if L1_DATA_B_LENGTH != 0
 633            (addr >= L1_DATA_B_START && (addr + 2) <= (L1_DATA_B_START + L1_DATA_B_LENGTH)) ||
 634#endif
 635            (addr >= L1_SCRATCH_START && (addr + 2) <= (L1_SCRATCH_START + L1_SCRATCH_LENGTH)) ||
 636            (!(bfin_read_EBIU_AMBCTL0() & B0RDYEN) &&
 637               addr >= ASYNC_BANK0_BASE && (addr + 2) <= (ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)) ||
 638            (!(bfin_read_EBIU_AMBCTL0() & B1RDYEN) &&
 639               addr >= ASYNC_BANK1_BASE && (addr + 2) <= (ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)) ||
 640            (!(bfin_read_EBIU_AMBCTL1() & B2RDYEN) &&
 641               addr >= ASYNC_BANK2_BASE && (addr + 2) <= (ASYNC_BANK2_BASE + ASYNC_BANK1_SIZE)) ||
 642            (!(bfin_read_EBIU_AMBCTL1() & B3RDYEN) &&
 643              addr >= ASYNC_BANK3_BASE && (addr + 2) <= (ASYNC_BANK3_BASE + ASYNC_BANK1_SIZE))) {
 644                *val = *address;
 645                return true;
 646        }
 647
 648#if L1_CODE_LENGTH != 0
 649        if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) {
 650                isram_memcpy(val, address, 2);
 651                return true;
 652        }
 653#endif
 654
 655
 656        return false;
 657}
 658
 659/* 
 660 * decode the instruction if we are printing out the trace, as it
 661 * makes things easier to follow, without running it through objdump
 662 * These are the normal instructions which cause change of flow, which
 663 * would be at the source of the trace buffer
 664 */
 665#ifdef CONFIG_DEBUG_VERBOSE
 666static void decode_instruction(unsigned short *address)
 667{
 668        unsigned short opcode;
 669
 670        if (get_instruction(&opcode, address)) {
 671                if (opcode == 0x0010)
 672                        verbose_printk("RTS");
 673                else if (opcode == 0x0011)
 674                        verbose_printk("RTI");
 675                else if (opcode == 0x0012)
 676                        verbose_printk("RTX");
 677                else if (opcode >= 0x0050 && opcode <= 0x0057)
 678                        verbose_printk("JUMP (P%i)", opcode & 7);
 679                else if (opcode >= 0x0060 && opcode <= 0x0067)
 680                        verbose_printk("CALL (P%i)", opcode & 7);
 681                else if (opcode >= 0x0070 && opcode <= 0x0077)
 682                        verbose_printk("CALL (PC+P%i)", opcode & 7);
 683                else if (opcode >= 0x0080 && opcode <= 0x0087)
 684                        verbose_printk("JUMP (PC+P%i)", opcode & 7);
 685                else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF))
 686                        verbose_printk("IF !CC JUMP");
 687                else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff))
 688                        verbose_printk("IF CC JUMP");
 689                else if (opcode >= 0x2000 && opcode <= 0x2fff)
 690                        verbose_printk("JUMP.S");
 691                else if (opcode >= 0xe080 && opcode <= 0xe0ff)
 692                        verbose_printk("LSETUP");
 693                else if (opcode >= 0xe200 && opcode <= 0xe2ff)
 694                        verbose_printk("JUMP.L");
 695                else if (opcode >= 0xe300 && opcode <= 0xe3ff)
 696                        verbose_printk("CALL pcrel");
 697                else
 698                        verbose_printk("0x%04x", opcode);
 699        }
 700
 701}
 702#endif
 703
 704void dump_bfin_trace_buffer(void)
 705{
 706#ifdef CONFIG_DEBUG_VERBOSE
 707#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
 708        int tflags, i = 0;
 709        char buf[150];
 710        unsigned short *addr;
 711#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
 712        int j, index;
 713#endif
 714
 715        trace_buffer_save(tflags);
 716
 717        printk(KERN_NOTICE "Hardware Trace:\n");
 718
 719#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
 720        printk(KERN_NOTICE "WARNING: Expanded trace turned on - can not trace exceptions\n");
 721#endif
 722
 723        if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
 724                for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
 725                        decode_address(buf, (unsigned long)bfin_read_TBUF());
 726                        printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
 727                        addr = (unsigned short *)bfin_read_TBUF();
 728                        decode_address(buf, (unsigned long)addr);
 729                        printk(KERN_NOTICE "     Source : %s ", buf);
 730                        decode_instruction(addr);
 731                        printk("\n");
 732                }
 733        }
 734
 735#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
 736        if (trace_buff_offset)
 737                index = trace_buff_offset / 4;
 738        else
 739                index = EXPAND_LEN;
 740
 741        j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128;
 742        while (j) {
 743                decode_address(buf, software_trace_buff[index]);
 744                printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
 745                index -= 1;
 746                if (index < 0 )
 747                        index = EXPAND_LEN;
 748                decode_address(buf, software_trace_buff[index]);
 749                printk(KERN_NOTICE "     Source : %s ", buf);
 750                decode_instruction((unsigned short *)software_trace_buff[index]);
 751                printk("\n");
 752                index -= 1;
 753                if (index < 0)
 754                        index = EXPAND_LEN;
 755                j--;
 756                i++;
 757        }
 758#endif
 759
 760        trace_buffer_restore(tflags);
 761#endif
 762#endif
 763}
 764EXPORT_SYMBOL(dump_bfin_trace_buffer);
 765
 766/*
 767 * Checks to see if the address pointed to is either a
 768 * 16-bit CALL instruction, or a 32-bit CALL instruction
 769 */
 770static bool is_bfin_call(unsigned short *addr)
 771{
 772        unsigned short opcode = 0, *ins_addr;
 773        ins_addr = (unsigned short *)addr;
 774
 775        if (!get_instruction(&opcode, ins_addr))
 776                return false;
 777
 778        if ((opcode >= 0x0060 && opcode <= 0x0067) ||
 779            (opcode >= 0x0070 && opcode <= 0x0077))
 780                return true;
 781
 782        ins_addr--;
 783        if (!get_instruction(&opcode, ins_addr))
 784                return false;
 785
 786        if (opcode >= 0xE300 && opcode <= 0xE3FF)
 787                return true;
 788
 789        return false;
 790
 791}
 792
 793void show_stack(struct task_struct *task, unsigned long *stack)
 794{
 795#ifdef CONFIG_PRINTK
 796        unsigned int *addr, *endstack, *fp = 0, *frame;
 797        unsigned short *ins_addr;
 798        char buf[150];
 799        unsigned int i, j, ret_addr, frame_no = 0;
 800
 801        /*
 802         * If we have been passed a specific stack, use that one otherwise
 803         *    if we have been passed a task structure, use that, otherwise
 804         *    use the stack of where the variable "stack" exists
 805         */
 806
 807        if (stack == NULL) {
 808                if (task) {
 809                        /* We know this is a kernel stack, so this is the start/end */
 810                        stack = (unsigned long *)task->thread.ksp;
 811                        endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
 812                } else {
 813                        /* print out the existing stack info */
 814                        stack = (unsigned long *)&stack;
 815                        endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
 816                }
 817        } else
 818                endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
 819
 820        printk(KERN_NOTICE "Stack info:\n");
 821        decode_address(buf, (unsigned int)stack);
 822        printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
 823
 824        addr = (unsigned int *)((unsigned int)stack & ~0x3F);
 825
 826        /* First thing is to look for a frame pointer */
 827        for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
 828                addr < endstack; addr++, i++) {
 829                if (*addr & 0x1)
 830                        continue;
 831                ins_addr = (unsigned short *)*addr;
 832                ins_addr--;
 833                if (is_bfin_call(ins_addr))
 834                        fp = addr - 1;
 835
 836                if (fp) {
 837                        /* Let's check to see if it is a frame pointer */
 838                        while (fp >= (addr - 1) && fp < endstack && fp)
 839                                fp = (unsigned int *)*fp;
 840                        if (fp == 0 || fp == endstack) {
 841                                fp = addr - 1;
 842                                break;
 843                        }
 844                        fp = 0;
 845                }
 846        }
 847        if (fp) {
 848                frame = fp;
 849                printk(" FP: (0x%p)\n", fp);
 850        } else
 851                frame = 0;
 852
 853        /*
 854         * Now that we think we know where things are, we
 855         * walk the stack again, this time printing things out
 856         * incase there is no frame pointer, we still look for
 857         * valid return addresses
 858         */
 859
 860        /* First time print out data, next time, print out symbols */
 861        for (j = 0; j <= 1; j++) {
 862                if (j)
 863                        printk(KERN_NOTICE "Return addresses in stack:\n");
 864                else
 865                        printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);
 866
 867                fp = frame;
 868                frame_no = 0;
 869
 870                for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
 871                     addr <= endstack; addr++, i++) {
 872
 873                        ret_addr = 0;
 874                        if (!j && i % 8 == 0)
 875                                printk("\n" KERN_NOTICE "%p:",addr);
 876
 877                        /* if it is an odd address, or zero, just skip it */
 878                        if (*addr & 0x1 || !*addr)
 879                                goto print;
 880
 881                        ins_addr = (unsigned short *)*addr;
 882
 883                        /* Go back one instruction, and see if it is a CALL */
 884                        ins_addr--;
 885                        ret_addr = is_bfin_call(ins_addr);
 886 print:
 887                        if (!j && stack == (unsigned long *)addr)
 888                                printk("[%08x]", *addr);
 889                        else if (ret_addr)
 890                                if (j) {
 891                                        decode_address(buf, (unsigned int)*addr);
 892                                        if (frame == addr) {
 893                                                printk(KERN_NOTICE "   frame %2i : %s\n", frame_no, buf);
 894                                                continue;
 895                                        }
 896                                        printk(KERN_NOTICE "    address : %s\n", buf);
 897                                } else
 898                                        printk("<%08x>", *addr);
 899                        else if (fp == addr) {
 900                                if (j)
 901                                        frame = addr+1;
 902                                else
 903                                        printk("(%08x)", *addr);
 904
 905                                fp = (unsigned int *)*addr;
 906                                frame_no++;
 907
 908                        } else if (!j)
 909                                printk(" %08x ", *addr);
 910                }
 911                if (!j)
 912                        printk("\n");
 913        }
 914#endif
 915}
 916
 917void dump_stack(void)
 918{
 919        unsigned long stack;
 920#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
 921        int tflags;
 922#endif
 923        trace_buffer_save(tflags);
 924        dump_bfin_trace_buffer();
 925        show_stack(current, &stack);
 926        trace_buffer_restore(tflags);
 927}
 928EXPORT_SYMBOL(dump_stack);
 929
 930void dump_bfin_process(struct pt_regs *fp)
 931{
 932#ifdef CONFIG_DEBUG_VERBOSE
 933        /* We should be able to look at fp->ipend, but we don't push it on the
 934         * stack all the time, so do this until we fix that */
 935        unsigned int context = bfin_read_IPEND();
 936
 937        if (oops_in_progress)
 938                verbose_printk(KERN_EMERG "Kernel OOPS in progress\n");
 939
 940        if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)
 941                verbose_printk(KERN_NOTICE "HW Error context\n");
 942        else if (context & 0x0020)
 943                verbose_printk(KERN_NOTICE "Deferred Exception context\n");
 944        else if (context & 0x3FC0)
 945                verbose_printk(KERN_NOTICE "Interrupt context\n");
 946        else if (context & 0x4000)
 947                verbose_printk(KERN_NOTICE "Deferred Interrupt context\n");
 948        else if (context & 0x8000)
 949                verbose_printk(KERN_NOTICE "Kernel process context\n");
 950
 951        /* Because we are crashing, and pointers could be bad, we check things
 952         * pretty closely before we use them
 953         */
 954        if ((unsigned long)current >= FIXED_CODE_START &&
 955            !((unsigned long)current & 0x3) && current->pid) {
 956                verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n");
 957                if (current->comm >= (char *)FIXED_CODE_START)
 958                        verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n",
 959                                current->comm, current->pid);
 960                else
 961                        verbose_printk(KERN_NOTICE "COMM= invalid\n");
 962
 963                if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
 964                        verbose_printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
 965                                KERN_NOTICE " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n"
 966                                KERN_NOTICE "\n",
 967                                (void *)current->mm->start_code,
 968                                (void *)current->mm->end_code,
 969                                (void *)current->mm->start_data,
 970                                (void *)current->mm->end_data,
 971                                (void *)current->mm->end_data,
 972                                (void *)current->mm->brk,
 973                                (void *)current->mm->start_stack);
 974                else
 975                        verbose_printk(KERN_NOTICE "invalid mm\n");
 976        } else
 977                verbose_printk(KERN_NOTICE "\n" KERN_NOTICE
 978                     "No Valid process in current context\n");
 979#endif
 980}
 981
 982void dump_bfin_mem(struct pt_regs *fp)
 983{
 984#ifdef CONFIG_DEBUG_VERBOSE
 985        unsigned short *addr, *erraddr, val = 0, err = 0;
 986        char sti = 0, buf[6];
 987
 988        erraddr = (void *)fp->pc;
 989
 990        verbose_printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
 991
 992        for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10;
 993             addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
 994             addr++) {
 995                if (!((unsigned long)addr & 0xF))
 996                        verbose_printk("\n" KERN_NOTICE "0x%p: ", addr);
 997
 998                if (!get_instruction(&val, addr)) {
 999                                val = 0;
1000                                sprintf(buf, "????");
1001                } else
1002                        sprintf(buf, "%04x", val);
1003
1004                if (addr == erraddr) {
1005                        verbose_printk("[%s]", buf);
1006                        err = val;
1007                } else
1008                        verbose_printk(" %s ", buf);
1009
1010                /* Do any previous instructions turn on interrupts? */
1011                if (addr <= erraddr &&                          /* in the past */
1012                    ((val >= 0x0040 && val <= 0x0047) ||        /* STI instruction */
1013                      val == 0x017b))                           /* [SP++] = RETI */
1014                        sti = 1;
1015        }
1016
1017        verbose_printk("\n");
1018
1019        /* Hardware error interrupts can be deferred */
1020        if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR &&
1021            oops_in_progress)){
1022                verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
1023#ifndef CONFIG_DEBUG_HWERR
1024                verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n"
1025                        KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a"
1026                         " better idea where it came from\n");
1027#else
1028                /* If we are handling only one peripheral interrupt
1029                 * and current mm and pid are valid, and the last error
1030                 * was in that user space process's text area
1031                 * print it out - because that is where the problem exists
1032                 */
1033                if ((!(((fp)->ipend & ~0x30) & (((fp)->ipend & ~0x30) - 1))) &&
1034                     (current->pid && current->mm)) {
1035                        /* And the last RETI points to the current userspace context */
1036                        if ((fp + 1)->pc >= current->mm->start_code &&
1037                            (fp + 1)->pc <= current->mm->end_code) {
1038                                verbose_printk(KERN_NOTICE "It might be better to look around here : \n");
1039                                verbose_printk(KERN_NOTICE "-------------------------------------------\n");
1040                                show_regs(fp + 1);
1041                                verbose_printk(KERN_NOTICE "-------------------------------------------\n");
1042                        }
1043                }
1044#endif
1045        }
1046#endif
1047}
1048
1049void show_regs(struct pt_regs *fp)
1050{
1051#ifdef CONFIG_DEBUG_VERBOSE
1052        char buf [150];
1053        struct irqaction *action;
1054        unsigned int i;
1055        unsigned long flags;
1056
1057        verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
1058        verbose_printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
1059                (long)fp->seqstat, fp->ipend, fp->syscfg);
1060        if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
1061                verbose_printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
1062                        (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
1063#ifdef EBIU_ERRMST
1064                /* If the error was from the EBIU, print it out */
1065                if (bfin_read_EBIU_ERRMST() & CORE_ERROR) {
1066                        verbose_printk(KERN_NOTICE "  EBIU Error Reason  : 0x%04x\n",
1067                                bfin_read_EBIU_ERRMST());
1068                        verbose_printk(KERN_NOTICE "  EBIU Error Address : 0x%08x\n",
1069                                bfin_read_EBIU_ERRADD());
1070                }
1071#endif
1072        }
1073        verbose_printk(KERN_NOTICE "  EXCAUSE   : 0x%lx\n",
1074                fp->seqstat & SEQSTAT_EXCAUSE);
1075        for (i = 6; i <= 15 ; i++) {
1076                if (fp->ipend & (1 << i)) {
1077                        decode_address(buf, bfin_read32(EVT0 + 4*i));
1078                        verbose_printk(KERN_NOTICE "  physical IVG%i asserted : %s\n", i, buf);
1079                }
1080        }
1081
1082        /* if no interrupts are going off, don't print this out */
1083        if (fp->ipend & ~0x3F) {
1084                for (i = 0; i < (NR_IRQS - 1); i++) {
1085                        spin_lock_irqsave(&irq_desc[i].lock, flags);
1086                        action = irq_desc[i].action;
1087                        if (!action)
1088                                goto unlock;
1089
1090                        decode_address(buf, (unsigned int)action->handler);
1091                        verbose_printk(KERN_NOTICE "  logical irq %3d mapped  : %s", i, buf);
1092                        for (action = action->next; action; action = action->next) {
1093                                decode_address(buf, (unsigned int)action->handler);
1094                                verbose_printk(", %s", buf);
1095                        }
1096                        verbose_printk("\n");
1097unlock:
1098                        spin_unlock_irqrestore(&irq_desc[i].lock, flags);
1099                }
1100        }
1101
1102        decode_address(buf, fp->rete);
1103        verbose_printk(KERN_NOTICE " RETE: %s\n", buf);
1104        decode_address(buf, fp->retn);
1105        verbose_printk(KERN_NOTICE " RETN: %s\n", buf);
1106        decode_address(buf, fp->retx);
1107        verbose_printk(KERN_NOTICE " RETX: %s\n", buf);
1108        decode_address(buf, fp->rets);
1109        verbose_printk(KERN_NOTICE " RETS: %s\n", buf);
1110        decode_address(buf, fp->pc);
1111        verbose_printk(KERN_NOTICE " PC  : %s\n", buf);
1112
1113        if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
1114            (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
1115                decode_address(buf, saved_dcplb_fault_addr);
1116                verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
1117                decode_address(buf, saved_icplb_fault_addr);
1118                verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
1119        }
1120
1121        verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
1122        verbose_printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
1123                fp->r0, fp->r1, fp->r2, fp->r3);
1124        verbose_printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",
1125                fp->r4, fp->r5, fp->r6, fp->r7);
1126        verbose_printk(KERN_NOTICE " P0 : %08lx    P1 : %08lx    P2 : %08lx    P3 : %08lx\n",
1127                fp->p0, fp->p1, fp->p2, fp->p3);
1128        verbose_printk(KERN_NOTICE " P4 : %08lx    P5 : %08lx    FP : %08lx    SP : %08lx\n",
1129                fp->p4, fp->p5, fp->fp, (long)fp);
1130        verbose_printk(KERN_NOTICE " LB0: %08lx    LT0: %08lx    LC0: %08lx\n",
1131                fp->lb0, fp->lt0, fp->lc0);
1132        verbose_printk(KERN_NOTICE " LB1: %08lx    LT1: %08lx    LC1: %08lx\n",
1133                fp->lb1, fp->lt1, fp->lc1);
1134        verbose_printk(KERN_NOTICE " B0 : %08lx    L0 : %08lx    M0 : %08lx    I0 : %08lx\n",
1135                fp->b0, fp->l0, fp->m0, fp->i0);
1136        verbose_printk(KERN_NOTICE " B1 : %08lx    L1 : %08lx    M1 : %08lx    I1 : %08lx\n",
1137                fp->b1, fp->l1, fp->m1, fp->i1);
1138        verbose_printk(KERN_NOTICE " B2 : %08lx    L2 : %08lx    M2 : %08lx    I2 : %08lx\n",
1139                fp->b2, fp->l2, fp->m2, fp->i2);
1140        verbose_printk(KERN_NOTICE " B3 : %08lx    L3 : %08lx    M3 : %08lx    I3 : %08lx\n",
1141                fp->b3, fp->l3, fp->m3, fp->i3);
1142        verbose_printk(KERN_NOTICE "A0.w: %08lx   A0.x: %08lx   A1.w: %08lx   A1.x: %08lx\n",
1143                fp->a0w, fp->a0x, fp->a1w, fp->a1x);
1144
1145        verbose_printk(KERN_NOTICE "USP : %08lx  ASTAT: %08lx\n",
1146                rdusp(), fp->astat);
1147
1148        verbose_printk(KERN_NOTICE "\n");
1149#endif
1150}
1151
1152#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
1153asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
1154#endif
1155
1156asmlinkage int sys_bfin_spinlock(int *spinlock)
1157{
1158        int ret = 0;
1159        int tmp = 0;
1160
1161        local_irq_disable();
1162        ret = get_user(tmp, spinlock);
1163        if (ret == 0) {
1164                if (tmp)
1165                        ret = 1;
1166                tmp = 1;
1167                put_user(tmp, spinlock);
1168        }
1169        local_irq_enable();
1170        return ret;
1171}
1172
1173int bfin_request_exception(unsigned int exception, void (*handler)(void))
1174{
1175        void (*curr_handler)(void);
1176
1177        if (exception > 0x3F)
1178                return -EINVAL;
1179
1180        curr_handler = ex_table[exception];
1181
1182        if (curr_handler != ex_replaceable)
1183                return -EBUSY;
1184
1185        ex_table[exception] = handler;
1186
1187        return 0;
1188}
1189EXPORT_SYMBOL(bfin_request_exception);
1190
1191int bfin_free_exception(unsigned int exception, void (*handler)(void))
1192{
1193        void (*curr_handler)(void);
1194
1195        if (exception > 0x3F)
1196                return -EINVAL;
1197
1198        curr_handler = ex_table[exception];
1199
1200        if (curr_handler != handler)
1201                return -EBUSY;
1202
1203        ex_table[exception] = ex_replaceable;
1204
1205        return 0;
1206}
1207EXPORT_SYMBOL(bfin_free_exception);
1208
1209void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
1210{
1211        switch (cplb_panic) {
1212        case CPLB_NO_UNLOCKED:
1213                printk(KERN_EMERG "All CPLBs are locked\n");
1214                break;
1215        case CPLB_PROT_VIOL:
1216                return;
1217        case CPLB_NO_ADDR_MATCH:
1218                return;
1219        case CPLB_UNKNOWN_ERR:
1220                printk(KERN_EMERG "Unknown CPLB Exception\n");
1221                break;
1222        }
1223
1224        oops_in_progress = 1;
1225
1226        dump_bfin_process(fp);
1227        dump_bfin_mem(fp);
1228        show_regs(fp);
1229        dump_stack();
1230        panic("Unrecoverable event\n");
1231}
1232
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.