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