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/regdef.h> 15#include <asm/mipsregs.h> 16#include <asm/stackframe.h> 17#include <asm/isadep.h> 18#include <asm/thread_info.h> 19#include <asm/war.h> 20 21#ifndef CONFIG_PREEMPT 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_PREEMPT 30FEXPORT(ret_from_exception) 31 local_irq_disable # preempt stop 32 b __ret_from_irq 33#endif 34FEXPORT(ret_from_irq) 35 LONG_S s0, TI_REGS($28) 36FEXPORT(__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 */ 41resume_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 46resume_userspace: 47 local_irq_disable # make sure we dont miss an 48 # interrupt setting need_resched 49 # between sampling and return 50#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR 51 lw k0, TI_R2_EMUL_RET($28) 52 bnez k0, restore_all_from_r2_emul 53#endif 54 55 LONG_L a2, TI_FLAGS($28) # current->work 56 andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) 57 bnez t0, work_pending 58 j restore_all 59 60#ifdef CONFIG_PREEMPT 61resume_kernel: 62 local_irq_disable 63 lw t0, TI_PRE_COUNT($28) 64 bnez t0, restore_all 65need_resched: 66 LONG_L t0, TI_FLAGS($28) 67 andi t1, t0, _TIF_NEED_RESCHED 68 beqz t1, restore_all 69 LONG_L t0, PT_STATUS(sp) # Interrupts off? 70 andi t0, 1 71 beqz t0, restore_all 72 jal preempt_schedule_irq 73 b need_resched 74#endif 75 76FEXPORT(ret_from_kernel_thread) 77 jal schedule_tail # a0 = struct task_struct *prev 78 move a0, s1 79 jal s0 80 j syscall_exit 81 82FEXPORT(ret_from_fork) 83 jal schedule_tail # a0 = struct task_struct *prev 84 85FEXPORT(syscall_exit) 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 123#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR 124restore_all_from_r2_emul: # restore full frame 125 .set noat 126 sw zero, TI_R2_EMUL_RET($28) # reset it 127 RESTORE_TEMP 128 RESTORE_AT 129 RESTORE_STATIC 130 RESTORE_SOME 131 LONG_L sp, PT_R29(sp) 132 eretnc 133 .set at 134#endif 135 136work_pending: 137 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 138 beqz t0, work_notifysig 139work_resched: 140 jal schedule 141 142 local_irq_disable # make sure need_resched and 143 # signals dont change between 144 # sampling and return 145 LONG_L a2, TI_FLAGS($28) 146 andi t0, a2, _TIF_WORK_MASK # is there any work to be done 147 # other than syscall tracing? 148 beqz t0, restore_all 149 andi t0, a2, _TIF_NEED_RESCHED 150 bnez t0, work_resched 151 152work_notifysig: # deal with pending signals and 153 # notify-resume requests 154 move a0, sp 155 li a1, 0 156 jal do_notify_resume # a2 already loaded 157 j resume_userspace_check 158 159FEXPORT(syscall_exit_partial) 160 local_irq_disable # make sure need_resched doesn't 161 # change between and return 162 LONG_L a2, TI_FLAGS($28) # current->work 163 li t0, _TIF_ALLWORK_MASK 164 and t0, a2 165 beqz t0, restore_partial 166 SAVE_STATIC 167syscall_exit_work: 168 LONG_L t0, PT_STATUS(sp) # returning to kernel mode? 169 andi t0, t0, KU_USER 170 beqz t0, resume_kernel 171 li t0, _TIF_WORK_SYSCALL_EXIT 172 and t0, a2 # a2 is preloaded with TI_FLAGS 173 beqz t0, work_pending # trace bit set? 174 local_irq_enable # could let syscall_trace_leave() 175 # call schedule() instead 176 move a0, sp 177 jal syscall_trace_leave 178 b resume_userspace 179 180#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \ 181 defined(CONFIG_MIPS_MT) 182 183/* 184 * MIPS32R2 Instruction Hazard Barrier - must be called 185 * 186 * For C code use the inline version named instruction_hazard(). 187 */ 188LEAF(mips_ihb) 189 .set MIPS_ISA_LEVEL_RAW 190 jr.hb ra 191 nop 192 END(mips_ihb) 193 194#endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */ 195