Import 2.3.18pre1
[davej-history.git] / arch / ppc / kernel / syscalls.c
blob30bed889beabac11b6b2c0b146046de88642241b
1 /*
2 * linux/arch/ppc/kernel/sys_ppc.c
4 * PowerPC version
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
14 * platform.
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>
25 #include <linux/mm.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>
39 #include <asm/ipc.h>
40 #include <asm/semaphore.h>
42 void
43 check_bugs(void)
47 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
49 printk(KERN_ERR "sys_ioperm()\n");
50 return -EIO;
53 int sys_iopl(int a1, int a2, int a3, int a4)
55 lock_kernel();
56 printk(KERN_ERR "sys_iopl(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
57 unlock_kernel();
58 return (-ENOSYS);
61 int sys_vm86(int a1, int a2, int a3, int a4)
63 lock_kernel();
64 printk(KERN_ERR "sys_vm86(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
65 unlock_kernel();
66 return (-ENOSYS);
69 int sys_modify_ldt(int a1, int a2, int a3, int a4)
71 lock_kernel();
72 printk(KERN_ERR "sys_modify_ldt(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
73 unlock_kernel();
74 return (-ENOSYS);
78 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
80 * This is really horribly ugly.
82 asmlinkage int
83 sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
85 int version, ret;
87 lock_kernel();
88 version = call >> 16; /* hack for backward compatibility */
89 call &= 0xffff;
91 ret = -EINVAL;
92 switch (call) {
93 case SEMOP:
94 ret = sys_semop (first, (struct sembuf *)ptr, second);
95 break;
96 case SEMGET:
97 ret = sys_semget (first, second, third);
98 break;
99 case SEMCTL: {
100 union semun fourth;
102 if (!ptr)
103 break;
104 if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long)))
105 || (ret = get_user(fourth.__pad, (void **)ptr)))
106 break;
107 ret = sys_semctl (first, second, third, fourth);
108 break;
110 case MSGSND:
111 ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third);
112 break;
113 case MSGRCV:
114 switch (version) {
115 case 0: {
116 struct ipc_kludge tmp;
118 if (!ptr)
119 break;
120 if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp)))
121 || (ret = copy_from_user(&tmp,
122 (struct ipc_kludge *) ptr,
123 sizeof (tmp))))
124 break;
125 ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
126 third);
127 break;
129 default:
130 ret = sys_msgrcv (first, (struct msgbuf *) ptr,
131 second, fifth, third);
132 break;
134 break;
135 case MSGGET:
136 ret = sys_msgget ((key_t) first, second);
137 break;
138 case MSGCTL:
139 ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
140 break;
141 case SHMAT:
142 switch (version) {
143 default: {
144 ulong raddr;
146 if ((ret = verify_area(VERIFY_WRITE, (ulong*) third,
147 sizeof(ulong))))
148 break;
149 ret = sys_shmat (first, (char *) ptr, second, &raddr);
150 if (ret)
151 break;
152 ret = put_user (raddr, (ulong *) third);
153 break;
155 case 1: /* iBCS2 emulator entry point */
156 if (!segment_eq(get_fs(), get_ds()))
157 break;
158 ret = sys_shmat (first, (char *) ptr, second,
159 (ulong *) third);
160 break;
162 break;
163 case SHMDT:
164 ret = sys_shmdt ((char *)ptr);
165 break;
166 case SHMGET:
167 ret = sys_shmget (first, second, third);
168 break;
169 case SHMCTL:
170 ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
171 break;
174 unlock_kernel();
175 return ret;
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)
184 int fd[2];
185 int error;
187 lock_kernel();
188 error = do_pipe(fd);
189 unlock_kernel();
190 if (!error) {
191 if (copy_to_user(fildes, fd, 2*sizeof(int)))
192 error = -EFAULT;
194 return error;
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;
202 int ret = -EBADF;
204 lock_kernel();
205 if (!(flags & MAP_ANONYMOUS)) {
206 if (!(file = fget(fd)))
207 goto out;
210 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
211 down(&current->mm->mmap_sem);
212 ret = do_mmap(file, addr, len, prot, flags, offset);
213 up(&current->mm->mmap_sem);
214 if (file)
215 fput(file);
216 out:
217 unlock_kernel();
218 return ret;
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
229 asmlinkage int
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))))
241 return -EFAULT;
243 return sys_select(n, inp, outp, exp, tvp);
246 asmlinkage int sys_pause(void)
248 current->state = TASK_INTERRUPTIBLE;
249 schedule();
250 return -ERESTARTNOHAND;
253 asmlinkage int sys_uname(struct old_utsname * name)
255 if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
256 return 0;
257 return -EFAULT;
260 asmlinkage int sys_olduname(struct oldold_utsname * name)
262 int error;
264 if (!name)
265 return -EFAULT;
266 if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
267 return -EFAULT;
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;
281 return error;