Merge ../linux-2.6-watchdog-mm
[linux-drm-fsl-dcu.git] / arch / sh / kernel / entry.S
index fe8221855b282648f25472cd64286814728f7843..39aaefb2d83f427d58a0b05ad48a45868dfba2e2 100644 (file)
@@ -1,17 +1,16 @@
-/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
- *
+/*
  *  linux/arch/sh/entry.S
  *
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- *  Copyright (C) 2003  Paul Mundt
+ *  Copyright (C) 2003 - 2006  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  */
-
 #include <linux/sys.h>
+#include <linux/errno.h>
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
  *     syscall #
  *
  */
-
-ENOSYS = 38
-EINVAL = 22
-
 #if defined(CONFIG_KGDB_NMI)
 NMI_VEC = 0x1c0                        ! Must catch early for debounce
 #endif
@@ -82,7 +77,6 @@ OFF_TRA       =  (16*4+6*4)
 #define k3     r3
 #define k4     r4
 
-#define k_ex_code      r2_bank /* r2_bank1 */
 #define g_imask                r6      /* r6_bank1 */
 #define k_g_imask      r6_bank /* r6_bank1 */
 #define current                r7      /* r7_bank1 */
@@ -695,7 +689,7 @@ interrupt:
 0:
 #endif /* defined(CONFIG_KGDB_NMI) */
        bra     handle_exception
-        mov.l  @k2, k2
+        mov    #-1, k2         ! interrupt exception marker
 
        .align  2
 1:     .long   EXPEVT
@@ -721,8 +715,7 @@ ENTRY(handle_exception)
        add     current, k1
        mov     k1, r15         ! change to kernel stack
        !
-1:     mov     #-1, k4
-       mov.l   2f, k1
+1:     mov.l   2f, k1
        !
 #ifdef CONFIG_SH_DSP
        mov.l   r2, @-r15               ! Save r2, we need another reg
@@ -767,6 +760,8 @@ skip_save:
 #endif
        ! Save the user registers on the stack.
        mov.l   k2, @-r15       ! EXPEVT
+
+       mov     #-1, k4
        mov.l   k4, @-r15       ! set TRA (default: -1)
        !
        sts.l   macl, @-r15
@@ -801,8 +796,21 @@ skip_save:
        mov.l   r2, @-r15
        mov.l   r1, @-r15
        mov.l   r0, @-r15
-       ! Then, dispatch to the handler, according to the exception code.
-       stc     k_ex_code, r8
+
+       /*
+        * This gets a bit tricky.. in the INTEVT case we don't want to use
+        * the VBR offset as a destination in the jump call table, since all
+        * of the destinations are the same. In this case, (interrupt) sets
+        * a marker in r2 (now r2_bank since SR.RB changed), which we check
+        * to determine the exception type. For all other exceptions, we
+        * forcibly read EXPEVT from memory and fix up the jump address, in
+        * the interrupt exception case we jump to do_IRQ() and defer the
+        * INTEVT read until there. As a bonus, we can also clean up the SR.RB
+        * checks that do_IRQ() was doing..
+        */
+       stc     r2_bank, r8
+       cmp/pz  r8
+       bf      interrupt_exception
        shlr2   r8
        shlr    r8
        mov.l   4f, r9
@@ -810,6 +818,8 @@ skip_save:
        mov.l   @r9, r9
        jmp     @r9
         nop
+       rts
+        nop
 
        .align  2
 1:     .long   0x00001000      ! DSP=1
@@ -817,8 +827,17 @@ skip_save:
 3:     .long   0xcfffffff      ! RB=0, BL=0
 4:     .long   exception_handling_table
 
+interrupt_exception:
+       mov.l   1f, r9
+       jmp     @r9
+        nop
+       rts
+        nop
+
+       .align 2
+1:     .long   do_IRQ
+
        .align  2
 ENTRY(exception_none)
        rts
         nop
-