linux/arch/mips/kernel/entry.S
<<
>>
Prefs
   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
  11#include <asm/asm.h>
  12#include <asm/asmmacro.h>
  13#include <asm/compiler.h>
  14#include <asm/irqflags.h>
  15#include <asm/regdef.h>
  16#include <asm/mipsregs.h>
  17#include <asm/stackframe.h>
  18#include <asm/isadep.h>
  19#include <asm/thread_info.h>
  20#include <asm/war.h>
  21
  22#ifndef CONFIG_PREEMPT
  23#define resume_kernel   restore_all
  24#else
  25#define __ret_from_irq  ret_from_exception
  26#endif
  27
  28        .text
  29        .align  5
  30#ifndef CONFIG_PREEMPT
  31FEXPORT(ret_from_exception)
  32        local_irq_disable                       # preempt stop
  33        b       __ret_from_irq
  34#endif
  35FEXPORT(ret_from_irq)
  36        LONG_S  s0, TI_REGS($28)
  37FEXPORT(__ret_from_irq)
  38/*
  39 * We can be coming here from a syscall done in the kernel space,
  40 * e.g. a failed kernel_execve().
  41 */
  42resume_userspace_check:
  43        LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
  44        andi    t0, t0, KU_USER
  45        beqz    t0, resume_kernel
  46
  47resume_userspace:
  48        local_irq_disable               # make sure we dont miss an
  49                                        # interrupt setting need_resched
  50                                        # between sampling and return
  51        LONG_L  a2, TI_FLAGS($28)       # current->work
  52        andi    t0, a2, _TIF_WORK_MASK  # (ignoring syscall_trace)
  53        bnez    t0, work_pending
  54        j       restore_all
  55
  56#ifdef CONFIG_PREEMPT
  57resume_kernel:
  58        local_irq_disable
  59        lw      t0, TI_PRE_COUNT($28)
  60        bnez    t0, restore_all
  61need_resched:
  62        LONG_L  t0, TI_FLAGS($28)
  63        andi    t1, t0, _TIF_NEED_RESCHED
  64        beqz    t1, restore_all
  65        LONG_L  t0, PT_STATUS(sp)               # Interrupts off?
  66        andi    t0, 1
  67        beqz    t0, restore_all
  68        jal     preempt_schedule_irq
  69        b       need_resched
  70#endif
  71
  72FEXPORT(ret_from_kernel_thread)
  73        jal     schedule_tail           # a0 = struct task_struct *prev
  74        move    a0, s1
  75        jal     s0
  76        j       syscall_exit
  77
  78FEXPORT(ret_from_fork)
  79        jal     schedule_tail           # a0 = struct task_struct *prev
  80
  81FEXPORT(syscall_exit)
  82#ifdef CONFIG_DEBUG_RSEQ
  83        move    a0, sp
  84        jal     rseq_syscall
  85#endif
  86        local_irq_disable               # make sure need_resched and
  87                                        # signals dont change between
  88                                        # sampling and return
  89        LONG_L  a2, TI_FLAGS($28)       # current->work
  90        li      t0, _TIF_ALLWORK_MASK
  91        and     t0, a2, t0
  92        bnez    t0, syscall_exit_work
  93
  94restore_all:                            # restore full frame
  95        .set    noat
  96        RESTORE_TEMP
  97        RESTORE_AT
  98        RESTORE_STATIC
  99restore_partial:                # restore partial frame
 100#ifdef CONFIG_TRACE_IRQFLAGS
 101        SAVE_STATIC
 102        SAVE_AT
 103        SAVE_TEMP
 104        LONG_L  v0, PT_STATUS(sp)
 105#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 106        and     v0, ST0_IEP
 107#else
 108        and     v0, ST0_IE
 109#endif
 110        beqz    v0, 1f
 111        jal     trace_hardirqs_on
 112        b       2f
 1131:      jal     trace_hardirqs_off
 1142:
 115        RESTORE_TEMP
 116        RESTORE_AT
 117        RESTORE_STATIC
 118#endif
 119        RESTORE_SOME
 120        RESTORE_SP_AND_RET
 121        .set    at
 122
 123work_pending:
 124        andi    t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
 125        beqz    t0, work_notifysig
 126work_resched:
 127        TRACE_IRQS_OFF
 128        jal     schedule
 129
 130        local_irq_disable               # make sure need_resched and
 131                                        # signals dont change between
 132                                        # sampling and return
 133        LONG_L  a2, TI_FLAGS($28)
 134        andi    t0, a2, _TIF_WORK_MASK  # is there any work to be done
 135                                        # other than syscall tracing?
 136        beqz    t0, restore_all
 137        andi    t0, a2, _TIF_NEED_RESCHED
 138        bnez    t0, work_resched
 139
 140work_notifysig:                         # deal with pending signals and
 141                                        # notify-resume requests
 142        move    a0, sp
 143        li      a1, 0
 144        jal     do_notify_resume        # a2 already loaded
 145        j       resume_userspace_check
 146
 147FEXPORT(syscall_exit_partial)
 148#ifdef CONFIG_DEBUG_RSEQ
 149        move    a0, sp
 150        jal     rseq_syscall
 151#endif
 152        local_irq_disable               # make sure need_resched doesn't
 153                                        # change between and return
 154        LONG_L  a2, TI_FLAGS($28)       # current->work
 155        li      t0, _TIF_ALLWORK_MASK
 156        and     t0, a2
 157        beqz    t0, restore_partial
 158        SAVE_STATIC
 159syscall_exit_work:
 160        LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
 161        andi    t0, t0, KU_USER
 162        beqz    t0, resume_kernel
 163        li      t0, _TIF_WORK_SYSCALL_EXIT
 164        and     t0, a2                  # a2 is preloaded with TI_FLAGS
 165        beqz    t0, work_pending        # trace bit set?
 166        local_irq_enable                # could let syscall_trace_leave()
 167                                        # call schedule() instead
 168        TRACE_IRQS_ON
 169        move    a0, sp
 170        jal     syscall_trace_leave
 171        b       resume_userspace
 172
 173#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \
 174    defined(CONFIG_MIPS_MT)
 175
 176/*
 177 * MIPS32R2 Instruction Hazard Barrier - must be called
 178 *
 179 * For C code use the inline version named instruction_hazard().
 180 */
 181LEAF(mips_ihb)
 182        .set    MIPS_ISA_LEVEL_RAW
 183        jr.hb   ra
 184        nop
 185        END(mips_ihb)
 186
 187#endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */
 188