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#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP 88/* Re-arm any temporarily masked interrupts not explicitly "acked" */ 89 mfc0 v0, CP0_TCSTATUS 90 ori v1, v0, TCSTATUS_IXMT 91 mtc0 v1, CP0_TCSTATUS 92 andi v0, TCSTATUS_IXMT 93 _ehb 94 mfc0 t0, CP0_TCCONTEXT 95 DMT 9 # dmt t1 96 jal mips_ihb 97 mfc0 t2, CP0_STATUS 98 andi t3, t0, 0xff00 99 or t2, t2, t3 100 mtc0 t2, CP0_STATUS 101 _ehb 102 andi t1, t1, VPECONTROL_TE 103 beqz t1, 1f 104 EMT 1051: 106 mfc0 v1, CP0_TCSTATUS 107 /* We set IXMT above, XOR should clear it here */ 108 xori v1, v1, TCSTATUS_IXMT 109 or v1, v0, v1 110 mtc0 v1, CP0_TCSTATUS 111 _ehb 112 xor t0, t0, t3 113 mtc0 t0, CP0_TCCONTEXT 114#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ 115#endif /* CONFIG_MIPS_MT_SMTC */ 116 .set noat 117 RESTORE_TEMP 118 RESTORE_AT 119 RESTORE_STATIC 120FEXPORT(restore_partial) # restore partial frame 121#ifdef CONFIG_TRACE_IRQFLAGS 122 SAVE_STATIC 123 SAVE_AT 124 SAVE_TEMP 125 LONG_L v0, PT_STATUS(sp) 126#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) 127 and v0, ST0_IEP 128#else 129 and v0, ST0_IE 130#endif 131 beqz v0, 1f 132 jal trace_hardirqs_on 133 b 2f 1341: jal trace_hardirqs_off 1352: 136 RESTORE_TEMP 137 RESTORE_AT 138 RESTORE_STATIC 139#endif 140 RESTORE_SOME 141 RESTORE_SP_AND_RET 142 .set at 143 144work_pending: 145 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 146 beqz t0, work_notifysig 147work_resched: 148 jal schedule 149 150 local_irq_disable # make sure need_resched and 151 # signals dont change between 152 # sampling and return 153 LONG_L a2, TI_FLAGS($28) 154 andi t0, a2, _TIF_WORK_MASK # is there any work to be done 155 # other than syscall tracing? 156 beqz t0, restore_all 157 andi t0, a2, _TIF_NEED_RESCHED 158 bnez t0, work_resched 159 160work_notifysig: # deal with pending signals and 161 # notify-resume requests 162 move a0, sp 163 li a1, 0 164 jal do_notify_resume # a2 already loaded 165 j resume_userspace 166 167FEXPORT(syscall_exit_work_partial) 168 SAVE_STATIC 169syscall_exit_work: 170 li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT 171 and t0, a2 # a2 is preloaded with TI_FLAGS 172 beqz t0, work_pending # trace bit set? 173 local_irq_enable # could let do_syscall_trace() 174 # call schedule() instead 175 move a0, sp 176 li a1, 1 177 jal do_syscall_trace 178 b resume_userspace 179 180#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT) 181 182/* 183 * MIPS32R2 Instruction Hazard Barrier - must be called 184 * 185 * For C code use the inline version named instruction_hazard(). 186 */ 187LEAF(mips_ihb) 188 .set mips32r2 189 jr.hb ra 190 nop 191 END(mips_ihb) 192 193#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */ 194