/*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/regdef.h>13#include <asm/mipsregs.h>14#include <asm/stackframe.h>15#include <asm/isadep.h>16#include <asm/thread_info.h>17#include <asm/war.h>18#ifdef CONFIG_MIPS_MT_SMTC19#include <asm/mipsmtregs.h>20#endif2122#ifndef CONFIG_PREEMPT23#define resume_kernel restore_all24#else25#define __ret_from_irq ret_from_exception26#endif2728.text29.align 530#ifndef CONFIG_PREEMPT31FEXPORT(ret_from_exception)32local_irq_disable # preempt stop33b __ret_from_irq34#endif35FEXPORT(ret_from_irq)36LONG_S s0, TI_REGS($28)37FEXPORT(__ret_from_irq)38LONG_L t0, PT_STATUS(sp) # returning to kernel mode?39andi t0, t0, KU_USER40beqz t0, resume_kernel4142resume_userspace:43local_irq_disable # make sure we dont miss an44# interrupt setting need_resched45# between sampling and return46LONG_L a2, TI_FLAGS($28) # current->work47andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace)48bnez t0, work_pending49j restore_all5051#ifdef CONFIG_PREEMPT52resume_kernel:53local_irq_disable54lw t0, TI_PRE_COUNT($28)55bnez t0, restore_all56need_resched:57LONG_L t0, TI_FLAGS($28)58andi t1, t0, _TIF_NEED_RESCHED59beqz t1, restore_all60LONG_L t0, PT_STATUS(sp) # Interrupts off?61andi t0, 162beqz t0, restore_all63jal preempt_schedule_irq64b need_resched65#endif6667FEXPORT(ret_from_fork)68jal schedule_tail # a0 = struct task_struct *prev6970FEXPORT(syscall_exit)71local_irq_disable # make sure need_resched and72# signals dont change between73# sampling and return74LONG_L a2, TI_FLAGS($28) # current->work75li t0, _TIF_ALLWORK_MASK76and t0, a2, t077bnez t0, syscall_exit_work7879FEXPORT(restore_all) # restore full frame80#ifdef CONFIG_MIPS_MT_SMTC81#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP82/* Re-arm any temporarily masked interrupts not explicitly "acked" */83mfc0 v0, CP0_TCSTATUS84ori v1, v0, TCSTATUS_IXMT85mtc0 v1, CP0_TCSTATUS86andi v0, TCSTATUS_IXMT87_ehb88mfc0 t0, CP0_TCCONTEXT89DMT 9 # dmt t190jal mips_ihb91mfc0 t2, CP0_STATUS92andi t3, t0, 0xff0093or t2, t2, t394mtc0 t2, CP0_STATUS95_ehb96andi t1, t1, VPECONTROL_TE97beqz t1, 1f98EMT991:100mfc0 v1, CP0_TCSTATUS101/* We set IXMT above, XOR should clear it here */102xori v1, v1, TCSTATUS_IXMT103or v1, v0, v1104mtc0 v1, CP0_TCSTATUS105_ehb106xor t0, t0, t3107mtc0 t0, CP0_TCCONTEXT108#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */109/* Detect and execute deferred IPI "interrupts" */110LONG_L s0, TI_REGS($28)111LONG_S sp, TI_REGS($28)112jal deferred_smtc_ipi113LONG_S s0, TI_REGS($28)114#endif /* CONFIG_MIPS_MT_SMTC */115.set noat116RESTORE_TEMP117RESTORE_AT118RESTORE_STATIC119FEXPORT(restore_partial) # restore partial frame120#ifdef CONFIG_TRACE_IRQFLAGS121SAVE_STATIC122SAVE_AT123SAVE_TEMP124LONG_L v0, PT_STATUS(sp)125#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)126and v0, ST0_IEP127#else128and v0, ST0_IE129#endif130beqz v0, 1f131jal trace_hardirqs_on132b 2f1331: jal trace_hardirqs_off1342:135RESTORE_TEMP136RESTORE_AT137RESTORE_STATIC138#endif139RESTORE_SOME140RESTORE_SP_AND_RET141.set at142143work_pending:144andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS145beqz t0, work_notifysig146work_resched:147jal schedule148149local_irq_disable # make sure need_resched and150# signals dont change between151# sampling and return152LONG_L a2, TI_FLAGS($28)153andi t0, a2, _TIF_WORK_MASK # is there any work to be done154# other than syscall tracing?155beqz t0, restore_all156andi t0, a2, _TIF_NEED_RESCHED157bnez t0, work_resched158159work_notifysig: # deal with pending signals and160# notify-resume requests161move a0, sp162li a1, 0163jal do_notify_resume # a2 already loaded164j resume_userspace165166FEXPORT(syscall_exit_work_partial)167SAVE_STATIC168syscall_exit_work:169li t0, _TIF_WORK_SYSCALL_EXIT170and t0, a2 # a2 is preloaded with TI_FLAGS171beqz t0, work_pending # trace bit set?172local_irq_enable # could let syscall_trace_leave()173# call schedule() instead174move a0, sp175jal syscall_trace_leave176b resume_userspace177178#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)179180/*181* MIPS32R2 Instruction Hazard Barrier - must be called182*183* For C code use the inline version named instruction_hazard().184*/185LEAF(mips_ihb)186.set mips32r2187jr.hb ra188nop189END(mips_ihb)190191#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */192193194