1907208c4SChristophe Leroy /* 2907208c4SChristophe Leroy * linux/arch/powerpc/kernel/traps.c 3907208c4SChristophe Leroy * 4907208c4SChristophe Leroy * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 5907208c4SChristophe Leroy * 6907208c4SChristophe Leroy * Modified by Cort Dougan (cort@cs.nmt.edu) 7907208c4SChristophe Leroy * and Paul Mackerras (paulus@cs.anu.edu.au) 8907208c4SChristophe Leroy * 9907208c4SChristophe Leroy * (C) Copyright 2000 10907208c4SChristophe Leroy * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 11907208c4SChristophe Leroy * 12907208c4SChristophe Leroy * SPDX-License-Identifier: GPL-2.0+ 13907208c4SChristophe Leroy */ 14907208c4SChristophe Leroy 15907208c4SChristophe Leroy /* 16907208c4SChristophe Leroy * This file handles the architecture-dependent parts of hardware exceptions 17907208c4SChristophe Leroy */ 18907208c4SChristophe Leroy 19907208c4SChristophe Leroy #include <common.h> 20907208c4SChristophe Leroy #include <command.h> 21907208c4SChristophe Leroy #include <asm/processor.h> 22907208c4SChristophe Leroy 23907208c4SChristophe Leroy /* Returns 0 if exception not found and fixup otherwise. */ 24907208c4SChristophe Leroy extern unsigned long search_exception_table(unsigned long); 25907208c4SChristophe Leroy 26907208c4SChristophe Leroy /* THIS NEEDS CHANGING to use the board info structure. 27907208c4SChristophe Leroy */ 28907208c4SChristophe Leroy #define END_OF_MEM 0x02000000 29907208c4SChristophe Leroy 30907208c4SChristophe Leroy /* 31907208c4SChristophe Leroy * Trap & Exception support 32907208c4SChristophe Leroy */ 33907208c4SChristophe Leroy 34907208c4SChristophe Leroy static void print_backtrace(unsigned long *sp) 35907208c4SChristophe Leroy { 36907208c4SChristophe Leroy int cnt = 0; 37907208c4SChristophe Leroy unsigned long i; 38907208c4SChristophe Leroy 39907208c4SChristophe Leroy printf("Call backtrace: "); 40907208c4SChristophe Leroy while (sp) { 41907208c4SChristophe Leroy if ((uint)sp > END_OF_MEM) 42907208c4SChristophe Leroy break; 43907208c4SChristophe Leroy 44907208c4SChristophe Leroy i = sp[1]; 45907208c4SChristophe Leroy if (cnt++ % 7 == 0) 46907208c4SChristophe Leroy printf("\n"); 47907208c4SChristophe Leroy printf("%08lX ", i); 48*70fd0710SChristophe Leroy if (cnt > 32) 49*70fd0710SChristophe Leroy break; 50907208c4SChristophe Leroy sp = (unsigned long *)*sp; 51907208c4SChristophe Leroy } 52907208c4SChristophe Leroy printf("\n"); 53907208c4SChristophe Leroy } 54907208c4SChristophe Leroy 55907208c4SChristophe Leroy void show_regs(struct pt_regs *regs) 56907208c4SChristophe Leroy { 57907208c4SChristophe Leroy int i; 58907208c4SChristophe Leroy 59907208c4SChristophe Leroy printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n", 60907208c4SChristophe Leroy regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); 61907208c4SChristophe Leroy printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", 62*70fd0710SChristophe Leroy regs->msr, regs->msr & MSR_EE ? 1 : 0, 63*70fd0710SChristophe Leroy regs->msr & MSR_PR ? 1 : 0, regs->msr & MSR_FP ? 1 : 0, 64*70fd0710SChristophe Leroy regs->msr & MSR_ME ? 1 : 0, regs->msr & MSR_IR ? 1 : 0, 65907208c4SChristophe Leroy regs->msr & MSR_DR ? 1 : 0); 66907208c4SChristophe Leroy 67907208c4SChristophe Leroy printf("\n"); 68907208c4SChristophe Leroy for (i = 0; i < 32; i++) { 69907208c4SChristophe Leroy if ((i % 8) == 0) 70907208c4SChristophe Leroy printf("GPR%02d: ", i); 71907208c4SChristophe Leroy 72907208c4SChristophe Leroy printf("%08lX ", regs->gpr[i]); 73907208c4SChristophe Leroy if ((i % 8) == 7) 74907208c4SChristophe Leroy printf("\n"); 75907208c4SChristophe Leroy } 76907208c4SChristophe Leroy } 77907208c4SChristophe Leroy 78907208c4SChristophe Leroy 79907208c4SChristophe Leroy static void _exception(int signr, struct pt_regs *regs) 80907208c4SChristophe Leroy { 81907208c4SChristophe Leroy show_regs(regs); 82907208c4SChristophe Leroy print_backtrace((unsigned long *)regs->gpr[1]); 83907208c4SChristophe Leroy panic("Exception in kernel pc %lx signal %d", regs->nip, signr); 84907208c4SChristophe Leroy } 85907208c4SChristophe Leroy 86907208c4SChristophe Leroy void MachineCheckException(struct pt_regs *regs) 87907208c4SChristophe Leroy { 88*70fd0710SChristophe Leroy unsigned long fixup = search_exception_table(regs->nip); 89907208c4SChristophe Leroy 90907208c4SChristophe Leroy /* Probing PCI using config cycles cause this exception 91907208c4SChristophe Leroy * when a device is not present. Catch it and return to 92907208c4SChristophe Leroy * the PCI exception handler. 93907208c4SChristophe Leroy */ 94*70fd0710SChristophe Leroy if (fixup != 0) { 95907208c4SChristophe Leroy regs->nip = fixup; 96907208c4SChristophe Leroy return; 97907208c4SChristophe Leroy } 98907208c4SChristophe Leroy 99907208c4SChristophe Leroy printf("Machine check in kernel mode.\n"); 100907208c4SChristophe Leroy printf("Caused by (from msr): "); 101907208c4SChristophe Leroy printf("regs %p ", regs); 102907208c4SChristophe Leroy switch (regs->msr & 0x000F0000) { 103907208c4SChristophe Leroy case (0x80000000 >> 12): 104907208c4SChristophe Leroy printf("Machine check signal - probably due to mm fault\n" 105907208c4SChristophe Leroy "with mmu off\n"); 106907208c4SChristophe Leroy break; 107907208c4SChristophe Leroy case (0x80000000 >> 13): 108907208c4SChristophe Leroy printf("Transfer error ack signal\n"); 109907208c4SChristophe Leroy break; 110907208c4SChristophe Leroy case (0x80000000 >> 14): 111907208c4SChristophe Leroy printf("Data parity signal\n"); 112907208c4SChristophe Leroy break; 113907208c4SChristophe Leroy case (0x80000000 >> 15): 114907208c4SChristophe Leroy printf("Address parity signal\n"); 115907208c4SChristophe Leroy break; 116907208c4SChristophe Leroy default: 117907208c4SChristophe Leroy printf("Unknown values in msr\n"); 118907208c4SChristophe Leroy } 119907208c4SChristophe Leroy show_regs(regs); 120907208c4SChristophe Leroy print_backtrace((unsigned long *)regs->gpr[1]); 121907208c4SChristophe Leroy panic("machine check"); 122907208c4SChristophe Leroy } 123907208c4SChristophe Leroy 124907208c4SChristophe Leroy void AlignmentException(struct pt_regs *regs) 125907208c4SChristophe Leroy { 126907208c4SChristophe Leroy show_regs(regs); 127907208c4SChristophe Leroy print_backtrace((unsigned long *)regs->gpr[1]); 128907208c4SChristophe Leroy panic("Alignment Exception"); 129907208c4SChristophe Leroy } 130907208c4SChristophe Leroy 131907208c4SChristophe Leroy void ProgramCheckException(struct pt_regs *regs) 132907208c4SChristophe Leroy { 133907208c4SChristophe Leroy show_regs(regs); 134907208c4SChristophe Leroy print_backtrace((unsigned long *)regs->gpr[1]); 135907208c4SChristophe Leroy panic("Program Check Exception"); 136907208c4SChristophe Leroy } 137907208c4SChristophe Leroy 138907208c4SChristophe Leroy void SoftEmuException(struct pt_regs *regs) 139907208c4SChristophe Leroy { 140907208c4SChristophe Leroy show_regs(regs); 141907208c4SChristophe Leroy print_backtrace((unsigned long *)regs->gpr[1]); 142907208c4SChristophe Leroy panic("Software Emulation Exception"); 143907208c4SChristophe Leroy } 144907208c4SChristophe Leroy 145907208c4SChristophe Leroy 146907208c4SChristophe Leroy void UnknownException(struct pt_regs *regs) 147907208c4SChristophe Leroy { 148907208c4SChristophe Leroy printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", 149907208c4SChristophe Leroy regs->nip, regs->msr, regs->trap); 150907208c4SChristophe Leroy _exception(0, regs); 151907208c4SChristophe Leroy } 152907208c4SChristophe Leroy 153907208c4SChristophe Leroy void DebugException(struct pt_regs *regs) 154907208c4SChristophe Leroy { 155907208c4SChristophe Leroy printf("Debugger trap at @ %lx\n", regs->nip); 156907208c4SChristophe Leroy show_regs(regs); 157907208c4SChristophe Leroy } 158907208c4SChristophe Leroy 159907208c4SChristophe Leroy /* Probe an address by reading. If not present, return -1, otherwise 160907208c4SChristophe Leroy * return 0. 161907208c4SChristophe Leroy */ 162907208c4SChristophe Leroy int addr_probe(uint *addr) 163907208c4SChristophe Leroy { 164907208c4SChristophe Leroy return 0; 165907208c4SChristophe Leroy } 166