xref: /openbmc/u-boot/arch/powerpc/cpu/mpc83xx/traps.c (revision 552a848e)
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 }
245