11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/arch/arm/kernel/sys_arm.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c 51da177e4SLinus Torvalds * Copyright (C) 1995, 1996 Russell King. 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds * it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds * published by the Free Software Foundation. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * This file contains various random system calls that 121da177e4SLinus Torvalds * have a non-standard calling sequence on the Linux/arm 131da177e4SLinus Torvalds * platform. 141da177e4SLinus Torvalds */ 151da177e4SLinus Torvalds #include <linux/module.h> 161da177e4SLinus Torvalds #include <linux/errno.h> 171da177e4SLinus Torvalds #include <linux/sched.h> 181da177e4SLinus Torvalds #include <linux/mm.h> 191da177e4SLinus Torvalds #include <linux/sem.h> 201da177e4SLinus Torvalds #include <linux/msg.h> 211da177e4SLinus Torvalds #include <linux/shm.h> 221da177e4SLinus Torvalds #include <linux/stat.h> 231da177e4SLinus Torvalds #include <linux/syscalls.h> 241da177e4SLinus Torvalds #include <linux/mman.h> 251da177e4SLinus Torvalds #include <linux/fs.h> 261da177e4SLinus Torvalds #include <linux/file.h> 27cba4fbbfSAdrian Bunk #include <linux/ipc.h> 2833fa9b13SRussell King #include <linux/uaccess.h> 29*5a0e3ad6STejun Heo #include <linux/slab.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds /* Fork a new task - this creates a new program thread. 321da177e4SLinus Torvalds * This is called indirectly via a small wrapper 331da177e4SLinus Torvalds */ 341da177e4SLinus Torvalds asmlinkage int sys_fork(struct pt_regs *regs) 351da177e4SLinus Torvalds { 36f24284adSHyok S. Choi #ifdef CONFIG_MMU 371da177e4SLinus Torvalds return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); 38f24284adSHyok S. Choi #else 39f24284adSHyok S. Choi /* can not support in nommu mode */ 40f24284adSHyok S. Choi return(-EINVAL); 41f24284adSHyok S. Choi #endif 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds /* Clone a task - this clones the calling program thread. 451da177e4SLinus Torvalds * This is called indirectly via a small wrapper 461da177e4SLinus Torvalds */ 471da177e4SLinus Torvalds asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, 481da177e4SLinus Torvalds int __user *parent_tidptr, int tls_val, 491da177e4SLinus Torvalds int __user *child_tidptr, struct pt_regs *regs) 501da177e4SLinus Torvalds { 511da177e4SLinus Torvalds if (!newsp) 521da177e4SLinus Torvalds newsp = regs->ARM_sp; 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds asmlinkage int sys_vfork(struct pt_regs *regs) 581da177e4SLinus Torvalds { 591da177e4SLinus Torvalds return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); 601da177e4SLinus Torvalds } 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds /* sys_execve() executes a new program. 631da177e4SLinus Torvalds * This is called indirectly via a small wrapper 641da177e4SLinus Torvalds */ 651da177e4SLinus Torvalds asmlinkage int sys_execve(char __user *filenamei, char __user * __user *argv, 661da177e4SLinus Torvalds char __user * __user *envp, struct pt_regs *regs) 671da177e4SLinus Torvalds { 681da177e4SLinus Torvalds int error; 691da177e4SLinus Torvalds char * filename; 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds filename = getname(filenamei); 721da177e4SLinus Torvalds error = PTR_ERR(filename); 731da177e4SLinus Torvalds if (IS_ERR(filename)) 741da177e4SLinus Torvalds goto out; 751da177e4SLinus Torvalds error = do_execve(filename, argv, envp, regs); 761da177e4SLinus Torvalds putname(filename); 771da177e4SLinus Torvalds out: 781da177e4SLinus Torvalds return error; 791da177e4SLinus Torvalds } 801da177e4SLinus Torvalds 813db03b4aSArnd Bergmann int kernel_execve(const char *filename, char *const argv[], char *const envp[]) 821da177e4SLinus Torvalds { 831da177e4SLinus Torvalds struct pt_regs regs; 841da177e4SLinus Torvalds int ret; 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds memset(®s, 0, sizeof(struct pt_regs)); 871da177e4SLinus Torvalds ret = do_execve((char *)filename, (char __user * __user *)argv, 881da177e4SLinus Torvalds (char __user * __user *)envp, ®s); 891da177e4SLinus Torvalds if (ret < 0) 901da177e4SLinus Torvalds goto out; 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds /* 931da177e4SLinus Torvalds * Save argc to the register structure for userspace. 941da177e4SLinus Torvalds */ 951da177e4SLinus Torvalds regs.ARM_r0 = ret; 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds /* 981da177e4SLinus Torvalds * We were successful. We won't be returning to our caller, but 991da177e4SLinus Torvalds * instead to user space by manipulating the kernel stack. 1001da177e4SLinus Torvalds */ 1011da177e4SLinus Torvalds asm( "add r0, %0, %1\n\t" 1021da177e4SLinus Torvalds "mov r1, %2\n\t" 1031da177e4SLinus Torvalds "mov r2, %3\n\t" 1041da177e4SLinus Torvalds "bl memmove\n\t" /* copy regs to top of stack */ 1051da177e4SLinus Torvalds "mov r8, #0\n\t" /* not a syscall */ 1061da177e4SLinus Torvalds "mov r9, %0\n\t" /* thread structure */ 1071da177e4SLinus Torvalds "mov sp, r0\n\t" /* reposition stack pointer */ 1081da177e4SLinus Torvalds "b ret_to_user" 1091da177e4SLinus Torvalds : 1101da177e4SLinus Torvalds : "r" (current_thread_info()), 1114f7a1812SRussell King "Ir" (THREAD_START_SP - sizeof(regs)), 1121da177e4SLinus Torvalds "r" (®s), 1131da177e4SLinus Torvalds "Ir" (sizeof(regs)) 114c2f48086SNicolas Pitre : "r0", "r1", "r2", "r3", "ip", "lr", "memory"); 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds out: 1171da177e4SLinus Torvalds return ret; 1181da177e4SLinus Torvalds } 1193db03b4aSArnd Bergmann EXPORT_SYMBOL(kernel_execve); 12068d9102fSNicolas Pitre 12168d9102fSNicolas Pitre /* 1226cbdc8c5SSimon Arlott * Since loff_t is a 64 bit type we avoid a lot of ABI hassle 12368d9102fSNicolas Pitre * with a different argument ordering. 12468d9102fSNicolas Pitre */ 12568d9102fSNicolas Pitre asmlinkage long sys_arm_fadvise64_64(int fd, int advice, 12668d9102fSNicolas Pitre loff_t offset, loff_t len) 12768d9102fSNicolas Pitre { 12868d9102fSNicolas Pitre return sys_fadvise64_64(fd, offset, len, advice); 12968d9102fSNicolas Pitre } 130