123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- /*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2001 MIPS Technologies, Inc.
- */
- #include <linux/config.h>
- #include <asm/asm.h>
- #include <asm/asmmacro.h>
- #include <asm/regdef.h>
- #include <asm/mipsregs.h>
- #include <asm/stackframe.h>
- #include <asm/isadep.h>
- #include <asm/thread_info.h>
- #include <asm/war.h>
- #ifdef CONFIG_PREEMPT
- .macro preempt_stop reg=t0
- .endm
- #else
- .macro preempt_stop reg=t0
- local_irq_disable \reg
- .endm
- #define resume_kernel restore_all
- #endif
- .text
- .align 5
- FEXPORT(ret_from_exception)
- preempt_stop
- FEXPORT(ret_from_irq)
- LONG_L t0, PT_STATUS(sp) # returning to kernel mode?
- andi t0, t0, KU_USER
- beqz t0, resume_kernel
- FEXPORT(resume_userspace)
- local_irq_disable t0 # make sure we dont miss an
- # interrupt setting need_resched
- # between sampling and return
- LONG_L a2, TI_FLAGS($28) # current->work
- andi a2, _TIF_WORK_MASK # (ignoring syscall_trace)
- bnez a2, work_pending
- j restore_all
- #ifdef CONFIG_PREEMPT
- ENTRY(resume_kernel)
- lw t0, TI_PRE_COUNT($28)
- bnez t0, restore_all
- need_resched:
- LONG_L t0, TI_FLAGS($28)
- andi t1, t0, _TIF_NEED_RESCHED
- beqz t1, restore_all
- LONG_L t0, PT_STATUS(sp) # Interrupts off?
- andi t0, 1
- beqz t0, restore_all
- li t0, PREEMPT_ACTIVE
- sw t0, TI_PRE_COUNT($28)
- local_irq_enable t0
- jal schedule
- sw zero, TI_PRE_COUNT($28)
- local_irq_disable t0
- b need_resched
- #endif
- FEXPORT(ret_from_fork)
- jal schedule_tail # a0 = task_t *prev
- FEXPORT(syscall_exit)
- local_irq_disable # make sure need_resched and
- # signals dont change between
- # sampling and return
- LONG_L a2, TI_FLAGS($28) # current->work
- li t0, _TIF_ALLWORK_MASK
- and t0, a2, t0
- bnez t0, syscall_exit_work
- FEXPORT(restore_all) # restore full frame
- .set noat
- RESTORE_TEMP
- RESTORE_AT
- RESTORE_STATIC
- FEXPORT(restore_partial) # restore partial frame
- RESTORE_SOME
- RESTORE_SP_AND_RET
- .set at
- FEXPORT(work_pending)
- andi t0, a2, _TIF_NEED_RESCHED
- beqz t0, work_notifysig
- work_resched:
- jal schedule
- local_irq_disable t0 # make sure need_resched and
- # signals dont change between
- # sampling and return
- LONG_L a2, TI_FLAGS($28)
- andi t0, a2, _TIF_WORK_MASK # is there any work to be done
- # other than syscall tracing?
- beqz t0, restore_all
- andi t0, a2, _TIF_NEED_RESCHED
- bnez t0, work_resched
- work_notifysig: # deal with pending signals and
- # notify-resume requests
- move a0, sp
- li a1, 0
- jal do_notify_resume # a2 already loaded
- j restore_all
- FEXPORT(syscall_exit_work_partial)
- SAVE_STATIC
- FEXPORT(syscall_exit_work)
- LONG_L t0, TI_FLAGS($28)
- li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
- and t0, t1
- beqz t0, work_pending # trace bit is set
- local_irq_enable # could let do_syscall_trace()
- # call schedule() instead
- move a0, sp
- li a1, 1
- jal do_syscall_trace
- b resume_userspace
- /*
- * Common spurious interrupt handler.
- */
- .text
- .align 5
- LEAF(spurious_interrupt)
- /*
- * Someone tried to fool us by sending an interrupt but we
- * couldn't find a cause for it.
- */
- #ifdef CONFIG_SMP
- lui t1, %hi(irq_err_count)
- 1: ll t0, %lo(irq_err_count)(t1)
- addiu t0, 1
- sc t0, %lo(irq_err_count)(t1)
- #if R10000_LLSC_WAR
- beqzl t0, 1b
- #else
- beqz t0, 1b
- #endif
- #else
- lui t1, %hi(irq_err_count)
- lw t0, %lo(irq_err_count)(t1)
- addiu t0, 1
- sw t0, %lo(irq_err_count)(t1)
- #endif
- j ret_from_irq
- END(spurious_interrupt)
|