/*1* This file is subject to the terms and conditions of the GNU General Public2* License. See the file "COPYING" in the main directory of this archive3* for more details.4*5* Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle6* Copyright (C) 1999, 2000 Silicon Graphics, Inc.7* Copyright (C) 2001 MIPS Technologies, Inc.8*/910#include <asm/asm.h>11#include <asm/asmmacro.h>12#include <asm/compiler.h>13#include <asm/irqflags.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>1920#ifndef CONFIG_PREEMPTION21#define resume_kernel restore_all22#else23#define __ret_from_irq ret_from_exception24#endif2526.text27.align 528#ifndef CONFIG_PREEMPTION29FEXPORT(ret_from_exception)30local_irq_disable # preempt stop31b __ret_from_irq32#endif33FEXPORT(ret_from_irq)34LONG_S s0, TI_REGS($28)35FEXPORT(__ret_from_irq)36/*37* We can be coming here from a syscall done in the kernel space,38* e.g. a failed kernel_execve().39*/40resume_userspace_check:41LONG_L t0, PT_STATUS(sp) # returning to kernel mode?42andi t0, t0, KU_USER43beqz t0, resume_kernel4445resume_userspace:46local_irq_disable # make sure we dont miss an47# interrupt setting need_resched48# between sampling and return49LONG_L a2, TI_FLAGS($28) # current->work50andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace)51bnez t0, work_pending52j restore_all5354#ifdef CONFIG_PREEMPTION55resume_kernel:56local_irq_disable57lw t0, TI_PRE_COUNT($28)58bnez t0, restore_all59LONG_L t0, TI_FLAGS($28)60andi t1, t0, _TIF_NEED_RESCHED61beqz t1, restore_all62LONG_L t0, PT_STATUS(sp) # Interrupts off?63andi t0, 164beqz t0, restore_all65PTR_LA ra, restore_all66j preempt_schedule_irq67#endif6869FEXPORT(ret_from_kernel_thread)70jal schedule_tail # a0 = struct task_struct *prev71move a0, s172jal s073j syscall_exit7475FEXPORT(ret_from_fork)76jal schedule_tail # a0 = struct task_struct *prev7778FEXPORT(syscall_exit)79#ifdef CONFIG_DEBUG_RSEQ80move a0, sp81jal rseq_syscall82#endif83local_irq_disable # make sure need_resched and84# signals dont change between85# sampling and return86LONG_L a2, TI_FLAGS($28) # current->work87li t0, _TIF_ALLWORK_MASK88and t0, a2, t089bnez t0, syscall_exit_work9091restore_all: # restore full frame92.set noat93RESTORE_TEMP94RESTORE_AT95RESTORE_STATIC96restore_partial: # restore partial frame97#ifdef CONFIG_TRACE_IRQFLAGS98SAVE_STATIC99SAVE_AT100SAVE_TEMP101LONG_L v0, PT_STATUS(sp)102#if defined(CONFIG_CPU_R3000)103and v0, ST0_IEP104#else105and v0, ST0_IE106#endif107beqz v0, 1f108jal trace_hardirqs_on109b 2f1101: jal trace_hardirqs_off1112:112RESTORE_TEMP113RESTORE_AT114RESTORE_STATIC115#endif116RESTORE_SOME117RESTORE_SP_AND_RET118.set at119120work_pending:121andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS122beqz t0, work_notifysig123work_resched:124TRACE_IRQS_OFF125jal schedule126127local_irq_disable # make sure need_resched and128# signals dont change between129# sampling and return130LONG_L a2, TI_FLAGS($28)131andi t0, a2, _TIF_WORK_MASK # is there any work to be done132# other than syscall tracing?133beqz t0, restore_all134andi t0, a2, _TIF_NEED_RESCHED135bnez t0, work_resched136137work_notifysig: # deal with pending signals and138# notify-resume requests139move a0, sp140li a1, 0141jal do_notify_resume # a2 already loaded142j resume_userspace_check143144FEXPORT(syscall_exit_partial)145#ifdef CONFIG_DEBUG_RSEQ146move a0, sp147jal rseq_syscall148#endif149local_irq_disable # make sure need_resched doesn't150# change between and return151LONG_L a2, TI_FLAGS($28) # current->work152li t0, _TIF_ALLWORK_MASK153and t0, a2154beqz t0, restore_partial155SAVE_STATIC156syscall_exit_work:157LONG_L t0, PT_STATUS(sp) # returning to kernel mode?158andi t0, t0, KU_USER159beqz t0, resume_kernel160li t0, _TIF_WORK_SYSCALL_EXIT161and t0, a2 # a2 is preloaded with TI_FLAGS162beqz t0, work_pending # trace bit set?163local_irq_enable # could let syscall_trace_leave()164# call schedule() instead165TRACE_IRQS_ON166move a0, sp167jal syscall_trace_leave168b resume_userspace169170#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \171defined(CONFIG_CPU_MIPSR6) || defined(CONFIG_MIPS_MT)172173/*174* MIPS32R2 Instruction Hazard Barrier - must be called175*176* For C code use the inline version named instruction_hazard().177*/178LEAF(mips_ihb)179.set MIPS_ISA_LEVEL_RAW180jr.hb ra181nop182END(mips_ihb)183184#endif /* CONFIG_CPU_MIPSR2 - CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */185186187