Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / arch / cris / kernel / sys_cris.c
1 /* $Id: sys_cris.c,v 1.6 2004/03/11 11:38:40 starvik Exp $
2  *
3  * linux/arch/cris/kernel/sys_cris.c
4  *
5  * This file contains various random system calls that
6  * have a non-standard calling sequence on some platforms.
7  * Since we don't have to do any backwards compatibility, our
8  * versions are done in the most "normal" way possible.
9  *
10  */
11
12 #include <linux/errno.h>
13 #include <linux/sched.h>
14 #include <linux/syscalls.h>
15 #include <linux/mm.h>
16 #include <linux/fs.h>
17 #include <linux/smp.h>
18 #include <linux/smp_lock.h>
19 #include <linux/sem.h>
20 #include <linux/msg.h>
21 #include <linux/shm.h>
22 #include <linux/stat.h>
23 #include <linux/mman.h>
24 #include <linux/file.h>
25 #include <linux/ipc.h>
26
27 #include <asm/uaccess.h>
28 #include <asm/segment.h>
29
30 /*
31  * sys_pipe() is the normal C calling standard for creating
32  * a pipe. It's not the way Unix traditionally does this, though.
33  */
34 asmlinkage int sys_pipe(unsigned long __user * fildes)
35 {
36         int fd[2];
37         int error;
38
39         lock_kernel();
40         error = do_pipe(fd);
41         unlock_kernel();
42         if (!error) {
43                 if (copy_to_user(fildes, fd, 2*sizeof(int)))
44                         error = -EFAULT;
45         }
46         return error;
47 }
48
49 /* common code for old and new mmaps */
50 static inline long
51 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
52         unsigned long flags, unsigned long fd, unsigned long pgoff)
53 {
54         int error = -EBADF;
55         struct file * file = NULL;
56
57         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
58         if (!(flags & MAP_ANONYMOUS)) {
59                 file = fget(fd);
60                 if (!file)
61                         goto out;
62         }
63
64         down_write(&current->mm->mmap_sem);
65         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
66         up_write(&current->mm->mmap_sem);
67
68         if (file)
69                 fput(file);
70 out:
71         return error;
72 }
73
74 asmlinkage unsigned long old_mmap(unsigned long __user *args)
75 {        
76         unsigned long buffer[6];
77         int err = -EFAULT;
78
79         if (copy_from_user(&buffer, args, sizeof(buffer)))
80                 goto out;
81
82         err = -EINVAL;
83         if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */
84                 goto out;
85
86         err = do_mmap2(buffer[0], buffer[1], buffer[2], buffer[3],
87                        buffer[4], buffer[5] >> PAGE_SHIFT);
88 out:
89         return err;
90 }
91
92 asmlinkage long
93 sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
94           unsigned long flags, unsigned long fd, unsigned long pgoff)
95 {
96         return do_mmap2(addr, len, prot, flags, fd, pgoff);
97 }
98
99 /*
100  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
101  *
102  * This is really horribly ugly. (same as arch/i386)
103  */
104
105 asmlinkage int sys_ipc (uint call, int first, int second,
106                         int third, void __user *ptr, long fifth)
107 {
108         int version, ret;
109
110         version = call >> 16; /* hack for backward compatibility */
111         call &= 0xffff;
112
113         switch (call) {
114         case SEMOP:
115                 return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
116         case SEMTIMEDOP:
117                 return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
118                                         (const struct timespec __user *)fifth);
119
120         case SEMGET:
121                 return sys_semget (first, second, third);
122         case SEMCTL: {
123                 union semun fourth;
124                 if (!ptr)
125                         return -EINVAL;
126                 if (get_user(fourth.__pad, (void * __user *) ptr))
127                         return -EFAULT;
128                 return sys_semctl (first, second, third, fourth);
129         }
130
131         case MSGSND:
132                 return sys_msgsnd (first, (struct msgbuf __user *) ptr, 
133                                    second, third);
134         case MSGRCV:
135                 switch (version) {
136                 case 0: {
137                         struct ipc_kludge tmp;
138                         if (!ptr)
139                                 return -EINVAL;
140                         
141                         if (copy_from_user(&tmp,
142                                            (struct ipc_kludge __user *) ptr, 
143                                            sizeof (tmp)))
144                                 return -EFAULT;
145                         return sys_msgrcv (first, tmp.msgp, second,
146                                            tmp.msgtyp, third);
147                 }
148                 default:
149                         return sys_msgrcv (first,
150                                            (struct msgbuf __user *) ptr,
151                                            second, fifth, third);
152                 }
153         case MSGGET:
154                 return sys_msgget ((key_t) first, second);
155         case MSGCTL:
156                 return sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
157
158         case SHMAT: {
159                 ulong raddr;
160                 ret = do_shmat (first, (char __user *) ptr, second, &raddr);
161                 if (ret)
162                         return ret;
163                 return put_user (raddr, (ulong __user *) third);
164         }
165         case SHMDT: 
166                 return sys_shmdt ((char __user *)ptr);
167         case SHMGET:
168                 return sys_shmget (first, second, third);
169         case SHMCTL:
170                 return sys_shmctl (first, second,
171                                    (struct shmid_ds __user *) ptr);
172         default:
173                 return -ENOSYS;
174         }
175 }