0001
0002
0003
0004
0005
0006
0007
0008
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
0039
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
0176
0177
0178
0179 LEAF(mips_ihb)
0180 .set MIPS_ISA_LEVEL_RAW
0181 jr.hb ra
0182 nop
0183 END(mips_ihb)
0184
0185 #endif