]>
Commit | Line | Data |
---|---|---|
8993e54b RJ |
1 | /* |
2 | * (C) Copyright 2000 - 2007 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | |
6 | * | |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
8993e54b RJ |
8 | * |
9 | * Derived from the MPC83xx code. | |
10 | */ | |
11 | ||
12 | /* | |
13 | * This file handles the architecture-dependent parts of hardware | |
14 | * exceptions | |
15 | */ | |
16 | ||
17 | #include <common.h> | |
e39bf1e2 | 18 | #include <kgdb.h> |
8993e54b RJ |
19 | #include <asm/processor.h> |
20 | ||
21 | DECLARE_GLOBAL_DATA_PTR; | |
22 | ||
23 | extern unsigned long search_exception_table(unsigned long); | |
24 | ||
9b124a68 BB |
25 | /* |
26 | * End of addressable memory. This may be less than the actual | |
27 | * amount of memory on the system if we're unable to keep all | |
28 | * the memory mapped in. | |
29 | */ | |
30 | extern ulong get_effective_memsize(void); | |
31 | #define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize()) | |
8993e54b RJ |
32 | |
33 | /* | |
34 | * Trap & Exception support | |
35 | */ | |
36 | ||
20051f2a | 37 | static void print_backtrace(unsigned long *sp) |
8993e54b RJ |
38 | { |
39 | int cnt = 0; | |
40 | unsigned long i; | |
41 | ||
20051f2a | 42 | puts("Call backtrace: "); |
8993e54b RJ |
43 | while (sp) { |
44 | if ((uint)sp > END_OF_MEM) | |
45 | break; | |
46 | ||
47 | i = sp[1]; | |
48 | if (cnt++ % 7 == 0) | |
20051f2a KP |
49 | putc('\n'); |
50 | printf("%08lX ", i); | |
8993e54b RJ |
51 | if (cnt > 32) break; |
52 | sp = (unsigned long *) *sp; | |
53 | } | |
20051f2a | 54 | putc('\n'); |
8993e54b RJ |
55 | } |
56 | ||
20051f2a | 57 | void show_regs(struct pt_regs *regs) |
8993e54b RJ |
58 | { |
59 | int i; | |
60 | ||
20051f2a | 61 | printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n", |
8993e54b | 62 | regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); |
20051f2a | 63 | printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", |
8993e54b RJ |
64 | regs->msr, regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0, |
65 | regs->msr & MSR_FP ? 1 : 0,regs->msr & MSR_ME ? 1 : 0, | |
66 | regs->msr & MSR_IR ? 1 : 0, | |
67 | regs->msr & MSR_DR ? 1 : 0); | |
68 | ||
20051f2a | 69 | putc('\n'); |
8993e54b RJ |
70 | for (i = 0; i < 32; i++) { |
71 | if ((i % 8) == 0) { | |
20051f2a | 72 | printf("GPR%02d: ", i); |
8993e54b RJ |
73 | } |
74 | ||
20051f2a | 75 | printf("%08lX ", regs->gpr[i]); |
8993e54b | 76 | if ((i % 8) == 7) { |
20051f2a | 77 | putc('\n'); |
8993e54b RJ |
78 | } |
79 | } | |
80 | } | |
81 | ||
82 | ||
20051f2a | 83 | static void _exception(int signr, struct pt_regs *regs) |
8993e54b | 84 | { |
20051f2a KP |
85 | show_regs(regs); |
86 | print_backtrace((unsigned long *)regs->gpr[1]); | |
87 | panic("Exception at pc %lx signal %d", regs->nip, signr); | |
8993e54b RJ |
88 | } |
89 | ||
90 | ||
20051f2a | 91 | void MachineCheckException(struct pt_regs *regs) |
8993e54b | 92 | { |
20051f2a | 93 | unsigned long fixup = search_exception_table(regs->nip); |
8993e54b | 94 | |
20051f2a | 95 | if (fixup) { |
8993e54b RJ |
96 | regs->nip = fixup; |
97 | return; | |
98 | } | |
99 | ||
afaac86f | 100 | #ifdef CONFIG_CMD_KGDB |
8993e54b RJ |
101 | if (debugger_exception_handler && (*debugger_exception_handler)(regs)) |
102 | return; | |
103 | #endif | |
104 | ||
20051f2a KP |
105 | puts("Machine check.\nCaused by (from msr): "); |
106 | printf("regs %p ", regs); | |
8993e54b RJ |
107 | switch (regs->msr & 0x00FF0000) { |
108 | case (0x80000000 >> 10): | |
20051f2a | 109 | puts("Instruction cache parity signal\n"); |
8993e54b RJ |
110 | break; |
111 | case (0x80000000 >> 11): | |
20051f2a | 112 | puts("Data cache parity signal\n"); |
8993e54b RJ |
113 | break; |
114 | case (0x80000000 >> 12): | |
20051f2a | 115 | puts("Machine check signal\n"); |
8993e54b RJ |
116 | break; |
117 | case (0x80000000 >> 13): | |
20051f2a | 118 | puts("Transfer error ack signal\n"); |
8993e54b RJ |
119 | break; |
120 | case (0x80000000 >> 14): | |
20051f2a | 121 | puts("Data parity signal\n"); |
8993e54b RJ |
122 | break; |
123 | case (0x80000000 >> 15): | |
20051f2a | 124 | puts("Address parity signal\n"); |
8993e54b RJ |
125 | break; |
126 | default: | |
20051f2a | 127 | puts("Unknown values in msr\n"); |
8993e54b | 128 | } |
20051f2a KP |
129 | show_regs(regs); |
130 | print_backtrace((unsigned long *)regs->gpr[1]); | |
8993e54b | 131 | |
20051f2a | 132 | panic("machine check"); |
8993e54b RJ |
133 | } |
134 | ||
20051f2a | 135 | void AlignmentException(struct pt_regs *regs) |
8993e54b | 136 | { |
afaac86f | 137 | #ifdef CONFIG_CMD_KGDB |
8993e54b RJ |
138 | if (debugger_exception_handler && (*debugger_exception_handler)(regs)) |
139 | return; | |
140 | #endif | |
20051f2a KP |
141 | show_regs(regs); |
142 | print_backtrace((unsigned long *)regs->gpr[1]); | |
143 | panic("Alignment Exception"); | |
8993e54b RJ |
144 | } |
145 | ||
20051f2a | 146 | void ProgramCheckException(struct pt_regs *regs) |
8993e54b | 147 | { |
afaac86f | 148 | #ifdef CONFIG_CMD_KGDB |
8993e54b RJ |
149 | if (debugger_exception_handler && (*debugger_exception_handler)(regs)) |
150 | return; | |
151 | #endif | |
20051f2a KP |
152 | show_regs(regs); |
153 | print_backtrace((unsigned long *)regs->gpr[1]); | |
154 | panic("Program Check Exception"); | |
8993e54b RJ |
155 | } |
156 | ||
20051f2a | 157 | void SoftEmuException(struct pt_regs *regs) |
8993e54b | 158 | { |
afaac86f | 159 | #ifdef CONFIG_CMD_KGDB |
8993e54b RJ |
160 | if (debugger_exception_handler && (*debugger_exception_handler)(regs)) |
161 | return; | |
162 | #endif | |
20051f2a KP |
163 | show_regs(regs); |
164 | print_backtrace((unsigned long *)regs->gpr[1]); | |
165 | panic("Software Emulation Exception"); | |
8993e54b RJ |
166 | } |
167 | ||
168 | ||
20051f2a | 169 | void UnknownException(struct pt_regs *regs) |
8993e54b | 170 | { |
afaac86f | 171 | #ifdef CONFIG_CMD_KGDB |
8993e54b RJ |
172 | if (debugger_exception_handler && (*debugger_exception_handler)(regs)) |
173 | return; | |
174 | #endif | |
20051f2a | 175 | printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", |
8993e54b | 176 | regs->nip, regs->msr, regs->trap); |
20051f2a | 177 | _exception(0, regs); |
8993e54b RJ |
178 | } |
179 | ||
afaac86f | 180 | #ifdef CONFIG_CMD_BEDBUG |
20051f2a | 181 | extern void do_bedbug_breakpoint(struct pt_regs *); |
8993e54b RJ |
182 | #endif |
183 | ||
20051f2a | 184 | void DebugException(struct pt_regs *regs) |
8993e54b | 185 | { |
20051f2a KP |
186 | printf("Debugger trap at @ %lx\n", regs->nip); |
187 | show_regs(regs); | |
afaac86f | 188 | #ifdef CONFIG_CMD_BEDBUG |
20051f2a | 189 | do_bedbug_breakpoint(regs); |
8993e54b RJ |
190 | #endif |
191 | } |