[POWERPC] pasemi: Fix module information for gpio-mdio
[sfrench/cifs-2.6.git] / arch / blackfin / mach-common / entry.S
index 9604588083446d6c866595e4336d0e63fc6c7b97..1b13fa470977e8d0c13aa3ba722f009f47556445 100644 (file)
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- * 25-Dec-2004 - LG Soft India
- *     1. Fix in return_from_int, to make sure any pending
- *     system call in ILAT for this process to get
- *     executed, otherwise in case context switch happens,
- *     system call of first process (i.e in ILAT) will be
- *     carried forward to the switched process.
- *     2. Removed Constant references for the following
- *             a.  IPEND
- *             b.  EXCAUSE mask
- *             c.  PAGE Mask
- */
-
-/*
- * NOTE: This code handles signal-recognition, which happens every time
+/* NOTE: This code handles signal-recognition, which happens every time
  * after a timer-interrupt and after each system call.
  */
 
 
 #include <asm/mach-common/context.S>
 
+#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
+# define EX_SCRATCH_REG RETN
+#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
+# define EX_SCRATCH_REG RETE
+#else
+# define EX_SCRATCH_REG CYCLES
+#endif
+
+#if ANOMALY_05000281
+ENTRY(_safe_speculative_execution)
+       NOP;
+       NOP;
+       NOP;
+       jump _safe_speculative_execution;
+ENDPROC(_safe_speculative_execution)
+#endif
+
 #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
 .section .l1.text
 #else
@@ -69,7 +72,7 @@
  * patch up CPLB misses on the kernel stack.
  */
 ENTRY(_ex_dcplb)
-#if defined(ANOMALY_05000261)
+#if ANOMALY_05000261
        /*
         * Work around an anomaly: if we see a new DCPLB fault, return
         * without doing anything.  Then, if we get the same fault again,
@@ -93,7 +96,7 @@ ENTRY(_ex_icplb)
        call __cplb_hdr;
        DEBUG_START_HWTRACE(p5, r7)
        RESTORE_ALL_SYS
-       SP = RETN;
+       SP = EX_SCRATCH_REG;
        rtx;
 ENDPROC(_ex_icplb)
 
@@ -102,7 +105,7 @@ ENTRY(_ex_syscall)
        (R7:6,P5:4) = [sp++];
        ASTAT = [sp++];
        raise 15;               /* invoked by TRAP #0, for sys call */
-       sp = retn;
+       sp = EX_SCRATCH_REG;
        rtx
 ENDPROC(_ex_syscall)
 
@@ -135,9 +138,9 @@ ENTRY(_ex_single_step)
        cc = r6 == r7;
        if !cc jump _ex_trap_c;
 
-_return_from_exception:
+ENTRY(_return_from_exception)
        DEBUG_START_HWTRACE(p5, r7)
-#ifdef ANOMALY_05000257
+#if ANOMALY_05000257
        R7=LC0;
        LC0=R7;
        R7=LC1;
@@ -145,7 +148,7 @@ _return_from_exception:
 #endif
        (R7:6,P5:4) = [sp++];
        ASTAT = [sp++];
-       sp = retn;
+       sp = EX_SCRATCH_REG;
        rtx;
 ENDPROC(_ex_soft_bp)
 
@@ -163,7 +166,17 @@ ENTRY(_handle_bad_cplb)
        [--sp] = ASTAT;
        [--sp] = (R7:6, P5:4);
 
+ENTRY(_ex_replaceable)
+       nop;
+
 ENTRY(_ex_trap_c)
+       /* Make sure we are not in a double fault */
+       p4.l = lo(IPEND);
+       p4.h = hi(IPEND);
+       r7 = [p4];
+       CC = BITTST (r7, 5);
+       if CC jump _double_fault;
+
        /* Call C code (trap_c) to handle the exception, which most
         * likely involves sending a signal to the current process.
         * To avoid double faults, lower our priority to IRQ5 first.
@@ -204,11 +217,57 @@ ENTRY(_ex_trap_c)
        DEBUG_START_HWTRACE(p5, r7)
        (R7:6,P5:4) = [sp++];
        ASTAT = [sp++];
-       SP = RETN;
+       SP = EX_SCRATCH_REG;
        raise 5;
        rtx;
 ENDPROC(_ex_trap_c)
 
+/* We just realized we got an exception, while we were processing a different
+ * exception. This is a unrecoverable event, so crash
+ */
+ENTRY(_double_fault)
+        /* Turn caches & protection off, to ensure we don't get any more
+         * double exceptions
+         */
+
+        P4.L = LO(IMEM_CONTROL);
+        P4.H = HI(IMEM_CONTROL);
+
+        R5 = [P4];              /* Control Register*/
+        BITCLR(R5,ENICPLB_P);
+        SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
+        .align 8;
+        [P4] = R5;
+        SSYNC;
+
+        P4.L = LO(DMEM_CONTROL);
+        P4.H = HI(DMEM_CONTROL);
+        R5 = [P4];
+        BITCLR(R5,ENDCPLB_P);
+        SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */
+        .align 8;
+        [P4] = R5;
+        SSYNC;
+
+        /* Fix up the stack */
+        (R7:6,P5:4) = [sp++];
+        ASTAT = [sp++];
+        SP = EX_SCRATCH_REG;
+
+        /* We should be out of the exception stack, and back down into
+         * kernel or user space stack
+         */
+        SAVE_ALL_SYS
+
+        r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */
+        SP += -12;
+        call _double_fault_c;
+        SP += 12;
+.L_double_fault_panic:
+        JUMP .L_double_fault_panic
+
+ENDPROC(_double_fault)
+
 ENTRY(_exception_to_level5)
        SAVE_ALL_SYS
 
@@ -279,7 +338,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
         * covered by a CPLB.  Switch to an exception stack; use RETN as a
         * scratch register (for want of a better option).
         */
-       retn = sp;
+       EX_SCRATCH_REG = sp;
        sp.l = _exception_stack_top;
        sp.h = _exception_stack_top;
        /* Try to deal with syscalls quickly.  */
@@ -290,8 +349,8 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
        r6.l = lo(SEQSTAT_EXCAUSE);
        r6.h = hi(SEQSTAT_EXCAUSE);
        r7 = r7 & r6;
-       p5.h = _extable;
-       p5.l = _extable;
+       p5.h = _ex_table;
+       p5.l = _ex_table;
        p4 = r7;
        p5 = p5 + (p4 << 2);
        p4 = [p5];
@@ -634,9 +693,9 @@ ENTRY(_return_from_int)
        p1.h = _schedule_and_signal_from_int;
        [p0] = p1;
        csync;
-#if defined(ANOMALY_05000281)
-       r0.l = lo(CONFIG_BOOT_LOAD);
-       r0.h = hi(CONFIG_BOOT_LOAD);
+#if ANOMALY_05000281
+       r0.l = _safe_speculative_execution;
+       r0.h = _safe_speculative_execution;
        reti = r0;
 #endif
        r0 = 0x801f (z);
@@ -648,9 +707,9 @@ ENTRY(_return_from_int)
 ENDPROC(_return_from_int)
 
 ENTRY(_lower_to_irq14)
-#if defined(ANOMALY_05000281)
-       r0.l = lo(CONFIG_BOOT_LOAD);
-       r0.h = hi(CONFIG_BOOT_LOAD);
+#if ANOMALY_05000281
+       r0.l = _safe_speculative_execution;
+       r0.h = _safe_speculative_execution;
        reti = r0;
 #endif
        r0 = 0x401f;
@@ -731,6 +790,114 @@ ENTRY(_init_exception_buff)
        rts;
 ENDPROC(_init_exception_buff)
 
+/* We handle this 100% in exception space - to reduce overhead
+ * Only potiential problem is if the software buffer gets swapped out of the
+ * CPLB table - then double fault. - so we don't let this happen in other places
+ */
+#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
+ENTRY(_ex_trace_buff_full)
+       [--sp] = P3;
+       [--sp] = P2;
+       [--sp] = LC0;
+       [--sp] = LT0;
+       [--sp] = LB0;
+       P5.L = _trace_buff_offset;
+       P5.H = _trace_buff_offset;
+       P3 = [P5];              /* trace_buff_offset */
+       P5.L = lo(TBUFSTAT);
+       P5.H = hi(TBUFSTAT);
+       R7 = [P5];
+       R7 <<= 1;               /* double, since we need to read twice */
+       LC0 = R7;
+       R7 <<= 2;               /* need to shift over again,
+                                * to get the number of bytes */
+       P5.L = lo(TBUF);
+       P5.H = hi(TBUF);
+       R6 = ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*1024) - 1;
+
+       P2 = R7;
+       P3 = P3 + P2;
+       R7 = P3;
+       R7 = R7 & R6;
+       P3 = R7;
+       P2.L = _trace_buff_offset;
+       P2.H = _trace_buff_offset;
+       [P2] = P3;
+
+       P2.L = _software_trace_buff;
+       P2.H = _software_trace_buff;
+
+       LSETUP (.Lstart, .Lend) LC0;
+.Lstart:
+       R7 = [P5];      /* read TBUF */
+       P4 = P3 + P2;
+       [P4] = R7;
+       P3 += -4;
+       R7 = P3;
+       R7 = R7 & R6;
+.Lend:
+       P3 = R7;
+
+       LB0 = [sp++];
+       LT0 = [sp++];
+       LC0 = [sp++];
+       P2 = [sp++];
+       P3 = [sp++];
+       jump _return_from_exception;
+ENDPROC(_ex_trace_buff_full)
+
+#if CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN == 4
+.data
+#else
+.section .l1.data.B
+#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN */
+ENTRY(_trace_buff_offset)
+        .long 0;
+ALIGN
+ENTRY(_software_trace_buff)
+       .rept ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*256);
+       .long 0
+       .endr
+#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND */
+
+#if CONFIG_EARLY_PRINTK
+.section .init.text
+ENTRY(_early_trap)
+       SAVE_ALL_SYS
+       trace_buffer_stop(p0,r0);
+
+       /* Turn caches off, to ensure we don't get double exceptions */
+
+       P4.L = LO(IMEM_CONTROL);
+       P4.H = HI(IMEM_CONTROL);
+
+       R5 = [P4];              /* Control Register*/
+       BITCLR(R5,ENICPLB_P);
+       CLI R1;
+       SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
+       .align 8;
+       [P4] = R5;
+       SSYNC;
+
+       P4.L = LO(DMEM_CONTROL);
+       P4.H = HI(DMEM_CONTROL);
+       R5 = [P4];
+       BITCLR(R5,ENDCPLB_P);
+       SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */
+       .align 8;
+       [P4] = R5;
+       SSYNC;
+       STI R1;
+
+       r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */
+       r1 = RETX;
+
+       SP += -12;
+       call _early_trap_c;
+       SP += 12;
+ENDPROC(_early_trap)
+#endif /* CONFIG_EARLY_PRINTK */
+
 /*
  * Put these in the kernel data section - that should always be covered by
  * a CPLB. This is needed to ensure we don't get double fault conditions
@@ -741,30 +908,33 @@ ENDPROC(_init_exception_buff)
 #else
 .data
 #endif
-ALIGN
-_extable:
+ENTRY(_ex_table)
        /* entry for each EXCAUSE[5:0]
         * This table must be in sync with the table in ./kernel/traps.c
         * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
         */
-       .long _ex_syscall;      /* 0x00 - User Defined - Linux Syscall */
+       .long _ex_syscall       /* 0x00 - User Defined - Linux Syscall */
        .long _ex_soft_bp       /* 0x01 - User Defined - Software breakpoint */
-       .long _ex_trap_c        /* 0x02 - User Defined */
+       .long _ex_replaceable   /* 0x02 - User Defined */
        .long _ex_trap_c        /* 0x03 - User Defined - userspace stack overflow */
-       .long _ex_trap_c        /* 0x04 - User Defined */
-       .long _ex_trap_c        /* 0x05 - User Defined */
-       .long _ex_trap_c        /* 0x06 - User Defined */
-       .long _ex_trap_c        /* 0x07 - User Defined */
-       .long _ex_trap_c        /* 0x08 - User Defined */
-       .long _ex_trap_c        /* 0x09 - User Defined */
-       .long _ex_trap_c        /* 0x0A - User Defined */
-       .long _ex_trap_c        /* 0x0B - User Defined */
-       .long _ex_trap_c        /* 0x0C - User Defined */
-       .long _ex_trap_c        /* 0x0D - User Defined */
-       .long _ex_trap_c        /* 0x0E - User Defined */
-       .long _ex_trap_c        /* 0x0F - User Defined */
+       .long _ex_trap_c        /* 0x04 - User Defined - dump trace buffer */
+       .long _ex_replaceable   /* 0x05 - User Defined */
+       .long _ex_replaceable   /* 0x06 - User Defined */
+       .long _ex_replaceable   /* 0x07 - User Defined */
+       .long _ex_replaceable   /* 0x08 - User Defined */
+       .long _ex_replaceable   /* 0x09 - User Defined */
+       .long _ex_replaceable   /* 0x0A - User Defined */
+       .long _ex_replaceable   /* 0x0B - User Defined */
+       .long _ex_replaceable   /* 0x0C - User Defined */
+       .long _ex_replaceable   /* 0x0D - User Defined */
+       .long _ex_replaceable   /* 0x0E - User Defined */
+       .long _ex_replaceable   /* 0x0F - User Defined */
        .long _ex_single_step   /* 0x10 - HW Single step */
+#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
+       .long _ex_trace_buff_full /* 0x11 - Trace Buffer Full */
+#else
        .long _ex_trap_c        /* 0x11 - Trace Buffer Full */
+#endif
        .long _ex_trap_c        /* 0x12 - Reserved */
        .long _ex_trap_c        /* 0x13 - Reserved */
        .long _ex_trap_c        /* 0x14 - Reserved */
@@ -812,8 +982,8 @@ _extable:
        .long _ex_trap_c        /* 0x3D - Reserved */
        .long _ex_trap_c        /* 0x3E - Reserved */
        .long _ex_trap_c        /* 0x3F - Reserved */
+END(_ex_table)
 
-ALIGN
 ENTRY(_sys_call_table)
        .long _sys_restart_syscall      /* 0 */
        .long _sys_exit
@@ -1184,7 +1354,7 @@ _exception_stack:
        .endr
 _exception_stack_top:
 
-#if defined(ANOMALY_05000261)
+#if ANOMALY_05000261
 /* Used by the assembly entry point to work around an anomaly.  */
 _last_cplb_fault_retx:
        .long 0;