2 * linux/arch/arm/kernel/sys_arm.c
4 * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c
5 * Copyright (C) 1995, 1996 Russell King.
7 * This file contains various random system calls that
8 * have a non-standard calling sequence on the Linux/arm
12 #include <linux/errno.h>
13 #include <linux/sched.h>
15 #include <linux/smp.h>
16 #include <linux/smp_lock.h>
17 #include <linux/sem.h>
18 #include <linux/msg.h>
19 #include <linux/shm.h>
20 #include <linux/stat.h>
21 #include <linux/mman.h>
22 #include <linux/file.h>
23 #include <linux/utsname.h>
25 #include <asm/uaccess.h>
29 * Constant strings used in inlined functions in header files
32 const char xchg_str
[] = "xchg";
35 * sys_pipe() is the normal C calling standard for creating
36 * a pipe. It's not the way unix traditionally does this, though.
38 asmlinkage
int sys_pipe(unsigned long * fildes
)
47 if (copy_to_user(fildes
, fd
, 2*sizeof(int)))
54 * Perform the select(nd, in, out, ex, tv) and mmap() system
55 * calls. ARM Linux didn't use to be able to handle more than
56 * 4 system call parameters, so these system calls used a memory
57 * block for parameter passing..
60 struct mmap_arg_struct
{
69 asmlinkage
int old_mmap(struct mmap_arg_struct
*arg
)
72 struct file
* file
= NULL
;
73 struct mmap_arg_struct a
;
76 if (copy_from_user(&a
, arg
, sizeof(a
)))
78 if (!(a
.flags
& MAP_ANONYMOUS
)) {
84 a
.flags
&= ~(MAP_EXECUTABLE
| MAP_DENYWRITE
);
85 error
= do_mmap(file
, a
.addr
, a
.len
, a
.prot
, a
.flags
, a
.offset
);
94 extern asmlinkage
int sys_select(int, fd_set
*, fd_set
*, fd_set
*, struct timeval
*);
96 struct sel_arg_struct
{
98 fd_set
*inp
, *outp
, *exp
;
102 asmlinkage
int old_select(struct sel_arg_struct
*arg
)
104 struct sel_arg_struct a
;
106 if (copy_from_user(&a
, arg
, sizeof(a
)))
108 /* sys_select() does the appropriate kernel locking */
109 return sys_select(a
.n
, a
.inp
, a
.outp
, a
.exp
, a
.tvp
);
113 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
115 * This is really horribly ugly.
117 asmlinkage
int sys_ipc (uint call
, int first
, int second
, int third
, void *ptr
, long fifth
)
122 version
= call
>> 16; /* hack for backward compatibility */
128 ret
= sys_semop (first
, (struct sembuf
*)ptr
, second
);
131 ret
= sys_semget (first
, second
, third
);
139 if (get_user(fourth
.__pad
, (void **) ptr
))
141 ret
= sys_semctl (first
, second
, third
, fourth
);
151 ret
= sys_msgsnd (first
, (struct msgbuf
*) ptr
,
157 struct ipc_kludge tmp
;
162 if (copy_from_user(&tmp
,(struct ipc_kludge
*) ptr
,
165 ret
= sys_msgrcv (first
, tmp
.msgp
, second
, tmp
.msgtyp
, third
);
169 ret
= sys_msgrcv (first
, (struct msgbuf
*) ptr
, second
, fifth
, third
);
173 ret
= sys_msgget ((key_t
) first
, second
);
176 ret
= sys_msgctl (first
, second
, (struct msqid_ds
*) ptr
);
188 ret
= sys_shmat (first
, (char *) ptr
, second
, &raddr
);
191 ret
= put_user (raddr
, (ulong
*) third
);
194 case 1: /* iBCS2 emulator entry point */
196 if (!segment_eq(get_fs(), get_ds()))
198 ret
= sys_shmat (first
, (char *) ptr
, second
, (ulong
*) third
);
202 ret
= sys_shmdt ((char *)ptr
);
205 ret
= sys_shmget (first
, second
, third
);
208 ret
= sys_shmctl (first
, second
, (struct shmid_ds
*) ptr
);
221 /* Fork a new task - this creates a new program thread.
222 * This is called indirectly via a small wrapper
224 asmlinkage
int sys_fork(struct pt_regs
*regs
)
229 ret
= do_fork(SIGCHLD
, regs
->ARM_sp
, regs
);
235 /* Clone a task - this clones the calling program thread.
236 * This is called indirectly via a small wrapper
238 asmlinkage
int sys_clone(unsigned long clone_flags
, unsigned long newsp
, struct pt_regs
*regs
)
244 newsp
= regs
->ARM_sp
;
245 ret
= do_fork(clone_flags
, newsp
, regs
);
250 /* sys_execve() executes a new program.
251 * This is called indirectly via a small wrapper
253 asmlinkage
int sys_execve(char *filenamei
, char **argv
, char **envp
, struct pt_regs
*regs
)
259 filename
= getname(filenamei
);
260 error
= PTR_ERR(filename
);
261 if (IS_ERR(filename
))
263 error
= do_execve(filename
, argv
, envp
, regs
);
271 * Detect the old function calling standard
273 static inline unsigned long old_calling_standard (struct pt_regs
*regs
)
275 unsigned long instr
, *pcv
= (unsigned long *)(instruction_pointer(regs
) - 8);
276 return (!get_user (instr
, pcv
) && instr
== 0xe1a0300d);
279 /* Compatability functions - we used to pass 5 parameters as r0, r1, r2, *r3, *(r3+4)
280 * We now use r0 - r4, and return an error if the old style calling standard is used.
281 * Eventually these functions will disappear.
284 sys_compat_llseek (unsigned int fd
, unsigned long offset_high
, unsigned long offset_low
,
285 loff_t
*result
, unsigned int origin
, struct pt_regs
*regs
)
287 extern int sys_llseek (unsigned int, unsigned long, unsigned long, loff_t
*, unsigned int);
289 if (old_calling_standard (regs
)) {
290 printk (KERN_NOTICE
"%s (%d): unsupported llseek call standard\n",
291 current
->comm
, current
->pid
);
294 return sys_llseek (fd
, offset_high
, offset_low
, result
, origin
);
298 sys_compat_mount (char *devname
, char *dirname
, char *type
, unsigned long flags
, void *data
,
299 struct pt_regs
*regs
)
301 extern int sys_mount (char *, char *, char *, unsigned long, void *);
303 if (old_calling_standard (regs
)) {
304 printk (KERN_NOTICE
"%s (%d): unsupported mount call standard\n",
305 current
->comm
, current
->pid
);
308 return sys_mount (devname
, dirname
, type
, flags
, data
);
311 asmlinkage
int sys_uname (struct old_utsname
* name
)
313 static int warned
= 0;
318 printk (KERN_NOTICE
"%s (%d): obsolete uname call\n",
319 current
->comm
, current
->pid
);
325 err
=copy_to_user (name
, &system_utsname
, sizeof (*name
));
327 return err
?-EFAULT
:0;
330 asmlinkage
int sys_olduname(struct oldold_utsname
* name
)
333 static int warned
= 0;
337 printk (KERN_NOTICE
"%s (%d): obsolete olduname call\n",
338 current
->comm
, current
->pid
);
344 if (!access_ok(VERIFY_WRITE
,name
,sizeof(struct oldold_utsname
)))
349 error
= __copy_to_user(&name
->sysname
,&system_utsname
.sysname
,__OLD_UTS_LEN
);
350 error
-= __put_user(0,name
->sysname
+__OLD_UTS_LEN
);
351 error
-= __copy_to_user(&name
->nodename
,&system_utsname
.nodename
,__OLD_UTS_LEN
);
352 error
-= __put_user(0,name
->nodename
+__OLD_UTS_LEN
);
353 error
-= __copy_to_user(&name
->release
,&system_utsname
.release
,__OLD_UTS_LEN
);
354 error
-= __put_user(0,name
->release
+__OLD_UTS_LEN
);
355 error
-= __copy_to_user(&name
->version
,&system_utsname
.version
,__OLD_UTS_LEN
);
356 error
-= __put_user(0,name
->version
+__OLD_UTS_LEN
);
357 error
-= __copy_to_user(&name
->machine
,&system_utsname
.machine
,__OLD_UTS_LEN
);
358 error
-= __put_user(0,name
->machine
+__OLD_UTS_LEN
);
362 error
= error
? -EFAULT
: 0;
367 asmlinkage
int sys_pause(void)
369 current
->state
= TASK_INTERRUPTIBLE
;
371 return -ERESTARTNOHAND
;