linux/arch/m68k/kernel/entry.S
<<
>>
Prefs
   1/* -*- mode: asm -*-
   2 *
   3 *  linux/arch/m68k/kernel/entry.S
   4 *
   5 *  Copyright (C) 1991, 1992  Linus Torvalds
   6 *
   7 * This file is subject to the terms and conditions of the GNU General Public
   8 * License.  See the file README.legal in the main directory of this archive
   9 * for more details.
  10 *
  11 * Linux/m68k support by Hamish Macdonald
  12 *
  13 * 68060 fixes by Jesper Skov
  14 *
  15 */
  16
  17/*
  18 * entry.S  contains the system-call and fault low-level handling routines.
  19 * This also contains the timer-interrupt handler, as well as all interrupts
  20 * and faults that can result in a task-switch.
  21 *
  22 * NOTE: This code handles signal-recognition, which happens every time
  23 * after a timer-interrupt and after each system call.
  24 *
  25 */
  26
  27/*
  28 * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
  29 *               all pointers that used to be 'current' are now entry
  30 *               number 0 in the 'current_set' list.
  31 *
  32 *  6/05/00 RZ:  addedd writeback completion after return from sighandler
  33 *               for 68040
  34 */
  35
  36#include <linux/linkage.h>
  37#include <asm/errno.h>
  38#include <asm/setup.h>
  39#include <asm/segment.h>
  40#include <asm/traps.h>
  41#include <asm/unistd.h>
  42#include <asm/asm-offsets.h>
  43#include <asm/entry.h>
  44
  45.globl system_call, buserr, trap, resume
  46.globl sys_call_table
  47.globl __sys_fork, __sys_clone, __sys_vfork
  48.globl bad_interrupt
  49.globl auto_irqhandler_fixup
  50.globl user_irqvec_fixup
  51
  52.text
  53ENTRY(__sys_fork)
  54        SAVE_SWITCH_STACK
  55        jbsr    sys_fork
  56        lea     %sp@(24),%sp
  57        rts
  58
  59ENTRY(__sys_clone)
  60        SAVE_SWITCH_STACK
  61        pea     %sp@(SWITCH_STACK_SIZE)
  62        jbsr    m68k_clone
  63        lea     %sp@(28),%sp
  64        rts
  65
  66ENTRY(__sys_vfork)
  67        SAVE_SWITCH_STACK
  68        jbsr    sys_vfork
  69        lea     %sp@(24),%sp
  70        rts
  71
  72ENTRY(__sys_clone3)
  73        SAVE_SWITCH_STACK
  74        pea     %sp@(SWITCH_STACK_SIZE)
  75        jbsr    m68k_clone3
  76        lea     %sp@(28),%sp
  77        rts
  78
  79ENTRY(sys_sigreturn)
  80        SAVE_SWITCH_STACK
  81        movel   %sp,%sp@-                 | switch_stack pointer
  82        pea     %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer
  83        jbsr    do_sigreturn
  84        addql   #8,%sp
  85        RESTORE_SWITCH_STACK
  86        rts
  87
  88ENTRY(sys_rt_sigreturn)
  89        SAVE_SWITCH_STACK
  90        movel   %sp,%sp@-                 | switch_stack pointer
  91        pea     %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer
  92        jbsr    do_rt_sigreturn
  93        addql   #8,%sp
  94        RESTORE_SWITCH_STACK
  95        rts
  96
  97ENTRY(buserr)
  98        SAVE_ALL_INT
  99        GET_CURRENT(%d0)
 100        movel   %sp,%sp@-               | stack frame pointer argument
 101        jbsr    buserr_c
 102        addql   #4,%sp
 103        jra     ret_from_exception
 104
 105ENTRY(trap)
 106        SAVE_ALL_INT
 107        GET_CURRENT(%d0)
 108        movel   %sp,%sp@-               | stack frame pointer argument
 109        jbsr    trap_c
 110        addql   #4,%sp
 111        jra     ret_from_exception
 112
 113        | After a fork we jump here directly from resume,
 114        | so that %d1 contains the previous task
 115        | schedule_tail now used regardless of CONFIG_SMP
 116ENTRY(ret_from_fork)
 117        movel   %d1,%sp@-
 118        jsr     schedule_tail
 119        addql   #4,%sp
 120        jra     ret_from_exception
 121
 122ENTRY(ret_from_kernel_thread)
 123        | a3 contains the kernel thread payload, d7 - its argument
 124        movel   %d1,%sp@-
 125        jsr     schedule_tail
 126        movel   %d7,(%sp)
 127        jsr     %a3@
 128        addql   #4,%sp
 129        jra     ret_from_exception
 130
 131#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
 132
 133#ifdef TRAP_DBG_INTERRUPT
 134
 135.globl dbginterrupt
 136ENTRY(dbginterrupt)
 137        SAVE_ALL_INT
 138        GET_CURRENT(%d0)
 139        movel   %sp,%sp@-               /* stack frame pointer argument */
 140        jsr     dbginterrupt_c
 141        addql   #4,%sp
 142        jra     ret_from_exception
 143#endif
 144
 145ENTRY(reschedule)
 146        /* save top of frame */
 147        pea     %sp@
 148        jbsr    set_esp0
 149        addql   #4,%sp
 150        pea     ret_from_exception
 151        jmp     schedule
 152
 153ENTRY(ret_from_user_signal)
 154        moveq #__NR_sigreturn,%d0
 155        trap #0
 156
 157ENTRY(ret_from_user_rt_signal)
 158        movel #__NR_rt_sigreturn,%d0
 159        trap #0
 160
 161#else
 162
 163do_trace_entry:
 164        movel   #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
 165        subql   #4,%sp
 166        SAVE_SWITCH_STACK
 167        jbsr    syscall_trace
 168        RESTORE_SWITCH_STACK
 169        addql   #4,%sp
 170        movel   %sp@(PT_OFF_ORIG_D0),%d0
 171        cmpl    #NR_syscalls,%d0
 172        jcs     syscall
 173badsys:
 174        movel   #-ENOSYS,%sp@(PT_OFF_D0)
 175        jra     ret_from_syscall
 176
 177do_trace_exit:
 178        subql   #4,%sp
 179        SAVE_SWITCH_STACK
 180        jbsr    syscall_trace
 181        RESTORE_SWITCH_STACK
 182        addql   #4,%sp
 183        jra     .Lret_from_exception
 184
 185ENTRY(ret_from_signal)
 186        movel   %curptr@(TASK_STACK),%a1
 187        tstb    %a1@(TINFO_FLAGS+2)
 188        jge     1f
 189        jbsr    syscall_trace
 1901:      RESTORE_SWITCH_STACK
 191        addql   #4,%sp
 192/* on 68040 complete pending writebacks if any */
 193#ifdef CONFIG_M68040
 194        bfextu  %sp@(PT_OFF_FORMATVEC){#0,#4},%d0
 195        subql   #7,%d0                          | bus error frame ?
 196        jbne    1f
 197        movel   %sp,%sp@-
 198        jbsr    berr_040cleanup
 199        addql   #4,%sp
 2001:
 201#endif
 202        jra     .Lret_from_exception
 203
 204ENTRY(system_call)
 205        SAVE_ALL_SYS
 206
 207        GET_CURRENT(%d1)
 208        movel   %d1,%a1
 209
 210        | save top of frame
 211        movel   %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
 212
 213        | syscall trace?
 214        tstb    %a1@(TINFO_FLAGS+2)
 215        jmi     do_trace_entry
 216        cmpl    #NR_syscalls,%d0
 217        jcc     badsys
 218syscall:
 219        jbsr    @(sys_call_table,%d0:l:4)@(0)
 220        movel   %d0,%sp@(PT_OFF_D0)     | save the return value
 221ret_from_syscall:
 222        |oriw   #0x0700,%sr
 223        movel   %curptr@(TASK_STACK),%a1
 224        movew   %a1@(TINFO_FLAGS+2),%d0
 225        jne     syscall_exit_work
 2261:      RESTORE_ALL
 227
 228syscall_exit_work:
 229        btst    #5,%sp@(PT_OFF_SR)      | check if returning to kernel
 230        bnes    1b                      | if so, skip resched, signals
 231        lslw    #1,%d0
 232        jcs     do_trace_exit
 233        jmi     do_delayed_trace
 234        lslw    #8,%d0
 235        jne     do_signal_return
 236        pea     resume_userspace
 237        jra     schedule
 238
 239
 240ENTRY(ret_from_exception)
 241.Lret_from_exception:
 242        btst    #5,%sp@(PT_OFF_SR)      | check if returning to kernel
 243        bnes    1f                      | if so, skip resched, signals
 244        | only allow interrupts when we are really the last one on the
 245        | kernel stack, otherwise stack overflow can occur during
 246        | heavy interrupt load
 247        andw    #ALLOWINT,%sr
 248
 249resume_userspace:
 250        movel   %curptr@(TASK_STACK),%a1
 251        moveb   %a1@(TINFO_FLAGS+3),%d0
 252        jne     exit_work
 2531:      RESTORE_ALL
 254
 255exit_work:
 256        | save top of frame
 257        movel   %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
 258        lslb    #1,%d0
 259        jne     do_signal_return
 260        pea     resume_userspace
 261        jra     schedule
 262
 263
 264do_signal_return:
 265        |andw   #ALLOWINT,%sr
 266        subql   #4,%sp                  | dummy return address
 267        SAVE_SWITCH_STACK
 268        pea     %sp@(SWITCH_STACK_SIZE)
 269        bsrl    do_notify_resume
 270        addql   #4,%sp
 271        RESTORE_SWITCH_STACK
 272        addql   #4,%sp
 273        jbra    resume_userspace
 274
 275do_delayed_trace:
 276        bclr    #7,%sp@(PT_OFF_SR)      | clear trace bit in SR
 277        pea     1                       | send SIGTRAP
 278        movel   %curptr,%sp@-
 279        pea     LSIGTRAP
 280        jbsr    send_sig
 281        addql   #8,%sp
 282        addql   #4,%sp
 283        jbra    resume_userspace
 284
 285
 286/* This is the main interrupt handler for autovector interrupts */
 287
 288ENTRY(auto_inthandler)
 289        SAVE_ALL_INT
 290        GET_CURRENT(%d0)
 291                                        |  put exception # in d0
 292        bfextu  %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
 293        subw    #VEC_SPUR,%d0
 294
 295        movel   %sp,%sp@-
 296        movel   %d0,%sp@-               |  put vector # on stack
 297auto_irqhandler_fixup = . + 2
 298        jsr     do_IRQ                  |  process the IRQ
 299        addql   #8,%sp                  |  pop parameters off stack
 300        jra     ret_from_exception
 301
 302/* Handler for user defined interrupt vectors */
 303
 304ENTRY(user_inthandler)
 305        SAVE_ALL_INT
 306        GET_CURRENT(%d0)
 307                                        |  put exception # in d0
 308        bfextu  %sp@(PT_OFF_FORMATVEC){#4,#10},%d0
 309user_irqvec_fixup = . + 2
 310        subw    #VEC_USER,%d0
 311
 312        movel   %sp,%sp@-
 313        movel   %d0,%sp@-               |  put vector # on stack
 314        jsr     do_IRQ                  |  process the IRQ
 315        addql   #8,%sp                  |  pop parameters off stack
 316        jra     ret_from_exception
 317
 318/* Handler for uninitialized and spurious interrupts */
 319
 320ENTRY(bad_inthandler)
 321        SAVE_ALL_INT
 322        GET_CURRENT(%d0)
 323
 324        movel   %sp,%sp@-
 325        jsr     handle_badint
 326        addql   #4,%sp
 327        jra     ret_from_exception
 328
 329resume:
 330        /*
 331         * Beware - when entering resume, prev (the current task) is
 332         * in a0, next (the new task) is in a1,so don't change these
 333         * registers until their contents are no longer needed.
 334         */
 335
 336        /* save sr */
 337        movew   %sr,%a0@(TASK_THREAD+THREAD_SR)
 338
 339        /* save fs (sfc,%dfc) (may be pointing to kernel memory) */
 340        movec   %sfc,%d0
 341        movew   %d0,%a0@(TASK_THREAD+THREAD_FS)
 342
 343        /* save usp */
 344        /* it is better to use a movel here instead of a movew 8*) */
 345        movec   %usp,%d0
 346        movel   %d0,%a0@(TASK_THREAD+THREAD_USP)
 347
 348        /* save non-scratch registers on stack */
 349        SAVE_SWITCH_STACK
 350
 351        /* save current kernel stack pointer */
 352        movel   %sp,%a0@(TASK_THREAD+THREAD_KSP)
 353
 354        /* save floating point context */
 355#ifndef CONFIG_M68KFPU_EMU_ONLY
 356#ifdef CONFIG_M68KFPU_EMU
 357        tstl    m68k_fputype
 358        jeq     3f
 359#endif
 360        fsave   %a0@(TASK_THREAD+THREAD_FPSTATE)
 361
 362#if defined(CONFIG_M68060)
 363#if !defined(CPU_M68060_ONLY)
 364        btst    #3,m68k_cputype+3
 365        beqs    1f
 366#endif
 367        /* The 060 FPU keeps status in bits 15-8 of the first longword */
 368        tstb    %a0@(TASK_THREAD+THREAD_FPSTATE+2)
 369        jeq     3f
 370#if !defined(CPU_M68060_ONLY)
 371        jra     2f
 372#endif
 373#endif /* CONFIG_M68060 */
 374#if !defined(CPU_M68060_ONLY)
 3751:      tstb    %a0@(TASK_THREAD+THREAD_FPSTATE)
 376        jeq     3f
 377#endif
 3782:      fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
 379        fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
 3803:
 381#endif  /* CONFIG_M68KFPU_EMU_ONLY */
 382        /* Return previous task in %d1 */
 383        movel   %curptr,%d1
 384
 385        /* switch to new task (a1 contains new task) */
 386        movel   %a1,%curptr
 387
 388        /* restore floating point context */
 389#ifndef CONFIG_M68KFPU_EMU_ONLY
 390#ifdef CONFIG_M68KFPU_EMU
 391        tstl    m68k_fputype
 392        jeq     4f
 393#endif
 394#if defined(CONFIG_M68060)
 395#if !defined(CPU_M68060_ONLY)
 396        btst    #3,m68k_cputype+3
 397        beqs    1f
 398#endif
 399        /* The 060 FPU keeps status in bits 15-8 of the first longword */
 400        tstb    %a1@(TASK_THREAD+THREAD_FPSTATE+2)
 401        jeq     3f
 402#if !defined(CPU_M68060_ONLY)
 403        jra     2f
 404#endif
 405#endif /* CONFIG_M68060 */
 406#if !defined(CPU_M68060_ONLY)
 4071:      tstb    %a1@(TASK_THREAD+THREAD_FPSTATE)
 408        jeq     3f
 409#endif
 4102:      fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
 411        fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
 4123:      frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
 4134:
 414#endif  /* CONFIG_M68KFPU_EMU_ONLY */
 415
 416        /* restore the kernel stack pointer */
 417        movel   %a1@(TASK_THREAD+THREAD_KSP),%sp
 418
 419        /* restore non-scratch registers */
 420        RESTORE_SWITCH_STACK
 421
 422        /* restore user stack pointer */
 423        movel   %a1@(TASK_THREAD+THREAD_USP),%a0
 424        movel   %a0,%usp
 425
 426        /* restore fs (sfc,%dfc) */
 427        movew   %a1@(TASK_THREAD+THREAD_FS),%a0
 428        movec   %a0,%sfc
 429        movec   %a0,%dfc
 430
 431        /* restore status register */
 432        movew   %a1@(TASK_THREAD+THREAD_SR),%sr
 433
 434        rts
 435
 436#endif /* CONFIG_MMU && !CONFIG_COLDFIRE */
 437