aboutsummaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorStefan Roese <sr@denx.de>2007-06-15 11:20:13 +0200
committerStefan Roese <sr@denx.de>2007-06-15 11:20:13 +0200
commitb7c3e93105c4955177cb2ab179ed2bf83ea02adc (patch)
tree9e2e1dd0debb051d79ba8458d9f3c48a8de8cdf5 /cpu
parentb765ffb773f5a3cd5aa94ec76b6a05276b8cd5b2 (diff)
parentefa35cf12d914d4caba942acd5a6c45f217de302 (diff)
Merge with /home/stefan/git/u-boot/denx-440-exceptions
Diffstat (limited to 'cpu')
-rw-r--r--cpu/ppc4xx/config.mk10
-rw-r--r--cpu/ppc4xx/start.S329
-rw-r--r--cpu/ppc4xx/traps.c107
3 files changed, 242 insertions, 204 deletions
diff --git a/cpu/ppc4xx/config.mk b/cpu/ppc4xx/config.mk
index 119e061b8..e7fc3f636 100644
--- a/cpu/ppc4xx/config.mk
+++ b/cpu/ppc4xx/config.mk
@@ -22,5 +22,13 @@
#
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -fno-strict-aliasing
+PLATFORM_CPPFLAGS += -DCONFIG_4xx -ffixed-r2 -ffixed-r29 -mstring -msoft-float
-PLATFORM_CPPFLAGS += -DCONFIG_4xx -ffixed-r2 -ffixed-r29 -mstring -Wa,-m405 -mcpu=405 -msoft-float
+cfg=$(shell grep configs $(TOPDIR)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
+is440=$(shell grep CONFIG_440 $(TOPDIR)/include/$(cfg))
+
+ifneq (,$(findstring CONFIG_440,$(is440)))
+PLATFORM_CPPFLAGS += -Wa,-m440 -mcpu=440
+else
+PLATFORM_CPPFLAGS += -Wa,-m405 -mcpu=405
+endif
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index 78d0042cc..e135220f6 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -294,11 +294,13 @@ skip_debug_init:
mtspr ivor7,r1 /* Floating point unavailable */
li r1,0x0c00
mtspr ivor8,r1 /* System call */
- li r1,0x1000
- mtspr ivor10,r1 /* Decrementer (PIT for 440) */
- li r1,0x1400
- mtspr ivor13,r1 /* Data TLB error */
+ li r1,0x0a00
+ mtspr ivor9,r1 /* Auxiliary Processor unavailable */
+ li r1,0x0900
+ mtspr ivor10,r1 /* Decrementer */
li r1,0x1300
+ mtspr ivor13,r1 /* Data TLB error */
+ li r1,0x1400
mtspr ivor14,r1 /* Instr TLB error */
li r1,0x2000
mtspr ivor15,r1 /* Debug */
@@ -503,11 +505,81 @@ version_string:
.ascii " (", __DATE__, " - ", __TIME__, ")"
.ascii CONFIG_IDENT_STRING, "\0"
-/*
- * Maybe this should be moved somewhere else because the current
- * location (0x100) is where the CriticalInput Execption should be.
- */
. = EXC_OFF_SYS_RESET
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Critical input. */
+ CRIT_EXCEPTION(0x100, CritcalInput, UnknownException)
+
+#ifdef CONFIG_440
+/* Machine check */
+ MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+#else
+ CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+#endif /* CONFIG_440 */
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ lwz r6,GOT(transfer_to_handler)
+ mtlr r6
+ blrl
+.L_Alignment:
+ .long AlignmentException - _start + _START_OFFSET
+ .long int_return - _start + _START_OFFSET
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ lwz r6,GOT(transfer_to_handler)
+ mtlr r6
+ blrl
+.L_ProgramCheck:
+ .long ProgramCheckException - _start + _START_OFFSET
+ .long int_return - _start + _START_OFFSET
+
+#ifdef CONFIG_440
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+ STD_EXCEPTION(0x900, Decrementer, DecrementerPITException)
+ STD_EXCEPTION(0xa00, APU, UnknownException)
+#endif
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+
+#ifdef CONFIG_440
+ STD_EXCEPTION(0x1300, DataTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, InstructionTLBError, UnknownException)
+#else
+ STD_EXCEPTION(0x1000, PIT, DecrementerPITException)
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+#endif
+ CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
+
+ .globl _end_of_vectors
+_end_of_vectors:
+ . = _START_OFFSET
#endif
.globl _start
_start:
@@ -1017,107 +1089,6 @@ start_ram:
#ifndef CONFIG_NAND_SPL
-/*****************************************************************************/
- .globl _start_of_vectors
-_start_of_vectors:
-
-#if 0
-/*TODO Fixup _start above so we can do this*/
-/* Critical input. */
- CRIT_EXCEPTION(0x100, CritcalInput, CritcalInputException)
-#endif
-
-/* Machine check */
- CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException)
-
-/* Data Storage exception. */
- STD_EXCEPTION(0x300, DataStorage, UnknownException)
-
-/* Instruction Storage exception. */
- STD_EXCEPTION(0x400, InstStorage, UnknownException)
-
-/* External Interrupt exception. */
- STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
-
-/* Alignment exception. */
- . = 0x600
-Alignment:
- EXCEPTION_PROLOG
- mfspr r4,DAR
- stw r4,_DAR(r21)
- mfspr r5,DSISR
- stw r5,_DSISR(r21)
- addi r3,r1,STACK_FRAME_OVERHEAD
- li r20,MSR_KERNEL
- rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
- lwz r6,GOT(transfer_to_handler)
- mtlr r6
- blrl
-.L_Alignment:
- .long AlignmentException - _start + EXC_OFF_SYS_RESET
- .long int_return - _start + EXC_OFF_SYS_RESET
-
-/* Program check exception */
- . = 0x700
-ProgramCheck:
- EXCEPTION_PROLOG
- addi r3,r1,STACK_FRAME_OVERHEAD
- li r20,MSR_KERNEL
- rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
- lwz r6,GOT(transfer_to_handler)
- mtlr r6
- blrl
-.L_ProgramCheck:
- .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
- .long int_return - _start + EXC_OFF_SYS_RESET
-
- /* No FPU on MPC8xx. This exception is not supposed to happen.
- */
- STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
-
- /* I guess we could implement decrementer, and may have
- * to someday for timekeeping.
- */
- STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
- STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
- STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
- STD_EXCEPTION(0xc00, SystemCall, UnknownException)
- STD_EXCEPTION(0xd00, SingleStep, UnknownException)
-
- STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
- STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
-
- /* On the MPC8xx, this is a software emulation interrupt. It occurs
- * for all unimplemented and illegal instructions.
- */
- STD_EXCEPTION(0x1000, PIT, PITException)
-
- STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
- STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
- STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
- STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
-
- STD_EXCEPTION(0x1500, Reserved5, UnknownException)
- STD_EXCEPTION(0x1600, Reserved6, UnknownException)
- STD_EXCEPTION(0x1700, Reserved7, UnknownException)
- STD_EXCEPTION(0x1800, Reserved8, UnknownException)
- STD_EXCEPTION(0x1900, Reserved9, UnknownException)
- STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
- STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
-
- STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
- STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
- STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
- STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
-
- CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
-
- .globl _end_of_vectors
-_end_of_vectors:
-
-
- . = 0x2100
-
/*
* This code finishes saving the registers to the exception frame
* and jumps to the appropriate handler for the exception.
@@ -1133,28 +1104,12 @@ transfer_to_handler:
SAVE_4GPRS(8, r21)
SAVE_8GPRS(12, r21)
SAVE_8GPRS(24, r21)
-#if 0
- andi. r23,r23,MSR_PR
- mfspr r23,SPRG3 /* if from user, fix up tss.regs */
- beq 2f
- addi r24,r1,STACK_FRAME_OVERHEAD
- stw r24,PT_REGS(r23)
-2: addi r2,r23,-TSS /* set r2 to current */
- tovirt(r2,r2,r23)
-#endif
mflr r23
andi. r24,r23,0x3f00 /* get vector offset */
stw r24,TRAP(r21)
li r22,0
stw r22,RESULT(r21)
mtspr SPRG2,r22 /* r1 is now kernel sp */
-#if 0
- addi r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
- cmplw 0,r1,r2
- cmplw 1,r1,r24
- crand 1,1,4
- bgt stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
-#endif
lwz r24,0(r23) /* virtual address of handler */
lwz r23,4(r23) /* where to go when done */
mtspr SRR0,r24
@@ -1215,16 +1170,64 @@ crit_return:
REST_GPR(31, r1)
lwz r2,_NIP(r1) /* Restore environment */
lwz r0,_MSR(r1)
- mtspr 990,r2 /* SRR2 */
- mtspr 991,r0 /* SRR3 */
+ mtspr csrr0,r2
+ mtspr csrr1,r0
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
lwz r1,GPR1(r1)
SYNC
rfci
-/* Cache functions.
-*/
+#ifdef CONFIG_440
+mck_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr mcsrr0,r2
+ mtspr mcsrr1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfmci
+#endif /* CONFIG_440 */
+
+
+/*
+ * Cache functions.
+ *
+ * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM,
+ * although for some cache-ralated calls stubs have to be provided to satisfy
+ * symbols resolution.
+ *
+ */
+#ifdef CONFIG_440
+ .globl dcache_disable
+dcache_disable:
+ blr
+
+ .globl dcache_status
+dcache_status:
+ blr
+#else
flush_dcache:
addis r9,r0,0x0002 /* set mask for EE and CE msr bits */
ori r9,r9,0x8000
@@ -1303,24 +1306,13 @@ dcache_status:
mfdccr r3
srwi r3, r3, 31 /* >>31 => select bit 0 */
blr
+#endif
.globl get_pvr
get_pvr:
mfspr r3, PVR
blr
-#if !defined(CONFIG_440)
- .globl wr_pit
-wr_pit:
- mtspr pit, r3
- blr
-#endif
-
- .globl wr_tcr
-wr_tcr:
- mtspr tcr, r3
- blr
-
/*------------------------------------------------------------------------------- */
/* Function: out16 */
/* Description: Output 16 bits */
@@ -1518,7 +1510,7 @@ relocate_code:
* initialization, now running from RAM.
*/
- addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ addi r0, r10, in_ram - _start + _START_OFFSET
mtlr r0
blr /* NEVER RETURNS! */
@@ -1588,7 +1580,7 @@ clear_bss:
*/
.globl trap_init
trap_init:
- lwz r7, GOT(_start)
+ lwz r7, GOT(_start_of_vectors)
lwz r8, GOT(_end_of_vectors)
li r9, 0x100 /* reset vector always at 0x100 */
@@ -1608,35 +1600,48 @@ trap_init:
/*
* relocate `hdlr' and `int_return' entries
*/
- li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
- li r8, Alignment - _start + EXC_OFF_SYS_RESET
+ li r7, .L_MachineCheck - _start + _START_OFFSET
+ li r8, Alignment - _start + _START_OFFSET
2:
bl trap_reloc
- addi r7, r7, 0x100 /* next exception vector */
+ addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 2b
- li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ li r7, .L_Alignment - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ li r7, .L_ProgramCheck - _start + _START_OFFSET
bl trap_reloc
- li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
- li r8, SystemCall - _start + EXC_OFF_SYS_RESET
-3:
- bl trap_reloc
- addi r7, r7, 0x100 /* next exception vector */
- cmplw 0, r7, r8
- blt 3b
+#ifdef CONFIG_440
+ li r7, .L_FPUnavailable - _start + _START_OFFSET
+ bl trap_reloc
- li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
- li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
-4:
- bl trap_reloc
- addi r7, r7, 0x100 /* next exception vector */
- cmplw 0, r7, r8
- blt 4b
+ li r7, .L_Decrementer - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_APU - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_InstructionTLBError - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_DataTLBError - _start + _START_OFFSET
+ bl trap_reloc
+#else /* CONFIG_440 */
+ li r7, .L_PIT - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_InstructionTLBMiss - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_DataTLBMiss - _start + _START_OFFSET
+ bl trap_reloc
+#endif /* CONFIG_440 */
+
+ li r7, .L_DebugBreakpoint - _start + _START_OFFSET
+ bl trap_reloc
#if !defined(CONFIG_440)
addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */
diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c
index 6aecca2db..54659d337 100644
--- a/cpu/ppc4xx/traps.c
+++ b/cpu/ppc4xx/traps.c
@@ -36,6 +36,8 @@
#include <command.h>
#include <asm/processor.h>
+DECLARE_GLOBAL_DATA_PTR;
+
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
@@ -45,8 +47,7 @@ extern unsigned long search_exception_table(unsigned long);
/* THIS NEEDS CHANGING to use the board info structure.
*/
-#define END_OF_MEM 0x00400000
-
+#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize)
static __inline__ void set_tsr(unsigned long val)
{
@@ -88,29 +89,29 @@ extern void do_bedbug_breakpoint(struct pt_regs *);
void
print_backtrace(unsigned long *sp)
{
- int cnt = 0;
- unsigned long i;
-
- printf("Call backtrace: ");
- while (sp) {
- if ((uint)sp > END_OF_MEM)
- break;
-
- i = sp[1];
- if (cnt++ % 7 == 0)
- printf("\n");
- printf("%08lX ", i);
- if (cnt > 32) break;
- sp = (unsigned long *)*sp;
- }
- printf("\n");
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
}
void show_regs(struct pt_regs * regs)
{
int i;
- printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DEAR: %08lX\n",
regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
@@ -139,14 +140,14 @@ _exception(int signr, struct pt_regs *regs)
{
show_regs(regs);
print_backtrace((unsigned long *)regs->gpr[1]);
- panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+ panic("Exception");
}
void
MachineCheckException(struct pt_regs *regs)
{
- unsigned long fixup;
-
+ unsigned long fixup, val;
+
/* Probing PCI using config cycles cause this exception
* when a device is not present. Catch it and return to
* the PCI exception handler.
@@ -161,26 +162,50 @@ MachineCheckException(struct pt_regs *regs)
return;
#endif
- printf("Machine check in kernel mode.\n");
+ printf("Machine Check Exception.\n");
printf("Caused by (from msr): ");
- printf("regs %p ",regs);
- switch( regs->msr & 0x000F0000) {
- case (0x80000000>>12):
- printf("Machine check signal - probably due to mm fault\n"
- "with mmu off\n");
- break;
- case (0x80000000>>13):
- printf("Transfer error ack signal\n");
- break;
- case (0x80000000>>14):
- printf("Data parity signal\n");
- break;
- case (0x80000000>>15):
- printf("Address parity signal\n");
- break;
- default:
- printf("Unknown values in msr\n");
+ printf("regs %p ", regs);
+
+ val = get_esr();
+
+#if !defined(CONFIG_440)
+ if (val& ESR_IMCP) {
+ printf("Instruction");
+ mtspr(ESR, val & ~ESR_IMCP);
+ } else
+ printf("Data");
+ printf(" machine check.\n");
+
+#elif defined(CONFIG_440)
+ if (val& ESR_IMCP){
+ printf("Instruction Synchronous Machine Check exception\n");
+ mtspr(SPRN_ESR, val & ~ESR_IMCP);
}
+ else {
+ val = mfspr(MCSR);
+ if (val & MCSR_IB)
+ printf("Instruction Read PLB Error\n");
+ if (val & MCSR_DRB)
+ printf("Data Read PLB Error\n");
+ if (val & MCSR_DWB)
+ printf("Data Write PLB Error\n");
+ if (val & MCSR_TLBP)
+ printf("TLB Parity Error\n");
+ if (val & MCSR_ICP){
+ /*flush_instruction_cache(); */
+ printf("I-Cache Parity Error\n");
+ }
+ if (val & MCSR_DCSP)
+ printf("D-Cache Search Parity Error\n");
+ if (val & MCSR_DCFP)
+ printf("D-Cache Flush Parity Error\n");
+ if (val & MCSR_IMPE)
+ printf("Machine Check exception is imprecise\n");
+
+ /* Clear MCSR */
+ mtspr(SPRN_MCSR, val);
+ }
+#endif
show_regs(regs);
print_backtrace((unsigned long *)regs->gpr[1]);
panic("machine check");
@@ -224,7 +249,7 @@ ProgramCheckException(struct pt_regs *regs)
}
void
-PITException(struct pt_regs *regs)
+DecrementerPITException(struct pt_regs *regs)
{
/*
* Reset PIT interrupt