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#include <linux/config.h> 11 12#include <asm/asm.h> 13#include <asm/asmmacro.h> 14#include <asm/regdef.h> 15#include <asm/mipsregs.h> 16#include <asm/stackframe.h> 17#include <asm/isadep.h> 18#include <asm/thread_info.h> 19#include <asm/war.h> 20 21#ifdef CONFIG_PREEMPT 22 .macro preempt_stop 23 .endm 24#else 25 .macro preempt_stop 26 local_irq_disable 27 .endm 28#define resume_kernel restore_all 29#endif 30 31 .text 32 .align 5 33FEXPORT(ret_from_exception) 34 preempt_stop 35FEXPORT(ret_from_irq) 36 LONG_L t0, PT_STATUS(sp) # returning to kernel mode? 37 andi t0, t0, KU_USER 38 beqz t0, resume_kernel 39 40resume_userspace: 41 local_irq_disable # make sure we dont miss an 42 # interrupt setting need_resched 43 # between sampling and return 44 LONG_L a2, TI_FLAGS($28) # current->work 45 andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) 46 bnez t0, work_pending 47 j restore_all 48 49#ifdef CONFIG_PREEMPT 50resume_kernel: 51 local_irq_disable 52 lw t0, TI_PRE_COUNT($28) 53 bnez t0, restore_all 54need_resched: 55 LONG_L t0, TI_FLAGS($28) 56 andi t1, t0, _TIF_NEED_RESCHED 57 beqz t1, restore_all 58 LONG_L t0, PT_STATUS(sp) # Interrupts off? 59 andi t0, 1 60 beqz t0, restore_all 61 jal preempt_schedule_irq 62 b need_resched 63#endif 64 65FEXPORT(ret_from_fork) 66 jal schedule_tail # a0 = task_t *prev 67 68FEXPORT(syscall_exit) 69 local_irq_disable # make sure need_resched and 70 # signals dont change between 71 # sampling and return 72 LONG_L a2, TI_FLAGS($28) # current->work 73 li t0, _TIF_ALLWORK_MASK 74 and t0, a2, t0 75 bnez t0, syscall_exit_work 76 77FEXPORT(restore_all) # restore full frame 78 .set noat 79 RESTORE_TEMP 80 RESTORE_AT 81 RESTORE_STATIC 82FEXPORT(restore_partial) # restore partial frame 83 RESTORE_SOME 84 RESTORE_SP_AND_RET 85 .set at 86 87work_pending: 88 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 89 beqz t0, work_notifysig 90work_resched: 91 jal schedule 92 93 local_irq_disable # make sure need_resched and 94 # signals dont change between 95 # sampling and return 96 LONG_L a2, TI_FLAGS($28) 97 andi t0, a2, _TIF_WORK_MASK # is there any work to be done 98 # other than syscall tracing? 99 beqz t0, restore_all 100 andi t0, a2, _TIF_NEED_RESCHED 101 bnez t0, work_resched 102 103work_notifysig: # deal with pending signals and 104 # notify-resume requests 105 move a0, sp 106 li a1, 0 107 jal do_notify_resume # a2 already loaded 108 j resume_userspace 109 110FEXPORT(syscall_exit_work_partial) 111 SAVE_STATIC 112syscall_exit_work: 113 li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT 114 and t0, a2 # a2 is preloaded with TI_FLAGS 115 beqz t0, work_pending # trace bit set? 116 local_irq_enable # could let do_syscall_trace() 117 # call schedule() instead 118 move a0, sp 119 li a1, 1 120 jal do_syscall_trace 121 b resume_userspace 122 123/* 124 * Common spurious interrupt handler. 125 */ 126LEAF(spurious_interrupt) 127 /* 128 * Someone tried to fool us by sending an interrupt but we 129 * couldn't find a cause for it. 130 */ 131 PTR_LA t1, irq_err_count 132#ifdef CONFIG_SMP 1331: ll t0, (t1) 134 addiu t0, 1 135 sc t0, (t1) 136#if R10000_LLSC_WAR 137 beqzl t0, 1b 138#else 139 beqz t0, 1b 140#endif 141#else 142 lw t0, (t1) 143 addiu t0, 1 144 sw t0, (t1) 145#endif 146 j ret_from_irq 147 END(spurious_interrupt) 148