Difference between revisions of "Syscall"

From LinuxMIPS
Jump to: navigation, search
(Calling conventions)
 
(2 intermediate revisions by one user not shown)
Line 7: Line 7:
  
 
{| {{PrettyTable}}
 
{| {{PrettyTable}}
! Register !! use on input !! use on output
+
! Register                   !! use on input         !! use on output                   !! Note
 
|-
 
|-
| $at                        || —                    || (caller saved)
+
| $at                        || —                    || (caller saved)                   ||
 
|-
 
|-
| $v0                        || syscall number      || return value
+
| $v0                        || syscall number      || return value                     ||
 
|-
 
|-
| $v1                        || —                    || 2nd fd only for pipe(2)
+
| $v1                        || —                    || 2nd fd only for pipe(2)         ||
 
|-
 
|-
| $a0 ... $a2/$a7 except $a3 || syscall arguments    || returned unmodified
+
| $a0 ... $a2               || syscall arguments    || returned unmodified             || O32
 
|-
 
|-
| $a3                        || 4th syscall argument || $a3 set to 0/1 for success/error
+
| $a0 ... $a2, $a4 ... $a7  || syscall arguments    || returned unmodified            || N32 and 64
 
|-
 
|-
| $t0 ... $t9                || —                    || (caller saved)
+
| $a3                        || 4th syscall argument || $a3 set to 0/1 for success/error ||
 
|-
 
|-
| $s0 ... $s8                || —                    || (callee saved)
+
| $t0 ... $t9                || —                    || (caller saved)                  ||
 +
|-
 +
| $s0 ... $s8                || —                    || (callee saved)                   ||
 +
|-
 +
| $hi, $lo                  || —                    || (caller saved)                  ||
 
|}
 
|}
  
Line 54: Line 58:
  
 
For the exact syscall numbers for the three Linux ABI, please see [//git.linux-mips.org/?p=ralf/linux.git;a=blob;f=arch/mips/include/asm/unistd.h <asm/unistd.h>] of your kernel.
 
For the exact syscall numbers for the three Linux ABI, please see [//git.linux-mips.org/?p=ralf/linux.git;a=blob;f=arch/mips/include/asm/unistd.h <asm/unistd.h>] of your kernel.
 +
 +
== Example ==
 +
This is a slightly polished version of the first application that ever ran successfully on Linux/MIPS in [[1995]]:
 +
 +
<pre>
 +
/*
 +
* hello-1.1/Makefile
 +
*
 +
* This file is subject to the terms and conditions of the GNU General Public
 +
* License.  See the file "COPYING" in the main directory of this archive
 +
* for more details.
 +
*
 +
* Copyright (C) 1995 by Ralf Baechle
 +
*/
 +
#include <asm/unistd.h>
 +
#include <asm/asm.h>
 +
#include <sys/syscall.h>
 +
 +
#define O_RDWR                02
 +
 +
        .set    noreorder
 +
        LEAF(main)
 +
 +
#      fd = open("/dev/tty1", O_RDWR, 0);
 +
        la      a0,tty
 +
        li      a1,O_RDWR
 +
        li      a2,0
 +
        li      v0,SYS_open
 +
        syscall
 +
 +
        bnez    a3,quit
 +
        move    s0,v0                          # delay slot
 +
 +
#      write(fd, "hello, world.\n", 14);
 +
        move    a0,s0
 +
        la      a1,hello
 +
        li      a2,14
 +
        li      v0,SYS_write
 +
        syscall
 +
 +
#      close(fd);
 +
        move    a0,s0
 +
        li      v0,SYS_close
 +
        syscall
 +
 +
quit:
 +
        li      a0,0
 +
        li      v0,SYS_exit
 +
        syscall
 +
 +
        j      quit
 +
        nop
 +
 +
        END(main)
 +
 +
        .data
 +
tty:    .asciz  "/dev/tty1"
 +
hello:  .ascii  "Hello, world.\n"
 +
</pre>
  
 
== See also ==
 
== See also ==
 
* [[MIPS OS]]
 
* [[MIPS OS]]
 
* [[MIPS ABI History]]
 
* [[MIPS ABI History]]

Latest revision as of 16:55, 11 September 2012

This article attempts to describe the calling conventions of syscalls on Linux/MIPS. Generally it's a less than great idea to directly access the system call interface. Libraries such as glibc, ucLibc and others are doing a great job and will hide all the possible optimizations and version dependencies from the application programmer. You have been warned.

Calling conventions

The syscall calling conventions are similar to subroutine calls. That is the set of caller saved and callee saved registers are pretty much the same. However, arguments are passed in $a0 ...$a3 for O32 rsp. $a0 ... $a7 for N32 and N64. The result value is returned in $v0 and $a3 will be set to 0 or 1 to indicate success. The s-registers should be assumed to be saved while the contents of the $t registers should be assumed to have been lost.

A few syscalls deviate from this calling conventions, for example sigreturn which modifies the entire register file or pipe(2) which returns the first file descriptor in $v0 and the second in $v1.

Register use on input use on output Note
$at (caller saved)
$v0 syscall number return value
$v1 2nd fd only for pipe(2)
$a0 ... $a2 syscall arguments returned unmodified O32
$a0 ... $a2, $a4 ... $a7 syscall arguments returned unmodified N32 and 64
$a3 4th syscall argument $a3 set to 0/1 for success/error
$t0 ... $t9 (caller saved)
$s0 ... $s8 (callee saved)
$hi, $lo (caller saved)

And of course a syscall is invoked through a SYSCALL instruction. The kernel assumes the syscall instruction not to be in a branch delay slot, that is, it will not check for branch delay slots and do branch emulation. Even iff it was, performance considerations would make it preferable to leave the SYSCALL instruction outside the branch delay slot. On return from a syscall the program counter will be set to the instruction following the SYSCALL instruction.

Up to 2.6.35 the kernel was assuming that the instruction immediately preceeding the SYSCALL instruction was reloading the syscall number and was using this for syscall restarting. This meant, to keep a syscall invokation restartable it was impossible to place a SYSCALL instruction in a branch delay slot anyway.

Syscall restarting

Syscall restarting is a special case where $v0, $v1 and $a3 will stay unmodified. Even the program counter will stay unmodified so the same syscall will be executed again. This is something that does not matter to application programmers but may become visible in debuggers. Syscall restarting is something that is used internally by the kernel, for example when during a large read(2) syscall the kernel receives a signal.

Compatibility ABIs

For compatibility ABIs Linux/MIPS obviously follows whatever the native OS is doing. This happens to be similar to what Linux/MIPS is doing or from a historical perspective, Linux/MIPS is following what other, earlier MIPS UNIX implementations were doing.

Syscall number ranges

OS flavor First Last
System V Release 4 flavored syscalls 0 999
System V syscalls. All flavors of IRIX use this number range as well. 1000 1999
BSD 4.3 syscalls 2000 2999
POSIX syscalls 3000 3999
Linux O32 syscalls 4000 4999
Linux N64 syscalls 5000 5999
Linux N32 syscalls 6000 6999

For the exact syscall numbers for the three Linux ABI, please see <asm/unistd.h> of your kernel.

Example

This is a slightly polished version of the first application that ever ran successfully on Linux/MIPS in 1995:

/*
 * hello-1.1/Makefile
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1995 by Ralf Baechle
 */
#include <asm/unistd.h>
#include <asm/asm.h>
#include <sys/syscall.h>

#define O_RDWR                02

        .set    noreorder
        LEAF(main)

#       fd = open("/dev/tty1", O_RDWR, 0);
        la      a0,tty
        li      a1,O_RDWR
        li      a2,0
        li      v0,SYS_open
        syscall

        bnez    a3,quit
        move    s0,v0                           # delay slot

#       write(fd, "hello, world.\n", 14);
        move    a0,s0
        la      a1,hello
        li      a2,14
        li      v0,SYS_write
        syscall

#       close(fd);
        move    a0,s0
        li      v0,SYS_close
        syscall

quit:
        li      a0,0
        li      v0,SYS_exit
        syscall

        j       quit
        nop

        END(main)

        .data
tty:    .asciz  "/dev/tty1"
hello:  .ascii  "Hello, world.\n"

See also