2005-04-16 15:20:36 -07:00
/*
* linux / arch / arm / kernel / sys_arm . c
*
* Copyright ( C ) People who wrote linux / arch / i386 / kernel / sys_i386 . c
* Copyright ( C ) 1995 , 1996 Russell King .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This file contains various random system calls that
* have a non - standard calling sequence on the Linux / arm
* platform .
*/
# include <linux/module.h>
# include <linux/errno.h>
# include <linux/sched.h>
# include <linux/slab.h>
# include <linux/mm.h>
# include <linux/sem.h>
# include <linux/msg.h>
# include <linux/shm.h>
# include <linux/stat.h>
# include <linux/syscalls.h>
# include <linux/mman.h>
# include <linux/fs.h>
# include <linux/file.h>
2007-10-16 23:29:24 -07:00
# include <linux/ipc.h>
2008-09-06 11:35:55 +01:00
# include <linux/uaccess.h>
2005-04-16 15:20:36 -07:00
/* Fork a new task - this creates a new program thread.
* This is called indirectly via a small wrapper
*/
asmlinkage int sys_fork ( struct pt_regs * regs )
{
2006-02-24 21:37:50 +00:00
# ifdef CONFIG_MMU
2005-04-16 15:20:36 -07:00
return do_fork ( SIGCHLD , regs - > ARM_sp , regs , 0 , NULL , NULL ) ;
2006-02-24 21:37:50 +00:00
# else
/* can not support in nommu mode */
return ( - EINVAL ) ;
# endif
2005-04-16 15:20:36 -07:00
}
/* Clone a task - this clones the calling program thread.
* This is called indirectly via a small wrapper
*/
asmlinkage int sys_clone ( unsigned long clone_flags , unsigned long newsp ,
int __user * parent_tidptr , int tls_val ,
int __user * child_tidptr , struct pt_regs * regs )
{
if ( ! newsp )
newsp = regs - > ARM_sp ;
return do_fork ( clone_flags , newsp , regs , 0 , parent_tidptr , child_tidptr ) ;
}
asmlinkage int sys_vfork ( struct pt_regs * regs )
{
return do_fork ( CLONE_VFORK | CLONE_VM | SIGCHLD , regs - > ARM_sp , regs , 0 , NULL , NULL ) ;
}
/* sys_execve() executes a new program.
* This is called indirectly via a small wrapper
*/
asmlinkage int sys_execve ( char __user * filenamei , char __user * __user * argv ,
char __user * __user * envp , struct pt_regs * regs )
{
int error ;
char * filename ;
filename = getname ( filenamei ) ;
error = PTR_ERR ( filename ) ;
if ( IS_ERR ( filename ) )
goto out ;
error = do_execve ( filename , argv , envp , regs ) ;
putname ( filename ) ;
out :
return error ;
}
2006-10-02 02:18:31 -07:00
int kernel_execve ( const char * filename , char * const argv [ ] , char * const envp [ ] )
2005-04-16 15:20:36 -07:00
{
struct pt_regs regs ;
int ret ;
memset ( & regs , 0 , sizeof ( struct pt_regs ) ) ;
ret = do_execve ( ( char * ) filename , ( char __user * __user * ) argv ,
( char __user * __user * ) envp , & regs ) ;
if ( ret < 0 )
goto out ;
/*
* Save argc to the register structure for userspace .
*/
regs . ARM_r0 = ret ;
/*
* We were successful . We won ' t be returning to our caller , but
* instead to user space by manipulating the kernel stack .
*/
asm ( " add r0, %0, %1 \n \t "
" mov r1, %2 \n \t "
" mov r2, %3 \n \t "
" bl memmove \n \t " /* copy regs to top of stack */
" mov r8, #0 \n \t " /* not a syscall */
" mov r9, %0 \n \t " /* thread structure */
" mov sp, r0 \n \t " /* reposition stack pointer */
" b ret_to_user "
:
: " r " ( current_thread_info ( ) ) ,
2005-05-05 13:11:00 +01:00
" Ir " ( THREAD_START_SP - sizeof ( regs ) ) ,
2005-04-16 15:20:36 -07:00
" r " ( & regs ) ,
" Ir " ( sizeof ( regs ) )
2005-10-04 23:17:53 +01:00
: " r0 " , " r1 " , " r2 " , " r3 " , " ip " , " lr " , " memory " ) ;
2005-04-16 15:20:36 -07:00
out :
return ret ;
}
2006-10-02 02:18:31 -07:00
EXPORT_SYMBOL ( kernel_execve ) ;
2005-09-01 12:37:13 +01:00
/*
2007-05-11 20:40:30 +01:00
* Since loff_t is a 64 bit type we avoid a lot of ABI hassle
2005-09-01 12:37:13 +01:00
* with a different argument ordering .
*/
asmlinkage long sys_arm_fadvise64_64 ( int fd , int advice ,
loff_t offset , loff_t len )
{
return sys_fadvise64_64 ( fd , offset , len , advice ) ;
}