Linux 2.6.31-rc6
[linux-2.6] / arch / mn10300 / kernel / sys_mn10300.c
1 /* MN10300 Weird system calls
2  *
3  * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence
8  * as published by the Free Software Foundation; either version
9  * 2 of the Licence, or (at your option) any later version.
10  */
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/syscalls.h>
14 #include <linux/mm.h>
15 #include <linux/smp.h>
16 #include <linux/sem.h>
17 #include <linux/msg.h>
18 #include <linux/shm.h>
19 #include <linux/stat.h>
20 #include <linux/mman.h>
21 #include <linux/file.h>
22 #include <linux/utsname.h>
23 #include <linux/tty.h>
24
25 #include <asm/uaccess.h>
26
27 #define MIN_MAP_ADDR    PAGE_SIZE       /* minimum fixed mmap address */
28
29 /*
30  * memory mapping syscall
31  */
32 asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
33                           unsigned long prot, unsigned long flags,
34                           unsigned long fd, unsigned long pgoff)
35 {
36         struct file *file = NULL;
37         long error = -EINVAL;
38
39         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
40
41         if (flags & MAP_FIXED && addr < MIN_MAP_ADDR)
42                 goto out;
43
44         error = -EBADF;
45         if (!(flags & MAP_ANONYMOUS)) {
46                 file = fget(fd);
47                 if (!file)
48                         goto out;
49         }
50
51         down_write(&current->mm->mmap_sem);
52         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
53         up_write(&current->mm->mmap_sem);
54
55         if (file)
56                 fput(file);
57 out:
58         return error;
59 }
60
61 asmlinkage long old_mmap(unsigned long addr, unsigned long len,
62                          unsigned long prot, unsigned long flags,
63                          unsigned long fd, unsigned long offset)
64 {
65         if (offset & ~PAGE_MASK)
66                 return -EINVAL;
67         return sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
68 }
69
70 struct sel_arg_struct {
71         unsigned long n;
72         fd_set *inp;
73         fd_set *outp;
74         fd_set *exp;
75         struct timeval *tvp;
76 };
77
78 asmlinkage int old_select(struct sel_arg_struct __user *arg)
79 {
80         struct sel_arg_struct a;
81
82         if (copy_from_user(&a, arg, sizeof(a)))
83                 return -EFAULT;
84         /* sys_select() does the appropriate kernel locking */
85         return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
86 }
87
88 /*
89  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
90  *
91  * This is really horribly ugly.
92  */
93 asmlinkage long sys_ipc(uint call, int first, int second,
94                         int third, void __user *ptr, long fifth)
95 {
96         int version, ret;
97
98         version = call >> 16; /* hack for backward compatibility */
99         call &= 0xffff;
100
101         switch (call) {
102         case SEMOP:
103                 return sys_semtimedop(first, (struct sembuf __user *)ptr,
104                                       second, NULL);
105         case SEMTIMEDOP:
106                 return sys_semtimedop(first, (struct sembuf __user *)ptr,
107                                       second,
108                                       (const struct timespec __user *)fifth);
109         case SEMGET:
110                 return sys_semget(first, second, third);
111         case SEMCTL: {
112                 union semun fourth;
113                 if (!ptr)
114                         return -EINVAL;
115                 if (get_user(fourth.__pad, (void __user * __user *) ptr))
116                         return -EFAULT;
117                 return sys_semctl(first, second, third, fourth);
118         }
119
120         case MSGSND:
121                 return sys_msgsnd(first, (struct msgbuf __user *) ptr,
122                                   second, third);
123         case MSGRCV:
124                 switch (version) {
125                 case 0: {
126                         struct ipc_kludge tmp;
127                         if (!ptr)
128                                 return -EINVAL;
129
130                         if (copy_from_user(&tmp,
131                                            (struct ipc_kludge __user *) ptr,
132                                            sizeof(tmp)))
133                                 return -EFAULT;
134                         return sys_msgrcv(first, tmp.msgp, second,
135                                           tmp.msgtyp, third);
136                 }
137                 default:
138                         return sys_msgrcv(first,
139                                           (struct msgbuf __user *) ptr,
140                                            second, fifth, third);
141                 }
142         case MSGGET:
143                 return sys_msgget((key_t) first, second);
144         case MSGCTL:
145                 return sys_msgctl(first, second,
146                                    (struct msqid_ds __user *) ptr);
147
148         case SHMAT:
149                 switch (version) {
150                 default: {
151                         ulong raddr;
152                         ret = do_shmat(first, (char __user *) ptr, second,
153                                        &raddr);
154                         if (ret)
155                                 return ret;
156                         return put_user(raddr, (ulong *) third);
157                 }
158                 case 1: /* iBCS2 emulator entry point */
159                         if (!segment_eq(get_fs(), get_ds()))
160                                 return -EINVAL;
161                         return do_shmat(first, (char __user *) ptr, second,
162                                         (ulong *) third);
163                 }
164         case SHMDT:
165                 return sys_shmdt((char __user *)ptr);
166         case SHMGET:
167                 return sys_shmget(first, second, third);
168         case SHMCTL:
169                 return sys_shmctl(first, second,
170                                   (struct shmid_ds __user *) ptr);
171         default:
172                 return -EINVAL;
173         }
174 }