[ubicom32]: move new files out from platform support patch
[openwrt/svn-archive/archive.git] / target / linux / ubicom32 / files / arch / ubicom32 / kernel / sys_ubicom32.c
1 /*
2 * arch/ubicom32/kernel/sys_ubicom32.c
3 * Ubicom32 architecture system call support implementation.
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 * arch/m68knommu
25 * arch/blackfin
26 * arch/parisc
27 *
28 * This file contains various random system calls that
29 * have a non-standard calling sequence on the Linux/ubicom32
30 * platform.
31 */
32
33 #include <linux/module.h>
34 #include <linux/errno.h>
35 #include <linux/sched.h>
36 #include <linux/mm.h>
37 #include <linux/smp.h>
38 #include <linux/sem.h>
39 #include <linux/msg.h>
40 #include <linux/shm.h>
41 #include <linux/stat.h>
42 #include <linux/syscalls.h>
43 #include <linux/mman.h>
44 #include <linux/file.h>
45 #include <linux/utsname.h>
46 #include <linux/ipc.h>
47 #include <linux/fs.h>
48 #include <linux/uaccess.h>
49 #include <linux/unistd.h>
50
51 #include <asm/setup.h>
52 #include <asm/traps.h>
53 #include <asm/cacheflush.h>
54
55 /* common code for old and new mmaps */
56 static inline long do_mmap2(
57 unsigned long addr, unsigned long len,
58 unsigned long prot, unsigned long flags,
59 unsigned long fd, unsigned long pgoff)
60 {
61 int error = -EBADF;
62 struct file *file = NULL;
63
64 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
65 if (!(flags & MAP_ANONYMOUS)) {
66 file = fget(fd);
67 if (!file)
68 goto out;
69 }
70
71 down_write(&current->mm->mmap_sem);
72 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
73 up_write(&current->mm->mmap_sem);
74
75 if (file)
76 fput(file);
77 out:
78 return error;
79 }
80
81 asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
82 unsigned long prot, unsigned long flags,
83 unsigned long fd, unsigned long pgoff)
84 {
85 return do_mmap2(addr, len, prot, flags, fd, pgoff);
86 }
87
88 /*
89 * Perform the select(nd, in, out, ex, tv) and mmap() system
90 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
91 * handle more than 4 system call parameters, so these system calls
92 * used a memory block for parameter passing..
93 */
94
95 struct mmap_arg_struct {
96 unsigned long addr;
97 unsigned long len;
98 unsigned long prot;
99 unsigned long flags;
100 unsigned long fd;
101 unsigned long offset;
102 };
103
104 asmlinkage int old_mmap(struct mmap_arg_struct *arg)
105 {
106 struct mmap_arg_struct a;
107 int error = -EFAULT;
108
109 if (copy_from_user(&a, arg, sizeof(a)))
110 goto out;
111
112 error = -EINVAL;
113 if (a.offset & ~PAGE_MASK)
114 goto out;
115
116 a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
117
118 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd,
119 a.offset >> PAGE_SHIFT);
120 out:
121 return error;
122 }
123
124 struct sel_arg_struct {
125 unsigned long n;
126 fd_set *inp, *outp, *exp;
127 struct timeval *tvp;
128 };
129
130 asmlinkage int old_select(struct sel_arg_struct *arg)
131 {
132 struct sel_arg_struct a;
133
134 if (copy_from_user(&a, arg, sizeof(a)))
135 return -EFAULT;
136 /* sys_select() does the appropriate kernel locking */
137 return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
138 }
139
140 /*
141 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
142 *
143 * This is really horribly ugly.
144 */
145 asmlinkage int sys_ipc(uint call, int first, int second,
146 int third, void *ptr, long fifth)
147 {
148 int version, ret;
149
150 version = call >> 16; /* hack for backward compatibility */
151 call &= 0xffff;
152
153 if (call <= SEMCTL)
154 switch (call) {
155 case SEMOP:
156 return sys_semop(first, (struct sembuf *)ptr, second);
157 case SEMGET:
158 return sys_semget(first, second, third);
159 case SEMCTL: {
160 union semun fourth;
161 if (!ptr)
162 return -EINVAL;
163 if (get_user(fourth.__pad, (void **) ptr))
164 return -EFAULT;
165 return sys_semctl(first, second, third, fourth);
166 }
167 default:
168 return -EINVAL;
169 }
170 if (call <= MSGCTL)
171 switch (call) {
172 case MSGSND:
173 return sys_msgsnd(first, (struct msgbuf *) ptr,
174 second, third);
175 case MSGRCV:
176 switch (version) {
177 case 0: {
178 struct ipc_kludge tmp;
179 if (!ptr)
180 return -EINVAL;
181 if (copy_from_user(&tmp,
182 (struct ipc_kludge *)ptr,
183 sizeof(tmp)))
184 return -EFAULT;
185 return sys_msgrcv(first, tmp.msgp, second,
186 tmp.msgtyp, third);
187 }
188 default:
189 return sys_msgrcv(first,
190 (struct msgbuf *) ptr,
191 second, fifth, third);
192 }
193 case MSGGET:
194 return sys_msgget((key_t) first, second);
195 case MSGCTL:
196 return sys_msgctl(first, second,
197 (struct msqid_ds *) ptr);
198 default:
199 return -EINVAL;
200 }
201 if (call <= SHMCTL)
202 switch (call) {
203 case SHMAT:
204 switch (version) {
205 default: {
206 ulong raddr;
207 ret = do_shmat(first, ptr, second, &raddr);
208 if (ret)
209 return ret;
210 return put_user(raddr, (ulong __user *) third);
211 }
212 }
213 case SHMDT:
214 return sys_shmdt(ptr);
215 case SHMGET:
216 return sys_shmget(first, second, third);
217 case SHMCTL:
218 return sys_shmctl(first, second, ptr);
219 default:
220 return -ENOSYS;
221 }
222
223 return -EINVAL;
224 }
225
226 /* sys_cacheflush -- flush (part of) the processor cache. */
227 asmlinkage int
228 sys_cacheflush(unsigned long addr, int scope, int cache, unsigned long len)
229 {
230 flush_cache_all();
231 return 0;
232 }
233
234 asmlinkage int sys_getpagesize(void)
235 {
236 return PAGE_SIZE;
237 }