blob: 9f5bcd7fc3350a5fa9b1b44496b9cac0e921872e [file] [log] [blame]
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +02001/*
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 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +02008 *
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>
Mike Frysinger629d88b2010-02-08 15:30:16 -050018#include <kgdb.h>
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020019#include <asm/processor.h>
20
21DECLARE_GLOBAL_DATA_PTR;
22
23extern unsigned long search_exception_table(unsigned long);
24
Becky Brucef095f5f2008-05-14 13:09:51 -050025/*
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 */
Becky Brucef095f5f2008-05-14 13:09:51 -050030#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020031
32/*
33 * Trap & Exception support
34 */
35
Kim Phillipse16737f2012-10-29 13:34:29 +000036static void print_backtrace(unsigned long *sp)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020037{
38 int cnt = 0;
39 unsigned long i;
40
Kim Phillipse16737f2012-10-29 13:34:29 +000041 puts("Call backtrace: ");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020042 while (sp) {
43 if ((uint)sp > END_OF_MEM)
44 break;
45
46 i = sp[1];
47 if (cnt++ % 7 == 0)
Kim Phillipse16737f2012-10-29 13:34:29 +000048 putc('\n');
49 printf("%08lX ", i);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020050 if (cnt > 32) break;
51 sp = (unsigned long *) *sp;
52 }
Kim Phillipse16737f2012-10-29 13:34:29 +000053 putc('\n');
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020054}
55
Kim Phillipse16737f2012-10-29 13:34:29 +000056void show_regs(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020057{
58 int i;
59
Kim Phillipse16737f2012-10-29 13:34:29 +000060 printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020061 regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
Kim Phillipse16737f2012-10-29 13:34:29 +000062 printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020063 regs->msr, regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0,
64 regs->msr & MSR_FP ? 1 : 0,regs->msr & MSR_ME ? 1 : 0,
65 regs->msr & MSR_IR ? 1 : 0,
66 regs->msr & MSR_DR ? 1 : 0);
67
Kim Phillipse16737f2012-10-29 13:34:29 +000068 putc('\n');
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020069 for (i = 0; i < 32; i++) {
70 if ((i % 8) == 0) {
Kim Phillipse16737f2012-10-29 13:34:29 +000071 printf("GPR%02d: ", i);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020072 }
73
Kim Phillipse16737f2012-10-29 13:34:29 +000074 printf("%08lX ", regs->gpr[i]);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020075 if ((i % 8) == 7) {
Kim Phillipse16737f2012-10-29 13:34:29 +000076 putc('\n');
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020077 }
78 }
79}
80
81
Kim Phillipse16737f2012-10-29 13:34:29 +000082static void _exception(int signr, struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020083{
Kim Phillipse16737f2012-10-29 13:34:29 +000084 show_regs(regs);
85 print_backtrace((unsigned long *)regs->gpr[1]);
86 panic("Exception at pc %lx signal %d", regs->nip, signr);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020087}
88
89
Kim Phillipse16737f2012-10-29 13:34:29 +000090void MachineCheckException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020091{
Kim Phillipse16737f2012-10-29 13:34:29 +000092 unsigned long fixup = search_exception_table(regs->nip);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020093
Kim Phillipse16737f2012-10-29 13:34:29 +000094 if (fixup) {
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +020095 regs->nip = fixup;
96 return;
97 }
98
Wolfgang Denk56cbd022007-08-12 14:27:39 +020099#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200100 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
101 return;
102#endif
103
Kim Phillipse16737f2012-10-29 13:34:29 +0000104 puts("Machine check.\nCaused by (from msr): ");
105 printf("regs %p ", regs);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200106 switch (regs->msr & 0x00FF0000) {
107 case (0x80000000 >> 10):
Kim Phillipse16737f2012-10-29 13:34:29 +0000108 puts("Instruction cache parity signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200109 break;
110 case (0x80000000 >> 11):
Kim Phillipse16737f2012-10-29 13:34:29 +0000111 puts("Data cache parity signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200112 break;
113 case (0x80000000 >> 12):
Kim Phillipse16737f2012-10-29 13:34:29 +0000114 puts("Machine check signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200115 break;
116 case (0x80000000 >> 13):
Kim Phillipse16737f2012-10-29 13:34:29 +0000117 puts("Transfer error ack signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200118 break;
119 case (0x80000000 >> 14):
Kim Phillipse16737f2012-10-29 13:34:29 +0000120 puts("Data parity signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200121 break;
122 case (0x80000000 >> 15):
Kim Phillipse16737f2012-10-29 13:34:29 +0000123 puts("Address parity signal\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200124 break;
125 default:
Kim Phillipse16737f2012-10-29 13:34:29 +0000126 puts("Unknown values in msr\n");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200127 }
Kim Phillipse16737f2012-10-29 13:34:29 +0000128 show_regs(regs);
129 print_backtrace((unsigned long *)regs->gpr[1]);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200130
Kim Phillipse16737f2012-10-29 13:34:29 +0000131 panic("machine check");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200132}
133
Kim Phillipse16737f2012-10-29 13:34:29 +0000134void AlignmentException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200135{
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200136#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200137 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
138 return;
139#endif
Kim Phillipse16737f2012-10-29 13:34:29 +0000140 show_regs(regs);
141 print_backtrace((unsigned long *)regs->gpr[1]);
142 panic("Alignment Exception");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200143}
144
Kim Phillipse16737f2012-10-29 13:34:29 +0000145void ProgramCheckException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200146{
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200147#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200148 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
149 return;
150#endif
Kim Phillipse16737f2012-10-29 13:34:29 +0000151 show_regs(regs);
152 print_backtrace((unsigned long *)regs->gpr[1]);
153 panic("Program Check Exception");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200154}
155
Kim Phillipse16737f2012-10-29 13:34:29 +0000156void SoftEmuException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200157{
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200158#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200159 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
160 return;
161#endif
Kim Phillipse16737f2012-10-29 13:34:29 +0000162 show_regs(regs);
163 print_backtrace((unsigned long *)regs->gpr[1]);
164 panic("Software Emulation Exception");
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200165}
166
167
Kim Phillipse16737f2012-10-29 13:34:29 +0000168void UnknownException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200169{
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200170#ifdef CONFIG_CMD_KGDB
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200171 if (debugger_exception_handler && (*debugger_exception_handler)(regs))
172 return;
173#endif
Kim Phillipse16737f2012-10-29 13:34:29 +0000174 printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200175 regs->nip, regs->msr, regs->trap);
Kim Phillipse16737f2012-10-29 13:34:29 +0000176 _exception(0, regs);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200177}
178
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200179#ifdef CONFIG_CMD_BEDBUG
Kim Phillipse16737f2012-10-29 13:34:29 +0000180extern void do_bedbug_breakpoint(struct pt_regs *);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200181#endif
182
Kim Phillipse16737f2012-10-29 13:34:29 +0000183void DebugException(struct pt_regs *regs)
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200184{
Kim Phillipse16737f2012-10-29 13:34:29 +0000185 printf("Debugger trap at @ %lx\n", regs->nip);
186 show_regs(regs);
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200187#ifdef CONFIG_CMD_BEDBUG
Kim Phillipse16737f2012-10-29 13:34:29 +0000188 do_bedbug_breakpoint(regs);
Rafal Jaworowskid3a02c32007-07-27 14:43:59 +0200189#endif
190}