blob: 46006ece41606525f882c54eeddbe556adc4dd3f [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Jon Loeligerdebb7352006-04-26 17:58:56 -05002/*
Jon Loeligerdebb7352006-04-26 17:58:56 -05003 * 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.
Jon Loeligerdebb7352006-04-26 17:58:56 -050010 */
11
12/*
13 * This file handles the architecture-dependent parts of hardware exceptions
14 */
15
16#include <common.h>
Simon Glass401d1c42020-10-30 21:38:53 -060017#include <asm/global_data.h>
Simon Glass25a58182020-05-10 11:40:06 -060018#include <asm/ptrace.h>
Jon Loeligerdebb7352006-04-26 17:58:56 -050019#include <command.h>
Simon Glass9b4a2052019-12-28 10:45:05 -070020#include <init.h>
Mike Frysingere39bf1e2010-02-08 15:30:16 -050021#include <kgdb.h>
Jon Loeligerdebb7352006-04-26 17:58:56 -050022#include <asm/processor.h>
23
Wolfgang Denk1218abf2007-09-15 20:48:41 +020024DECLARE_GLOBAL_DATA_PTR;
25
Jon Loeligerdebb7352006-04-26 17:58:56 -050026/* Returns 0 if exception not found and fixup otherwise. */
27extern unsigned long search_exception_table(unsigned long);
28
Becky Bruce279726b2008-05-14 13:09:58 -050029/*
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 */
Stefan Roesee207f222020-08-12 13:16:36 +020034#define END_OF_MEM (gd->ram_base + get_effective_memsize())
Jon Loeligerdebb7352006-04-26 17:58:56 -050035
36/*
37 * Trap & Exception support
38 */
39
Kim Phillips20051f22012-10-29 13:34:29 +000040static void print_backtrace(unsigned long *sp)
Jon Loeligerdebb7352006-04-26 17:58:56 -050041{
Jon Loeligerdebb7352006-04-26 17:58:56 -050042 int cnt = 0;
43 unsigned long i;
44
45 printf("Call backtrace: ");
46 while (sp) {
Jon Loeligerffff3ae2006-08-22 12:06:18 -050047 if ((uint) sp > END_OF_MEM)
Jon Loeligerdebb7352006-04-26 17:58:56 -050048 break;
49
50 i = sp[1];
51 if (cnt++ % 7 == 0)
52 printf("\n");
53 printf("%08lX ", i);
Jon Loeligerffff3ae2006-08-22 12:06:18 -050054 if (cnt > 32)
55 break;
Jon Loeligerdebb7352006-04-26 17:58:56 -050056 sp = (unsigned long *)*sp;
57 }
58 printf("\n");
59}
60
Kim Phillips20051f22012-10-29 13:34:29 +000061void show_regs(struct pt_regs *regs)
Jon Loeligerdebb7352006-04-26 17:58:56 -050062{
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",
Jon Loeligerffff3ae2006-08-22 12:06:18 -050070 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);
Jon Loeligerdebb7352006-04-26 17:58:56 -050074
75 printf("\n");
Jon Loeligerffff3ae2006-08-22 12:06:18 -050076 for (i = 0; i < 32; i++) {
77 if ((i % 8) == 0) {
Jon Loeligerdebb7352006-04-26 17:58:56 -050078 printf("GPR%02d: ", i);
79 }
80
81 printf("%08lX ", regs->gpr[i]);
Jon Loeligerffff3ae2006-08-22 12:06:18 -050082 if ((i % 8) == 7) {
Jon Loeligerdebb7352006-04-26 17:58:56 -050083 printf("\n");
84 }
85 }
86}
87
88
Kim Phillips20051f22012-10-29 13:34:29 +000089static void _exception(int signr, struct pt_regs *regs)
Jon Loeligerdebb7352006-04-26 17:58:56 -050090{
91 show_regs(regs);
92 print_backtrace((unsigned long *)regs->gpr[1]);
Jon Loeligerffff3ae2006-08-22 12:06:18 -050093 panic("Exception in kernel pc %lx signal %d", regs->nip, signr);
Jon Loeligerdebb7352006-04-26 17:58:56 -050094}
95
Kim Phillips20051f22012-10-29 13:34:29 +000096void MachineCheckException(struct pt_regs *regs)
Jon Loeligerdebb7352006-04-26 17:58:56 -050097{
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
Jon Loeligerb24629f2007-06-13 13:23:15 -0500109#if defined(CONFIG_CMD_KGDB)
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500110 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
Jon Loeligerdebb7352006-04-26 17:58:56 -0500111 return;
112#endif
113
114 printf("Machine check in kernel mode.\n");
115 printf("Caused by (from msr): ");
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500116 printf("regs %p ", regs);
Jon Loeligercfc7a7f2007-08-02 14:42:20 -0500117 switch ( regs->msr & 0x001F0000) {
118 case (0x80000000>>11):
119 printf("MSS error. MSSSR0: %08x\n", mfspr(SPRN_MSSSR0));
120 break;
121 case (0x80000000>>12):
Jon Loeligerdebb7352006-04-26 17:58:56 -0500122 printf("Machine check signal - probably due to mm fault\n"
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500123 "with mmu off\n");
Jon Loeligerdebb7352006-04-26 17:58:56 -0500124 break;
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500125 case (0x80000000 >> 13):
Jon Loeligerdebb7352006-04-26 17:58:56 -0500126 printf("Transfer error ack signal\n");
127 break;
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500128 case (0x80000000 >> 14):
Jon Loeligerdebb7352006-04-26 17:58:56 -0500129 printf("Data parity signal\n");
130 break;
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500131 case (0x80000000 >> 15):
Jon Loeligerdebb7352006-04-26 17:58:56 -0500132 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
Kim Phillips20051f22012-10-29 13:34:29 +0000142void AlignmentException(struct pt_regs *regs)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500143{
Jon Loeligerb24629f2007-06-13 13:23:15 -0500144#if defined(CONFIG_CMD_KGDB)
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500145 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
Jon Loeligerdebb7352006-04-26 17:58:56 -0500146 return;
147#endif
148 show_regs(regs);
149 print_backtrace((unsigned long *)regs->gpr[1]);
150 panic("Alignment Exception");
151}
152
Kim Phillips20051f22012-10-29 13:34:29 +0000153void ProgramCheckException(struct pt_regs *regs)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500154{
155 unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
156 int i, j;
157
Jon Loeligerb24629f2007-06-13 13:23:15 -0500158#if defined(CONFIG_CMD_KGDB)
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500159 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
Jon Loeligerdebb7352006-04-26 17:58:56 -0500160 return;
161#endif
162 show_regs(regs);
163
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500164 p = (unsigned char *)((unsigned long)p & 0xFFFFFFE0);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500165 p -= 32;
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500166 for (i = 0; i < 256; i += 16) {
167 printf("%08x: ", (unsigned int)p + i);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500168 for (j = 0; j < 16; j++) {
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500169 printf("%02x ", p[i + j]);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500170 }
171 printf("\n");
172 }
173
174 print_backtrace((unsigned long *)regs->gpr[1]);
175 panic("Program Check Exception");
176}
177
Kim Phillips20051f22012-10-29 13:34:29 +0000178void SoftEmuException(struct pt_regs *regs)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500179{
Jon Loeligerb24629f2007-06-13 13:23:15 -0500180#if defined(CONFIG_CMD_KGDB)
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500181 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
Jon Loeligerdebb7352006-04-26 17:58:56 -0500182 return;
183#endif
184 show_regs(regs);
185 print_backtrace((unsigned long *)regs->gpr[1]);
186 panic("Software Emulation Exception");
187}
188
Kim Phillips20051f22012-10-29 13:34:29 +0000189void UnknownException(struct pt_regs *regs)
Jon Loeligerdebb7352006-04-26 17:58:56 -0500190{
Jon Loeligerb24629f2007-06-13 13:23:15 -0500191#if defined(CONFIG_CMD_KGDB)
Jon Loeligerffff3ae2006-08-22 12:06:18 -0500192 if (debugger_exception_handler && (*debugger_exception_handler) (regs))
Jon Loeligerdebb7352006-04-26 17:58:56 -0500193 return;
194#endif
Wolfgang Denk9b55a252008-07-11 01:16:00 +0200195 printf("UnknownException regs@%lx\n", (ulong)regs);
Jon Loeligerdebb7352006-04-26 17:58:56 -0500196 printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
197 regs->nip, regs->msr, regs->trap);
198 _exception(0, regs);
199}