Back to home page

LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
0007  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
0008  * Copyright (C) 2001 MIPS Technologies, Inc.
0009  */
0010 
0011 #include <asm/asm.h>
0012 #include <asm/asmmacro.h>
0013 #include <asm/compiler.h>
0014 #include <asm/regdef.h>
0015 #include <asm/mipsregs.h>
0016 #include <asm/stackframe.h>
0017 #include <asm/isadep.h>
0018 #include <asm/thread_info.h>
0019 #include <asm/war.h>
0020 
0021 #ifndef CONFIG_PREEMPT
0022 #define resume_kernel   restore_all
0023 #else
0024 #define __ret_from_irq  ret_from_exception
0025 #endif
0026 
0027     .text
0028     .align  5
0029 #ifndef CONFIG_PREEMPT
0030 FEXPORT(ret_from_exception)
0031     local_irq_disable           # preempt stop
0032     b   __ret_from_irq
0033 #endif
0034 FEXPORT(ret_from_irq)
0035     LONG_S  s0, TI_REGS($28)
0036 FEXPORT(__ret_from_irq)
0037 /*
0038  * We can be coming here from a syscall done in the kernel space,
0039  * e.g. a failed kernel_execve().
0040  */
0041 resume_userspace_check:
0042     LONG_L  t0, PT_STATUS(sp)       # returning to kernel mode?
0043     andi    t0, t0, KU_USER
0044     beqz    t0, resume_kernel
0045 
0046 resume_userspace:
0047     local_irq_disable       # make sure we dont miss an
0048                     # interrupt setting need_resched
0049                     # between sampling and return
0050 #ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
0051     lw  k0, TI_R2_EMUL_RET($28)
0052     bnez    k0, restore_all_from_r2_emul
0053 #endif
0054 
0055     LONG_L  a2, TI_FLAGS($28)   # current->work
0056     andi    t0, a2, _TIF_WORK_MASK  # (ignoring syscall_trace)
0057     bnez    t0, work_pending
0058     j   restore_all
0059 
0060 #ifdef CONFIG_PREEMPT
0061 resume_kernel:
0062     local_irq_disable
0063     lw  t0, TI_PRE_COUNT($28)
0064     bnez    t0, restore_all
0065 need_resched:
0066     LONG_L  t0, TI_FLAGS($28)
0067     andi    t1, t0, _TIF_NEED_RESCHED
0068     beqz    t1, restore_all
0069     LONG_L  t0, PT_STATUS(sp)       # Interrupts off?
0070     andi    t0, 1
0071     beqz    t0, restore_all
0072     jal preempt_schedule_irq
0073     b   need_resched
0074 #endif
0075 
0076 FEXPORT(ret_from_kernel_thread)
0077     jal schedule_tail       # a0 = struct task_struct *prev
0078     move    a0, s1
0079     jal s0
0080     j   syscall_exit
0081 
0082 FEXPORT(ret_from_fork)
0083     jal schedule_tail       # a0 = struct task_struct *prev
0084 
0085 FEXPORT(syscall_exit)
0086     local_irq_disable       # make sure need_resched and
0087                     # signals dont change between
0088                     # sampling and return
0089     LONG_L  a2, TI_FLAGS($28)   # current->work
0090     li  t0, _TIF_ALLWORK_MASK
0091     and t0, a2, t0
0092     bnez    t0, syscall_exit_work
0093 
0094 restore_all:                # restore full frame
0095     .set    noat
0096     RESTORE_TEMP
0097     RESTORE_AT
0098     RESTORE_STATIC
0099 restore_partial:        # restore partial frame
0100 #ifdef CONFIG_TRACE_IRQFLAGS
0101     SAVE_STATIC
0102     SAVE_AT
0103     SAVE_TEMP
0104     LONG_L  v0, PT_STATUS(sp)
0105 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
0106     and v0, ST0_IEP
0107 #else
0108     and v0, ST0_IE
0109 #endif
0110     beqz    v0, 1f
0111     jal trace_hardirqs_on
0112     b   2f
0113 1:  jal trace_hardirqs_off
0114 2:
0115     RESTORE_TEMP
0116     RESTORE_AT
0117     RESTORE_STATIC
0118 #endif
0119     RESTORE_SOME
0120     RESTORE_SP_AND_RET
0121     .set    at
0122 
0123 #ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
0124 restore_all_from_r2_emul:           # restore full frame
0125     .set    noat
0126     sw  zero, TI_R2_EMUL_RET($28)   # reset it
0127     RESTORE_TEMP
0128     RESTORE_AT
0129     RESTORE_STATIC
0130     RESTORE_SOME
0131     LONG_L  sp, PT_R29(sp)
0132     eretnc
0133     .set    at
0134 #endif
0135 
0136 work_pending:
0137     andi    t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
0138     beqz    t0, work_notifysig
0139 work_resched:
0140     jal schedule
0141 
0142     local_irq_disable       # make sure need_resched and
0143                     # signals dont change between
0144                     # sampling and return
0145     LONG_L  a2, TI_FLAGS($28)
0146     andi    t0, a2, _TIF_WORK_MASK  # is there any work to be done
0147                     # other than syscall tracing?
0148     beqz    t0, restore_all
0149     andi    t0, a2, _TIF_NEED_RESCHED
0150     bnez    t0, work_resched
0151 
0152 work_notifysig:             # deal with pending signals and
0153                     # notify-resume requests
0154     move    a0, sp
0155     li  a1, 0
0156     jal do_notify_resume    # a2 already loaded
0157     j   resume_userspace_check
0158 
0159 FEXPORT(syscall_exit_partial)
0160     local_irq_disable       # make sure need_resched doesn't
0161                     # change between and return
0162     LONG_L  a2, TI_FLAGS($28)   # current->work
0163     li  t0, _TIF_ALLWORK_MASK
0164     and t0, a2
0165     beqz    t0, restore_partial
0166     SAVE_STATIC
0167 syscall_exit_work:
0168     LONG_L  t0, PT_STATUS(sp)       # returning to kernel mode?
0169     andi    t0, t0, KU_USER
0170     beqz    t0, resume_kernel
0171     li  t0, _TIF_WORK_SYSCALL_EXIT
0172     and t0, a2          # a2 is preloaded with TI_FLAGS
0173     beqz    t0, work_pending    # trace bit set?
0174     local_irq_enable        # could let syscall_trace_leave()
0175                     # call schedule() instead
0176     move    a0, sp
0177     jal syscall_trace_leave
0178     b   resume_userspace
0179 
0180 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \
0181     defined(CONFIG_MIPS_MT)
0182 
0183 /*
0184  * MIPS32R2 Instruction Hazard Barrier - must be called
0185  *
0186  * For C code use the inline version named instruction_hazard().
0187  */
0188 LEAF(mips_ihb)
0189     .set    MIPS_ISA_LEVEL_RAW
0190     jr.hb   ra
0191     nop
0192     END(mips_ihb)
0193 
0194 #endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */