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 and v0, 1 125 beqz v0, 1f 126 jal trace_hardirqs_on 127 b 2f 1281: jal trace_hardirqs_off 1292: 130 RESTORE_TEMP 131 RESTORE_AT 132 RESTORE_STATIC 133#endif 134 RESTORE_SOME 135 RESTORE_SP_AND_RET 136 .set at 137 138work_pending: 139 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 140 beqz t0, work_notifysig 141work_resched: 142 jal schedule 143 144 local_irq_disable # make sure need_resched and 145 # signals dont change between 146 # sampling and return 147 LONG_L a2, TI_FLAGS($28) 148 andi t0, a2, _TIF_WORK_MASK # is there any work to be done 149 # other than syscall tracing? 150 beqz t0, restore_all 151 andi t0, a2, _TIF_NEED_RESCHED 152 bnez t0, work_resched 153 154work_notifysig: # deal with pending signals and 155 # notify-resume requests 156 move a0, sp 157 li a1, 0 158 jal do_notify_resume # a2 already loaded 159 j resume_userspace 160 161FEXPORT(syscall_exit_work_partial) 162 SAVE_STATIC 163syscall_exit_work: 164 li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT 165 and t0, a2 # a2 is preloaded with TI_FLAGS 166 beqz t0, work_pending # trace bit set? 167 local_irq_enable # could let do_syscall_trace() 168 # call schedule() instead 169 move a0, sp 170 li a1, 1 171 jal do_syscall_trace 172 b resume_userspace 173 174#if defined(CONFIG_CPU_MIPSR2) || 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 mips32r2 183 jr.hb ra 184 nop 185 END(mips_ihb) 186 187#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */ 188