[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 <robin.getz@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com>
This commit is contained in:
@@ -34,9 +34,13 @@
|
||||
#include <asm/entry.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/trace.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
#include <asm/mach-common/context.S>
|
||||
|
||||
.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:
|
||||
|
Reference in New Issue
Block a user