]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc512x/traps.c
Merge branch 'karo-tx-uboot' into kc-merge
[karo-tx-uboot.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  * SPDX-License-Identifier:     GPL-2.0+
8  *
9  * Derived from the MPC83xx code.
10  */
11
12 /*
13  * This file handles the architecture-dependent parts of hardware
14  * exceptions
15  */
16
17 #include <common.h>
18 #include <kgdb.h>
19 #include <asm/processor.h>
20
21 DECLARE_GLOBAL_DATA_PTR;
22
23 extern unsigned long search_exception_table(unsigned long);
24
25 /*
26  * End of addressable memory.  This may be less than the actual
27  * amount of memory on the system if we're unable to keep all
28  * the memory mapped in.
29  */
30 #define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
31
32 /*
33  * Trap & Exception support
34  */
35
36 static void print_backtrace(unsigned long *sp)
37 {
38         int cnt = 0;
39         unsigned long i;
40
41         puts("Call backtrace: ");
42         while (sp) {
43                 if ((uint)sp > END_OF_MEM)
44                         break;
45
46                 i = sp[1];
47                 if (cnt++ % 7 == 0)
48                         putc('\n');
49                 printf("%08lX ", i);
50                 if (cnt > 32) break;
51                 sp = (unsigned long *) *sp;
52         }
53         putc('\n');
54 }
55
56 void show_regs(struct pt_regs *regs)
57 {
58         int i;
59
60         printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
61                regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
62         printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
63                regs->msr, regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0,
64                regs->msr & MSR_FP ? 1 : 0,regs->msr & MSR_ME ? 1 : 0,
65                regs->msr & MSR_IR ? 1 : 0,
66                regs->msr & MSR_DR ? 1 : 0);
67
68         putc('\n');
69         for (i = 0;  i < 32;  i++) {
70                 if ((i % 8) == 0) {
71                         printf("GPR%02d: ", i);
72                 }
73
74                 printf("%08lX ", regs->gpr[i]);
75                 if ((i % 8) == 7) {
76                         putc('\n');
77                 }
78         }
79 }
80
81
82 static void _exception(int signr, struct pt_regs *regs)
83 {
84         show_regs(regs);
85         print_backtrace((unsigned long *)regs->gpr[1]);
86         panic("Exception at pc %lx signal %d", regs->nip, signr);
87 }
88
89
90 void MachineCheckException(struct pt_regs *regs)
91 {
92         unsigned long fixup = search_exception_table(regs->nip);
93
94         if (fixup) {
95                 regs->nip = fixup;
96                 return;
97         }
98
99 #ifdef CONFIG_CMD_KGDB
100         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
101                 return;
102 #endif
103
104         puts("Machine check.\nCaused by (from msr): ");
105         printf("regs %p ", regs);
106         switch (regs->msr & 0x00FF0000) {
107         case (0x80000000 >> 10):
108                 puts("Instruction cache parity signal\n");
109                 break;
110         case (0x80000000 >> 11):
111                 puts("Data cache parity signal\n");
112                 break;
113         case (0x80000000 >> 12):
114                 puts("Machine check signal\n");
115                 break;
116         case (0x80000000 >> 13):
117                 puts("Transfer error ack signal\n");
118                 break;
119         case (0x80000000 >> 14):
120                 puts("Data parity signal\n");
121                 break;
122         case (0x80000000 >> 15):
123                 puts("Address parity signal\n");
124                 break;
125         default:
126                 puts("Unknown values in msr\n");
127         }
128         show_regs(regs);
129         print_backtrace((unsigned long *)regs->gpr[1]);
130
131         panic("machine check");
132 }
133
134 void AlignmentException(struct pt_regs *regs)
135 {
136 #ifdef CONFIG_CMD_KGDB
137         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
138                 return;
139 #endif
140         show_regs(regs);
141         print_backtrace((unsigned long *)regs->gpr[1]);
142         panic("Alignment Exception");
143 }
144
145 void ProgramCheckException(struct pt_regs *regs)
146 {
147 #ifdef CONFIG_CMD_KGDB
148         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
149                 return;
150 #endif
151         show_regs(regs);
152         print_backtrace((unsigned long *)regs->gpr[1]);
153         panic("Program Check Exception");
154 }
155
156 void SoftEmuException(struct pt_regs *regs)
157 {
158 #ifdef CONFIG_CMD_KGDB
159         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
160                 return;
161 #endif
162         show_regs(regs);
163         print_backtrace((unsigned long *)regs->gpr[1]);
164         panic("Software Emulation Exception");
165 }
166
167
168 void UnknownException(struct pt_regs *regs)
169 {
170 #ifdef CONFIG_CMD_KGDB
171         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
172                 return;
173 #endif
174         printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
175                regs->nip, regs->msr, regs->trap);
176         _exception(0, regs);
177 }
178
179 #ifdef CONFIG_CMD_BEDBUG
180 extern void do_bedbug_breakpoint(struct pt_regs *);
181 #endif
182
183 void DebugException(struct pt_regs *regs)
184 {
185         printf("Debugger trap at @ %lx\n", regs->nip);
186         show_regs(regs);
187 #ifdef CONFIG_CMD_BEDBUG
188         do_bedbug_breakpoint(regs);
189 #endif
190 }