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