linux/arch/mips/kernel/entry.S
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
   7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
   8 * Copyright (C) 2001 MIPS Technologies, Inc.
   9 */
  10
  11#include <asm/asm.h>
  12#include <asm/asmmacro.h>
  13#include <asm/compiler.h>
  14#include <asm/regdef.h>
  15#include <asm/mipsregs.h>
  16#include <asm/stackframe.h>
  17#include <asm/isadep.h>
  18#include <asm/thread_info.h>
  19#include <asm/war.h>
  20
  21#ifndef CONFIG_PREEMPT
  22#define resume_kernel   restore_all
  23#else
  24#define __ret_from_irq  ret_from_exception
  25#endif
  26
  27        .text
  28        .align  5
  29#ifndef CONFIG_PREEMPT
  30FEXPORT(ret_from_exception)
  31        local_irq_disable                       # preempt stop
  32        b       __ret_from_irq
  33#endif
  34FEXPORT(ret_from_irq)
  35        LONG_S  s0, TI_REGS($28)
  36FEXPORT(__ret_from_irq)
  37/*
  38 * We can be coming here from a syscall done in the kernel space,
  39 * e.g. a failed kernel_execve().
  40 */
  41resume_userspace_check:
  42        LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
  43        andi    t0, t0, KU_USER
  44        beqz    t0, resume_kernel
  45
  46resume_userspace:
  47        local_irq_disable               # make sure we dont miss an
  48                                        # interrupt setting need_resched
  49                                        # between sampling and return
  50        LONG_L  a2, TI_FLAGS($28)       # current->work
  51        andi    t0, a2, _TIF_WORK_MASK  # (ignoring syscall_trace)
  52        bnez    t0, work_pending
  53        j       restore_all
  54
  55#ifdef CONFIG_PREEMPT
  56resume_kernel:
  57        local_irq_disable
  58        lw      t0, TI_PRE_COUNT($28)
  59        bnez    t0, restore_all
  60need_resched:
  61        LONG_L  t0, TI_FLAGS($28)
  62        andi    t1, t0, _TIF_NEED_RESCHED
  63        beqz    t1, restore_all
  64        LONG_L  t0, PT_STATUS(sp)               # Interrupts off?
  65        andi    t0, 1
  66        beqz    t0, restore_all
  67        jal     preempt_schedule_irq
  68        b       need_resched
  69#endif
  70
  71FEXPORT(ret_from_kernel_thread)
  72        jal     schedule_tail           # a0 = struct task_struct *prev
  73        move    a0, s1
  74        jal     s0
  75        j       syscall_exit
  76
  77FEXPORT(ret_from_fork)
  78        jal     schedule_tail           # a0 = struct task_struct *prev
  79
  80FEXPORT(syscall_exit)
  81        local_irq_disable               # make sure need_resched and
  82                                        # signals dont change between
  83                                        # sampling and return
  84        LONG_L  a2, TI_FLAGS($28)       # current->work
  85        li      t0, _TIF_ALLWORK_MASK
  86        and     t0, a2, t0
  87        bnez    t0, syscall_exit_work
  88
  89restore_all:                            # restore full frame
  90        .set    noat
  91        RESTORE_TEMP
  92        RESTORE_AT
  93        RESTORE_STATIC
  94restore_partial:                # restore partial frame
  95#ifdef CONFIG_TRACE_IRQFLAGS
  96        SAVE_STATIC
  97        SAVE_AT
  98        SAVE_TEMP
  99        LONG_L  v0, PT_STATUS(sp)
 100#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 101        and     v0, ST0_IEP
 102#else
 103        and     v0, ST0_IE
 104#endif
 105        beqz    v0, 1f
 106        jal     trace_hardirqs_on
 107        b       2f
 1081:      jal     trace_hardirqs_off
 1092:
 110        RESTORE_TEMP
 111        RESTORE_AT
 112        RESTORE_STATIC
 113#endif
 114        RESTORE_SOME
 115        RESTORE_SP_AND_RET
 116        .set    at
 117
 118work_pending:
 119        andi    t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
 120        beqz    t0, work_notifysig
 121work_resched:
 122        jal     schedule
 123
 124        local_irq_disable               # make sure need_resched and
 125                                        # signals dont change between
 126                                        # sampling and return
 127        LONG_L  a2, TI_FLAGS($28)
 128        andi    t0, a2, _TIF_WORK_MASK  # is there any work to be done
 129                                        # other than syscall tracing?
 130        beqz    t0, restore_all
 131        andi    t0, a2, _TIF_NEED_RESCHED
 132        bnez    t0, work_resched
 133
 134work_notifysig:                         # deal with pending signals and
 135                                        # notify-resume requests
 136        move    a0, sp
 137        li      a1, 0
 138        jal     do_notify_resume        # a2 already loaded
 139        j       resume_userspace_check
 140
 141FEXPORT(syscall_exit_partial)
 142        local_irq_disable               # make sure need_resched doesn't
 143                                        # change between and return
 144        LONG_L  a2, TI_FLAGS($28)       # current->work
 145        li      t0, _TIF_ALLWORK_MASK
 146        and     t0, a2
 147        beqz    t0, restore_partial
 148        SAVE_STATIC
 149syscall_exit_work:
 150        LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
 151        andi    t0, t0, KU_USER
 152        beqz    t0, resume_kernel
 153        li      t0, _TIF_WORK_SYSCALL_EXIT
 154        and     t0, a2                  # a2 is preloaded with TI_FLAGS
 155        beqz    t0, work_pending        # trace bit set?
 156        local_irq_enable                # could let syscall_trace_leave()
 157                                        # call schedule() instead
 158        move    a0, sp
 159        jal     syscall_trace_leave
 160        b       resume_userspace
 161
 162#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \
 163    defined(CONFIG_MIPS_MT)
 164
 165/*
 166 * MIPS32R2 Instruction Hazard Barrier - must be called
 167 *
 168 * For C code use the inline version named instruction_hazard().
 169 */
 170LEAF(mips_ihb)
 171        .set    MIPS_ISA_LEVEL_RAW
 172        jr.hb   ra
 173        nop
 174        END(mips_ihb)
 175
 176#endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */
 177