2 * linux/arch/ppc/kernel/sys_ppc.c
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
7 * Derived from "arch/i386/kernel/sys_i386.c"
8 * Adapted from the i386 version by Gary Thomas
9 * Modified by Cort Dougan (cort@cs.nmt.edu)
10 * and Paul Mackerras (paulus@cs.anu.edu.au).
12 * This file contains various random system calls that
13 * have a non-standard calling sequence on the Linux/PPC
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
23 #include <linux/errno.h>
24 #include <linux/sched.h>
26 #include <linux/smp.h>
27 #include <linux/smp_lock.h>
28 #include <linux/sem.h>
29 #include <linux/msg.h>
30 #include <linux/shm.h>
31 #include <linux/stat.h>
32 #include <linux/mman.h>
33 #include <linux/sys.h>
34 #include <linux/ipc.h>
35 #include <linux/utsname.h>
36 #include <linux/file.h>
38 #include <asm/uaccess.h>
40 #include <asm/semaphore.h>
47 asmlinkage
int sys_ioperm(unsigned long from
, unsigned long num
, int on
)
49 printk(KERN_ERR
"sys_ioperm()\n");
53 int sys_iopl(int a1
, int a2
, int a3
, int a4
)
56 printk(KERN_ERR
"sys_iopl(%x, %x, %x, %x)!\n", a1
, a2
, a3
, a4
);
61 int sys_vm86(int a1
, int a2
, int a3
, int a4
)
64 printk(KERN_ERR
"sys_vm86(%x, %x, %x, %x)!\n", a1
, a2
, a3
, a4
);
69 int sys_modify_ldt(int a1
, int a2
, int a3
, int a4
)
72 printk(KERN_ERR
"sys_modify_ldt(%x, %x, %x, %x)!\n", a1
, a2
, a3
, a4
);
78 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
80 * This is really horribly ugly.
83 sys_ipc (uint call
, int first
, int second
, int third
, void *ptr
, long fifth
)
88 version
= call
>> 16; /* hack for backward compatibility */
94 ret
= sys_semop (first
, (struct sembuf
*)ptr
, second
);
97 ret
= sys_semget (first
, second
, third
);
104 if ((ret
= verify_area (VERIFY_READ
, ptr
, sizeof(long)))
105 || (ret
= get_user(fourth
.__pad
, (void **)ptr
)))
107 ret
= sys_semctl (first
, second
, third
, fourth
);
111 ret
= sys_msgsnd (first
, (struct msgbuf
*) ptr
, second
, third
);
116 struct ipc_kludge tmp
;
120 if ((ret
= verify_area (VERIFY_READ
, ptr
, sizeof(tmp
)))
121 || (ret
= copy_from_user(&tmp
,
122 (struct ipc_kludge
*) ptr
,
125 ret
= sys_msgrcv (first
, tmp
.msgp
, second
, tmp
.msgtyp
,
130 ret
= sys_msgrcv (first
, (struct msgbuf
*) ptr
,
131 second
, fifth
, third
);
136 ret
= sys_msgget ((key_t
) first
, second
);
139 ret
= sys_msgctl (first
, second
, (struct msqid_ds
*) ptr
);
146 if ((ret
= verify_area(VERIFY_WRITE
, (ulong
*) third
,
149 ret
= sys_shmat (first
, (char *) ptr
, second
, &raddr
);
152 ret
= put_user (raddr
, (ulong
*) third
);
155 case 1: /* iBCS2 emulator entry point */
156 if (!segment_eq(get_fs(), get_ds()))
158 ret
= sys_shmat (first
, (char *) ptr
, second
,
164 ret
= sys_shmdt ((char *)ptr
);
167 ret
= sys_shmget (first
, second
, third
);
170 ret
= sys_shmctl (first
, second
, (struct shmid_ds
*) ptr
);
179 * sys_pipe() is the normal C calling standard for creating
180 * a pipe. It's not the way unix traditionally does this, though.
182 asmlinkage
int sys_pipe(int *fildes
)
191 if (copy_to_user(fildes
, fd
, 2*sizeof(int)))
197 asmlinkage
unsigned long sys_mmap(unsigned long addr
, size_t len
,
198 unsigned long prot
, unsigned long flags
,
199 unsigned long fd
, off_t offset
)
201 struct file
* file
= NULL
;
205 if (!(flags
& MAP_ANONYMOUS
)) {
206 if (!(file
= fget(fd
)))
210 flags
&= ~(MAP_EXECUTABLE
| MAP_DENYWRITE
);
211 down(¤t
->mm
->mmap_sem
);
212 ret
= do_mmap(file
, addr
, len
, prot
, flags
, offset
);
213 up(¤t
->mm
->mmap_sem
);
221 extern asmlinkage
int sys_select(int, fd_set
*, fd_set
*, fd_set
*, struct timeval
*);
224 * Due to some executables calling the wrong select we sometimes
225 * get wrong args. This determines how the args are being passed
226 * (a single ptr to them all args passed) then calls
227 * sys_select() with the appropriate args. -- Cort
230 ppc_select(int n
, fd_set
*inp
, fd_set
*outp
, fd_set
*exp
, struct timeval
*tvp
)
232 if ( (unsigned long)n
>= 4096 )
234 unsigned long *buffer
= (unsigned long *)n
;
235 if (verify_area(VERIFY_READ
, buffer
, 5*sizeof(unsigned long))
236 || __get_user(n
, buffer
)
237 || __get_user(inp
, ((fd_set
**)(buffer
+1)))
238 || __get_user(outp
, ((fd_set
**)(buffer
+2)))
239 || __get_user(exp
, ((fd_set
**)(buffer
+3)))
240 || __get_user(tvp
, ((struct timeval
**)(buffer
+4))))
243 return sys_select(n
, inp
, outp
, exp
, tvp
);
246 asmlinkage
int sys_pause(void)
248 current
->state
= TASK_INTERRUPTIBLE
;
250 return -ERESTARTNOHAND
;
253 asmlinkage
int sys_uname(struct old_utsname
* name
)
255 if (name
&& !copy_to_user(name
, &system_utsname
, sizeof (*name
)))
260 asmlinkage
int sys_olduname(struct oldold_utsname
* name
)
266 if (!access_ok(VERIFY_WRITE
,name
,sizeof(struct oldold_utsname
)))
269 error
= __copy_to_user(&name
->sysname
,&system_utsname
.sysname
,__OLD_UTS_LEN
);
270 error
-= __put_user(0,name
->sysname
+__OLD_UTS_LEN
);
271 error
-= __copy_to_user(&name
->nodename
,&system_utsname
.nodename
,__OLD_UTS_LEN
);
272 error
-= __put_user(0,name
->nodename
+__OLD_UTS_LEN
);
273 error
-= __copy_to_user(&name
->release
,&system_utsname
.release
,__OLD_UTS_LEN
);
274 error
-= __put_user(0,name
->release
+__OLD_UTS_LEN
);
275 error
-= __copy_to_user(&name
->version
,&system_utsname
.version
,__OLD_UTS_LEN
);
276 error
-= __put_user(0,name
->version
+__OLD_UTS_LEN
);
277 error
-= __copy_to_user(&name
->machine
,&system_utsname
.machine
,__OLD_UTS_LEN
);
278 error
= __put_user(0,name
->machine
+__OLD_UTS_LEN
);
279 error
= error
? -EFAULT
: 0;