Merge /spare/repo/netdev-2.6/ branch 'ieee80211'
[pandora-kernel.git] / arch / xtensa / kernel / syscalls.c
1 /*
2  * arch/xtensa/kernel/syscall.c
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file "COPYING" in the main directory of this archive
6  * for more details.
7  *
8  * Copyright (C) 2001 - 2005 Tensilica Inc.
9  * Copyright (C) 2000 Silicon Graphics, Inc.
10  * Copyright (C) 1995 - 2000 by Ralf Baechle
11  *
12  * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
13  * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
14  * Chris Zankel <chris@zankel.net>
15  * Kevin Chea
16  *
17  */
18
19 #define DEBUG   0
20
21 #include <linux/config.h>
22 #include <linux/linkage.h>
23 #include <linux/mm.h>
24 #include <linux/smp.h>
25 #include <linux/smp_lock.h>
26 #include <linux/mman.h>
27 #include <linux/sched.h>
28 #include <linux/file.h>
29 #include <linux/slab.h>
30 #include <linux/utsname.h>
31 #include <linux/unistd.h>
32 #include <linux/stringify.h>
33 #include <linux/syscalls.h>
34 #include <linux/sem.h>
35 #include <linux/msg.h>
36 #include <linux/shm.h>
37 #include <linux/errno.h>
38 #include <asm/ptrace.h>
39 #include <asm/signal.h>
40 #include <asm/uaccess.h>
41 #include <asm/hardirq.h>
42 #include <asm/mman.h>
43 #include <asm/shmparam.h>
44 #include <asm/page.h>
45 #include <asm/ipc.h>
46
47 extern void do_syscall_trace(void);
48 typedef int (*syscall_t)(void *a0,...);
49 extern int (*do_syscalls)(struct pt_regs *regs, syscall_t fun,
50                                      int narg);
51 extern syscall_t sys_call_table[];
52 extern unsigned char sys_narg_table[];
53
54 /*
55  * sys_pipe() is the normal C calling standard for creating a pipe. It's not
56  * the way unix traditional does this, though.
57  */
58
59 int sys_pipe(int __user *userfds)
60 {
61         int fd[2];
62         int error;
63
64         error = do_pipe(fd);
65         if (!error) {
66                 if (copy_to_user(userfds, fd, 2 * sizeof(int)))
67                         error = -EFAULT;
68         }
69         return error;
70 }
71
72 /*
73  * Common code for old and new mmaps.
74  */
75
76 static inline long do_mmap2(unsigned long addr, unsigned long len,
77                             unsigned long prot, unsigned long flags,
78                             unsigned long fd, unsigned long pgoff)
79 {
80         int error = -EBADF;
81         struct file * file = NULL;
82
83         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
84         if (!(flags & MAP_ANONYMOUS)) {
85                 file = fget(fd);
86                 if (!file)
87                         goto out;
88         }
89
90         down_write(&current->mm->mmap_sem);
91         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
92         up_write(&current->mm->mmap_sem);
93
94         if (file)
95                 fput(file);
96 out:
97         return error;
98 }
99
100 unsigned long old_mmap(unsigned long addr, size_t len, int prot,
101                        int flags, int fd, off_t offset)
102 {
103         return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
104 }
105
106 long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
107                unsigned long flags, unsigned long fd, unsigned long pgoff)
108 {
109         return do_mmap2(addr, len, prot, flags, fd, pgoff);
110 }
111
112 int sys_fork(struct pt_regs *regs)
113 {
114         return do_fork(SIGCHLD, regs->areg[1], regs, 0, NULL, NULL);
115 }
116
117 int sys_vfork(struct pt_regs *regs)
118 {
119         return do_fork(CLONE_VFORK|CLONE_VM|SIGCHLD, regs->areg[1],
120                        regs, 0, NULL, NULL);
121 }
122
123 int sys_clone(struct pt_regs *regs)
124 {
125         unsigned long clone_flags;
126         unsigned long newsp;
127         int __user *parent_tidptr, *child_tidptr;
128         clone_flags = regs->areg[4];
129         newsp = regs->areg[3];
130         parent_tidptr = (int __user *)regs->areg[5];
131         child_tidptr = (int __user *)regs->areg[6];
132         if (!newsp)
133                 newsp = regs->areg[1];
134         return do_fork(clone_flags,newsp,regs,0,parent_tidptr,child_tidptr);
135 }
136
137 /*
138  * sys_execve() executes a new program.
139  */
140
141 int sys_execve(struct pt_regs *regs)
142 {
143         int error;
144         char * filename;
145
146         filename = getname((char *) (long)regs->areg[5]);
147         error = PTR_ERR(filename);
148         if (IS_ERR(filename))
149                 goto out;
150         error = do_execve(filename, (char **) (long)regs->areg[3],
151                           (char **) (long)regs->areg[4], regs);
152         putname(filename);
153
154 out:
155         return error;
156 }
157
158 int sys_uname(struct old_utsname * name)
159 {
160         if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
161                 return 0;
162         return -EFAULT;
163 }
164
165 int sys_olduname(struct oldold_utsname * name)
166 {
167         int error;
168
169         if (!name)
170                 return -EFAULT;
171         if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
172                 return -EFAULT;
173
174         error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
175         error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
176         error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
177         error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
178         error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
179         error -= __put_user(0,name->release+__OLD_UTS_LEN);
180         error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
181         error -= __put_user(0,name->version+__OLD_UTS_LEN);
182         error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
183         error -= __put_user(0,name->machine+__OLD_UTS_LEN);
184
185         return error ? -EFAULT : 0;
186 }
187
188
189 /*
190  * Build the string table for the builtin "poor man's strace".
191  */
192
193 #if DEBUG
194 #define SYSCALL(fun, narg) #fun,
195 static char *sfnames[] = {
196 #include "syscalls.h"
197 };
198 #undef SYS
199 #endif
200
201 void system_call (struct pt_regs *regs)
202 {
203         syscall_t syscall;
204         unsigned long parm0, parm1, parm2, parm3, parm4, parm5;
205         int nargs, res;
206         unsigned int syscallnr;
207         int ps;
208
209 #if DEBUG
210         int i;
211         unsigned long parms[6];
212         char *sysname;
213 #endif
214
215         regs->syscall = regs->areg[2];
216
217         do_syscall_trace();
218
219         /* Have to load after syscall_trace because strace
220          * sometimes changes regs->syscall.
221          */
222         syscallnr = regs->syscall;
223
224         parm0 = parm1 = parm2 = parm3 = parm4 = parm5 = 0;
225
226         /* Restore interrupt level to syscall invoker's.
227          * If this were in assembly, we wouldn't disable
228          * interrupts in the first place:
229          */
230         local_save_flags (ps);
231         local_irq_restore((ps & ~XCHAL_PS_INTLEVEL_MASK) |
232                           (regs->ps & XCHAL_PS_INTLEVEL_MASK) );
233
234         if (syscallnr > __NR_Linux_syscalls) {
235                 regs->areg[2] = -ENOSYS;
236                 return;
237         }
238
239         syscall = sys_call_table[syscallnr];
240         nargs = sys_narg_table[syscallnr];
241
242         if (syscall == NULL) {
243                 regs->areg[2] = -ENOSYS;
244                 return;
245         }
246
247         /* There shouldn't be more than six arguments in the table! */
248
249         if (nargs > 6)
250                 panic("Internal error - too many syscall arguments (%d)!\n",
251                       nargs);
252
253         /* Linux takes system-call arguments in registers.  The ABI
254          * and Xtensa software conventions require the system-call
255          * number in a2.  If an argument exists in a2, we move it to
256          * the next available register.  Note that for improved
257          * efficiency, we do NOT shift all parameters down one
258          * register to maintain the original order.
259          *
260          * At best case (zero arguments), we just write the syscall
261          * number to a2.  At worst case (1 to 6 arguments), we move
262          * the argument in a2 to the next available register, then
263          * write the syscall number to a2.
264          *
265          * For clarity, the following truth table enumerates all
266          * possibilities.
267          *
268          * arguments    syscall number  arg0, arg1, arg2, arg3, arg4, arg5
269          * ---------    --------------  ----------------------------------
270          *      0             a2
271          *      1             a2        a3
272          *      2             a2        a4,   a3
273          *      3             a2        a5,   a3,   a4
274          *      4             a2        a6,   a3,   a4,   a5
275          *      5             a2        a7,   a3,   a4,   a5,   a6
276          *      6             a2        a8,   a3,   a4,   a5,   a6,   a7
277          */
278         if (nargs) {
279                 parm0 = regs->areg[nargs+2];
280                 parm1 = regs->areg[3];
281                 parm2 = regs->areg[4];
282                 parm3 = regs->areg[5];
283                 parm4 = regs->areg[6];
284                 parm5 = regs->areg[7];
285         } else /* nargs == 0 */
286                 parm0 = (unsigned long) regs;
287
288 #if DEBUG
289         parms[0] = parm0;
290         parms[1] = parm1;
291         parms[2] = parm2;
292         parms[3] = parm3;
293         parms[4] = parm4;
294         parms[5] = parm5;
295
296         sysname = sfnames[syscallnr];
297         if (strncmp(sysname, "sys_", 4) == 0)
298                 sysname = sysname + 4;
299
300         printk("\017SYSCALL:I:%x:%d:%s  %s(", regs->pc, current->pid,
301                current->comm, sysname);
302         for (i = 0; i < nargs; i++)
303                 printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
304         printk(")\n");
305 #endif
306
307         res = syscall((void *)parm0, parm1, parm2, parm3, parm4, parm5);
308
309 #if DEBUG
310         printk("\017SYSCALL:O:%d:%s  %s(",current->pid, current->comm, sysname);
311         for (i = 0; i < nargs; i++)
312                 printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
313         if (res < 4096)
314                 printk(") = %d\n", res);
315         else
316                 printk(") = %#x\n", res);
317 #endif /* DEBUG */
318
319         regs->areg[2] = res;
320         do_syscall_trace();
321 }
322
323 /*
324  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
325  *
326  * This is really horribly ugly.
327  */
328
329 int sys_ipc (uint call, int first, int second,
330                         int third, void __user *ptr, long fifth)
331 {
332         int version, ret;
333
334         version = call >> 16; /* hack for backward compatibility */
335         call &= 0xffff;
336         ret = -ENOSYS;
337
338         switch (call) {
339         case SEMOP:
340                 ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
341                                      second, NULL);
342                 break;
343
344         case SEMTIMEDOP:
345                 ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
346                                       second, (const struct timespec *) fifth);
347                 break;
348
349         case SEMGET:
350                 ret = sys_semget (first, second, third);
351                 break;
352
353         case SEMCTL: {
354                 union semun fourth;
355
356                 if (ptr && !get_user(fourth.__pad, (void *__user *) ptr))
357                         ret = sys_semctl (first, second, third, fourth);
358                 break;
359                 }
360
361         case MSGSND:
362                 ret = sys_msgsnd (first, (struct msgbuf __user*) ptr,
363                                   second, third);
364                 break;
365
366         case MSGRCV:
367                 switch (version) {
368                 case 0: {
369                         struct ipc_kludge tmp;
370
371                         if (ptr && !copy_from_user(&tmp,
372                                            (struct ipc_kludge *) ptr,
373                                            sizeof (tmp)))
374                                 ret = sys_msgrcv (first, tmp.msgp, second,
375                                                   tmp.msgtyp, third);
376                         break;
377                         }
378
379                 default:
380                         ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
381                                           second, 0, third);
382                         break;
383                 }
384                 break;
385
386         case MSGGET:
387                 ret = sys_msgget ((key_t) first, second);
388                 break;
389
390         case MSGCTL:
391                 ret = sys_msgctl (first, second, (struct msqid_ds __user*) ptr);
392                 break;
393
394         case SHMAT: {
395                 ulong raddr;
396                 ret = do_shmat (first, (char __user *) ptr, second, &raddr);
397
398                 if (!ret)
399                         ret = put_user (raddr, (ulong __user *) third);
400
401                 break;
402                 }
403
404         case SHMDT:
405                 ret = sys_shmdt ((char __user *)ptr);
406                 break;
407
408         case SHMGET:
409                 ret = sys_shmget (first, second, third);
410                 break;
411
412         case SHMCTL:
413                 ret = sys_shmctl (first, second, (struct shmid_ds __user*) ptr);
414                 break;
415         }
416         return ret;
417 }
418