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/irqflags.h> 15 #include <asm/regdef.h> 16 #include <asm/mipsregs.h> 17 #include <asm/stackframe.h> 18 #include <asm/isadep.h> 19 #include <asm/thread_info.h> 20 21 #ifndef CONFIG_PREEMPTION 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_PREEMPTION 30 FEXPORT(ret_from_exception) 31 local_irq_disable # preempt stop 32 b __ret_from_irq 33 #endif 34 FEXPORT(ret_from_irq) 35 LONG_S s0, TI_REGS($28) 36 FEXPORT(__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 */ 41 resume_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 46 resume_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_PREEMPTION 56 resume_kernel: 57 local_irq_disable 58 lw t0, TI_PRE_COUNT($28) 59 bnez t0, restore_all 60 LONG_L t0, TI_FLAGS($28) 61 andi t1, t0, _TIF_NEED_RESCHED 62 beqz t1, restore_all 63 LONG_L t0, PT_STATUS(sp) # Interrupts off? 64 andi t0, 1 65 beqz t0, restore_all 66 PTR_LA ra, restore_all 67 j preempt_schedule_irq 68 #endif 69 70 FEXPORT(ret_from_kernel_thread) 71 jal schedule_tail # a0 = struct task_struct *prev 72 move a0, s1 73 jal s0 74 j syscall_exit 75 76 FEXPORT(ret_from_fork) 77 jal schedule_tail # a0 = struct task_struct *prev 78 79 FEXPORT(syscall_exit) 80 #ifdef CONFIG_DEBUG_RSEQ 81 move a0, sp 82 jal rseq_syscall 83 #endif 84 local_irq_disable # make sure need_resched and 85 # signals dont change between 86 # sampling and return 87 LONG_L a2, TI_FLAGS($28) # current->work 88 li t0, _TIF_ALLWORK_MASK 89 and t0, a2, t0 90 bnez t0, syscall_exit_work 91 92 restore_all: # restore full frame 93 .set noat 94 RESTORE_TEMP 95 RESTORE_AT 96 RESTORE_STATIC 97 restore_partial: # restore partial frame 98 #ifdef CONFIG_TRACE_IRQFLAGS 99 SAVE_STATIC 100 SAVE_AT 101 SAVE_TEMP 102 LONG_L v0, PT_STATUS(sp) 103 #if defined(CONFIG_CPU_R3000) 104 and v0, ST0_IEP 105 #else 106 and v0, ST0_IE 107 #endif 108 beqz v0, 1f 109 jal trace_hardirqs_on 110 b 2f 111 1: jal trace_hardirqs_off 112 2: 113 RESTORE_TEMP 114 RESTORE_AT 115 RESTORE_STATIC 116 #endif 117 RESTORE_SOME 118 RESTORE_SP_AND_RET 119 .set at 120 121 work_pending: 122 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 123 beqz t0, work_notifysig 124 work_resched: 125 TRACE_IRQS_OFF 126 jal schedule 127 128 local_irq_disable # make sure need_resched and 129 # signals dont change between 130 # sampling and return 131 LONG_L a2, TI_FLAGS($28) 132 andi t0, a2, _TIF_WORK_MASK # is there any work to be done 133 # other than syscall tracing? 134 beqz t0, restore_all 135 andi t0, a2, _TIF_NEED_RESCHED 136 bnez t0, work_resched 137 138 work_notifysig: # deal with pending signals and 139 # notify-resume requests 140 move a0, sp 141 li a1, 0 142 jal do_notify_resume # a2 already loaded 143 j resume_userspace_check 144 145 FEXPORT(syscall_exit_partial) 146 #ifdef CONFIG_DEBUG_RSEQ 147 move a0, sp 148 jal rseq_syscall 149 #endif 150 local_irq_disable # make sure need_resched doesn't 151 # change between and return 152 LONG_L a2, TI_FLAGS($28) # current->work 153 li t0, _TIF_ALLWORK_MASK 154 and t0, a2 155 beqz t0, restore_partial 156 SAVE_STATIC 157 syscall_exit_work: 158 LONG_L t0, PT_STATUS(sp) # returning to kernel mode? 159 andi t0, t0, KU_USER 160 beqz t0, resume_kernel 161 li t0, _TIF_WORK_SYSCALL_EXIT 162 and t0, a2 # a2 is preloaded with TI_FLAGS 163 beqz t0, work_pending # trace bit set? 164 local_irq_enable # could let syscall_trace_leave() 165 # call schedule() instead 166 TRACE_IRQS_ON 167 move a0, sp 168 jal syscall_trace_leave 169 b resume_userspace 170 171 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \ 172 defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT) 173 174 /* 175 * MIPS32R2 Instruction Hazard Barrier - must be called 176 * 177 * For C code use the inline version named instruction_hazard(). 178 */ 179 LEAF(mips_ihb) 180 .set MIPS_ISA_LEVEL_RAW 181 jr.hb ra 182 nop 183 END(mips_ihb) 184 185 #endif /* CONFIG_CPU_MIPSR2 - CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.