root/arch/mips/kernel/scall32-o32.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) 1995-99, 2000- 02, 06 Ralf Baechle <ralf@linux-mips.org>
   7  * Copyright (C) 2001 MIPS Technologies, Inc.
   8  * Copyright (C) 2004 Thiemo Seufer
   9  * Copyright (C) 2014 Imagination Technologies Ltd.
  10  */
  11 #include <linux/errno.h>
  12 #include <asm/asm.h>
  13 #include <asm/asmmacro.h>
  14 #include <asm/irqflags.h>
  15 #include <asm/mipsregs.h>
  16 #include <asm/regdef.h>
  17 #include <asm/stackframe.h>
  18 #include <asm/isadep.h>
  19 #include <asm/sysmips.h>
  20 #include <asm/thread_info.h>
  21 #include <asm/unistd.h>
  22 #include <asm/war.h>
  23 #include <asm/asm-offsets.h>
  24 
  25         .align  5
  26 NESTED(handle_sys, PT_SIZE, sp)
  27         .set    noat
  28         SAVE_SOME
  29         TRACE_IRQS_ON_RELOAD
  30         STI
  31         .set    at
  32 
  33         lw      t1, PT_EPC(sp)          # skip syscall on return
  34 
  35         addiu   t1, 4                   # skip to next instruction
  36         sw      t1, PT_EPC(sp)
  37 
  38         sw      a3, PT_R26(sp)          # save a3 for syscall restarting
  39 
  40         /*
  41          * More than four arguments.  Try to deal with it by copying the
  42          * stack arguments from the user stack to the kernel stack.
  43          * This Sucks (TM).
  44          */
  45         lw      t0, PT_R29(sp)          # get old user stack pointer
  46 
  47         /*
  48          * We intentionally keep the kernel stack a little below the top of
  49          * userspace so we don't have to do a slower byte accurate check here.
  50          */
  51         lw      t5, TI_ADDR_LIMIT($28)
  52         addu    t4, t0, 32
  53         and     t5, t4
  54         bltz    t5, bad_stack           # -> sp is bad
  55 
  56         /*
  57          * Ok, copy the args from the luser stack to the kernel stack.
  58          */
  59 
  60         .set    push
  61         .set    noreorder
  62         .set    nomacro
  63 
  64 load_a4: user_lw(t5, 16(t0))            # argument #5 from usp
  65 load_a5: user_lw(t6, 20(t0))            # argument #6 from usp
  66 load_a6: user_lw(t7, 24(t0))            # argument #7 from usp
  67 load_a7: user_lw(t8, 28(t0))            # argument #8 from usp
  68 loads_done:
  69 
  70         sw      t5, 16(sp)              # argument #5 to ksp
  71         sw      t6, 20(sp)              # argument #6 to ksp
  72         sw      t7, 24(sp)              # argument #7 to ksp
  73         sw      t8, 28(sp)              # argument #8 to ksp
  74         .set    pop
  75 
  76         .section __ex_table,"a"
  77         PTR     load_a4, bad_stack_a4
  78         PTR     load_a5, bad_stack_a5
  79         PTR     load_a6, bad_stack_a6
  80         PTR     load_a7, bad_stack_a7
  81         .previous
  82 
  83         lw      t0, TI_FLAGS($28)       # syscall tracing enabled?
  84         li      t1, _TIF_WORK_SYSCALL_ENTRY
  85         and     t0, t1
  86         bnez    t0, syscall_trace_entry # -> yes
  87 syscall_common:
  88         subu    v0, v0, __NR_O32_Linux  # check syscall number
  89         sltiu   t0, v0, __NR_O32_Linux_syscalls
  90         beqz    t0, illegal_syscall
  91 
  92         sll     t0, v0, 2
  93         la      t1, sys_call_table
  94         addu    t1, t0
  95         lw      t2, (t1)                # syscall routine
  96 
  97         beqz    t2, illegal_syscall
  98 
  99         jalr    t2                      # Do The Real Thing (TM)
 100 
 101         li      t0, -EMAXERRNO - 1      # error?
 102         sltu    t0, t0, v0
 103         sw      t0, PT_R7(sp)           # set error flag
 104         beqz    t0, 1f
 105 
 106         lw      t1, PT_R2(sp)           # syscall number
 107         negu    v0                      # error
 108         sw      t1, PT_R0(sp)           # save it for syscall restarting
 109 1:      sw      v0, PT_R2(sp)           # result
 110 
 111 o32_syscall_exit:
 112         j       syscall_exit_partial
 113 
 114 /* ------------------------------------------------------------------------ */
 115 
 116 syscall_trace_entry:
 117         SAVE_STATIC
 118         move    a0, sp
 119 
 120         /*
 121          * syscall number is in v0 unless we called syscall(__NR_###)
 122          * where the real syscall number is in a0
 123          */
 124         move    a1, v0
 125         subu    t2, v0,  __NR_O32_Linux
 126         bnez    t2, 1f /* __NR_syscall at offset 0 */
 127         lw      a1, PT_R4(sp)
 128 
 129 1:      jal     syscall_trace_enter
 130 
 131         bltz    v0, 1f                  # seccomp failed? Skip syscall
 132 
 133         RESTORE_STATIC
 134         lw      v0, PT_R2(sp)           # Restore syscall (maybe modified)
 135         lw      a0, PT_R4(sp)           # Restore argument registers
 136         lw      a1, PT_R5(sp)
 137         lw      a2, PT_R6(sp)
 138         lw      a3, PT_R7(sp)
 139         j       syscall_common
 140 
 141 1:      j       syscall_exit
 142 
 143 /* ------------------------------------------------------------------------ */
 144 
 145         /*
 146          * Our open-coded access area sanity test for the stack pointer
 147          * failed. We probably should handle this case a bit more drastic.
 148          */
 149 bad_stack:
 150         li      v0, EFAULT
 151         sw      v0, PT_R2(sp)
 152         li      t0, 1                           # set error flag
 153         sw      t0, PT_R7(sp)
 154         j       o32_syscall_exit
 155 
 156 bad_stack_a4:
 157         li      t5, 0
 158         b       load_a5
 159 
 160 bad_stack_a5:
 161         li      t6, 0
 162         b       load_a6
 163 
 164 bad_stack_a6:
 165         li      t7, 0
 166         b       load_a7
 167 
 168 bad_stack_a7:
 169         li      t8, 0
 170         b       loads_done
 171 
 172         /*
 173          * The system call does not exist in this kernel
 174          */
 175 illegal_syscall:
 176         li      v0, ENOSYS                      # error
 177         sw      v0, PT_R2(sp)
 178         li      t0, 1                           # set error flag
 179         sw      t0, PT_R7(sp)
 180         j       o32_syscall_exit
 181         END(handle_sys)
 182 
 183         LEAF(sys_syscall)
 184         subu    t0, a0, __NR_O32_Linux  # check syscall number
 185         sltiu   v0, t0, __NR_O32_Linux_syscalls
 186         beqz    t0, einval              # do not recurse
 187         sll     t1, t0, 2
 188         beqz    v0, einval
 189         lw      t2, sys_call_table(t1)          # syscall routine
 190 
 191         move    a0, a1                          # shift argument registers
 192         move    a1, a2
 193         move    a2, a3
 194         lw      a3, 16(sp)
 195         lw      t4, 20(sp)
 196         lw      t5, 24(sp)
 197         lw      t6, 28(sp)
 198         sw      t4, 16(sp)
 199         sw      t5, 20(sp)
 200         sw      t6, 24(sp)
 201         jr      t2
 202         /* Unreached */
 203 
 204 einval: li      v0, -ENOSYS
 205         jr      ra
 206         END(sys_syscall)
 207 
 208 #ifdef CONFIG_MIPS_MT_FPAFF
 209         /*
 210          * For FPU affinity scheduling on MIPS MT processors, we need to
 211          * intercept sys_sched_xxxaffinity() calls until we get a proper hook
 212          * in kernel/sched/core.c.  Considered only temporary we only support
 213          * these hooks for the 32-bit kernel - there is no MIPS64 MT processor
 214          * atm.
 215          */
 216 #define sys_sched_setaffinity   mipsmt_sys_sched_setaffinity
 217 #define sys_sched_getaffinity   mipsmt_sys_sched_getaffinity
 218 #endif /* CONFIG_MIPS_MT_FPAFF */
 219 
 220 #define __SYSCALL(nr, entry)    PTR entry
 221         .align  2
 222         .type   sys_call_table, @object
 223 EXPORT(sys_call_table)
 224 #include <asm/syscall_table_32_o32.h>
 225 #undef __SYSCALL

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