1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4 *
5 * Modified by Cort Dougan (cort@cs.nmt.edu)
6 * and Paul Mackerras (paulus@cs.anu.edu.au)
7 *
8 * (C) Copyright 2000
9 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
10 */
11
12 /*
13 * This file handles the architecture-dependent parts of hardware exceptions
14 */
15
16 #include <common.h>
17 #include <asm/global_data.h>
18 #include <asm/ptrace.h>
19 #include <command.h>
20 #include <init.h>
21 #include <kgdb.h>
22 #include <asm/processor.h>
23
24 DECLARE_GLOBAL_DATA_PTR;
25
26 /* Returns 0 if exception not found and fixup otherwise. */
27 extern unsigned long search_exception_table(unsigned long);
28
29 /*
30 * End of addressable memory. This may be less than the actual
31 * amount of memory on the system if we're unable to keep all
32 * the memory mapped in.
33 */
34 #define END_OF_MEM (gd->ram_base + get_effective_memsize())
35
36 /*
37 * Trap & Exception support
38 */
39
print_backtrace(unsigned long * sp)40 static void print_backtrace(unsigned long *sp)
41 {
42 int cnt = 0;
43 unsigned long i;
44
45 printf("Call backtrace: ");
46 while (sp) {
47 if ((uint) sp > END_OF_MEM)
48 break;
49
50 i = sp[1];
51 if (cnt++ % 7 == 0)
52 printf("\n");
53 printf("%08lX ", i);
54 if (cnt > 32)
55 break;
56 sp = (unsigned long *)*sp;
57 }
58 printf("\n");
59 }
60
show_regs(struct pt_regs * regs)61 void show_regs(struct pt_regs *regs)
62 {
63 int i;
64
65 printf("NIP: %08lX XER: %08lX LR: %08lX REGS:"
66 " %p TRAP: %04lx DAR: %08lX\n",
67 regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
68 printf("MSR: %08lx EE: %01x PR: %01x FP:"
69 " %01x ME: %01x IR/DR: %01x%01x\n",
70 regs->msr, regs->msr & MSR_EE ? 1 : 0,
71 regs->msr & MSR_PR ? 1 : 0, regs->msr & MSR_FP ? 1 : 0,
72 regs->msr & MSR_ME ? 1 : 0, regs->msr & MSR_IR ? 1 : 0,
73 regs->msr & MSR_DR ? 1 : 0);
74
75 printf("\n");
76 for (i = 0; i < 32; i++) {
77 if ((i % 8) == 0) {
78 printf("GPR%02d: ", i);
79 }
80
81 printf("%08lX ", regs->gpr[i]);
82 if ((i % 8) == 7) {
83 printf("\n");
84 }
85 }
86 }
87
88
_exception(int signr,struct pt_regs * regs)89 static void _exception(int signr, struct pt_regs *regs)
90 {
91 show_regs(regs);
92 print_backtrace((unsigned long *)regs->gpr[1]);
93 panic("Exception in kernel pc %lx signal %d", regs->nip, signr);
94 }
95
MachineCheckException(struct pt_regs * regs)96 void MachineCheckException(struct pt_regs *regs)
97 {
98 unsigned long fixup;
99
100 /* Probing PCI using config cycles cause this exception
101 * when a device is not present. Catch it and return to
102 * the PCI exception handler.
103 */
104 if ((fixup = search_exception_table(regs->nip)) != 0) {
105 regs->nip = fixup;
106 return;
107 }
108
109 #if defined(CONFIG_CMD_KGDB)
110 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
111 return;
112 #endif
113
114 printf("Machine check in kernel mode.\n");
115 printf("Caused by (from msr): ");
116 printf("regs %p ", regs);
117 switch ( regs->msr & 0x001F0000) {
118 case (0x80000000>>11):
119 printf("MSS error. MSSSR0: %08x\n", mfspr(SPRN_MSSSR0));
120 break;
121 case (0x80000000>>12):
122 printf("Machine check signal - probably due to mm fault\n"
123 "with mmu off\n");
124 break;
125 case (0x80000000 >> 13):
126 printf("Transfer error ack signal\n");
127 break;
128 case (0x80000000 >> 14):
129 printf("Data parity signal\n");
130 break;
131 case (0x80000000 >> 15):
132 printf("Address parity signal\n");
133 break;
134 default:
135 printf("Unknown values in msr\n");
136 }
137 show_regs(regs);
138 print_backtrace((unsigned long *)regs->gpr[1]);
139 panic("machine check");
140 }
141
AlignmentException(struct pt_regs * regs)142 void AlignmentException(struct pt_regs *regs)
143 {
144 #if defined(CONFIG_CMD_KGDB)
145 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
146 return;
147 #endif
148 show_regs(regs);
149 print_backtrace((unsigned long *)regs->gpr[1]);
150 panic("Alignment Exception");
151 }
152
ProgramCheckException(struct pt_regs * regs)153 void ProgramCheckException(struct pt_regs *regs)
154 {
155 unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
156 int i, j;
157
158 #if defined(CONFIG_CMD_KGDB)
159 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
160 return;
161 #endif
162 show_regs(regs);
163
164 p = (unsigned char *)((unsigned long)p & 0xFFFFFFE0);
165 p -= 32;
166 for (i = 0; i < 256; i += 16) {
167 printf("%08x: ", (unsigned int)p + i);
168 for (j = 0; j < 16; j++) {
169 printf("%02x ", p[i + j]);
170 }
171 printf("\n");
172 }
173
174 print_backtrace((unsigned long *)regs->gpr[1]);
175 panic("Program Check Exception");
176 }
177
SoftEmuException(struct pt_regs * regs)178 void SoftEmuException(struct pt_regs *regs)
179 {
180 #if defined(CONFIG_CMD_KGDB)
181 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
182 return;
183 #endif
184 show_regs(regs);
185 print_backtrace((unsigned long *)regs->gpr[1]);
186 panic("Software Emulation Exception");
187 }
188
UnknownException(struct pt_regs * regs)189 void UnknownException(struct pt_regs *regs)
190 {
191 #if defined(CONFIG_CMD_KGDB)
192 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
193 return;
194 #endif
195 printf("UnknownException regs@%lx\n", (ulong)regs);
196 printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
197 regs->nip, regs->msr, regs->trap);
198 _exception(0, regs);
199 }
200