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