15468e5824572b4ff163d964d81cac53ef392a27
[oweals/u-boot.git] / arch / powerpc / cpu / mpc512x / traps.c
1 /*
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>
31 #include <kgdb.h>
32 #include <asm/processor.h>
33
34 DECLARE_GLOBAL_DATA_PTR;
35
36 extern unsigned long search_exception_table(unsigned long);
37
38 /*
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  */
43 extern ulong get_effective_memsize(void);
44 #define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
45
46 /*
47  * Trap & Exception support
48  */
49
50 static void print_backtrace(unsigned long *sp)
51 {
52         int cnt = 0;
53         unsigned long i;
54
55         puts("Call backtrace: ");
56         while (sp) {
57                 if ((uint)sp > END_OF_MEM)
58                         break;
59
60                 i = sp[1];
61                 if (cnt++ % 7 == 0)
62                         putc('\n');
63                 printf("%08lX ", i);
64                 if (cnt > 32) break;
65                 sp = (unsigned long *) *sp;
66         }
67         putc('\n');
68 }
69
70 void show_regs(struct pt_regs *regs)
71 {
72         int i;
73
74         printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
75                regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
76         printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
77                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
82         putc('\n');
83         for (i = 0;  i < 32;  i++) {
84                 if ((i % 8) == 0) {
85                         printf("GPR%02d: ", i);
86                 }
87
88                 printf("%08lX ", regs->gpr[i]);
89                 if ((i % 8) == 7) {
90                         putc('\n');
91                 }
92         }
93 }
94
95
96 static void _exception(int signr, struct pt_regs *regs)
97 {
98         show_regs(regs);
99         print_backtrace((unsigned long *)regs->gpr[1]);
100         panic("Exception at pc %lx signal %d", regs->nip, signr);
101 }
102
103
104 void MachineCheckException(struct pt_regs *regs)
105 {
106         unsigned long fixup = search_exception_table(regs->nip);
107
108         if (fixup) {
109                 regs->nip = fixup;
110                 return;
111         }
112
113 #ifdef CONFIG_CMD_KGDB
114         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
115                 return;
116 #endif
117
118         puts("Machine check.\nCaused by (from msr): ");
119         printf("regs %p ", regs);
120         switch (regs->msr & 0x00FF0000) {
121         case (0x80000000 >> 10):
122                 puts("Instruction cache parity signal\n");
123                 break;
124         case (0x80000000 >> 11):
125                 puts("Data cache parity signal\n");
126                 break;
127         case (0x80000000 >> 12):
128                 puts("Machine check signal\n");
129                 break;
130         case (0x80000000 >> 13):
131                 puts("Transfer error ack signal\n");
132                 break;
133         case (0x80000000 >> 14):
134                 puts("Data parity signal\n");
135                 break;
136         case (0x80000000 >> 15):
137                 puts("Address parity signal\n");
138                 break;
139         default:
140                 puts("Unknown values in msr\n");
141         }
142         show_regs(regs);
143         print_backtrace((unsigned long *)regs->gpr[1]);
144
145         panic("machine check");
146 }
147
148 void AlignmentException(struct pt_regs *regs)
149 {
150 #ifdef 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("Alignment Exception");
157 }
158
159 void ProgramCheckException(struct pt_regs *regs)
160 {
161 #ifdef 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("Program Check Exception");
168 }
169
170 void SoftEmuException(struct pt_regs *regs)
171 {
172 #ifdef CONFIG_CMD_KGDB
173         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
174                 return;
175 #endif
176         show_regs(regs);
177         print_backtrace((unsigned long *)regs->gpr[1]);
178         panic("Software Emulation Exception");
179 }
180
181
182 void UnknownException(struct pt_regs *regs)
183 {
184 #ifdef CONFIG_CMD_KGDB
185         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
186                 return;
187 #endif
188         printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
189                regs->nip, regs->msr, regs->trap);
190         _exception(0, regs);
191 }
192
193 #ifdef CONFIG_CMD_BEDBUG
194 extern void do_bedbug_breakpoint(struct pt_regs *);
195 #endif
196
197 void DebugException(struct pt_regs *regs)
198 {
199         printf("Debugger trap at @ %lx\n", regs->nip);
200         show_regs(regs);
201 #ifdef CONFIG_CMD_BEDBUG
202         do_bedbug_breakpoint(regs);
203 #endif
204 }