u-boot/arch/avr32/cpu/exception.c
Haavard Skinnemoen 8d1334a787 avr32: Print unrelocated PC on exception
In addition to the real PC value, also print the value of PC after
subtracting the relocation offset. This value will match the address in
the ELF file so it's much easier to figure out where things went wrong.

Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
2010-09-03 15:12:42 +02:00

122 lines
3.6 KiB
C

/*
* Copyright (C) 2005-2006 Atmel Corporation
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/sysreg.h>
#include <asm/ptrace.h>
DECLARE_GLOBAL_DATA_PTR;
static const char * const cpu_modes[8] = {
"Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
"Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
};
static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
{
unsigned long p;
int i;
printf("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
for (p = bottom & ~31; p < top; ) {
printf("%04lx: ", p & 0xffff);
for (i = 0; i < 8; i++, p += 4) {
unsigned int val;
if (p < bottom || p >= top)
printf(" ");
else {
val = *(unsigned long *)p;
printf("%08x ", val);
}
}
printf("\n");
}
}
void do_unknown_exception(unsigned int ecr, struct pt_regs *regs)
{
unsigned int mode;
printf("\n *** Unhandled exception %u at PC=0x%08lx [%08lx]\n",
ecr, regs->pc, regs->pc - gd->reloc_off);
switch (ecr) {
case ECR_BUS_ERROR_WRITE:
case ECR_BUS_ERROR_READ:
printf("Bus error at address 0x%08lx\n",
sysreg_read(BEAR));
break;
case ECR_TLB_MULTIPLE:
case ECR_ADDR_ALIGN_X:
case ECR_PROTECTION_X:
case ECR_ADDR_ALIGN_R:
case ECR_ADDR_ALIGN_W:
case ECR_PROTECTION_R:
case ECR_PROTECTION_W:
case ECR_DTLB_MODIFIED:
case ECR_TLB_MISS_X:
case ECR_TLB_MISS_R:
case ECR_TLB_MISS_W:
printf("MMU exception at address 0x%08lx\n",
sysreg_read(TLBEAR));
break;
}
printf(" pc: %08lx lr: %08lx sp: %08lx r12: %08lx\n",
regs->pc, regs->lr, regs->sp, regs->r12);
printf(" r11: %08lx r10: %08lx r9: %08lx r8: %08lx\n",
regs->r11, regs->r10, regs->r9, regs->r8);
printf(" r7: %08lx r6: %08lx r5: %08lx r4: %08lx\n",
regs->r7, regs->r6, regs->r5, regs->r4);
printf(" r3: %08lx r2: %08lx r1: %08lx r0: %08lx\n",
regs->r3, regs->r2, regs->r1, regs->r0);
printf("Flags: %c%c%c%c%c\n",
regs->sr & SR_Q ? 'Q' : 'q',
regs->sr & SR_V ? 'V' : 'v',
regs->sr & SR_N ? 'N' : 'n',
regs->sr & SR_Z ? 'Z' : 'z',
regs->sr & SR_C ? 'C' : 'c');
printf("Mode bits: %c%c%c%c%c%c%c%c%c\n",
regs->sr & SR_H ? 'H' : 'h',
regs->sr & SR_R ? 'R' : 'r',
regs->sr & SR_J ? 'J' : 'j',
regs->sr & SR_EM ? 'E' : 'e',
regs->sr & SR_I3M ? '3' : '.',
regs->sr & SR_I2M ? '2' : '.',
regs->sr & SR_I1M ? '1' : '.',
regs->sr & SR_I0M ? '0' : '.',
regs->sr & SR_GM ? 'G' : 'g');
mode = (regs->sr >> SYSREG_M0_OFFSET) & 7;
printf("CPU Mode: %s\n", cpu_modes[mode]);
/* Avoid exception loops */
if (regs->sp < (gd->stack_end - CONFIG_STACKSIZE)
|| regs->sp >= gd->stack_end)
printf("\nStack pointer seems bogus, won't do stack dump\n");
else
dump_mem("\nStack: ", regs->sp, gd->stack_end);
panic("Unhandled exception\n");
}