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