]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc8260/traps.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc8260 / 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  *
9  * (C) Copyright 2000
10  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
11  *
12  * SPDX-License-Identifier:     GPL-2.0+
13  */
14
15 /*
16  * This file handles the architecture-dependent parts of hardware exceptions
17  */
18
19 #include <common.h>
20 #include <command.h>
21 #include <kgdb.h>
22 #include <asm/processor.h>
23 #include <asm/m8260_pci.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         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 in kernel pc %lx signal %d",regs->nip,signr);
87 }
88
89 #ifdef CONFIG_PCI
90 void dump_pci (void)
91 {
92
93         volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
94
95         printf ("PCI: err status %x err mask %x err ctrl %x\n",
96                 le32_to_cpu (immap->im_pci.pci_esr),
97                 le32_to_cpu (immap->im_pci.pci_emr),
98                 le32_to_cpu (immap->im_pci.pci_ecr));
99         printf ("     error address %x error data %x ctrl %x\n",
100                 le32_to_cpu (immap->im_pci.pci_eacr),
101                 le32_to_cpu (immap->im_pci.pci_edcr),
102                 le32_to_cpu (immap->im_pci.pci_eccr));
103
104 }
105 #endif
106
107 void MachineCheckException(struct pt_regs *regs)
108 {
109         unsigned long fixup;
110
111         /* Probing PCI using config cycles cause this exception
112          * when a device is not present.  Catch it and return to
113          * the PCI exception handler.
114          */
115 #ifdef CONFIG_PCI
116         volatile immap_t *immap  = (immap_t *)CONFIG_SYS_IMMR;
117 #ifdef DEBUG
118         dump_pci();
119 #endif
120         /* clear the error in the error status register */
121         if(immap->im_pci.pci_esr & cpu_to_le32(PCI_ERROR_PCI_NO_RSP)) {
122                 immap->im_pci.pci_esr = cpu_to_le32(PCI_ERROR_PCI_NO_RSP);
123                 return;
124         }
125 #endif
126         if ((fixup = search_exception_table(regs->nip)) != 0) {
127                 regs->nip = fixup;
128                 return;
129         }
130
131 #if defined(CONFIG_CMD_KGDB)
132         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
133                 return;
134 #endif
135
136         puts ("Machine check in kernel mode.\n"
137                 "Caused by (from msr): ");
138         printf("regs %p ",regs);
139         switch( regs->msr & 0x000F0000) {
140         case (0x80000000>>12):
141                 puts ("Machine check signal - probably due to mm fault\n"
142                         "with mmu off\n");
143                 break;
144         case (0x80000000>>13):
145                 puts ("Transfer error ack signal\n");
146                 break;
147         case (0x80000000>>14):
148                 puts ("Data parity signal\n");
149                 break;
150         case (0x80000000>>15):
151                 puts ("Address parity signal\n");
152                 break;
153         default:
154                 puts ("Unknown values in msr\n");
155         }
156         show_regs(regs);
157         print_backtrace((unsigned long *)regs->gpr[1]);
158 #ifdef CONFIG_PCI
159         dump_pci();
160 #endif
161         panic("machine check");
162 }
163
164 void AlignmentException(struct pt_regs *regs)
165 {
166 #if defined(CONFIG_CMD_KGDB)
167         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
168                 return;
169 #endif
170         show_regs(regs);
171         print_backtrace((unsigned long *)regs->gpr[1]);
172         panic("Alignment Exception");
173 }
174
175 void ProgramCheckException(struct pt_regs *regs)
176 {
177 #if defined(CONFIG_CMD_KGDB)
178         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
179                 return;
180 #endif
181         show_regs(regs);
182         print_backtrace((unsigned long *)regs->gpr[1]);
183         panic("Program Check Exception");
184 }
185
186 void SoftEmuException(struct pt_regs *regs)
187 {
188 #if defined(CONFIG_CMD_KGDB)
189         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
190                 return;
191 #endif
192         show_regs(regs);
193         print_backtrace((unsigned long *)regs->gpr[1]);
194         panic("Software Emulation Exception");
195 }
196
197
198 void UnknownException(struct pt_regs *regs)
199 {
200 #if defined(CONFIG_CMD_KGDB)
201         if (debugger_exception_handler && (*debugger_exception_handler)(regs))
202                 return;
203 #endif
204         printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
205                regs->nip, regs->msr, regs->trap);
206         _exception(0, regs);
207 }
208
209 #if defined(CONFIG_CMD_BEDBUG)
210 extern void do_bedbug_breakpoint(struct pt_regs *);
211 #endif
212
213 void DebugException(struct pt_regs *regs)
214 {
215
216   printf("Debugger trap at @ %lx\n", regs->nip );
217   show_regs(regs);
218 #if defined(CONFIG_CMD_BEDBUG)
219   do_bedbug_breakpoint( regs );
220 #endif
221 }
222
223 /* Probe an address by reading.  If not present, return -1, otherwise
224  * return 0.
225  */
226 int addr_probe(uint *addr)
227 {
228 #if 0
229         int     retval;
230
231         __asm__ __volatile__(                   \
232                 "1:     lwz %0,0(%1)\n"         \
233                 "       eieio\n"                \
234                 "       li %0,0\n"              \
235                 "2:\n"                          \
236                 ".section .fixup,\"ax\"\n"      \
237                 "3:     li %0,-1\n"             \
238                 "       b 2b\n"                 \
239                 ".section __ex_table,\"a\"\n"   \
240                 "       .align 2\n"             \
241                 "       .long 1b,3b\n"          \
242                 ".text"                         \
243                 : "=r" (retval) : "r"(addr));
244
245         return (retval);
246 #endif
247         return 0;
248 }