root/arch/mips/kernel/scall64-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 - 2000, 2001 by Ralf Baechle
   7  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
   8  * Copyright (C) 2001 MIPS Technologies, Inc.
   9  * Copyright (C) 2004 Thiemo Seufer
  10  *
  11  * Hairy, the userspace application uses a different argument passing
  12  * convention than the kernel, so we have to translate things from o32
  13  * to ABI64 calling convention.  64-bit syscalls are also processed
  14  * here for now.
  15  */
  16 #include <linux/errno.h>
  17 #include <asm/asm.h>
  18 #include <asm/asmmacro.h>
  19 #include <asm/irqflags.h>
  20 #include <asm/mipsregs.h>
  21 #include <asm/regdef.h>
  22 #include <asm/stackframe.h>
  23 #include <asm/thread_info.h>
  24 #include <asm/unistd.h>
  25 #include <asm/sysmips.h>
  26 
  27         .align  5
  28 NESTED(handle_sys, PT_SIZE, sp)
  29         .set    noat
  30         SAVE_SOME
  31         TRACE_IRQS_ON_RELOAD
  32         STI
  33         .set    at
  34         ld      t1, PT_EPC(sp)          # skip syscall on return
  35 
  36         dsubu   t0, v0, __NR_O32_Linux  # check syscall number
  37         sltiu   t0, t0, __NR_O32_Linux_syscalls
  38         daddiu  t1, 4                   # skip to next instruction
  39         sd      t1, PT_EPC(sp)
  40         beqz    t0, not_o32_scall
  41 #if 0
  42  SAVE_ALL
  43  move a1, v0
  44  PRINT("Scall %ld\n")
  45  RESTORE_ALL
  46 #endif
  47 
  48         /* We don't want to stumble over broken sign extensions from
  49            userland. O32 does never use the upper half. */
  50         sll     a0, a0, 0
  51         sll     a1, a1, 0
  52         sll     a2, a2, 0
  53         sll     a3, a3, 0
  54 
  55         sd      a3, PT_R26(sp)          # save a3 for syscall restarting
  56 
  57         /*
  58          * More than four arguments.  Try to deal with it by copying the
  59          * stack arguments from the user stack to the kernel stack.
  60          * This Sucks (TM).
  61          *
  62          * We intentionally keep the kernel stack a little below the top of
  63          * userspace so we don't have to do a slower byte accurate check here.
  64          */
  65         ld      t0, PT_R29(sp)          # get old user stack pointer
  66         daddu   t1, t0, 32
  67         bltz    t1, bad_stack
  68 
  69 load_a4: lw     a4, 16(t0)              # argument #5 from usp
  70 load_a5: lw     a5, 20(t0)              # argument #6 from usp
  71 load_a6: lw     a6, 24(t0)              # argument #7 from usp
  72 load_a7: lw     a7, 28(t0)              # argument #8 from usp
  73 loads_done:
  74 
  75         .section __ex_table,"a"
  76         PTR     load_a4, bad_stack_a4
  77         PTR     load_a5, bad_stack_a5
  78         PTR     load_a6, bad_stack_a6
  79         PTR     load_a7, bad_stack_a7
  80         .previous
  81 
  82         li      t1, _TIF_WORK_SYSCALL_ENTRY
  83         LONG_L  t0, TI_FLAGS($28)       # syscall tracing enabled?
  84         and     t0, t1, t0
  85         bnez    t0, trace_a_syscall
  86 
  87 syscall_common:
  88         dsll    t0, v0, 3               # offset into table
  89         ld      t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
  90 
  91         jalr    t2                      # Do The Real Thing (TM)
  92 
  93         li      t0, -EMAXERRNO - 1      # error?
  94         sltu    t0, t0, v0
  95         sd      t0, PT_R7(sp)           # set error flag
  96         beqz    t0, 1f
  97 
  98         ld      t1, PT_R2(sp)           # syscall number
  99         dnegu   v0                      # error
 100         sd      t1, PT_R0(sp)           # save it for syscall restarting
 101 1:      sd      v0, PT_R2(sp)           # result
 102 
 103 o32_syscall_exit:
 104         j       syscall_exit_partial
 105 
 106 /* ------------------------------------------------------------------------ */
 107 
 108 trace_a_syscall:
 109         SAVE_STATIC
 110         sd      a4, PT_R8(sp)           # Save argument registers
 111         sd      a5, PT_R9(sp)
 112         sd      a6, PT_R10(sp)
 113         sd      a7, PT_R11(sp)          # For indirect syscalls
 114 
 115         move    a0, sp
 116         /*
 117          * absolute syscall number is in v0 unless we called syscall(__NR_###)
 118          * where the real syscall number is in a0
 119          * note: NR_syscall is the first O32 syscall but the macro is
 120          * only defined when compiling with -mabi=32 (CONFIG_32BIT)
 121          * therefore __NR_O32_Linux is used (4000)
 122          */
 123         .set    push
 124         .set    reorder
 125         subu    t1, v0,  __NR_O32_Linux
 126         move    a1, v0
 127         bnez    t1, 1f /* __NR_syscall at offset 0 */
 128         ld      a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
 129         .set    pop
 130 
 131 1:      jal     syscall_trace_enter
 132 
 133         bltz    v0, 1f                  # seccomp failed? Skip syscall
 134 
 135         RESTORE_STATIC
 136         ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
 137         ld      a0, PT_R4(sp)           # Restore argument registers
 138         ld      a1, PT_R5(sp)
 139         ld      a2, PT_R6(sp)
 140         ld      a3, PT_R7(sp)
 141         ld      a4, PT_R8(sp)
 142         ld      a5, PT_R9(sp)
 143         ld      a6, PT_R10(sp)
 144         ld      a7, PT_R11(sp)          # For indirect syscalls
 145 
 146         dsubu   t0, v0, __NR_O32_Linux  # check (new) syscall number
 147         sltiu   t0, t0, __NR_O32_Linux_syscalls
 148         beqz    t0, not_o32_scall
 149 
 150         j       syscall_common
 151 
 152 1:      j       syscall_exit
 153 
 154 /* ------------------------------------------------------------------------ */
 155 
 156         /*
 157          * The stackpointer for a call with more than 4 arguments is bad.
 158          */
 159 bad_stack:
 160         li      v0, EFAULT
 161         sd      v0, PT_R2(sp)
 162         li      t0, 1                   # set error flag
 163         sd      t0, PT_R7(sp)
 164         j       o32_syscall_exit
 165 
 166 bad_stack_a4:
 167         li      a4, 0
 168         b       load_a5
 169 
 170 bad_stack_a5:
 171         li      a5, 0
 172         b       load_a6
 173 
 174 bad_stack_a6:
 175         li      a6, 0
 176         b       load_a7
 177 
 178 bad_stack_a7:
 179         li      a7, 0
 180         b       loads_done
 181 
 182 not_o32_scall:
 183         /*
 184          * This is not an o32 compatibility syscall, pass it on
 185          * to the 64-bit syscall handlers.
 186          */
 187 #ifdef CONFIG_MIPS32_N32
 188         j       handle_sysn32
 189 #else
 190         j       handle_sys64
 191 #endif
 192         END(handle_sys)
 193 
 194 LEAF(sys32_syscall)
 195         subu    t0, a0, __NR_O32_Linux  # check syscall number
 196         sltiu   v0, t0, __NR_O32_Linux_syscalls
 197         beqz    t0, einval              # do not recurse
 198         dsll    t1, t0, 3
 199         beqz    v0, einval
 200         ld      t2, sys32_call_table(t1)                # syscall routine
 201 
 202         move    a0, a1                  # shift argument registers
 203         move    a1, a2
 204         move    a2, a3
 205         move    a3, a4
 206         move    a4, a5
 207         move    a5, a6
 208         move    a6, a7
 209         jr      t2
 210         /* Unreached */
 211 
 212 einval: li      v0, -ENOSYS
 213         jr      ra
 214         END(sys32_syscall)
 215 
 216 #define __SYSCALL(nr, entry)    PTR entry
 217         .align  3
 218         .type   sys32_call_table,@object
 219 EXPORT(sys32_call_table)
 220 #include <asm/syscall_table_64_o32.h>
 221 #undef __SYSCALL

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