From 57f0f512b273f60d52568b8c6b77e17f5636edc0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Wed, 5 Aug 2015 17:04:01 -0300 Subject: Initial import --- arch/mips/kernel/entry.S | 194 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 arch/mips/kernel/entry.S (limited to 'arch/mips/kernel/entry.S') diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S new file mode 100644 index 000000000..7791840cf --- /dev/null +++ b/arch/mips/kernel/entry.S @@ -0,0 +1,194 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_PREEMPT +#define resume_kernel restore_all +#else +#define __ret_from_irq ret_from_exception +#endif + + .text + .align 5 +#ifndef CONFIG_PREEMPT +FEXPORT(ret_from_exception) + local_irq_disable # preempt stop + b __ret_from_irq +#endif +FEXPORT(ret_from_irq) + LONG_S s0, TI_REGS($28) +FEXPORT(__ret_from_irq) +/* + * We can be coming here from a syscall done in the kernel space, + * e.g. a failed kernel_execve(). + */ +resume_userspace_check: + LONG_L t0, PT_STATUS(sp) # returning to kernel mode? + andi t0, t0, KU_USER + beqz t0, resume_kernel + +resume_userspace: + local_irq_disable # make sure we dont miss an + # interrupt setting need_resched + # between sampling and return +#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR + lw k0, TI_R2_EMUL_RET($28) + bnez k0, restore_all_from_r2_emul +#endif + + LONG_L a2, TI_FLAGS($28) # current->work + andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) + bnez t0, work_pending + j restore_all + +#ifdef CONFIG_PREEMPT +resume_kernel: + local_irq_disable + 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 + jal preempt_schedule_irq + b need_resched +#endif + +FEXPORT(ret_from_kernel_thread) + jal schedule_tail # a0 = struct task_struct *prev + move a0, s1 + jal s0 + j syscall_exit + +FEXPORT(ret_from_fork) + jal schedule_tail # a0 = struct task_struct *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 + +restore_all: # restore full frame + .set noat + RESTORE_TEMP + RESTORE_AT + RESTORE_STATIC +restore_partial: # restore partial frame +#ifdef CONFIG_TRACE_IRQFLAGS + SAVE_STATIC + SAVE_AT + SAVE_TEMP + LONG_L v0, PT_STATUS(sp) +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + and v0, ST0_IEP +#else + and v0, ST0_IE +#endif + beqz v0, 1f + jal trace_hardirqs_on + b 2f +1: jal trace_hardirqs_off +2: + RESTORE_TEMP + RESTORE_AT + RESTORE_STATIC +#endif + RESTORE_SOME + RESTORE_SP_AND_RET + .set at + +#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR +restore_all_from_r2_emul: # restore full frame + .set noat + sw zero, TI_R2_EMUL_RET($28) # reset it + RESTORE_TEMP + RESTORE_AT + RESTORE_STATIC + RESTORE_SOME + LONG_L sp, PT_R29(sp) + eretnc + .set at +#endif + +work_pending: + andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS + beqz t0, work_notifysig +work_resched: + jal schedule + + local_irq_disable # 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 resume_userspace_check + +FEXPORT(syscall_exit_partial) + local_irq_disable # make sure need_resched doesn't + # change between and return + LONG_L a2, TI_FLAGS($28) # current->work + li t0, _TIF_ALLWORK_MASK + and t0, a2 + beqz t0, restore_partial + SAVE_STATIC +syscall_exit_work: + LONG_L t0, PT_STATUS(sp) # returning to kernel mode? + andi t0, t0, KU_USER + beqz t0, resume_kernel + li t0, _TIF_WORK_SYSCALL_EXIT + and t0, a2 # a2 is preloaded with TI_FLAGS + beqz t0, work_pending # trace bit set? + local_irq_enable # could let syscall_trace_leave() + # call schedule() instead + move a0, sp + jal syscall_trace_leave + b resume_userspace + +#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \ + defined(CONFIG_MIPS_MT) + +/* + * MIPS32R2 Instruction Hazard Barrier - must be called + * + * For C code use the inline version named instruction_hazard(). + */ +LEAF(mips_ihb) + .set MIPS_ISA_LEVEL_RAW + jr.hb ra + nop + END(mips_ihb) + +#endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */ -- cgit v1.2.3-54-g00ecf