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