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/regdef.h>
  15#include <asm/mipsregs.h>
  16#include <asm/stackframe.h>
  17#include <asm/isadep.h>
  18#include <asm/thread_info.h>
  19#include <asm/war.h>
  20
  21#ifndef CONFIG_PREEMPT
  22#define resume_kernel   restore_all
  23#else
  24#define __ret_from_irq  ret_from_exception
  25#endif
  26
  27        .text
  28        .align  5
  29#ifndef CONFIG_PREEMPT
  30FEXPORT(ret_from_exception)
  31        local_irq_disable                       # preempt stop
  32        b       __ret_from_irq
  33#endif
  34FEXPORT(ret_from_irq)
  35        LONG_S  s0, TI_REGS($28)
  36FEXPORT(__ret_from_irq)
  37/*
  38 * We can be coming here from a syscall done in the kernel space,
  39 * e.g. a failed kernel_execve().
  40 */
  41resume_userspace_check:
  42        LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
  43        andi    t0, t0, KU_USER
  44        beqz    t0, resume_kernel
  45
  46resume_userspace:
  47        local_irq_disable               # make sure we dont miss an
  48                                        # interrupt setting need_resched
  49                                        # between sampling and return
  50#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
  51        lw      k0, TI_R2_EMUL_RET($28)
  52        bnez    k0, restore_all_from_r2_emul
  53#endif
  54
  55        LONG_L  a2, TI_FLAGS($28)       # current->work
  56        andi    t0, a2, _TIF_WORK_MASK  # (ignoring syscall_trace)
  57        bnez    t0, work_pending
  58        j       restore_all
  59
  60#ifdef CONFIG_PREEMPT
  61resume_kernel:
  62        local_irq_disable
  63        lw      t0, TI_PRE_COUNT($28)
  64        bnez    t0, restore_all
  65need_resched:
  66        LONG_L  t0, TI_FLAGS($28)
  67        andi    t1, t0, _TIF_NEED_RESCHED
  68        beqz    t1, restore_all
  69        LONG_L  t0, PT_STATUS(sp)               # Interrupts off?
  70        andi    t0, 1
  71        beqz    t0, restore_all
  72        jal     preempt_schedule_irq
  73        b       need_resched
  74#endif
  75
  76FEXPORT(ret_from_kernel_thread)
  77        jal     schedule_tail           # a0 = struct task_struct *prev
  78        move    a0, s1
  79        jal     s0
  80        j       syscall_exit
  81
  82FEXPORT(ret_from_fork)
  83        jal     schedule_tail           # a0 = struct task_struct *prev
  84
  85FEXPORT(syscall_exit)
  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
 123#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
 124restore_all_from_r2_emul:                       # restore full frame
 125        .set    noat
 126        sw      zero, TI_R2_EMUL_RET($28)       # reset it
 127        RESTORE_TEMP
 128        RESTORE_AT
 129        RESTORE_STATIC
 130        RESTORE_SOME
 131        LONG_L  sp, PT_R29(sp)
 132        eretnc
 133        .set    at
 134#endif
 135
 136work_pending:
 137        andi    t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
 138        beqz    t0, work_notifysig
 139work_resched:
 140        jal     schedule
 141
 142        local_irq_disable               # make sure need_resched and
 143                                        # signals dont change between
 144                                        # sampling and return
 145        LONG_L  a2, TI_FLAGS($28)
 146        andi    t0, a2, _TIF_WORK_MASK  # is there any work to be done
 147                                        # other than syscall tracing?
 148        beqz    t0, restore_all
 149        andi    t0, a2, _TIF_NEED_RESCHED
 150        bnez    t0, work_resched
 151
 152work_notifysig:                         # deal with pending signals and
 153                                        # notify-resume requests
 154        move    a0, sp
 155        li      a1, 0
 156        jal     do_notify_resume        # a2 already loaded
 157        j       resume_userspace_check
 158
 159FEXPORT(syscall_exit_partial)
 160        local_irq_disable               # make sure need_resched doesn't
 161                                        # change between and return
 162        LONG_L  a2, TI_FLAGS($28)       # current->work
 163        li      t0, _TIF_ALLWORK_MASK
 164        and     t0, a2
 165        beqz    t0, restore_partial
 166        SAVE_STATIC
 167syscall_exit_work:
 168        LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
 169        andi    t0, t0, KU_USER
 170        beqz    t0, resume_kernel
 171        li      t0, _TIF_WORK_SYSCALL_EXIT
 172        and     t0, a2                  # a2 is preloaded with TI_FLAGS
 173        beqz    t0, work_pending        # trace bit set?
 174        local_irq_enable                # could let syscall_trace_leave()
 175                                        # call schedule() instead
 176        move    a0, sp
 177        jal     syscall_trace_leave
 178        b       resume_userspace
 179
 180#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \
 181    defined(CONFIG_MIPS_MT)
 182
 183/*
 184 * MIPS32R2 Instruction Hazard Barrier - must be called
 185 *
 186 * For C code use the inline version named instruction_hazard().
 187 */
 188LEAF(mips_ihb)
 189        .set    MIPS_ISA_LEVEL_RAW
 190        jr.hb   ra
 191        nop
 192        END(mips_ihb)
 193
 194#endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */
 195