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 LONG_L t0, PT_STATUS(sp) # returning to kernel mode? 40 andi t0, t0, KU_USER 41 beqz t0, resume_kernel 42 43resume_userspace: 44 local_irq_disable # make sure we dont miss an 45 # interrupt setting need_resched 46 # between sampling and return 47 LONG_L a2, TI_FLAGS($28) # current->work 48 andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) 49 bnez t0, work_pending 50 j restore_all 51 52#ifdef CONFIG_PREEMPT 53resume_kernel: 54 local_irq_disable 55 lw t0, TI_PRE_COUNT($28) 56 bnez t0, restore_all 57need_resched: 58 LONG_L t0, TI_FLAGS($28) 59 andi t1, t0, _TIF_NEED_RESCHED 60 beqz t1, restore_all 61 LONG_L t0, PT_STATUS(sp) # Interrupts off? 62 andi t0, 1 63 beqz t0, restore_all 64 jal preempt_schedule_irq 65 b need_resched 66#endif 67 68FEXPORT(ret_from_fork) 69 jal schedule_tail # a0 = struct task_struct *prev 70 71FEXPORT(syscall_exit) 72 local_irq_disable # make sure need_resched and 73 # signals dont change between 74 # sampling and return 75 LONG_L a2, TI_FLAGS($28) # current->work 76 li t0, _TIF_ALLWORK_MASK 77 and t0, a2, t0 78 bnez t0, syscall_exit_work 79 80FEXPORT(restore_all) # restore full frame 81#ifdef CONFIG_MIPS_MT_SMTC 82/* Detect and execute deferred IPI "interrupts" */ 83 LONG_L s0, TI_REGS($28) 84 LONG_S sp, TI_REGS($28) 85 jal deferred_smtc_ipi 86 LONG_S s0, TI_REGS($28) 87/* Re-arm any temporarily masked interrupts not explicitly "acked" */ 88 mfc0 v0, CP0_TCSTATUS 89 ori v1, v0, TCSTATUS_IXMT 90 mtc0 v1, CP0_TCSTATUS 91 andi v0, TCSTATUS_IXMT 92 _ehb 93 mfc0 t0, CP0_TCCONTEXT 94 DMT 9 # dmt t1 95 jal mips_ihb 96 mfc0 t2, CP0_STATUS 97 andi t3, t0, 0xff00 98 or t2, t2, t3 99 mtc0 t2, CP0_STATUS 100 _ehb 101 andi t1, t1, VPECONTROL_TE 102 beqz t1, 1f 103 EMT 1041: 105 mfc0 v1, CP0_TCSTATUS 106 /* We set IXMT above, XOR should clear it here */ 107 xori v1, v1, TCSTATUS_IXMT 108 or v1, v0, v1 109 mtc0 v1, CP0_TCSTATUS 110 _ehb 111 xor t0, t0, t3 112 mtc0 t0, CP0_TCCONTEXT 113#endif /* CONFIG_MIPS_MT_SMTC */ 114 .set noat 115 RESTORE_TEMP 116 RESTORE_AT 117 RESTORE_STATIC 118FEXPORT(restore_partial) # restore partial frame 119#ifdef CONFIG_TRACE_IRQFLAGS 120 SAVE_STATIC 121 SAVE_AT 122 SAVE_TEMP 123 LONG_L v0, PT_STATUS(sp) 124#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) 125 and v0, ST0_IEP 126#else 127 and v0, ST0_IE 128#endif 129 beqz v0, 1f 130 jal trace_hardirqs_on 131 b 2f 1321: jal trace_hardirqs_off 1332: 134 RESTORE_TEMP 135 RESTORE_AT 136 RESTORE_STATIC 137#endif 138 RESTORE_SOME 139 RESTORE_SP_AND_RET 140 .set at 141 142work_pending: 143 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 144 beqz t0, work_notifysig 145work_resched: 146 jal schedule 147 148 local_irq_disable # make sure need_resched and 149 # signals dont change between 150 # sampling and return 151 LONG_L a2, TI_FLAGS($28) 152 andi t0, a2, _TIF_WORK_MASK # is there any work to be done 153 # other than syscall tracing? 154 beqz t0, restore_all 155 andi t0, a2, _TIF_NEED_RESCHED 156 bnez t0, work_resched 157 158work_notifysig: # deal with pending signals and 159 # notify-resume requests 160 move a0, sp 161 li a1, 0 162 jal do_notify_resume # a2 already loaded 163 j resume_userspace 164 165FEXPORT(syscall_exit_work_partial) 166 SAVE_STATIC 167syscall_exit_work: 168 li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT 169 and t0, a2 # a2 is preloaded with TI_FLAGS 170 beqz t0, work_pending # trace bit set? 171 local_irq_enable # could let do_syscall_trace() 172 # call schedule() instead 173 move a0, sp 174 li a1, 1 175 jal do_syscall_trace 176 b resume_userspace 177 178#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT) 179 180/* 181 * MIPS32R2 Instruction Hazard Barrier - must be called 182 * 183 * For C code use the inline version named instruction_hazard(). 184 */ 185LEAF(mips_ihb) 186 .set mips32r2 187 jr.hb ra 188 nop 189 END(mips_ihb) 190 191#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */ 192