Modified: branches/2009R1/arch/blackfin/kernel/cplb-nompu/cplbmgr.c (6613 => 6614)
--- branches/2009R1/arch/blackfin/kernel/cplb-nompu/cplbmgr.c 2009-06-09 01:18:41 UTC (rev 6613)
+++ branches/2009R1/arch/blackfin/kernel/cplb-nompu/cplbmgr.c 2009-06-09 01:24:05 UTC (rev 6614)
@@ -28,6 +28,7 @@
#include <asm/cplbinit.h>
#include <asm/cplb.h>
#include <asm/mmu_context.h>
+#include <asm/traps.h>
/*
* WARNING
@@ -100,28 +101,6 @@
#endif
}
-/*
- * Given the contents of the status register, return the index of the
- * CPLB that caused the fault.
- */
-static inline int faulting_cplb_index(int status)
-{
- int signbits = __builtin_bfin_norm_fr1x32(status & 0xFFFF);
- return 30 - signbits;
-}
-
-/*
- * Given the contents of the status register and the DCPLB_DATA contents,
- * return true if a write access should be permitted.
- */
-static inline int write_permitted(int status, unsigned long data)
-{
- if (status & FAULT_USERSUPV)
- return !!(data & CPLB_SUPV_WR);
- else
- return !!(data & CPLB_USER_WR);
-}
-
/* Counters to implement round-robin replacement. */
static int icplb_rr_index[NR_CPUS] PDT_ATTR;
static int dcplb_rr_index[NR_CPUS] PDT_ATTR;
@@ -245,43 +224,16 @@
return CPLB_RELOADED;
}
-MGR_ATTR static noinline int dcplb_protection_fault(int cpu)
-{
- int status = bfin_read_DCPLB_STATUS();
-
- nr_dcplb_prot[cpu]++;
-
- if (likely(status & FAULT_RW)) {
- int idx = faulting_cplb_index(status);
- unsigned long regaddr = DCPLB_DATA0 + idx * 4;
- unsigned long data = ""
-
- /* Check if fault is to dirty a clean page */
- if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) &&
- write_permitted(status, data)) {
-
- dcplb_tbl[cpu][idx].data = ""
- bfin_write32(regaddr, data);
- return CPLB_RELOADED;
- }
- }
-
- return CPLB_PROT_VIOL;
-}
-
MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs)
{
int cause = seqstat & 0x3f;
unsigned int cpu = smp_processor_id();
switch (cause) {
- case 0x2C:
+ case VEC_CPLB_I_M:
return icplb_miss(cpu);
- case 0x26:
+ case VEC_CPLB_M:
return dcplb_miss(cpu);
default:
- if (unlikely(cause == 0x23))
- return dcplb_protection_fault(cpu);
-
return CPLB_UNKNOWN_ERR;
}
}
Modified: branches/2009R1/arch/blackfin/mach-common/entry.S (6613 => 6614)
--- branches/2009R1/arch/blackfin/mach-common/entry.S 2009-06-09 01:18:41 UTC (rev 6613)
+++ branches/2009R1/arch/blackfin/mach-common/entry.S 2009-06-09 01:24:05 UTC (rev 6614)
@@ -42,6 +42,7 @@
#include <asm/thread_info.h> /* TIF_NEED_RESCHED */
#include <asm/asm-offsets.h>
#include <asm/trace.h>
+#include <asm/traps.h>
#include <asm/context.S>
@@ -84,13 +85,15 @@
if !cc jump _bfin_return_from_exception;
/* fall through */
R7 = P4;
- R6 = 0x26; /* Data CPLB Miss */
+ R6 = VEC_CPLB_M; /* Data CPLB Miss */
cc = R6 == R7;
if cc jump _ex_dcplb_miss (BP);
- R6 = 0x23; /* Data CPLB Miss */
+#ifdef CONFIG_MPU
+ R6 = VEC_CPLB_VL; /* Data CPLB Violation */
cc = R6 == R7;
if cc jump _ex_dcplb_viol (BP);
- /* Handle 0x23 Data CPLB Protection Violation
+#endif
+ /* Handle Data CPLB Protection Violation
* and Data CPLB Multiple Hits - Linux Trap Zero
*/
jump _ex_trap_c;
@@ -200,7 +203,18 @@
cc = r7 == 0;
if !cc jump 1f;
#endif
-
+#ifdef CONFIG_EXACT_HWERR
+ /* Read the ILAT, and to check to see if the process we are
+ * single stepping caused a previous hardware error
+ * If so, do not single step, (which lowers to IRQ5, and makes
+ * us miss the error).
+ */
+ p5.l = lo(ILAT);
+ p5.h = hi(ILAT);
+ r7 = [p5];
+ cc = bittst(r7, EVT_IVHW_P);
+ if cc jump 1f;
+#endif
/* Single stepping only a single instruction, so clear the trace
* bit here. */
r7 = syscfg;
@@ -259,7 +273,7 @@
r6.l = lo(SEQSTAT_EXCAUSE);
r6.h = hi(SEQSTAT_EXCAUSE);
r7 = r7 & r6;
- r6 = 0x25;
+ r6 = VEC_UNCOV;
CC = R7 == R6;
if CC JUMP _double_fault;
#endif
@@ -855,7 +869,7 @@
p1.h = _schedule_and_signal;
[p0] = p1;
csync;
- raise 15; /* raise evt14 to do signal or reschedule */
+ raise 15; /* raise evt15 to do signal or reschedule */
4:
r0 = syscfg;
bitclr(r0, 0);
@@ -916,7 +930,7 @@
p1.h = _schedule_and_signal_from_int;
[p0] = p1;
csync;
-#if ANOMALY_05000281
+#if ANOMALY_05000281 || ANOMALY_05000461
r0.l = lo(SAFE_USER_INSTRUCTION);
r0.h = hi(SAFE_USER_INSTRUCTION);
reti = r0;
@@ -930,18 +944,27 @@
ENDPROC(_return_from_int)
ENTRY(_lower_to_irq14)
-#if ANOMALY_05000281
+#if ANOMALY_05000281 || ANOMALY_05000461
r0.l = lo(SAFE_USER_INSTRUCTION);
r0.h = hi(SAFE_USER_INSTRUCTION);
reti = r0;
#endif
- r0 = 0x401f;
+
+#ifdef CONFIG_DEBUG_HWERR
+ /* enable irq14 & hwerr interrupt, until we transition to _evt14_softirq */
+ r0 = (EVT_IVG14 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#else
+ /* Only enable irq14 interrupt, until we transition to _evt14_softirq */
+ r0 = (EVT_IVG14 | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#endif
sti r0;
raise 14;
rti;
+ENDPROC(_lower_to_irq14)
+
ENTRY(_evt14_softirq)
#ifdef CONFIG_DEBUG_HWERR
- r0 = 0x3f;
+ r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
sti r0;
#else
cli r0;
@@ -949,8 +972,9 @@
[--sp] = RETI;
SP += 4;
rts;
+ENDPROC(_evt14_softirq)
-_schedule_and_signal_from_int:
+ENTRY(_schedule_and_signal_from_int)
/* To end up here, vector 15 was changed - so we have to change it
* back.
*/
@@ -983,8 +1007,9 @@
call _finish_atomic_sections;
sp += 12;
jump.s .Lresume_userspace;
+ENDPROC(_schedule_and_signal_from_int)
-_schedule_and_signal:
+ENTRY(_schedule_and_signal)
SAVE_CONTEXT_SYSCALL
/* To end up here, vector 15 was changed - so we have to change it
* back.
@@ -1002,7 +1027,7 @@
1:
RESTORE_CONTEXT
rti;
-ENDPROC(_lower_to_irq14)
+ENDPROC(_schedule_and_signal)
/* We handle this 100% in exception space - to reduce overhead
* Only potiential problem is if the software buffer gets swapped out of the