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#ifdef CONFIG_MIPS_MT_SMTC 20#include <asm/mipsmtregs.h> 21#endif 22 23#ifndef CONFIG_PREEMPT 24#define resume_kernel restore_all 25#else 26#define __ret_from_irq ret_from_exception 27#endif 28 29 .text 30 .align 5 31#ifndef CONFIG_PREEMPT 32FEXPORT(ret_from_exception) 33 local_irq_disable # preempt stop 34 b __ret_from_irq 35#endif 36FEXPORT(ret_from_irq) 37 LONG_S s0, TI_REGS($28) 38FEXPORT(__ret_from_irq) 39/* 40 * We can be coming here from a syscall done in the kernel space, 41 * e.g. a failed kernel_execve(). 42 */ 43resume_userspace_check: 44 LONG_L t0, PT_STATUS(sp) # returning to kernel mode? 45 andi t0, t0, KU_USER 46 beqz t0, resume_kernel 47 48resume_userspace: 49 local_irq_disable # make sure we dont miss an 50 # interrupt setting need_resched 51 # between sampling and return 52 LONG_L a2, TI_FLAGS($28) # current->work 53 andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) 54 bnez t0, work_pending 55 j restore_all 56 57#ifdef CONFIG_PREEMPT 58resume_kernel: 59 local_irq_disable 60 lw t0, TI_PRE_COUNT($28) 61 bnez t0, restore_all 62need_resched: 63 LONG_L t0, TI_FLAGS($28) 64 andi t1, t0, _TIF_NEED_RESCHED 65 beqz t1, restore_all 66 LONG_L t0, PT_STATUS(sp) # Interrupts off? 67 andi t0, 1 68 beqz t0, restore_all 69 jal preempt_schedule_irq 70 b need_resched 71#endif 72 73FEXPORT(ret_from_kernel_thread) 74 jal schedule_tail # a0 = struct task_struct *prev 75 move a0, s1 76 jal s0 77 j syscall_exit 78 79FEXPORT(ret_from_fork) 80 jal schedule_tail # a0 = struct task_struct *prev 81 82FEXPORT(syscall_exit) 83 local_irq_disable # make sure need_resched and 84 # signals dont change between 85 # sampling and return 86 LONG_L a2, TI_FLAGS($28) # current->work 87 li t0, _TIF_ALLWORK_MASK 88 and t0, a2, t0 89 bnez t0, syscall_exit_work 90 91restore_all: # restore full frame 92#ifdef CONFIG_MIPS_MT_SMTC 93#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP 94/* Re-arm any temporarily masked interrupts not explicitly "acked" */ 95 mfc0 v0, CP0_TCSTATUS 96 ori v1, v0, TCSTATUS_IXMT 97 mtc0 v1, CP0_TCSTATUS 98 andi v0, TCSTATUS_IXMT 99 _ehb 100 mfc0 t0, CP0_TCCONTEXT 101 DMT 9 # dmt t1 102 jal mips_ihb 103 mfc0 t2, CP0_STATUS 104 andi t3, t0, 0xff00 105 or t2, t2, t3 106 mtc0 t2, CP0_STATUS 107 _ehb 108 andi t1, t1, VPECONTROL_TE 109 beqz t1, 1f 110 EMT 1111: 112 mfc0 v1, CP0_TCSTATUS 113 /* We set IXMT above, XOR should clear it here */ 114 xori v1, v1, TCSTATUS_IXMT 115 or v1, v0, v1 116 mtc0 v1, CP0_TCSTATUS 117 _ehb 118 xor t0, t0, t3 119 mtc0 t0, CP0_TCCONTEXT 120#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ 121/* Detect and execute deferred IPI "interrupts" */ 122 LONG_L s0, TI_REGS($28) 123 LONG_S sp, TI_REGS($28) 124 jal deferred_smtc_ipi 125 LONG_S s0, TI_REGS($28) 126#endif /* CONFIG_MIPS_MT_SMTC */ 127 .set noat 128 RESTORE_TEMP 129 RESTORE_AT 130 RESTORE_STATIC 131restore_partial: # restore partial frame 132 LONG_L v0, PT_STATUS(sp) # returning to kernel mode? 133 andi v0, v0, KU_USER 134 beqz v0, 3f 135 LONG_L v0, TI_FLAGS($28) 136 and v0, _TIF_FPU_LOSE_REQUEST 137 beqz v0, 3f 138 SAVE_STATIC 139 SAVE_AT 140 SAVE_TEMP 141 jal mips_lose_fpu 142 RESTORE_TEMP 143 RESTORE_AT 144 RESTORE_STATIC 1453: 146#ifdef CONFIG_TRACE_IRQFLAGS 147 SAVE_STATIC 148 SAVE_AT 149 SAVE_TEMP 150 LONG_L v0, PT_STATUS(sp) 151#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) 152 and v0, ST0_IEP 153#else 154 and v0, ST0_IE 155#endif 156 beqz v0, 1f 157 jal trace_hardirqs_on 158 b 2f 1591: jal trace_hardirqs_off 1602: 161 RESTORE_TEMP 162 RESTORE_AT 163 RESTORE_STATIC 164#endif 165 RESTORE_SOME 166 RESTORE_SP_AND_RET 167 .set at 168 169work_pending: 170 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 171 beqz t0, work_notifysig 172work_resched: 173 jal schedule 174 175 local_irq_disable # make sure need_resched and 176 # signals dont change between 177 # sampling and return 178 LONG_L a2, TI_FLAGS($28) 179 andi t0, a2, _TIF_WORK_MASK # is there any work to be done 180 # other than syscall tracing? 181 beqz t0, restore_all 182 andi t0, a2, _TIF_NEED_RESCHED 183 bnez t0, work_resched 184 185work_notifysig: # deal with pending signals and 186 # notify-resume requests 187 move a0, sp 188 li a1, 0 189 jal do_notify_resume # a2 already loaded 190 j resume_userspace_check 191 192FEXPORT(syscall_exit_partial) 193 local_irq_disable # make sure need_resched doesn't 194 # change between and return 195 LONG_L a2, TI_FLAGS($28) # current->work 196 li t0, _TIF_ALLWORK_MASK 197 and t0, a2 198 beqz t0, restore_partial 199 SAVE_STATIC 200syscall_exit_work: 201 LONG_L t0, PT_STATUS(sp) # returning to kernel mode? 202 andi t0, t0, KU_USER 203 beqz t0, resume_kernel 204 li t0, _TIF_WORK_SYSCALL_EXIT 205 and t0, a2 # a2 is preloaded with TI_FLAGS 206 beqz t0, work_pending # trace bit set? 207 local_irq_enable # could let syscall_trace_leave() 208 # call schedule() instead 209 move a0, sp 210 jal syscall_trace_leave 211 b resume_userspace 212 213#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT) 214 215/* 216 * MIPS32R2 Instruction Hazard Barrier - must be called 217 * 218 * For C code use the inline version named instruction_hazard(). 219 */ 220#ifdef CONFIG_EVA 221 .align 8 222#endif 223LEAF(mips_ihb) 224#ifdef CONFIG_CPU_MIPSR6 225 .set mips64r6 226#else 227 .set mips32r2 228#endif 229 jr.hb ra 230 nop 231 .set mips0 232#ifdef CONFIG_EVA 233 .align 8 234#endif 235 END(mips_ihb) 236 237#endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */ 238