uboot/arch/powerpc/cpu/ppc4xx/traps.c
<<
>>
Prefs
   1/*
   2 * linux/arch/powerpc/kernel/traps.c
   3 *
   4 * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
   5 *
   6 * Modified by Cort Dougan (cort@cs.nmt.edu)
   7 * and Paul Mackerras (paulus@cs.anu.edu.au)
   8 *
   9 * (C) Copyright 2000
  10 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  11 *
  12 * See file CREDITS for list of people who contributed to this
  13 * project.
  14 *
  15 * This program is free software; you can redistribute it and/or
  16 * modify it under the terms of the GNU General Public License as
  17 * published by the Free Software Foundation; either version 2 of
  18 * the License, or (at your option) any later version.
  19 *
  20 * This program is distributed in the hope that it will be useful,
  21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23 * GNU General Public License for more details.
  24 *
  25 * You should have received a copy of the GNU General Public License
  26 * along with this program; if not, write to the Free Software
  27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  28 * MA 02111-1307 USA
  29 */
  30
  31/*
  32 * This file handles the architecture-dependent parts of hardware exceptions
  33 */
  34
  35#include <common.h>
  36#include <command.h>
  37#include <kgdb.h>
  38#include <asm/processor.h>
  39
  40DECLARE_GLOBAL_DATA_PTR;
  41
  42/* Returns 0 if exception not found and fixup otherwise.  */
  43extern unsigned long search_exception_table(unsigned long);
  44
  45/* THIS NEEDS CHANGING to use the board info structure.
  46 */
  47#define END_OF_MEM      (gd->bd->bi_memstart + gd->bd->bi_memsize)
  48
  49static __inline__ void set_tsr(unsigned long val)
  50{
  51#if defined(CONFIG_440)
  52        asm volatile("mtspr 0x150, %0" : : "r" (val));
  53#else
  54        asm volatile("mttsr %0" : : "r" (val));
  55#endif
  56}
  57
  58static __inline__ unsigned long get_esr(void)
  59{
  60        unsigned long val;
  61
  62#if defined(CONFIG_440)
  63        asm volatile("mfspr %0, 0x03e" : "=r" (val) :);
  64#else
  65        asm volatile("mfesr %0" : "=r" (val) :);
  66#endif
  67        return val;
  68}
  69
  70#define ESR_MCI 0x80000000
  71#define ESR_PIL 0x08000000
  72#define ESR_PPR 0x04000000
  73#define ESR_PTR 0x02000000
  74#define ESR_DST 0x00800000
  75#define ESR_DIZ 0x00400000
  76#define ESR_U0F 0x00008000
  77
  78#if defined(CONFIG_CMD_BEDBUG)
  79extern void do_bedbug_breakpoint(struct pt_regs *);
  80#endif
  81
  82/*
  83 * Trap & Exception support
  84 */
  85
  86void
  87print_backtrace(unsigned long *sp)
  88{
  89        int cnt = 0;
  90        unsigned long i;
  91
  92        printf("Call backtrace: ");
  93        while (sp) {
  94                if ((uint)sp > END_OF_MEM)
  95                        break;
  96
  97                i = sp[1];
  98                if (cnt++ % 7 == 0)
  99                        printf("\n");
 100                printf("%08lX ", i);
 101                if (cnt > 32) break;
 102                sp = (unsigned long *)*sp;
 103        }
 104        printf("\n");
 105}
 106
 107void show_regs(struct pt_regs * regs)
 108{
 109        int i;
 110
 111        printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DEAR: %08lX\n",
 112               regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
 113        printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
 114               regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
 115               regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
 116               regs->msr&MSR_IR ? 1 : 0,
 117               regs->msr&MSR_DR ? 1 : 0);
 118
 119        printf("\n");
 120        for (i = 0;  i < 32;  i++) {
 121                if ((i % 8) == 0) {
 122                        printf("GPR%02d: ", i);
 123                }
 124
 125                printf("%08lX ", regs->gpr[i]);
 126                if ((i % 8) == 7) {
 127                        printf("\n");
 128                }
 129        }
 130}
 131
 132
 133void
 134_exception(int signr, struct pt_regs *regs)
 135{
 136        show_regs(regs);
 137        print_backtrace((unsigned long *)regs->gpr[1]);
 138        panic("Exception");
 139}
 140
 141void
 142MachineCheckException(struct pt_regs *regs)
 143{
 144        unsigned long fixup, val;
 145#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
 146        u32 value2;
 147        int corr_ecc = 0;
 148        int uncorr_ecc = 0;
 149#endif
 150
 151        if ((fixup = search_exception_table(regs->nip)) != 0) {
 152                regs->nip = fixup;
 153                val = mfspr(MCSR);
 154                /* Clear MCSR */
 155                mtspr(SPRN_MCSR, val);
 156                return;
 157        }
 158
 159#if defined(CONFIG_CMD_KGDB)
 160        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 161                return;
 162#endif
 163
 164        printf("Machine Check Exception.\n");
 165        printf("Caused by (from msr): ");
 166        printf("regs %p ", regs);
 167
 168        val = get_esr();
 169
 170#if !defined(CONFIG_440) && !defined(CONFIG_405EX)
 171        if (val& ESR_IMCP) {
 172                printf("Instruction");
 173                mtspr(ESR, val & ~ESR_IMCP);
 174        } else {
 175                printf("Data");
 176        }
 177        printf(" machine check.\n");
 178
 179#elif defined(CONFIG_440) || defined(CONFIG_405EX)
 180        if (val& ESR_IMCP){
 181                printf("Instruction Synchronous Machine Check exception\n");
 182                mtspr(SPRN_ESR, val & ~ESR_IMCP);
 183        } else {
 184                val = mfspr(MCSR);
 185                if (val & MCSR_IB)
 186                        printf("Instruction Read PLB Error\n");
 187#if defined(CONFIG_440)
 188                if (val & MCSR_DRB)
 189                        printf("Data Read PLB Error\n");
 190                if (val & MCSR_DWB)
 191                        printf("Data Write PLB Error\n");
 192#else
 193                if (val & MCSR_DB)
 194                        printf("Data PLB Error\n");
 195#endif
 196                if (val & MCSR_TLBP)
 197                        printf("TLB Parity Error\n");
 198                if (val & MCSR_ICP){
 199                        /*flush_instruction_cache(); */
 200                        printf("I-Cache Parity Error\n");
 201                }
 202                if (val & MCSR_DCSP)
 203                        printf("D-Cache Search Parity Error\n");
 204                if (val & MCSR_DCFP)
 205                        printf("D-Cache Flush Parity Error\n");
 206                if (val & MCSR_IMPE)
 207                        printf("Machine Check exception is imprecise\n");
 208
 209                /* Clear MCSR */
 210                mtspr(SPRN_MCSR, val);
 211        }
 212
 213#if defined(CONFIG_DDR_ECC) && defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
 214        /*
 215         * Read and print ECC status register/info:
 216         * The faulting address is only known upon uncorrectable ECC
 217         * errors.
 218         */
 219        mfsdram(SDRAM_ECCES, val);
 220        if (val & SDRAM_ECCES_CE)
 221                printf("ECC: Correctable error\n");
 222        if (val & SDRAM_ECCES_UE) {
 223                printf("ECC: Uncorrectable error at 0x%02x%08x\n",
 224                       mfdcr(SDRAM_ERRADDULL), mfdcr(SDRAM_ERRADDLLL));
 225        }
 226#endif /* CONFIG_DDR_ECC ... */
 227
 228#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
 229        mfsdram(DDR0_00, val) ;
 230        printf("DDR0: DDR0_00 %lx\n", val);
 231        val = (val >> 16) & 0xff;
 232        if (val & 0x80)
 233                printf("DDR0: At least one interrupt active\n");
 234        if (val & 0x40)
 235                printf("DDR0: DRAM initialization complete.\n");
 236        if (val & 0x20) {
 237                printf("DDR0: Multiple uncorrectable ECC events.\n");
 238                uncorr_ecc = 1;
 239        }
 240        if (val & 0x10) {
 241                printf("DDR0: Single uncorrectable ECC event.\n");
 242                uncorr_ecc = 1;
 243        }
 244        if (val & 0x08) {
 245                printf("DDR0: Multiple correctable ECC events.\n");
 246                corr_ecc = 1;
 247        }
 248        if (val & 0x04) {
 249                printf("DDR0: Single correctable ECC event.\n");
 250                corr_ecc = 1;
 251        }
 252        if (val & 0x02)
 253                printf("Multiple accesses outside the defined"
 254                       " physical memory space detected\n");
 255        if (val & 0x01)
 256                printf("DDR0: Single access outside the defined"
 257                       " physical memory space detected.\n");
 258
 259        mfsdram(DDR0_01, val);
 260        val = (val >> 8) & 0x7;
 261        switch (val ) {
 262        case 0:
 263                printf("DDR0: Write Out-of-Range command\n");
 264                break;
 265        case 1:
 266                printf("DDR0: Read Out-of-Range command\n");
 267                break;
 268        case 2:
 269                printf("DDR0: Masked write Out-of-Range command\n");
 270                break;
 271        case 4:
 272                printf("DDR0: Wrap write Out-of-Range command\n");
 273                break;
 274        case 5:
 275                printf("DDR0: Wrap read Out-of-Range command\n");
 276                break;
 277        default:
 278                mfsdram(DDR0_01, value2);
 279                printf("DDR0: No DDR0 error know 0x%lx %x\n", val, value2);
 280        }
 281        mfsdram(DDR0_23, val);
 282        if (((val >> 16) & 0xff) && corr_ecc)
 283                printf("DDR0: Syndrome for correctable ECC event 0x%lx\n",
 284                       (val >> 16) & 0xff);
 285        mfsdram(DDR0_23, val);
 286        if (((val >> 8) & 0xff) && uncorr_ecc)
 287                printf("DDR0: Syndrome for uncorrectable ECC event 0x%lx\n",
 288                       (val >> 8) & 0xff);
 289        mfsdram(DDR0_33, val);
 290        if (val)
 291                printf("DDR0: Address of command that caused an "
 292                       "Out-of-Range interrupt %lx\n", val);
 293        mfsdram(DDR0_34, val);
 294        if (val && uncorr_ecc)
 295                printf("DDR0: Address of uncorrectable ECC event %lx\n", val);
 296        mfsdram(DDR0_35, val);
 297        if (val && uncorr_ecc)
 298                printf("DDR0: Address of uncorrectable ECC event %lx\n", val);
 299        mfsdram(DDR0_36, val);
 300        if (val && uncorr_ecc)
 301                printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val);
 302        mfsdram(DDR0_37, val);
 303        if (val && uncorr_ecc)
 304                printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val);
 305        mfsdram(DDR0_38, val);
 306        if (val && corr_ecc)
 307                printf("DDR0: Address of correctable ECC event %lx\n", val);
 308        mfsdram(DDR0_39, val);
 309        if (val && corr_ecc)
 310                printf("DDR0: Address of correctable ECC event %lx\n", val);
 311        mfsdram(DDR0_40, val);
 312        if (val && corr_ecc)
 313                printf("DDR0: Data of correctable ECC event 0x%08lx\n", val);
 314        mfsdram(DDR0_41, val);
 315        if (val && corr_ecc)
 316                printf("DDR0: Data of correctable ECC event 0x%08lx\n", val);
 317#endif /* CONFIG_440EPX */
 318#endif /* CONFIG_440 */
 319        show_regs(regs);
 320        print_backtrace((unsigned long *)regs->gpr[1]);
 321        panic("machine check");
 322}
 323
 324void
 325AlignmentException(struct pt_regs *regs)
 326{
 327#if defined(CONFIG_CMD_KGDB)
 328        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 329                return;
 330#endif
 331
 332        show_regs(regs);
 333        print_backtrace((unsigned long *)regs->gpr[1]);
 334        panic("Alignment Exception");
 335}
 336
 337void
 338ProgramCheckException(struct pt_regs *regs)
 339{
 340        long esr_val;
 341
 342#if defined(CONFIG_CMD_KGDB)
 343        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 344                return;
 345#endif
 346
 347        show_regs(regs);
 348
 349        esr_val = get_esr();
 350        if( esr_val & ESR_PIL )
 351                printf( "** Illegal Instruction **\n" );
 352        else if( esr_val & ESR_PPR )
 353                printf( "** Privileged Instruction **\n" );
 354        else if( esr_val & ESR_PTR )
 355                printf( "** Trap Instruction **\n" );
 356
 357        print_backtrace((unsigned long *)regs->gpr[1]);
 358        panic("Program Check Exception");
 359}
 360
 361void
 362DecrementerPITException(struct pt_regs *regs)
 363{
 364        /*
 365         * Reset PIT interrupt
 366         */
 367        set_tsr(0x08000000);
 368
 369        /*
 370         * Call timer_interrupt routine in interrupts.c
 371         */
 372        timer_interrupt(NULL);
 373}
 374
 375
 376void
 377UnknownException(struct pt_regs *regs)
 378{
 379#if defined(CONFIG_CMD_KGDB)
 380        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 381                return;
 382#endif
 383
 384        printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
 385               regs->nip, regs->msr, regs->trap);
 386        _exception(0, regs);
 387}
 388
 389void
 390DebugException(struct pt_regs *regs)
 391{
 392        printf("Debugger trap at @ %lx\n", regs->nip );
 393        show_regs(regs);
 394#if defined(CONFIG_CMD_BEDBUG)
 395        do_bedbug_breakpoint( regs );
 396#endif
 397}
 398
 399/* Probe an address by reading.  If not present, return -1, otherwise
 400 * return 0.
 401 */
 402int
 403addr_probe(uint *addr)
 404{
 405#if 0
 406        int     retval;
 407
 408        __asm__ __volatile__(                   \
 409                "1:     lwz %0,0(%1)\n"         \
 410                "       eieio\n"                \
 411                "       li %0,0\n"              \
 412                "2:\n"                          \
 413                ".section .fixup,\"ax\"\n"      \
 414                "3:     li %0,-1\n"             \
 415                "       b 2b\n"                 \
 416                ".section __ex_table,\"a\"\n"   \
 417                "       .align 2\n"             \
 418                "       .long 1b,3b\n"          \
 419                ".text"                         \
 420                : "=r" (retval) : "r"(addr));
 421
 422        return (retval);
 423#endif
 424        return 0;
 425}
 426