Back to home page

LXR

 
 

    


0001 /* -*- mode: asm -*-
0002  *
0003  *  linux/arch/m68k/kernel/entry.S
0004  *
0005  *  Copyright (C) 1991, 1992  Linus Torvalds
0006  *
0007  * This file is subject to the terms and conditions of the GNU General Public
0008  * License.  See the file README.legal in the main directory of this archive
0009  * for more details.
0010  *
0011  * Linux/m68k support by Hamish Macdonald
0012  *
0013  * 68060 fixes by Jesper Skov
0014  *
0015  */
0016 
0017 /*
0018  * entry.S  contains the system-call and fault low-level handling routines.
0019  * This also contains the timer-interrupt handler, as well as all interrupts
0020  * and faults that can result in a task-switch.
0021  *
0022  * NOTE: This code handles signal-recognition, which happens every time
0023  * after a timer-interrupt and after each system call.
0024  *
0025  */
0026 
0027 /*
0028  * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
0029  *               all pointers that used to be 'current' are now entry
0030  *               number 0 in the 'current_set' list.
0031  *
0032  *  6/05/00 RZ:  addedd writeback completion after return from sighandler
0033  *       for 68040
0034  */
0035 
0036 #include <linux/linkage.h>
0037 #include <asm/errno.h>
0038 #include <asm/setup.h>
0039 #include <asm/segment.h>
0040 #include <asm/traps.h>
0041 #include <asm/unistd.h>
0042 #include <asm/asm-offsets.h>
0043 #include <asm/entry.h>
0044 
0045 .globl system_call, buserr, trap, resume
0046 .globl sys_call_table
0047 .globl __sys_fork, __sys_clone, __sys_vfork
0048 .globl bad_interrupt
0049 .globl auto_irqhandler_fixup
0050 .globl user_irqvec_fixup
0051 
0052 .text
0053 ENTRY(__sys_fork)
0054     SAVE_SWITCH_STACK
0055     jbsr    sys_fork
0056     lea     %sp@(24),%sp
0057     rts
0058 
0059 ENTRY(__sys_clone)
0060     SAVE_SWITCH_STACK
0061     pea %sp@(SWITCH_STACK_SIZE)
0062     jbsr    m68k_clone
0063     lea     %sp@(28),%sp
0064     rts
0065 
0066 ENTRY(__sys_vfork)
0067     SAVE_SWITCH_STACK
0068     jbsr    sys_vfork
0069     lea     %sp@(24),%sp
0070     rts
0071 
0072 ENTRY(sys_sigreturn)
0073     SAVE_SWITCH_STACK
0074     movel   %sp,%sp@-         | switch_stack pointer
0075     pea %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer
0076     jbsr    do_sigreturn
0077     addql   #8,%sp
0078     RESTORE_SWITCH_STACK
0079     rts
0080 
0081 ENTRY(sys_rt_sigreturn)
0082     SAVE_SWITCH_STACK
0083     movel   %sp,%sp@-         | switch_stack pointer
0084     pea %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer
0085     jbsr    do_rt_sigreturn
0086     addql   #8,%sp
0087     RESTORE_SWITCH_STACK
0088     rts
0089 
0090 ENTRY(buserr)
0091     SAVE_ALL_INT
0092     GET_CURRENT(%d0)
0093     movel   %sp,%sp@-       | stack frame pointer argument
0094     jbsr    buserr_c
0095     addql   #4,%sp
0096     jra ret_from_exception
0097 
0098 ENTRY(trap)
0099     SAVE_ALL_INT
0100     GET_CURRENT(%d0)
0101     movel   %sp,%sp@-       | stack frame pointer argument
0102     jbsr    trap_c
0103     addql   #4,%sp
0104     jra ret_from_exception
0105 
0106     | After a fork we jump here directly from resume,
0107     | so that %d1 contains the previous task
0108     | schedule_tail now used regardless of CONFIG_SMP
0109 ENTRY(ret_from_fork)
0110     movel   %d1,%sp@-
0111     jsr schedule_tail
0112     addql   #4,%sp
0113     jra ret_from_exception
0114 
0115 ENTRY(ret_from_kernel_thread)
0116     | a3 contains the kernel thread payload, d7 - its argument
0117     movel   %d1,%sp@-
0118     jsr schedule_tail
0119     movel   %d7,(%sp)
0120     jsr %a3@
0121     addql   #4,%sp
0122     jra ret_from_exception
0123 
0124 #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
0125 
0126 #ifdef TRAP_DBG_INTERRUPT
0127 
0128 .globl dbginterrupt
0129 ENTRY(dbginterrupt)
0130     SAVE_ALL_INT
0131     GET_CURRENT(%d0)
0132     movel   %sp,%sp@-       /* stack frame pointer argument */
0133     jsr dbginterrupt_c
0134     addql   #4,%sp
0135     jra ret_from_exception
0136 #endif
0137 
0138 ENTRY(reschedule)
0139     /* save top of frame */
0140     pea %sp@
0141     jbsr    set_esp0
0142     addql   #4,%sp
0143     pea ret_from_exception
0144     jmp schedule
0145 
0146 ENTRY(ret_from_user_signal)
0147     moveq #__NR_sigreturn,%d0
0148     trap #0
0149 
0150 ENTRY(ret_from_user_rt_signal)
0151     movel #__NR_rt_sigreturn,%d0
0152     trap #0
0153 
0154 #else
0155 
0156 do_trace_entry:
0157     movel   #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
0158     subql   #4,%sp
0159     SAVE_SWITCH_STACK
0160     jbsr    syscall_trace
0161     RESTORE_SWITCH_STACK
0162     addql   #4,%sp
0163     movel   %sp@(PT_OFF_ORIG_D0),%d0
0164     cmpl    #NR_syscalls,%d0
0165     jcs syscall
0166 badsys:
0167     movel   #-ENOSYS,%sp@(PT_OFF_D0)
0168     jra ret_from_syscall
0169 
0170 do_trace_exit:
0171     subql   #4,%sp
0172     SAVE_SWITCH_STACK
0173     jbsr    syscall_trace
0174     RESTORE_SWITCH_STACK
0175     addql   #4,%sp
0176     jra .Lret_from_exception
0177 
0178 ENTRY(ret_from_signal)
0179     movel   %curptr@(TASK_STACK),%a1
0180     tstb    %a1@(TINFO_FLAGS+2)
0181     jge 1f
0182     jbsr    syscall_trace
0183 1:  RESTORE_SWITCH_STACK
0184     addql   #4,%sp
0185 /* on 68040 complete pending writebacks if any */
0186 #ifdef CONFIG_M68040
0187     bfextu  %sp@(PT_OFF_FORMATVEC){#0,#4},%d0
0188     subql   #7,%d0              | bus error frame ?
0189     jbne    1f
0190     movel   %sp,%sp@-
0191     jbsr    berr_040cleanup
0192     addql   #4,%sp
0193 1:
0194 #endif
0195     jra .Lret_from_exception
0196 
0197 ENTRY(system_call)
0198     SAVE_ALL_SYS
0199 
0200     GET_CURRENT(%d1)
0201     movel   %d1,%a1
0202 
0203     | save top of frame
0204     movel   %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
0205 
0206     | syscall trace?
0207     tstb    %a1@(TINFO_FLAGS+2)
0208     jmi do_trace_entry
0209     cmpl    #NR_syscalls,%d0
0210     jcc badsys
0211 syscall:
0212     jbsr    @(sys_call_table,%d0:l:4)@(0)
0213     movel   %d0,%sp@(PT_OFF_D0) | save the return value
0214 ret_from_syscall:
0215     |oriw   #0x0700,%sr
0216     movel   %curptr@(TASK_STACK),%a1
0217     movew   %a1@(TINFO_FLAGS+2),%d0
0218     jne syscall_exit_work
0219 1:  RESTORE_ALL
0220 
0221 syscall_exit_work:
0222     btst    #5,%sp@(PT_OFF_SR)  | check if returning to kernel
0223     bnes    1b          | if so, skip resched, signals
0224     lslw    #1,%d0
0225     jcs do_trace_exit
0226     jmi do_delayed_trace
0227     lslw    #8,%d0
0228     jne do_signal_return
0229     pea resume_userspace
0230     jra schedule
0231 
0232 
0233 ENTRY(ret_from_exception)
0234 .Lret_from_exception:
0235     btst    #5,%sp@(PT_OFF_SR)  | check if returning to kernel
0236     bnes    1f          | if so, skip resched, signals
0237     | only allow interrupts when we are really the last one on the
0238     | kernel stack, otherwise stack overflow can occur during
0239     | heavy interrupt load
0240     andw    #ALLOWINT,%sr
0241 
0242 resume_userspace:
0243     movel   %curptr@(TASK_STACK),%a1
0244     moveb   %a1@(TINFO_FLAGS+3),%d0
0245     jne exit_work
0246 1:  RESTORE_ALL
0247 
0248 exit_work:
0249     | save top of frame
0250     movel   %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
0251     lslb    #1,%d0
0252     jne do_signal_return
0253     pea resume_userspace
0254     jra schedule
0255 
0256 
0257 do_signal_return:
0258     |andw   #ALLOWINT,%sr
0259     subql   #4,%sp          | dummy return address
0260     SAVE_SWITCH_STACK
0261     pea %sp@(SWITCH_STACK_SIZE)
0262     bsrl    do_notify_resume
0263     addql   #4,%sp
0264     RESTORE_SWITCH_STACK
0265     addql   #4,%sp
0266     jbra    resume_userspace
0267 
0268 do_delayed_trace:
0269     bclr    #7,%sp@(PT_OFF_SR)  | clear trace bit in SR
0270     pea 1           | send SIGTRAP
0271     movel   %curptr,%sp@-
0272     pea LSIGTRAP
0273     jbsr    send_sig
0274     addql   #8,%sp
0275     addql   #4,%sp
0276     jbra    resume_userspace
0277 
0278 
0279 /* This is the main interrupt handler for autovector interrupts */
0280 
0281 ENTRY(auto_inthandler)
0282     SAVE_ALL_INT
0283     GET_CURRENT(%d0)
0284                     |  put exception # in d0
0285     bfextu  %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
0286     subw    #VEC_SPUR,%d0
0287 
0288     movel   %sp,%sp@-
0289     movel   %d0,%sp@-       |  put vector # on stack
0290 auto_irqhandler_fixup = . + 2
0291     jsr do_IRQ          |  process the IRQ
0292     addql   #8,%sp          |  pop parameters off stack
0293     jra ret_from_exception
0294 
0295 /* Handler for user defined interrupt vectors */
0296 
0297 ENTRY(user_inthandler)
0298     SAVE_ALL_INT
0299     GET_CURRENT(%d0)
0300                     |  put exception # in d0
0301     bfextu  %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
0302 user_irqvec_fixup = . + 2
0303     subw    #VEC_USER,%d0
0304 
0305     movel   %sp,%sp@-
0306     movel   %d0,%sp@-       |  put vector # on stack
0307     jsr do_IRQ          |  process the IRQ
0308     addql   #8,%sp          |  pop parameters off stack
0309     jra ret_from_exception
0310 
0311 /* Handler for uninitialized and spurious interrupts */
0312 
0313 ENTRY(bad_inthandler)
0314     SAVE_ALL_INT
0315     GET_CURRENT(%d0)
0316 
0317     movel   %sp,%sp@-
0318     jsr handle_badint
0319     addql   #4,%sp
0320     jra ret_from_exception
0321 
0322 resume:
0323     /*
0324      * Beware - when entering resume, prev (the current task) is
0325      * in a0, next (the new task) is in a1,so don't change these
0326      * registers until their contents are no longer needed.
0327      */
0328 
0329     /* save sr */
0330     movew   %sr,%a0@(TASK_THREAD+THREAD_SR)
0331 
0332     /* save fs (sfc,%dfc) (may be pointing to kernel memory) */
0333     movec   %sfc,%d0
0334     movew   %d0,%a0@(TASK_THREAD+THREAD_FS)
0335 
0336     /* save usp */
0337     /* it is better to use a movel here instead of a movew 8*) */
0338     movec   %usp,%d0
0339     movel   %d0,%a0@(TASK_THREAD+THREAD_USP)
0340 
0341     /* save non-scratch registers on stack */
0342     SAVE_SWITCH_STACK
0343 
0344     /* save current kernel stack pointer */
0345     movel   %sp,%a0@(TASK_THREAD+THREAD_KSP)
0346 
0347     /* save floating point context */
0348 #ifndef CONFIG_M68KFPU_EMU_ONLY
0349 #ifdef CONFIG_M68KFPU_EMU
0350     tstl    m68k_fputype
0351     jeq 3f
0352 #endif
0353     fsave   %a0@(TASK_THREAD+THREAD_FPSTATE)
0354 
0355 #if defined(CONFIG_M68060)
0356 #if !defined(CPU_M68060_ONLY)
0357     btst    #3,m68k_cputype+3
0358     beqs    1f
0359 #endif
0360     /* The 060 FPU keeps status in bits 15-8 of the first longword */
0361     tstb    %a0@(TASK_THREAD+THREAD_FPSTATE+2)
0362     jeq 3f
0363 #if !defined(CPU_M68060_ONLY)
0364     jra 2f
0365 #endif
0366 #endif /* CONFIG_M68060 */
0367 #if !defined(CPU_M68060_ONLY)
0368 1:  tstb    %a0@(TASK_THREAD+THREAD_FPSTATE)
0369     jeq 3f
0370 #endif
0371 2:  fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
0372     fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
0373 3:
0374 #endif  /* CONFIG_M68KFPU_EMU_ONLY */
0375     /* Return previous task in %d1 */
0376     movel   %curptr,%d1
0377 
0378     /* switch to new task (a1 contains new task) */
0379     movel   %a1,%curptr
0380 
0381     /* restore floating point context */
0382 #ifndef CONFIG_M68KFPU_EMU_ONLY
0383 #ifdef CONFIG_M68KFPU_EMU
0384     tstl    m68k_fputype
0385     jeq 4f
0386 #endif
0387 #if defined(CONFIG_M68060)
0388 #if !defined(CPU_M68060_ONLY)
0389     btst    #3,m68k_cputype+3
0390     beqs    1f
0391 #endif
0392     /* The 060 FPU keeps status in bits 15-8 of the first longword */
0393     tstb    %a1@(TASK_THREAD+THREAD_FPSTATE+2)
0394     jeq 3f
0395 #if !defined(CPU_M68060_ONLY)
0396     jra 2f
0397 #endif
0398 #endif /* CONFIG_M68060 */
0399 #if !defined(CPU_M68060_ONLY)
0400 1:  tstb    %a1@(TASK_THREAD+THREAD_FPSTATE)
0401     jeq 3f
0402 #endif
0403 2:  fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
0404     fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
0405 3:  frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
0406 4:
0407 #endif  /* CONFIG_M68KFPU_EMU_ONLY */
0408 
0409     /* restore the kernel stack pointer */
0410     movel   %a1@(TASK_THREAD+THREAD_KSP),%sp
0411 
0412     /* restore non-scratch registers */
0413     RESTORE_SWITCH_STACK
0414 
0415     /* restore user stack pointer */
0416     movel   %a1@(TASK_THREAD+THREAD_USP),%a0
0417     movel   %a0,%usp
0418 
0419     /* restore fs (sfc,%dfc) */
0420     movew   %a1@(TASK_THREAD+THREAD_FS),%a0
0421     movec   %a0,%sfc
0422     movec   %a0,%dfc
0423 
0424     /* restore status register */
0425     movew   %a1@(TASK_THREAD+THREAD_SR),%sr
0426 
0427     rts
0428 
0429 #endif /* CONFIG_MMU && !CONFIG_COLDFIRE */