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