uboot/arch/powerpc/cpu/mpc83xx/traps.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9
  10/*
  11 * This file handles the architecture-dependent parts of hardware
  12 * exceptions
  13 */
  14
  15#include <common.h>
  16#include <command.h>
  17#include <kgdb.h>
  18#include <asm/processor.h>
  19#include <asm/mpc8349_pci.h>
  20
  21DECLARE_GLOBAL_DATA_PTR;
  22
  23/* Returns 0 if exception not found and fixup otherwise.  */
  24extern unsigned long search_exception_table(unsigned long);
  25
  26#define END_OF_MEM      (gd->bd->bi_memstart + gd->bd->bi_memsize)
  27
  28/*
  29 * Trap & Exception support
  30 */
  31
  32static void print_backtrace(unsigned long *sp)
  33{
  34        int cnt = 0;
  35        unsigned long i;
  36
  37        puts ("Call backtrace: ");
  38        while (sp) {
  39                if ((uint)sp > END_OF_MEM)
  40                        break;
  41
  42                i = sp[1];
  43                if (cnt++ % 7 == 0)
  44                        putc ('\n');
  45                printf("%08lX ", i);
  46                if (cnt > 32) break;
  47                sp = (unsigned long *)*sp;
  48        }
  49        putc ('\n');
  50}
  51
  52void show_regs(struct pt_regs *regs)
  53{
  54        int i;
  55
  56        printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
  57               regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
  58        printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
  59               regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
  60               regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
  61               regs->msr&MSR_IR ? 1 : 0,
  62               regs->msr&MSR_DR ? 1 : 0);
  63
  64        putc ('\n');
  65        for (i = 0;  i < 32;  i++) {
  66                if ((i % 8) == 0) {
  67                        printf("GPR%02d: ", i);
  68                }
  69
  70                printf("%08lX ", regs->gpr[i]);
  71                if ((i % 8) == 7) {
  72                        putc ('\n');
  73                }
  74        }
  75}
  76
  77
  78static void _exception(int signr, struct pt_regs *regs)
  79{
  80        show_regs(regs);
  81        print_backtrace((unsigned long *)regs->gpr[1]);
  82        panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
  83}
  84
  85#ifdef CONFIG_PCI
  86void dump_pci (void)
  87{
  88/*
  89        volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
  90        printf ("PCI: err status %x err mask %x err ctrl %x\n",
  91                le32_to_cpu (immap->im_pci.pci_esr),
  92                le32_to_cpu (immap->im_pci.pci_emr),
  93                le32_to_cpu (immap->im_pci.pci_ecr));
  94        printf ("     error address %x error data %x ctrl %x\n",
  95                le32_to_cpu (immap->im_pci.pci_eacr),
  96                le32_to_cpu (immap->im_pci.pci_edcr),
  97                le32_to_cpu (immap->im_pci.pci_eccr));
  98*/
  99}
 100#endif
 101
 102void MachineCheckException(struct pt_regs *regs)
 103{
 104        unsigned long fixup;
 105
 106        /* Probing PCI using config cycles cause this exception
 107         * when a device is not present.  Catch it and return to
 108         * the PCI exception handler.
 109         */
 110#ifdef CONFIG_PCI
 111#if 0
 112        volatile immap_t *immap  = (immap_t *)CONFIG_SYS_IMMR;
 113#ifdef DEBUG
 114        dump_pci();
 115#endif
 116        /* clear the error in the error status register */
 117        if(immap->im_pci.pci_esr & cpu_to_le32(PCI_ERROR_PCI_NO_RSP)) {
 118                immap->im_pci.pci_esr = cpu_to_le32(PCI_ERROR_PCI_NO_RSP);
 119                return;
 120        }
 121#endif
 122#endif /* CONFIG_PCI */
 123        if ((fixup = search_exception_table(regs->nip)) != 0) {
 124                regs->nip = fixup;
 125                return;
 126        }
 127
 128#if defined(CONFIG_CMD_KGDB)
 129        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 130                return;
 131#endif
 132
 133        puts ("Machine check in kernel mode.\n"
 134                "Caused by (from msr): ");
 135        printf("regs %p ",regs);
 136        switch( regs->msr & 0x000F0000) {
 137        case (0x80000000>>12):
 138                puts ("Machine check signal - probably due to mm fault\n"
 139                        "with mmu off\n");
 140                break;
 141        case (0x80000000>>13):
 142                puts ("Transfer error ack signal\n");
 143                break;
 144        case (0x80000000>>14):
 145                puts ("Data parity signal\n");
 146                break;
 147        case (0x80000000>>15):
 148                puts ("Address parity signal\n");
 149                break;
 150        default:
 151                puts ("Unknown values in msr\n");
 152        }
 153        show_regs(regs);
 154        print_backtrace((unsigned long *)regs->gpr[1]);
 155#ifdef CONFIG_PCI
 156        dump_pci();
 157#endif
 158        panic("machine check");
 159}
 160
 161void AlignmentException(struct pt_regs *regs)
 162{
 163#if defined(CONFIG_CMD_KGDB)
 164        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 165                return;
 166#endif
 167        show_regs(regs);
 168        print_backtrace((unsigned long *)regs->gpr[1]);
 169        panic("Alignment Exception");
 170}
 171
 172void ProgramCheckException(struct pt_regs *regs)
 173{
 174#if defined(CONFIG_CMD_KGDB)
 175        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 176                return;
 177#endif
 178        show_regs(regs);
 179        print_backtrace((unsigned long *)regs->gpr[1]);
 180        panic("Program Check Exception");
 181}
 182
 183void SoftEmuException(struct pt_regs *regs)
 184{
 185#if defined(CONFIG_CMD_KGDB)
 186        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 187                return;
 188#endif
 189        show_regs(regs);
 190        print_backtrace((unsigned long *)regs->gpr[1]);
 191        panic("Software Emulation Exception");
 192}
 193
 194
 195void UnknownException(struct pt_regs *regs)
 196{
 197#if defined(CONFIG_CMD_KGDB)
 198        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
 199                return;
 200#endif
 201        printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
 202               regs->nip, regs->msr, regs->trap);
 203        _exception(0, regs);
 204}
 205
 206#if defined(CONFIG_CMD_BEDBUG)
 207extern void do_bedbug_breakpoint(struct pt_regs *);
 208#endif
 209
 210void DebugException(struct pt_regs *regs)
 211{
 212        printf("Debugger trap at @ %lx\n", regs->nip );
 213        show_regs(regs);
 214#if defined(CONFIG_CMD_BEDBUG)
 215        do_bedbug_breakpoint( regs );
 216#endif
 217}
 218
 219/* Probe an address by reading.  If not present, return -1, otherwise
 220 * return 0.
 221 */
 222int addr_probe(uint *addr)
 223{
 224#if 0
 225        int     retval;
 226
 227        __asm__ __volatile__(                   \
 228                "1:     lwz %0,0(%1)\n"         \
 229                "       eieio\n"                \
 230                "       li %0,0\n"              \
 231                "2:\n"                          \
 232                ".section .fixup,\"ax\"\n"      \
 233                "3:     li %0,-1\n"             \
 234                "       b 2b\n"                 \
 235                ".section __ex_table,\"a\"\n"   \
 236                "       .align 2\n"             \
 237                "       .long 1b,3b\n"          \
 238                ".text"                         \
 239                : "=r" (retval) : "r"(addr));
 240
 241        return (retval);
 242#endif
 243        return 0;
 244}
 245