Goodbye mips64. 31704 lines of code bite the dust.
[linux-2.6/linux-mips.git] / arch / mips / kernel / syscall.c
blobf7a544584c2819dac0b4ecfc9cd8e3f23f41d8e4
1 /*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
6 * Copyright (C) 1995, 1996, 1997, 2000, 2001 by Ralf Baechle
7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8 * Copyright (C) 2001 MIPS Technologies, Inc.
9 */
10 #include <linux/errno.h>
11 #include <linux/linkage.h>
12 #include <linux/mm.h>
13 #include <linux/smp.h>
14 #include <linux/smp_lock.h>
15 #include <linux/mman.h>
16 #include <linux/ptrace.h>
17 #include <linux/sched.h>
18 #include <linux/string.h>
19 #include <linux/file.h>
20 #include <linux/slab.h>
21 #include <linux/utsname.h>
22 #include <linux/unistd.h>
23 #include <linux/sem.h>
24 #include <linux/msg.h>
25 #include <linux/shm.h>
27 #include <asm/branch.h>
28 #include <asm/cachectl.h>
29 #include <asm/cacheflush.h>
30 #include <asm/ipc.h>
31 #include <asm/offset.h>
32 #include <asm/signal.h>
33 #include <asm/sim.h>
34 #include <asm/shmparam.h>
35 #include <asm/sysmips.h>
36 #include <asm/uaccess.h>
38 asmlinkage int sys_pipe(nabi_no_regargs struct pt_regs regs)
40 int fd[2];
41 int error, res;
43 error = do_pipe(fd);
44 if (error) {
45 res = error;
46 goto out;
48 regs.regs[3] = fd[1];
49 res = fd[0];
50 out:
51 return res;
54 unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
56 #define COLOUR_ALIGN(addr,pgoff) \
57 ((((addr) + shm_align_mask) & ~shm_align_mask) + \
58 (((pgoff) << PAGE_SHIFT) & shm_align_mask))
60 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
61 unsigned long len, unsigned long pgoff, unsigned long flags)
63 struct vm_area_struct * vmm;
64 int do_color_align;
66 if (flags & MAP_FIXED) {
68 * We do not accept a shared mapping if it would violate
69 * cache aliasing constraints.
71 if ((flags & MAP_SHARED) && (addr & shm_align_mask))
72 return -EINVAL;
73 return addr;
76 if (len > TASK_SIZE)
77 return -ENOMEM;
78 do_color_align = 0;
79 if (filp || (flags & MAP_SHARED))
80 do_color_align = 1;
81 if (addr) {
82 if (do_color_align)
83 addr = COLOUR_ALIGN(addr, pgoff);
84 else
85 addr = PAGE_ALIGN(addr);
86 vmm = find_vma(current->mm, addr);
87 if (TASK_SIZE - len >= addr &&
88 (!vmm || addr + len <= vmm->vm_start))
89 return addr;
91 addr = TASK_UNMAPPED_BASE;
92 if (do_color_align)
93 addr = COLOUR_ALIGN(addr, pgoff);
94 else
95 addr = PAGE_ALIGN(addr);
97 for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
98 /* At this point: (!vmm || addr < vmm->vm_end). */
99 if (TASK_SIZE - len < addr)
100 return -ENOMEM;
101 if (!vmm || addr + len <= vmm->vm_start)
102 return addr;
103 addr = vmm->vm_end;
104 if (do_color_align)
105 addr = COLOUR_ALIGN(addr, pgoff);
109 /* common code for old and new mmaps */
110 static inline long
111 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
112 unsigned long flags, unsigned long fd, unsigned long pgoff)
114 int error = -EBADF;
115 struct file * file = NULL;
117 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
118 if (!(flags & MAP_ANONYMOUS)) {
119 file = fget(fd);
120 if (!file)
121 goto out;
124 down_write(&current->mm->mmap_sem);
125 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
126 up_write(&current->mm->mmap_sem);
128 if (file)
129 fput(file);
130 out:
131 return error;
134 asmlinkage unsigned long old_mmap(unsigned long addr, size_t len, int prot,
135 int flags, int fd, off_t offset)
137 int result;
139 result = -EINVAL;
140 if (offset & ~PAGE_MASK)
141 goto out;
143 result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
145 out:
146 return result;
149 asmlinkage long
150 sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
151 unsigned long flags, unsigned long fd, unsigned long pgoff)
153 return do_mmap2(addr, len, prot, flags, fd, pgoff);
156 save_static_function(sys_fork);
157 static_unused int _sys_fork(nabi_no_regargs struct pt_regs regs)
159 save_static(&regs);
160 return do_fork(SIGCHLD, regs.regs[29], &regs, 0, NULL, NULL);
163 save_static_function(sys_clone);
164 static_unused int _sys_clone(nabi_no_regargs struct pt_regs regs)
166 unsigned long clone_flags;
167 unsigned long newsp;
168 int *parent_tidptr, *child_tidptr;
170 save_static(&regs);
171 clone_flags = regs.regs[4];
172 newsp = regs.regs[5];
173 if (!newsp)
174 newsp = regs.regs[29];
175 parent_tidptr = (int *) regs.regs[6];
176 child_tidptr = (int *) regs.regs[7];
177 return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
178 parent_tidptr, child_tidptr);
182 * sys_execve() executes a new program.
184 asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
186 int error;
187 char * filename;
189 filename = getname((char *) (long)regs.regs[4]);
190 error = PTR_ERR(filename);
191 if (IS_ERR(filename))
192 goto out;
193 error = do_execve(filename, (char **) (long)regs.regs[5],
194 (char **) (long)regs.regs[6], &regs);
195 putname(filename);
197 out:
198 return error;
202 * Compacrapability ...
204 asmlinkage int sys_uname(struct old_utsname * name)
206 if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
207 return 0;
208 return -EFAULT;
212 * Compacrapability ...
214 asmlinkage int sys_olduname(struct oldold_utsname * name)
216 int error;
218 if (!name)
219 return -EFAULT;
220 if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
221 return -EFAULT;
223 error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
224 error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
225 error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
226 error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
227 error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
228 error -= __put_user(0,name->release+__OLD_UTS_LEN);
229 error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
230 error -= __put_user(0,name->version+__OLD_UTS_LEN);
231 error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
232 error = __put_user(0,name->machine+__OLD_UTS_LEN);
233 error = error ? -EFAULT : 0;
235 return error;
238 asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
240 int tmp, len;
241 char *name;
243 switch(cmd) {
244 case SETNAME: {
245 char nodename[__NEW_UTS_LEN + 1];
247 if (!capable(CAP_SYS_ADMIN))
248 return -EPERM;
250 name = (char *) arg1;
252 len = strncpy_from_user(nodename, name, __NEW_UTS_LEN);
253 if (len < 0)
254 return -EFAULT;
256 down_write(&uts_sem);
257 strncpy(system_utsname.nodename, nodename, len);
258 nodename[__NEW_UTS_LEN] = '\0';
259 strlcpy(system_utsname.nodename, nodename,
260 sizeof(system_utsname.nodename));
261 up_write(&uts_sem);
262 return 0;
265 case MIPS_ATOMIC_SET:
266 printk(KERN_CRIT "How did I get here?\n");
267 return -EINVAL;
269 case MIPS_FIXADE:
270 tmp = current->thread.mflags & ~3;
271 current->thread.mflags = tmp | (arg1 & 3);
272 return 0;
274 case FLUSH_CACHE:
275 __flush_cache_all();
276 return 0;
278 case MIPS_RDNVRAM:
279 return -EIO;
282 return -EINVAL;
286 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
288 * This is really horribly ugly.
290 asmlinkage int sys_ipc (uint call, int first, int second,
291 unsigned long third, void *ptr, long fifth)
293 int version, ret;
295 version = call >> 16; /* hack for backward compatibility */
296 call &= 0xffff;
298 switch (call) {
299 case SEMOP:
300 return sys_semop (first, (struct sembuf *)ptr, second);
301 case SEMGET:
302 return sys_semget (first, second, third);
303 case SEMCTL: {
304 union semun fourth;
305 if (!ptr)
306 return -EINVAL;
307 if (get_user(fourth.__pad, (void **) ptr))
308 return -EFAULT;
309 return sys_semctl (first, second, third, fourth);
312 case MSGSND:
313 return sys_msgsnd (first, (struct msgbuf *) ptr,
314 second, third);
315 case MSGRCV:
316 switch (version) {
317 case 0: {
318 struct ipc_kludge tmp;
319 if (!ptr)
320 return -EINVAL;
322 if (copy_from_user(&tmp,
323 (struct ipc_kludge *) ptr,
324 sizeof (tmp)))
325 return -EFAULT;
326 return sys_msgrcv (first, tmp.msgp, second,
327 tmp.msgtyp, third);
329 default:
330 return sys_msgrcv (first,
331 (struct msgbuf *) ptr,
332 second, fifth, third);
334 case MSGGET:
335 return sys_msgget ((key_t) first, second);
336 case MSGCTL:
337 return sys_msgctl (first, second, (struct msqid_ds *) ptr);
339 case SHMAT:
340 switch (version) {
341 default: {
342 ulong raddr;
343 ret = sys_shmat (first, (char *) ptr, second, &raddr);
344 if (ret)
345 return ret;
346 return put_user (raddr, (ulong *) third);
348 case 1: /* iBCS2 emulator entry point */
349 if (!segment_eq(get_fs(), get_ds()))
350 return -EINVAL;
351 return sys_shmat (first, (char *) ptr, second, (ulong *) third);
353 case SHMDT:
354 return sys_shmdt ((char *)ptr);
355 case SHMGET:
356 return sys_shmget (first, second, third);
357 case SHMCTL:
358 return sys_shmctl (first, second,
359 (struct shmid_ds *) ptr);
360 default:
361 return -ENOSYS;
366 * No implemented yet ...
368 asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
370 return -ENOSYS;
374 * If we ever come here the user sp is bad. Zap the process right away.
375 * Due to the bad stack signaling wouldn't work.
377 asmlinkage void bad_stack(void)
379 do_exit(SIGSEGV);