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/irqflags.h> 15#include <asm/regdef.h> 16#include <asm/mipsregs.h> 17#include <asm/stackframe.h> 18#include <asm/isadep.h> 19#include <asm/thread_info.h> 20 21#ifndef CONFIG_PREEMPTION 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_PREEMPTION 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 LONG_L a2, TI_FLAGS($28) # current->work 51 andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) 52 bnez t0, work_pending 53 j restore_all 54 55#ifdef CONFIG_PREEMPTION 56resume_kernel: 57 local_irq_disable 58 lw t0, TI_PRE_COUNT($28) 59 bnez t0, restore_all 60 LONG_L t0, TI_FLAGS($28) 61 andi t1, t0, _TIF_NEED_RESCHED 62 beqz t1, restore_all 63 LONG_L t0, PT_STATUS(sp) # Interrupts off? 64 andi t0, 1 65 beqz t0, restore_all 66 PTR_LA ra, restore_all 67 j preempt_schedule_irq 68#endif 69 70FEXPORT(ret_from_kernel_thread) 71 jal schedule_tail # a0 = struct task_struct *prev 72 move a0, s1 73 jal s0 74 j syscall_exit 75 76FEXPORT(ret_from_fork) 77 jal schedule_tail # a0 = struct task_struct *prev 78 79FEXPORT(syscall_exit) 80#ifdef CONFIG_DEBUG_RSEQ 81 move a0, sp 82 jal rseq_syscall 83#endif 84 local_irq_disable # make sure need_resched and 85 # signals dont change between 86 # sampling and return 87 LONG_L a2, TI_FLAGS($28) # current->work 88 li t0, _TIF_ALLWORK_MASK 89 and t0, a2, t0 90 bnez t0, syscall_exit_work 91 92restore_all: # restore full frame 93 .set noat 94 RESTORE_TEMP 95 RESTORE_AT 96 RESTORE_STATIC 97restore_partial: # restore partial frame 98#ifdef CONFIG_TRACE_IRQFLAGS 99 SAVE_STATIC 100 SAVE_AT 101 SAVE_TEMP 102 LONG_L v0, PT_STATUS(sp) 103#if defined(CONFIG_CPU_R3000) 104 and v0, ST0_IEP 105#else 106 and v0, ST0_IE 107#endif 108 beqz v0, 1f 109 jal trace_hardirqs_on 110 b 2f 1111: jal trace_hardirqs_off 1122: 113 RESTORE_TEMP 114 RESTORE_AT 115 RESTORE_STATIC 116#endif 117 RESTORE_SOME 118 RESTORE_SP_AND_RET 119 .set at 120 121work_pending: 122 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 123 beqz t0, work_notifysig 124work_resched: 125 TRACE_IRQS_OFF 126 jal schedule 127 128 local_irq_disable # make sure need_resched and 129 # signals dont change between 130 # sampling and return 131 LONG_L a2, TI_FLAGS($28) 132 andi t0, a2, _TIF_WORK_MASK # is there any work to be done 133 # other than syscall tracing? 134 beqz t0, restore_all 135 andi t0, a2, _TIF_NEED_RESCHED 136 bnez t0, work_resched 137 138work_notifysig: # deal with pending signals and 139 # notify-resume requests 140 move a0, sp 141 li a1, 0 142 jal do_notify_resume # a2 already loaded 143 j resume_userspace_check 144 145FEXPORT(syscall_exit_partial) 146#ifdef CONFIG_DEBUG_RSEQ 147 move a0, sp 148 jal rseq_syscall 149#endif 150 local_irq_disable # make sure need_resched doesn't 151 # change between and return 152 LONG_L a2, TI_FLAGS($28) # current->work 153 li t0, _TIF_ALLWORK_MASK 154 and t0, a2 155 beqz t0, restore_partial 156 SAVE_STATIC 157syscall_exit_work: 158 LONG_L t0, PT_STATUS(sp) # returning to kernel mode? 159 andi t0, t0, KU_USER 160 beqz t0, resume_kernel 161 li t0, _TIF_WORK_SYSCALL_EXIT 162 and t0, a2 # a2 is preloaded with TI_FLAGS 163 beqz t0, work_pending # trace bit set? 164 local_irq_enable # could let syscall_trace_leave() 165 # call schedule() instead 166 TRACE_IRQS_ON 167 move a0, sp 168 jal syscall_trace_leave 169 b resume_userspace 170 171#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \ 172 defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT) 173 174/* 175 * MIPS32R2 Instruction Hazard Barrier - must be called 176 * 177 * For C code use the inline version named instruction_hazard(). 178 */ 179LEAF(mips_ihb) 180 .set MIPS_ISA_LEVEL_RAW 181 jr.hb ra 182 nop 183 END(mips_ihb) 184 185#endif /* CONFIG_CPU_MIPSR2 - CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */ 186