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#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
 213        mfsdram(DDR0_00, val) ;
 214        printf("DDR0: DDR0_00 %lx\n", val);
 215        val = (val >> 16) & 0xff;
 216        if (val & 0x80)
 217                printf("DDR0: At least one interrupt active\n");
 218        if (val & 0x40)
 219                printf("DDR0: DRAM initialization complete.\n");
 220        if (val & 0x20) {
 221                printf("DDR0: Multiple uncorrectable ECC events.\n");
 222                uncorr_ecc = 1;
 223        }
 224        if (val & 0x10) {
 225                printf("DDR0: Single uncorrectable ECC event.\n");
 226                uncorr_ecc = 1;
 227        }
 228        if (val & 0x08) {
 229                printf("DDR0: Multiple correctable ECC events.\n");
 230                corr_ecc = 1;
 231        }
 232        if (val & 0x04) {
 233                printf("DDR0: Single correctable ECC event.\n");
 234                corr_ecc = 1;
 235        }
 236        if (val & 0x02)
 237                printf("Multiple accesses outside the defined"
 238                       " physical memory space detected\n");
 239        if (val & 0x01)
 240                printf("DDR0: Single access outside the defined"
 241                       " physical memory space detected.\n");
 242
 243        mfsdram(DDR0_01, val);
 244        val = (val >> 8) & 0x7;
 245        switch (val ) {
 246        case 0:
 247                printf("DDR0: Write Out-of-Range command\n");
 248                break;
 249        case 1:
 250                printf("DDR0: Read Out-of-Range command\n");
 251                break;
 252        case 2:
 253                printf("DDR0: Masked write Out-of-Range command\n");
 254                break;
 255        case 4:
 256                printf("DDR0: Wrap write Out-of-Range command\n");
 257                break;
 258        case 5:
 259                printf("DDR0: Wrap read Out-of-Range command\n");
 260                break;
 261        default:
 262                mfsdram(DDR0_01, value2);
 263                printf("DDR0: No DDR0 error know 0x%lx %x\n", val, value2);
 264        }
 265        mfsdram(DDR0_23, val);
 266        if (((val >> 16) & 0xff) && corr_ecc)
 267                printf("DDR0: Syndrome for correctable ECC event 0x%lx\n",
 268                       (val >> 16) & 0xff);
 269        mfsdram(DDR0_23, val);
 270        if (((val >> 8) & 0xff) && uncorr_ecc)
 271                printf("DDR0: Syndrome for uncorrectable ECC event 0x%lx\n",
 272                       (val >> 8) & 0xff);
 273        mfsdram(DDR0_33, val);
 274        if (val)
 275                printf("DDR0: Address of command that caused an "
 276                       "Out-of-Range interrupt %lx\n", val);
 277        mfsdram(DDR0_34, val);
 278        if (val && uncorr_ecc)
 279                printf("DDR0: Address of uncorrectable ECC event %lx\n", val);
 280        mfsdram(DDR0_35, val);
 281        if (val && uncorr_ecc)
 282                printf("DDR0: Address of uncorrectable ECC event %lx\n", val);
 283        mfsdram(DDR0_36, val);
 284        if (val && uncorr_ecc)
 285                printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val);
 286        mfsdram(DDR0_37, val);
 287        if (val && uncorr_ecc)
 288                printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val);
 289        mfsdram(DDR0_38, val);
 290        if (val && corr_ecc)
 291                printf("DDR0: Address of correctable ECC event %lx\n", val);
 292        mfsdram(DDR0_39, val);
 293        if (val && corr_ecc)
 294                printf("DDR0: Address of correctable ECC event %lx\n", val);
 295        mfsdram(DDR0_40, val);
 296        if (val && corr_ecc)
 297                printf("DDR0: Data of correctable ECC event 0x%08lx\n", val);
 298        mfsdram(DDR0_41, val);
 299        if (val && corr_ecc)
 300                printf("DDR0: Data of correctable ECC event 0x%08lx\n", val);
 301#endif /* CONFIG_440EPX */
 302#endif /* CONFIG_440 */
 303        show_regs(regs);
 304        print_backtrace((unsigned long *)regs->gpr[1]);
 305        panic("machine check");
 306}
 307
 308void
 309AlignmentException(struct pt_regs *regs)
 310{
 311#if defined(CONFIG_CMD_KGDB)
 312        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 313                return;
 314#endif
 315
 316        show_regs(regs);
 317        print_backtrace((unsigned long *)regs->gpr[1]);
 318        panic("Alignment Exception");
 319}
 320
 321void
 322ProgramCheckException(struct pt_regs *regs)
 323{
 324        long esr_val;
 325
 326#if defined(CONFIG_CMD_KGDB)
 327        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 328                return;
 329#endif
 330
 331        show_regs(regs);
 332
 333        esr_val = get_esr();
 334        if( esr_val & ESR_PIL )
 335                printf( "** Illegal Instruction **\n" );
 336        else if( esr_val & ESR_PPR )
 337                printf( "** Privileged Instruction **\n" );
 338        else if( esr_val & ESR_PTR )
 339                printf( "** Trap Instruction **\n" );
 340
 341        print_backtrace((unsigned long *)regs->gpr[1]);
 342        panic("Program Check Exception");
 343}
 344
 345void
 346DecrementerPITException(struct pt_regs *regs)
 347{
 348        /*
 349         * Reset PIT interrupt
 350         */
 351        set_tsr(0x08000000);
 352
 353        /*
 354         * Call timer_interrupt routine in interrupts.c
 355         */
 356        timer_interrupt(NULL);
 357}
 358
 359
 360void
 361UnknownException(struct pt_regs *regs)
 362{
 363#if defined(CONFIG_CMD_KGDB)
 364        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 365                return;
 366#endif
 367
 368        printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
 369               regs->nip, regs->msr, regs->trap);
 370        _exception(0, regs);
 371}
 372
 373void
 374DebugException(struct pt_regs *regs)
 375{
 376        printf("Debugger trap at @ %lx\n", regs->nip );
 377        show_regs(regs);
 378#if defined(CONFIG_CMD_BEDBUG)
 379        do_bedbug_breakpoint( regs );
 380#endif
 381}
 382
 383/* Probe an address by reading.  If not present, return -1, otherwise
 384 * return 0.
 385 */
 386int
 387addr_probe(uint *addr)
 388{
 389#if 0
 390        int     retval;
 391
 392        __asm__ __volatile__(                   \
 393                "1:     lwz %0,0(%1)\n"         \
 394                "       eieio\n"                \
 395                "       li %0,0\n"              \
 396                "2:\n"                          \
 397                ".section .fixup,\"ax\"\n"      \
 398                "3:     li %0,-1\n"             \
 399                "       b 2b\n"                 \
 400                ".section __ex_table,\"a\"\n"   \
 401                "       .align 2\n"             \
 402                "       .long 1b,3b\n"          \
 403                ".text"                         \
 404                : "=r" (retval) : "r"(addr));
 405
 406        return (retval);
 407#endif
 408        return 0;
 409}
 410