Back to home page

OSCL-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/irqflags.h>
0015 #include <asm/regdef.h>
0016 #include <asm/mipsregs.h>
0017 #include <asm/stackframe.h>
0018 #include <asm/isadep.h>
0019 #include <asm/thread_info.h>
0020 
0021 #ifndef CONFIG_PREEMPTION
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_PREEMPTION
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     LONG_L  a2, TI_FLAGS($28)   # current->work
0051     andi    t0, a2, _TIF_WORK_MASK  # (ignoring syscall_trace)
0052     bnez    t0, work_pending
0053     j   restore_all
0054 
0055 #ifdef CONFIG_PREEMPTION
0056 resume_kernel:
0057     local_irq_disable
0058     lw  t0, TI_PRE_COUNT($28)
0059     bnez    t0, restore_all
0060     LONG_L  t0, TI_FLAGS($28)
0061     andi    t1, t0, _TIF_NEED_RESCHED
0062     beqz    t1, restore_all
0063     LONG_L  t0, PT_STATUS(sp)       # Interrupts off?
0064     andi    t0, 1
0065     beqz    t0, restore_all
0066     PTR_LA  ra, restore_all
0067     j   preempt_schedule_irq
0068 #endif
0069 
0070 FEXPORT(ret_from_kernel_thread)
0071     jal schedule_tail       # a0 = struct task_struct *prev
0072     move    a0, s1
0073     jal s0
0074     j   syscall_exit
0075 
0076 FEXPORT(ret_from_fork)
0077     jal schedule_tail       # a0 = struct task_struct *prev
0078 
0079 FEXPORT(syscall_exit)
0080 #ifdef CONFIG_DEBUG_RSEQ
0081     move    a0, sp
0082     jal rseq_syscall
0083 #endif
0084     local_irq_disable       # make sure need_resched and
0085                     # signals dont change between
0086                     # sampling and return
0087     LONG_L  a2, TI_FLAGS($28)   # current->work
0088     li  t0, _TIF_ALLWORK_MASK
0089     and t0, a2, t0
0090     bnez    t0, syscall_exit_work
0091 
0092 restore_all:                # restore full frame
0093     .set    noat
0094     RESTORE_TEMP
0095     RESTORE_AT
0096     RESTORE_STATIC
0097 restore_partial:        # restore partial frame
0098 #ifdef CONFIG_TRACE_IRQFLAGS
0099     SAVE_STATIC
0100     SAVE_AT
0101     SAVE_TEMP
0102     LONG_L  v0, PT_STATUS(sp)
0103 #if defined(CONFIG_CPU_R3000)
0104     and v0, ST0_IEP
0105 #else
0106     and v0, ST0_IE
0107 #endif
0108     beqz    v0, 1f
0109     jal trace_hardirqs_on
0110     b   2f
0111 1:  jal trace_hardirqs_off
0112 2:
0113     RESTORE_TEMP
0114     RESTORE_AT
0115     RESTORE_STATIC
0116 #endif
0117     RESTORE_SOME
0118     RESTORE_SP_AND_RET
0119     .set    at
0120 
0121 work_pending:
0122     andi    t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
0123     beqz    t0, work_notifysig
0124 work_resched:
0125     TRACE_IRQS_OFF
0126     jal schedule
0127 
0128     local_irq_disable       # make sure need_resched and
0129                     # signals dont change between
0130                     # sampling and return
0131     LONG_L  a2, TI_FLAGS($28)
0132     andi    t0, a2, _TIF_WORK_MASK  # is there any work to be done
0133                     # other than syscall tracing?
0134     beqz    t0, restore_all
0135     andi    t0, a2, _TIF_NEED_RESCHED
0136     bnez    t0, work_resched
0137 
0138 work_notifysig:             # deal with pending signals and
0139                     # notify-resume requests
0140     move    a0, sp
0141     li  a1, 0
0142     jal do_notify_resume    # a2 already loaded
0143     j   resume_userspace_check
0144 
0145 FEXPORT(syscall_exit_partial)
0146 #ifdef CONFIG_DEBUG_RSEQ
0147     move    a0, sp
0148     jal rseq_syscall
0149 #endif
0150     local_irq_disable       # make sure need_resched doesn't
0151                     # change between and return
0152     LONG_L  a2, TI_FLAGS($28)   # current->work
0153     li  t0, _TIF_ALLWORK_MASK
0154     and t0, a2
0155     beqz    t0, restore_partial
0156     SAVE_STATIC
0157 syscall_exit_work:
0158     LONG_L  t0, PT_STATUS(sp)       # returning to kernel mode?
0159     andi    t0, t0, KU_USER
0160     beqz    t0, resume_kernel
0161     li  t0, _TIF_WORK_SYSCALL_EXIT
0162     and t0, a2          # a2 is preloaded with TI_FLAGS
0163     beqz    t0, work_pending    # trace bit set?
0164     local_irq_enable        # could let syscall_trace_leave()
0165                     # call schedule() instead
0166     TRACE_IRQS_ON
0167     move    a0, sp
0168     jal syscall_trace_leave
0169     b   resume_userspace
0170 
0171 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \
0172     defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT)
0173 
0174 /*
0175  * MIPS32R2 Instruction Hazard Barrier - must be called
0176  *
0177  * For C code use the inline version named instruction_hazard().
0178  */
0179 LEAF(mips_ihb)
0180     .set    MIPS_ISA_LEVEL_RAW
0181     jr.hb   ra
0182     nop
0183     END(mips_ihb)
0184 
0185 #endif /* CONFIG_CPU_MIPSR2 - CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */