From 13fe24f37df20e580a5a364e67ec8cf3219d8f8c Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sun, 27 Jan 2008 15:38:56 +0800 Subject: [Blackfin] arch: fix bug - trap_tests fails to recover on some tests. http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=3719 When the CPLBs get a miss, we do: - find a victim in the HW table - remove the victim - find the replacement in the software table - put it into the HW table. If we can't find a replacement in the software table, we accidently leave a duplicate in the HW table. This patch ensures that duplicate is marked as not valid. What we should do is find the replacement in the software table, before we find a victim in the HW table - but its too late in the release cycle to do that much restructuring of this code. Rather that duplicate code, connect Hardware Errors (irq5) into trap_c, so user space processes get killed properly. The rest of irq_panic() can be moved into traps.c (later) There is still a small corner case that causes problems when a pheriperal interrupt goes off a single cycle before a user space hardware error. This causes a kernel panic, rather than the user space process being killed. But, this checkin makes things work in 99.9% of the cases, and is a vast improvement from what is there today (which fails 100% of the time). Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/interrupt.S | 40 ++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'arch/blackfin/mach-common/interrupt.S') diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 4de3764..f983ac7 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -34,9 +34,13 @@ #include #include #include +#include +#include #include +.extern _ret_from_exception + #ifdef CONFIG_I_ENTRY_L1 .section .l1.text #else @@ -134,10 +138,11 @@ __common_int_entry: /* interrupt routine for ivhw - 5 */ ENTRY(_evt_ivhw) - SAVE_CONTEXT + SAVE_ALL_SYS #ifdef CONFIG_FRAME_POINTER fp = 0; #endif + #if ANOMALY_05000283 cc = r7 == r7; p5.h = 0xffc0; @@ -147,13 +152,8 @@ ENTRY(_evt_ivhw) 1: #endif - trace_buffer_stop(p0, r0); - - r0 = IRQ_HWERR; - r1 = sp; - #ifdef CONFIG_HARDWARE_PM - r7 = SEQSTAT; + r7 = [sp + PT_SEQSTAT]; r7 = r7 >>> 0xe; r6 = 0x1F; r7 = r7 & r6; @@ -161,11 +161,29 @@ ENTRY(_evt_ivhw) cc = r7 == r5; if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */ #endif - + # We are going to dump something out, so make sure we print IPEND properly + p2.l = lo(IPEND); + p2.h = hi(IPEND); + r0 = [p2]; + [sp + PT_IPEND] = r0; + + /* set the EXCAUSE to HWERR for trap_c */ + r0 = [sp + PT_SEQSTAT]; + R1.L = LO(VEC_HWERR); + R1.H = HI(VEC_HWERR); + R0 = R0 | R1; + [sp + PT_SEQSTAT] = R0; + + r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ SP += -12; - call _irq_panic; + call _trap_c; SP += 12; + + call _ret_from_exception; +.Lcommon_restore_all_sys: + RESTORE_ALL_SYS rti; + #ifdef CONFIG_HARDWARE_PM .Lcall_do_ovf: @@ -173,9 +191,11 @@ ENTRY(_evt_ivhw) call _pm_overflow; SP += 12; - jump .Lcommon_restore_context; + jump .Lcommon_restore_all_sys; #endif +ENDPROC(_evt_ivhw) + /* Interrupt routine for evt2 (NMI). * We don't actually use this, so just return. * For inner circle type details, please see: -- cgit v1.1