sh: nmi_debug support.
[linux-block.git] / arch / sh / kernel / cpu / sh3 / entry.S
index 55da0ff9848db392297c05d12773452c74bf1793..d1142d36592529ba0e9088fc1c5b5979721b7eea 100644 (file)
@@ -113,34 +113,34 @@ OFF_TRA   =  (16*4+6*4)
 #if defined(CONFIG_MMU)
        .align  2
 ENTRY(tlb_miss_load)
-       bra     call_dpf
+       bra     call_handle_tlbmiss
         mov    #0, r5
 
        .align  2
 ENTRY(tlb_miss_store)
-       bra     call_dpf
+       bra     call_handle_tlbmiss
         mov    #1, r5
 
        .align  2
 ENTRY(initial_page_write)
-       bra     call_dpf
-        mov    #1, r5
+       bra     call_handle_tlbmiss
+        mov    #2, r5
 
        .align  2
 ENTRY(tlb_protection_violation_load)
-       bra     call_dpf
+       bra     call_do_page_fault
         mov    #0, r5
 
        .align  2
 ENTRY(tlb_protection_violation_store)
-       bra     call_dpf
+       bra     call_do_page_fault
         mov    #1, r5
 
-call_dpf:
+call_handle_tlbmiss:
+       setup_frame_reg
        mov.l   1f, r0
        mov     r5, r8
        mov.l   @r0, r6
-       mov     r6, r9
        mov.l   2f, r0
        sts     pr, r10
        jsr     @r0
@@ -151,16 +151,25 @@ call_dpf:
         lds    r10, pr
        rts
         nop
-0:     mov.l   3f, r0
-       mov     r9, r6
+0:
        mov     r8, r5
+call_do_page_fault:
+       mov.l   1f, r0
+       mov.l   @r0, r6
+
+       sti
+
+       mov.l   3f, r0
+       mov.l   4f, r1
+       mov     r15, r4
        jmp     @r0
-        mov    r15, r4
+        lds    r1, pr
 
        .align 2
 1:     .long   MMU_TEA
-2:     .long   __do_page_fault
+2:     .long   handle_tlbmiss
 3:     .long   do_page_fault
+4:     .long   ret_from_exception
 
        .align  2
 ENTRY(address_error_load)
@@ -254,43 +263,9 @@ restore_all:
 
        lds     k2, pr                  ! restore pr
        !
-#ifdef CONFIG_SH_DSP
-       mov.l   @r15+, k0               ! DSP mode marker
-       mov.l   5f, k1
-       cmp/eq  k0, k1                  ! Do we have a DSP stack frame?
-       bf      skip_restore
-
-       stc     sr, k0                  ! Enable CPU DSP mode
-       or      k1, k0                  ! (within kernel it may be disabled)
-       ldc     k0, sr
-       mov     r2, k0                  ! Backup r2
-
-       ! Restore DSP registers from stack
-       mov     r15, r2
-       movs.l  @r2+, a1
-       movs.l  @r2+, a0g
-       movs.l  @r2+, a1g
-       movs.l  @r2+, m0
-       movs.l  @r2+, m1
-       mov     r2, r15
-
-       lds.l   @r15+, a0
-       lds.l   @r15+, x0
-       lds.l   @r15+, x1
-       lds.l   @r15+, y0
-       lds.l   @r15+, y1
-       lds.l   @r15+, dsr
-       ldc.l   @r15+, rs
-       ldc.l   @r15+, re
-       ldc.l   @r15+, mod
-
-       mov     k0, r2                  ! Restore r2
-skip_restore:
-#endif
-       !
        ! Calculate new SR value
        mov     k3, k2                  ! original SR value
-       mov     #0xf0, k1
+       mov     #0xfffffff0, k1
        extu.b  k1, k1
        not     k1, k1
        and     k1, k2                  ! Mask original SR value
@@ -358,7 +333,7 @@ general_exception:
        add     k0, k4
 0:
        ! Setup stack and save DSP context (k0 contains original r15 on return)
-       bsr     prepare_stack_save_dsp
+       bsr     prepare_stack
         nop
 
        ! Save registers / Switch to bank 0
@@ -374,15 +349,14 @@ general_exception:
 1:     .long   EXPEVT
 #endif
 
-! prepare_stack_save_dsp()
+! prepare_stack()
 ! - roll back gRB
 ! - switch to kernel stack
-! - save DSP
 ! k0 returns original sp (after roll back)
 ! k1 trashed
 ! k2 trashed
 
-prepare_stack_save_dsp:
+prepare_stack:
 #ifdef CONFIG_GUSA
        ! Check for roll back gRB (User and Kernel)
        mov     r15, k0
@@ -416,47 +390,9 @@ prepare_stack_save_dsp:
        mov     k1, r15         ! change to kernel stack
        !
 1:
-#ifdef CONFIG_SH_DSP
-       ! Save DSP context if needed
-       stc     sr, k1
-       mov     #0x10, k2
-       shll8   k2                      ! DSP=1 (0x00001000)
-       tst     k2, k1                  ! Check if in DSP mode (passed in k2)
-       bt/s    skip_save
-        mov    #0, k1                  ! Set marker for no stack frame
-
-       mov     k2, k1                  ! Save has-frame marker
-
-       ! Save DSP registers on stack
-       stc.l   mod, @-r15
-       stc.l   re, @-r15
-       stc.l   rs, @-r15
-       sts.l   dsr, @-r15
-       sts.l   y1, @-r15
-       sts.l   y0, @-r15
-       sts.l   x1, @-r15
-       sts.l   x0, @-r15
-       sts.l   a0, @-r15
-
-       ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr.
-
-       ! FIXME: Make sure that this is still the case with newer toolchains,
-       ! as we're not at all interested in supporting ancient toolchains at
-       ! this point. -- PFM.
-
-       mov     r15, k2
-       .word   0xf653                  ! movs.l        a1, @-r2
-       .word   0xf6f3                  ! movs.l        a0g, @-r2
-       .word   0xf6d3                  ! movs.l        a1g, @-r2
-       .word   0xf6c3                  ! movs.l        m0, @-r2
-       .word   0xf6e3                  ! movs.l        m1, @-r2
-       mov     k2, r15
-
-skip_save:
-       mov.l   k1, @-r15               ! Push DSP mode marker onto stack
-#endif
        rts
         nop
+
 !
 ! 0x400: Instruction and Data TLB miss exception vector
 !
@@ -468,7 +404,7 @@ handle_exception:
        mova    exception_data, k0
 
        ! Setup stack and save DSP context (k0 contains original r15 on return)
-       bsr     prepare_stack_save_dsp
+       bsr     prepare_stack
         PREF(k0)
 
        ! Save registers / Switch to bank 0
@@ -572,7 +508,7 @@ ENTRY(handle_interrupt)
        mova    exception_data, k0
 
        ! Setup stack and save DSP context (k0 contains original r15 on return)
-       bsr     prepare_stack_save_dsp
+       bsr     prepare_stack
         PREF(k0)
 
        ! Save registers / Switch to bank 0
@@ -580,13 +516,49 @@ ENTRY(handle_interrupt)
        bsr     save_regs       ! needs original pr value in k3
         mov    #-1, k2         ! default vector kept in k2
 
+       setup_frame_reg
+
+       stc     sr, r0  ! get status register
+       shlr2   r0
+       and     #0x3c, r0
+       cmp/eq  #0x3c, r0
+       bf      9f
+       TRACE_IRQS_OFF
+9:
+
        ! Setup return address and jump to do_IRQ
        mov.l   4f, r9          ! fetch return address
        lds     r9, pr          ! put return address in pr
        mov.l   2f, r4
        mov.l   3f, r9
        mov.l   @r4, r4         ! pass INTEVT vector as arg0
+
+       shlr2   r4
+       shlr    r4
+       mov     r4, r0          ! save vector->jmp table offset for later
+
+       shlr2   r4              ! vector to IRQ# conversion
+       add     #-0x10, r4
+
+       cmp/pz  r4              ! is it a valid IRQ?
+       bt      10f
+
+       /*
+        * We got here as a result of taking the INTEVT path for something
+        * that isn't a valid hard IRQ, therefore we bypass the do_IRQ()
+        * path and special case the event dispatch instead.  This is the
+        * expected path for the NMI (and any other brilliantly implemented
+        * exception), which effectively wants regular exception dispatch
+        * but is unfortunately reported through INTEVT rather than
+        * EXPEVT.  Grr.
+        */
+       mov.l   6f, r9
+       mov.l   @(r0, r9), r9
        jmp     @r9
+        mov    r15, r8         ! trap handlers take saved regs in r8
+
+10:
+       jmp     @r9             ! Off to do_IRQ() we go.
         mov    r15, r5         ! pass saved registers as arg1
 
 ENTRY(exception_none)