blob: 15468e5824572b4ff163d964d81cac53ef392a27 [file] [log] [blame]
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +02001/*
2 * (C) Copyright 2000 - 2007
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 *
22 * Derived from the MPC83xx code.
23 */
24
25/*
26 * This file handles the architecture-dependent parts of hardware
27 * exceptions
28 */
29
30#include <common.h>
Mike Frysinger629d88b2010-02-08 15:30:16 -050031#include <kgdb.h>
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020032#include <asm/processor.h>
33
34DECLARE_GLOBAL_DATA_PTR;
35
36extern unsigned long search_exception_table(unsigned long);
37
Becky Brucef095f5f2008-05-14 13:09:51 -050038/*
39 * End of addressable memory. This may be less than the actual
40 * amount of memory on the system if we're unable to keep all
41 * the memory mapped in.
42 */
43extern ulong get_effective_memsize(void);
44#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020045
46/*
47 * Trap & Exception support
48 */
49
Kim Phillipse16737f2012-10-29 13:34:29 +000050static void print_backtrace(unsigned long *sp)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020051{
52 int cnt = 0;
53 unsigned long i;
54
Kim Phillipse16737f2012-10-29 13:34:29 +000055 puts("Call backtrace: ");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020056 while (sp) {
57 if ((uint)sp > END_OF_MEM)
58 break;
59
60 i = sp[1];
61 if (cnt++ % 7 == 0)
Kim Phillipse16737f2012-10-29 13:34:29 +000062 putc('\n');
63 printf("%08lX ", i);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020064 if (cnt > 32) break;
65 sp = (unsigned long *) *sp;
66 }
Kim Phillipse16737f2012-10-29 13:34:29 +000067 putc('\n');
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020068}
69
Kim Phillipse16737f2012-10-29 13:34:29 +000070void show_regs(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020071{
72 int i;
73
Kim Phillipse16737f2012-10-29 13:34:29 +000074 printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020075 regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
Kim Phillipse16737f2012-10-29 13:34:29 +000076 printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020077 regs->msr, regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0,
78 regs->msr & MSR_FP ? 1 : 0,regs->msr & MSR_ME ? 1 : 0,
79 regs->msr & MSR_IR ? 1 : 0,
80 regs->msr & MSR_DR ? 1 : 0);
81
Kim Phillipse16737f2012-10-29 13:34:29 +000082 putc('\n');
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020083 for (i = 0; i < 32; i++) {
84 if ((i % 8) == 0) {
Kim Phillipse16737f2012-10-29 13:34:29 +000085 printf("GPR%02d: ", i);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020086 }
87
Kim Phillipse16737f2012-10-29 13:34:29 +000088 printf("%08lX ", regs->gpr[i]);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020089 if ((i % 8) == 7) {
Kim Phillipse16737f2012-10-29 13:34:29 +000090 putc('\n');
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020091 }
92 }
93}
94
95
Kim Phillipse16737f2012-10-29 13:34:29 +000096static void _exception(int signr, struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020097{
Kim Phillipse16737f2012-10-29 13:34:29 +000098 show_regs(regs);
99 print_backtrace((unsigned long *)regs->gpr[1]);
100 panic("Exception at pc %lx signal %d", regs->nip, signr);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200101}
102
103
Kim Phillipse16737f2012-10-29 13:34:29 +0000104void MachineCheckException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200105{
Kim Phillipse16737f2012-10-29 13:34:29 +0000106 unsigned long fixup = search_exception_table(regs->nip);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200107
Kim Phillipse16737f2012-10-29 13:34:29 +0000108 if (fixup) {
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200109 regs->nip = fixup;
110 return;
111 }
112
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200113#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200114 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
115 return;
116#endif
117
Kim Phillipse16737f2012-10-29 13:34:29 +0000118 puts("Machine check.\nCaused by (from msr): ");
119 printf("regs %p ", regs);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200120 switch (regs->msr & 0x00FF0000) {
121 case (0x80000000 >> 10):
Kim Phillipse16737f2012-10-29 13:34:29 +0000122 puts("Instruction cache parity signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200123 break;
124 case (0x80000000 >> 11):
Kim Phillipse16737f2012-10-29 13:34:29 +0000125 puts("Data cache parity signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200126 break;
127 case (0x80000000 >> 12):
Kim Phillipse16737f2012-10-29 13:34:29 +0000128 puts("Machine check signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200129 break;
130 case (0x80000000 >> 13):
Kim Phillipse16737f2012-10-29 13:34:29 +0000131 puts("Transfer error ack signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200132 break;
133 case (0x80000000 >> 14):
Kim Phillipse16737f2012-10-29 13:34:29 +0000134 puts("Data parity signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200135 break;
136 case (0x80000000 >> 15):
Kim Phillipse16737f2012-10-29 13:34:29 +0000137 puts("Address parity signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200138 break;
139 default:
Kim Phillipse16737f2012-10-29 13:34:29 +0000140 puts("Unknown values in msr\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200141 }
Kim Phillipse16737f2012-10-29 13:34:29 +0000142 show_regs(regs);
143 print_backtrace((unsigned long *)regs->gpr[1]);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200144
Kim Phillipse16737f2012-10-29 13:34:29 +0000145 panic("machine check");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200146}
147
Kim Phillipse16737f2012-10-29 13:34:29 +0000148void AlignmentException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200149{
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200150#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200151 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
152 return;
153#endif
Kim Phillipse16737f2012-10-29 13:34:29 +0000154 show_regs(regs);
155 print_backtrace((unsigned long *)regs->gpr[1]);
156 panic("Alignment Exception");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200157}
158
Kim Phillipse16737f2012-10-29 13:34:29 +0000159void ProgramCheckException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200160{
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200161#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200162 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
163 return;
164#endif
Kim Phillipse16737f2012-10-29 13:34:29 +0000165 show_regs(regs);
166 print_backtrace((unsigned long *)regs->gpr[1]);
167 panic("Program Check Exception");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200168}
169
Kim Phillipse16737f2012-10-29 13:34:29 +0000170void SoftEmuException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200171{
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200172#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200173 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
174 return;
175#endif
Kim Phillipse16737f2012-10-29 13:34:29 +0000176 show_regs(regs);
177 print_backtrace((unsigned long *)regs->gpr[1]);
178 panic("Software Emulation Exception");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200179}
180
181
Kim Phillipse16737f2012-10-29 13:34:29 +0000182void UnknownException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200183{
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200184#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200185 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
186 return;
187#endif
Kim Phillipse16737f2012-10-29 13:34:29 +0000188 printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200189 regs->nip, regs->msr, regs->trap);
Kim Phillipse16737f2012-10-29 13:34:29 +0000190 _exception(0, regs);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200191}
192
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200193#ifdef CONFIG_CMD_BEDBUG
Kim Phillipse16737f2012-10-29 13:34:29 +0000194extern void do_bedbug_breakpoint(struct pt_regs *);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200195#endif
196
Kim Phillipse16737f2012-10-29 13:34:29 +0000197void DebugException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200198{
Kim Phillipse16737f2012-10-29 13:34:29 +0000199 printf("Debugger trap at @ %lx\n", regs->nip);
200 show_regs(regs);
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200201#ifdef CONFIG_CMD_BEDBUG
Kim Phillipse16737f2012-10-29 13:34:29 +0000202 do_bedbug_breakpoint(regs);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200203#endif
204}