Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / powerpc / cpu / mpc83xx / traps.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2000
4  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5  *
6  * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
7  */
8
9 /*
10  * This file handles the architecture-dependent parts of hardware
11  * exceptions
12  */
13
14 #include <common.h>
15 #include <asm/ptrace.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 }