]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc5xxx/traps.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc5xxx / traps.c
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  * fixed Machine Check Reasons by Reinhard Meyer (r.meyer@emk-elektronik.de)
9  *
10  * (C) Copyright 2000-2003
11  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
12  *
13  * SPDX-License-Identifier:     GPL-2.0+
14  */
15
16 /*
17  * This file handles the architecture-dependent parts of hardware exceptions
18  */
19
20 #include <common.h>
21 #include <command.h>
22 #include <kgdb.h>
23 #include <asm/processor.h>
24
25 /* Returns 0 if exception not found and fixup otherwise.  */
26 extern unsigned long search_exception_table(unsigned long);
27
28 /* THIS NEEDS CHANGING to use the board info structure.
29 */
30 #define END_OF_MEM      0x02000000
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         printf("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                         printf("\n");
49                 printf("%08lX ", i);
50                 if (cnt > 32) break;
51                 sp = (unsigned long *)*sp;
52         }
53         printf("\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         printf("\n");
69         for (i = 0;  i < 32;  i++) {
70                 if ((i % 8) == 0)
71                 {
72                         printf("GPR%02d: ", i);
73                 }
74
75                 printf("%08lX ", regs->gpr[i]);
76                 if ((i % 8) == 7)
77                 {
78                         printf("\n");
79                 }
80         }
81 }
82
83
84 static void _exception(int signr, struct pt_regs *regs)
85 {
86         show_regs(regs);
87         print_backtrace((unsigned long *)regs->gpr[1]);
88         panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
89 }
90
91 void MachineCheckException(struct pt_regs *regs)
92 {
93         unsigned long fixup;
94
95         /* Probing PCI using config cycles cause this exception
96          * when a device is not present.  Catch it and return to
97          * the PCI exception handler.
98          */
99         if ((fixup = search_exception_table(regs->nip)) != 0) {
100                 regs->nip = fixup;
101                 return;
102         }
103
104 #if defined(CONFIG_CMD_KGDB)
105         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
106                 return;
107 #endif
108
109         printf("Machine check in kernel mode.\n");
110         printf("Caused by (from msr): ");
111         printf("regs %p ",regs);
112         /* refer to 603e Manual (MPC603EUM/AD), chapter 4.5.2.1 */
113         switch( regs->msr & 0x000F0000)
114         {
115         case (0x80000000>>12) :
116                 printf("Machine check signal - probably due to mm fault\n"
117                         "with mmu off\n");
118                 break;
119         case (0x80000000>>13) :
120                 printf("Transfer error ack signal\n");
121                 break;
122         case (0x80000000>>14) :
123                 printf("Data parity signal\n");
124                 break;
125         case (0x80000000>>15) :
126                 printf("Address parity signal\n");
127                 break;
128         default:
129                 printf("Unknown values in msr\n");
130         }
131         show_regs(regs);
132         print_backtrace((unsigned long *)regs->gpr[1]);
133         panic("machine check");
134 }
135
136 void AlignmentException(struct pt_regs *regs)
137 {
138 #if defined(CONFIG_CMD_KGDB)
139         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
140                 return;
141 #endif
142         show_regs(regs);
143         print_backtrace((unsigned long *)regs->gpr[1]);
144         panic("Alignment Exception");
145 }
146
147 void ProgramCheckException(struct pt_regs *regs)
148 {
149 #if defined(CONFIG_CMD_KGDB)
150         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
151                 return;
152 #endif
153         show_regs(regs);
154         print_backtrace((unsigned long *)regs->gpr[1]);
155         panic("Program Check Exception");
156 }
157
158 void SoftEmuException(struct pt_regs *regs)
159 {
160 #if defined(CONFIG_CMD_KGDB)
161         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
162                 return;
163 #endif
164         show_regs(regs);
165         print_backtrace((unsigned long *)regs->gpr[1]);
166         panic("Software Emulation Exception");
167 }
168
169
170 void UnknownException(struct pt_regs *regs)
171 {
172 #if defined(CONFIG_CMD_KGDB)
173         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
174                 return;
175 #endif
176         printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
177                regs->nip, regs->msr, regs->trap);
178         _exception(0, regs);
179 }
180
181 #if defined(CONFIG_CMD_BEDBUG)
182 extern void do_bedbug_breakpoint(struct pt_regs *);
183 #endif
184
185 void DebugException(struct pt_regs *regs)
186 {
187
188   printf("Debugger trap at @ %lx\n", regs->nip );
189   show_regs(regs);
190 #if defined(CONFIG_CMD_BEDBUG)
191   do_bedbug_breakpoint( regs );
192 #endif
193 }
194
195 /* Probe an address by reading.  If not present, return -1, otherwise
196  * return 0.
197  */
198 int addr_probe(uint *addr)
199 {
200 #if 0
201         int     retval;
202
203         __asm__ __volatile__(                   \
204                 "1:     lwz %0,0(%1)\n"         \
205                 "       eieio\n"                \
206                 "       li %0,0\n"              \
207                 "2:\n"                          \
208                 ".section .fixup,\"ax\"\n"      \
209                 "3:     li %0,-1\n"             \
210                 "       b 2b\n"                 \
211                 ".section __ex_table,\"a\"\n"   \
212                 "       .align 2\n"             \
213                 "       .long 1b,3b\n"          \
214                 ".text"                         \
215                 : "=r" (retval) : "r"(addr));
216
217         return (retval);
218 #endif
219         return 0;
220 }