Back to home page

LXR

 
 

    


0001 /*
0002  * arch/sh/kernel/cpu/sh2/entry.S
0003  *
0004  * The SH-2 exception entry
0005  *
0006  * Copyright (C) 2005-2008 Yoshinori Sato
0007  * Copyright (C) 2005  AXE,Inc.
0008  *
0009  * This file is subject to the terms and conditions of the GNU General Public
0010  * License.  See the file "COPYING" in the main directory of this archive
0011  * for more details.
0012  */
0013 
0014 #include <linux/linkage.h>
0015 #include <asm/asm-offsets.h>
0016 #include <asm/thread_info.h>
0017 #include <cpu/mmu_context.h>
0018 #include <asm/unistd.h>
0019 #include <asm/errno.h>
0020 #include <asm/page.h>
0021     
0022 /* Offsets to the stack */
0023 OFF_R0  =  0        /* Return value. New ABI also arg4 */
0024 OFF_R1  =  4        /* New ABI: arg5 */
0025 OFF_R2  =  8        /* New ABI: arg6 */
0026 OFF_R3  =  12       /* New ABI: syscall_nr */
0027 OFF_R4  =  16       /* New ABI: arg0 */
0028 OFF_R5  =  20       /* New ABI: arg1 */
0029 OFF_R6  =  24       /* New ABI: arg2 */
0030 OFF_R7  =  28       /* New ABI: arg3 */
0031 OFF_SP  =  (15*4)
0032 OFF_PC  =  (16*4)
0033 OFF_SR  =  (16*4+2*4)
0034 OFF_TRA =  (16*4+6*4)
0035 
0036 #include <asm/entry-macros.S>
0037 
0038 ENTRY(exception_handler)
0039     ! stack
0040     ! r0 <- point sp
0041     ! r1
0042     ! pc
0043     ! sr
0044     ! r0 = temporary
0045     ! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
0046     mov.l   r2,@-sp
0047     mov.l   r3,@-sp
0048     cli
0049     mov.l   $cpu_mode,r2
0050 #ifdef CONFIG_SMP
0051     mov.l   $cpuid,r3
0052     mov.l   @r3,r3
0053     mov.l   @r3,r3
0054     shll2   r3
0055     add r3,r2
0056 #endif
0057     mov.l   @r2,r0
0058     mov.l   @(5*4,r15),r3   ! previous SR
0059     or  r0,r3       ! set MD
0060     tst r0,r0
0061     bf/s    1f      ! previous mode check
0062      mov.l  r3,@(5*4,r15)   ! update SR
0063     ! switch to kernel mode
0064     mov.l   __md_bit,r0
0065     mov.l   r0,@r2      ! enter kernel mode
0066     mov.l   $current_thread_info,r2
0067 #ifdef CONFIG_SMP
0068     mov.l   $cpuid,r0
0069     mov.l   @r0,r0
0070     mov.l   @r0,r0
0071     shll2   r0
0072     add r0,r2
0073 #endif
0074     mov.l   @r2,r2
0075     mov #(THREAD_SIZE >> 8),r0
0076     shll8   r0
0077     add r2,r0
0078     mov r15,r2      ! r2 = user stack top
0079     mov r0,r15      ! switch kernel stack
0080     mov.l   r1,@-r15    ! TRA
0081     sts.l   macl, @-r15
0082     sts.l   mach, @-r15
0083     stc.l   gbr, @-r15
0084     mov.l   @(5*4,r2),r0
0085     mov.l   r0,@-r15    ! original SR
0086     sts.l   pr,@-r15
0087     mov.l   @(4*4,r2),r0
0088     mov.l   r0,@-r15    ! original PC
0089     mov r2,r3
0090     add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame
0091     mov.l   r3,@-r15    ! original SP
0092     mov.l   r14,@-r15
0093     mov.l   r13,@-r15
0094     mov.l   r12,@-r15
0095     mov.l   r11,@-r15
0096     mov.l   r10,@-r15
0097     mov.l   r9,@-r15
0098     mov.l   r8,@-r15
0099     mov.l   r7,@-r15
0100     mov.l   r6,@-r15
0101     mov.l   r5,@-r15
0102     mov.l   r4,@-r15
0103     mov r1,r9       ! save TRA
0104     mov r2,r8       ! copy user -> kernel stack
0105     mov.l   @(0,r8),r3
0106     mov.l   r3,@-r15
0107     mov.l   @(4,r8),r2
0108     mov.l   r2,@-r15
0109     mov.l   @(12,r8),r1
0110     mov.l   r1,@-r15
0111     mov.l   @(8,r8),r0
0112     bra 2f
0113      mov.l  r0,@-r15
0114 1:
0115     ! in kernel exception
0116     mov #(22-4-4-1)*4+4,r0
0117     mov r15,r2
0118     sub r0,r15
0119     mov.l   @r2+,r0     ! old R3
0120     mov.l   r0,@-r15    
0121     mov.l   @r2+,r0     ! old R2
0122     mov.l   r0,@-r15    
0123     mov.l   @(4,r2),r0  ! old R1
0124     mov.l   r0,@-r15    
0125     mov.l   @r2,r0      ! old R0
0126     mov.l   r0,@-r15
0127     add #8,r2
0128     mov.l   @r2+,r3     ! old PC
0129     mov.l   @r2+,r0     ! old SR
0130     add #-4,r2      ! exception frame stub (sr)
0131     mov.l   r1,@-r2     ! TRA
0132     sts.l   macl, @-r2
0133     sts.l   mach, @-r2
0134     stc.l   gbr, @-r2
0135     mov.l   r0,@-r2     ! save old SR
0136     sts.l   pr,@-r2
0137     mov.l   r3,@-r2     ! save old PC
0138     mov r2,r0
0139     add #8*4,r0
0140     mov.l   r0,@-r2     ! save old SP
0141     mov.l   r14,@-r2
0142     mov.l   r13,@-r2
0143     mov.l   r12,@-r2
0144     mov.l   r11,@-r2
0145     mov.l   r10,@-r2
0146     mov.l   r9,@-r2
0147     mov.l   r8,@-r2
0148     mov.l   r7,@-r2
0149     mov.l   r6,@-r2
0150     mov.l   r5,@-r2
0151     mov.l   r4,@-r2
0152     mov r1,r9
0153     mov.l   @(OFF_R0,r15),r0
0154     mov.l   @(OFF_R1,r15),r1
0155     mov.l   @(OFF_R2,r15),r2
0156     mov.l   @(OFF_R3,r15),r3
0157 2:
0158     mov #64,r8
0159     cmp/hs  r8,r9
0160     bt  interrupt_entry ! vec >= 64 is interrupt
0161     mov #31,r8
0162     cmp/hs  r8,r9
0163     bt  trap_entry  ! 64 > vec >= 31  is trap
0164 #ifdef CONFIG_CPU_J2
0165     mov #16,r8
0166     cmp/hs  r8,r9
0167     bt  interrupt_entry ! 31 > vec >= 16 is interrupt
0168 #endif
0169 
0170     mov.l   4f,r8
0171     mov r9,r4
0172     shll2   r9
0173     add r9,r8
0174     mov.l   @r8,r8      ! exception handler address
0175     tst r8,r8
0176     bf  3f
0177     mov.l   8f,r8       ! unhandled exception
0178 3:
0179     mov.l   5f,r10
0180     jmp @r8
0181      lds    r10,pr
0182 
0183 interrupt_entry:
0184     mov r9,r4
0185     mov r15,r5
0186     mov.l   6f,r9
0187     mov.l   7f,r8
0188     jmp @r8
0189      lds    r9,pr
0190 
0191     .align  2
0192 4:  .long   exception_handling_table
0193 5:  .long   ret_from_exception
0194 6:  .long   ret_from_irq
0195 7:  .long   do_IRQ
0196 8:  .long   exception_error
0197 
0198 trap_entry:
0199     mov #0x30,r8
0200     cmp/ge  r8,r9       ! vector 0x1f-0x2f is systemcall
0201     bt  1f
0202     mov     #0x1f,r9    ! convert to unified SH2/3/4 trap number
0203 1:  
0204     shll2   r9          ! TRA
0205     bra system_call ! jump common systemcall entry
0206      mov    r9,r8
0207     
0208 #if defined(CONFIG_SH_STANDARD_BIOS)
0209     /* Unwind the stack and jmp to the debug entry */
0210 ENTRY(sh_bios_handler)
0211     mov r15,r0
0212     add #(22-4)*4-4,r0
0213     ldc.l   @r0+,gbr
0214     lds.l   @r0+,mach
0215     lds.l   @r0+,macl
0216     mov r15,r0
0217     mov.l   @(OFF_SP,r0),r1
0218     mov #OFF_SR,r2
0219     mov.l   @(r0,r2),r3
0220     mov.l   r3,@-r1
0221     mov #OFF_SP,r2
0222     mov.l   @(r0,r2),r3
0223     mov.l   r3,@-r1
0224     mov r15,r0
0225     add #(22-4)*4-8,r0
0226     mov.l   1f,r2
0227     mov.l   @r2,r2
0228     stc sr,r3
0229     mov.l   r2,@r0
0230     mov.l   r3,@(4,r0)
0231     mov.l   r1,@(8,r0)  
0232     mov.l   @r15+, r0
0233     mov.l   @r15+, r1
0234     mov.l   @r15+, r2
0235     mov.l   @r15+, r3
0236     mov.l   @r15+, r4
0237     mov.l   @r15+, r5
0238     mov.l   @r15+, r6
0239     mov.l   @r15+, r7
0240     mov.l   @r15+, r8
0241     mov.l   @r15+, r9
0242     mov.l   @r15+, r10
0243     mov.l   @r15+, r11
0244     mov.l   @r15+, r12
0245     mov.l   @r15+, r13
0246     mov.l   @r15+, r14
0247     add #8,r15
0248     lds.l   @r15+, pr
0249     mov.l   @r15+,r15
0250     rte
0251      nop
0252     .align  2
0253 1:  .long   gdb_vbr_vector
0254 #endif /* CONFIG_SH_STANDARD_BIOS */
0255 
0256 ENTRY(address_error_trap_handler)
0257     mov r15,r4              ! regs
0258     mov #OFF_PC,r0
0259     mov.l   @(r0,r15),r6            ! pc
0260     mov.l   1f,r0
0261     jmp @r0
0262      mov    #0,r5               ! writeaccess is unknown
0263 
0264     .align  2
0265 1:  .long   do_address_error
0266 
0267 restore_all:
0268     stc sr,r0
0269     or  #0xf0,r0
0270     ldc r0,sr               ! all interrupt block (same BL = 1)
0271     ! restore special register
0272     ! overlap exception frame
0273     mov r15,r0
0274     add #17*4,r0
0275     lds.l   @r0+,pr
0276     add #4,r0
0277     ldc.l   @r0+,gbr
0278     lds.l   @r0+,mach
0279     lds.l   @r0+,macl
0280     mov r15,r0
0281     mov.l   $cpu_mode,r2
0282 #ifdef CONFIG_SMP
0283     mov.l   $cpuid,r3
0284     mov.l   @r3,r3
0285     mov.l   @r3,r3
0286     shll2   r3
0287     add r3,r2
0288 #endif
0289     mov #OFF_SR,r3
0290     mov.l   @(r0,r3),r1
0291     mov.l   __md_bit,r3
0292     and r1,r3               ! copy MD bit
0293     mov.l   r3,@r2
0294     shll2   r1              ! clear MD bit
0295     shlr2   r1
0296     mov.l   @(OFF_SP,r0),r2
0297     add #-8,r2
0298     mov.l   r2,@(OFF_SP,r0)         ! point exception frame top
0299     mov.l   r1,@(4,r2)          ! set sr
0300     mov #OFF_PC,r3
0301     mov.l   @(r0,r3),r1
0302     mov.l   r1,@r2              ! set pc
0303     get_current_thread_info r0, r1
0304     mov.l   $current_thread_info,r1
0305 #ifdef CONFIG_SMP
0306     mov.l   $cpuid,r3
0307     mov.l   @r3,r3
0308     mov.l   @r3,r3
0309     shll2   r3
0310     add r3,r1
0311 #endif
0312     mov.l   r0,@r1
0313     mov.l   @r15+,r0
0314     mov.l   @r15+,r1
0315     mov.l   @r15+,r2
0316     mov.l   @r15+,r3
0317     mov.l   @r15+,r4
0318     mov.l   @r15+,r5
0319     mov.l   @r15+,r6
0320     mov.l   @r15+,r7
0321     mov.l   @r15+,r8
0322     mov.l   @r15+,r9
0323     mov.l   @r15+,r10
0324     mov.l   @r15+,r11
0325     mov.l   @r15+,r12
0326     mov.l   @r15+,r13
0327     mov.l   @r15+,r14
0328     mov.l   @r15,r15
0329     rte
0330      nop
0331 
0332     .align 2
0333 __md_bit:
0334     .long   0x40000000
0335 $current_thread_info:
0336     .long   __current_thread_info
0337 $cpu_mode:  
0338     .long   __cpu_mode
0339 #ifdef CONFIG_SMP
0340 $cpuid:
0341     .long sh2_cpuid_addr
0342 #endif
0343         
0344 ! common exception handler
0345 #include "../../entry-common.S"
0346 
0347 #ifdef CONFIG_NR_CPUS
0348 #define NR_CPUS CONFIG_NR_CPUS
0349 #else
0350 #define NR_CPUS 1
0351 #endif
0352     
0353     .data
0354 ! cpu operation mode 
0355 ! bit30 = MD (compatible SH3/4)
0356 __cpu_mode:
0357     .rept   NR_CPUS
0358     .long   0x40000000
0359     .endr
0360 
0361 #ifdef CONFIG_SMP
0362 .global sh2_cpuid_addr
0363 sh2_cpuid_addr:
0364     .long   dummy_cpuid
0365 dummy_cpuid:
0366     .long   0
0367 #endif
0368         
0369     .section    .bss
0370 __current_thread_info:
0371     .rept   NR_CPUS
0372     .long   0
0373     .endr
0374 
0375 ENTRY(exception_handling_table)
0376     .space  4*32