root/arch/mips/kernel/entry.S

/* [<][>][^][v][top][bottom][index][help] */
   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
  31 FEXPORT(ret_from_exception)
  32         local_irq_disable                       # preempt stop
  33         b       __ret_from_irq
  34 #endif
  35 FEXPORT(ret_from_irq)
  36         LONG_S  s0, TI_REGS($28)
  37 FEXPORT(__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  */
  42 resume_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 
  47 resume_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
  57 resume_kernel:
  58         local_irq_disable
  59         lw      t0, TI_PRE_COUNT($28)
  60         bnez    t0, restore_all
  61         LONG_L  t0, TI_FLAGS($28)
  62         andi    t1, t0, _TIF_NEED_RESCHED
  63         beqz    t1, restore_all
  64         LONG_L  t0, PT_STATUS(sp)               # Interrupts off?
  65         andi    t0, 1
  66         beqz    t0, restore_all
  67         PTR_LA  ra, restore_all
  68         j       preempt_schedule_irq
  69 #endif
  70 
  71 FEXPORT(ret_from_kernel_thread)
  72         jal     schedule_tail           # a0 = struct task_struct *prev
  73         move    a0, s1
  74         jal     s0
  75         j       syscall_exit
  76 
  77 FEXPORT(ret_from_fork)
  78         jal     schedule_tail           # a0 = struct task_struct *prev
  79 
  80 FEXPORT(syscall_exit)
  81 #ifdef CONFIG_DEBUG_RSEQ
  82         move    a0, sp
  83         jal     rseq_syscall
  84 #endif
  85         local_irq_disable               # make sure need_resched and
  86                                         # signals dont change between
  87                                         # sampling and return
  88         LONG_L  a2, TI_FLAGS($28)       # current->work
  89         li      t0, _TIF_ALLWORK_MASK
  90         and     t0, a2, t0
  91         bnez    t0, syscall_exit_work
  92 
  93 restore_all:                            # restore full frame
  94         .set    noat
  95         RESTORE_TEMP
  96         RESTORE_AT
  97         RESTORE_STATIC
  98 restore_partial:                # restore partial frame
  99 #ifdef CONFIG_TRACE_IRQFLAGS
 100         SAVE_STATIC
 101         SAVE_AT
 102         SAVE_TEMP
 103         LONG_L  v0, PT_STATUS(sp)
 104 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 105         and     v0, ST0_IEP
 106 #else
 107         and     v0, ST0_IE
 108 #endif
 109         beqz    v0, 1f
 110         jal     trace_hardirqs_on
 111         b       2f
 112 1:      jal     trace_hardirqs_off
 113 2:
 114         RESTORE_TEMP
 115         RESTORE_AT
 116         RESTORE_STATIC
 117 #endif
 118         RESTORE_SOME
 119         RESTORE_SP_AND_RET
 120         .set    at
 121 
 122 work_pending:
 123         andi    t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
 124         beqz    t0, work_notifysig
 125 work_resched:
 126         TRACE_IRQS_OFF
 127         jal     schedule
 128 
 129         local_irq_disable               # make sure need_resched and
 130                                         # signals dont change between
 131                                         # sampling and return
 132         LONG_L  a2, TI_FLAGS($28)
 133         andi    t0, a2, _TIF_WORK_MASK  # is there any work to be done
 134                                         # other than syscall tracing?
 135         beqz    t0, restore_all
 136         andi    t0, a2, _TIF_NEED_RESCHED
 137         bnez    t0, work_resched
 138 
 139 work_notifysig:                         # deal with pending signals and
 140                                         # notify-resume requests
 141         move    a0, sp
 142         li      a1, 0
 143         jal     do_notify_resume        # a2 already loaded
 144         j       resume_userspace_check
 145 
 146 FEXPORT(syscall_exit_partial)
 147 #ifdef CONFIG_DEBUG_RSEQ
 148         move    a0, sp
 149         jal     rseq_syscall
 150 #endif
 151         local_irq_disable               # make sure need_resched doesn't
 152                                         # change between and return
 153         LONG_L  a2, TI_FLAGS($28)       # current->work
 154         li      t0, _TIF_ALLWORK_MASK
 155         and     t0, a2
 156         beqz    t0, restore_partial
 157         SAVE_STATIC
 158 syscall_exit_work:
 159         LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
 160         andi    t0, t0, KU_USER
 161         beqz    t0, resume_kernel
 162         li      t0, _TIF_WORK_SYSCALL_EXIT
 163         and     t0, a2                  # a2 is preloaded with TI_FLAGS
 164         beqz    t0, work_pending        # trace bit set?
 165         local_irq_enable                # could let syscall_trace_leave()
 166                                         # call schedule() instead
 167         TRACE_IRQS_ON
 168         move    a0, sp
 169         jal     syscall_trace_leave
 170         b       resume_userspace
 171 
 172 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \
 173     defined(CONFIG_MIPS_MT)
 174 
 175 /*
 176  * MIPS32R2 Instruction Hazard Barrier - must be called
 177  *
 178  * For C code use the inline version named instruction_hazard().
 179  */
 180 LEAF(mips_ihb)
 181         .set    MIPS_ISA_LEVEL_RAW
 182         jr.hb   ra
 183         nop
 184         END(mips_ihb)
 185 
 186 #endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */

/* [<][>][^][v][top][bottom][index][help] */